马克,
似乎问题可能在于您移动鼠标的速度比 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代码及说明