Page 1 of 1

[SOLVED] Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 3:50 pm
by Joubarbe

Code: Select all

OpenWindow(0, 0, 0, 720, 640, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
    Debug -(WParam >> 16) / #WHEEL_DELTA
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
With that code, when I pull the wheel towards me, I have negative value. But I also have negative value when I push it away from me, but only when I give it a good spin! ie. if I go very slowly, it returns 0. So it's very unreliable. (I'm using a touchpad); how to recognise with 100% certainty that the mouse wheel is going up or down?

SOLVED:

Code: Select all

OpenWindow(0, 0, 0, 720, 640, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
    Define Wheel.w = (WParam & $FFFF0000) >> 16
    If Wheel < 0
      Debug "Down"
    ElseIf Wheel > 0
      Debug "Up"
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 4:38 pm
by RASHAD
Hi
You can try
Windows x64

Code: Select all

  If Message = #WM_MOUSEWHEEL
    value = wParam >> 24
    If value = 0
      Debug "up"
    ElseIf value = 255
      Debug "down"
    EndIf
  EndIf

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 4:44 pm
by Joubarbe
RASHAD wrote: Sat Dec 06, 2025 4:38 pm Hi
You can try
Windows x64

Code: Select all

  If Message = #WM_MOUSEWHEEL
    value = wParam >> 24
    If value = 0
      Debug "up"
    ElseIf value = 255
      Debug "down"
    EndIf
  EndIf
Yep, that works, thank you! I don't know anything about this topic, but there's always some low level games like Dwarf Fortress that don't like touchpads. I cannot scroll in those games without having a buggy behaviour (it always goes up when scrolling too fast).

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 4:46 pm
by PureLust
You should check the Event Parameters.

Code: Select all

Debug ""

OpenWindow(0, 0, 0, 300, 200, "Test your Mousewheel inside here", #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
  	
        Wheel.w = (EventwParam() & $FFFF0000) >> 16
        If Wheel < 0
        	Debug -1
        ElseIf Wheel > 0
        	Debug 1
        EndIf
     
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
(Used Tipp by HeXOR from THIS Post.)

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 4:54 pm
by Joubarbe
Doesn't work with me. EventwParam() is always 0. We go through a callback here, so WParam must be used. But the previous example works fine.

EDIT: Actually no, the example of RASHAD doesn't work when I go too fast. But yours work all the time, so thank you! :D

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 5:10 pm
by PureLust
I'm not sure, if there is a real difference between WParam and EventwParam(), but there is i difference in RASHADs code and mine (or better say from HeXOR) how the Value is processed. As HeXOR wrote in his Post, he is not a fried of fixed values, so am I. :wink:

Pls try this code, and check if it also works fine.
If so, it was just the difference in processing the value from WParam, that made the difference in reliability.

Code: Select all

Debug ""

OpenWindow(0, 0, 0, 300, 200, "Test your Mousewheel inside here", #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
  	
        Wheel.w = (WParam & $FFFF0000) >> 16
        If Wheel < 0
        	Debug -1
        ElseIf Wheel > 0
        	Debug 1
        EndIf
     
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 5:29 pm
by Axolotl
The difference between wParam and EventWParam() lies in the correct call position.
EventWParam() probably only returns valid values after calling WaitWindowEvent() (WindowEvent()) and not within the callback function.

BTW:
I do this acc. to the MSDN help pages ...

Code: Select all

Procedure.w GET_WHEEL_DELTA_WPARAM(wParam) ; WORD  
  ProcedureReturn (wParam >> 16) & $FFFF 
EndProcedure 

Procedure WinCallback(hwnd, umsg, wParam, lParam) 
  Protected delta 
  Select umsg 
    Case #WM_MOUSEWHEEL 
      delta = GET_WHEEL_DELTA_WPARAM(wParam) / #WHEEL_DELTA 
      SetGadgetText(2, Str(delta)) 
  EndSelect 

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 400, 200, "MouseWheel Event handling example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  TextGadget(0,   8,  8, 240, 20, "use the MouseWheel and watch this: ")  
  TextGadget(1,   8, 32, 160, 20, "MouseWheel Direction " )  
  TextGadget(2, 176, 32, 40, 20, "<do it>", #PB_Text_Right)  
  SetWindowCallback(@WinCallback(), 0) 

  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 5:41 pm
by PureLust
Joubarbe wrote: Sat Dec 06, 2025 4:54 pm EDIT: Actually no, the example of RASHAD doesn't work when I go too fast. But yours work all the time, so thank you! :D
Usually each 'tick' from the Mousewheel is interpreted as #WHEEL_DELTA (which is set to 120 by default).

So, if RASHADs code does not work (because its assuming a fixed value), it might be, that your Touchpad gives back more 'ticks' at once (e.g. 240, 360,...)

You can check that with the following code:

Code: Select all

Debug "#WHEEL_DELTA Default-Value: "+#WHEEL_DELTA

OpenWindow(0, 0, 0, 300, 200, "Test your Mousewheel inside here", #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
  	
        Wheel.w = (EventwParam() & $FFFF0000) >> 16
        If Wheel < 0
        	Debug "Value : " + Str(Wheel) + "     -        UP      "+Str(Abs(Wheel/#WHEEL_DELTA)) + " Tick(s)"
        ElseIf Wheel > 0
        	Debug "Value :  " + Wheel + "     -     DOWN  "+Str(Wheel/#WHEEL_DELTA) + " Tick(s)"
        EndIf
     
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Anyway, recoling to WinAPI, HeXORs way [Value.w = (EventwParam() & $FFFF0000) >> 16] seems to be the way to handle the Data from WParam right.
"The high-order word indicates the distance the wheel is rotated, expressed in multiples or divisions of WHEEL_DELTA, which is 120." :wink:

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 6:21 pm
by RNBW
I have tried all the alternatives and I get RASHAD's and Purelust's code to work, with the exception of his last bit of code. When I tried that I got Value -120 UP 1 Tick(s) when scrolling down and 120 DOWN 1 Tick(s) when scrolling up.

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sat Dec 06, 2025 6:28 pm
by PureLust
Axolotl wrote: Sat Dec 06, 2025 5:29 pm BTW:
I do this acc. to the MSDN help pages ...

Oh, I see. The Problem in your first code was only, that you have not handled the Result from [x >> 16] as a Word-Value (e.g. by storing it into a Word-Variable), so you don't get a signed result.
$ffff (as a Long = 65535) is different to $ffff (as a Word = -1).

Here is your original code, only added the usage of the Word variable Wheel.w and now it's working as expected: :wink:

Code: Select all

OpenWindow(0, 0, 0, 720, 640, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message = #WM_MOUSEWHEEL
  	Wheel.w = WParam >> 16
    Debug Str((WParam >> 16) / #WHEEL_DELTA) + "     -     " + Str(Wheel / #WHEEL_DELTA)
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sun Dec 07, 2025 12:00 am
by BarryG
I've been doing it like this for years with no problem:

Code: Select all

#mouse_wheel_up=-1
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
  #mouse_wheel_down=-545
CompilerElse
  #mouse_wheel_down=1
CompilerEndIf

[...]

If ev=#WM_MOUSEWHEEL ; From WaitWindowEvent()
  dir=-(EventwParam()>>16)/#WHEEL_DELTA
  If dir=#mouse_wheel_up
    ; Do something when scrolled up
  ElseIf dir=#mouse_wheel_down
    ; Do something when scrolled down
  EndIf
EndIf

Re: Reliable #WM_MOUSEWHEEL value?

Posted: Sun Dec 07, 2025 9:16 am
by Joubarbe
BarryG wrote: Sun Dec 07, 2025 12:00 am I've been doing it like this for years with no problem:

Code: Select all

OpenWindow(0, 0, 0, 720, 640, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

#mouse_wheel_up=-1
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
  #mouse_wheel_down=-545
CompilerElse
  #mouse_wheel_down=1
CompilerEndIf

Procedure.i WinCallback(WindowID, Message, WParam, LParam)
  Define Result = #PB_ProcessPureBasicEvents
  
  If Message=#WM_MOUSEWHEEL ; From WaitWindowEvent()
    Define dir=-(EventwParam()>>16)/#WHEEL_DELTA
    If dir=#mouse_wheel_up
      Debug "up"
      ; Do something when scrolled up
    ElseIf dir=#mouse_wheel_down
      Debug "down"
      ; Do something when scrolled down
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

SetWindowCallback(@WinCallback())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Dwarf Fortress have been doing their system for years too, and that doesn't mean it works for everyone. Your code doesn't take into account multiple scrolling steps done at the same time. Take the code below, every step has an event, but not in your code; it basically goes one by one. It's definitely not wrong, but it's not entirely right. Plus, this arbitrary value feels very weird to me. The faster you scroll, the higher the number. And again, as it has been previously noted, WParam should be converted to a Word.

Code: Select all

If Message = #WM_MOUSEWHEEL
  Define Wheel.w = (WParam & $FFFF0000) >> 16
  If Wheel < 0
    Debug "Down"
  ElseIf Wheel > 0
    Debug "Up"
  EndIf
EndIf

Re: [SOLVED] Reliable #WM_MOUSEWHEEL value?

Posted: Sun Dec 07, 2025 1:31 pm
by BarryG
I meant my code is only meant to show if the wheel is scrolled up or down, so you can do something from that. That's all. Any deeper use is up to you.

In my case, it zooms in or out of an image when scrolled, and it works fine.