在 Windows 提供很底层的方法接收硬件设备的裸数据,通过接收裸数据可以做到性能更高的全局键盘,还能支持多个鼠标。但是用这个方法需要自己解析裸数据,同时会因为接受到很多消息降低性能。
1、设计需求
由于鼠标键盘设计时候需要进行多次测试才能知道设备功能。而针对于这类高频率使用的设备,都需要进行成千上万的测试,所以就设计一款能够解决自动化测试鼠标键盘使用功能,并生成log文件记录自动化测试的结果,如下是软件界面图。
百度网盘分享的文件:1.rawinput_自动测试工具
链接:https://pan.baidu.com/s/1EIlPrt5c6l-ivQGavsl0dg
提取码:cu73
2、rawinput相关API
除了键盘和鼠标以外,还有很多其他的用户输入设备,比如手柄、触摸屏、麦克风等等,这些设备统称为人机接口设备HID(Human Interface Device),RawInput 提供API用于接受任何HID设备的原生输入,包括键盘和鼠标。
2.1、RawInput输入模型有以下几个优点
- 应用程序不必检测或打开输入设备。
- 应用程序直接从设备获取数据,并根据其需求处理数据。
- 应用程序可以区分输入源,即使是同一类型的设备。例如,两个鼠标设备。
- 应用程序可以通过从设备集合里的指定数据或者指定的设别类型来管理数据流
- 向前兼容,HID设备可以保持可用,无需更新新的消息类型或者更新系统后在
WM_APPCOMMAND里更新操作指令
2.2、注册Raw Input设备
一般情况下没有程序能够直接获取rawinput数据,在获取数据之前必须注册设备。
注册设备之前,应用程序首先要创建一个RAWINPUTDEVICE的结构体数组来指定顶层集合(TCL)里需要的设备。顶层集合(TCL)包括一个Usage Page(设备类别)和一个 Usage ID(设备类别中对应的设备类型)。例如,获取键盘的顶层集合,需要设置设备类别UsagePage = 0x01 即通用桌面控制器,设置设备类型为UsageID = 0x06即键盘类型。然后应用调用RegisterRawInputDevices去注册设备。
想要获取一个设备的注册状态,调用 GetRegisteredRawInputDevices 。
在 MainWindows 注册事件:
1 | public MainWindow() |
通过RawInputDevice.GetDevices 可以知道当前可以注册的设备有哪些,使用 RawInputDevice.RegisterDevice 可以注册事件,这里注册的是键盘事件,自己修改 HidUsageAndPage 的值可以注册不同的事件。
注册事件就可以在 Hook 函数接收到 WM_INPUT 消息,通过这个消息解析就可以拿到裸数据,对裸数据处理就可以收到输入,如果需要接入 WPF 可以使用WPF 模拟触摸设备将收到的消息模拟触摸。
1 | private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled) |
用 RawInput 就是通过 RegisterRawInputDevices告诉系统当前进程需要支持裸数据,系统将会根据传入的参数将裸数据转发给应用。应用在消息解析数据拿到裸数据,然后按照业务解析裸数据。这个方法可以解决一些特殊设备支持,因为 HID 设备是独占设备,只能让系统独占,如果想要应用也接收硬件发过来的消息,就需要额外通道给应用。另外应用如果需要解决其他应用钩了消息,可以注册裸数据解决其他应用勾了键盘消息。
2.3、读取Raw Input输入数据
应用程序可以从任何顶层集合内匹配的已注册设备获取输入数据。当应用程序收到raw input数据的时候,他的消息队列获取到一个WM_INPUT消息并且队列状态标志设为QS_RAWINPUT(QS_INPUT包含在这个标志里)应用程序在前台和后台的时候都能接受到输入数据。
3、程序示例
使用RAWINPUT,获取键盘原始输入,拦截键盘消息,键盘钩子:
1 |
|
运行效果图:
