2010-06-03 10 views
5

Załóżmy, że mam okno, dla którego chcę zasymulować kliknięcie myszy o określonej współrzędnej x, y. Już mam hwnd, ale nie jestem pewien jak skonstruować lParam. Używałem SendMessage w przeszłości, aby kliknąd przyciski , ale znałem ich hwnds. Każda pomoc będzie bardzo ceniona. Nie mogę też pomóc, ale zastanawiam się, czy to jest właściwa droga. Moim celem końcowym jest kliknięcie na określonego użytkownika w oknie głównym skype (na przykład). Użyłem EnumChildWindows , aby znaleźć wszystkie dzieci w głównym oknie, ale nie mogłem znaleźć właściwego. Tak więc pomyślałem, że spróbuję "kliknąć" na nim używając współrzędnych.python win32 symulować kliknij

Odpowiedz

7

Możesz używać api o niskim poziomie dzięki ctypes. Zobacz przykład poniżej (zaadaptowane z czymś nie testowałem go ale powinno być ok)

import ctypes 
MOUSEEVENTF_MOVE = 0x0001 # mouse move 
MOUSEEVENTF_ABSOLUTE = 0x8000 # absolute move 
MOUSEEVENTF_MOVEABS = MOUSEEVENTF_MOVE + MOUSEEVENTF_ABSOLUTE 

MOUSEEVENTF_LEFTDOWN = 0x0002 # left button down 
MOUSEEVENTF_LEFTUP = 0x0004 # left button up 
MOUSEEVENTF_CLICK = MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP 

def click(x, y): 
    #move first 
    x = 65536L * x/ctypes.windll.user32.GetSystemMetrics(0) + 1 
    y = 65536L * y/ctypes.windll.user32.GetSystemMetrics(1) + 1 
    ctypes.windll.user32.mouse_event(MOUSEEVENTF_MOVEABS, x, y, 0, 0) 

    #then click 
    ctypes.windll.user32.mouse_event(MOUSEEVENTF_CLICK, 0, 0, 0, 0) 

Aktualizacja: nie testowałem poniższy kod, ale myślę, że powinno pomóc napisać coś uzyskać pozycję dziecka. Następnie możesz spróbować kliknąć we właściwej pozycji.

CHILD= None 

def the_callback(child_hwnd, regex): 
    '''Pass to win32gui.EnumWindows() to check all the opened windows''' 
    if re.match(regex, win32gui.GetWindowText(child_hwnd)): 
     CHILD= child_hwnd 

win32gui.EnumChildWindows(hwnd, the_callback, regex) 


if CHILD: 
    (x_tl, y_tl, x_br, y_br) = win32gui.GetWindowRect(CHILD) 
+0

Cześć dzięki za szybką odpowiedź. btw pozwala powiedzieć, że masz hwnd z głównego okna i kilka jego okien dzieci również z ich hwnds ... Czy wiesz, jak mogę szukać określonych treści tekstowych w poprzek wszystkich tych dzieci? i zidentyfikować właściwy, aby móc kliknąć ten tekst (link)? ... – nabizan

+0

@nabizan: zobacz moją aktualizację. Mam nadzieję, że pomogę – luc

+0

hmmm poprawić mnie, jeśli jestem zły, ale * .GetWindowText zwraca tylko tytuł okna. To jest dla mnie coś nowego i nie wiem, jak dokładnie działa, ale myślę, że za każdym razem, gdy otworzysz okno jakiejś złożonej aplikacji (np. Photoshop), otrzymasz główny plik hwnd i kilka okien dzieci (nie mają tytułu) więc na początku musisz znaleźć jedno konkretne okno potomne, które działa na przykład z losowymi wygenerowanymi linkami, a potem możesz je kliknąć ... nie wiem, czy jest to właściwa metoda, idąc tutaj niewidomym – nabizan

8

myślę, że to jest dobre dla ciebie, można korzystać przez bezpośredni lub importować to do swojego programu Pythona.

"""mousemacro.py defines the following functions: 

click() -- calls left mouse click 
hold() -- presses and holds left mouse button 
release() -- releases left mouse button 

rightclick() -- calls right mouse click 
righthold() -- calls right mouse hold 
rightrelease() -- calls right mouse release 

middleclick() -- calls middle mouse click 
middlehold() -- calls middle mouse hold 
middlerelease() -- calls middle mouse release 

move(x,y) -- moves mouse to x/y coordinates (in pixels) 
getpos() -- returns mouse x/y coordinates (in pixels) 
slide(x,y) -- slides mouse to x/y coodinates (in pixels) 
       also supports optional speed='slow', speed='fast' 
""" 

from ctypes import* 
from ctypes.wintypes import * 
from time import sleep 
import win32ui 

__all__ = ['click', 'hold', 'release', 'rightclick', 'righthold', 'rightrelease', 'middleclick', 'middlehold', 'middlerelease', 'move', 'slide', 'getpos'] 

