2010-06-03 18 views
5

Digamos que tengo una ventana para la que quiero simular un clic del mouse en una coordenada x, y específica. Ya tengo el hwnd pero no estoy seguro cómo construir el lParam. He usado SendMessage en el pasado para hacer clic en en botones, etc., pero sabía sus hwnds. Cualquier ayuda sería muy apreciada. Tampoco puedo evitar preguntarme si voy por esto de la manera correcta. Mi objetivo final es hacer clic en un determinado usuario de en la ventana principal de skype (por ejemplo). Utilicé EnumChildWindows para encontrar todos los hijos de la ventana principal, pero no pude encontrar el correcto. Así que pensé que trataría de 'hacer clic' en él usando las coordenadas.python win32 simular haga clic en

Respuesta

7

Puede utilizar la API de bajo nivel gracias a los ctypes. Ver un ejemplo a continuación (adaptado de algo que no he probado, pero debería estar bien)

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) 

Actualización: no he probado el código de abajo pero creo que debería ayudarle a escribir algo para obtener el puesto de niño Luego puede intentar hacer clic en la posición correcta.

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

hola gracias por la respuesta rápida. Por cierto, digamos que tienes ventanas principales y muchos de sus hijos también con sus archivos ... ¿sabes cómo puedo buscar contenido de texto específico para todos esos niños? e identifique el correcto para poder hacer clic en este texto (enlace)? ... – nabizan

+0

@nabizan: ver mi actualización. Espero que ayude – luc

+0

hmmm me corrijan si estoy equivocado pero * .GetWindowText solo devuelve el título de la ventana. esto es algo nuevo para mí y no sé cómo funciona exactamente, pero creo que cada vez que abres una ventana de una aplicación compleja (por ejemplo, photoshop) obtienes la ventana principal y varias ventanas secundarias (no tienen título) entonces al principio tienes que encontrar la ventana de un niño específico que funciona, por ejemplo, con algunos enlaces generados al azar y luego puedes hacer clic en él ... no sé si es la manera correcta de quedarme ciego aquí – nabizan

8

Creo que este es bueno para usted, puede utilizarlo directamente o importar esto a su programa de python.

"""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

gracias se ve bien – nabizan

+0

Esto es totalmente increíble! Gracias. – IronManMark20