我听说在 Win10 到 Win11 的系统版本左右,微软加上了一大波触摸性能优化,准确来说是 HID 性能优化。我想测试一下在这些系统下,采用从 Windows 消息接收到 WM_TOUCH 触摸消息的延迟将会是多少。本文将告诉大家我编写的测试应用
为了能够让 WPF 窗口能接收到 WM_TOUCH 触摸消息,首先需要将 WPF 默认走的实时触摸机制禁用,否则两个触摸接收方法将会打架,在 Windows 层将不会调度 WM_TOUCH 触摸消息给到 WPF 窗口。根据 WPF 禁用实时触摸 提供的方法禁用实时触摸,如果没有禁用 WPF 的 RealTimeStylus 实时触摸,就无法拿到 WM_TOUCH 消息,这是因为两套触摸机制将会打架。在 Windows 系统层发现开启了实时触摸之后,将不会调度 WM_TOUCH 消息给到应用窗口
在 App 构造函数加上以下代码用来禁用 RealTimeStylus 实时触摸
为了更加方便调用 Win32 函数,按照 dotnet 使用 CsWin32 库简化 Win32 函数调用逻辑 博客的方法,安装 Microsoft.Windows.CsWin32 库用来减少编写 PInvoke 的定义方法
这里采用 .NET 7 的 WPF 项目,可以编辑 csproj 用来安装 Microsoft.Windows.CsWin32 库,十分方便,修改 csproj 项目文件为以下代码
根据 dotnet 使用 CsWin32 库简化 Win32 函数调用逻辑 博客提到的方法,需要在项目新建一个名为 NativeMethods.txt 的文件,在此文件里面写入需要使用的 Win32 函数。此时 CsWin32 库将使用 SourceGenerator 技术生成这些写入的 Win32 函数的定义
下面是在 NativeMethods.txt 写入的代码
进入到 MainWindow 函数里面监听 SourceInitialized 事件。在 WPF 框架里面,约定了在 SourceInitialized 事件里就是创建完成了 Win32 窗口之后触发的,在此事件里面使用 Win32 窗口相关方法是安全的
在 MainWindow_SourceInitialized
方法里面调用 RegisterTouchWindow 用来注册 WM_Touch 消息,代码如下
这里传入了 TWF_WANTPALM
参数,传入这个参数可以减少触摸消息延迟
接着根据 WPF 添加窗口消息钩子方法 博客接收 Windows 消息,代码如下
在 Hook 函数里面,判断收到的消息是否 WM_Touch 消息,如果是那就记录当前的消息时间,用来判断两条 WM_Touch 消息之间的延迟
在自己的电脑上运行代码,即可用来测试 WM_Touch 触摸的延迟
我使用以上代码在我的 Demo 上测试和在我的一个复杂项目上测试,结果就是在 Demo 上的触摸延迟是 WM_Touch 和 RealTimeStylus 实时触摸几乎一样。但是在复杂的项目上,由于 Windows 消息太多或者是主线程忙碌,触摸延迟是 WM_Touch 比 RealTimeStylus 实时触摸大许多
本文的代码放在github 和 gitee 欢迎访问
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码
获取代码之后,进入 WalqujemjelNekokelhuwererere 文件夹
更多触摸请看 WPF 触摸相关
原文链接: http://blog.lindexi.com/post/WPF-%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E6%B5%8B%E8%AF%95-WM_TOUCH-%E8%A7%A6%E6%91%B8%E6%B6%88%E6%81%AF%E5%BB%B6%E8%BF%9F%E7%9A%84%E5%BA%94%E7%94%A8
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。