【发布时间】:2016-07-24 22:56:34
【问题描述】:
我正在像这样在 python 中设置鼠标钩子:
def listen():
global hook_id
def low_level_handler(aCode, wParam, lParam):
if aCode != win32con.HC_ACTION:
return ctypes.windll.user32.CallNextHookEx(hook_id, aCode, wParam, lParam)
return ctypes.windll.user32.CallNextHookEx(hook_id, aCode, wParam, lParam)
# Our low level handler signature.
CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_void_p))
# Convert the Python handler into C pointer.
pointer = CMPFUNC(low_level_handler)
# Hook both key up and key down events for common keys (non-system).
hook_id = ctypes.windll.user32.SetWindowsHookExA(win32con.WH_MOUSE_LL, pointer,
GetModuleHandle(None), 0)
# Register to remove the hook when the interpreter exits. Unfortunately a
# try/finally block doesn't seem to work here.
atexit.register(ctypes.windll.user32.UnhookWindowsHookEx, hook_id)
def process_msg():
while True:
status, msg = PeekMessage(None, 0, 0, win32con.PM_REMOVE)
if status == 0:
break
TranslateMessage(ctypes.byref(msg))
DispatchMessage(ctypes.byref(msg))
process_msg 随后在循环中被调用
一切似乎都工作正常,直到我在同一个应用程序中模拟鼠标点击的 SendInput。一旦我模拟点击,就会发生崩溃。可能是什么原因?
谢谢。
【问题讨论】:
-
GetModuleHandle返回一个指向模块基地址的指针。通常,对于 64 位支持,您需要将其restype属性设置为指针类型,例如c_void_p。WPARAM也是无符号的并且是指针的大小;您可以为此使用c_void_p。 -
避免使用
ctypes.windll。这无疑是 ctypes 中最糟糕的事情。它使您受到碰巧加载的任何使用 ctypes 的模块的支配,因为它缓存了库,这些库缓存了函数指针。而是使用user32 = ctypes.WinDLL('user32', use_last_error=True)。 -
@eryksun 谢谢,你帮我修好了!