[Solved] Mouse wheel hook laggy in Windows

Windows specific forum
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

[Solved] Mouse wheel hook laggy in Windows

Post 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
Last edited by BarryG on Fri Aug 18, 2023 12:27 am, edited 6 times in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Mouse wheel hook laggy in Windows

Post 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

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: Mouse wheel hook laggy in Windows

Post 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?
Last edited by BarryG on Sun Dec 25, 2022 8:35 am, edited 1 time in total.
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Mouse wheel hook laggy in Windows

Post 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() 

User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Mouse wheel hook laggy in Windows

Post by mk-soft »

Also good, but you don't need to copy the MouseInput structure. You can also work with a pointer.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Mouse wheel hook laggy in Windows

Post 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
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] Mouse wheel hook laggy in Windows

Post 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.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: [Solved] Mouse wheel hook laggy in Windows

Post by mk-soft »

No problem.

It keeps me a bit fit, into the Windows API.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] Mouse wheel hook laggy in Windows

Post 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).
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] Mouse wheel hook laggy in Windows

Post 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.
Last edited by BarryG on Mon Mar 11, 2024 10:46 am, edited 1 time in total.
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: [Solved] Mouse wheel hook laggy in Windows

Post by Fred »

needs to be integer
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] Mouse wheel hook laggy in Windows

Post by BarryG »

Okay, thanks Fred! :)
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: [Solved] Mouse wheel hook laggy in Windows

Post by idle »

Change to .i
BarryG
Addict
Addict
Posts: 4138
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] Mouse wheel hook laggy in Windows

Post by BarryG »

Changed to ".i" and all is working well again. Far out. Coding with 6.10 is so confusing now. :(
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: [Solved] Mouse wheel hook laggy in Windows

Post by mk-soft »

This is not a problem with pb v6.10.
It is a problem with old codes written for x86.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply