Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problems using scroll wheel

Started by DividedByZero Sep 9, 2010 at 7:18 PM 17 replies 2.3k views
Original Post
DividedByZero
DividedByZero
Hi guys,

I have setup a message handler for detecting movement of the scroll wheel, which is all good.

case WM_MOUSEWHEEL:
{
g_mouseZ=GET_WHEEL_DELTA_WPARAM(wParam);
}
break;


But, the problem I am having is that wParam seems to be holding the value until a different Window message is recieved, whether it be a keypress, mouse movement, or whatever.

I want to have it so g_mouseZ resets back to zero when the scroll wheel is not used.

In my main message loop I am setting g_mouseZ to zero manually but this doesn't work. I am still either getting 120 or -120 (depending on the initial scrollwheel direction of movement).

Any ideas on what might be going on?

[Edited by - lonewolff on September 9, 2010 9:34:31 PM]
taby
taby
Perhaps try return 0; directly after g_mouseZ=GET_WHEEL_DELTA_WPARAM(wParam);

See WM_MOUSEWHEEL Message.

"If an application processes this message, it should return zero."
DividedByZero
DividedByZero
Hi taby,

I just tried your suggestion but it still gave the same result.
MaulingMonkey
MaulingMonkey
Quote:
Original post by lonewolff
In my main message loop I am setting g_mouseZ to zero manually but this doesn't work. I am still either getting 120 or -120 (depending on the initial scrollwheel direction of movement).

Any ideas on what might be going on?

5 lines isn't really enough. In general, don't describe code: Show code, and then describe what you expect it to do.
Try tracing through it with a debugger to see where your assumptions go awry.
You could be doing any number of silly things, such as having multiple variables named g_mouseZ (one global, one local? These things do happen without us noticing.)
DividedByZero
DividedByZero
The entire message handler is

LRESULT CALLBACK WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){	switch(message)	{		case WM_DESTROY:		{			PostQuitMessage(0);		}		break;		case WM_MOUSEMOVE:		{			g_mouseX=LOWORD(lParam);			g_mouseY=HIWORD(lParam);		}		break;		case WM_MOUSEWHEEL:		{			g_mouseZ=GET_WHEEL_DELTA_WPARAM(wParam);		}		break;	}	return DefWindowProc(hWnd,message,wParam,lParam);}


There is not much in the main program side and there is only one instane of g_mouseZ;

As I mentioned earlier as soon as he mouse is moved in the x & y direction the g_mouseZ variable resets to zero (as long as g_mouseZ=0 is present in the main loop)

The main loop is also using PeekMessage() with the PM_REMOVE flag to remove the messages from the queue.
DividedByZero
DividedByZero
I found out the issue.

I am also using the Ogre API which apparently requires WindowEventUtilities::messagePump() after the frame is rendered.

I stuck that in and things started to behave as normal.

Thanks for the tips though :)
taby
taby
OK, in any case, returning DefWindowProc is not the same as returning 0. Unless you have a very good reason otherwise, you absolutely need to return 0 when you process a message. It's stated in the MSDN docs. If you don't, further bad stuff will happen to you.
Endurion
Endurion
Quote:
Original post by taby
OK, in any case, returning DefWindowProc is not the same as returning 0. Unless you have a very good reason otherwise, you absolutely need to return 0 when you process a message. It's stated in the MSDN docs. If you don't, further bad stuff will happen to you.


No, don't! Do read in the MSDN docs. Return 0 works for some message, but not for all. You can't simply return 0 for every message you handle.

And you also need to consider that some messages after being handled by you still need to be passed on.
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
DividedByZero
DividedByZero
I agree with Endurion on this one.

Returning DefWindowProc is the standard. You only have to look at the samples in the Microsoft SDK's to see this.

And 'absolutely need to return 0' and 'should return 0' are a bit different.

BTW, thanks for the help on this one guys. :)
Nanoha
Nanoha
If your using Ogre I'd reccomend using the input handling in that (OIS). Its alot nicer to play with than windows messages.

That message pump, took me forever to work out why my things weren't working untill I found that :P.
Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.
DividedByZero
DividedByZero
Thanks Nanoha,

The sole reason that I didn't go with OIS is because OIS uses DirectInput (under Windows anyway) and because of this, mouse movement is linear and does not take into account mouse ballistics.

As a result, the mouse movement feels a bit funky and is hard to get used to.

Using WM_MOUSEMOVE, the ballistics are taken care of for you. So, the mouse feels the same as it does normally under Windows.
taby
taby
Quote:
Original post by Endurion
...


Yes you are correct, which is why I said "a very good reason otherwise", like in the event that the message must be passed on.

The right answer is still to NOT return DefWindowProc by default, and instead read the documentation for each message type to determine whether return 0; is suitable. I forgot that Microsoft has shitty consistency in their APIs.
taby
taby
Quote:
Original post by lonewolff
...


You must be kidding:
http://msdn.microsoft.com/en-us/library/ms645617%28VS.85%29.aspx
Quote:

Return Value

If an application processes this message, it should return zero.


As for ABSOLUTELY return 0, see my previous comment where I highlight the words "a very good reason otherwise". That would be like, where the documentation tells you otherwise.

FFS ppl. This kind of boils my kettle! The next time my words are twisted like this, I will have to skull f**k someone from behind, verbally, OK? /me picks up totem, shakes head, and walks away.
Ryan_001
Ryan_001
I thought I might add a good article which relates to window message handling:

http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx

