Sign in to follow this  
fourth

Handling Mouse Movement

Recommended Posts

I'm digging up some of my old code and found that the window message pump is collecting WM_MOVE events and passing them to an input handler. To prevent a mouse from leaving the window I was resetting the mouse to the centre of the window and just collecting the delta. This was then applied to my game cursor which maintains a non centre position.

 

Problem is, I'm occasionally seeing bursts of ~1000's of WM_MOVE events come in, as when they hit the 'distance from centre' code, it just repeats the same message 1000's of times, each one moving the cursor, which flies off to the window edges. 

 

My tactical hack was to just ignore all messages after the first... but the mouse movement it now not tracking well.

 

I suspect I'm getting this all wrong. How do you guys handle mouse movement? (Note, I'm not using Direct Input)

Share this post


Link to post
Share on other sites

To prevent a mouse from leaving the window I was resetting the mouse to the centre of the window and just collecting the delta.

 

If you need to prevent the mouse from leaving any area, ClipCursor() is probably the function you are looking for.

 

For example, if you've got a click-and-drag inside your main window and you don't want the user flinging their units out of the play window, call ClipCursor() when they click, call it again with ClipCursor(0) when they've released and are allowed to exit the clipping area again.

Share this post


Link to post
Share on other sites

Kind thanks frob, that's a much better solution. It funny that you of all people answered this question after all these years. I remember your account from back in 2002 when I was last here.

Share this post


Link to post
Share on other sites

I am not reading your precise situation, but there is also this way, that you literaly can (and should) allow user to leave your window with mouse, even when setting mouse centered it can happen, but this will be handled quite correctly if you will also handle mouse returnal in a correct way, such that if you do not want to experience "instant-input-reforma" at the returnal, you detect the returnal and use it as the zero-starting differentiation value for after coming MOVE events (you reset the differential, to not experience large twist-turns on mouse returns).

 

That generally means setting cursor at center when "mouse return" is detected (while move handling is omitted), and continue listening mouse move and handling it from there.

Share this post


Link to post
Share on other sites

Um... Doesn't WM_MOVE indicate that the window was moved to a new position?

 

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632631%28v=vs.85%29.aspx

 

You get flurries of them because winapi is crufty and silly, so when you move a window you get a ton of messages until the move stops. One strategy for handling this (if you need to) is to have a struct something like

struct Derp {
  int x, y;
  bool dirty;
};

When you get a move message set the x,y accordingly and turn on the bool. When you draw or update, or whatever it is that reacts to the move, check to see if the bool is on. If so then react to the new coords and turn the bool off, otherwise nothing happened.

 

If you were referring to WM_MOUSEMOVE then I don't get why we're talking about deltas... What are you up to here? What kind of game/controls?

 

Share this post


Link to post
Share on other sites

Um... Doesn't WM_MOVE indicate that the window was moved to a new position?

WIndowd not, cursor yes.

Exactly, mouse MOVE event provides a position of event at stake, and, it is up to the responsibility of program to have recorded the last one (the differentive one).

This goes further from comfortable seeking of MOVE differency. MOVE event literaly tells momental state -but only in YOUR SCOPE of happening. If your scope of happening has been escaped, you need to track it back to yourself if returned.

Share this post


Link to post
Share on other sites

There is a little "arbitrarity" in the dilema - but I have made it succseffully towards mouse intented Control.

Serving quite well, please, ask further questions if so.

 


You simply must prepare your application for "mouse escape" eventualy, and for the "mouse returnal" event.

If it is to be smooth, you also can count on the fact that mouse escape means application dwelling, and certain actions you can take ^_^ 

Edited by JohnnyCode

Share this post


Link to post
Share on other sites

WM_MOVE message indicates a change in cursor position.

This change is attributed to you only if it happens in the scope of your APP window. No where else.

It is up to the Application speculation how to handle it. It literaly states "current postion", while the event does or does not provide previous one- in the scope of application as well- in time or anywhere else.

