在 Windows Mobile 6.5 中,可使用 Gestures API 擷取使用者的手勢
1. 簡介
手勢 Gestures 在行動裝置上越來越重要,使用者可在行動裝置,透過觸控筆(滑鼠),透過不同的手勢動作來執行命令,在 Windows Mobile 6.5 的 new feature 中,就包含了 Gestures API (另一個是 Widget),本文介紹 Windows Mobile 6.5 Developer Tool 中 Gestures API Sample Code。
註 : 在 2009/7/31 MSDN 有篇關於 Gestures API 的完整介紹,Using Gestures in Windows Mobile 6.5,需注意 Gesture API 只能使用在 Windows Mobile 6.5 中,範例的位置請參考下圖
2. Gestures API
2.1 Touch Gestures
Touch Gestures 是當使用者在螢幕上,透過手指或觸控筆做短暫且具方向性的描繪動作,根據其動作,產生相對應的事件,最簡單的就是對螢幕做一次敲擊,而在做敲擊的動作中,手指按下 ( WM_LBUTTONDOWN) 與手指離開( WM_LBUTTONUP) 時就會產生事件。而在手指按下與離開的這段期間,手指移動的方向(帶正負)、位置與速度,透過手勢辨識產生相對應的事件,Gestures API 支援五種不同的手勢訊息。
(1) Tap : 代表滑鼠左鍵單擊,事件 GID_SELECT
(2) Double Tap : 代表滑鼠左鍵雙擊,事件 GID_DOUBLESELECT
(3) Hold : 使用者觸控筆觸控螢幕並保持狀態,代表滑數右鍵,事件 GID_HOLD
(4) Flick : 使用者在螢幕透過手指做單一像素滑動,當速度夠快時,則產生捲動,事件 GID_SCROLL -> GID_END
(5) Pan : 使用者觸控且在螢幕上隨意移動,代表滑鼠移動,事件 GID_PAN -> GID_END
*註 : 相關事件可參考 GESTUREINFO
想要使用 Gestures API,需 include 一些標頭檔,主要是以下三個
#include <gesture.h>
#include <GesturePhysicsEngine.h>
#include <WindowAutoGesture.h>
檔案位置在 C:\Program Files\Windows Mobile 6 SDK\PocketPC\Include\Armv4i
2.2 WM_GESTURE 訊息
以下程式碼為取得 WM_GESTURE 訊息的基礎程式,且透過 switch 方式,當取得 Gestures 訊息時所對應哪些處理。
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
LRESULT CALLBACK WndProca(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL fHandled = FALSE;
GESTUREINFO gi = {sizeof(gi)};
// Go get the gesture - will return FALSE if the gesture engine is not present in the system.
if (TKGetGestureInfo(reinterpret_cast<HGESTUREINFO>(lParam), &gi))
{
switch(wParam)
{
case GID_HOLD:
break;
case GID_SELECT:
break;
case GID_DOUBLESELECT:
break;
case GID_PAN:
break;
}
if (!fHandled)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
return 0;
}
2.3 Gesture Metrics Sample
以下影片是執行 Gesture Metrics Sample 範例程式,一開始觸控螢幕,並且保持不動,產生 GID_HOLD 訊息,接著單擊螢幕,產生 GID_SELECT 訊息,最後雙擊螢幕,產生 GID_DOUBLESELECT訊息。
在此範例程式,使用 WM_GESTURE 中的 GID_SELECT, GID_HOLD, GID_SELECT 和 GID_DOUBLESELECT訊息,當使用者觸控螢幕時,有三種情形
(1) GID_HOLD
使用者觸控螢幕時,於 OnLButtonDown 事件中,StartTimer(hWnd, ID_HOLD_TIMER); 於 WndProc 接收 WM_GESTURE 訊息,當訊息為 GID_HOLD 時,則 KillTimers(hWnd); // ID_HOLD_TIMER,並於畫面顯示 HOLD DETECTED
(2) GID_SELECT
於 WndProc 接收 WM_GESTURE 訊息,當訊息為 GID_SELECT 時,透過 TKGetGestureInfo 取得結構與細節,顯示 SELECT DETECTED,StartTimer(hWnd, ID_DOUBLESELECT_TIMER);
(3) GID_DOUBLESELECT
於 WndProc 接收 WM_GESTURE 訊息,當訊息為 GID_DOUBLESELECT 時 檢測到是GID_DOUBLESELECT,
則 KillTimers(hWnd); // ID_DOUBLESELECT_TIMER,並顯示 DOUBLE SELECT DETECTED。
2.4 Physics Engine Sample
以下影片是執行 Physics Engine Sample 範例程式,使用者按住後,進行拖放的動作,則圖片跟著移動,並且垂直與水平捲軸跟著移動。
主要接收訊息的部份,寫在以下 FUNCTION 中,藉由接收 WM_GESTURE 中的 GID_PAN、GID_SCROLL 訊息,做捲軸相對應處理。
// FUNCTION: ProcessGesture(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Handles processing of WM_GESTURE command.
//
BOOL ProcessGesture(HWND hWnd, UINT, WPARAM wParam, LPARAM lParam)
{
BOOL fHandled = FALSE;
GESTUREINFO gi = {sizeof(gi)};
// Go get the gesture - will return FALSE if the gesture engine is not present in the system.
if (TKGetGestureInfo(reinterpret_cast<HGESTUREINFO>(lParam), &gi))
{
static POINT ptsLast = {0};
switch (wParam)
{
case GID_PAN:
{
if (g_fAnimating)
{
// Stop any running animations
SnapBackToFrame(hWnd);
}
if (GF_BEGIN == (gi.dwFlags & GF_BEGIN))
{
ptsLast.x = gi.ptsLocation.x;
ptsLast.y = gi.ptsLocation.y;
}f
else
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
ScrollWindowEx(hWnd,
gi.ptsLocation.x - ptsLast.x,
gi.ptsLocation.y - ptsLast.y,
&rcClient, &rcClient, NULL, NULL, SW_INVALIDATE);
g_nXPos -= gi.ptsLocation.x - ptsLast.x;
g_nYPos -= gi.ptsLocation.y - ptsLast.y;
ptsLast.x = gi.ptsLocation.x;
ptsLast.y = gi.ptsLocation.y;
SetScrollPos(hWnd, SB_VERT, g_nYPos, TRUE);
SetScrollPos(hWnd, SB_HORZ, g_nXPos, TRUE);
UpdateWindow(hWnd);
}
fHandled = TRUE;
}
break;
case GID_SCROLL:
{
ProcessEndPan( hWnd,
(int)GID_SCROLL_VELOCITY(gi.ullArguments),
(int)GID_SCROLL_ANGLE(gi.ullArguments),
&gi);
fHandled = TRUE;
}
break;
case GID_END:
{
ProcessEndPan( hWnd,
0,0,
&gi);
// GID_BEGIN/GID_END should always be send to DefGestureProc
}
break;
}
}
return fHandled;
}
3. 結語
本文初步介紹 Gestures API 的使用,以及展示 Gestures API Sample Code,建議想要學習的人,把 GID 相關訊息的部份,設定中斷點,了解程式的運作過程。此外,也可以自己寫程式,透過接收滑鼠事件來定義各種手勢,可以參考這兩篇文章。
Adding Mouse Gesture Support to .NET Windows Applications
Implementing Gestures recognition in .NET Compact Framework
4. 參考
Using Gestures in Windows Mobile 6.5
Let’s Talk About Touch (Part1)
Gesture APIs-Furthering Windows Mobile 6.5 Touch Gesture Framework