[SOLVED] Reliable #WM_MOUSEWHEEL value?

Just starting out? Need help? Post your questions and find answers here.
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

[SOLVED] Reliable #WM_MOUSEWHEEL value?

Post 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
Last edited by Joubarbe on Sun Dec 07, 2025 9:17 am, edited 2 times in total.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5017
Joined: Sun Apr 12, 2009 6:27 am

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
Egypt my love
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Reliable #WM_MOUSEWHEEL value?

Post 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).
PureLust
Enthusiast
Enthusiast
Posts: 486
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Reliable #WM_MOUSEWHEEL value?

Post 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.)
Last edited by PureLust on Sat Dec 06, 2025 4:59 pm, edited 2 times in total.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
PureLust
Enthusiast
Enthusiast
Posts: 486
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Axolotl
Addict
Addict
Posts: 905
Joined: Wed Dec 31, 2008 3:36 pm

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
PureLust
Enthusiast
Enthusiast
Posts: 486
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Reliable #WM_MOUSEWHEEL value?

Post 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:
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
RNBW
User
User
Posts: 77
Joined: Thu Jan 02, 2014 5:01 pm

Re: Reliable #WM_MOUSEWHEEL value?

Post 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.
PureLust
Enthusiast
Enthusiast
Posts: 486
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
BarryG
Addict
Addict
Posts: 4292
Joined: Thu Apr 18, 2019 8:17 am

Re: Reliable #WM_MOUSEWHEEL value?

Post 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
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Reliable #WM_MOUSEWHEEL value?

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

Re: [SOLVED] Reliable #WM_MOUSEWHEEL value?

Post 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.
Post Reply