Ctypes鼠标事件

10

ctypes.windll.user32.mouse_event(3, 0, 0, 0,0)

我正在处理鼠标位置,偶然发现这行代码可以模拟鼠标点击。请问是否有类似的文档(例如右击等)?

2个回答

18

我有一个小类,用于封装鼠标管理。

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 = 65536 * x_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CXSCREEN) + 1
        y_calc = 65536 * 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()

以下是一个小例子:

import time
mouse = Mouse()
mouse.click((20, 10), "left")
time.sleep(2.0)

mouse.click((100, 100), "right")

我希望这可以帮到你


1
如果您仅使用 win32api 查询鼠标位置,您可以在 ctypes 中执行此操作 - RattleyCooper
2
_do_event的部分不起作用,65536L返回错误。 - That One Random Scrub
3
可能为时已晚,但我必须去掉L,然后将x_calc和y_calc转换为整数。然后它就可以工作了:D - Generic Guy
好的,请根据@GenericGuy的说法更新你的答案。 - Nouman
@BlackThunder 完成了 :-) 很抱歉我直到现在才注意到。 - luc

5
这段文字来源于http://blog.lazynice.net/?p=63
这个脚本每分钟检测一次Windows系统的闲置时间。如果闲置时间超过5分钟,它会发送一个鼠标事件,让屏幕保护程序认为是用户在操作鼠标,从而重置计时器。只需要将闲置时间设置为小于屏幕保护等待时间即可运行!
from ctypes import Structure, windll, c_uint, sizeof, byref
import time

class LASTINPUTINFO(Structure):
    _fields_ = [('cbSize', c_uint), ('dwTime', c_uint)]

def get_idle_duration():
    lastInputInfo = LASTINPUTINFO()
    lastInputInfo.cbSize = sizeof(lastInputInfo)
    windll.user32.GetLastInputInfo(byref(lastInputInfo)) 
    millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
    return millis / 1000.0

while True:
    d = get_idle_duration()
    if d > 60 * 5:
        windll.user32.mouse_event(1, 1, 1, 0, 0)
    time.sleep(60)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接