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原生按鈕,這讓這個問題更難理解了)

 

最后,希望有了解的大神幫我解釋這個問題,從而得到不惡心人的解決方法。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM