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

前端 未结 1 1969
花落未央
花落未央 2021-01-22 22:49

I have a Logitech G500 gaming mouse that is running at its full DPI of 5700.

I\'m trying to write a program in C++ that accurately measures horizontal movement of the mo

相关标签:
1条回答
  • 2021-01-22 23:25

    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

    0 讨论(0)
提交回复
热议问题