最近,生产线反馈,在执行生产大屏测试软件的时候,软件大概率出现不能触摸,但是可以用鼠标的的情况。刚好 这个软件又是WPF 做的,所以做了以下排查。

.Net 环境: .NetFrameWork 4.8(经过测试,.Net6的版本也会出现)

建立一个最简单的Demo复现以上的问题,就是在一个主窗口MainWindow的Loaded事件,延时2s启动 Show 出 Window1 的空白窗口,间隔10s中,自动关闭

 /// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
btn.Background = Brushes.Red;
Loaded += MainWindow_Loaded;
StylusDown += MainWindow_StylusDown;
MouseDown += MainWindow_MouseDown;
} private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
App.Log.Info("MainWindow_MouseDown");
} private void MainWindow_StylusDown(object sender, StylusDownEventArgs e)
{
App.Log.Info("MainWindow_StylusDown");
} private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
await Task.Delay(2000); var win = new Window1();
win.Owner = this;
win.Closed += Win_Closed;
win.Show(); await Task.Delay(10000);
win.Close();
} private void Win_Closed(object sender, EventArgs e)
{
grid1.Visibility = Visibility.Visible;
} private void Btn_Click(object sender, RoutedEventArgs e)
{
App.Log.Info($"按钮点击了Btn_Click");
if (btn.Background == Brushes.Green)
{
btn.Background = Brushes.Red;
}
else if (btn.Background == Brushes.Red)
{
btn.Background = Brushes.Green;
}
}
}

  

<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
WindowState="Maximized"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid x:Name="grid1" Visibility="Collapsed">
<Button
x:Name="btn"
Width="200"
Height="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="Btn_Click" />
</Grid>
</Grid>
</Window>

  

<Window
x:Class="WpfApp1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Window1"
Width="800"
Height="450"
Topmost="True"
WindowState="Maximized"
mc:Ignorable="d">
<Grid />
</Window>

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes; namespace WpfApp1
{
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}

添加现场复现的操作手法:

  在Show出Window1的时候,用双手的手掌按住Window1的窗口,直至10s后Window1窗口自动关闭,这时候MainWindow 窗口就不能触摸了。测试了几台规格不一样的大屏,均能复现到,只不过有些能自动恢复触摸的比较快(1分钟),有一台大屏则需要15分钟甚至更长的时间还不能恢复。

选择了一台久久不能恢复的大屏,用了德熙哥团队ManipulationDemo工具(详见:WPF 使用 ManipulationDemo 工具辅助调试设备触摸失效问题)协助排查,在ManipulationDemo加入了以上的弹窗的代码,没有异常数据,比如:插拔、程序Exception的抛出,没有任何触摸的Down、Move、Up的事件触发,但是是可以接受到WM_Pointer的消息的,并且接上鼠标,是有鼠标的Down、Move、Up 的事件触发

以上的代码,再次使用Dnspy运行调试进去,用相同的复现手法复现问题,查看 在 PresentationCore 程序集下的 Sysrem.Windows.Input 程序集下 PenThreadWorker 类里边,断点调试 ThreadProc 的方法体

发现如下问题:

1、_PenContexts 和 _handles 的个数都是2,这样会走进去执行 GetPenEventMultiple 

2、成功执行了UnsafeNativeMethods.GetPenEventMultiple 的方法,返回的 cPackets、cbPacket、pPackets 都是 0

3、调用 FireEvent 的方法,array = null,导致不执行Down、Move、Up的方法了

正常的书写调试

用Dnspy,调试了正常书写流程的,子窗口Windows1 的关闭,是会调用RemovePenContext,释放到已经无效的 PenContext,handle,这样_PenContexts 和 _handles 的个数就是1,就会进入调用UnsafeNativeMethods.GetPenEvent,获取到正常的书写数据包,从而进入FirePenDown、FirePenUp 得到可书写的状态

目前的解决方案:

1、由于在触摸失效的时候,是可以监听到Pointer的消息的, 可以在WPF 窗口开启Pointer的设置,(详见冬哥的 WPF 开启Pointer消息 - 唐宋元明清2188 - 博客园

AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true); 

但是 开启Pointer 会有其他的问题,我测试过用.Net6版本,开启Pointer消息,确实能解决大部分触摸失效的问题,但是由于 Pointer的消息输出的是屏幕的坐标,所以应用内部还需要做适配,还会有其他的坑

详见德熙的 WPF 开启Pointer消息存在的坑 - lindexi - 博客园

2、利用规避的方式,由于触摸窗口的自动关闭,导致触摸的PenContext数据错误的问题,先可以不将Windows1的窗口关闭,调用Window1.Hide() 的方式,隐藏起来,也可以规避当前的问题。

