複製鏈接
請複製以下鏈接發送給好友

手勢功能

鎖定
勢可包括許多不同的動作。它可以是計算機屏幕上的手指移動,而且就像揮動手臂或與別人握手一樣,搖頭甚至也算得上是一種手勢(姿勢)。依我看來,只將屏幕輸入視為唯一手勢來源似乎有點狹隘。當今的許多設備都有多種傳感器,其中包括觸摸屏、加速感應器、羅盤、GPS 裝置及照相機等。搖晃、翻轉、旋轉設備,甚至對着鏡頭微笑都可以解釋為需要軟件進行響應的手勢(姿勢),而這些僅僅是我們所知傳感器能夠識別的手勢。
中文名
手勢功能
釋    義
屏幕驅動程序生成鼠標左鍵移動
手    勢
知傳感器能夠識別的
體    現
一致性,路由
技    巧
先度量,再應用適當的改進。
提    示
首幀時間至關重要

手勢功能功能概述

自 2002 年第一批 Windows Mobile 設備問世以來,觸摸屏已經成為該設備的代名詞;不過,據稱 Windows Mobile 6.5 才是第一個向開發人員公開所有形式手勢支持的版本。那麼什麼是手勢,它又為何如此風靡?
Windows Mobile Professional 設備的傳統觸摸屏提供的是鼠標模擬圖面,它通過屏幕驅動程序接口生成鼠標左鍵和鼠標移動消息。在處理和傳送這些消息時,屏幕和觸筆就像實際的鼠標一樣,它們之間存在一定的相似性:鼠標與屏幕上的觸筆一樣,以線性方式產生一系列位置座標,都可用作非常精確的指針設備。
兩者之間也有一些區別。比如,鼠標發送的位置信息與按鈕信息無關,而觸摸屏總是模擬按下的左鍵,僅在發生屏幕接觸時才發送位置信息。只要觸摸屏與鼠標保持足夠的相似性,此模式就仍然有用武之地。然而,隨着現代話機屏幕的不斷增大,用户食指已然迅速變成最自然而直觀的觸筆。在個人消費市場上,精度要求和易失性都比較高的觸筆很快就會過時,取而代之的是對粗獷的交互式界面的需求,這種界面會勾起消費者的觸摸衝動,促進與用户之間的情感聯繫。
與觸筆筆尖的精確度要求形成鮮明的對比,手指活動提供了一種不同的操作模式,它與鼠標輸入截然不同。輸入數據不再是精確定位的,線性輸入軌跡往往更接近於繞月軌道而非直線。區別不僅在於數據;輸入結果也應產生與輸入序列相符的平滑動態響應。現在,鼠標模式顯然已不再適用,我們需要一種不同的新模式來幫助描述這種輸入並瞭解其響應方式。答案就是手勢。

手勢功能觸摸手勢

在詳細瞭解觸摸手勢之前,我們先在更寬泛的層面思考一下一般意義上的手勢。手勢可包括許多不同的動作。它可以是計算機屏幕上的手指移動,而且就像揮動手臂或與別人握手一樣,搖頭甚至也算得上是一種手勢(姿勢)。依我看來,只將屏幕輸入視為唯一手勢來源似乎有點狹隘。當今的許多設備都有多種傳感器,其中包括觸摸屏、加速感應器、羅盤、GPS 裝置及照相機等。搖晃、翻轉、旋轉設備,甚至對着鏡頭微笑都可以解釋為需要軟件進行響應的手勢(姿勢),而這些僅僅是我們所知傳感器能夠識別的手勢。
Windows Mobile 6.5 中的體系結構在設計上考慮到了這一點,因此將手勢來源及識別過程與該手勢的路由、傳送和響應分開。雖然我們只有觸摸手勢識別功能,但一旦具備相應傳感器和識別組件,就可以通過系統提供新的手勢。新的傳感器和識別軟件可由硬件製造商添加,並集成到現有手勢傳送體系結構中, 圖 3 五種核心手勢
您可能會奇怪為什麼要使用其中的一些手勢,因為鼠標行為似乎已足以獲取相同的信息。比如,選擇手勢就像單擊按鈕一樣,而平移手勢就像鼠標移動一樣。這五種手勢的重要性體現在兩個方面。
一致性:系統通過兩個消息接收鼠標點擊操作:鼠標按鈕按下和彈起。識別點擊操作的具體行為是識別該操作的控件所特有的功能。比如,當鼠標按鈕按下和彈起的位置都位於窗口邊界內時,按鈕控件會將這兩個動作識別為一次點擊。相比之下,ListView 控件對其列表中的每一項也會識別同樣的事件。選擇手勢通過使用一致的參數,使其識別獨立於控件。用於手勢識別的距離閾值可識別分辨率(或者更準確地説,可識別到點/英寸),並且是為使用最廣泛的指形(手指形狀範圍異常廣泛)而設的。因此,可在大小不同的屏幕上使用相同的物理距離,從而在設備之間提供一致性。
路由手指不是準確指針設備,當用户在移動或走動中時尤為如此,因此應用程序需要最大化可觸摸目標區域,這一點至關重要。手勢傳送組件藉助特定的規則完成此任務,從而提升了這些簡單手勢的價值。

