0

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;
    }
}

2
  • Message-Only Windows. Commented Jul 26, 2021 at 20:46
  • 1
    "the global hook LowLevelMouseProc does not work for me because it returns a MOUSEHOOKSTRUCT" - no, it does not. Read the documentation. It gives you a (pointer to a) MSLLHOOKSTRUCT instead. Two different types. Commented Jul 26, 2021 at 22:01

1 Answer 1

3

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 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.

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);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.