Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Intercept messages from USB auxiliary device
#2
Note: If a button already does some action, the raw input API cannot block that action. You'll get `WM_INPUT` and can then execute code, but cannot block the default action. If there is no default action, then no problem.
 
Code:
Copy      Help
// script "Raw input.cs"
//Registers a raw input device to receive WM_INPUT messages. On message reads data.
//Run this script. To stop, click the End button on the toolbar.
//Raw input docs: https://learn.microsoft.com/en-us/windows/win32/inputdev/raw-input


var w = WndUtil.CreateMessageOnlyWindow("#32770");

var rid = new api.RAWINPUTDEVICE {
    usUsagePage = 1, usUsage = 6, //TODO: set correct values. It depends on device. The 0 6 if for keyboards. Run script "Raw input device info.cs" to get the values. See https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/hid-usages
    dwFlags = api.RIDEV_INPUTSINK,
    hwndTarget = w
};
if (!api.RegisterRawInputDevices(rid, 1, Marshal.SizeOf<api.RAWINPUTDEVICE>())) throw new AuException(lastError.message);

while (api.GetMessage(out var m)) {
    if (m.message == api.WM_INPUT) _WmInput(m.wParam, m.lParam);
    else api.DispatchMessage(m);
}


unsafe void _WmInput(nint wParam, nint lParam) {
    print.it("WM_INPUT", wParam, lParam);
    
    int size = 0;
    if (api.GetRawInputData(lParam, api.RID_INPUT, null, ref size, Marshal.SizeOf<api.RAWINPUTHEADER>()) == -1) return;
    var b = stackalloc byte[size];
    if (api.GetRawInputData(lParam, api.RID_INPUT, b, ref size, Marshal.SizeOf<api.RAWINPUTHEADER>()) != size) return;
    ref api.RAWINPUT raw = ref *(api.RAWINPUT*)b;
    if (raw.header.hDevice == 0) return;
    
    //print.it(raw.header.dwType);
    //print.it(raw.data.hid.dwCount);
    
    //but I don't know how to read the data for non-keyboard/mouse devices. It depends on device. Ask AI.

}

#pragma warning disable 649, 169 //field never assigned/used
unsafe class api : NativeApi {
    [
DllImport("user32.dll", SetLastError = true)]
    internal static extern bool RegisterRawInputDevices(in RAWINPUTDEVICE pRawInputDevices, uint uiNumDevices, int cbSize);
    
    internal struct RAWINPUTDEVICE {
        public ushort usUsagePage;
        public ushort usUsage;
        public uint dwFlags;
        public wnd hwndTarget;
    }

    
    internal const uint RIDEV_INPUTSINK = 0x100;
    
    [
DllImport("user32.dll", EntryPoint = "GetMessageW", SetLastError = true)]
    internal static extern bool GetMessage(out MSG lpMsg, wnd hWnd = default, uint wMsgFilterMin = 0, uint wMsgFilterMax = 0);
    
    [
DllImport("user32.dll", EntryPoint = "DispatchMessageW")]
    internal static extern nint DispatchMessage(in MSG lpMsg);
    
    internal const ushort WM_INPUT = 0xFF;
    
    [
DllImport("user32.dll")]
    internal static extern int GetRawInputData(nint hRawInput, uint uiCommand, void* pData, ref int pcbSize, int cbSizeHeader);
    
    internal const uint RID_INPUT = 0x10000003;
    
    internal struct RAWINPUTHEADER {
        public uint dwType;
        public uint dwSize;
        public nint hDevice;
        public nint wParam;
    }

    
    internal struct RAWINPUT {
        public RAWINPUTHEADER header;
        public _data_e__Union data;
        
        [
StructLayout(LayoutKind.Explicit)]
        public struct _data_e__Union {
            [
FieldOffset(0)] public RAWMOUSE mouse;
            [
FieldOffset(0)] public RAWKEYBOARD keyboard;
            [
FieldOffset(0)] public RAWHID hid;
        }
    }

    
    internal struct RAWHID {
        public uint dwSizeHid;
        public uint dwCount;
        public FlexibleArray<byte> bRawData;
    }

    
    internal struct RAWKEYBOARD {
        public ushort MakeCode;
        public ushort Flags;
        public ushort Reserved;
        public ushort VKey;
        public uint Message;
        public uint ExtraInformation;
    }

    
    internal struct RAWMOUSE {
        public ushort usFlags;
        public _Anonymous_e__Union u_;
        public uint ulRawButtons;
        public int lLastX;
        public int lLastY;
        public uint ulExtraInformation;
        
