Reputation: 3366
I'm wondering how to get true mouse displacement with windows.
For example, I could save the position of a previous mouse position, and request the new position, and subtract the latter from the previous. But this would not give me true mouse displacement.
Imagine the previous cursor position would be the maximum x coordinate of your screen resolution, and the user is moving his mouse to the right. Is there still a way to capture the true mouse displacement then?
Thanks
Upvotes: 2
Views: 3929
Reputation: 6775
The method on windows is as such:
// you can #include <hidusage.h> for these defines
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
then in message loop:
case WM_INPUT:
{
UINT dwSize = sizeof(RAWINPUT);
static BYTE lpb[sizeof(RAWINPUT)];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
}
break;
}
Installing hooks will trigger sensitive antiviruses. MSDN doc to refer
Upvotes: 1
Reputation: 1436
The most reliable way is to use window hooks. Here is a minimalist sample using C(++)
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){
MSLLHOOKSTRUCT* hookStruct = (MSLLHOOKSTRUCT*)lParam;
int ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int x = hookStruct->pt.x * ScreenWidth / 65536);
int y = hookStruct->pt.y * ScreenHeight / 65536);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
HHOOK LowLevelMouseProcHook = NULL;
void hook_window_procedure()
{
if (LowLevelMouseProcHook == NULL)
LowLevelMouseProcHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LowLevelMouseProc, (HINSTANCE)NULL, NULL);
}
void unhook_window_procedure()
{
if (LowLevelMouseProcHook != NULL)
UnhookWindowsHookEx(LowLevelMouseProcHook);
}
You can hook the mouse calling hook_window_procedure();
and unhook it by calling unhook_window_procedure();
You will receive calls to void LowLevelMouseProc(...)
whenever the mouse moves. lParam
contains a pointer to MSLLHOOKSTRUCT
and you find all needed mouse information in its structs. Most interesting here is POINT pt;
that is in relative screen coordinates assuming 1/65536th of the screen. Transform them to real pixels by multiplying with int ScreenWidth
or int ScreenHeight
and dividing by 65536
If you struggle being clamped by the screen borders, you can make a workaround setting the mouse back to the center of your window each call. This is often seen in older games. If you are not forced to use only the Windows API, I would try using Direct Input.
Another way would be to evaluate WM_INPUT
directly in your WindowProc for example. This reads data directly from the Human Interface Device (HID) stack and should have raw Mouse-Data in it. Here is a link to the MS-Documentation
Upvotes: 1
Reputation: 6181
As far as I know DirectX has its own APIs to interact with peripherals, that is recommended for game developers. You should look into it - try for example DirectX 8 and the Mouse, more detailed documentation you can find on MSDN.
Upvotes: 1
Reputation: 1006
A common method for this (in games):
Every frame of the game, get the position of the mouse and then recenter the mouse in the middle of the window using operating system functions. For every frame other than the first, this should give you an accurate displacement information. The key is to just be re-centering the mouse every frame so it never reaches the blocking outer bounds of the screen.
EDIT: Woops, didn't realize that DXM had already said this.
Upvotes: 0
Reputation: 8587
This sort of displacement ? : http://en.wikipedia.org/wiki/Differential_calculus
Try pitch/yaw : How could simply calling Pitch() and Yaw() cause the camera to eventually Roll()?
FPS style : http://cboard.cprogramming.com/game-programming/94944-mouse-input-aiming-fps-style-using-glut.html
and this : Jittering when moving mouse
pseudo code:
int mouseX, mouseY;
int oldMouseX, oldMouseY;
while(game_is_Running)
{
oldMouseX = mouseX;
oldMouseY = mouseY;
mouseX = get_new_mouse_from_windows_X();
mouseY = get_new_mouse_from_windows_Y();
if ((mouseX - oldMouseX) > 0)
{
// mouse moved to the right
}
else if ((mouseX - oldMouseX) < 0)
{
// mouse moved to the left
}
if ((mouseY - oldMouseY) < 0)
{
// mouse moved down
}
else if ((mouseY - oldMouseY) > 0)
{
// mouse moved up
}
}
Upvotes: 0
Reputation: 3366
It is not possible to track physical mouse displacement with the Windows API. However, DirectInput provides features to keep track of it. You can also 'fake' it using only the Windows API, using the neat little trick in the answer of SO user DXM
Upvotes: -2
Reputation: 4543
Although it might be possible to actually read sensor data (after all the mouse itself only reports movement, not location), I'm not aware of how this could be done. I think at the very low levels of windows, that displacement information gets translated into cursor position on the screen and from then on, you will always be limited by your screen resolution.
In whatever you are trying to do, is the mouse cursor still visible?
A little while ago, I wrote a WPF numeric edit box control that mimicked the way those controls work in Expression Blend. The ones where you can drag the mouse from the edit box itself and it'll change the value. I ran into exactly same issue that you found and my solution was to hide the mouse cursor, detect displacement on every tick and reset the cursor to the center of the screen. Then when the user lets go of the button to stop dragging, I would put the cursor back to where I found it before the drag. This worked out really well and Expression Blend also behaves this way in hiding the cursor.
Upvotes: 2