如何以英寸或厘米为单位精确测量具有已知DPI的鼠标的移动
How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI
我有一个罗技G500游戏鼠标,DPI为5700。
我正试图用c++写一个程序,准确地测量鼠标在物理单位的水平运动,即。厘米或英寸。
我通过WM_INPUT消息使用windows API和windows原始输入来从鼠标获得原始运动变化。
然后假设通过WM_INPUT报告的1个移动单位是1/5700英寸,并且当我跟踪鼠标的净运动时,我认为我可以执行一个简单的计算来产生净物理运动:
distance(inch) = total_movement_from_wminput/dpi;//dpi = 5700
不幸的是,计算似乎并不准确。我可以从我的鼠标垫上的物理测量中得知,在鼠标移动约6英寸时,计算得出的值约为5.5英寸(损失约1/2英寸)。
我哪里错了?我把鼠标的控制面板设置为5700DPI,它的实际DPI会比这个小吗?我的假设关于1单位的变化通过WM_INPUT是1/dpi英寸的物理运动不正确?
有谁知道我怎样才能使这个准确吗?谢谢!
Marc,
似乎问题可能是当你移动鼠标比Windows事件WM_INPUT
处理它的速度快。例如,假设鼠标在一帧中移动了2个像素。您将损失1/5700英寸(在您的情况下),因为对于一个 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
变量two来确定自上次启动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代码和说明
- 在C++中测量postscript字体宽度
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 用时钟测量程序的运行时间
- 用于测量微秒的QueryPerformanceCounter的奇怪行为
- 为什么根据测量位置测量经过的时间时会有很大的不同?
- 为什么我的程序在输入某个形状的面积的测量值后没有结束?
- 为什么在尝试测量函数返回所需的时间时,我的运行时编号是错误的?
- 分别测量每个线程上花费的 CPU 时间(C++)
- 如何测量管道延迟?
- 测量时间以在 c++ 中生成更好的随机数
- OpenCL 内核计时测量 0 秒或导致 SIGABRT
- 给定使用 C++ 或 C,我如何测量在 linux 下进行线程切换需要多长时间?可能吗?
- 使用 Qt 测量过程的实际运行时间
- 当DPI感知,全屏和无框时,客户区域在WM_NCACTIVATE上擦除
- System Verilog DPI - 在 cpp 中运行并行线程,在 SV 中运行另一个并行线程
- 为什么 std::chrono 在测量循环和编译器优化的并行 OpenMP 的执行时间时不起作用?
- V8垃圾收集器回调,用于测量GC活动
- 测量精确的时间,单位为纳秒C++
- 如何测量cudaMalloc执行时间
- 如何以英寸或厘米为单位精确测量具有已知DPI的鼠标的移动