如何使用 WinAPI 区分真实的鼠标滚轮和生成的滚轮?
How to distinguish between real mouse scrollwheels and generated ones, with WinAPI?
这个 Python 代码检测鼠标滚轮滚动,它工作得很好(参见 ):
import win32api, win32con
from ctypes import windll, CFUNCTYPE, c_int, c_void_p, wintypes, byref
user32 = windll.user32
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
print(nCode, wParam, lParam)
# win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0) # code-generated scrollwheels
CMPFUNC = CFUNCTYPE(c_void_p, c_int, wintypes.WPARAM, wintypes.LPARAM)
user32.SetWindowsHookExW.argtypes = [c_int, CMPFUNC, wintypes.HINSTANCE, wintypes.DWORD]
pointer = CMPFUNC(LowLevelMouseProc)
hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL,pointer,win32api.GetModuleHandle(None), 0)
msg = wintypes.MSG()
while user32.GetMessageW(byref(msg), 0, 0, 0) != 0:
user32.TranslateMessage(msg)
user32.DispatchMessageW(msg)
有效,但不区分滚动向下和滚动向上。在这两种情况下,我都有:
0 522 3010120
0 522 3010120
0 522 3010120
0 522 3010120
如何使用win32api
、ctypes
,而没有其他第三方库,如何区分上下滚动?
此外,基于某些特定的鼠标行为,我想触发额外的鼠标滚动:
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
print(nCode, wParam, lParam)
win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0) # TRIGGER HERE
问题:这些代码触发的虚假鼠标滚轮被检测为真实的 WM_MOUSEWHEEL 事件,它们落入事件循环/事件侦听器中,并自行生成我不想要的新事件。
问题:如何避免此鼠标滚轮事件侦听器将代码生成的滚动考虑在内?
按照@RbMm 的建议,这里有一个 MSLLHOOKSTRUCT
的解决方案:
import win32api, win32con, ctypes
from ctypes import windll, CFUNCTYPE, c_int, c_void_p, wintypes, byref, POINTER, Structure
user32 = windll.user32
class MSLLHOOKSTRUCT(Structure):
_fields_ = [
("x", ctypes.c_long),
("y", ctypes.c_long),
("mouseData", ctypes.c_ulong),
("flags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", ctypes.c_ulong)
]
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
injected = lParam.contents.flags & 0x00000001
print(lParam.contents.x, lParam.contents.y, injected)
if injected == 0:
win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0)
CMPFUNC = CFUNCTYPE(c_void_p, c_int, wintypes.WPARAM, POINTER(MSLLHOOKSTRUCT))
user32.SetWindowsHookExW.argtypes = [c_int, CMPFUNC, wintypes.HINSTANCE, wintypes.DWORD]
pointer = CMPFUNC(LowLevelMouseProc)
hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL, pointer, win32api.GetModuleHandle(None), 0)
msg = wintypes.MSG()
while user32.GetMessageW(byref(msg), 0, 0, 0) != 0:
user32.TranslateMessage(msg)
user32.DispatchMessageW(msg)
这个 Python 代码检测鼠标滚轮滚动,它工作得很好(参见
import win32api, win32con
from ctypes import windll, CFUNCTYPE, c_int, c_void_p, wintypes, byref
user32 = windll.user32
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
print(nCode, wParam, lParam)
# win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0) # code-generated scrollwheels
CMPFUNC = CFUNCTYPE(c_void_p, c_int, wintypes.WPARAM, wintypes.LPARAM)
user32.SetWindowsHookExW.argtypes = [c_int, CMPFUNC, wintypes.HINSTANCE, wintypes.DWORD]
pointer = CMPFUNC(LowLevelMouseProc)
hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL,pointer,win32api.GetModuleHandle(None), 0)
msg = wintypes.MSG()
while user32.GetMessageW(byref(msg), 0, 0, 0) != 0:
user32.TranslateMessage(msg)
user32.DispatchMessageW(msg)
有效,但不区分滚动向下和滚动向上。在这两种情况下,我都有:
0 522 3010120
0 522 3010120
0 522 3010120
0 522 3010120
如何使用win32api
、ctypes
,而没有其他第三方库,如何区分上下滚动?
此外,基于某些特定的鼠标行为,我想触发额外的鼠标滚动:
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
print(nCode, wParam, lParam)
win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0) # TRIGGER HERE
问题:这些代码触发的虚假鼠标滚轮被检测为真实的 WM_MOUSEWHEEL 事件,它们落入事件循环/事件侦听器中,并自行生成我不想要的新事件。
问题:如何避免此鼠标滚轮事件侦听器将代码生成的滚动考虑在内?
按照@RbMm 的建议,这里有一个 MSLLHOOKSTRUCT
的解决方案:
import win32api, win32con, ctypes
from ctypes import windll, CFUNCTYPE, c_int, c_void_p, wintypes, byref, POINTER, Structure
user32 = windll.user32
class MSLLHOOKSTRUCT(Structure):
_fields_ = [
("x", ctypes.c_long),
("y", ctypes.c_long),
("mouseData", ctypes.c_ulong),
("flags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", ctypes.c_ulong)
]
def LowLevelMouseProc(nCode, wParam, lParam):
if wParam == win32con.WM_MOUSEWHEEL:
injected = lParam.contents.flags & 0x00000001
print(lParam.contents.x, lParam.contents.y, injected)
if injected == 0:
win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, 1, 0)
CMPFUNC = CFUNCTYPE(c_void_p, c_int, wintypes.WPARAM, POINTER(MSLLHOOKSTRUCT))
user32.SetWindowsHookExW.argtypes = [c_int, CMPFUNC, wintypes.HINSTANCE, wintypes.DWORD]
pointer = CMPFUNC(LowLevelMouseProc)
hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL, pointer, win32api.GetModuleHandle(None), 0)
msg = wintypes.MSG()
while user32.GetMessageW(byref(msg), 0, 0, 0) != 0:
user32.TranslateMessage(msg)
user32.DispatchMessageW(msg)