WPF 客戶端開發需要知道的觸摸失效問題

  • 2019 年 10 月 5 日
  • 筆記

在說 WPF 開發的時候,如果開發的應用是觸摸應用,那麼熟悉的小夥伴會說到觸摸失效問題。從分類上觸摸失效有系統的觸摸失效,應用程序的觸摸失效,同時觸摸失效指的不是觸摸沒反應,本文詳細告訴大家什麼是觸摸失效

在說觸摸失效時,需要先知道有多少分類。首先是系統觸摸失效還是應用觸摸失效,所有的觸摸失效本身都分為兩個不同失效的方式,一個是全觸摸失效,另一個是多指觸摸失效了,請看下圖

觸摸失效

全觸摸失效

多指觸摸失效

系統觸摸失效

系統桌面用觸摸點不了任何內容,但是用鼠標可以

在任何應用都無法使用觸摸,但是鼠標可以

系統的觸摸都轉鼠標,開啟觸摸點反饋的時候發現只有鼠標光標顯示,沒有顯示觸摸光標。無法在系統和任何應用使用多指觸摸

應用觸摸失效

在某個應用裏面無法用觸摸,但是可以使用鼠標

在應用裏面所有觸摸都轉鼠標,也就是收不到Touch事件,同時收不到多指觸摸

系統觸摸失效和應用觸摸失效的不同在於,應用觸摸失效只對某個應用,在其他應用或還是此應用重啟之後可能就可以使用觸摸了。如果是系統觸摸失效了,大概就和沒有觸摸設備一樣,所有的應用和系統都觸摸失效

觸摸失效的全觸摸失效是就像沒有觸摸設備所有觸摸沒有響應,但是鼠標可以響應。而多指觸摸失效是觸摸不支持多指,但是可以轉換為單指觸摸或轉為鼠標,相當於是鼠標點擊

在應用程序裏面還有瞬時觸摸失效問題,這時的瞬時觸摸失效就是某次觸摸沒有響應,但是此後應用程序能恢復觸摸

對於不同的觸摸失效問題對應不同的方法

在應用程序裏面的觸摸失效請看WPF 程序無法觸摸操作?我們一起來找原因和解決方法! – walterlv

在應用程序的觸摸失效可以分為啟動前和運行過程,如果應用程序在啟動前就已經觸摸失效了,那麼和應用程序本身的代碼執行無關。在 Win7 系統存在很多觸摸問題,在應用啟動過程還沒有進入用戶代碼就觸摸失效一般就是系統問題。如果在運行過程觸摸失效了,也可能和系統相關但是大部分都是應用程序問題

為什麼系統沒有觸摸失效而應用觸摸失效了?從官方文檔可以知道 windows 對觸摸的處理方式,和從 打開 HID 集合Windows 觸摸文檔 可以知道,從硬件收到的消息需要進入 windows 內核處理,然後讓處理之後的消息經過 Windows touch sdk 然後轉發到應用,如下圖

以上圖片從windows 觸摸架構文章複製

這是因為如果HID設備作為一個USB設備,如果被某個應用獨佔了,那麼其他應用將無法訪問這個USB設備。在 HID 設備中,默認都會被系統獨佔,那麼被系統獨佔的 HID 設備是如何將數據發送到每個應用?此時就需要系統做轉發了

但是在 win7 的時候,多指觸摸還沒有完善,很多古老的程序不知道有觸摸消息,如果此時 Windows 直接發送觸摸消息給到所有應用。那麼可以看到有很多應用都是不工作的,於是小夥伴就會說垃圾微軟,我的觸摸屏無法使用。解決這樣的問題很簡單,只有在聲明自己支持觸摸的應用程序上,系統才會發送對應的觸摸消息,如下文

Unless an application registers for Windows Touch input messages with the RegisterTouchWindow function, notifications for gestures (WM_GESTURE messages) are created by Windows and sent to that application window. If an application Window registers to receive touch messages, notifications for Windows Touch input (WM_TOUCH messages) are sent to that application window.

因為兼容的問題,有很古老的軟件,例如 windows 的畫圖板,這部分軟件以為自己是獨佔整個輸入設備的,如 DirectInput 概述 裏面相關博客提到的,那麼這部分設備應該如何處理?系統將會在上層虛擬化出對應的設備,這些都是軟件設備,讓對應的應用獨佔,這樣每個應用對獨佔的設備做了不清真的處理也不會影響其他程序

