I am trying to monitor and printout the RAWINPUT from a mouse sent to the foreground window, or just all RAWINPUT
from the mouse in general.
the global hook LowLevelMouseProc
does not work for me because it returns a MOUSEHOOKSTRUCT
that does not give me the dx and dy.
The Raw Input API mentions that for WM_INPUT
received when the current window is in the back ground, wParam will be set to RIM_INPUTSINK
. But I have no idea how to receive WM_INPUT
while the program is in the background.
here is some code explaining what I am trying to do.
int main()
{
//regiter the monitoring device
static bool raw_input_initialized = false;
if (raw_input_initialized == false)
{
RAWINPUTDEVICE rid;
rid.usUsagePage = 0x01; //Mouse
rid.usUsage = 0x02;
rid.dwFlags = 0;
rid.hwndTarget = NULL;
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)) == FALSE)
{
exit(-1);
}
raw_input_initialized = true;
}
HWND targetWindow = { 0 };
while (true)
{
targetWindow = GetForegroundWindow(); // get the window runing in the formost window;
std::cout << targetWindow << '\n';
}
return 0;
}
// enterd every time there is a rawinput to ForegroundWindow, or alternatively just a rawinput in general
LRESULT CALLBACK targetWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// print out the values that I need
case WM_INPUT:
UINT dataSize;
GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, NULL, &dataSize, sizeof(RAWINPUTHEADER)); //Need to populate data size first
std::cout << GET_RAWINPUT_CODE_WPARAM(wParam) << " code thing\n";
if (dataSize > 0)
{
std::unique_ptr<BYTE[]> rawdata = std::make_unique<BYTE[]>(dataSize);
if (GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, rawdata.get(), &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
{
RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(rawdata.get());
if (raw->header.dwType == RIM_TYPEMOUSE)
{
std::cout << raw->data.mouse.lLastX << std::endl;
}
}
}
break;
}
}
But I have no idea how to receive WM_INPUT while the program is in the background.
You need to specify the RIDEV_INPUTSINK
flag when registering the device, per the RAWINPUTDEVICE
documentation:
dwFlags
Type:DWORD
Mode flag that specifies how to interpret the information provided by
usUsagePage
andusUsage
. It can be zero (the default) or one of the following values. By default, the operating system sends raw input from devices with the specified top level collection (TLC) to the registered application as long as it has the window focus....
RIDEV_INPUTSINK
0x00000100If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that
hwndTarget
must be specified.
As such, you must specify an HWND
to receive the WM_INPUT
messages, and have a message loop to service that window.
Try this:
#include <iostream>
#include <vector>
#include <Windows.h>
LRESULT CALLBACK targetWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int main()
{
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASS wc = {};
wc.lpfnWndProc = targetWindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = TEXT("MyRawInputWnd");
if (!RegisterClass(&wc))
return -1;
HWND targetWindow = CreateWindowEx(0, wc.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
if (!targetWindow)
return -1;
//register the monitoring device
RAWINPUTDEVICE rid = {};
rid.usUsagePage = 0x01; //Mouse
rid.usUsage = 0x02;
rid.dwFlags = RIDEV_INPUTSINK;
rid.hwndTarget = targetWindow;
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
return -1;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DestroyWindow(targetWindow);
return 0;
}
LRESULT CALLBACK targetWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// print out the values that I need
case WM_INPUT: {
UINT dataSize;
GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, NULL, &dataSize, sizeof(RAWINPUTHEADER)); //Need to populate data size first
std::cout << GET_RAWINPUT_CODE_WPARAM(wParam) << " code thing\n";
if (dataSize > 0)
{
std::vector<BYTE> rawdata(dataSize);
if (GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, rawdata.data(), &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
{
RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(rawdata.data());
if (raw->header.dwType == RIM_TYPEMOUSE)
{
std::cout << raw->data.mouse.lLastX << std::endl;
}
}
}
return 0;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}