WPF 窗口 触摸失效 的一种场景的更多相关文章

  1. @Transactional注解事务失效的几种场景及原因

    1. 介紹 在业务开发的许多场景中,我们会使用到通过事务去控制多个操作的一致性.比较多的就是通过声明式事务,即使用 @Transactional 注解修饰方法的形式.但在使用过程中,要足够了解事务失效 ...

  2. MySQL索引失效的几种场景

    我们都知道建立索引能够提高查询效率,那么是不是任何情况下都能提高呢,当然不是的的,下面我们就来列举一些常见的索引失效的场景. 借用上一篇文章的dm_person_info表 在card_code列没加 ...

  3. @Transaction注解失效的几种场景

    一.@Transactional介绍 1.@Transactional注解可以作用于哪些地方? @Transactional 可以作用在接口.类.类方法上. 作用于类:表示所有该类的public方法都 ...

  4. 聊聊spring事务失效的12种场景,太坑了

    前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...

  5. spring事务失效的12种场景

    一 事务不生效 1.访问权限问题 java的访问权限主要有四种:private<default<protected<public. 把有某些事务方法,定义了错误的访问权限,就会导致事 ...

  6. spring 事务失效的几种场景

    以下场景是基于mysql数据库,InnoDB的存储引擎. 一.没有添加@Transactional注解 二.方法声明是private或者static 三.没有抛出异常而是try catch了异常 下面 ...

  7. WPF 插拔触摸设备触摸失效

    原文:WPF 插拔触摸设备触摸失效 最近使用 WPF 程序,在不停插拔触摸设备会让 WPF 程序触摸失效.通过分析 WPF 源代码可以找到 WPF 触摸失效的原因. 在 Windows 会将所有的 H ...

  8. 2018-8-15-WPF-插拔触摸设备触摸失效

    title author date CreateTime categories WPF 插拔触摸设备触摸失效 lindexi 2018-08-15 08:12:47 +0800 2018-08-09 ...

  9. 通过解读 WPF 触摸源码,分析 WPF 插拔设备触摸失效的问题(问题篇)

    在 .NET Framework 4.7 以前,WPF 程序的触摸处理是基于操作系统组件但又自成一套的,这其实也为其各种各样的触摸失效问题埋下了伏笔.再加上它出现得比较早,触摸失效问题也变得更加难以解 ...

  10. VS编程,WPF中,获取鼠标相对于当前程序窗口的坐标的一种方法

    原文:VS编程,WPF中,获取鼠标相对于当前程序窗口的坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/ ...

随机推荐

  1. P4118 [Ynoi2018] 末日时在做什么?有没有空?可以来拯救吗?

    YNOI 智慧题 EasyVer1 [Ynoi Easy Round 2015] 世上最幸福的女孩 EasyVer2 小白逛公园 先看 EasyVer2 单点修改 区间查询最大子段和 考虑在线段树维护 ...

  2. Python装饰器:套层壳我变得更强了!

    Python装饰器:套层壳我变得更强了 Python装饰器:套层壳我变得更强了 关于作用域和闭包可以聊点什么? 什么是作用域 什么是闭包 装饰器:套层壳我变得更强了 参考资料 昨天阅读了<Pyt ...

  3. 单页应用(SPA)是什么?

    来源:https://zhuanlan.zhihu.com/p/648113861 概述 单页应用(SPA,Single Page Application)是一种网页应用或网站的设计模式,它在浏览器中 ...

  4. 【Unit1】表达式化简(层次化设计)-作业总结

    三次作业围绕表达式化简展开,逐次递进.主体思路为:递归下降解析表达式保存至类中,依据相关模式化简,依照规范输出字符串. 1.第一次作业 1.1 题目概述 表达式 = 项 + 项 + ... 项 = 因 ...

  5. 【记录】C/C++-关于I/O的坑与教训

    吐槽 每每读取字符串时,倘若稍有灵活的操作,总会遇上诡异奇怪的事情.究其原因,就是没完全理解一些基本读写函数的机制.这次做Uva227就把I/O上的问题全暴露出来了.想来还是应该记录一些经验教训. 记 ...

  6. 大模型基础补全计划(二)---词嵌入(word embedding)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   无 前言   本文是这个系列第二篇,它们是: &l ...

  7. 什么是VMware vSphere

    VMware vSphere不是特定的产品或软件.VMware vSphere是整个VMware套件的商业名称.VMware vSphere堆栈包括虚拟化,管理和界面层.VMware vSphere的 ...

  8. nacos(八): sentinel——基本使用

    一.概要 在微服务的架构中,流控是一个重要的任务.sentinel是阿里开源的流量治理组件,针对访问的"资源"或服务路径进行流控,内置了限流.熔断及系统负载保护等功能. senti ...

  9. 把postgreSQL的表导入SQLite

    万能的互联网,一查一大堆废话,几乎搞不定.现将查到的资料结合实践概况如下,对不对也不清楚,反正可以跑了. 1.把PostgreSQL的表SQL语句复制出来 CREATE TABLE "mai ...

  10. arthas安装和简单使用

    介绍 Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load.内存.gc.线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参.异常,监测方法执 ...