[Windows Mobile]Gestures API 擷取使用者的手勢

  • 13101
  • 0
  • 2013-04-15

在 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 中,範例的位置請參考下圖

image

 

 

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

image

 

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)

一起来学习Windows Mobile 6.5

Gesture APIs-Furthering Windows Mobile 6.5 Touch Gesture Framework