【发布时间】:2018-09-25 12:53:03
【问题描述】:
对于我的大学项目,我正在开发一种解决方案,以区分来自帕金森氏症患者和健康人的鼠标用户数据。我需要鼠标数据,最好是原始数据。
我想我误解了如何从 WM_INPUT 消息中收集原始鼠标输入,但我想不通。
我一直在看以下线程:How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI 和 github 上的鼠标输入库,所有这些似乎都可以轻松捕获 WM_INPUT 消息,其 lParam 是一些 RawInputData 的句柄,如下所示:
GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0);
if (msg.message == WM_INPUT){ .....
然后从消息中检索 lParam 并收集与该句柄关联的数据:
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
但是,当我在主循环中调用 GetMessage 时,函数永远不会退出!
因此,我无法(据我所知)获取 RawInputData 的句柄。特别是因为 MSDN 页面只是假设您已经拥有 lParam。
总之,我需要一种方法让 lParam 传递给 GetRawInputData 函数,无论程序是否在活动窗口中运行,该函数都将保持活动状态。
我正在使用“winuser.h”库在 Visual Studio 中的空白 C++ CLR 项目中运行此代码。
#include "stdafx.h"
#include "Windows.h"
#include "winuser.h"
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
int main(array<System::String ^> ^args)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = 0; //ideally RIDEV_INPUTSINK but that prevents registration
Rid[0].hwndTarget = GetActiveWindow(); //ideally this would be Null to be independent of the active window
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
//registration failed. Call GetLastError for the cause of the error
Console::WriteLine("Registration Error");
}
MSG msg;
while (true) {
while (GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0) != 0) { //this command is never completed
DispatchMessage(&msg); //this line is never ran
}
if (msg.message == WM_INPUT) {
Console::WriteLine("caught a message!!!");
}
}
}
【问题讨论】:
-
WM_INPUT的文档指出:“仅当应用程序使用有效的设备规范调用RegisterRawInputDevices时,原始输入才可用”。你的应用程序这么叫吗? -
问题可能在任何地方,我们需要查看minimal reproducible example。
-
抱歉缺少代码,我已经编辑了我的原始帖子,感谢您的反馈:)
-
好吧,如果我错了,请原谅我,但我从那篇文章中得到的是,我应该通过传递
GetMessage(&msg, NULL, 0, 0)来从GetMessage函数中删除 hwnd 过滤器,但是这会导致与GetMessage之前的行为相同,从不返回值。有趣的是peekMessage确实在msg对象中返回和设置值。但是我怀疑这是否是完全有效的代码:while (true) { PeekMessage(&msg, NULL, 0, 0, 0); if (msg.message == WM_INPUT) { Console::WriteLine("Found a WMM_INPUT message"); } }
标签: windows winapi c++-cli raw-input