Sign in to follow this  
Symphonic

Incredible trouble with SetCursorPos

Recommended Posts

Symphonic    313
I'm trying to provide some functionality in my windows code to read in total change in the mouse's position since the last frame, the main loop is something like this: process messages { if it's a mouse move, calculate distance from center of screen and add to aggregate } update game world draw game world set mouse aggregate to zero, SetCursorPos( center of screen ) I'm getting really erratic behaviour, the cursor stays where its supposed to all the time, but the aggregate is always zero, or randomly very high values. Any thoughts on fixing it?

Share this post


Link to post
Share on other sites
Symphonic    313
The code is on a different comp right now,

I'm using the message parameters that are passed to the window message processor, they are integer coordinates from the top left corner of the window.

I'm going to have a look at GetCursorPos...

Share this post


Link to post
Share on other sites
simon10k    220
I've had that problem before, when processing the WM_MOVE message. DirectInput is probably a better choice for what your trying.

Share this post


Link to post
Share on other sites
Symphonic    313
OK, I figured out how to do it, it's actually quite elegant.

I gave up trying to process mouse movement in the window message handler, instead I wrote a function to process the mouse movement using GetCursorPos(), because it gives the cursor position in screen coordinates (not window coordinates), I needed to do some translation back and forth.

This functions is called every frame to translate mouse movement:

static void updateMouse(HWND hWnd){
vec2 &v = glbc_mouse_location;
POINT p;
RECT c,w;
GetCursorPos(&p);

// translate cursor into client coordinates
GetWindowRect(hWnd, &w);

p.x -= w.left + window_width_diff;
p.y -= w.top + window_height_diff;

// Get client rectangle and transform mouse coordinates
GetClientRect(hWnd, &c);
if(glbc_pin_mouse){
v.x = p.x - (c.right/2);
v.x /= float(c.right);
v.y = (c.bottom/2) - p.y;
v.y /= float(c.bottom);

SetCursorPos(w.left + window_width_diff + c.right/2, w.top + window_height_diff + c.bottom/2);
}else{
v.x = p.x / float(c.right);
v.y = (c.bottom - p.y) / float(c.bottom);
}
}

And the following function is called to turn mouse-pinning on or off.

When the mouse is pinned, it is invisible, and confined to the window's client area, but its movements are caught by the program and translated into something useful.

When the mouse is unpinned, it is visible, and can move anywhere on-screen.

//-----------------
// mousePin(bool)
// turns mouse pinning on or off,
// changes settings so that moving the mouse changes the aggregate instead of absolute position
// or moves the mouse to its last good position and changes settings so that the absolute is changed

void mousePin(bool p){
RECT w,c;
HWND hWnd = *(HWND*)optPtr(window_handle);
GetWindowRect(hWnd, &w);
GetClientRect(hWnd, &c);

w.left += window_width_diff;
w.right = w.left + c.right;

w.top += window_height_diff;
w.bottom = w.top + c.bottom;

if(p != glbc_pin_mouse){
if(p){
glbc_mouse_old_location = glbc_mouse_location;
glbc_mouse_location =vec2(0,0);
SetCursorPos(w.left + c.right/2, w.top + c.bottom/2); // move cursor to center of screen
ClipCursor(&w); // confine the cursor to the window
ShowCursor(0);
}else{
glbc_mouse_location = glbc_mouse_old_location;
ClipCursor(0);
SetCursorPos(w.left + int(c.right*glbc_mouse_location.x), w.top + int(c.bottom*(1-glbc_mouse_location.y))); // move cursor to last unpinned position
ShowCursor(1);
}
glbc_pin_mouse = p;
}
}


Of course this code is wrought with the idiosyncrasies of the basecode I'm using, but I think it speaks for itself without further explanation. Let me know if you have any questions (yes it does work exactly as I wanted it to).

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