原始输入 - 在 window/program 处于后台时接收 WM_INPUT
Raw Input - recive WM_INPUT while window/program is in background
我正在尝试从发送到前台的鼠标监视和打印 RAWINPUT window,或者只是从鼠标发送的所有 RAWINPUT
。
全局钩子 LowLevelMouseProc
对我不起作用,因为它 returns MOUSEHOOKSTRUCT
没有给我 dx 和 dy。
Raw Input API提到当当前window在后台时收到WM_INPUT
,wParam会被设置为RIM_INPUTSINK
。 但我不知道程序在后台时如何接收WM_INPUT
。
这里有一些代码解释了我正在尝试做的事情。
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.
根据 RAWINPUTDEVICE
文档,您需要在注册设备时指定 RIDEV_INPUTSINK
标志:
dwFlags
Type: DWORD
Mode flag that specifies how to interpret the information provided by usUsagePage
and usUsage
. 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
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.
因此,您必须指定一个 HWND
来接收 WM_INPUT
消息,并有一个消息循环来为 window.
提供服务
试试这个:
#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);
}
我正在尝试从发送到前台的鼠标监视和打印 RAWINPUT window,或者只是从鼠标发送的所有 RAWINPUT
。
全局钩子 LowLevelMouseProc
对我不起作用,因为它 returns MOUSEHOOKSTRUCT
没有给我 dx 和 dy。
Raw Input API提到当当前window在后台时收到WM_INPUT
,wParam会被设置为RIM_INPUTSINK
。 但我不知道程序在后台时如何接收WM_INPUT
。
这里有一些代码解释了我正在尝试做的事情。
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.
根据 RAWINPUTDEVICE
文档,您需要在注册设备时指定 RIDEV_INPUTSINK
标志:
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.
因此,您必须指定一个 HWND
来接收 WM_INPUT
消息,并有一个消息循环来为 window.
试试这个:
#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);
}