Basically it boils down to, calling DefWindowProc() is safe to call under most circumstances (even if you handle/process the message), since its what you were supposed to call anyways if you didn't handle the message.
taby
taby
Quote:
Original post by Ryan_001
I thought I might add a good article which relates to window message handling:

http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx

Basically it boils down to, calling DefWindowProc() is safe to call under most circumstances (even if you handle/respond to the message), since its what you were supposed to call anyways if you didn't handle the message.


That is, until you get some fucked up behaviour because you didn't tell Windows that you've handled it.

For instance, I wonder if anyone's tested this theory with WM_PAINT messages, or anything beyond simple WM_CHAR messages for that matter. gloomyandy mentions this very thing on that page you linked to. No offense, but what this blogger writes is sheer madness, and obviously goes against what the MSDN docs say that one should do.
Ryan_001
Ryan_001
Quote:
Original post by taby
Quote:
Original post by Ryan_001
I thought I might add a good article which relates to window message handling:

http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx

Basically it boils down to, calling DefWindowProc() is safe to call under most circumstances (even if you handle/respond to the message), since its what you were supposed to call anyways if you didn't handle the message.


That is, until you get some fucked up behaviour because you didn't tell Windows that you've handled it.

For instance, I wonder if anyone's tested this theory with WM_PAINT messages, or anything beyond simple WM_CHAR messages for that matter. gloomyandy mentions this very thing on that page you linked to.


Did you even bother to read the post?

As far as handling WM_PAINT. If you don't want to use GDI to paint to a windows client area, you can safely pass all the WM_PAINT messages onto DefWindowProc(). I've never bothered to handle WM_PAINT messages for any of my programs that use DirectX.
taby
taby
Quote:
Original post by Ryan_001
...


And so, if you don't manually handle the WM_PAINT messages, yet still draw overtop of the window in question using D3D/OpenGL, you don't find yourself competing with Windows at all (e.g., Windows isn't using up extra CPU cycles for naught)?

I'm not surprised that you're not handling WM_PAINT messages with full bravado. WM_PAINT sends in little rectangles, not necessarily the entire window. To draw the little rectangles would be against the whole idea of how D3D/OpenGL operates, no?

And what occurs when you use GDI, I wonder...

In any case, not following the official documentation is just stupid. Who the fuck suggests that? Chen's been on the API team for a very long time, but why he would go against the documentation in such a bold way is beyond me. Yes, I did read the post. Yes, I follow Chen religiously. So what? He's not God. He won't strike me down with a lightning bolt if I disagree with him.

The only thing Chen has done is turn you guys into a bunch of cowboys who laugh in the face of official documentation. WTF is that good for? Nothing. Surely you use S_OK and SAFEDELETE in your D3D endevours, do you not? If so, then you're being hypocritical. If not, then you're being a cowboy...

[Edited by - taby on September 10, 2010 2:58:11 PM]
Ryan_001
Ryan_001
I'm sorry if my original post came off as hostile (tone is very hard to convey via text), I was merely posting in attempt to discuss, not argue.

Quote:
Original post by taby
And so, if you don't manually handle the WM_PAINT messages, yet still draw overtop of the window in question using D3D/OpenGL, you don't find yourself competing with Windows at all (e.g., Windows isn't using up extra CPU cycles for naught)?


I've only done a bit of GDI programming (a few lines, fills, bitmap blits were the extent of it). But from my experience if you don't handle the WM_PAINT message nothing happens. The system sends the dirty rect info via the WM_PAINT, which is then safely discarded by DefWindowProc(). Since nothing is drawn the portion of the client rect that wasn't drawn to is filled with random data (whatever was there before, stretched, scewed and/or trailed across the screen usually). I don't see how manually handling the WM_PAINT message (and doing nothing) would take more processor time than letting DefWindowProc() do nothing for you.

Quote:
I'm not surprised that you're not handling WM_PAINT messages with full bravado. WM_PAINT sends in little rectangles, not necessarily the entire window. To draw the little rectangles would be against the whole idea of how D3D/OpenGL operates, no?

And what occurs when you use GDI, I wonder...


I'm not sure what you're trying to imply here.

Quote:
In any case, not following the official documentation is just stupid. Who the fuck suggests that? Chen's been on the API team for a very long time, but why he would go against the documentation in such a bold way is beyond me. Yes, I did read the post. Yes, I follow Chen religiously. So what? He's not God. He won't strike me down with a lightning bolt if I disagree with him.

The only thing Chen has done is turn you guys into a bunch of cowboys who laugh in the face of official documentation. WTF is that good for? Nothing. Surely you use S_OK and SAFEDELETE in your D3D endevours, do you not? If so, then you're being hypocritical. If not, then you're being a cowboy...


Raymond Chen is very knowledgeable when it comes to the inner workings of the Windows API. I don't think following his advice would turn "us" guys into "a bunch of cowboys".

I'm not saying take his work as gospel truth, but rather its something to consider. The online Windows documentation is pretty sparse in a lot of areas, and its nice to have an insiders view on what goes on behind the curtains.
taby
taby
I'm glad you didn't take what I said to be too hostile either.

What I was trying to imply was that if you don't handle WM_PAINT messages properly (ValidateRect, return 0) when using GDI, D3D, or OpenGL, Windows can continue to annoy your message pump unnecessarily with old events. That is never good because it wastes CPU cycles.

The vast majority of people (other than NeHe, I suppose) handle these things with care:
http://www.gamedev.net/community/forums/topic.asp?topic_id=542639

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.