2

我有一个罗技 G500 游戏鼠标,它的全 DPI 为 5700。

我正在尝试用 C++ 编写一个程序,该程序可以准确地测量鼠标在物理单位中的水平移动,即。厘米或英寸。

我通过 WM_INPUT 消息使用 windows API 和 windows 原始输入来获取鼠标的原始移动变化。

然后我假设通过 WM_INPUT 报告的 1 个移动单位是 1/5700 英寸,当我跟踪鼠标的净移动时,我想我可以执行一个简单的计算来产生净物理移动:

距离(英寸)= total_movement_from_wminput / dpi;// 在这种情况下 dpi = 5700

不幸的是,计算似乎并不准确。我可以从鼠标垫上的物理测量中看出,鼠标移动约 6 英寸,计算得出的值约为 5 英寸半(每英寸损失约 1/2 英寸)。

我哪里错了?我在控制面板中将鼠标设置为 5700DPI,它的实际 DPI 会不会小于这个值?我假设通过 WM_INPUT 的 1 个单位变化是 1/dpi 英寸的物理运动不正确吗?

有没有人对我如何才能做到这一点有任何想法?谢谢!

4

1 回答 1

2

马克,

似乎问题可能在于您移动鼠标的速度比 Windows 事件WM_INPUT处理它的速度快。例如,假设鼠标在一帧中移动了 2 个像素。您将损失 1/5700 英寸(在您的情况下),因为对于处理的一个 WM_INPUT事件,您将移动两个像素。

要解决此问题,您应该检查每次将 WM_INPUT 消息发送到程序时鼠标移动了多少像素。您要做的是创建一个RAWINPUTDEVICE 变量并设置结构,以便它具有有关鼠标的信息。

以下代码注册了RAWINPUTDEVICE,因此可以在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]);

以下代码实际使用Rid变量 2 确定自上次WM_INPUT启动以来鼠标移动了多少像素。

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;
}

请注意,此代码与 msdn 上关于此主题的代码相同(链接如下)。

您现在可以拥有某种类型的全局变量,它具有鼠标的 x 位置和 y 位置(以像素为单位)。然后,您只需将这些变量除以 DPI,就可以得到从将全局变量设置为 0 时的英寸偏移量。


一个更简单的方法是处理WM_MOUSEMOVE事件。它可以很容易地获得鼠标的确切位置(当然,以像素为单位)。使用它,您可以从起始位置的像素值中减去它。

例子:

DPI = 5700。

初始位置 = (100px, 300px)。

3 秒后的位置 = (500px, 400px)。

在这 3 秒内移动的英寸量 = ( (500px - 100px)/5700 英寸, (400px - 300px)/5700 英寸)

一般规则:S 秒后移动的英寸数 = (inital_pixels_x - final_pixels_x)/DPI 英寸

水平方向,(initial_pixels_y - final_pixels_y)/DPI 垂直方向英寸

这里,final_pixels_x 是鼠标在 s 秒后的 x 位置,而 final_pixels y 是 s 秒后的 y 位置。


总结一下你做错了什么,你错误地假设每个WM_INPUT事件都意味着鼠标移动了 1 个像素。

如果我出于某种原因误解了这个问题,并且您知道您已经移动了正确数量的像素,请发表评论,我将尽我所能尝试修复我的答案。但是,我仍然建议使用WM_MOUSEMOVE而不是,WM_INPUT因为它专门用于鼠标,它应用“指针加速”,您可以在最底部的链接上阅读。

谢谢你的提问,tcs08

使用 WM_INPUT 进行鼠标输入的 msdn 代码和解释

WM_MOUSEMOVE鼠标输入的msdn代码及说明

于 2013-07-03T23:45:36.010 回答