簡(jiǎn)介Windows Mobile 6.5 Gesture API
所謂Gesture(手勢(shì))既用來(lái)描述用戶(hù)使用手指或者觸筆在控件上進(jìn)行一個(gè)短的具有一定方向的移動(dòng)操作。大多數(shù)的Gesture都是基于手指的落下和抬起(WM_LBUTTONDOWN & WM_LBUTTONUP)這個(gè)操作組合(當(dāng)然雙擊的操作是個(gè)特例,它使用兩次這個(gè)組合)。手勢(shì)在這個(gè)手指的落下和抬起的操作組合之上加入了一些其他信息,例如方向,位置,角度等等。Windows Mobile支持如下的手勢(shì):Gesture描述
Tap 就像是鼠標(biāo)的單擊事件。
手指在特定的時(shí)間和距離間隔上落下和抬起后,應(yīng)用程序會(huì)接收到一個(gè)GID_SELECT的Gesture消息。同時(shí),有可能在WM_LBUTTONDOWN和GID_SELECT消息之間產(chǎn)生多個(gè)WM_MOUSEMOVE消息.
Double Tap 相當(dāng)于鼠標(biāo)的左鍵雙擊。
用戶(hù)在特定的時(shí)間間隔和距離上進(jìn)行雙擊操作,應(yīng)用程序會(huì)獲得GID_DOUBLESELECT消息。
Hold 用戶(hù)可以按下并保持住。
用戶(hù)按下并保持一定時(shí)間,同時(shí)手指在一個(gè)特定的距離范圍內(nèi),應(yīng)用程序?qū)?huì)收到GID_HOLD消息 。在手指抬起或者一個(gè)設(shè)定的時(shí)間間隔之后,將會(huì)伴隨一個(gè)GID_END消息。
Flick 用戶(hù)在屏幕上快速的滑動(dòng)手指一段距離。
應(yīng)用程序?qū)?huì)收到一個(gè)或者多個(gè)GID_PAN消息,然后是GID_SCROLL消息(手指抬起后),在最后 ,將收到GID_END消息。
Pan 用戶(hù)按下并保持在屏幕上,然后拖動(dòng)一頓距離。
應(yīng)用程序?qū)?huì)收到一個(gè)或者多個(gè)GID_PAN消息。 當(dāng)手指抬起后,將會(huì)收到一個(gè)GID_END消息。
在Hold之后也可以接著產(chǎn)生Pan的消息。
很遺憾,在這里我們沒(méi)有看到多點(diǎn)觸摸的支持?;蛟S在不久的將來(lái),在Windows Mobile 7中,我們期望能看到多點(diǎn)觸摸的支持。
默認(rèn)支持Gesture的控件
在上一小節(jié)中我們講到了Windows Mobile 6.5已經(jīng)支持的手勢(shì)種類(lèi)。那么如果我們要使用Gesture的話(huà),哪些控件是支持手勢(shì)的呢?主要有以下幾種:
TabControl, Listbox, Listview, ComboBox, Treeview以及Webbrowser控件。
這六種控件是天然支持手勢(shì)的,我們不需要編寫(xiě)一行的代碼(WebBrowser控件除外),他們?cè)诒匾臅r(shí)候就可以自動(dòng)支持手勢(shì)。下面我附上的例子中,你可以看到,我用TabControl的tabPage來(lái)分別包含了一個(gè)Listbox, Listview, ComboBox和Treeview。然后給這些控件填充一些數(shù)據(jù)以便測(cè)試。您可以將該工程編譯后分別部署到Windows Mobile 6以及Windows Mobile 6.5的真實(shí)設(shè)備/模擬器上(注意,該工程需要.NET Compact Framework 3.5的支持)。您會(huì)發(fā)現(xiàn),同樣的代碼在Windows Mobile 6.5上已經(jīng)天然支持手勢(shì)了,不過(guò)在Windows Mobile 6.0上并不支持任何手勢(shì)。
這里需要特別指出的是,對(duì)于WebBrowser控件來(lái)說(shuō),在.NET Compact Framework中無(wú)法直接支持手勢(shì)。必須在C++中通過(guò)設(shè)定HS_NOSELECTION來(lái)建立DISPLAYCLASS。
GestureDemo1.zip(測(cè)試工程源代碼) (31.51 kb)
下面是該工程在Windows Mobile 6.5上運(yùn)行的狀態(tài):
使用Managed Gesture API
在前面我們提到了微軟針對(duì)Windows Mobile的Gesture提供了5種不同的手勢(shì)。他們分別是Tap, Double Tap, Hold, Flick, Pan。如果您使用C++來(lái)開(kāi)發(fā)Windows Mobile 6.5上的應(yīng)用程序,那么請(qǐng)參考MSDN上關(guān)于Windows Mobile上Gesture的參考文檔 http://msdn.microsoft.com/en-us/library/ee220917.aspx。 如果您是使用托管代碼,那么您可以使用由微軟的兩位工程師(Alex Yakhnin, Ron Buckton)所封裝的針對(duì)托管代碼的API(http://code.msdn.microsoft.com/gestureswm)。
在這套API中,分別針對(duì)這5種手勢(shì)做了封裝,不過(guò)名字略有改動(dòng):Tap改為Select; Double Tap改為DoubleSelect; Flick改為Scroll。 Hold和Pan沒(méi)有改變。這套API的用法很簡(jiǎn)單,實(shí)例化一個(gè)他們封裝好的手勢(shì)識(shí)別器組件,然后給它指定要監(jiān)控的對(duì)象。最后,加上針對(duì)這5種手勢(shì)的事件處理函數(shù)即可。如下代碼所示:
- 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 + ")";
- }
該示例代碼是在窗體上放了兩個(gè)控件: Panel1用來(lái)捕獲手勢(shì)事件;label1用來(lái)顯示當(dāng)前手勢(shì)的一些參數(shù)。 運(yùn)行狀況如下圖所示:

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

