使用Python在Windows中检测鼠标点击

26
无论鼠标在哪个窗口,我该如何检测鼠标点击事件?最好使用 Python,但如果有人能用其他语言解释,我也可以试着理解。
我在 Microsoft 的网站上找到了这个页面: http://msdn.microsoft.com/en-us/library/ms645533(VS.85).aspx 但我不知道如何检测或获取其中列出的通知。
我尝试使用 Pygame 的 pygame.mouse.get_pos() 函数,代码如下:
import pygame
pygame.init()
while True:
    print pygame.mouse.get_pos()

这只返回0,0。我不熟悉pygame,是否有遗漏的部分?

无论如何,我更喜欢一种不需要安装第三方模块的方法。 (除了pywin32 http://sourceforge.net/projects/pywin32/ 之外)


你正在使用哪个UI工具包/库? - Swaroop C H
3
我认为可以使用win32ui和ctypes来实现。我发现可以使用windll.user32.GetCursorPos(pointer(pt_struct))获取鼠标位置。(详情请参阅:http://monkut.webfactional.com/blog/archive/2008/10/2/python-win-mouse-position) - monkut
5个回答

32

检测程序外的鼠标事件的唯一方法是使用SetWindowsHookEx安装Windows钩子。pyHook模块封装了细节。以下是一个示例,将打印每个鼠标单击的位置:

import pyHook
import pythoncom

def onclick(event):
    print event.Position
    return True

hm = pyHook.HookManager()
hm.SubscribeMouseAllButtonsDown(onclick)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()

您可以查看安装模块时附带的example.py脚本,了解有关event参数的更多信息。

在纯Python脚本中使用pyHook可能会很棘手,因为它需要一个活动消息泵。来自教程

任何想要接收全局输入事件通知的应用程序都必须拥有Windows消息泵。获取其中之一的最简单方法是使用Python的Win32扩展包中的PumpMessages方法。[...]运行此程序只需等待Windows事件即可。如果使用GUI工具包(例如wxPython),则此循环是不必要的,因为工具包提供了自己的循环。


请注意,PyHook已经移动到https://sourceforge.net/projects/pyhook/,期间可能有所变化。 - Tobias Kienzler
如果你想退出,导入ctypes库,然后在当前线程的任何位置执行以下代码: ctypes.windll.user32.PostQuitMessage(0) 这将结束pythoncom.PumpMessages() - Diego Orellana
最近,像Python 3.8+这样的版本,pyHook的这个分支可能会很有帮助:https://pypi.org/project/pyWinhook/ 它还很好地在PyPI上,所以您不必直接处理.whl文件。正常的pip install pyWinhook应该就可以了。 - tscizzle

22

我使用win32api。在单击任何窗口时都可以工作。

# Code to check if left or right mouse buttons were pressed
import win32api
import time

state_left = win32api.GetKeyState(0x01)  # Left button down = 0 or 1. Button up = -127 or -128
state_right = win32api.GetKeyState(0x02)  # Right button down = 0 or 1. Button up = -127 or -128

while True:
    a = win32api.GetKeyState(0x01)
    b = win32api.GetKeyState(0x02)

    if a != state_left:  # Button state changed
        state_left = a
        print(a)
        if a < 0:
            print('Left Button Pressed')
        else:
            print('Left Button Released')

    if b != state_right:  # Button state changed
        state_right = b
        print(b)
        if b < 0:
            print('Right Button Pressed')
        else:
            print('Right Button Released')
    time.sleep(0.001)

7

这个问题已经有一段时间了,但我想分享我的解决方案:我只是使用了内置模块ctypes。(顺便提一下,我使用的是Python 3.3)

import ctypes
import time

def DetectClick(button, watchtime = 5):
    '''Waits watchtime seconds. Returns True on click, False otherwise'''
    if button in (1, '1', 'l', 'L', 'left', 'Left', 'LEFT'):
        bnum = 0x01
    elif button in (2, '2', 'r', 'R', 'right', 'Right', 'RIGHT'):
        bnum = 0x02

    start = time.time()
    while 1:
        if ctypes.windll.user32.GetKeyState(bnum) not in [0, 1]:
            # ^ this returns either 0 or 1 when button is not being held down
            return True
        elif time.time() - start >= watchtime:
            break
        time.sleep(0.001)
    return False

1
使用内置库赢得了这一点(加上使用“热分钟”) - scign

5

使用Mark Hammond的Python for Windows扩展,可以使用Python访问Windows MFC(包括GUI编程)。这里提供了相关扩展的下载。Hammond和Robinson的书籍O'Reilly书摘展示了如何挂钩鼠标消息。

self.HookMessage(self.OnMouseMove,win32con.WM_MOUSEMOVE)

原始的MFC并不容易或直观,但是在网上搜索Python示例可能会得到一些可用的示例。


2

在Windows中,处理WM_LBUTTONDBLCLK消息是一种方法。

要发送此消息,您的窗口类需要使用CS_DBLCLKS类样式创建。

很抱歉,我不知道如何在Python中应用它,但希望这可能会给您一些提示。


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