WM_MOUSEWHEEL message and the Touchpad : SOLVED thanks to Randor
-
I am processing the WM_MOUSEWHEEL messages in a C++ application,
void CView::OnMouseWheel(
HWND hWnd,
int xPos,
int yPos,
int zDelta,
UINT fwKeys
)
{
zDelta /= WHEEL_DELTA; // calculate the number of lines to move
if (zDelta != 0)
{
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}
}but when I use the touchpad nothing happens. Following the advice in the MSDN documentation I divide the zDelta value by 120 (WHEEL_DELTA) to calculate the (approximate) number of lines to scroll. The debugger shows that the resulting value is always zero. If I use my mouse and turn the wheel it scrolls correctly. The weird part is that using other applications (VS, Word, Chrome etc.) the touchpad works correctly. So I conclude that the code should somehow get some other information that identifies the touchpad, and adjusts the delta accordingly. Anyone else seen similar problems? [edit] Thanks to David D's sugestion I modified the code to accumulate deltas that are less than the value of WHEEL_DELTA, thus:
static int myDelta = 0;
if (abs(zDelta) < WHEEL_DELTA)
{
myDelta += zDelta;
zDelta = myDelta;
}
zDelta /= WHEEL_DELTA; // this value works better than WHEEL_DELTA;
if (zDelta != 0)
{
myDelta = myDelta % WHEEL_DELTA; // save the remainder for further movements
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}which works a treat. Note that I use the value 3 for the number of lines to scroll. In a proper commercial application the code should use the value of the system parameter:
SPI_GETWHEELSCROLLLINES
. [/edit]I found the mouse wheel events specific to the "mouse wheel". When using only touch (tablet swipe) I got the scrolling, but the "wheel event" that I used to detect "at bottom or top" no longer fires and I need to find something else. I think it now has to tie into a "view changing" and / or "view changed" event and / or manipulation started / ended. (And I think a touchpad is treated as a "pointer" in Windows 10).
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.' ― Confucian Analects
-
I am processing the WM_MOUSEWHEEL messages in a C++ application,
void CView::OnMouseWheel(
HWND hWnd,
int xPos,
int yPos,
int zDelta,
UINT fwKeys
)
{
zDelta /= WHEEL_DELTA; // calculate the number of lines to move
if (zDelta != 0)
{
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}
}but when I use the touchpad nothing happens. Following the advice in the MSDN documentation I divide the zDelta value by 120 (WHEEL_DELTA) to calculate the (approximate) number of lines to scroll. The debugger shows that the resulting value is always zero. If I use my mouse and turn the wheel it scrolls correctly. The weird part is that using other applications (VS, Word, Chrome etc.) the touchpad works correctly. So I conclude that the code should somehow get some other information that identifies the touchpad, and adjusts the delta accordingly. Anyone else seen similar problems? [edit] Thanks to David D's sugestion I modified the code to accumulate deltas that are less than the value of WHEEL_DELTA, thus:
static int myDelta = 0;
if (abs(zDelta) < WHEEL_DELTA)
{
myDelta += zDelta;
zDelta = myDelta;
}
zDelta /= WHEEL_DELTA; // this value works better than WHEEL_DELTA;
if (zDelta != 0)
{
myDelta = myDelta % WHEEL_DELTA; // save the remainder for further movements
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}which works a treat. Note that I use the value 3 for the number of lines to scroll. In a proper commercial application the code should use the value of the system parameter:
SPI_GETWHEELSCROLLLINES
. [/edit]Is your message loop receiving any other messages (e.g.,
WM_TOUCH
) when the touch pad is being interacted with?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
-
I found the mouse wheel events specific to the "mouse wheel". When using only touch (tablet swipe) I got the scrolling, but the "wheel event" that I used to detect "at bottom or top" no longer fires and I need to find something else. I think it now has to tie into a "view changing" and / or "view changed" event and / or manipulation started / ended. (And I think a touchpad is treated as a "pointer" in Windows 10).
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.' ― Confucian Analects
The messages are coming through correctly, but the delta value is always less than 120. That is unless I give a fast swipe from top to bottom of the pad. I have checked the parameters sent with the message and, apart from the delta value, they are the same for the mouse or the touchpad. More debugging required I expect.
-
Is your message loop receiving any other messages (e.g.,
WM_TOUCH
) when the touch pad is being interacted with?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
-
I am processing the WM_MOUSEWHEEL messages in a C++ application,
void CView::OnMouseWheel(
HWND hWnd,
int xPos,
int yPos,
int zDelta,
UINT fwKeys
)
{
zDelta /= WHEEL_DELTA; // calculate the number of lines to move
if (zDelta != 0)
{
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}
}but when I use the touchpad nothing happens. Following the advice in the MSDN documentation I divide the zDelta value by 120 (WHEEL_DELTA) to calculate the (approximate) number of lines to scroll. The debugger shows that the resulting value is always zero. If I use my mouse and turn the wheel it scrolls correctly. The weird part is that using other applications (VS, Word, Chrome etc.) the touchpad works correctly. So I conclude that the code should somehow get some other information that identifies the touchpad, and adjusts the delta accordingly. Anyone else seen similar problems? [edit] Thanks to David D's sugestion I modified the code to accumulate deltas that are less than the value of WHEEL_DELTA, thus:
static int myDelta = 0;
if (abs(zDelta) < WHEEL_DELTA)
{
myDelta += zDelta;
zDelta = myDelta;
}
zDelta /= WHEEL_DELTA; // this value works better than WHEEL_DELTA;
if (zDelta != 0)
{
myDelta = myDelta % WHEEL_DELTA; // save the remainder for further movements
// line up or down once per delta
OnVScroll(hWnd, NULL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN, 3);
}which works a treat. Note that I use the value 3 for the number of lines to scroll. In a proper commercial application the code should use the value of the system parameter:
SPI_GETWHEELSCROLLLINES
. [/edit]Hi,
Richard MacCutchan wrote:
I divide the zDelta value by 120 (WHEEL_DELTA) to calculate the (approximate) number of lines to scroll.
While it is true that the many of the old mouse drivers sent WHEEL_DELTA in multiples of 120 that is not always the case for high-precision mice and touchpads. You are probably getting values much smaller than 120. To fix your code you need to keep track of the delta modulo of +/- 120 in a static local or class variable and add/subtract the latest delta from the previous value. I also observe that you are hard-coding the line count rather than retrieving the user preference via SystemParametersInfo with SPI_GETWHEELSCROLLLINES. Best Wishes, -David Delaune
-
Hi,
Richard MacCutchan wrote:
I divide the zDelta value by 120 (WHEEL_DELTA) to calculate the (approximate) number of lines to scroll.
While it is true that the many of the old mouse drivers sent WHEEL_DELTA in multiples of 120 that is not always the case for high-precision mice and touchpads. You are probably getting values much smaller than 120. To fix your code you need to keep track of the delta modulo of +/- 120 in a static local or class variable and add/subtract the latest delta from the previous value. I also observe that you are hard-coding the line count rather than retrieving the user preference via SystemParametersInfo with SPI_GETWHEELSCROLLLINES. Best Wishes, -David Delaune
Randor wrote:
you need to keep track of the delta
Thanks David, that works perfectly - simple when you know how. As to the fixed value, this is purely for personal use so I am not too concerned with system settings; although I notice that 3 is the default value.
-
Is your message loop receiving any other messages (e.g.,
WM_TOUCH
) when the touch pad is being interacted with?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
-
I found the mouse wheel events specific to the "mouse wheel". When using only touch (tablet swipe) I got the scrolling, but the "wheel event" that I used to detect "at bottom or top" no longer fires and I need to find something else. I think it now has to tie into a "view changing" and / or "view changed" event and / or manipulation started / ended. (And I think a touchpad is treated as a "pointer" in Windows 10).
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.' ― Confucian Analects
-
Randor wrote:
you need to keep track of the delta
Thanks David, that works perfectly - simple when you know how. As to the fixed value, this is purely for personal use so I am not too concerned with system settings; although I notice that 3 is the default value.
Richard MacCutchan wrote:
Thanks David, that works perfectly
Looks good, although I do see a minor issue with your latest code. You are dropping the remainder without the modulo operation. Rather than setting your delta to zero you should keep the remainder after scrolling with:
myDelta = myDelta % WHEEL_DELTA;
Such a precision loss is probably not a big deal for simply scrolling a text window. But let's make our code samples more correct. Best Wishes, -David Delaune
-
Richard MacCutchan wrote:
Thanks David, that works perfectly
Looks good, although I do see a minor issue with your latest code. You are dropping the remainder without the modulo operation. Rather than setting your delta to zero you should keep the remainder after scrolling with:
myDelta = myDelta % WHEEL_DELTA;
Such a precision loss is probably not a big deal for simply scrolling a text window. But let's make our code samples more correct. Best Wishes, -David Delaune
-
The touchpad is just a mouse to the system, but it sends
WM_MOUSEWHEEL
messages somewhat differently. I have added the solution to my original post.Glad you got it working. Yes, "delta" is a double, so it has quite a range. I needed the "Manipulation events" which give scroll direction and distance.
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.' ― Confucian Analects
-
Glad you got it working. Yes, "delta" is a double, so it has quite a range. I needed the "Manipulation events" which give scroll direction and distance.
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.' ― Confucian Analects
The strange thing was that using both the debugger and Spy++, I could not 'see' the multiple messages coming in. In both cases after a scroll gesture on the touchpad, they both showed just one message and then went back to the application window. So it as if the delta values were just too small. BTW, thanks for your interest.