Search code examples
pythonwinapimouseeventpywin32mousewheel

Get Mouse Wheel Scroll using Win32api in Python


I want to read mouse wheel scroll events and then simulate them. I know I can simulate it using below code.

#Scroll one up
win32api.mouse_event(MOUSEEVENTF_WHEEL, x, y, 1, 0)

#Scroll one down
win32api.mouse_event(MOUSEEVENTF_WHEEL, x, y, -1, 0)

However, I couldn't find a way to get whell scroll event using win32api in Python. Is there any way to detect wheel scroll up or down events?


Solution

  • If you need to get the global WM_MOUSEWHEEL message, you can use the SetWindowsHookEx function and with WH_MOUSE_LL hook.

    Then handle the WM_MOUSEWHEEL message in the hook function.

    Here is a sample:

    import win32api 
    import win32con
    import ctypes
    from ctypes import windll, CFUNCTYPE, POINTER, c_int, c_void_p, byref
    
    user32 = ctypes.windll.user32
    kernel32 = ctypes.windll.kernel32
    
    def LowLevelMouseProc(nCode, wParam, lParam):
        if wParam == win32con.WM_MOUSEWHEEL:
            print("mousewheel triggerd!")
        return windll.user32.CallNextHookEx(hook_id, nCode, wParam, lParam)
    
    if __name__ == '__main__':
        CMPFUNC = CFUNCTYPE(c_void_p, c_int, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
    
        pointer = CMPFUNC(LowLevelMouseProc)
        hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL,pointer,c_void_p(win32api.GetModuleHandle(None), 0)
        msg = ctypes.wintypes.MSG()
        while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
            user32.TranslateMessage(msg)
            user32.DispatchMessageW(msg)
    

    It works for me:

    enter image description here

    Edit

    If there are problems like <class'OverflowError'>: int too long to convert, you can try the following code:

    import win32api 
    import win32con
    import ctypes
    from ctypes import windll, CFUNCTYPE, c_int, c_void_p, wintypes
    
     
    
    user32 = ctypes.windll.user32
    kernel32 = ctypes.windll.kernel32
    user32.CallNextHookEx.argtypes = [ctypes.wintypes.HHOOK,c_int, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM]
    
     
    
    def LowLevelMouseProc(nCode, wParam, lParam):
        if wParam == win32con.WM_MOUSEWHEEL:
            print("mousewheel triggerd!")
        return user32.CallNextHookEx(hook_id, nCode, wParam, lParam)
    
     
    
    if __name__ == '__main__':
        CMPFUNC = CFUNCTYPE(c_void_p, c_int, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
        user32.SetWindowsHookExW.argtypes = [c_int,CMPFUNC,ctypes.wintypes.HINSTANCE,ctypes.wintypes.DWORD]
        pointer = CMPFUNC(LowLevelMouseProc)
        hook_id = user32.SetWindowsHookExW(win32con.WH_MOUSE_LL,pointer,win32api.GetModuleHandle(None), 0)
        msg = ctypes.wintypes.MSG()
        while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
            user32.TranslateMessage(msg)
            user32.DispatchMessageW(msg)