也就是從硬件的觸摸到達應用需要經過系統,而應用程序是否真的有觸摸,還需要系統給應用程序一個觸摸設備或觸摸信息。如果是上古的軟件,系統將會給應用一個軟件設備。如果是古老的軟件,在沒有聲明支持觸摸支持的時候,系統將不會發送觸摸消息。如果是現代的軟件聲明 Pointer 的,那麼將默認給觸摸消息

應用的觸摸失效很多都在於系統給應用分配觸摸的時候,在應用程序啟動的過程,如果和系統聲明了自己是支持觸摸的,但是系統訪問驅動程序沒有返回正確的觸摸設備,或者系統這部分處理被魔改了,那麼這個應用將觸摸失效。如果系統認為這個應用是需要獨佔設備的,實際這個應用支持觸摸,那麼系統將會給這個應用設備列表,應用需要使用GetRawInputDeviceList自己手動監聽,如果應用沒有做,那麼系統連觸摸轉鼠標都不會發給應用,這時的應用就會全觸摸失效。而如果應用聲明了自己支持觸摸,系統沒有處理,系統認為這是不支持觸摸的應用,那麼系統為了兼容就將觸摸轉鼠標給應用,此時應用將會多指觸摸失效

是不是覺得上面的話很複雜?看看下面的圖片方便你理解

如果是應用觸摸失效,同時在啟動的過程就觸摸失效,那麼可以做的方法是重啟軟件,重啟軟件將會重新告訴系統。此時系統可能返回對的值。如果系統很多次都沒有給應用觸摸,那麼可能是系統的驅動沒有安裝對,或者系統的補丁沒打對,或者系統是魔改的系統,此時可以嘗試安裝驅動,如果安裝驅動沒有用,那麼嘗試安裝系統補丁或重裝清真的系統

基本上應用觸摸失效,同時在啟動過程就觸摸失效的,都是win7的系統,現在win10的觸摸架構修改了,很少有用戶告訴我觸摸失效

那麼如果是系統觸摸失效了,如果是全失效,大部分都是硬件問題,測試方法是使用這個主機接到另一個市場上在賣的觸摸設備,如果此時觸摸可以用,但是接到自己做的觸摸設備上無法使用觸摸。那麼就是自己的觸摸設備沒有做好,請閱讀Windows 的 Pen 協議同時使用 BusHound 抓硬件發過來的數據,看是不是有哪些數據發的不符合文檔

如果系統只是多指觸摸失效了,那麼也需要看一下是不是硬件問題,然後檢查系統是否打上了驅動以及是否開啟多指觸摸支持

WPF 程序無法觸摸操作?我們一起來找原因和解決方法! – walterlv

Resolve HID compliant touch screen missing

打開 HID 集合

Required HID Descriptors

winapi – How to determine display – touch device associations for windows 10? – Stack Overflow

RAWINPUT (winuser.h)

c++ – Associate HID Touch Device with Pnp Monitor – Stack Overflow

GetRawInputDeviceList function (winuser.h)

c – Too many raw input device from GetRawInputDeviceList() – Stack Overflow

winapi – GetRawInputDeviceList not working as expected on Windows7 – Stack Overflow

Windows 中支持的 HID 客戶端 – Windows drivers

獲取按用戶模式應用程序的 HID 報表 – Windows drivers

HID 客戶端驅動程序 – Windows drivers

鍵盤和鼠標 HID 客戶端驅動程序 – Windows drivers

About Windows Touch – Windows applications


本文會經常更新,請閱讀原文: https://blog.lindexi.com/post/WPF-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%BC%80%E5%8F%91%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E7%9A%84%E8%A7%A6%E6%91%B8%E5%A4%B1%E6%95%88%E9%97%AE%E9%A2%98.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。

如果你想持續閱讀我的最新博客,請點擊 RSS 訂閱,推薦使用RSS Stalker訂閱博客,或者前往 CSDN 關注我的主頁

本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名林德熙(包含鏈接: https://blog.lindexi.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請 與我聯繫