Share this post


Link to post
Share on other sites

My old code has mature handling of WM_MOUSEMOVE. The technique I used at the time was to turn off the cursor visibility, render a quad with a cursor texture on it for my home grown GUI. When the mouse moved from the centre (lets say 400, 300 on a 800, 600 window, I would capture the delta, set the position back to 400,300 and apply the delta to my internal mouse position. Usually something like 0, -1 if the mouse is moving downwards. 

 

However, my code is literally windows 2000 era. My mouse at the time was not even USB. Over the intervening years it seems as though the OS has moved to a model of reporting mouse moves a LOT more than it did in the past. I recorded all the events in to a file and timestamped them to work out why my mouse would move a few pixels then slam to the screen edges. 

 

Why? The logs indicates I would get a steady stream of delta's as expected(maybe a dozen a second), then BOOM, I'd get a few thousand in a very short period. When my engine applied the 1000 delta's it would move right to the boundary. 

 

When I considered the problem. I could not work out a good way to see if an update was at normal speed or was a spam update. So... I needed a new system. Hence this post.

 

My current interim solution is to just set the internal mouse to the system mouse position whenever the WM_MOUSEMOVE comes in. The spam burst seem to not affect framerate so I can ignore it for now. When I get my old circa 2002 voxel engine back up and running. However in 3d model I'll have to start working out how to start doing deltas again. My current idea on how to handle this is to just to run two mouse handlers. Only use WM_MOVE for the GUI, then when no active forms are rendered to the screen I just poll a mouse api directly I'm sure there is something in DirectInput that can help me. Everyone else has worked this out so it;s just a matter of finding some open source and digging around I guess though I'm not sure how else people handle this other than locking the mouse in to a strict position. 

 

I did try clip cursor btw, I got back success on the call but the mouse can easily wander out of the window anyway. 

Share this post


Link to post
Share on other sites

If you're using system mouse coords then I believe you can just avoid the whole thing by simply changing the cursor image when you set up the window. Clip the mouse if you need to, then just query its position whenever it's relevant.
 
Refer to:
WNDCLASS::hCursor 
 
GetCursorPos()
 
ScreenToClient()

and ClipCursor(), which Frob mentioned earlier.

 

Deltas are more useful when you're doing something like a first-person shooter, where you're interested in motion rather than position.

Share this post


Link to post
Share on other sites
I've personally started using raw input for this. It means no need to worry about the actual mouse cursor - you just get deltas representing the mouse movement.

I can post some code if you want. Edited by Aardvajk

Share this post


Link to post
Share on other sites

The logs indicates I would get a steady stream of delta's as expected(maybe a dozen a second), then BOOM, I'd get a few thousand in a very short period. When my engine applied the 1000 delta's it would move right to the boundary. When I considered the problem. I could not work out a good way to see if an update was at normal speed or was a spam update. So... I needed a new system. Hence this post. My current interim solution is to just set the internal mouse to the system mouse position whenever the WM_MOUSEMOVE comes in. The spam burst seem to not affect framerate so I can ignore it for now.

 

You should'nt handle every cursor move event by any further logic than simple remembering of it.

You should set your own explicit delta depending on your program frequency, and peek for computing newest explicit delta the time you decide to observe the explicit difference.

 

This is done that at every MOUSEMOVE message you simply save the difference by pushing it to some array (most of the time you want to algebraicaly add them), and then you are able to find out new most current explicit delta the moment you observe this MOUSEMOVE deltas-pumped array.

 

Some gamer mouses fires incredible amounts of MOUSEMOVE events, 1000 a second at least, when you disable certain mouse behaviors in windows for example.

It is totaly standard, it gives high input resolution to the gamer, but your program must handle properly this intense information.

 

If you will handle every event by some advanced definitive logic influencing your program, you will experience event-dummy artifacts. This applies even for keys.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this