我們始終只能看到屏幕中間顯示的地圖的一小塊,但是整個(gè)圖片控件其實(shí)非常大,已經(jīng)超出了窗體的范圍。在這里我們需要注意的是,ViewportControl他的實(shí)際大小通常比ExtentControl要小,但是它是ExtentControl的父級(jí)對(duì)象。即 ExtentControl在ViewportControl內(nèi)部。
當(dāng)我們需要它進(jìn)行滾動(dòng)的時(shí)候,我們只需要簡(jiǎn)單的設(shè)置physicsAnimation對(duì)象的運(yùn)動(dòng)角度(確切說(shuō),是弧度),力度,然后調(diào)用其Start方法就可以。而要停止某一個(gè)運(yùn)動(dòng),只需要調(diào)用其Stop方法,正在滾動(dòng)的動(dòng)作就會(huì)停止。
- 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組件的使用方式。這是利用的上一小節(jié)中咱們用到的Gesture API來(lái)捕獲Flick動(dòng)作,也就是滾動(dòng)。
首先我們使用Stop方法停止當(dāng)前的動(dòng)畫(huà);然后設(shè)置運(yùn)動(dòng)的方向的弧度,這里是通過(guò)Gesture來(lái)判定運(yùn)動(dòng)方向;然后是力度,同樣也是從 Gesture中獲得;最后調(diào)用Start方法,則指定的ExtentControl就在ViewportControl對(duì)象的可視區(qū)域內(nèi)滾動(dòng)起來(lái)。
【編輯推薦】
- Windows Mobile 6.5定于10月6日發(fā)布
- Windows Mobile 6.5 Widgets開(kāi)發(fā)初體驗(yàn)
- Windows Mobile 6.5開(kāi)發(fā)環(huán)境搭建以及變化
- Windows Mobile 6.5 SDK發(fā)布(附下載)