手勢功能路由

手勢信息通過新的 WM_GESTURE 消息進行傳送,而且該消息與所有窗口消息一樣,也有包含消息詳細信息的關聯參數 DWORD wParam 和 LONG lParam。WM_GESTURE 消息參數包含手勢 ID 作為 wParam 以指示要傳送的手勢,幷包含完整手勢信息的句柄作為 lParam。鼠標消息總是發送到鼠標座標位置所在的最頂層窗口(不包括鼠標捕獲情形),但對於手勢來説,這些規則將有所不同。手勢消息與之不同,它們總是發送到構成完整手勢序列的第一個觸摸點相應的最頂層窗口。對於屏幕移動距離容差很小的選擇、按住和雙選手勢來説,這一細微差異的影響不大。但對於平移手勢,差別就很大了。在開始平移時,所有平移消息都會發送到開始平移時所在的窗口,即使平移移動使觸摸點移出原始窗口也如此。
同樣,滾動手勢的識別位置也會從其原始觸摸點延伸到許多像素的距離。但將滾動消息路由到與上述平移消息相同的窗口中比較合理,因為用户在該原始控件中啓動輸入序列並打算以其作為目標。鑑於平移手勢通常與直接操控有關(即像在桌面上移動紙張一樣在屏幕上移動內容),因此此路由非常合理,因為在屏幕上移動內容期間,在最初觸摸時指下的控件或屏幕點應始終保持在指下。
未處理的消息路由
手勢消息路由的另一個不同尋常的方面是對未處理手勢消息所採取的操作。與所有未處理的消息一樣,它們最終也被髮送到 DefWindowProc 以進行默認處理。當 DefWindowProc 收到手勢消息時,它會嘗試查找當前窗口的父窗口並將該消息發送到該父窗口。這樣做可最大限度地擴大可供用户使用的可觸摸區域。
為便於解釋,請考慮一個包含一些子標籤控件的可滾動窗口。父窗口實現平移和滾動手勢響應邏輯,從而在可視圖面中上下移動子標籤控件。不過,這些標籤控件未發生修改,對手勢支持一無所知。如果用户手勢碰巧始於觸摸標籤控件而不是父窗口,該用户也可獲得相同的結果,也就是窗體將相應地移動以響應輸入移動。通過將未處理的手勢消息從標籤控件轉發到父窗口,滿足了用户的期望,內容移動的效果就像用户直接觸摸窗體一樣。手勢消息
Windows Mobile 6.5 可識別五種手勢,而應用程序可接收七種手勢。額外的兩種手勢是在手勢序列開始和結束時發送的 BEGIN 和 END(所有手勢類型都帶有前綴 GID_ 以指示手勢標識符,因此這兩種手勢的標識符是 GID_BEGIN 和 GID_END)。例如,如果識別選擇手勢,則應用程序會收到三個手勢消息:GID_BEGIN、GID_SELECT 和 GID_END。對於以滾動手勢為結果的平移序列,應用程序會收到 GID_BEGIN、GID_PAN、GID_PAN…、GID_SCROLL 及最後的 GID_END。
GID_BEGIN 十分有用,因為它包含原始觸摸點的屏幕座標。GID_END 可方便地指示何時用户輸入已結束並且不再為當前序列發送手勢。
為了幫助您瞭解 Windows Mobile 6.5 中的基本手勢識別和傳送系統,我在附帶的示例 SimpleGestureCapture 中包含了一個 Visual Studio 項目。此示例顯示一個列表框,併為主窗口收到的每個手勢消息添加一個新行,其中包括所有手勢的位置信息及滾動手勢的角度和速度。您將需要安裝 Visual Studio 2005 或 Visual Studio 2008 以及 Windows Mobile 6 Professional SDK 和 Windows Mobile 6.5 Developer Tool Kit。從該示例中,您可以瞭解如何接收手勢消息並提取數據。

手勢功能物理引擎

