c++winapisendinput

Win32 SendInput mousemove lag and freeze


I am trying to move the mouse (on Windows 10) using SendInput when I perform a physical mouse click. It works fine if I click once or twice, but if clicking for examples 6 times in quick succession the mouse lags for a few seconds then the program stops responding. Is there any obvious reason why this is happening?

(Edited)

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

LRESULT CALLBACK MouseHook(int, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
{
    HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseHook, NULL, 0);
    MessageBox(NULL, L"Hello", L"Hello", MB_OK);
    UnhookWindowsHookEx(hook);

    return 0;
}

LRESULT CALLBACK MouseHook(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        switch (wParam) {
        case WM_RBUTTONUP:
            INPUT buffer;
            ZeroMemory(&buffer, sizeof(buffer));
            buffer.type = INPUT_MOUSE;
            buffer.mi.dx = 0;
            buffer.mi.dy = 10;
            buffer.mi.mouseData = 0;
            buffer.mi.dwFlags = MOUSEEVENTF_MOVE;
            buffer.mi.time = 0;
            buffer.mi.dwExtraInfo = 0;
            SendInput(1, &buffer, sizeof(INPUT));
        }
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

Solution

  • Using Raw Input sample:

    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    BOOL registerTouchpadForInput(HWND hWnd)
    {
        RAWINPUTDEVICE rid;
        rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
        rid.usUsagePage = 1;                            
        rid.usUsage = 2;
        rid.hwndTarget = hWnd;
        return RegisterRawInputDevices(&rid, 1, sizeof(rid));
    }
    void getinputdata(LPARAM lparam)
    {
        HRAWINPUT hInput = (HRAWINPUT)lparam;
        RAWINPUT input = { 0 };
    
        UINT size = sizeof(RAWINPUT);
        GetRawInputData(hInput, RID_INPUT,&input, &size,sizeof(RAWINPUTHEADER));
        if (RIM_TYPEMOUSE == input.header.dwType)
        {
            if (input.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
            {
                INPUT buffer;
                ZeroMemory(&buffer, sizeof(buffer));
                buffer.type = INPUT_MOUSE;
                buffer.mi.dx = 0;
                buffer.mi.dy = 10;
                buffer.mi.mouseData = 0;
                buffer.mi.dwFlags = MOUSEEVENTF_MOVE;
                buffer.mi.time = 0;
                buffer.mi.dwExtraInfo = 0;
                SendInput(1, &buffer, sizeof(INPUT));
            }
        }
        return;
    }
    
    static LRESULT CALLBACK NVTouch_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        BOOL  registrationStatus = false;
        switch (message)
        {
        case WM_CREATE:
            registrationStatus = registerTouchpadForInput(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_INPUT:
            getinputdata(lParam);
            return DefWindowProc(hwnd, message, wParam, lParam);
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }
    
    int main()
    {
        WNDCLASSEX wndclass = {
            sizeof(WNDCLASSEX),
            CS_DBLCLKS,
            NVTouch_WindowProc,
            0,
            0,
            GetModuleHandle(0),
            LoadIcon(0,IDI_APPLICATION),
            LoadCursor(0,IDC_ARROW),
            HBRUSH(COLOR_WINDOW + 1),
            0,
            L"myclass",
            LoadIcon(0,IDI_APPLICATION)
        };
        bool isClassRegistered = false;
        isClassRegistered = RegisterClassEx(&wndclass);
        if (isClassRegistered)
        {
            HWND window = CreateWindow(wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL);
            if (window)
            {
                ShowWindow(window, SW_SHOWDEFAULT);
                MSG msg;
                while (GetMessage(&msg, 0, 0, 0))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
        }
    }