/// <summary> /// Processes WM_INPUT messages to retrieve information about any keyboard events that occur /// </summary> /// <param name="message">The WM_INPUT message to process</param> private void ProcessInputCommand(Message message) { uint dwSize = (uint)0; //First call to GetRawInputData sets the value of dwSize, which can then be used to allocate the appropriate amount of memory, storing the pointer in "buffer" GetRawInputData(message.LParam, (uint)RID_INPUT, IntPtr.Zero, ref dwSize, System.Convert.ToUInt32((uint)(Marshal.SizeOf(typeof(RAWINPUTHEADER))))); IntPtr buffer = Marshal.AllocHGlobal((int)dwSize); try { //Check that buffer points to something, and if so, call GetRawInputData again to fill the allocated memory with information about the input if (buffer != IntPtr.Zero && GetRawInputData(message.LParam, (uint)RID_INPUT, buffer, ref dwSize, System.Convert.ToUInt32((uint)(Marshal.SizeOf(new RAWINPUTHEADER())))) == dwSize) { //Store the message information in "raw", then check that the input comes from a keyboard device before processing it to raise an appropriate KeyPressed event RAWINPUT raw = (RAWINPUT)(Marshal.PtrToStructure(buffer, typeof(RAWINPUT))); if (raw.header.dwType == RIM_TYPEKEYBOARD) { //Filter for Key Down events and then retrieve information about the keystroke if (raw.keyboard.Message == WM_KEYDOWN || raw.keyboard.Message == WM_SYSKEYDOWN) { ushort key = raw.keyboard.VKey; //On most keyboards, "extended" keys such as the arrow or page keys return two codes - the key's own code, and an //"extended key" flag, which translates to 255. This flag isn't useful to us, so it can be disregarded if (key > VK_LAST_KEY) { return; } //Retrieve information about the device and the key that was pressed CDeviceInfo dInfo = null; m_mutexDeviceList.WaitOne(); if (m_deviceList.Contains(raw.header.hDevice)) { Keys myKey = System.Windows.Forms.Keys.A; dInfo = (CDeviceInfo)(m_deviceList[raw.header.hDevice]); myKey = (Keys)(Enum.Parse(typeof(Keys), Enum.GetName(typeof(Keys), key))); dInfo.vKey = myKey.ToString(); dInfo.key = key; } else { string errMessage = string.Format("Handle :{0} was not in hashtable. The device may support more than one handle or usage page, and is probably not a standard keyboard.", raw.header.hDevice); throw (new ApplicationException(errMessage)); } m_mutexDeviceList.Release(); //If the key that was pressed is valid and there was no problem retrieving information on the device, raise the KeyPressed event if (dInfo != null) { if (KeyPressedEvent != null) { KeyPressedEvent(this, new CKeyControlEventArgs(dInfo, GetDevice(message.LParam.ToInt32()))); } } else { string errMessage = string.Format("Received Unknown Key: {0}. Possibly an unknown device", key); throw (new ApplicationException(errMessage)); } } } } } finally { Marshal.FreeHGlobal(buffer); } }
public CKeyControlEventArgs(CDeviceInfo dInfo, InputDeviceType device) { m_deviceInfo = dInfo; m_device = device; }
/// <summary> /// Iterates through the list provided by GetRawInputDeviceList, counting keyboard devices and adding them to deviceList /// </summary> /// <returns>The number of keyboard devices found</returns> public int EnumerateDevices() { int NumberOfDevices = 0; uint deviceCount = (uint)0; int dwSize = Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)); //Get the number of raw input devices in the list, then allocate sufficient memory and get the entire list if (GetRawInputDeviceList(IntPtr.Zero, ref deviceCount, (uint)dwSize) == 0) { IntPtr pRawInputDeviceList = Marshal.AllocHGlobal((int)(dwSize * deviceCount)); GetRawInputDeviceList(pRawInputDeviceList, ref deviceCount, (uint)dwSize); m_mutexDeviceList.WaitOne(); m_deviceList.Clear(); //Iterate through the list, discarding undesired items and retrieving further information on keyboard devices for (var i = 0; i <= deviceCount - 1; i++) { CDeviceInfo dInfo = default(CDeviceInfo); string deviceName = ""; uint pcbSize = (uint)0; RAWINPUTDEVICELIST rid = (RAWINPUTDEVICELIST)(Marshal.PtrToStructure(new IntPtr(pRawInputDeviceList.ToInt32() + (dwSize * i)), typeof(RAWINPUTDEVICELIST))); GetRawInputDeviceInfo(rid.hDevice, (uint)RIDI_DEVICENAME, IntPtr.Zero, ref pcbSize); if (pcbSize > 0) { IntPtr pData = Marshal.AllocHGlobal((int)pcbSize); GetRawInputDeviceInfo(rid.hDevice, (uint)RIDI_DEVICENAME, pData, ref pcbSize); deviceName = (string)Marshal.PtrToStringAnsi(pData); //Drop the "root" keyboard and mouse devices used for Terminal Services and the Remote Desktop if (deviceName.ToUpper().Contains("ROOT")) { continue; } //If the device is identified in the list as a keyboard or HID device, create a DeviceInfo object to store information about it if (rid.dwType == RIM_TYPEKEYBOARD | rid.dwType == RIM_TYPEHID) { dInfo = new CDeviceInfo(); dInfo.deviceName = Marshal.PtrToStringAnsi(pData); dInfo.deviceHandle = rid.hDevice; dInfo.deviceType = GetDeviceType(rid.dwType); //Check the Registry to retrieve a more friendly description. string DeviceDesc = ReadReg(deviceName); dInfo.Name = DeviceDesc; //If it isn't already in the list, add it to the deviceList hashtable and increase the NumberOfDevices count if (!m_deviceList.Contains(rid.hDevice)) { NumberOfDevices++; m_deviceList.Add(rid.hDevice, dInfo); } } Marshal.FreeHGlobal(pData); } } m_mutexDeviceList.Release(); Marshal.FreeHGlobal(pRawInputDeviceList); return(NumberOfDevices); } else { throw (new ApplicationException("An error occurred while retrieving the list of devices.")); } }