• 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原生按钮,这让这个问题更难理解了)

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

  • 相关阅读:
    Webpack 入门学习
    如何把百度地图引入自己的网页中
    哗啦啦Python之路 Day 1 数据类型,运算符和表达式
    哗啦啦python之路 Day 2 程序控制结构
    找个轻量级的Log库还挺难
    W32.Downadup.autorun病毒的清除
    一个VxWorks源代码网站
    VisualSVNServer无法卸载也无法安装,报告不是有效的MOF文件(0x8004401e)错误
    如何用Visual Studio 2005编译Wireshark的插件
    TAU G2中的BitString和OctetString
  • 原文地址:https://www.cnblogs.com/GuoRL/p/5944649.html
Copyright © 2020-2023  润新知