【问题标题】:Get Raw Mouse Movement in Qt在 Qt 中获取原始鼠标移动
【发布时间】:2016-05-06 11:22:54
【问题描述】:

在处理 thisQAbstractNativeEventFilter 类之后,我终于从 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);

我尝试了几天,但找不到解决方案。有没有人...(???)

【问题讨论】:

  • 但是你的问题是什么? “不能分开”是什么意思?
  • 要么我有 RIM_TYPEMOUSE 检查要么不一样。当我按下鼠标或键盘键时,我有输出......其次,我只看到零。

标签: c++ qt winapi mouseevent raw-input


【解决方案1】:

@nnatarr 你的帮助很大!谢谢!!!

我终于找到了解决办法。

我不得不在 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;
}

【讨论】:

    【解决方案2】:

    正如GetRawInputData MSDN 页面所述,此函数的第一个参数是

    hRawInput [in]
    类型:HRAWINPUT
    RAWINPUT 结构的句柄。这来自 WM_INPUT 中的 lParam。

    因此,您需要首先检查您正在处理的消息是否是 WM_INPUT 消息 (msg-&gt;message == WM_INPUT),然后才尝试提取原始输入数据。 接下来,WM_INPUT 消息的lParam

    l参数
    包含来自设备的原始输入的 RAWINPUT 结构的句柄。

    正如WM_INPUT MSDN 页面上所说。您需要在 GetRawInputData 函数中使用此句柄。现在,您使用了不正确的数据句柄,因此 GetRawInputData 不会向您返回任何有效信息(它只是不知道从哪里获取数据来处理)。

    您应该阅读文章MSDN: Using Raw Input。在那里您可以找到键盘和鼠标原始输入处理的示例代码。

    有用的链接:

    还有一件事。您可以使用相等运算符将 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 属性 (WId QWidget::winId() const),这正是您正在寻找的 hWnd。因此,您需要将窗口的winId() 转换为HWND 并写入Rid 结构,如下所示:

    Rid[0].hwndTarget = (HWND)w->winId();
    

    如果没有帮助,您需要提供Minimal, Complete, and Verifiable example 以供进一步调查。

    【讨论】:

    • 感谢您的回答!我将 lParam 设置为 (HRAWINPUT)msg->lParam。与 WM_INPUT 的应用程序关联在构造函数中实现。我会把它放在我的问题上。当我取消注释 WM_INPUT 的 if 语句时,它不会出现。我用更多信息编辑我的问题......我检查了你在答案中突出显示的链接,因为我已经在我的研究中通过了这些链接。再次感谢您的宝贵时间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多