在Qt中获取原始鼠标移动
Get Raw Mouse Movement in Qt
在处理了这个和QAbstractNativeEventFilter类之后,我终于从HID(鼠标和键盘)获得了本机事件。
我读过很多类似的问题,但没有一个能解决我的问题。我试着让鼠标移动基于dpi。我在Qt 5.5上工作,因为我的整个项目都建在那里。
即使使用RIM_TYPEMOUSE标志,我也无法将鼠标移动事件与其他HID事件(鼠标和键盘)分开。
以下是我的实现中的一些代码:
bool MouseRawMovement::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
if(eventType == "windows_generic_MSG")
{
MSG *msg = reinterpret_cast<MSG*>(message);
qDebug()<<msg->message; // It prints numbers such as 6,26,28,141 on each event
if(msg->message == WM_INPUT) //it never gets in
{
UINT dwSize = 40;
static BYTE lpb[40];
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
qDebug()<<xPosRelative<<yPosRelative ;
}
}
}
return false;
}
这里还有我的构造函数
MouseRawMovement::MouseRawMovement()
{
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = 0;
if(!RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])))
qDebug()<<QString::number(GetLastError()); //I see error msg 6 - Ref. ERROR_INVALID_HANDLE
}
输出始终显示零(0)。
hWnd怎么了。我试着给出这个:
HWND hWnd =::GetConsoleWindow();
但我得到了同样的结果。
在main.cpp中,我安装了本机过滤器
MainWindow w;
a.installNativeEventFilter(&w.mm);
我试了好几天都没找到解决办法。有人。。。(??)
@nnatar您的帮助是巨大的!非常感谢。
我终于找到了解决办法。
我不得不在main.cpp中调用RegisterRawInputDevices
,并更改了很多内容。
这是main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <windows.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
a.installNativeEventFilter(&w.mm);
w.show();
UINT nDevices;
PRAWINPUTDEVICELIST pRawInputDeviceList;
if (!GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)))
{
qDebug() << "ERROR -- GetRawInputDeviceList ...";
return 1;
}
if (!(pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices)))
{
qDebug() << "Initialization failed...";
return 1;
}
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)w.effectiveWinId();
if(!RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])))
qDebug()<<"Huston Problem.";
qDebug()<<QString::number(GetLastError());
return a.exec();
}
这是Mouse Handlig Class 的一部分
bool MouseRawMovement::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
if(eventType == "windows_generic_MSG")
{
MSG *msg = reinterpret_cast<MSG*>(message);
if(msg->message == WM_INPUT)
{
UINT dwSize = 40;
static BYTE lpb[40];
if(!GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT,lpb, &dwSize, sizeof(RAWINPUTHEADER)))
qDebug()<<"Error GetRawInputData";
else
{
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
//qDebug()<<xPosRelative<<yPosRelative;
}
}
}
}
return false;
}
正如GetRawInputData MSDN页面所述,该函数的第一个参数是
hRawInput[in]
类型:HRAWMINPUT
RAWMINPUT结构的句柄。这来自WM_INPUT中的lParam。
所以,您需要首先检查正在处理的消息是否是WM_INPUT消息(msg->message == WM_INPUT
),然后才尝试提取原始输入数据。接下来,WM_INPUT消息的lParam
是
lParam
RAWMINPUT结构的句柄,包含来自设备的原始输入。
正如WM_INPUT MSDN页面上所说。您需要在GetRawInputData函数中使用此句柄。现在,您使用的数据句柄不正确,因此GetRawInputData不会向您返回任何有效信息(它只是不知道在哪里处理数据)。
您应该阅读文章MSDN:使用原始输入。在那里你可以找到键盘和鼠标原始输入处理的示例代码。
有用的链接:
- MSDN:GetRawInputData
- MSDN:WM_INPUT
- MSDN:RegisterRawInputDevices–您应该将应用程序与原始输入相关联,以接收WM_input消息
- MSDN:使用原始输入–用于注册原始输入和原始输入处理的示例代码
还有一件事。您可以使用相等运算符将QByteArray实例与字符串进行比较,在您的情况下,它将是这样的:if (eventType == "windows_generic_MSG") {...}
。这是因为QByteArray有过载的相等运算符:
bool QByteArray::operator==(const QString & str) const
你可以在这个页面上阅读:QByteArray::operator==。
更新
MSDN:RAWINPUTDEVICE页面指出
RIDEV_INPUTSINK 0x00000100
如果设置,这将使调用方能够接收即使当呼叫者不在前台时输入。请注意必须指定hwndTarget。
您有INVALID_HANDLE_ERROR错误,因为您需要指定窗口的hWnd。什么是MainWindow
类?您继承了QMainWindow还是QWidget?Qt中的每个小部件都有winId
属性(WIdQWidget::winId()const),这正是您要查找的hWnd。因此,您需要获取窗口的winId()
,将其强制转换为HWND
,然后像这样写入Rid
结构:
Rid[0].hwndTarget = (HWND)w->winId();
如果它没有帮助,那么你需要提供一个最小、完整和可验证的例子来进行进一步的调查。
- SendInput()鼠标移动计算
- Win32 发送输入鼠标移动滞后并冻结
- 如何通过拖动鼠标QT检查按钮?鼠标移动事件
- 使用具有设置延迟C++的mouse_event平滑鼠标移动
- Qt将鼠标移动事件转移到新窗口
- Qt 如何使用鼠标移动事件移动视图
- 触发鼠标按下事件,但不触发鼠标移动事件
- 发送到另一个窗口的鼠标移动消息不执行任何操作
- 如何将双精度类型的鼠标移动 x 和 y 从主机传递到 Qemu 中的虚拟机
- GLFW 不会检测到 GLFW 窗口外的鼠标移动
- QT QTest::键单击或鼠标移动似乎不适用于 QMenu 在我的情况下
- MFC GUI 自定义控件:如何绘制光标更新以响应鼠标移动?
- 在Qt5的OpenGL绘图中通过鼠标移动计算对象旋转角度
- SDL2 中的 GLFW 风格的无限鼠标移动
- 如何使用SFML鼠标移动分别移动多个图像
- 当光标锁定在屏幕中时,如何获得鼠标移动
- 当鼠标移动时,如何从wm_mousemove中获得每个像素坐标
- 如何在使用鼠标移动时捕捉QWidget几何图形
- 在Qt中获取原始鼠标移动
- 在eventFilter()中未捕获Qt鼠标移动事件