/// <summary> /// Print information about this device to our debug output. /// </summary> public void DebugWrite() { if (!IsValid) { Debug.WriteLine("==== Invalid HidEvent"); return; } Device.DebugWrite(); if (IsGeneric) { Debug.WriteLine("==== Generic"); } if (IsKeyboard) { Debug.WriteLine("==== Keyboard"); } if (IsMouse) { Debug.WriteLine("==== Mouse"); } Debug.WriteLine("==== Foreground: " + IsForeground); Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4")); Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4")); foreach (var usage in Usages) { Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4")); } }
public HIDDeviceDescriptorBuilder AddElement(UsagePage usagePage, int usage, int sizeInBits) { if (m_Elements == null) { m_Elements = new List<HIDElementDescriptor>(); } else { // Make sure the usage and usagePage combination is unique. foreach (var element in m_Elements) { // Skip elements that aren't in the same report. if (element.reportId != m_CurrentReportId || element.reportType != m_CurrentReportType) continue; if (element.usagePage == usagePage && element.usage == usage) throw new InvalidOperationException(string.Format( "Cannot add two elements with the same usage page '{0}' and usage '0x{1:X} the to same device", usagePage, usage)); } } m_Elements.Add(new HIDElementDescriptor { usage = usage, usagePage = usagePage, reportOffsetInBits = m_CurrentReportOffsetInBits, reportSizeInBits = sizeInBits, reportType = m_CurrentReportType, reportId = m_CurrentReportId }); m_CurrentReportOffsetInBits += sizeInBits; return this; }
/// <summary> /// Create a human readable string out of this object. /// </summary> /// <returns></returns> public override string ToString() { if (!IsValid) { return("HID: Invalid HidEvent"); } // string res = "==== HidEvent ====\n"; res += Device.ToString(); if (IsGeneric) { res += "Generic\n"; } if (IsKeyboard) { res += "Keyboard\n"; } if (IsMouse) { res += "Mouse\n"; } res += "Foreground: " + IsForeground + "\n"; res += "UsagePage: 0x" + UsagePage.ToString("X4") + "\n"; res += "UsageCollection: 0x" + UsageCollection.ToString("X4") + "\n"; foreach (var usage in Usages) { res += "Usage: 0x" + usage.ToString("X4") + "\n"; } res += "==================\n"; return(res); }
public ListViewItem ToListViewItem() { //TODO: What to do with multiple usage var usage = ""; var usagePage = (UsagePage)UsagePage; switch (usagePage) { case Hid.UsagePage.Consumer: usage = ((ConsumerControl)Usages[0]).ToString(); break; case Hid.UsagePage.WindowsMediaCenterRemoteControl: usage = ((WindowsMediaCenterRemoteControl)Usages[0]).ToString(); break; } var item = new ListViewItem(new[] { usage, UsagePage.ToString("X2"), UsageCollection.ToString("X2"), RepeatCount.ToString(), Time.ToString("HH:mm:ss:fff") }); return(item); }
/// <summary> /// Provide the type for the usage corresponding to the given usage page. /// </summary> /// <param name="aUsagePage"></param> /// <returns></returns> public static Type UsageType(UsagePage aUsagePage) { switch (aUsagePage) { case UsagePage.GenericDesktopControls: return(typeof(Usage.GenericDesktop)); case UsagePage.Consumer: return(typeof(Usage.ConsumerControl)); case UsagePage.WindowsMediaCenterRemoteControl: return(typeof(Usage.WindowsMediaCenterRemoteControl)); case UsagePage.Telephony: return(typeof(Usage.TelephonyDevice)); case UsagePage.SimulationControls: return(typeof(Usage.SimulationControl)); case UsagePage.GameControls: return(typeof(Usage.GameControl)); case UsagePage.GenericDeviceControls: return(typeof(Usage.GenericDevice)); default: return(null); } }
public static bool UsageToString(UsagePage usagePage, int usage, out string usagePageString, out string usageString) { const string kVendorDefined = "Vendor-Defined"; if (( int )usagePage >= 0xFF00) { usagePageString = kVendorDefined; usageString = kVendorDefined; return(true); } usagePageString = usagePage.ToString(); usageString = null; switch (usagePage) { case UsagePage.GenericDesktop: usageString = ((GenericDesktop)usage).ToString(); break; case UsagePage.Simulation: usageString = ((Simulation)usage).ToString(); break; default: return(false); } return(true); }
/// <summary> /// Registers the devices that supply the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">The flags.</param> /// <param name="target">The target.</param> /// <param name="options">The options.</param> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, RegisterDeviceOptions options = RegisterDeviceOptions.Default) { var rawInputDevices = new RawInputDevice[1]; rawInputDevices[0].UsagePage = (short)usagePage; rawInputDevices[0].Usage = (short)usageId; rawInputDevices[0].Flags = (int)flags; rawInputDevices[0].Target = target; // Register this device RawInputFunctions.RegisterRawInputDevices(rawInputDevices, 1, Utilities.SizeOf <RawInputDevice>()); if (options != RegisterDeviceOptions.NoFiltering && rawInputMessageFilter == null) { rawInputMessageFilter = new RawInputMessageFilter(); if (options == RegisterDeviceOptions.Default) { Application.AddMessageFilter(rawInputMessageFilter); } else { MessageFilterHook.AddMessageFilter(target, rawInputMessageFilter); } } }
// This allocates, however it should be used only when launching app public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target) { Device.RegisterDevice(usagePage, usageId, flags, target, false); if (m_filter == null) { m_filterWindow = target; m_filter = new RawInputMessageFilter(); MessageFilterHook.AddMessageFilter(m_filterWindow, m_filter); } }
public DisposableRawInputHook(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, EventHandler <KeyboardInputEventArgs> handler) { this.usagePage = usagePage; this.usageId = usageId; this.handler = handler; Device.RegisterDevice(usagePage, usageId, flags, target); Device.KeyboardInput += handler; }
public static bool RegisterDevice(UsagePage usagePage, UsageId usageId, ModeFlags flags, IntPtr target) { var device = new RawInputDevice { UsagePage = (ushort)usagePage, Usage = (ushort)usageId, Flags = (uint)flags, Target = target }; return(RegisterDevice(device)); }
public DisposableRawInputHook(UsagePage usagePage, UsageId usageIdKeyboard, UsageId usageIdMouse, DeviceFlags flags, IntPtr target, EventHandler <KeyboardInputEventArgs> keyHandler, EventHandler <MouseInputEventArgs> mouseHandler) { this.usagePage = usagePage; this.usageIdKeyboard = usageIdKeyboard; this.usageIdMouse = usageIdMouse; this.keyHandler = keyHandler; this.mouseHandler = mouseHandler; Device.RegisterDevice(usagePage, usageIdKeyboard, flags, target); Device.KeyboardInput += keyHandler; Device.RegisterDevice(usagePage, usageIdMouse, flags, target); Device.MouseInput += mouseHandler; }
/// <summary> /// Registers a device that supplies the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">A combination of flags specifying how to interpret the values of <paramref name="usageId"/> and <paramref name="usagePage"/>.</param> /// <param name="windowHandle"> /// A handle to the target window. Specify <see cref="IntPtr.Zero"/> to not associate the device with a window. Instead the /// input data will follow the input focus. This is useful when specifying the flag <see cref="DeviceFlags.InputSink"/> or /// <see cref="DeviceFlags.ExclusiveInputSink"/>. The default value is <see cref="IntPtr.Zero"/>. /// </param> /// <remarks> /// To receive <c>WM_INPUT</c> messages (through the events <see cref="MouseInput"/>, <see cref="KeyboardInput"/>, and /// <see cref="Input"/>), an application must first register the raw input devices using <see cref="RegisterRawInputDevice"/>. /// By default, an application does not receive raw input. /// <para/> /// To receive <c>WM_INPUT_DEVICE_CHANGE</c> messages (through the <see cref="DeviceChanged"/> event), an application must /// specify <see cref="DeviceFlags.DeviceNotify"/> for each device class that is specified by the <see cref="UsagePage"/> /// and <see cref="UsageId"/> of the <see cref="RawInputDevice" /> structure. By default, an application does not receive /// <c>WM_INPUT_DEVICE_CHANGE</c> notifications for raw input device arrival and removal. /// <para/> /// To unregister a device, specify <see cref="DeviceFlags.Remove"/>. This tells the operating system to stop reading /// from a device that matches the top level collection (specified through <paramref name="usagePage"/> and /// <paramref name="usageId"/>). Alternatively, use the <see cref="UnregisterDevice"/> method. /// <para/> /// If the <see cref="DeviceFlags.Remove"/> flag is set and <paramref name="windowHandle"/> is not set to /// <see cref="IntPtr.Zero"/>, then parameter validation will fail. /// </remarks> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr windowHandle = default) { RawInputDevice rawInputDevice; rawInputDevice.UsagePage = usagePage; rawInputDevice.UsageId = usageId; rawInputDevice.Flags = flags; rawInputDevice.Target = windowHandle; if (!RegisterRawInputDevice(rawInputDevice)) { CheckLastResult(); } UpdateRegisteredDeviceList(); }
private static Type UsageCollectionType(UsagePage aUsagePage) { switch (aUsagePage) { case UsagePage.GenericDesktopControls: return(typeof(GenericDesktop)); case UsagePage.Consumer: return(typeof(Consumer)); case UsagePage.WindowsMediaCenterRemoteControl: return(typeof(WindowsMediaCenter)); default: return(null); } }
/// <summary> /// Provide the type for the usage collection corresponding to the given usage page. /// </summary> /// <param name="usagePage"></param> /// <returns></returns> public static Type UsageCollectionType(UsagePage usagePage) { switch (usagePage) { case UsagePage.GenericDesktopControls: return(typeof(UsageCollection.GenericDesktop)); case UsagePage.Consumer: return(typeof(UsageCollection.Consumer)); case UsagePage.WindowsMediaCenterRemoteControl: return(typeof(UsageCollection.WindowsMediaCenter)); case UsagePage.Digitiser: return(typeof(UsageCollection.Digitizer)); default: return(null); } }
/// <summary> /// Provide the type for the usage collection corresponding to the given usage page. /// </summary> /// <param name="aUsagePage"></param> /// <returns></returns> public static Type UsageCollectionType(UsagePage aUsagePage) { switch (aUsagePage) { case UsagePage.GenericDesktopControls: return(typeof(UsageCollection.GenericDesktop)); case UsagePage.Consumer: return(typeof(UsageCollection.Consumer)); case UsagePage.WindowsMediaCenterRemoteControl: return(typeof(UsageCollection.WindowsMediaCenter)); case UsagePage.VirtualRealityControls: return(typeof(UsageCollection.VirtualReality)); default: return(null); } }
/// <summary> /// /// </summary> private void SetFriendlyName() { //Work out proper suffix for our device root node. //That allows users to see in a glance what kind of device this is. string suffix = ""; Type usageCollectionType = null; if (Info.dwType == RawInputDeviceType.RIM_TYPEHID) { //Process usage page if (Enum.IsDefined(typeof(UsagePage), Info.hid.usUsagePage)) { //We know this usage page, add its name UsagePage usagePage = (UsagePage)Info.hid.usUsagePage; suffix += " ( " + usagePage.ToString() + ", "; usageCollectionType = Utils.UsageCollectionType(usagePage); } else { //We don't know this usage page, add its value suffix += " ( 0x" + Info.hid.usUsagePage.ToString("X4") + ", "; } //Process usage collection //We don't know this usage page, add its value if (usageCollectionType == null || !Enum.IsDefined(usageCollectionType, Info.hid.usUsage)) { //Show Hexa suffix += "0x" + Info.hid.usUsage.ToString("X4") + " )"; } else { //We know this usage page, add its name suffix += Enum.GetName(usageCollectionType, Info.hid.usUsage) + " )"; } } else if (Info.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD) { suffix = " - Keyboard"; } else if (Info.dwType == RawInputDeviceType.RIM_TYPEMOUSE) { suffix = " - Mouse"; } if (Product != null && Product.Length > 1) { //This device as a proper name, use it FriendlyName = Product + suffix; } else { //Extract friendly name from name char[] delimiterChars = { '#', '&' }; string[] words = Name.Split(delimiterChars); if (words.Length >= 2) { //Use our name sub-string to describe this device FriendlyName = words[1] + " - 0x" + ProductId.ToString("X4") + suffix; } else { //No proper name just use the device ID instead FriendlyName = "0x" + ProductId.ToString("X4") + suffix; } } }
/// <summary> /// Registers the devices that supply the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">The flags.</param> /// <param name="target">The target.</param> /// <param name="options">The options.</param> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, RegisterDeviceOptions options = RegisterDeviceOptions.Default) { var rawInputDevices = new RawInputDevice[1]; rawInputDevices[0].UsagePage = (short)usagePage; rawInputDevices[0].Usage = (short)usageId; rawInputDevices[0].Flags = (int)flags; rawInputDevices[0].Target = target; // Register this device RawInputFunctions.RegisterRawInputDevices(rawInputDevices, 1, Utilities.SizeOf<RawInputDevice>()); if (options != RegisterDeviceOptions.NoFiltering && rawInputMessageFilter == null) { rawInputMessageFilter = new RawInputMessageFilter(); if (options == RegisterDeviceOptions.Default) { Application.AddMessageFilter(rawInputMessageFilter); } else { MessageFilterHook.AddMessageFilter(target, rawInputMessageFilter); } } }
/// <summary> /// Registers the devices that supply the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">The flags.</param> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags) { RegisterDevice(usagePage, usageId, flags, IntPtr.Zero); }
/// <summary> /// Initializes a new instance of the <see cref="DeviceButtonGroup"/> class. /// </summary> /// <param name="caps">The HID button caps.</param> private DeviceButtonGroup(ref ButtonCaps caps) { this.usagePage = caps.UsagePage; this.linkCollection = caps.LinkCollection; this.first = caps.Range.UsageMin; this.Count = 1 + caps.Range.UsageMax - caps.Range.UsageMin; this.Pressed = new BitArray(this.Count); }
/// <summary> /// Initializes a new instance of the <see cref="DeviceAxis"/> class. /// </summary> /// <param name="caps">The HID value caps.</param> private DeviceAxis(ref ValueCaps caps) { this.usage = caps.Single.Usage; this.usagePage = caps.UsagePage; this.linkCollection = caps.LinkCollection; this.minimumValue = caps.LogicalMin; this.maximumValue = caps.LogicalMax; switch (this.usagePage) { case UsagePage.Generic: switch (this.usage) { case Usage.X: this.Name = "X axis"; this.Type = AxisType.X; break; case Usage.Y: this.Name = "Y axis"; this.Type = AxisType.Y; break; case Usage.Z: this.Name = "Z axis"; this.Type = AxisType.Z; break; case Usage.Rx: this.Name = "RX axis"; this.Type = AxisType.Rx; break; case Usage.Ry: this.Name = "RY axis"; this.Type = AxisType.Ry; break; case Usage.Rz: this.Name = "RZ axis"; this.Type = AxisType.Rz; break; case Usage.Dial: this.Name = "Dial"; this.Type = AxisType.Dial; break; case Usage.Wheel: this.Name = "Wheel"; this.Type = AxisType.Wheel; break; case Usage.Slider: this.Name = "Slider"; this.Type = AxisType.Slider; break; } break; case UsagePage.Simulation: switch (this.usage) { case Usage.Rudder: this.Name = "Rudder"; this.Type = AxisType.Rudder; break; case Usage.Throttle: this.Name = "Throttle"; this.Type = AxisType.Throttle; break; } break; } }
/// <summary> /// Create a list view item describing this HidEvent /// </summary> /// <returns></returns> public ListViewItem ToListViewItem() { string usageText = ""; string inputReport = null; foreach (ushort usage in Usages) { if (usageText != "") { //Add a separator usageText += ", "; } //Try to get a name for that usage string name = ""; if (Enum.IsDefined(typeof(Hid.UsagePage), UsagePage)) { UsagePage usagePage = (UsagePage)UsagePage; try { name = Enum.GetName(Utils.UsageType(usagePage), usage); } catch { } } if (name == null || name.Equals("") || Device.IsGamePad) //Gamepad buttons do not belong to Usage enumeration, they are just ordinal { name = usage.ToString("X2"); } usageText += name; } // Get input report for generic HID events if (IsGeneric) { inputReport = InputReportString(); } //If we are a gamepad display axis and dpad values if (Device != null && Device.IsGamePad) { //uint dpadUsageValue = GetUsageValue((ushort)Hid.UsagePage.GenericDesktopControls, (ushort)Hid.Usage.GenericDesktop.HatSwitch); //usageText = dpadUsageValue.ToString("X") + " (dpad), " + usageText; if (usageText != "") { //Add a separator usageText += " (Buttons)"; } if (usageText != "") { //Add a separator usageText += ", "; } usageText += GetDirectionPadState().ToString(); //For each axis foreach (KeyValuePair <HIDP_VALUE_CAPS, uint> entry in UsageValues) { if (entry.Key.IsRange) { continue; } //Get our usage type Type usageType = Utils.UsageType((UsagePage)entry.Key.UsagePage); if (usageType == null) { //Unknown usage type //TODO: check why this is happening on Logitech rumble gamepad 2. //Probably some of our axis are hiding in there. continue; } //Get the name of our axis string name = Enum.GetName(usageType, entry.Key.NotRange.Usage); if (usageText != "") { //Add a separator usageText += ", "; } usageText += entry.Value.ToString("X") + " (" + name + ")"; } } //Handle keyboard events else if (IsKeyboard) { //Get the virtual key System.Windows.Forms.Keys vKey = (Keys)RawInput.keyboard.VKey; usageText = vKey.ToString() + " -"; //Get the key flag if (IsButtonUp) { usageText += " UP"; } else if (IsButtonDown) { usageText += " DOWN"; } if (RawInput.keyboard.Flags.HasFlag(RawInputKeyFlags.RI_KEY_E0)) { usageText += " E0"; } if (RawInput.keyboard.Flags.HasFlag(RawInputKeyFlags.RI_KEY_E1)) { usageText += " E1"; } if (HasModifierShift) { usageText += " SHIFT"; } if (HasModifierControl) { usageText += " CTRL"; } if (HasModifierAlt) { usageText += " ALT"; } if (HasModifierWindows) { usageText += " WIN"; } //Put our scan code into our input report field inputReport = "0x" + RawInput.keyboard.MakeCode.ToString("X4"); } //Now create our list item ListViewItem item = new ListViewItem(new[] { usageText, inputReport, UsagePageNameAndValue(), UsageCollectionNameAndValue(), RepeatCount.ToString(), Time.ToString("HH:mm:ss:fff"), IsBackground.ToString() }); return(item); }
/// <summary> /// /// </summary> /// <returns></returns> public string ToLog(uint aDepth = 0) { string res = ""; if (!IsValid) { res += "WARNING: Invalid HID Event"; } //Compute our prefix and indent const string KPrefix = " "; string prefix = ""; for (uint i = 0; i < aDepth; i++) { prefix += KPrefix; } string indent = prefix + KPrefix; // //Open our HID Event block res += "[HID Event]" + "\r\n"; // Log our debug string too to give a quick overview res += indent + "String: " + ToString() + "\r\n"; //For each properties of our HID Event foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this)) { string propertyName = property.Name; object value = property.GetValue(this); if (value != null) { //Check if our property value object type has a method of the same name has this one. Type type = value.GetType(); MethodInfo method = type.GetMethod(System.Reflection.MethodBase.GetCurrentMethod().Name); if (method != null && method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == aDepth.GetType()) { object[] parameters = new object[] { aDepth + 1 }; res += method.Invoke(value, parameters); } //Make special case for some properties else if (propertyName.Equals("InputReport")) { res += string.Format("{0}{1}: {2}\r\n", indent, propertyName, InputReportString()); } else if (propertyName.Equals("UsagePage")) { res += string.Format("{0}{1}: {2} (0x{3})\r\n", indent, propertyName, UsagePageEnum, UsagePage.ToString("X4")); } else if (propertyName.Equals("UsageCollection")) { res += string.Format("{0}{1}: {2}\r\n", indent, propertyName, UsageCollectionNameAndValue()); } else if (propertyName.Equals("Usages")) { for (int i = 0; i < Usages.Count; i++) { res += string.Format("{0}{1}: {2}\r\n", indent, propertyName, UsageNameAndValue(i)); } } else if (propertyName.Equals("UsageValues")) { //Just give the count res += string.Format("{0}{1}: {2}\r\n", indent, "UsageValues count", UsageValues.Count); } else if (propertyName.Equals("RawInput") || propertyName.Equals("UsagePageEnum")) { //Skip those } else { res += string.Format("{0}{1}: {2}\r\n", indent, propertyName, value); } } else { // Special case for NULL values res += string.Format("{0}{1}: NULL\r\n", indent, propertyName); } } //Close our HID Event block res += "[/HID Event]" + "\r\n"; return(res); }
/// <summary> /// Provides name and value of our usage page as a string. /// </summary> public string UsagePageNameAndValue() { return(string.Format("{0} (0x{1})", UsagePageName(), UsagePage.ToString("X4"))); }
/// <summary> /// Registers the devices that supply the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">The flags.</param> /// <param name="target">The target.</param> /// <param name="addMessageFilter">if set to <c>true</c> register message filter to Application.AddMessageFilter.</param> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, bool addMessageFilter = true) { if (target == IntPtr.Zero) { target = Win32Native.GetFocus(); } var rawInputDevices = new RawInputDevice[1]; rawInputDevices[0].UsagePage = (short) usagePage; rawInputDevices[0].Usage = (short) usageId; rawInputDevices[0].Flags = (int) flags; rawInputDevices[0].Target = target; // Register this device RawInputFunctions.RegisterRawInputDevices(rawInputDevices, 1, Utilities.SizeOf<RawInputDevice>()); if (rawInputMessageFilter == null && addMessageFilter) { rawInputMessageFilter = new RawInputMessageFilter(); MessageFilterHook.AddMessageFilter(target, rawInputMessageFilter); } }
public static extern int MaxUsageListLength(ReportType ReportType, UsagePage UsagePage, void* PreparsedData);
public static extern Result GetUsages(ReportType ReportType, UsagePage UsagePage, ushort LinkCollection, short* UsageList, ref int UsageLength, void* PreparsedData, void* Report, int ReportLength);
public HIDDeviceDescriptorBuilder(UsagePage usagePage, int usage) : this() { this.usagePage = usagePage; this.usage = usage; }
public static extern Result GetUsageValue(ReportType ReportType, UsagePage UsagePage, ushort LinkCollection, Usage Usage, out int UsageValue, void* PreparsedData, void* Report, int ReportLength);
/// <summary> /// Unregisters a device that supplies the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <remarks> /// This function tells the operating system to stop reading from a device that matches the top level collection /// (specified through <paramref name="usagePage"/> and <paramref name="usageId"/>). /// </remarks> public static void UnregisterDevice(UsagePage usagePage, UsageId usageId) => RegisterDevice(usagePage, usageId, DeviceFlags.Remove);
/// <summary> /// Registers the devices that supply the raw input data. /// </summary> /// <param name="usagePage">The usage page.</param> /// <param name="usageId">The usage id.</param> /// <param name="flags">The flags.</param> /// <param name="target">The target.</param> /// <param name="addMessageFilter">if set to <c>true</c> register message filter to Application.AddMessageFilter.</param> public static void RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, bool addMessageFilter = true) { var rawInputDevices = new RawInputDevice[1]; rawInputDevices[0].UsagePage = (short) usagePage; rawInputDevices[0].Usage = (short) usageId; rawInputDevices[0].Flags = (int) flags; rawInputDevices[0].Target = target; // Register this device RawInputFunctions.RegisterRawInputDevices(rawInputDevices, 1, Utilities.SizeOf<RawInputDevice>()); if (rawInputMessageFilter == null && addMessageFilter) { rawInputMessageFilter = new RawInputMessageFilter(); Application.AddMessageFilter(rawInputMessageFilter); } }