Reputation: 43
After working on this and QAbstractNativeEventFilter class I finally got native events from HID (both mouse and keyboard).
I've read many similar questions but none solved my problem. I try to get mouse movement based on dpi. I work on Qt 5.5 cause my whole project built there.
I can't separate mouse movement events from other HID events (mouse and keyboard) even with RIM_TYPEMOUSE flag.
Here is some code from my implementation:
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;
}
Also here is my constructor
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
}
Output shows me zeros (0) all time.
Whats going on with hWnd. I tried to give this:
HWND hWnd =::GetConsoleWindow();
but I had the same result.
In main.cpp I install native Filter
MainWindow w;
a.installNativeEventFilter(&w.mm);
I try for days and I could not find the solution. Is there anyone...(???)
Upvotes: 1
Views: 2550
Reputation: 43
@nnatarr your help was substantial! Thank you!!!
I finally find the solution.
I had to call RegisterRawInputDevices
in main.cpp and change lot of things.
Here is 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();
}
And here is a part from 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;
}
Upvotes: 2
Reputation: 526
As the GetRawInputData MSDN page states, first parameter of this function is
hRawInput [in]
Type: HRAWINPUT
A handle to the RAWINPUT structure. This comes from the lParam in WM_INPUT.
So, you need to check first if message you are processing is a WM_INPUT message (msg->message == WM_INPUT
) and only then try to extract raw input data.
Next, the lParam
of WM_INPUT message is
lParam
A handle to the RAWINPUT structure that contains the raw input from the device.
as it says on WM_INPUT MSDN page. You need to use this handle in GetRawInputData function. Right now, you are using incorrect data handle so GetRawInputData do not return any valid information to you (it just doesn't know where to take data to process).
You should read article MSDN: Using Raw Input. There you can find sample code for the keybaord and mouse raw input processing.
Useful links:
One more thing. You can use equality operator to compare QByteArray instance to a string, in your case it will be like this: if (eventType == "windows_generic_MSG") {...}
. This is because QByteArray has the overloaded equality operator:
bool QByteArray::operator==(const QString & str) const
You can read about it at this page: QByteArray::operator==.
UPDATE
MSDN: RAWINPUTDEVICE page notes that
RIDEV_INPUTSINK 0x00000100
If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified.
You have the INVALID_HANDLE_ERROR error because you need to specify hWnd of your window.
What is MainWindow
class? Do you inherit from QMainWindow or QWidget? Every widget in Qt have the winId
property (WId QWidget::winId() const) which is the very hWnd you are looking for. So you need to take winId()
of your window, cast it to HWND
and write into the Rid
structure like this:
Rid[0].hwndTarget = (HWND)w->winId();
If it won't help, then you need to provide a Minimal, Complete, and Verifiable example for further investigation.
Upvotes: 1