在手勢支持中,最令人興奮的部分就是操控屏幕內容時用户體驗到的自然響應。此響應的關鍵之處是設備間的一致、可預測和自然的體驗。為了實現此一致性,在操作系統中新增了一種名為“物理引擎”的組件。此模塊提供一套獲取輸入信息(包括滾動手勢的角度和速度)的數字處理算法,並使用特定減速係數按時間來減慢速度。此外,當輸入速度足以將動畫點移到邊框以外時,還可使用物理引擎應用邊界動畫。
若要在 Windows Mobile 6.5 中使用物理引擎,必須首選創建並初始化物理引擎的新實例。這樣,系統會以固定的時間間隔定期對其進行輪詢以檢索當前動畫位置,並且調用應用程序會相應地重繪其客户端區域。物理引擎會持續減慢動畫速度,直至在低於最小閾值,那時會將動畫標記為完成並可將其釋放。
作為初始化數據的一部分,應用程序必須指定數據空間的邊框以及顯示空間的視圖框(見圖 5)。如果視圖框移到邊框以外,物理引擎會使用所選邊界動畫(也是初始化數據的一部分)將視圖框重新納入邊框之內。物理引擎初始化十分靈活,可以只允許在一個軸上設置動畫,必要時也可為每個軸設置不同的邊界動畫。
圖 5 物理引擎如何處理邊框和顯示框
默認情況下,物理引擎根據從初始化時刻到每個位置檢索調用時刻這一期間所獲取的時間差值來減慢速度。調用應用程序可通過指定“user time”值來覆蓋此設置,並讓物理引擎計算該時間點的位置。這對於查找動畫結束屏幕位置十分有用。
項大小是另一個引人注目的物理引擎配置。此信息用於向數據空間強加一個有效停止位置網格,從而強制物理引擎允許視圖的最終位置落於其中某一網格座標。當應用程序要在屏幕上顯示項列表,而不希望在屏幕頂部顯示不完整的項時,此行為十分有用。該行為適用於任意軸或同時適用於兩個軸,並將調整動畫減速和停止算法以延長或縮短動畫持續時間,從而擊中所需的停止點。

手勢功能綜合講述

若要應用程序完全支持觸摸手勢,需要對其進行改進,使其識別相應的手勢消息並做出相應的響應。必要時,需要創建和查詢物理引擎實例以驅動屏幕重繪。此外,應用程序還需要考慮在動畫或手勢序列被進一步的用户輸入或其他事件中斷時應採用什麼操作,並確保這種情況得到有效處理。雖然所有這一切的實現方式相對而言簡單明確,但需要編寫大量必須為響應手勢的每個窗口而創建的 Boilerplate 代碼。因此,Windows Mobile 6.5 中已採取一些步驟來簡化此任務。
首先,一些內置控件已更新為支持手勢,包括 LISTVIEWLISTBOX、TREEVIEW 和 WEBVIEW 控件(有些模式不支持手勢)。如果您已在使用上述任意控件,則表示您的應用程序已支持手勢。
對於沒有使用這些內置控件的應用程序,有一個名為 Window Auto Gesture (WAG) 的新 API 可顯著簡化在最常見方案中實現手勢支持所需的工作。

手勢功能自動手勢

