使用 DirectManipulation 处理输入

本部分概述 直接操作 线程模型、直接操作如何处理窗口消息,以及视区的状态如何随着输入映射到输出动作而更改。

直接操作 使用两个线程来协调异步操作:

UI 线程 - 拥有与输入关联的 HWND 的线程。 此线程拥有 直接操作的初始化。 鼠标和键盘输入处理也在 UI 线程上进行。

委托线程 - 直接操作创建并拥有的线程。 触摸输入处理发生在委托线程上。

输入流

在 UI 线程上执行命中测试的典型配置中, 直接操作 按以下顺序处理窗口消息:

显示消息处理顺序的示意图。

对于静态视区:

  1. 一系列窗口消息到达委托线程。
  2. WM_POINTERDOWNDM_POINTERHITTEST 消息由委托线程发送到独立命中测试 (IHT) 线程。
  3. 如果从 IHT 线程调用 SetContact,则委托线程可能会将消息发送到 UI 线程,具体取决于调用 RegisterHitTestTarget 时的 DIRECTMANIPULATION_HITTEST_TYPE 值。
  4. 如果未从 IHT 线程调用 SetContact ,则消息始终由委托线程发送到 UI 线程。
  5. 客户端可以从 UI 线程调用 SetContact ,让 直接操作 检测操作。
  6. 如果检测到操作, 直接操作 会发送 WM/_POINTERCAPTURECHANGED 消息,通知客户端直接操作正在处理输入。 视区状态设置为 “正在运行 ”,输出转换将更新。
  7. 如果检测到操作以外的交互, 直接操作 会将剩余消息发送到 UI 线程。

对于状态为 RUNNING 或 INERTIA) 的动态 (视区,窗口消息首先到达委托线程,其中 直接操作 针对所有正在运行的视区命中测试。 直接操作自动将触点分配给通过命中测试标识的相应视区。 视区状态为“正在运行”,输出转换将更新。

在某些情况下,应用程序 UI 线程可能太慢,无法响应命中测试。 可以使用命中测试线程 (RegisterHitTestTarget) ,以允许客户端将 WM/_POINTERDOWNDM/_POINTERHITTEST 消息移动到特定线程,以便进行命中测试。

备注

通常, 直接操作 仅将 WM/_POINTERDOWNDM/_POINTERHITTEST 消息发送到 UI 线程,在等待客户端的响应时保留后续消息。 如果客户端调用 SetContact,则 UI 线程在检测到操作时接收的唯一消息是 WM/_POINTERDOWNDM/_POINTERHITTEST,以及 WM/_POINTERCAPTURECHANGED 消息

处理 WM/_POINTERDOWNDM/_POINTERHITTEST 消息时,客户端可能不会调用 SetContact。 在这种情况下, 直接操作 会将所有消息发送到 UI 线程,而无需分析消息以查看是否存在操作。 然后,客户端可以选择调用 SetContact 的任何点,让直接操作开始检测操作,并在检测到 WM /_POINTERCAPTURECHANGED 消息 时发送消息。

Windows 10 及更高版本:可以通过在 WM/_POINTERDOWNDM/_POINTERHITTEST 消息上调用 SetContact 之前调用 DeferContact 来决定要处理哪些操作。 DeferContact 可确保在指定时间段内将所有后续消息发送到 UI 线程。