簡介Windows Mobile 6.5 Gesture API
所謂Gesture(手勢)既用來描述用戶使用手指或者觸筆在控件上進行一個短的具有一定方向的移動操作。大多數的Gesture都是基于手指的落下和抬起(WM_LBUTTONDOWN & WM_LBUTTONUP)這個操作組合(當然雙擊的操作是個特例,它使用兩次這個組合)。手勢在這個手指的落下和抬起的操作組合之上加入了一些其他信息,例如方向,位置,角度等等。Windows Mobile支持如下的手勢:Gesture描述
Tap 就像是鼠標的單擊事件。
手指在特定的時間和距離間隔上落下和抬起后,應用程序會接收到一個GID_SELECT的Gesture消息。同時,有可能在WM_LBUTTONDOWN和GID_SELECT消息之間產生多個WM_MOUSEMOVE消息.
Double Tap 相當于鼠標的左鍵雙擊。
用戶在特定的時間間隔和距離上進行雙擊操作,應用程序會獲得GID_DOUBLESELECT消息。
Hold 用戶可以按下并保持住。
用戶按下并保持一定時間,同時手指在一個特定的距離范圍內,應用程序將會收到GID_HOLD消息 。在手指抬起或者一個設定的時間間隔之后,將會伴隨一個GID_END消息。
Flick 用戶在屏幕上快速的滑動手指一段距離。
應用程序將會收到一個或者多個GID_PAN消息,然后是GID_SCROLL消息(手指抬起后),在最后 ,將收到GID_END消息。
Pan 用戶按下并保持在屏幕上,然后拖動一頓距離。
應用程序將會收到一個或者多個GID_PAN消息。 當手指抬起后,將會收到一個GID_END消息。
在Hold之后也可以接著產生Pan的消息。
很遺憾,在這里我們沒有看到多點觸摸的支持。或許在不久的將來,在Windows Mobile 7中,我們期望能看到多點觸摸的支持。
默認支持Gesture的控件
在上一小節中我們講到了Windows Mobile 6.5已經支持的手勢種類。那么如果我們要使用Gesture的話,哪些控件是支持手勢的呢?主要有以下幾種:
TabControl, Listbox, Listview, ComboBox, Treeview以及Webbrowser控件。
這六種控件是天然支持手勢的,我們不需要編寫一行的代碼(WebBrowser控件除外),他們在必要的時候就可以自動支持手勢。下面我附上的例子中,你可以看到,我用TabControl的tabPage來分別包含了一個Listbox, Listview, ComboBox和Treeview。然后給這些控件填充一些數據以便測試。您可以將該工程編譯后分別部署到Windows Mobile 6以及Windows Mobile 6.5的真實設備/模擬器上(注意,該工程需要.NET Compact Framework 3.5的支持)。您會發現,同樣的代碼在Windows Mobile 6.5上已經天然支持手勢了,不過在Windows Mobile 6.0上并不支持任何手勢。
這里需要特別指出的是,對于WebBrowser控件來說,在.NET Compact Framework中無法直接支持手勢。必須在C++中通過設定HS_NOSELECTION來建立DISPLAYCLASS。
GestureDemo1.zip(測試工程源代碼) (31.51 kb)
下面是該工程在Windows Mobile 6.5上運行的狀態:
使用Managed Gesture API
在前面我們提到了微軟針對Windows Mobile的Gesture提供了5種不同的手勢。他們分別是Tap, Double Tap, Hold, Flick, Pan。如果您使用C++來開發Windows Mobile 6.5上的應用程序,那么請參考MSDN上關于Windows Mobile上Gesture的參考文檔 http://msdn.microsoft.com/en-us/library/ee220917.aspx。 如果您是使用托管代碼,那么您可以使用由微軟的兩位工程師(Alex Yakhnin, Ron Buckton)所封裝的針對托管代碼的API(http://code.msdn.microsoft.com/gestureswm)。
在這套API中,分別針對這5種手勢做了封裝,不過名字略有改動:Tap改為Select; Double Tap改為DoubleSelect; Flick改為Scroll。 Hold和Pan沒有改變。這套API的用法很簡單,實例化一個他們封裝好的手勢識別器組件,然后給它指定要監控的對象。最后,加上針對這5種手勢的事件處理函數即可。如下代碼所示:
- private void InitGestureRecognizer()
- {
- gestureRecognizer1 = new GestureRecognizer(this.panel1);
- //You can also set the TargetControl property
- //gestureRecognizer1.TargetControl = this.panel1;
- gestureRecognizer1.Hold += new EventHandler(gestureRecognizer1_Hold);
- gestureRecognizer1.Select += new EventHandler(gestureRecognizer1_Select);
- gestureRecognizer1.DoubleSelect += new EventHandler(gestureRecognizer1_DoubleSelect);
- gestureRecognizer1.Pan += new EventHandler(gestureRecognizer1_Pan);
- gestureRecognizer1.Scroll += new EventHandler(gestureRecognizer1_Scroll);
- }
- void gestureRecognizer1_Scroll(object sender, GestureScrollEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + "), d=" + e.ScrollDirection + ", a=" + e.Angle + ", v=" + e.Velocity;
- }
- void gestureRecognizer1_Pan(object sender, GestureEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + ")";
- }
- void gestureRecognizer1_DoubleSelect(object sender, GestureEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + ")";
- }
- void gestureRecognizer1_Select(object sender, GestureEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + ")";
- }
- void gestureRecognizer1_Hold(object sender, GestureEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + ")";
- }
該示例代碼是在窗體上放了兩個控件: Panel1用來捕獲手勢事件;label1用來顯示當前手勢的一些參數。 運行狀況如下圖所示:

