public bool StartListenInput(HidDevice[] devices) { var rids = devices.Select(x => new RAWINPUTDEVICE { usUsagePage = x.UsagePage, usUsage = x.Usage, dwFlags = RIDEV.INPUTSINK, hwndTarget = _handle }).ToArray(); var structSize = (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICE)); var isRegistered = RawInput.RegisterRawInputDevices(rids, (uint)rids.Length, structSize); var z = WinKernel.GetLastError(); return(isRegistered); }
/// <summary> /// Retrieves the raw input header from the specified device. /// </summary> /// <remarks>See <see cref="GetRawInputData"/> for more information.</remarks> /// <param name="hRawInput">A handle to the <see cref="RAWINPUT"/> structure. This comes from the /// <b>lParam</b> in <see cref="WM.INPUT">WM_INPUT</see>.</param> /// <returns>The raw input header as <see cref="RAWINPUTHEADER"/>.</returns> public static RAWINPUTHEADER GetRawInputDataHeader(HRAWINPUT hRawInput) { uint size = RAWINPUTHEADER.SIZE; RAWINPUTHEADER ret = new RAWINPUTHEADER(); ret.dwSize = size; uint err = GetRawInputDataH(hRawInput, RID.HEADER, ref ret, ref size, RAWINPUTHEADER.SIZE); if (err == uint.MaxValue) { throw new Exception(string.Format("Error getting header of WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return(ret); }
/// <summary> /// Retrieves the raw input data from the specified device. /// </summary> /// <remarks>See <see cref="GetRawInputData"/> for more information.</remarks> /// <typeparam name="T">A <b>struct</b> that will be the type of the returned data.</typeparam> /// <param name="hRawInput">A handle to the <see cref="RAWINPUT"/> structure. This comes from the /// <b>lParam</b> in <see cref="WM.INPUT">WM_INPUT</see>.</param> /// <param name="size">Size of the <see cref="RAWINPUT"/> structure. Can be queried using /// <see cref="GetRawInputDataHeader"/>; the size is stored in <see cref="RAWINPUTHEADER.dwSize"/>.</param> /// <param name="offset">An offset to the start of the data, to be returned, in the resulting data of a /// <see cref="GetRawInputData"/> call, without the <see cref="RAWINPUTHEADER"/>, which is omitted anyway.</param> /// <returns>The raw input header as specified when called.</returns> public unsafe static T GetRawInputData <T>(HRAWINPUT hRawInput, int size, int offset = 0) where T : struct { if (size < (uint)Marshal.SizeOf(typeof(T))) { throw new ArgumentOutOfRangeException("size", "Must be greater than or equal to sizeof(RAWINPUT)."); } IntPtr buffer = Marshal.AllocHGlobal(size); uint dwSize = (uint)size; try { uint err = GetRawInputData(hRawInput, RID.INPUT, buffer, ref dwSize, RAWINPUTHEADER.SIZE); if (err == uint.MaxValue) { throw new Exception(string.Format("Error getting WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return((T)Marshal.PtrToStructure(buffer + (int)RAWINPUTHEADER.SIZE + offset, typeof(T))); } finally { Marshal.FreeHGlobal(buffer); } }
/// <summary> /// Returns a list of raw input device handles and raw input device types. /// </summary> /// <returns>The list of raw input device handles and raw input device types.</returns> public static List <Tuple <HANDLE, RIM_TYPE> > EnumerateDevices() { uint size = (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)); uint deviceCount = 0; uint err = GetRawInputDeviceList(null, ref deviceCount, size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error enumerating raw input devices. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } if (deviceCount == 0) { return(new List <Tuple <LRESULT, RIM_TYPE> >()); } RAWINPUTDEVICELIST[] tmp = new RAWINPUTDEVICELIST[deviceCount + 16]; // Just a few more, for the case they just got attached. err = GetRawInputDeviceList(tmp, ref deviceCount, size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error enumerating raw input devices. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } List <Tuple <LRESULT, RIM_TYPE> > ret = new List <Tuple <LRESULT, RIM_TYPE> >(); for (int i = 0; i < deviceCount; i++) { ret.Add(new Tuple <LRESULT, RIM_TYPE>(tmp[i].hDevice, tmp[i].dwType)); } return(ret); }
/// <summary> /// Retrieves the preparsed data of a raw input device. /// </summary> /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see> /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param> /// <returns>The preparsed data of raw input device.</returns> public static byte[] GetRawInputDevicePreparsedData(HANDLE hDevice) { uint size = 0; uint err = GetRawInputDeviceInfo(hDevice, RIDI.PREPARSEDDATA, IntPtr.Zero, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining preparsed data of device (length). (Error code: 0x{0:X8})", WinKernel.GetLastError())); } byte[] ret = new byte[size]; err = GetRawInputDeviceInfo(hDevice, RIDI.PREPARSEDDATA, ret, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining preparsed data of device. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return(ret); }
/// <summary> /// Retrieves information about the raw input device. /// </summary> /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see> /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param> /// <returns>The information about the raw input device.</returns> public static RID_DEVICE_INFO GetRawInputDeviceInfo(HANDLE hDevice) { uint size = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO)); RID_DEVICE_INFO ret = new RID_DEVICE_INFO(); ret.cbSize = size; uint err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICEINFO, ref ret, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining device information. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return(ret); }
/// <summary> /// Retrieves the device name of a raw input device. /// </summary> /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see> /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param> /// <returns>The device name of the raw input device.</returns> public static string GetRawInputDeviceName(HANDLE hDevice) { uint size = 0; uint err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICENAME, IntPtr.Zero, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining device name (length). (Error code: 0x{0:X8})", WinKernel.GetLastError())); } size = Math.Max(err, size) + 1; StringBuilder tmp = new StringBuilder((int)size); err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICENAME, tmp, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining device name. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return(tmp.ToString()); }
/// <summary> /// Processes a <see cref="WM.INPUT">WM_INPUT</see> messages and raises the proper events. /// </summary> /// <param name="lParam">The handle to the raw input dataset.</param> /// <param name="size">The size, in bytes, of the raw input dataset.</param> public void ProcessInput(IntPtr lParam, uint size) { IntPtr buffer = Marshal.AllocHGlobal((int)size); uint dwSize = size; try { uint err = RawInput.GetRawInputData(lParam, RID.INPUT, buffer, ref dwSize, RAWINPUTHEADER.SIZE); if (err == uint.MaxValue) { throw new Exception(string.Format("Error getting WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } RAWINPUTHEADER inputHeader = (RAWINPUTHEADER)Marshal.PtrToStructure(buffer, typeof(RAWINPUTHEADER)); SpaceMouseEventHeader eventHeader = (SpaceMouseEventHeader)Marshal.PtrToStructure(buffer + (int)RAWINPUTHEADER.SIZE, typeof(SpaceMouseEventHeader)); int eventHeaderSize = SpaceMouseEventHeader.SIZE + (int)RAWINPUTHEADER.SIZE; switch (eventHeader.eventType) { case SpaceMouseEventType.Translation: if (eventHeader.dwSizeHid == 7) // check report size for safety { EventHandler <SpaceMouseTranslationEventArgs> tEvt = Translation; if (tEvt != null) // no need to handle if nobody is listing { for (int i = 0; i < eventHeader.dwCount; i++) { SpaceMouseTranslationEventData translation = (SpaceMouseTranslationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseTranslationEventData)); tEvt(this, new SpaceMouseTranslationEventArgs(inputHeader.hDevice, translation.X, translation.Y, translation.Z)); } } } else if (eventHeader.dwSizeHid == 13) // "High Speed" firmware version includes both T and R vector in the same report { EventHandler <SpaceMouseTranslationEventArgs> tEvt = Translation; EventHandler <SpaceMouseRotationEventArgs> rEvt = Rotation; if (tEvt != null || rEvt != null) // no need to handle if nobody is listing { for (int i = 0; i < eventHeader.dwCount; i++) { SpaceMouseTranslationRotationEventData transRot = (SpaceMouseTranslationRotationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseTranslationRotationEventData)); if (tEvt != null) { tEvt(this, new SpaceMouseTranslationEventArgs(inputHeader.hDevice, transRot.X, transRot.Y, transRot.Z)); } if (rEvt != null) { rEvt(this, new SpaceMouseRotationEventArgs(inputHeader.hDevice, transRot.RX, transRot.RY, transRot.RZ)); } } } } break; case SpaceMouseEventType.Rotation: if (eventHeader.dwSizeHid == 7) // check report size for safety { EventHandler <SpaceMouseRotationEventArgs> rEvt = Rotation; if (rEvt != null) // no need to handle if nobody is listing { for (int i = 0; i < eventHeader.dwCount; i++) { SpaceMouseRotationEventData rotation = (SpaceMouseRotationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseRotationEventData)); rEvt(this, new SpaceMouseRotationEventArgs(inputHeader.hDevice, rotation.RX, rotation.RY, rotation.RZ)); } } } break; case SpaceMouseEventType.Buttons: if (eventHeader.dwSizeHid >= 5) // check report size for safety { EventHandler <SpaceMouseButtonsEventArgs> bEvt = Buttons; if (bEvt != null) // no need to handle if nobody is listing { if (!DeviceToProduct.ContainsKey(inputHeader.hDevice)) { var di = RawInput.GetRawInputDeviceInfo(inputHeader.hDevice); DeviceToProduct.Add(inputHeader.hDevice, di.hid.dwProductId); } uint product = DeviceToProduct[inputHeader.hDevice]; for (int i = 0; i < eventHeader.dwCount; i++) { SpaceMouseButtonsEventData tmpButtons = (SpaceMouseButtonsEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseButtonsEventData)); SpaceMouseButtons buttons = SpaceMouseButtons.NONE; switch (product) { case ProductID.SpacePilot: buttons = FromSpacePilot(tmpButtons.ButtonState); break; case ProductID.SpaceExplorer: buttons = FromSpaceExplorer(tmpButtons.ButtonState); break; case ProductID.SpaceNavigator: case ProductID.SpaceNavigatorforNotebooks: case ProductID.SpaceMouse: case ProductID.SpaceMouseWireless: buttons = FromSpaceMouse(tmpButtons.ButtonState); break; case ProductID.SpacePilotPro: buttons = FromSpacePilotPro(tmpButtons.ButtonState); break; case ProductID.SpaceMousePro: case ProductID.SpaceMouseProWireless: buttons = FromSpaceMousePro(tmpButtons.ButtonState); break; case ProductID.SpaceMouseTouch: buttons = FromSpaceMouseTouch(tmpButtons.ButtonState); break; } bEvt(this, new SpaceMouseButtonsEventArgs(inputHeader.hDevice, buttons)); } } } break; } } finally { Marshal.FreeHGlobal(buffer); } }