WPF 记录鼠标、触摸多设备混合输入场景问题

本文记录在WPF应用中鼠标、触摸混合输入,鼠标事件抬起时不会有MouseUp事件触发的问题。

事件输入我们都知道有3类:鼠标、触摸、触笔,鼠标是windows系统出来就有的事件,后面加了触笔、触摸。

1.鼠标输入,只会触发Mouse冒泡隧道事件;

2.触笔输入,会触发除了Stylus事件外,还会触发Mouse事件;

3.触摸输入,触发Touch事件、Stylus事件、Mouse事件。

如何区分三类事件可以参考 WPF 屏幕点击的设备类型 - 唐宋元明清2188 - 博客园,封装所有事件类型(包括Button阻止冒泡事件场景)整合成一个Device事件可以参考 WPF 设备输入事件封装 - 唐宋元明清2188 - 博客园

和小伙伴在定位PPT批注翻页问题时,发现在以WIN32跨进程设置父子窗口后再调动PPT上下翻页,批注触摸操作只会触发Mouse事件,但此Mouse事件只有Down没有Up,这类触摸只转鼠标的场景后面我单独描述下。当我尝试使用鼠标+触摸混合操作时,也能复现Mouse没有Up抬起事件。

鼠标+触摸,复现步骤:

1.鼠标按下

2.在其它位置触摸按下

3.鼠标抬起

4.触摸抬起

我们看看WPF真实反馈的事件输出,UI监听下面几个冒泡事件:

复制代码
1     <Grid Background="LightGray"
2           MouseDown="UIElement_OnMouseDown" MouseUp="UIElement_OnMouseUp"
3           StylusDown="UIElement_OnStylusDown" StylusUp="UIElement_OnStylusUp"
4           TouchDown="UIElement_OnTouchDown" TouchUp="UIElement_OnTouchUp">
5     </Grid>

记录下输出事件,下面区分了鼠标、触摸、触笔:

复制代码
 1     private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
 2     {
 3         if (e.StylusDevice != null) return;
 4         Debug.WriteLine("UIElement_OnMouseDown");
 5     }
 6     private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e)
 7     {
 8         if (e.StylusDevice != null) return;
 9         Debug.WriteLine("UIElement_OnMouseUp");
10     }
11 
12     private void UIElement_OnStylusDown(object sender, StylusDownEventArgs e)
13     {
14         if (e.StylusDevice.TabletDevice.Type != TabletDeviceType.Stylus)
15         {
16             return;
17         }
18         Debug.WriteLine("UIElement_OnStylusDown");
19     }
20     private void UIElement_OnStylusUp(object sender, StylusEventArgs e)
21     {
22         if (e.StylusDevice.TabletDevice.Type != TabletDeviceType.Stylus)
23         {
24             return;
25         }
26         Debug.WriteLine("UIElement_OnStylusUp");
27     }
28 
29     private void UIElement_OnTouchDown(object? sender, TouchEventArgs e)
30     {
31         Debug.WriteLine("UIElement_OnTouchDown");
32     }
33     private void UIElement_OnTouchUp(object? sender, TouchEventArgs e)
34     {
35         Debug.WriteLine("UIElement_OnTouchUp");
36     }

输出结果如下,鼠标+触摸混合操作时MouseUp事件被吞了

我们用Snoop抓事件列表,Grid层鼠标按下后就没有后续了:

有意思的是,鼠标重新按下抬起时,是有正常的MouseDown、MouseUp事件触发,所以只是之前那一次MouseUp未触发:

然后找了台Surface,使用鼠标+触笔按上面路径验证,也是有同样问题:

但是我发现使用触摸板+触笔,MouseUp事件正常触发了。。。

所以这WPF框架问题,还区分鼠标、触摸板?我们看TouchPad设备的原理:标识输入设备 - Windows apps | Microsoft Learn触控板交互 - Windows apps | Microsoft Learn,触摸板可以实现鼠标+多点触摸的功能,但单指操作时并不是鼠标或者触摸,如果要区分的话就需要通过其它其它途径。比如这篇文章有说相比正常的鼠标操作,触摸板返回鼠标消息时GetMessageExtraInfo()函数返回值是0: 如何区分触摸板和鼠标设备生成的WM_MOUSE***消息?-腾讯云开发者社区-腾讯云

这个问题目前没有解决方案,但同一控件多设备混合输入场景比较少见,白板、批注等应用可能使用到,可以在触摸事件输入后判断上一次操作是否为鼠标事件,然后手动触发相应鼠标抬起事件的业务逻辑。

相关推荐
c#上位机3 小时前
wpf之RelativeSource用法总结
c#·wpf
玖笙&3 天前
✨WPF编程基础【2.1】布局原则
c++·wpf·visual studio
玖笙&3 天前
✨WPF编程基础【2.2】:布局面板实战
c++·wpf·visual studio
SEO-狼术3 天前
.NET WPF 数据编辑器集合提供列表框控件
.net·wpf
FuckPatience7 天前
WPF 具有跨线程功能的UI元素
wpf
诗仙&李白7 天前
HEFrame.WpfUI :一个现代化的 开源 WPF UI库
ui·开源·wpf
He BianGu7 天前
【笔记】在WPF中Binding里的详细功能介绍
笔记·wpf
He BianGu7 天前
【笔记】在WPF中 BulletDecorator 的功能、使用方式并对比 HeaderedContentControl 与常见 Panel 布局的区别
笔记·wpf
123梦野8 天前
WPF——效果和可视化对象
wpf
He BianGu8 天前
【笔记】在WPF中Decorator是什么以及何时优先考虑 Decorator 派生类
笔记·wpf