Page 1 of 2

[Solved] Mouse wheel hook laggy in Windows

Posted: Sat Dec 24, 2022 1:27 pm
by BarryG
[Edit] Solved! My new mouse is a better model than my old one, and there is no lag with the new mouse with this code.

Hi all! Merry Christmas for tomorrow.

Now to business: I'm using the following code to set a global mouse wheel hook, but the mouse moves very laggy (slow and jerky) when it's hooked. You can try this by running the code and moving the mouse around. So, is there anything I should be doing to make it smooth like there was no hook in effect? Something I've overlooked? Thanks.

Code: Select all

Global MouseWheelHook,MouseWheelWindow,MouseWheelDir

Procedure LowLevelMouseProc(nCode.l,wParam.l,lParam.l)
  If wParam=#WM_MOUSEWHEEL
    MouseWheelDir=-(EventwParam()>>16)/#WHEEL_DELTA
    PostMessage_(MouseWheelWindow,#WM_MOUSEWHEEL,PeekL(lParam+8),0)
  EndIf
  ProcedureReturn CallNextHookEx_(MouseWheelHook,nCode,wParam,lParam)
EndProcedure

Procedure AddMouseWheelHook(hWnd)
  If MouseWheelHook=0
    MouseWheelHook=SetWindowsHookEx_(#WH_MOUSE_LL,@LowLevelMouseProc(),GetModuleHandle_(0),0)
  EndIf
  MouseWheelWindow=hWnd
  ProcedureReturn MouseWheelHook
EndProcedure

Procedure RemoveMouseWheelHook()
  If MouseWheelHook
    UnhookWindowsHookEx_(MouseWheelHook)
    MouseWheelHook=0
  EndIf
EndProcedure

OpenWindow(0,400,200,640,320,"Mouse Hook",#PB_Window_SystemMenu)

AddMouseWheelHook(WindowID(0)) ; Makes mouse slow and laggy to move.

Repeat
  ev=WaitWindowEvent()
Until ev=#PB_Event_CloseWindow

Re: Mouse wheel hook laggy in Windows

Posted: Sat Dec 24, 2022 3:00 pm
by mk-soft
It runs smoothly for me. But Windows runs as a VM for me

Update 2
- In order not to have double events of WM_MOUSEWHEEL, it is better to take a WM_USER message.

Code: Select all

Macro LOWORD(dwValue)
  (dwValue & $FFFF)
EndMacro

Macro HIWORD(dwValue)
  (dwValue >> 16)
EndMacro

Enumeration #WM_USER + 1
  #WM_USER_MOUSEWHEEL
EndEnumeration

Structure MSLLHOOKSTRUCT
  pt.point
  mouseData.l
  flags.l
  time.l
  *dwExtraInfo
EndStructure

Global MouseWheelHook,MouseWheelWindow,MouseWheelDir

Procedure LowLevelMouseProc(nCode.i,wParam.i,lParam.i)
  Protected *data.MSLLHOOKSTRUCT, wNewParam.l, lNewParam.l
  If wParam = #WM_MOUSEWHEEL
    *data = lParam
    wNewParam = *data\mouseData & $FFFF0000
    lNewParam = (*data\pt\y << 16) | (*data\pt\x & $FFFF) 
    PostMessage_(MouseWheelWindow,#WM_USER_MOUSEWHEEL,wNewParam,lNewParam)
  EndIf
  ProcedureReturn CallNextHookEx_(MouseWheelHook,nCode,wParam,lParam)
EndProcedure

Procedure AddMouseWheelHook(hWnd)
  If MouseWheelHook=0
    MouseWheelHook=SetWindowsHookEx_(#WH_MOUSE_LL,@LowLevelMouseProc(),GetModuleHandle_(0),0)
  EndIf
  MouseWheelWindow=hWnd
  ProcedureReturn MouseWheelHook
EndProcedure

Procedure RemoveMouseWheelHook()
  If MouseWheelHook
    UnhookWindowsHookEx_(MouseWheelHook)
    MouseWheelHook=0
  EndIf
EndProcedure

; ****

Procedure MyWindowCallback(WindowID, Message, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected info.s, dwValue.l, dwValue2.l
  
  Select Message
    Case #WM_USER_MOUSEWHEEL
      dwValue = wParam
      dwValue2 = lParam
      info = "User Message Delta = " + Str(HIWORD(dwValue) / #WHEEL_DELTA)
      info + " / X = " + Str(LOWORD(dwValue2)) + " /  Y = " + Str(HIWORD(dwValue2))
      Debug info
      
    Case #WM_MOUSEWHEEL
      dwValue = wParam
      dwValue2 = lParam
      info = "Window Message Delta = " + Str(HIWORD(dwValue) / #WHEEL_DELTA)
      info + " / X = " + Str(LOWORD(dwValue2)) + " /  Y = " + Str(HIWORD(dwValue2))
      Debug info
      
  EndSelect
  
  ProcedureReturn Result
EndProcedure


If OpenWindow(0,400,200,640,320,"Mouse Hook",#PB_Window_SystemMenu)
  
  AddMouseWheelHook(WindowID(0)) ; Makes mouse slow and laggy to move.
  
  SetWindowCallback(@MyWindowCallback())
  
  Repeat
    ev=WaitWindowEvent()
  Until ev=#PB_Event_CloseWindow
EndIf


Re: Mouse wheel hook laggy in Windows

Posted: Sat Dec 24, 2022 9:55 pm
by BarryG
mk-soft wrote: Sat Dec 24, 2022 3:00 pmIt runs smoothly for me
Thanks for the confirmation and new test code,mk-soft, but your code is still laggy for me when I move the mouse around. I guess this must mean that my PC is at fault (mouse driver or something?). Dang it.

[Edit] Wow, by amazing co-incidence, Santa gave me a new keyboard, mouse and headset combo today (Laser KBX-ULT4IN1GL). When I tried my code with the new mouse, there is no lag at all! This new mouse is 6400 DPI, but I'm not sure what the old one was because I don't have the manual for it anymore. Anyway, this was definitely a mouse problem rather than code.

But the question still remains: can my original code somehow be made better for users with a crappy lower-DPI mouse?

Re: Mouse wheel hook laggy in Windows

Posted: Sun Dec 25, 2022 4:42 am
by idle
what about this

Code: Select all

#WH_MOUSE_LL = 14 
#WM_MOUSEHWHEEL = 526

Structure MSLLHOOKSTRUCT
    pt.POINT;
    mouseData.l;
    flags.l;
    time.l;
    dwExtraInfo.l;
EndStructure

Global myKeyHook.l

Procedure.l MouseProc(ncode.l,wParam.l,lParam.l)
    
    Static lbStarttime.i,lbEndtime.i 
    Static rbStarttime.i,rbEndtime.i
    Static sx,ex,sy,ey
    Protected px,py
    Static mMouseInput.MSLLHOOKSTRUCT
    CopyMemory(lparam,@mMouseInput,SizeOf(MSLLHOOKSTRUCT))  
    Static mInput.MOUSEINPUT
    
    If ncode = #HC_ACTION
      If wParam 
                                      
        Select wParam

        Case #WM_LBUTTONDOWN
          sx= mMouseInput\pt\x
          sy= mMouseInput\pt\y
          lbStartTime = mMouseInput\time 
          AddGadgetItem(0, -1, "Left Button Down")
        Case #WM_LBUTTONUP
          ex= mMouseInput\pt\x
          ey= mMouseInput\pt\y
          lbEndtime = mMouseInput\time 
          AddGadgetItem(0, -1, "Left Button Up (" + Str(lbEndTime - lbStartTime) + " ms elapsed)")
        Case #WM_RBUTTONDOWN
          sx=mMouseInput\pt\x
          sx=mMouseInput\pt\y
          rbStartTime = mMouseInput\time 
          AddGadgetItem(0, -1, "Right Button Down") 
        Case #WM_RBUTTONUP
          ex=mMouseInput\pt\x
          ey=mMouseInput\pt\y
          rbEndtime = mMouseInput\time 
          AddGadgetItem(0, -1, "Right Button Up (" + Str(rbEndTime - rbStartTime) + " ms elapsed)")      
        Case #WM_MOUSEMOVE
          px = mMouseInput\pt\x 
          py = mMouseInput\pt\y 
        Case #WM_MOUSEWHEEL
          If mMouseInput\mouseData > 0 
             Debug "up"  
          Else 
             Debug "down"
          EndIf  
        EndSelect
     EndIf 
   EndIf 
      
   ProcedureReturn CallNextHookEx_(myMousehook, nCode, wParam, lParam)

EndProcedure 

Procedure SetMouseHook()
    hInstance = GetModuleHandle_(0)
      
    If hInstance 
       myMouseHook = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseProc(),hInstance,0) 
    Else 
       MessageRequester("hook", "can't get module handle")
    EndIf  

EndProcedure 

Procedure KillMouseHook()
   UnhookWindowsHookEx_(myMouseHook)
   MyMouseHook = 0
EndProcedure 

If OpenWindow(0, 0, 0, 500, 300, "Mouse Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetMouseHook()
  EditorGadget (0, 10, 10, 480, 260)
  TextGadget(1, 10,  280, 250, 20, "Click in this here area down here")
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

KillMouseHook() 


Re: Mouse wheel hook laggy in Windows

Posted: Sun Dec 25, 2022 10:08 am
by mk-soft
Also good, but you don't need to copy the MouseInput structure. You can also work with a pointer.

Re: Mouse wheel hook laggy in Windows

Posted: Sun Dec 25, 2022 10:38 am
by idle
There's no need to copy it, I think the intent was to shunt the event into a ring buffer. It's an old code that would have become part of my remote desktop app

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Dec 26, 2022 10:48 am
by BarryG
I just tried mk-soft and idle's codes with my old mouse, and it still had lag/jerky movements with both. Plugged in my new mouse (to the same USB port) and there is NO lag. Marking this topic as "Solved" as it's definitely a hardware issue, rather than a coding issue. Sorry for wasting both your time.

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Dec 26, 2022 1:13 pm
by mk-soft
No problem.

It keeps me a bit fit, into the Windows API.

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Fri Aug 18, 2023 12:28 am
by BarryG
@mk-soft: Just a quick message to say your code above just did help me out with a new unexplained mouse wheel hook issue I was having. So thanks again for posting it! (For some reason, the code in my first post was always returning 0 for the MouseWheelDir variable, when it never did before. Your code enabled me to get my app working again).

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:45 am
by BarryG
New problem with PureBasic 6.10: I'm using Idle's code above but my app is now crashing on this line:

Code: Select all

CopyMemory(lparam,@mMouseInput,SizeOf(MSLLHOOKSTRUCT))
The error was caught with OnErrorCall() as "Access violation" for that line. Any tips on how to fix this?

I note that Idle has longs for his procedure call, but mk-soft has integers?

Code: Select all

mk-soft: Procedure LowLevelMouseProc(nCode.i,wParam.i,lParam.i)
idle   : Procedure.l MouseProc(ncode.l,wParam.l,lParam.l)
Which is correct? Thanks.

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:46 am
by Fred
needs to be integer

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:47 am
by BarryG
Okay, thanks Fred! :)

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:48 am
by idle
Change to .i

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:51 am
by BarryG
Changed to ".i" and all is working well again. Far out. Coding with 6.10 is so confusing now. :(

Re: [Solved] Mouse wheel hook laggy in Windows

Posted: Mon Mar 11, 2024 10:58 am
by mk-soft
This is not a problem with pb v6.10.
It is a problem with old codes written for x86.