Automation of user inputs always requires to click several buttons or menus. I personally prefer to use mouse.py to automate and control my mouse in python. It was posted in a forum entry on stackoverlow http://stackoverflow.com/questions/4263608/ctypes-mouse-events.
The module as is works great. I did however miss some functionality: Clicking without moving the cursor. I extended mouse.py to click without moving the cursor. I have noticed that very rarely you still see the cursor moving. This only happens if my computer is rather busy. I remember using PostMessage back in my old AHK days, but unfortunately I can not get it to work.
An other function I included is clicking relative coordinates. I often would rather click coordinates in a window without having to deal with where that window is actually at. On a side note, a great tool for relative coordinates especially with multiple monitors is my module python screen coordinates. It does all the conversion of coordinates and has a hit test to determine what screen you are on.
Do you know of other ways to control your mouse in python? Please share any method you know. I would really like to see a PostMessage example work. I know TableCrab has a working solution, but I didnt get a chance yet to look through all the code.
Here is my extended version of mouse.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import win32gui, win32api, win32con, ctypes class Mouse: """It simulates the mouse""" MOUSEEVENTF_MOVE = 0x0001 # mouse move MOUSEEVENTF_LEFTDOWN = 0x0002 # left button down MOUSEEVENTF_LEFTUP = 0x0004 # left button up MOUSEEVENTF_RIGHTDOWN = 0x0008 # right button down MOUSEEVENTF_RIGHTUP = 0x0010 # right button up MOUSEEVENTF_MIDDLEDOWN = 0x0020 # middle button down MOUSEEVENTF_MIDDLEUP = 0x0040 # middle button up MOUSEEVENTF_WHEEL = 0x0800 # wheel button rolled MOUSEEVENTF_ABSOLUTE = 0x8000 # absolute move SM_CXSCREEN = 0 SM_CYSCREEN = 1 def _do_event(self, flags, x_pos, y_pos, data, extra_info): """generate a mouse event""" x_calc = 65536L * x_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CXSCREEN) + 1 y_calc = 65536L * y_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CYSCREEN) + 1 return ctypes.windll.user32.mouse_event(flags, x_calc, y_calc, data, extra_info) def _get_button_value(self, button_name, button_up=False): """convert the name of the button into the corresponding value""" buttons = 0 if button_name.find("right") >= 0: buttons = self.MOUSEEVENTF_RIGHTDOWN if button_name.find("left") >= 0: buttons = buttons + self.MOUSEEVENTF_LEFTDOWN if button_name.find("middle") >= 0: buttons = buttons + self.MOUSEEVENTF_MIDDLEDOWN if button_up: buttons = buttons << 1 return buttons def move_mouse(self, pos): """move the mouse to the specified coordinates""" (x, y) = pos old_pos = self.get_position() x = x if (x != -1) else old_pos[0] y = y if (y != -1) else old_pos[1] self._do_event(self.MOUSEEVENTF_MOVE + self.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0) def press_button(self, pos=(-1, -1), button_name="left", button_up=False): """push a button of the mouse""" self.move_mouse(pos) self._do_event(self.get_button_value(button_name, button_up), 0, 0, 0, 0) def click(self, pos=(-1, -1), button_name= "left"): """Click at the specified placed""" ## self.move_mouse(pos) self._do_event(self._get_button_value(button_name, False)+self._get_button_value(button_name, True), 0, 0, 0, 0) def double_click (self, pos=(-1, -1), button_name="left"): """Double click at the specifed placed""" for i in xrange(2): self.click(pos, button_name) def get_position(self): """get mouse position""" return win32api.GetCursorPos() #----------------------------------------------------------------------------------------- #Added functions #----------------------------------------------------------------------------------------- def invisible_click(self,pos=(-1, -1), button_name="left"): """Click in specified place without moving mouse""" xcur,ycur = win32gui.GetCursorPos() ctypes.windll.user32.SetCursorPos(pos[0],pos[1]) self.click(pos,button_name) ctypes.windll.user32.SetCursorPos(xcur,ycur) def invisible_click_rel(self,handle,pos, button_name="left"): """Click in window coordinates without moving mouse""" #get window info xleft, ytop, xright, ybottom = win32gui.GetWindowRect(handle) xcur,ycur = win32gui.GetCursorPos() ctypes.windll.user32.SetCursorPos(pos[0]+xleft,pos[1]+ytop) self.click((pos[0]+xleft,pos[1]+ytop),button_name) ctypes.windll.user32.SetCursorPos(xcur,ycur) if __name__ == '__main__': ## p = (210,260) ## print win32gui.GetForegroundWindow() ## mouse = Mouse() ## mouse.invisible_click_rel(win32gui.GetForegroundWindow(),p) |
import win32gui, win32api, win32con, ctypes
class Mouse:
"""It simulates the mouse"""
MOUSEEVENTF_MOVE = 0x0001 # mouse move
MOUSEEVENTF_LEFTDOWN = 0x0002 # left button down
MOUSEEVENTF_LEFTUP = 0x0004 # left button up
MOUSEEVENTF_RIGHTDOWN = 0x0008 # right button down
MOUSEEVENTF_RIGHTUP = 0x0010 # right button up
MOUSEEVENTF_MIDDLEDOWN = 0x0020 # middle button down
MOUSEEVENTF_MIDDLEUP = 0x0040 # middle button up
MOUSEEVENTF_WHEEL = 0x0800 # wheel button rolled
MOUSEEVENTF_ABSOLUTE = 0x8000 # absolute move
SM_CXSCREEN = 0
SM_CYSCREEN = 1
def _do_event(self, flags, x_pos, y_pos, data, extra_info):
"""generate a mouse event"""
x_calc = 65536L * x_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CXSCREEN) + 1
y_calc = 65536L * y_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CYSCREEN) + 1
return ctypes.windll.user32.mouse_event(flags, x_calc, y_calc, data, extra_info)
def _get_button_value(self, button_name, button_up=False):
"""convert the name of the button into the corresponding value"""
buttons = 0
if button_name.find("right") >= 0:
buttons = self.MOUSEEVENTF_RIGHTDOWN
if button_name.find("left") >= 0:
buttons = buttons + self.MOUSEEVENTF_LEFTDOWN
if button_name.find("middle") >= 0:
buttons = buttons + self.MOUSEEVENTF_MIDDLEDOWN
if button_up:
buttons = buttons << 1
return buttons
def move_mouse(self, pos):
"""move the mouse to the specified coordinates"""
(x, y) = pos
old_pos = self.get_position()
x = x if (x != -1) else old_pos[0]
y = y if (y != -1) else old_pos[1]
self._do_event(self.MOUSEEVENTF_MOVE + self.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0)
def press_button(self, pos=(-1, -1), button_name="left", button_up=False):
"""push a button of the mouse"""
self.move_mouse(pos)
self._do_event(self.get_button_value(button_name, button_up), 0, 0, 0, 0)
def click(self, pos=(-1, -1), button_name= "left"):
"""Click at the specified placed"""
## self.move_mouse(pos)
self._do_event(self._get_button_value(button_name, False)+self._get_button_value(button_name, True), 0, 0, 0, 0)
def double_click (self, pos=(-1, -1), button_name="left"):
"""Double click at the specifed placed"""
for i in xrange(2):
self.click(pos, button_name)
def get_position(self):
"""get mouse position"""
return win32api.GetCursorPos()
#-----------------------------------------------------------------------------------------
#Added functions
#-----------------------------------------------------------------------------------------
def invisible_click(self,pos=(-1, -1), button_name="left"):
"""Click in specified place without moving mouse"""
xcur,ycur = win32gui.GetCursorPos()
ctypes.windll.user32.SetCursorPos(pos[0],pos[1])
self.click(pos,button_name)
ctypes.windll.user32.SetCursorPos(xcur,ycur)
def invisible_click_rel(self,handle,pos, button_name="left"):
"""Click in window coordinates without moving mouse"""
#get window info
xleft, ytop, xright, ybottom = win32gui.GetWindowRect(handle)
xcur,ycur = win32gui.GetCursorPos()
ctypes.windll.user32.SetCursorPos(pos[0]+xleft,pos[1]+ytop)
self.click((pos[0]+xleft,pos[1]+ytop),button_name)
ctypes.windll.user32.SetCursorPos(xcur,ycur)
if __name__ == '__main__':
## p = (210,260)
## print win32gui.GetForegroundWindow()
## mouse = Mouse()
## mouse.invisible_click_rel(win32gui.GetForegroundWindow(),p)I hope it helps you, please let me know about questions. Comments are always welcome!
No comments yet.