This Python code detects mouse wheel scrolls, it works perfectly (see Get Mouse Wheel Scroll using Win32api in 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)
It works but it does not distinguish between scrolling down and scrolling up. In both cases, I have:
0 522 3010120
0 522 3010120
0 522 3010120
0 522 3010120
How to distinguish up and down scrolls, by using win32api
, ctypes
, but no other third party library?
Also, based on some specific mouse behaviour, I'd like to trigger additional mousescrolls with:
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
Problem: these code-triggered fake mousewheels are detected as real WM_MOUSEWHEEL events, and they fall in the event loop / event listener, and generate themselves new events, which I don't want.
Question: how to avoid that this mousewheel event listener takes the code-generated scrolls in consideration?
CodePudding user response:
Following @RbMm's advice, here is a solution with 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)