2010-06-03 6 views
5

Предположим, у меня есть окно, для которого я хочу смоделировать щелчок мышью с определенной координатой x, y. У меня уже есть hwnd, но я не уверен как построить lParam. Я использовал SendMessage в прошлом, чтобы щелкнуть на кнопках и т. Д., Но я знал их hwnds. Любая помощь будет принята с благодарностью. Я также не могу не задаться вопросом, есть ли . Я собираюсь сделать это правильно. Моя конечная цель - щелкнуть по определенному пользователю в главном окне скайпа (например). Я использовал EnumChildWindows , чтобы найти всех детей главного окна, но не смог найти правильный. Итак, понял, что я попытаюсь нажать на него, используя координаты.python win32 simulate click

ответ

7

Вы можете использовать низкоуровневые окна api благодаря ctypes. Смотрите пример ниже (адаптировано из чего-то я не проверял, но это должно быть в порядке)

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) 

Update: Я не проверял код, приведенный ниже, но я думаю, что это должно помочь вам написать что-то получить детскую позицию. Затем вы можете попытаться щелкнуть по правильному положению.

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

привет спасибо за быстрый ответ. btw позволяет сказать, что у вас есть hwnd главного окна и куча окон его детей также с их hwnds ... знаете ли вы, как я могу найти какой-то конкретный текстовый контент для всех этих детей? и определить правильный, чтобы я мог нажать на этот текст (ссылка)? ... – nabizan

+0

@nabizan: см. Мое обновление. Я надеюсь, что это поможет – luc

+0

hmmm исправьте меня, если я ошибаюсь, но * .GetWindowText возвращает название окна. это что-то новое для меня, и я не знаю, как именно он работает, но я думаю, что в любое время, когда вы открываете окно какого-либо сложного приложения (например, фотошоп), вы получаете главный hwnd и кучу детских окон (у них нет названия) поэтому сначала вам нужно найти одно конкретное дочернее окно, которое работает, например, с некоторыми произвольными сгенерированными ссылками, а после этого вы можете щелкнуть его ... я не знаю, правильно ли он будет выглядеть здесь здесь – nabizan

8

Я думаю, что это хорошо для вас, вы можете использовать его прямо или импортировать в свою программу 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

спасибо, это прекрасно выглядит – nabizan

+0

Это абсолютно здорово! Благодарю. – IronManMark20