# START SENDINPUT TYPE DECLARATIONS 
PUL = POINTER(c_ulong) 

class KeyBdInput(Structure): 
    _fields_ = [("wVk", c_ushort), 
      ("wScan", c_ushort), 
      ("dwFlags", c_ulong), 
      ("time", c_ulong), 
      ("dwExtraInfo", PUL)] 

class HardwareInput(Structure): 
    _fields_ = [("uMsg", c_ulong), 
      ("wParamL", c_short), 
      ("wParamH", c_ushort)] 

class MouseInput(Structure): 
    _fields_ = [("dx", c_long), 
      ("dy", c_long), 
      ("mouseData", c_ulong), 
      ("dwFlags", c_ulong), 
      ("time",c_ulong), 
      ("dwExtraInfo", PUL)] 

class Input_I(Union): 
    _fields_ = [("ki", KeyBdInput), 
       ("mi", MouseInput), 
       ("hi", HardwareInput)] 

class Input(Structure): 
    _fields_ = [("type", c_ulong), 
      ("ii", Input_I)] 

class POINT(Structure): 
    _fields_ = [("x", c_ulong), 
      ("y", c_ulong)] 
# END SENDINPUT TYPE DECLARATIONS 

    # LEFTDOWN = 0x00000002, 
    # LEFTUP  = 0x00000004, 
    # MIDDLEDOWN = 0x00000020, 
    # MIDDLEUP = 0x00000040, 
    # MOVE  = 0x00000001, 
    # ABSOLUTE = 0x00008000, 
    # RIGHTDOWN = 0x00000008, 
    # RIGHTUP = 0x00000010 

MIDDLEDOWN = 0x00000020 
MIDDLEUP = 0x00000040 
MOVE  = 0x00000001 
ABSOLUTE = 0x00008000 
RIGHTDOWN = 0x00000008 
RIGHTUP = 0x00000010 


FInputs = Input * 2 
extra = c_ulong(0) 

click = Input_I() 
click.mi = MouseInput(0, 0, 0, 2, 0, pointer(extra)) 
release = Input_I() 
release.mi = MouseInput(0, 0, 0, 4, 0, pointer(extra)) 

x = FInputs((0, click), (0, release)) 
#user32.SendInput(2, pointer(x), sizeof(x[0])) CLICK & RELEASE 

x2 = FInputs((0, click)) 
#user32.SendInput(2, pointer(x2), sizeof(x2[0])) CLICK & HOLD 

x3 = FInputs((0, release)) 
#user32.SendInput(2, pointer(x3), sizeof(x3[0])) RELEASE HOLD 


def move(x,y): 
    windll.user32.SetCursorPos(x,y) 

def getpos(): 
    global pt 
    pt = POINT() 
    windll.user32.GetCursorPos(byref(pt)) 
    return pt.x, pt.y 

def slide(a,b,speed=0): 
    while True: 
     if speed == 'slow': 
      sleep(0.005) 
      Tspeed = 2 
     if speed == 'fast': 
      sleep(0.001) 
      Tspeed = 5 
     if speed == 0: 
      sleep(0.001) 
      Tspeed = 3 

     x = getpos()[0] 
     y = getpos()[1] 
     if abs(x-a) < 5: 
      if abs(y-b) < 5: 
       break 

     if a < x: 
      x -= Tspeed 
     if a > x: 
      x += Tspeed 
     if b < y: 
      y -= Tspeed 
     if b > y: 
      y += Tspeed 
     move(x,y) 


def click(): 
    windll.user32.SendInput(2,pointer(x),sizeof(x[0])) 

def hold(): 
    windll.user32.SendInput(2, pointer(x2), sizeof(x2[0])) 

def release(): 
    windll.user32.SendInput(2, pointer(x3), sizeof(x3[0])) 


def rightclick(): 
    windll.user32.mouse_event(RIGHTDOWN,0,0,0,0) 
    windll.user32.mouse_event(RIGHTUP,0,0,0,0) 

def righthold(): 
    windll.user32.mouse_event(RIGHTDOWN,0,0,0,0) 

def rightrelease(): 
    windll.user32.mouse_event(RIGHTUP,0,0,0,0) 


def middleclick(): 
    windll.user32.mouse_event(MIDDLEDOWN,0,0,0,0) 
    windll.user32.mouse_event(MIDDLEUP,0,0,0,0) 

def middlehold(): 
    windll.user32.mouse_event(MIDDLEDOWN,0,0,0,0) 

def middlerelease(): 
    windll.user32.mouse_event(MIDDLEUP,0,0,0,0) 

if __name__ == '__main__': 
    while 1: 
     move(10,1) 
+0

dzięki temu wygląda dobrze – nabizan

+0

To jest całkowicie niesamowite! Dzięki. – IronManMark20