最后一部分,是demo程序的源代碼:GestureDemo2.zip (58.05 kb)
看到了吧,在Windows Mobile 6.5中,我們要給我們的程序加上手勢的支持是如此的簡單方便。好了,本小節就到這里,在下一節中我們將討論手勢和動畫。
使用動畫引擎
手勢的意義
在前面我們學會了如何使用托管的Mobile Gesture API來捕獲用戶的手勢:Tap, Double Tap, Hold, Flick, Pan.到這里就結束了么?沒有,我們需要看到手勢背后的意義。我們的程序應該通過這些通用的手勢消息來判斷用戶的操作意圖,來了解用戶想要做什么事情,從而做出進一步的響應:
Tap:點擊,即用戶用手指敲擊某一個控件。通常需要觸發某一個操作(按鈕類控件),或者是意味著在眾多控件/內容中選中該控件。
Double Tap:雙擊,即用戶快速的點擊兩次該控件。其實這是用戶從PC時代帶過來的一個操作,在電腦上我們經常會雙擊鼠標來打開某個文件夾或者選中某些內容等等。所以大家很自然的把它延伸到了Windows phone的操作習慣上。我們應該盡量減少用戶的雙擊操作,而是用單次點擊來代替。
Hold:即長時間的按在某個控件/內容上。例如用戶在玩游戲的時候按住某個按鈕,這表示某種持續性操作;而有時候長時間按住用戶則希望系統能夠給出一個上下文菜單。
Flick:即手指快速的滑動,通常用戶做這個操作的時候是希望窗體上的內容按照滑動的方向進行滾動。同時,手指滑動的速度快慢則體現了用戶希望該內容滑動滾動的速度快慢。
Pan:即手指按在屏幕上然后平移一段距離。通常這種操作的時候,用戶是希望將當前屏幕上的內容按照手指的方向同步平移。這有點像電腦上鼠標的點擊并拖拽的操作。
動畫引擎
對于Tap,Double Tap,Hold和Pan來說,我們看到都比較容易處理。無在乎就是根據用戶的操作來進行提示或者界面繪制或者彈出菜單等等。但是對于Flick來說,要讓窗體滾動起來就相對麻煩一些。
而且,窗體的滾動不能單純的只是一個勻速的移動過程。大家希望能夠看到滾動的內容更加符合現實世界中的一些感官,這也就是物理引擎。例如這個內容的滾動,他應該是從速度慢,然后加速,最后在減速。而最終停止的時候,不應該是直接突然停下來。用戶更加希望他是一個減速過程,同時能夠有阻尼震蕩。慶幸的是,Windwos Mobile 6.5的SDK中,給我們提供了這樣的物理引擎。我們可以很方便的使用它來制作一個窗體滾動的動畫效果。
在這套托管的Gesture API中,提供了一個physicsAnimation對象,他就是我們所利用的物理引擎。要使用這套物理引擎,我們只需要在當前窗體添加這個
physicsAnimation對象,然后設置其ExtentControl和ViewportControl。什么是ExtentControl呢,他就是你想要在窗體上滾動的那塊內容;而ViewportControl,就是用戶當前可以看到的那一部分。如下圖所示:

我們始終只能看到屏幕中間顯示的地圖的一小塊,但是整個圖片控件其實非常大,已經超出了窗體的范圍。在這里我們需要注意的是,ViewportControl他的實際大小通常比ExtentControl要小,但是它是ExtentControl的父級對象。即 ExtentControl在ViewportControl內部。
當我們需要它進行滾動的時候,我們只需要簡單的設置physicsAnimation對象的運動角度(確切說,是弧度),力度,然后調用其Start方法就可以。而要停止某一個運動,只需要調用其Stop方法,正在滾動的動作就會停止。
- private void gestureRecognizer1_Scroll(object sender, GestureScrollEventArgs e)
- {
- label1.Text = e.Kind.ToString() + ": " + e.State + ", (" + e.X + ", " + e.Y + "), d=" + e.ScrollDirection + ", a=" + e.Angle + ", v=" + e.Velocity;
- this.physicsAnimation1.Stop();
- this.physicsAnimation1.Angle = e.Angle;
- this.physicsAnimation1.Velocity = e.Velocity;
- this.physicsAnimation1.Start();
- }
上面這段代碼就演示了physicsAnimation組件的使用方式。這是利用的上一小節中咱們用到的Gesture API來捕獲Flick動作,也就是滾動。
首先我們使用Stop方法停止當前的動畫;然后設置運動的方向的弧度,這里是通過Gesture來判定運動方向;然后是力度,同樣也是從 Gesture中獲得;最后調用Start方法,則指定的ExtentControl就在ViewportControl對象的可視區域內滾動起來。
【編輯推薦】
- Windows Mobile 6.5定于10月6日發布
- Windows Mobile 6.5 Widgets開發初體驗
- Windows Mobile 6.5開發環境搭建以及變化
- Windows Mobile 6.5 SDK發布(附下載)