Incredible trouble with SetCursorPos

Started by
4 comments, last by Andrew Russell 18 years, 10 months ago
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?
Geordi
George D. Filiotis
Advertisement
Post the relevant code. What are you using to calculate the position of the cursor by the way? GetCursorPosition()?
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...
Geordi
George D. Filiotis
I've had that problem before, when processing the WM_MOVE message. DirectInput is probably a better choice for what your trying.
-----------------------------Language: C++API: Win32, DirectXCompiler: VC++ 2003
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 changedvoid 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).
Geordi
George D. Filiotis
I know you've fixed it - but just to point out what your problem probably was for people googling - SetCursorPos fires a WM_MOUSEMOVE event.

This topic is closed to new replies.

Advertisement