通过


原始输入概述

传统键盘和鼠标旁边有许多用户输入设备。 例如,用户输入可能来自游戏杆、触摸屏、麦克风或其他设备,这些设备提供极大的输入灵活性。 这些设备统称为人机接口设备(HID)。 原始输入 API 提供了一种稳定可靠的方法,使应用程序能够接受来自任何 HID 的原始输入,包括键盘和鼠标。

本部分介绍以下主题:

原始输入模型

以前,键盘和鼠标通常生成输入数据。 系统解释来自这些设备的数据,消除了原始信息中与特定设备相关的详细内容。 例如,键盘会生成特定于设备的扫描代码,但系统为应用程序提供虚拟键代码。 除了隐藏原始输入的详细信息外,窗口管理器不支持所有新的 HID。 若要从不支持的 HID 获取输入,应用程序必须执行许多操作:打开设备、管理共享模式、定期读取设备或设置 I/O 完成端口等。 开发了原始输入模型和关联的 API,以便从所有输入设备(包括键盘和鼠标)轻松访问原始输入。

原始输入模型与键盘和鼠标的原始 Windows 输入模型不同。 在原始输入模型中,应用程序以发送或发布到窗口的消息的形式接收独立于设备的输入,例如 WM_CHARWM_MOUSEMOVEWM_APPCOMMAND。 相比之下,对于原始输入,应用程序必须注册要从中获取数据的设备。 此外,应用程序通过 WM_INPUT 消息获取原始输入。

原始输入模型有几个优点:

  • 应用程序无需检测或打开输入设备。
  • 应用程序直接从设备获取数据,并根据需要处理数据。
  • 应用程序可以区分输入的来源,即使它来自同样类型的设备。 例如,两个鼠标设备。
  • 应用程序通过指定来自设备集合或仅特定设备类型的数据来管理数据流量。
  • HID 设备在市场上可用时即可使用,无需等待新的消息类型或更新操作系统以便在 WM_APPCOMMAND 中增加新命令。

请注意, WM_APPCOMMAND 确实支持某些 HID 设备。 但是, WM_APPCOMMAND 是与设备无关的更高级别的输入事件,而 WM_INPUT 发送特定于设备的原始低级别数据。

原始数据输入注册

默认情况下,没有应用程序接收原始输入。 若要从设备接收原始输入,应用程序必须注册设备。

为了注册设备,应用程序首先创建一个用于指定所需设备的RAWINPUTDEVICE结构数组,这个数组定义了设备的顶级集合 (TLC)。 TLC 由 使用情况页 (设备类)和 使用情况 ID (类中的设备)定义。 例如,若要获取键盘 TLC,请设置 UsagePage = 0x01,UsageID = 0x06。 应用程序调用 RegisterRawInputDevices 来注册设备。

请注意,应用程序可以注册当前未附加到系统的设备。 附加此设备后,Windows 管理器会自动将原始输入发送到应用程序。 若要获取系统上的原始输入设备列表,应用程序调用 GetRawInputDeviceList。 使用此调用中的 hDevice ,应用程序调用 GetRawInputDeviceInfo 来获取设备信息。

通过 RAWINPUTDEVICEdwFlags 成员,应用程序可以选择要侦听的设备,也可以选择要忽略的设备。 例如,应用程序可以从所有电话设备请求输入,但应答计算机除外。 有关示例代码,请参阅 “注册原始输入”。

请注意,鼠标和键盘也是 HID,因此来自它们的数据可以通过 HID 消息 WM_INPUT 和传统消息传递。 应用程序可以通过 在 RAWINPUTDEVICE 中正确选择标志来选择任一方法。

若要获取应用程序的注册状态,请随时调用 GetRegisteredRawInputDevices

读取原始输入

应用程序从任何 HID 接收原始输入,其 顶级集合 (TLC) 与注册中的 TLC 匹配。 当应用程序收到原始输入时,其消息队列将获取 WM_INPUT 消息,并设置队列状态标志 QS_RAWINPUTQS_INPUT 还包括此标志)。 应用程序在前台和后台时(如果已注册 RIDEV_INPUTSINK),应用程序可以接收数据。

有两种方法可以读取原始数据:标准方法和缓冲方法。

标准方法 一次读取一个 RAWINPUT 结构,并且适用于大多数设备。 应用程序调用 GetMessage 以检索WM_INPUT消息,然后使用传入 lParamHRAWINPUT 句柄调用 GetRawInputData。 有关示例,请参阅 执行原始输入的标准读取

缓冲方法 一次读取一个 RAWINPUT 结构的数组,对于像 1000Hz 的鼠标这样的高频率设备非常有用,因为多个事件可能会在消息循环的迭代之间积累。 应用程序调用 GetRawInputBuffer 以清空单个批处理中的所有累积事件。 使用 NEXTRAWINPUTBLOCK 宏遍历生成的数组。

重要

GetMessage 在返回之前从原始输入队列中删除当前 WM_INPUT 。 因此, GetRawInputBuffer 不会看到当前事件 , 仅看到到达事件之后的事件。 组合这两种方法时,正确的模式为:

  1. 使用 lParam 句柄调用 GetRawInputData 以读取当前事件。
  2. 在循环中调用 GetRawInputBuffer 以清空队列中累积的任何其他事件。

有关示例,请参阅 执行原始输入的批量读取

若要解释原始输入,可能需要有关 HID 的详细信息。 应用程序通过使用设备句柄调用 GetRawInputDeviceInfo 来 获取设备信息。 此句柄可以通过 WM_INPUTlParam 中的 GetRawInputDataRID_HEADER 获取,或者通过 RAWINPUTHEADERhDevice 成员获取。

另请参阅