使用 DirectManipulation 处理输入
本部分概述 直接操作 线程模型、直接操作如何处理窗口消息,以及视区的状态如何随着输入映射到输出动作而更改。
直接操作 使用两个线程来协调异步操作:
UI 线程 - 拥有与输入关联的 HWND 的线程。 此线程拥有 直接操作的初始化。 鼠标和键盘输入处理也在 UI 线程上进行。
委托线程 - 直接操作创建并拥有的线程。 触摸输入处理发生在委托线程上。
输入流
在 UI 线程上执行命中测试的典型配置中, 直接操作 按以下顺序处理窗口消息:
对于静态视区:
- 一系列窗口消息到达委托线程。
- WM_POINTERDOWN 和 DM_POINTERHITTEST 消息由委托线程发送到独立命中测试 (IHT) 线程。
- 如果从 IHT 线程调用 SetContact,则委托线程可能会将消息发送到 UI 线程,具体取决于调用 RegisterHitTestTarget 时的 DIRECTMANIPULATION_HITTEST_TYPE 值。
- 如果未从 IHT 线程调用 SetContact ,则消息始终由委托线程发送到 UI 线程。
- 客户端可以从 UI 线程调用 SetContact ,让 直接操作 检测操作。
- 如果检测到操作, 直接操作 会发送 WM/_POINTERCAPTURECHANGED 消息,通知客户端直接操作正在处理输入。 视区状态设置为 “正在运行 ”,输出转换将更新。
- 如果检测到操作以外的交互, 直接操作 会将剩余消息发送到 UI 线程。
对于状态为 RUNNING 或 INERTIA) 的动态 (视区,窗口消息首先到达委托线程,其中 直接操作 针对所有正在运行的视区命中测试。 直接操作自动将触点分配给通过命中测试标识的相应视区。 视区状态为“正在运行”,输出转换将更新。
在某些情况下,应用程序 UI 线程可能太慢,无法响应命中测试。 可以使用命中测试线程 (RegisterHitTestTarget) ,以允许客户端将 WM/_POINTERDOWN 和 DM/_POINTERHITTEST 消息移动到特定线程,以便进行命中测试。
备注
通常, 直接操作 仅将 WM/_POINTERDOWN 和 DM/_POINTERHITTEST 消息发送到 UI 线程,在等待客户端的响应时保留后续消息。 如果客户端调用 SetContact,则 UI 线程在检测到操作时接收的唯一消息是 WM/_POINTERDOWN 和 DM/_POINTERHITTEST,以及 WM/_POINTERCAPTURECHANGED 消息。
处理 WM/_POINTERDOWN 和 DM/_POINTERHITTEST 消息时,客户端可能不会调用 SetContact。 在这种情况下, 直接操作 会将所有消息发送到 UI 线程,而无需分析消息以查看是否存在操作。 然后,客户端可以选择调用 SetContact 的任何点,让直接操作开始检测操作,并在检测到 WM /_POINTERCAPTURECHANGED 消息 时发送消息。
Windows 10 及更高版本:可以通过在 WM/_POINTERDOWN 或 DM/_POINTERHITTEST 消息上调用 SetContact 之前调用 DeferContact 来决定要处理哪些操作。 DeferContact 可确保在指定时间段内将所有后续消息发送到 UI 线程。