How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI

◇◆丶佛笑我妖孽 提交于 2019-12-02 01:29:07

Marc,

It seems that the problem may be when you move the mouse faster than Windows event WM_INPUT processes it. For instance, suppose the mouse moved 2 pixels in one frame. You would have a loss of 1/5700th of an inch (in your case) because for the one WM_INPUT event processed, you would move two pixels.

To fix this, you should check how many pixels the mouse moves every time the WM_INPUT message is sent to the program. What you have to do is make a RAWINPUTDEVICE variable and set the struct so it has the information about the mouse.

The following code registers the RAWINPUTDEVICE so it can be used in WM_INPUT.

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]);

The following code acutally uses the Rid variable two determine how many pixels the mouse has moved since the last time WM_INPUT was initiated.

case WM_INPUT: 
{
    UINT dwSize = 40;
    static BYTE lpb[40];

    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; // Could be 1, or could be more than 1
        int yPosRelative = raw->data.mouse.lLastY; // Could be 1, or could be more than 1!
    } 
    break;
}

Note that this code is the same code presented on msdn on this very topic (link below).

You could now have some type of global variable that has the x-position and y-position (in pixels) of the mouse. Then, you simply divide those variables by the DPI, and you have the amount of inches offset from whenever you set the global variables to 0.


An altogether easier method would be to process the WM_MOUSEMOVE event instead. It makes it easy to get the exact position of the mouse (in pixels, of course). Using this, you can subtract this from the pixel values of the starting location.

Example:

DPI = 5700.

Initial position = (100px, 300px).

Position after 3 seconds = (500px, 400px).

The amount of inches moved in those 3 seconds = ( (500px - 100px)/5700 inches, (400px - 300px)/5700 inches )

General rule: Amount of inches moved after S seconds = (inital_pixels_x - final_pixels_x)/DPI inches

horizontally, (initial_pixels_y - final_pixels_y)/DPI inches vertically

Here, final_pixels_x is the x-position of the mouse after s seconds, and final_pixels y is the y-position after s seconds.


To summarize what you did wrong, you incorrectly assumed that each WM_INPUT event means that 1 pixel was travelled by the mouse.

If I for some reason misunderstood the question and you know that you are already getting the correct amount of pixels moved, please leave a comment and I will do my best to try and fix my answer. However, I would still recommend using WM_MOUSEMOVE instead of WM_INPUT as it is specifically for the mouse and it applies "pointer acceleration" which you can read about on the link at the very bottom.

Thank you for asking your question, tcs08

Msdn code and explanation for mouse input with WM_INPUT

Msdn code and explanation for mouse input with WM_MOUSEMOVE

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!