Win32RawInput.cs
author sl
Fri, 05 Dec 2014 23:18:13 +0100
changeset 18 24ac84ab9620
parent 15 2044181ade12
child 22 8b2a3da54187
permissions -rw-r--r--
Consolidating our HID input report parsing.
     1 using System;
     2 using System.Runtime.InteropServices;
     3 
     4 namespace Win32
     5 {
     6 
     7     static partial class Function
     8     {
     9         [DllImport("User32.dll", SetLastError = true)]
    10 		public extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);
    11 
    12         [DllImport("User32.dll", SetLastError = true)]
    13 		public extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
    14 
    15    		[DllImport("User32.dll", SetLastError=true)]
    16 		public extern static int GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
    17     }
    18 
    19 
    20     static partial class Macro
    21     {
    22         /// <summary>
    23         /// Retrieves the input code from wParam in WM_INPUT.
    24         /// See RIM_INPUT and RIM_INPUTSINK.
    25         /// </summary>
    26         /// <param name="wParam"></param>
    27         /// <returns></returns>
    28         public static int GET_RAWINPUT_CODE_WPARAM(IntPtr wParam)
    29         {
    30             return (wParam.ToInt32() & 0xff);
    31         }
    32 
    33         public static int GET_APPCOMMAND_LPARAM(IntPtr lParam)
    34         {
    35             return ((short)HIWORD(lParam.ToInt32()) & ~Const.FAPPCOMMAND_MASK);
    36         }
    37 
    38         public static int GET_DEVICE_LPARAM(IntPtr lParam)
    39         {
    40             return ((ushort)(HIWORD(lParam.ToInt32()) & Const.FAPPCOMMAND_MASK));
    41         }
    42 
    43         public static int HIWORD(int val)
    44         {
    45             return ((val >> 16) & 0xffff);
    46         }
    47 
    48 
    49         //#define HIWORD(l)           ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
    50         //#define LOWORD(l)           ((WORD)(((DWORD_PTR)(l)) & 0xffff))        
    51         //#define LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
    52         //#define HIBYTE(w)           ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))
    53 
    54         //#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
    55         //#define GET_DEVICE_LPARAM(lParam)     ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
    56         //#define GET_MOUSEORKEY_LPARAM         GET_DEVICE_LPARAM
    57         //#define GET_FLAGS_LPARAM(lParam)      (LOWORD(lParam))
    58         //#define GET_KEYSTATE_LPARAM(lParam)   GET_FLAGS_LPARAM(lParam)
    59 
    60     }
    61 
    62 
    63 
    64     static partial class Const
    65     {
    66         /// <summary>
    67         /// Windows Messages
    68         /// </summary>
    69         public const int WM_KEYDOWN = 0x0100;
    70         public const int WM_APPCOMMAND = 0x0319;
    71         public const int WM_INPUT = 0x00FF;
    72 
    73         /// <summary>
    74         /// GetRawInputDeviceInfo pData points to a string that contains the device name.
    75         /// </summary>
    76         public const uint RIDI_DEVICENAME = 0x20000007;
    77         /// <summary>
    78         /// GetRawInputDeviceInfo For this uiCommand only, the value in pcbSize is the character count (not the byte count).
    79         /// </summary>
    80         public const uint RIDI_DEVICEINFO = 0x2000000b;
    81         /// <summary>
    82         /// GetRawInputDeviceInfo pData points to an RID_DEVICE_INFO structure.
    83         /// </summary>
    84         public const uint RIDI_PREPARSEDDATA = 0x20000005;
    85 
    86 
    87         /// <summary>
    88         /// Data comes from a mouse.
    89         /// </summary>
    90         public const uint RIM_TYPEMOUSE = 0;
    91         /// <summary>
    92         /// Data comes from a keyboard.
    93         /// </summary>
    94         public const uint RIM_TYPEKEYBOARD = 1;
    95         /// <summary>
    96         /// Data comes from an HID that is not a keyboard or a mouse.
    97         /// </summary>
    98         public const uint RIM_TYPEHID = 2;
    99 
   100         public const int RID_INPUT = 0x10000003;
   101         public const int RID_HEADER = 0x10000005;
   102 
   103         /// <summary>
   104         /// Possible value taken by wParam for WM_INPUT.
   105         /// <para />
   106         /// Input occurred while the application was in the foreground. The application must call DefWindowProc so the system can perform cleanup.
   107         /// </summary>
   108         public const int RIM_INPUT = 0;
   109         /// <summary>
   110         /// Possible value taken by wParam for WM_INPUT.
   111         /// <para />
   112         /// Input occurred while the application was not in the foreground. The application must call DefWindowProc so the system can perform the cleanup.
   113         /// </summary>
   114         public const int RIM_INPUTSINK = 1;
   115 
   116         /// <summary>
   117         /// If set, the application command keys are handled. RIDEV_APPKEYS can be specified only if RIDEV_NOLEGACY is specified for a keyboard device.
   118         /// </summary>        
   119         public const uint RIDEV_APPKEYS = 0x00000400;
   120 
   121         /// <summary>
   122         /// If set, the mouse button click does not activate the other window.
   123         /// </summary>
   124 	    public const uint RIDEV_CAPTUREMOUSE = 0x00000200;
   125         
   126         /// <summary>
   127         /// If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal.
   128         /// Windows XP:  This flag is not supported until Windows Vista
   129         /// </summary>
   130 	    public const uint RIDEV_DEVNOTIFY = 0x00002000;
   131 
   132         /// <summary>
   133         /// If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with RIDEV_PAGEONLY.
   134         /// </summary>
   135         public const uint RIDEV_EXCLUDE = 0x00000010;
   136 
   137         /// <summary>
   138         /// If set, this enables the caller to receive input in the background only if the foreground application does not process it. In other words, if the foreground application is not registered for raw input, then the background application that is registered will receive the input.
   139         /// Windows XP:  This flag is not supported until Windows Vista
   140         /// </summary>
   141 	    public const uint RIDEV_EXINPUTSINK = 0x00001000;
   142 
   143         /// <summary>
   144         /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified.
   145         /// </summary>
   146 	    public const uint RIDEV_INPUTSINK = 0x00000100;
   147 
   148 	    /// <summary>
   149 	    /// If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. RIDEV_NOHOTKEYS can be specified even if RIDEV_NOLEGACY is not specified and hwndTarget is NULL.
   150 	    /// </summary>
   151         public const uint RIDEV_NOHOTKEYS = 0x00000200;
   152 
   153         /// <summary>
   154         /// If set, this prevents any devices specified by usUsagePage or usUsage from generating legacy messages. This is only for the mouse and keyboard. See Remarks.
   155         /// </summary>
   156         public const uint RIDEV_NOLEGACY = 0x00000030;
   157         
   158         /// <summary>
   159         /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that usUsage must be zero. To exclude a particular top level collection, use RIDEV_EXCLUDE.
   160         /// </summary>
   161         public const uint RIDEV_PAGEONLY = 0x00000020;
   162 
   163 	    /// <summary>
   164         /// If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection.
   165 	    /// </summary>
   166         public const uint RIDEV_REMOVE = 0x00000001;
   167 
   168         public const int APPCOMMAND_BROWSER_BACKWARD = 1;
   169         public const int APPCOMMAND_VOLUME_MUTE = 8;
   170         public const int APPCOMMAND_VOLUME_DOWN = 9;
   171         public const int APPCOMMAND_VOLUME_UP = 10;
   172         public const int APPCOMMAND_MEDIA_NEXTTRACK = 11;
   173         public const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12;
   174         public const int APPCOMMAND_MEDIA_STOP = 13;
   175         public const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14;
   176         public const int APPCOMMAND_MEDIA_PLAY = 46;
   177         public const int APPCOMMAND_MEDIA_PAUSE = 47;
   178         public const int APPCOMMAND_MEDIA_RECORD = 48;
   179         public const int APPCOMMAND_MEDIA_FAST_FORWARD = 49;
   180         public const int APPCOMMAND_MEDIA_REWIND = 50;
   181         public const int APPCOMMAND_MEDIA_CHANNEL_UP = 51;
   182         public const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
   183 
   184         public const int FAPPCOMMAND_MASK = 0xF000;
   185         public const int FAPPCOMMAND_MOUSE = 0x8000;
   186         public const int FAPPCOMMAND_KEY = 0;
   187         public const int FAPPCOMMAND_OEM = 0x1000;
   188 
   189     }
   190 
   191 
   192     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   193     internal struct RAWINPUTDEVICE
   194     {
   195         [MarshalAs(UnmanagedType.U2)]
   196         public ushort usUsagePage;
   197         [MarshalAs(UnmanagedType.U2)]
   198         public ushort usUsage;
   199         [MarshalAs(UnmanagedType.U4)]
   200         public uint dwFlags;
   201         public IntPtr hwndTarget;
   202     }
   203 
   204 
   205     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   206     internal struct RAWINPUTHEADER
   207     {
   208         [MarshalAs(UnmanagedType.U4)]
   209         public int dwType;
   210         [MarshalAs(UnmanagedType.U4)]
   211         public int dwSize;
   212         public IntPtr hDevice;
   213         [MarshalAs(UnmanagedType.U4)]
   214         public int wParam;
   215     }
   216 
   217 
   218     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   219     internal struct RAWHID
   220     {
   221         [MarshalAs(UnmanagedType.U4)]
   222         public uint dwSizeHid;
   223         [MarshalAs(UnmanagedType.U4)]
   224         public uint dwCount;
   225         //
   226         //BYTE  bRawData[1];
   227     }
   228 
   229 
   230     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   231     internal struct BUTTONSSTR
   232     {
   233         [MarshalAs(UnmanagedType.U2)]
   234         public ushort usButtonFlags;
   235         [MarshalAs(UnmanagedType.U2)]
   236         public ushort usButtonData;
   237     }
   238 
   239 
   240     [StructLayout(LayoutKind.Explicit, Pack = 1)]
   241     internal struct RAWMOUSE
   242     {
   243         [MarshalAs(UnmanagedType.U2)]
   244         [FieldOffset(0)]
   245         public ushort usFlags;
   246         [MarshalAs(UnmanagedType.U4)]
   247         [FieldOffset(4)]
   248         public uint ulButtons;
   249         [FieldOffset(4)]
   250         public BUTTONSSTR buttonsStr;
   251         [MarshalAs(UnmanagedType.U4)]
   252         [FieldOffset(8)]
   253         public uint ulRawButtons;
   254         [MarshalAs(UnmanagedType.U4)]
   255         [FieldOffset(12)]
   256         public int lLastX;
   257         [MarshalAs(UnmanagedType.U4)]
   258         [FieldOffset(16)]
   259         public int lLastY;
   260         [MarshalAs(UnmanagedType.U4)]
   261         [FieldOffset(20)]
   262         public uint ulExtraInformation;
   263     }
   264 
   265     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   266     internal struct RAWKEYBOARD
   267     {
   268         [MarshalAs(UnmanagedType.U2)]
   269         public ushort MakeCode;
   270         [MarshalAs(UnmanagedType.U2)]
   271         public ushort Flags;
   272         [MarshalAs(UnmanagedType.U2)]
   273         public ushort Reserved;
   274         [MarshalAs(UnmanagedType.U2)]
   275         public ushort VKey;
   276         [MarshalAs(UnmanagedType.U4)]
   277         public uint Message;
   278         [MarshalAs(UnmanagedType.U4)]
   279         public uint ExtraInformation;
   280     }
   281 
   282 
   283     [StructLayout(LayoutKind.Explicit, Pack = 1)]
   284     internal struct RAWINPUT
   285     {
   286         [FieldOffset(0)]
   287         public RAWINPUTHEADER header;
   288         [FieldOffset(16)]
   289         public RAWMOUSE mouse;
   290         [FieldOffset(16)]
   291         public RAWKEYBOARD keyboard;
   292         [FieldOffset(16)]
   293         public RAWHID hid;
   294     }
   295 
   296 
   297     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   298     internal struct RID_DEVICE_INFO_MOUSE
   299     {
   300         public uint dwId;
   301         public uint dwNumberOfButtons;
   302         public uint dwSampleRate;
   303         public bool fHasHorizontalWheel;
   304     }
   305 
   306 
   307     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   308     internal struct RID_DEVICE_INFO_KEYBOARD
   309     {
   310         public uint dwType;
   311         public uint dwSubType;
   312         public uint dwKeyboardMode;
   313         public uint dwNumberOfFunctionKeys;
   314         public uint dwNumberOfIndicators;
   315         public uint dwNumberOfKeysTotal;
   316     }
   317 
   318     [StructLayout(LayoutKind.Sequential, Pack = 1)]
   319     internal struct RID_DEVICE_INFO_HID
   320     {
   321         public uint dwVendorId;
   322         public uint dwProductId;
   323         public uint dwVersionNumber;
   324         public ushort usUsagePage;
   325         public ushort usUsage;
   326     }
   327 
   328     [StructLayout(LayoutKind.Explicit, Pack = 1)]
   329     internal struct RID_DEVICE_INFO
   330     {
   331         [FieldOffset(0)]
   332         public uint cbSize;
   333         [FieldOffset(4)]
   334         public uint dwType;
   335         [FieldOffset(8)]
   336         public RID_DEVICE_INFO_MOUSE mouse;
   337         [FieldOffset(8)]
   338         public RID_DEVICE_INFO_KEYBOARD keyboard;
   339         [FieldOffset(8)]
   340         public RID_DEVICE_INFO_HID hid;
   341     }
   342 
   343 
   344 }