public static bool GetRawInputData(IntPtr hRawInput, ref RAWINPUTHEADER header, ref RAWMOUSE mouse, ref RAWKEYBOARD keyboard, ref RAWHID hid) { int iSize = 0; GetRawInputData(hRawInput, 0x10000003, IntPtr.Zero, ref iSize, Marshal.SizeOf <RAWINPUTHEADER>()); // RID_INPUT if (iSize == 0) { return(false); } IntPtr mem = Marshal.AllocHGlobal(iSize); if (mem == IntPtr.Zero) { return(false); } if (GetRawInputData(hRawInput, 0x10000003, mem, ref iSize, Marshal.SizeOf <RAWINPUTHEADER>()) != iSize) { Marshal.FreeHGlobal(mem); return(false); } if (Environment.Is64BitProcess) { var str = Marshal.PtrToStructure <RAWINPUT64>(mem); header = str.header; mouse = str.mouse; keyboard = str.keyboard; hid = str.hid; } else { var str = Marshal.PtrToStructure <RAWINPUT32>(mem); header = str.header; mouse = str.mouse; keyboard = str.keyboard; hid = str.hid; } Marshal.FreeHGlobal(mem); return(true); }
// Raw input message private void _ProcessInput(ref IntPtr lResult, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) { lResult = IntPtr.Zero; // Get data packet uint size = 0; if (0 > GetRawInputData(lParam, RID_INPUT, null, ref size, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)))) { throw new Exception("Bad return value from Win32 function"); } if (size <= 0) { return; } var bytes = new byte[size]; if (0 >= GetRawInputData(lParam, RID_INPUT, bytes, ref size, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)))) { throw new Exception("Bad return value from Win32 function"); } // Extract the header and raw data portions var header = ToStruct <RAWINPUTHEADER>(bytes); if (header.dwSize != size) { throw new Exception("Size field mismatch"); } int hdrSize = Marshal.SizeOf(typeof(RAWINPUTHEADER)); var data = new byte[size - hdrSize]; Array.Copy(bytes, hdrSize, data, 0, data.Length); // Parse data bytes object obj = null; if (header.dwType == RIM_TYPEMOUSE) { var raw = ToStruct <RAWMOUSE>(data); obj = new MouseData { flags = raw.usFlags, buttons = raw.ulButtons, rawButtons = raw.ulRawButtons, lastX = raw.lLastX, lastY = raw.lLastY, extraInformation = raw.ulExtraInformation }; } if (header.dwType == RIM_TYPEKEYBOARD) { var raw = ToStruct <RAWKEYBOARD>(data); obj = new KeyboardData { makecode = raw.usMakecode, flags = raw.usFlags, reserved = raw.usReserved, vKey = raw.usVKey, message = raw.dwMessage, extraInformation = raw.ulExtraInformation }; } if (header.dwType == RIM_TYPEHID) { // Hid data contains 2x DWORD header plus variable-length stream of bytes var raw = new RAWHID(); raw.dwSizeHid = BitConverter.ToUInt32(data, 0); raw.dwCount = BitConverter.ToUInt32(data, 4); int len = (int)(raw.dwSizeHid * raw.dwCount); if (len < data.Length - 8) { throw new Exception("RawData array length too small to fit requested elements count"); } raw.bRawData = new byte[len]; Array.Copy(data, 8, raw.bRawData, 0, raw.bRawData.Length); var arrays = new byte[raw.dwCount][]; for (int i = 0; i < arrays.Length; i++) { arrays[i] = new byte[raw.dwSizeHid]; Array.Copy(raw.bRawData, i * raw.dwSizeHid, arrays[i], 0, arrays[i].Length); } obj = new HidData { rawData = arrays }; } // IntPtr.Zero means there is no associated device if (header.hDevice == IntPtr.Zero) { // Trigger universal event & null device's event if (header.dwType >= 0 && header.dwType <= 2) { Device.DeviceType tp = 0; if (header.dwType == RIM_TYPEMOUSE) { tp = Device.DeviceType.Mouse; } if (header.dwType == RIM_TYPEKEYBOARD) { tp = Device.DeviceType.Keyboard; } if (header.dwType == RIM_TYPEHID) { tp = Device.DeviceType.Hid; } var dev = _nullDevices[tp]; InputReceived?.Invoke(this, new RawInputEventArgs(dev, obj)); dev.RaiseInputReceived(obj); } } // Data does have an associated device else { // Lookup device in dictionary if (_devices.ContainsKey(header.hDevice)) { // Trigger universal event & device object's event var dev = _devices[header.hDevice]; InputReceived?.Invoke(this, new RawInputEventArgs(dev, obj)); dev.RaiseInputReceived(obj); } } }