        [
StructLayout(LayoutKind.Explicit)]
        public struct _Anonymous_e__Union {
            [
FieldOffset(0)] public uint ulButtons;
            [
FieldOffset(0)] public _Anonymous_e__Struct n_;
            
            public struct _Anonymous_e__Struct {
                public ushort usButtonFlags;
                public ushort usButtonData;
            }
        }
    }
}

#pragma warning restore 649, 169 //field never assigned/used
Code:
Copy      Help
// script "Raw input device info.cs"
//Prints some info of raw input devices other than keyboard and mouse.

print.clear();

unsafe {
    int nDev = 0, bSize = 0;
    api.GetRawInputDeviceList(null, ref nDev, sizeof(api.RAWINPUTDEVICELIST));
    var a = new api.RAWINPUTDEVICELIST[nDev];
    nDev = api.GetRawInputDeviceList(a, ref nDev, sizeof(api.RAWINPUTDEVICELIST));
    foreach (var d in a) {
        //print.it(d.dwType, d.hDevice);
        if (d.dwType != api.RIM_TYPEHID) continue;
        
        //get name
        api.GetRawInputDeviceInfo(d.hDevice, api.RIDI_DEVICENAME, null, ref bSize);
        var name = string.Create(bSize - 1, 0, (span, _) => {
            fixed(char* p = span) api.GetRawInputDeviceInfo(d.hDevice, api.RIDI_DEVICENAME, p, ref bSize);
        });

        print.it(name);
        
        //get other info
        var di = new api.RID_DEVICE_INFO { cbSize = sizeof(api.RID_DEVICE_INFO) };
        api.GetRawInputDeviceInfo(d.hDevice, api.RIDI_DEVICEINFO, &di, ref di.cbSize);
        print.it($"Usage page: {di.u_.hid.usUsagePage},  usage: {di.u_.hid.usUsage}");
    }
    
}



#pragma warning disable 649, 169 //field never assigned/used
unsafe class api : NativeApi {
    [
DllImport("user32.dll", SetLastError = true)]
    internal static extern int GetRawInputDeviceList([Out] RAWINPUTDEVICELIST[] pRawInputDeviceList, ref int puiNumDevices, int cbSize);
    
    internal struct RAWINPUTDEVICELIST {
        public nint hDevice;
        public uint dwType;
    }


internal const uint RIM_TYPEHID = 0x2;

[
DllImport("user32.dll", EntryPoint = "GetRawInputDeviceInfoW", SetLastError = true)]
internal static extern int GetRawInputDeviceInfo(nint hDevice, uint uiCommand, void* pData, ref int pcbSize);

internal const uint RIDI_DEVICENAME = 0x20000007;
internal const uint RIDI_DEVICEINFO = 0x2000000B;

internal struct RID_DEVICE_INFO {
    public int cbSize;
    public uint dwType;
    public _Anonymous_e__Union u_;

    [
StructLayout(LayoutKind.Explicit)]
    public struct _Anonymous_e__Union {
        [
FieldOffset(0)] public RID_DEVICE_INFO_MOUSE mouse;
        [
FieldOffset(0)] public RID_DEVICE_INFO_KEYBOARD keyboard;
        [
FieldOffset(0)] public RID_DEVICE_INFO_HID hid;
    }
}


internal struct RID_DEVICE_INFO_HID {
    public uint dwVendorId;
    public uint dwProductId;
    public uint dwVersionNumber;
    public ushort usUsagePage;
    public ushort usUsage;
}


internal struct RID_DEVICE_INFO_KEYBOARD {
    public uint dwType;
    public uint dwSubType;
    public uint dwKeyboardMode;
    public uint dwNumberOfFunctionKeys;
    public uint dwNumberOfIndicators;
    public uint dwNumberOfKeysTotal;
}


internal struct RID_DEVICE_INFO_MOUSE {
    public uint dwId;
    public uint dwNumberOfButtons;
    public uint dwSampleRate;
    public BOOL fHasHorizontalWheel;
}
}

#pragma warning restore 649, 169 //field never assigned/used


Messages In This Thread
RE: Intercept messages from USB auxiliary device - by Gintaras - 02-25-2026, 05:25 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)