zoukankan      html  css  js  c++  java
  • WPF之坑——surface触控失灵之谜

    本次又遇到了WPF编写触控程序的一个问题,虽然已解决,但原因确搞不太明白,希望有大神看到这篇文章帮我解答。

    在项目中实现了自己定义的icommandsource,因为需要对触控有特殊需求,控件对鼠标与触摸有了各自的事件响应,以下代码是原始touchup事件的处理逻辑。

     1         protected override void OnTouchUp(TouchEventArgs e)
     2         {
     3             if (_deviceId == e.TouchDevice.Id)
     4             {
     5                 ReleaseAllTouchCaptures();
     6                 ReleaseDevice();
     7 
     8                 if (!_isDraging)
     9                 {
    10                       RoutedEventArgs rea = new RoutedEventArgs(Button.ClickEvent, this);
    11                       RaiseEvent(rea);
    12 
    13                       if (!rea.Handled && ClickCommand != null)
    14                       {
    15                           ClickCommand.Execute(ClickCommandParam);
    16                       }
    17 
    18                 }
    19 
    20                 base.OnTouchUp(e);
    21         }        

    使用该控件编写界面,触摸点击按钮后弹出其他窗口,这时神奇的事件发生了:

    如果使用的是带触控屏的PC上,新弹出的窗口不会自动激活需要新点击1次(貌似问题不大)

    但如果程序运行在一台surface上,新弹出的窗口需要点击10次才会被激活,随后其中的控件才会收到事件响应。(PC与Surface均是win10系统,需要点击10次这个数据很准确,已经过反复测试,就像是谁在代码是设置了计数器一样准确)。

    发现问题后感觉特别茫然,也没查到太多有关信息,一顿乱试发现了解决方案。改写后的代码如下:

     1         protected override void OnTouchUp(TouchEventArgs e)
     2         {
     3             if (_deviceId == e.TouchDevice.Id)
     4             {
     5                 ReleaseAllTouchCaptures();
     6                 ReleaseDevice();
     7 
     8                 if (!_isDraging)
     9                 {
    10                     DelayRaiseClick();
    11                 }
    12             }
    13 
    14             base.OnTouchUp(e);
    15         }
    16 
    17         private async void DelayRaiseClick()
    18         {
    19             await System.Threading.Tasks.Task.Run(() =>
    20             {
    21                 System.Threading.Thread.Sleep(50);
    22             });
    23 
    24             RoutedEventArgs rea = new RoutedEventArgs(Button.ClickEvent, this);
    25             RaiseEvent(rea);
    26 
    27             if (!rea.Handled && ClickCommand != null)
    28             {
    29                 ClickCommand.Execute(ClickCommandParam);
    30             }
    31         }

    可以看到,上下代码的唯一区别仅是抛出click事件前异步等待了50ms,但这个变化使得新弹出的窗口可以直接激活,surface与pc上运行效果一致。那么问题就来了,在这异步等待的50ms中发生了什么,我能想到的就是,界面的路由事件可以完整的传递完毕,包括touchup和由触摸引发的mouseup消息。至于为什么消息没有传递完毕就会出问题(把e.Handled置为true可以阻止消息继续传递啊,也没说必须传递完)想不明白,还有,为什么在surface上需要操作10次,这个计数是谁干的,完全没有头续。。。

    借用我一个同事的话说,这个解决方案虽然完成了任务,但太恶心了(ps,他也遇到了跟我一样的问题,而具用的是wpf原生按钮,这让这个问题更难理解了)

    最后,希望有了解的大神帮我解释这个问题,从而得到不恶心人的解决方法。。

  • 相关阅读:
    XML相关知识点
    MLPlatform开发日志
    1.0 es6 箭头函数
    基本数学概念
    4.4 thymeleaf使用补充
    vim操作手册
    eclise创建后台项目
    正则表达式
    数据库隔离级别
    1. gradle的使用教程
  • 原文地址:https://www.cnblogs.com/GuoRL/p/5944649.html
Copyright © 2011-2022 走看看