WAG 邏輯與 DefWindowProc處理緊密結合,提供了可用於任何窗口的默認手勢響應。啓用後,WAG 會自動響應 GID_PAN 和 GID_SCROLL 手勢,創建物理引擎實例並通過通知消息將相關定位數據發送迴應用程序。此外,WAG 還可以通過在平移或滾動手勢進行時監視輸入隊列來執行手勢中斷,從而提供與動畫狀態之間的適當轉換。
WAG 的默認配置是忽略手勢消息,因此要使用 WAG 行為的所有窗口都必須先啓用手勢支持。若要啓用手勢支持,應用程序必須為需要該支持的每個窗口調用 TKSetWindowAutoGesture,並傳遞所需的配置設置。如前所述,WAG 旨在簡化最常見的手勢支持方案。因此,若要使 WAG 驅動窗口,則創建該窗口時須在可由觸摸手勢操控的軸中設置 WS_VSCROLL 和/或 VS_HSCROLL 樣式。此外,應用程序須正確管理滾動條,能夠根據需要維護範圍、最小化/最大化和頁面大小。這樣 WAG 才能夠計算窗口所顯示的數據區域大小。
WAG 有幾個選項值得一提:
WAG 可處理 GID_PAN 和 GID_SCROLL 手勢,但可根據需要禁用其中任意手勢。與物理引擎一樣,WAG 也支持設置項的寬度和高度。此信息不僅用於設置捕捉點,而且還會將滾動範圍值從項計數擴展到像素計數。例如,假設一個列表包含 10 項,其滾動條範圍為 0 到 9,每項在垂直方向需要佔用 20 像素來顯示其內容,則項的高度應設置為 20。WAG 會將該滾動範圍 (10) 與像素高度 (20) 相乘,從而確定數據的完整像素範圍(200 像素)。WAG 支持一種特殊模式,該模式通過嚮應用程序生成 WM_xSCROLL 消息來驅動窗口移動,而不是通過生成較常見的所有者動畫消息。如果您使用舊式應用程序,並且希望在儘可能少更改代碼的情況下獲得觸摸手勢支持,則此模式十分有用。啓用此模式的方法是:將 nOwnerAnimateMessage 值(TKSetWindowAutoGesture初始化數據的一部分)設置為 0 而不是常用的 WM_USER + x 值。在此模式下,有些功能是受限的,如不支持逐像素操控,只能逐項操控控件。此外,在此模式下不能超出滾動範圍,因此將忽略擴充值。此選項不適合同時在兩個軸上滾動,因為每個軸必須獨立移動。擴充描述可將顯示區域拖到數據範圍之外的距離,表示為顯示大小的百分比。啓用擴充時須小心謹慎,因為這會允許用户將顯示區域拖動到滾動限制之外,並公開許多現有應用程序都無法正常處理的屏幕區域。當空間顯示在數據範圍頂部或左側以外時,請確保應用程序能夠正確清除屏幕。通常,應用程序會將 WAG 的 nOwnerAnimateMessage 配置為一個 WM_USER 到 WM_APP 範圍的值。每次應用程序需要重繪其顯示區域時,WAG 就會在發回到應用程序的消息中使用此值。在序列中的首個動畫消息之前有一個狀態消息,該消息指示控件現在正在響應手勢輸入。WAG 會自動聚合 GID_PAN 手勢消息,並以每秒 24 次的最大頻率(使用來自 Windows Mobile 6.5 Developer Tool Kit 的 gesturephysics.h 中的 GESTURE_ANIMATION_FRAME_DELAY_MS 計時器持續時間進行管理)只嚮應用程序發送動畫消息。這同樣適用於滾動動畫,WAG 使用相同的計時器來查詢其物理引擎,最大頻率為每秒 24 次。
如果控件支持焦點或者在沒有用户交互的情況下發生外觀變化(例如通過異步更新),則 WAG 的狀態消息選項尤為有用。狀態消息通知控件用户正通過觸摸界面進行交互。此類消息可用作觸發器,用於暫停執行一些更新,這些更新可能更改控件或其內容的外觀或者因屏幕動畫而不必要地佔用資源。生成全屏動畫效果可能佔用大量資源,因此應暫停所有不必要的後台處理,並集中資源為用户提供流暢及時的響應,這是非常重要的。完成觸摸交互之後,可根據需要使用狀態消息觸發數據刷新和更新。

手勢功能提示技巧

使用手勢 API 接受和處理手勢信息的思路十分簡單。不過,要生成響應手勢的流暢動畫可能要花一些心思。下面的提示可能對您有所幫助。
首幀時間至關重要。人眼對用户界面延遲的敏感程度令人吃驚。例如,如果屏幕觸摸與圖形響應之間的延遲超過 100 毫秒,那麼即使應用程序隨後保持穩定的每秒 24 幀的速率 (fps),用户也會感覺到反映遲緩。應設法確保首幀響應速度足夠快,最好低於 50 毫秒。值得一提的是,手勢識別器和手勢傳送功能的開銷已經過精心優化,從觸摸到起效的時間僅為 1 毫秒或 2 毫秒。
首選一致的幀速率在我們的測試中,用户寧願選擇稍慢但更一致的幀速率,也不是很快但變化較大的速率。利用此信息,我們創建了一個計時器來調控幀更新頻率,並調整了計時器以確保在每個幀中有一些空閒的 CPU 時間可以處理其他任務。
消除動畫期間的不必要開銷。顯而易見,每幀中的工作量越少,每秒繪製的幀數就越多。不過,有時很難確定具體可以留出哪些工作。在觸摸操控期間,尤其是在滾動動畫期間,用户不太注意細節,而是關注更醒目的內容。例如,在滾動電子郵件列表期間,用户可能不太注意每封郵件的預覽,而更關注郵件在列表中的位置及其標題。因此,可以停止更新或檢索預覽文本,以騰出額外的時間保持順暢的動畫。
明智地使用屏外緩衝區。雙緩衝可能是提高繪製性能以及減少屏幕零碎繪製的極佳方法。不過,使用該方法時必須謹慎,因為屏外緩衝區會消耗大量資源。應確保該緩衝區保留儘可能短的時間並保持最小大小。使用 ScrollWindowEx API 通常可以實現類似的結果,而不會產生屏外緩衝區的內存開銷。
先度量,再應用適當的改進。標準性能分析做法可確保您修復已發生的問題。因此在更改任何代碼之前,您務必先通過度量了解動畫循環中的開銷在哪裏,然後在對應用程序最有益的方面開展工作。