使用RegisterRawInputDevices注册触摸屏HID不起作用

我正在尝试使用RAWINPUT API从Surface触摸屏获取原始输入数据。

获取设备列表很有用。 但是当我想用RegisterRawInputDevices注册触摸屏设备时,我遇到了问题:该函数在GetLastError中返回false(87)(ERROR_INVALID_PARAMETER)…我尝试了不同的东西,我在网上阅读但没有工作。

我在C#上使用Interop用于非常简单的桌面控制台应用程序,在Windows 8.1上使用Visual Studio 2013进行开发。 目标是Surface Pro 3。

使用API​​的代码在下面…(对于丑陋的编辑感到遗憾)。

我会非常感谢你的帮助:)

皮埃尔

CASS中API封装的CLASS

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Diagnostics; namespace ConsoleApplication3 { class APIWrapper { #region Properties private static int _vendorID=-1; public static int VendorID { get { return _vendorID; } } private static int _productID=-1; public static int ProductID { get { return _productID; } } #endregion #region API structs internal struct RAWINPUTDEVICELIST_ELMT { public IntPtr hDevice; public uint dwType; } public enum RawInputDeviceType : uint { RIM_TYPEMOUSE = 0, RIM_TYPEKEYBOARD = 1, RIM_TYPEHID = 2, } [StructLayout(LayoutKind.Sequential)] internal struct RAWINPUTDEVICE { public ushort usUsagePage; public ushort usUsage; public int dwFlags; public IntPtr hwndTarget; } public enum RawInputDeviceInfoType : uint { RIDI_DEVICENAME = 0x20000007, RIDI_DEVICEINFO = 0x2000000b, RIDI_PREPARSEDDATA = 0x20000005, } public const ushort RIDEV_INPUTSINK =0x00000100; public const ushort RIDEV_PAGEONLY = 0x00000020; [StructLayout(LayoutKind.Sequential)] internal struct RID_DEVICE_INFO_HID { public int dwVendorId; public int dwProductId; public int dwVersionNumber; public ushort usUsagePage; public ushort usUsage; } [StructLayout(LayoutKind.Sequential)] internal struct RID_DEVICE_INFO_MOUSE { public int dwId; public int dwNumberOfButtons; public int dwSampleRate; public bool fHasHorizontalWheel; } [StructLayout(LayoutKind.Sequential)] internal struct RID_DEVICE_INFO_KEYBOARD { public int dwType; public int dwSubType; public int dwKeyboardMode; public int dwNumberOfFunctionKeys; public int dwNumberOfIndicators; public int dwNumberOfKeysTotal; } [StructLayout(LayoutKind.Explicit)] internal struct RID_DEVICE_INFO { [FieldOffset(0)] public uint cbSize; [FieldOffset(4)] public RawInputDeviceType dwType; [FieldOffset(8)] public RID_DEVICE_INFO_MOUSE mouse; [FieldOffset(8)] public RID_DEVICE_INFO_KEYBOARD keyboard; [FieldOffset(8)] public RID_DEVICE_INFO_HID hid; } [StructLayout(LayoutKind.Sequential)] internal struct RAWINPUTHEADER { public RawInputDeviceType dwType; public int dwSize; public IntPtr hDevice; public uint wParam; } [StructLayout(LayoutKind.Explicit)] internal struct RAWMOUSE { [FieldOffset(0)] public ushort usFlags; [FieldOffset(2)] public uint ulButtons; [FieldOffset(4)] public ushort usButtonFlags; [FieldOffset(2)] public ushort usButtonData; [FieldOffset(6)] public uint ulRawButtons; [FieldOffset(10)] public int lLastX; [FieldOffset(14)] public int lLastY; [FieldOffset(18)] public uint ulExtraInformation; } [StructLayout(LayoutKind.Sequential)] internal struct RAWKEYBOARD { public ushort MakeCode; public ushort Flags; public ushort Reserved; public ushort VKey; public uint Message; public uint ExtraInformation; } [StructLayout(LayoutKind.Sequential)] internal struct RAWHID { public int dwSizeHid; public int dwCount; //use of a pointer here for struct reason public IntPtr pbRawData; } [StructLayout(LayoutKind.Explicit)] internal struct RAWINPUT { [FieldOffset(0)] public RAWINPUTHEADER header; [FieldOffset(16 + 8)] public RAWMOUSE mouse; [FieldOffset(16 + 8)] public RAWKEYBOARD keyboard; [FieldOffset(16 + 8)] public RAWHID hid; } #endregion #region API functions [DllImport("user32.dll", SetLastError = true)] static extern uint GetRawInputDeviceList([In, Out] RAWINPUTDEVICELIST_ELMT[] InputdeviceList, [In, Out] ref uint puiNumDevices, [In] uint cbSize); [DllImport("user32.dll", SetLastError = true)] static extern uint GetRawInputDeviceInfo([In] IntPtr hDevice, [In] RawInputDeviceInfoType uiCommand, [In, Out] IntPtr pData, [In, Out] ref uint pcbSize); [DllImport("user32.dll", SetLastError = true)] static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, uint cbSize); [DllImport("user32.dll")] static extern uint GetRegisteredRawInputDevices([In, Out] RAWINPUTDEVICE[] InputdeviceList, [In, Out] ref uint puiNumDevices, [In] uint cbSize); [DllImport("user32.dll", SetLastError = true)] static extern uint GetRawInputBuffer([In,Out] RAWINPUT[] pData, [In, Out] ref uint pcbSize, [In] uint cbSizeHeader); #endregion #region Methods for devices public static bool GetRawInputDeviceList() { bool res = false; RAWINPUTDEVICELIST_ELMT[] pRawInputDeviceList = null; uint puiNumDevices = 0; uint returnCode = GetRawInputDeviceList(pRawInputDeviceList, ref puiNumDevices, (uint)Marshal.SizeOf(new RAWINPUTDEVICELIST_ELMT())); res = (0xFFFFFFFF != returnCode); if (res) { //alloc array pRawInputDeviceList = new RAWINPUTDEVICELIST_ELMT[puiNumDevices]; //get devices returnCode = GetRawInputDeviceList(pRawInputDeviceList, ref puiNumDevices, (uint)Marshal.SizeOf((typeof(RAWINPUTDEVICELIST_ELMT)))); res = (0xFFFFFFFF != returnCode); if (res) { //look for the touchscreen. bool foundTouchScreen = false; foreach (RAWINPUTDEVICELIST_ELMT rawInputDevice in pRawInputDeviceList) { //IntPtr pData = IntPtr.Zero; //uint strsize = 0; //IntPtr deviceHandle = rawInputDevice.hDevice; //returnCode = GetRawInputDeviceInfo(deviceHandle, RawInputDeviceInfoType.RIDI_DEVICENAME, pData, ref strsize); //pData = Marshal.AllocHGlobal((int)strsize); //returnCode = GetRawInputDeviceInfo(deviceHandle, RawInputDeviceInfoType.RIDI_DEVICENAME, pData, ref strsize); ////Console.WriteLine("Result = " + returnCode + " ErrorCode = " + Marshal.GetLastWin32Error()); //string name = Marshal.PtrToStringAnsi(pData); //Console.WriteLine("Name = " + name); uint structsize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO)); RID_DEVICE_INFO di = new RID_DEVICE_INFO(); di.cbSize = structsize; IntPtr pData = Marshal.AllocHGlobal((int)structsize); returnCode = GetRawInputDeviceInfo(rawInputDevice.hDevice, RawInputDeviceInfoType.RIDI_DEVICEINFO, pData, ref structsize); if (0xFFFFFFF != returnCode && 0 != returnCode) { di = (RID_DEVICE_INFO)Marshal.PtrToStructure(pData, typeof(RID_DEVICE_INFO)); //Console.WriteLine("di.dwType = " + Enum.GetName(typeof(RawInputDeviceType), di.dwType)); switch (di.dwType) { case RawInputDeviceType.RIM_TYPEHID: /* Console.WriteLine("di.hid.dwVendorId = " + di.hid.dwVendorId); Console.WriteLine("di.hid.dwProductId = " + di.hid.dwProductId); Console.WriteLine("di.hid.dwVersionNumber = " + di.hid.dwVersionNumber); Console.WriteLine("di.hid.usUsagePage = " + di.hid.usUsagePage); Console.WriteLine("di.hid.usUsage = " + di.hid.usUsage);*/ if (0x0D == di.hid.usUsagePage && 0x04 == di.hid.usUsage) { _vendorID = di.hid.dwVendorId; _productID = di.hid.dwProductId; foundTouchScreen = true; } break; case RawInputDeviceType.RIM_TYPEKEYBOARD: case RawInputDeviceType.RIM_TYPEMOUSE: default: break; } if (foundTouchScreen) { RAWINPUTDEVICE[] rawInputDevicesToMonitor = new RAWINPUTDEVICE[1]; RAWINPUTDEVICE device = new RAWINPUTDEVICE(); device.dwFlags =RIDEV_INPUTSINK; device.hwndTarget = Process.GetCurrentProcess().MainWindowHandle; device.usUsage = di.hid.usUsage; device.usUsagePage = di.hid.usUsagePage; rawInputDevicesToMonitor[0] = device; if (!RegisterRawInputDevices(rawInputDevicesToMonitor, (uint)1, (uint)Marshal.SizeOf(new RAWINPUTDEVICE()))) { Console.WriteLine("Registration of device --> NOK (error: " + Marshal.GetLastWin32Error()+")"); RAWINPUTDEVICE [] pRegisteredRawInputDeviceList = null; uint puiNumRegDevices = 0; returnCode = GetRegisteredRawInputDevices(pRegisteredRawInputDeviceList, ref puiNumRegDevices, (uint)Marshal.SizeOf(new RAWINPUTDEVICE())); res = (0xFFFFFFFF != returnCode); if (res) { //alloc array pRegisteredRawInputDeviceList = new RAWINPUTDEVICE[puiNumRegDevices]; //get devices returnCode = GetRegisteredRawInputDevices(pRegisteredRawInputDeviceList, ref puiNumRegDevices, (uint)Marshal.SizeOf((typeof(RAWINPUTDEVICE)))); Console.WriteLine("Registered devices nb : " + returnCode); } } break; } } } } /*Need to set RIDEV_INPUTSINK in the dwFlags member and set hwndTarget to be able to make use of this function otherwise * GetRawInputBuffer will ALWAYS say 0 when you try to find out what size you need the buffer to be. */ } /*else int error = Marshal.GetLastWin32Error();*/ return res; } #endregion } } 

主类:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication3 { class Program { static void Main(string[] args) { //look for the touch screen device if (!APIWrapper.GetRawInputDeviceList()) { Console.WriteLine("Error occured when getting RawInputDevice List."); } if (APIWrapper.VendorID == -1 && APIWrapper.ProductID == -1) { Console.WriteLine("No Touchscreen device has been found."); } else { Console.WriteLine("Touchscreen found : VendorID=" + APIWrapper.VendorID + " ProductID=" + APIWrapper.ProductID); //wait for rawinputdata Console.WriteLine("Waiting data loop : started."); uint dataNb = APIWrapper.ReadHIDData(); switch (dataNb) { case 0xFFFFFFFF: Console.WriteLine("An error occured."); break; case 0: Console.WriteLine("No data received."); break; default: Console.WriteLine(dataNb + " rawInputData received"); break; } Console.WriteLine("Waiting data loop : ended."); } Console.ReadLine(); } } }