在Windows Mobile中使用手势 - [Using Gestures in Windows Mobile 6.5]

 原文为:MSDN的 Using Gestures in Windows Mobile 6.5

 

 Using Gestures in Windows Mobile 6.5

      1. Touch Gestures

      2. Gesture Reference (DTK)

           2.1 Gesture Constants (DTK)

           2.2 Gesture Functions (DTK)

                 2.2.1 TKGetAnimateMessageInfo

                 2.2.2 TKGetGestureExtraArguments

                 2.2.3 TKGetGestureInfo

                 2.2.4 TKGetGestureMetrics

                 2.2.5 TKGetWindowAutoGesture

                 2.2.6 TKSetWindowAutoGesture

           2.3 Gesture Macros (DTK)

                 2.3.1 GID_ROTATE_ANGLE_FROM_ARGUMENT

                 2.3.2 GID_ROTATE_ANGLE_TO_ARGUMENT

                 2.3.3 GID_SCROLL_ANGLE

                 2.3.4 GID_SCROLL_DIRECTION

                 2.3.5 GID_SCROLL_VELOCITY

           2.4 Gesture Messages (DTK)

                 2.4.1 WM_GESTURE

           2.5 Gesture Structures (DTK)

                 2.5.1 ANIMATEMESSAGEINFO

                 2.5.2 GESTUREINFO

                 2.5.3 GESTUREMETRICS

                 2.5.4 WAGINFO

      3. Physics Engine Overview

      4. Physics Engine Reference (DTK)

           4.1 Physics Engine Functions (DTK)

                 4.1.1 TKCreatePhysicsEngine

                 4.1.2 TKDestroyPhysicsEngine

                 4.1.3 TKQueryPhysicsEngine

                 4.1.4 TKSetPhysicsEngineUserTime

          4.2 Physics Engine Constants

          4.3 Physics Engine Structures

                 4.3.1 PHYSICSENGINEINIT

                 4.3.2 PHYSICSENGINESTATE  

 


 Using Gestures in Windows Mobile 6.5

它包含针对触摸事件、手势和手势动画的表述。

触摸APIs分成两部分:手势APIs,用于管理触摸输入;手势物理引擎(the Gesture Physics Engine)APIs,用于控制显示区字段如何对用户触摸做出反应。

触摸函数、消息和结构体和鼠标共享,因为应用程序把光笔事件作为鼠标左键点击处理。更多触摸参考信息,参见Mouse Reference 。

本文的讨论包括:

Touch Gestures:介绍窗口手势并且讨论怎样在你的应用程序中实现手势接口。

Gesture Reference (DTK):该API允许程序监控和响应触摸输入。

Physics Engine Overview:介绍物理引擎以及在实现手势接口时如何使用物理引擎。

Physics Engine Reference (DTK):该API控制屏幕如何响应触摸输入以及如何使你的应用程序象shell(操作系统外壳)一样响应触摸。 

 

  Touch Gestures

该段介绍触摸手势,你可以用手指或光笔队按照某种手势对屏幕上的控件或对象做短距离有向运动。大多数手势是单独的点击,它相当于一次手指按下(WM_LBUTTONDOWN)和一次手指抬起(WM_LBUTTONUP)事件对。双击是个例外,它相当于连续两次手指按下和手指抬起事件对。手势的识别根据:手指按下和抬起事件加上方向、位置和由手势识别器计算出的速度。Windows Mobile支持5种手势: 

手势

描述

Tap

代表一次鼠标左键点击。 当手机按下和抬起事件发生在一个已定义的时间段和距离内时,程序只接收一次GID_SELECT 手势消息。在WM_LBUTTONDOWN 事件后和GID_SELECT 消息前可能会有几次WM_MOUSEMOVE消息。

Double Tap

代表2次鼠标左键点击。  当手指抬起事件发生在一个已定义的时间段和距离内时,程序接收一次GID_DOUBLESELECT 手势消息。

Hold

用户按下并一直按住屏幕代表鼠标右键点击。 当手指按下并一直按住超过了一个预定义的时间段,而且这段时间内按下的点都在一个指定的距离范围内时,程序会只接收一次GID_HOLD消息。 一旦手指抬起或在按住时间临界值后,程序会接收到一个GID_END 消息然后紧接着收到一个GID_HOLD 消息。

Flick

用户移动手指划过屏幕来启动每个像素移动。 如果移动足够快,滚动在手指抬起后仍会继续。 当手指移动结束抬起后,程序会接收一次GID_SCROLL 手势消息。 Flick经常发生在Pan之后(即一个或多个GID_PAN 手势消息,紧接着是GID_SCROLL ,然后是GID_END 消息)。

Pan

用户按下并按住屏幕,然后在任意方向拖动手指来代表鼠标移动事件。 位置发生改变时程序接收一个或多个GID_PAN 手势消息,当手指抬起时接收一个GID_END 消息。鼠标消息和手势消息交错出现。

更多关于GID_*手势的消息参见:GESTUREINFO

手势识别引擎的系统构架由一个手势识别状态机和现有的触摸事件发送程序构成。触摸事件由触摸屏驱动(Touch Screen Drivers)发送到状态机。当手势被识别后,一个手势窗口消息将被发送到目标进程消息队列。

注意调用SetCapture将会为手势改变目标窗口。

手势事件通常总是在手指抬起前发送以便接收者能够调用TKGetGestureInfo处理手势消息并通过鼠标抬起事件来取消任何动作。

Window Auto Gestures:

自动手势使窗口内的控件和程序能够自动地处理Flick和Pan手势。可以通过 TKSetWindowAutoGesture 和 TKGetWindowAutoGesture 函数来控制手势处理。自动手势使动画消息被发送到窗口过程来管理和Flicks和Pans相关的动画。可以调用TKGetAnimateMessageInfo函数来取到那些消息。

 

  Gesture Reference (DTK)

 窗口自动手势能够使窗口中的内容自动响应Flick和Pan手势滚动。

本部分包括:

Gesture Functions (DTK):提供触摸手势相关函数的概述。

Gesture Structures (DTK):提供触摸手势相关结构体的概述

Gesture Macros (DTK):提供触摸手势相关宏的概述

Gesture Constants (DTK):提供触摸手势相关常量的概述

Gesture Messages (DTK):提供触摸手势相关消息的概述

 

  Gesture Constants (DTK)

下面的常量为在 GESTUREINFO 结构体中使用的命令。

名称

描述

GID_BEGIN

1

包含标记每个手势开始点的坐标。当触摸屏幕时发送。

GID_END

2

包含标记每个手势结束点的坐标。当手指或光笔从屏幕抬起后发送。

当接收该命令后,GESTUREINFO  ullArguments 字段总是被设置为0

GID_PAN

4

an在当用户在窗口上按下而且在任意方向移动(该过程手指保持和屏幕一直接触)时发生。 识别引擎发送GID_PAN消息,该消息包含手势的开始点和当前点。在手指或光笔从窗口屏幕抬起前,会为每次窗口移动消息发送一次GID_PAN消息。GID_END 用来标记Pan移动的结束。

程序根据连续两次Pan手势间的差异计算移动增量。

如果设置GF_INERTIA标志,GESTUREINFO  ullArguments 值和GID_SCROLL 时一样。

GID_SCROLL

8

用户按下窗口(或者也可能在窗口上Pan),然后手指或光标在任意方向迅速移动,当移动结束抬起手指或光笔前发生Scroll。识别引擎在Flick手势后发送GID_SCROLL消息。GID_SCROLL会被发送到接收当前触摸过程第一个手势消息的窗口,可能是一个Pan消息或一个Hold消息。GESTUREINFO ullArguments 字段包含关于角度、方向和Flick速度的信息。

主要的方向常量值如下:

  ARG_SCROLL_NONE

  ARG_SCROLL_RIGHT

  ARG_SCROLL_UP

  ARG_SCROLL_LEFT

  ARG_SCROLL_DOWN

当设备旋转时,手势自动调整匹配旋转。

Flick的角度值以从065535范围值计量。

可以使用下面的宏从GID_SCROLL手势消息的ullArguments 字段来提取出角度、方向和速度。

  GID_SCROLL_ANGLE

  GID_SCROLL_DIRECTION

  GID_SCROLL_VELOCITY

可以使用下面的宏在角度和弧度间相互转换。

  GID_ROTATE_ANGLE_TO_ARGUMENT

  GID_ROTATE_ANGLE_FROM_ARGUMENT

GID_HOLD

9

用户按下窗口并保持手指或光笔按住超过指定的超时时间,此时发生Hold

识别引擎发送一个GID_HOLD消息,然后当手指或光笔抬起时发送一个GID_END 消息。

Hold 手势后可能会跟着Pan移动(移动过程会生成许多GID_PAN消息),但是,在生成GID_PAN消息后绝不会再生成GID_HOLD消息

GID_SELECT

10

当用户用手指或光笔敲击屏幕,敲击过程时间小于系统指定的SELECT超时时间,此时发生SelectGESTUREINFO ullArguments 字段不会在该命令中使用。

GID_DOUBLESELECT

11

当用户用手指或光笔敲击两次屏幕,两次敲击过程时间小于系统指定的DOUBLESELECT超时时间,此时发生Double SelectDOUBLESELECT超时时间是指连续两次鼠标抬起事件发生的间隔时间。

GESTUREINFO ullArguments 字段不会在该命令中使用。

  

  Gesture Functions (DTK)

 下表显示支持手势的函数及其用途。

函数

描述

TKGetAnimateMessageInfo

该函数取回由窗口自动手势发送的所有动画消息的移动信息。

TKGetGestureExtraArguments

该函数用来获得手势消息配备的额外信息。

TKGetGestureInfo

该函数使用传递到WM_GESTURE消息的触摸手势的内容填充GESTUREINFO结构。

TKGetGestureMetrics

用来给指定手势取回触摸手势识别的尺寸(比如,触摸手势引擎使用的距离和时间公差)

TKGetWindowAutoGesture

为指定窗口句柄取回当前自动手势配置设置。

TKSetWindowAutoGesture

为指定窗口指定自动手势配置设置。

 

  TKGetAnimateMessageInfo

该函数取回由窗口自动手势发送的所有动画消息的移动信息。该特性使窗口中的内容响应Flick和Pan手势自动滚动。要自动处理手势滚动,目标窗口一定要包含WS_VSCROLL 或 WS_HSCROLL(或者两者都包含)类型并且设置正确的范围。

该函数在WindowAutoGesture.h头文件中。

程序调用TKSetWindowAutoGesture并指定WAGIF_OWNERANIMATE 标志后,当内容动起来时,消息被发送至窗口过程。程序应该为每个动画消息调用该函数来取回正确的值。

声明:

BOOL TKGetAnimateMessageInfo(
                             HWND hWnd,
                             WPARAM wParam,
                             LPARAM lParam,
                             LPANIMATEMESSAGEINFO pAnimateMessageInfo
                             );

参数:

hWnd:目标窗口句柄。

wParam、lParam:动画消息参数。

pAnimateMessageInfo:指向 ANIMATEMESSAGEINFO 结构指针,该结构由移动信息组成。

返回值:

成功返回TRUE;失败返回FALSE。调用GetLastError获取扩展错误信息。

备注:

必须调用TKSetWindowAutoGesture函数并且在目标窗口收到任何动画消息前为窗口设置WAGIF_OWNERANIMATE 标志。


  TKGetGestureExtraArguments

该函数用来获得手势消息配备的额外信息,在Gesture.h头文件中。

声明:

BOOL TKGetGestureExtraArguments 
    HGESTUREINFO hGestureInfo
,
    UINT cbExtraArguments
,
    PBYTE pExtraArguments
);

参数:

hGestureInfo:[in]手势信息句柄,HGESTUREINFO,从 WM_GESTURE 窗口消息的lparam 参数获得。

cbExtraArguments: [in]客户端传递的缓冲大小,用来取回手势详细内容,从GESTUREINFO的cbExtraArguments 值获得。

pExtraArguments:[out]指向大小为cbExtraArguments 的BYTE数组的指针,用来接收而外信息。

返回值:

成功返回TRUE;失败返回FALSE。调用GetLastError取回更多信息。下表显示GetLastError可能获取的返回值。

描述

ERROR_NO_DATA

没有数据返回。也可能是由于没有足够缓冲造成。

ERROR_INVALID_PARAMETER

如果pExtraArguments为空或hGestureInfo 无效。

备注:

客户端程序检测GESTUREINFO 的cbExtraArguments 值来决定是否需要调用TKGetGestureExtraArguments。

程序通常先检查cbExtraArguments 值,如果值为非0,将填充BYTES数组。客户端程序需要按照文档描述那样为某个手势消息解析该内存缓冲。 

 

  TKGetGestureInfo

该函数使用传递到WM_GESTURE消息的触摸手势的内容填充GESTUREINFO结构,该函数在Gesture.h头文件中。

声明:

BOOL TKGetGestureInfo(
                      HGESTUREINFO hGestureInfo,
                      PGESTUREINFO pGestureInfo
                      );

参数

hGestureInfo:GESTUREINFO结构句柄。

pGestureInfo:指向GESTUREINFO结构的指针,该结构由传递到WM_GESTURE消息的触摸手势的内容填充。结构的cbSize值必须在调用函数前正确地初始化。

备注

根据手势ID,程序直接翻译 WM_GESTURE 消息的参数,或者传递参数给GetGestureInfo,如下代码:

GESTUREINFO gi;
memset(&gi, 0, sizeof(gi));
gi.cbSize = sizeof(GESTUREINFO);
if (TKGetGestureInfo((HGESTUREINFO)lParam, &gi))
{
    // Handle gesture indicated by wParam
}
else
{
    // Error handling.
} 

 

  TKGetGestureMetrics

用来给指定手势取回触摸手势识别的尺寸(比如,触摸手势引擎使用的距离和时间公差)。该函数在Gesture.h头文件中。

声明:

BOOL TKGetGestureMetrics(
                         LPGESTUREMETRICS lpGestureMetricsInfo
                         );

参数:

lpGestureMetricsInfo:[in/out]GESTUREMETRICS结构指针。该值不能为NULL。调用者必须设置dwID 值为下面的一个:

  GID_PAN

  GID_ SCROLL

  GID_HOLD

  GID_SELECT

  GID_DOUBLESELECT

所有其他的字段会按照需要根据dwID的值重写。

调用该函数时cbSize字段需要被设置正确的值。

返回值:

成功返回TRUE;失败返回FALSE。调用GetLastError获取扩展错误信息。

成功返回TRUE;失败返回FALSE。

 

  TKGetWindowAutoGesture

为指定窗口句柄取回当前自动手势配置设置。窗口自动手势能够使窗口中的内容自动响应Flick和Pan手势滚动。

要自动处理手势滚动,目标窗口一定要包含WS_VSCROLL 或 WS_HSCROLL(或者两者都包含)类型并且设置正确的范围。

该函数包含在WindowAutoGesture.h头文件中。

声明:

BOOL TKGetWindowAutoGesture(
                            HWND hWnd
                            LPWAGINFO lpAutoGestureInfo
                            );

参数:

hWnd:[in]目标窗口句柄。

lpAutoGestureInfo:[out] 指向WAGINFO结构的指针。

返回值:

成功返回TRUE;失败返回FALSE。调用GetLastError获取扩展错误信息。

备注:

在使用 TKSetWindowAutoGesture 或 TKGetWindowAutoGesture函数前必须要设置目标窗口的滚动类型。

 

  TKSetWindowAutoGesture

为指定窗口指定自动手势配置设置。窗口自动手势能够使窗口中的内容自动响应Flick和Pan手势滚动。

要自动处理手势滚动,目标窗口一定要包含WS_VSCROLL 或 WS_HSCROLL(或者两者都包含)类型并且设置正确的范围。

该函数包含在WindowAutoGesture.h头文件中。

声明:

BOOL TKSetWindowAutoGesture(
                            HWND hWnd
                            LPWAGINFO lpAutoGestureInfo
                            );

参数:

hWnd:[in]目标窗口句柄。

lpAutoGestureInfo:[in]指向WAGINFO结构的指针。

返回值:

成功返回TRUE;失败返回FALSE。调用GetLastError获取扩展错误信息。

备注:

在使用 TKSetWindowAutoGesture 或 TKGetWindowAutoGesture函数前必须要设置目标窗口的滚动类型。

必须在lpAutoGestureInfo的dwflags成员中包含WAGIF_OWNERANIMATE 标志。 

SDK提供的例子:

void ConfigureWAG(HWND hWnd)
{
    WAGINFO wagInfo 
= {sizeof(WAGINFO)};

    wagInfo
.dwFlags WAGIF_OWNERANIMATE 
        (g_fHScrollable WAGIF_HSCROLLABLE : 0) | 
        (g_fVScrollable WAGIF_VSCROLLABLE : 0) | 
        (g_fAllowPAN    ? 0 : WAGIF_IGNOREPAN) |
        (g_fAllowSCROLL ? 0 : WAGIF_IGNORESCROLL) |
        (g_fLockAxis    ? WAGIF_LOCKAXES : 0);

    wagInfo
.nOwnerAnimateMessage = (g_fUseWMSCroll ? 0 : WM_PRIVATEANIMATEMSG);
    wagInfo
.nItemHeight g_nVertItemSize;
    wagInfo
.nItemWidth g_nHorizItemSize;
    wagInfo
.bHorizontalExtent = (BYTE)g_nHorizExtent;
    wagInfo
.bVerticalExtent = (BYTE)g_nVertExtent;

    if 
(!TKSetWindowAutoGesture(hWnd, &wagInfo))
    {
        MessageBox
hWnd,
            TEXT
("Failure from SetWindowAutoGesture()"),
            TEXT
("Error"), 
            MB_OK
);
    }

    // Make sure the item sizes are at least 1 for now - i.e. calculated size is 1 pixel
    g_nHorizItemSize 
max(1,g_nHorizItemSize);
    g_nVertItemSize 
max(1,g_nVertItemSize);
}

 

  Gesture Macros (DTK)

下表显示支持手势的宏和用途。

名称

描述

GID_ROTATE_ANGLE_TO_ARGUMENT

从原始角度转换为弧度。

GID_ROTATE_ANGLE_FROM_ARGUMENT

从弧度转换为原始角度。

GID_SCROLL_ANGLE

ullArguments 字段提取Flick手势角度。

GID_SCROLL_DIRECTION

ullArguments 字段提取Flick手势方向。

GID_SCROLL_VELOCITY

ullArguments 字段提取Flick手势速度。

 

GID_ROTATE_ANGLE_FROM_ARGUMENT

       GID_ROTATE_ANGLE_TO_ARGUMENT

使用下面的宏在原始角度和弧度之间转换。该宏在Gesture.h头文件中。

声明:

GID_ROTATE_ANGLE_FROM_ARGUMENT(Arg)
GID_ROTATE_ANGLE_TO_ARGUMENT(Arg)

Arg为要转换参数。

在头文件定义为:

/*
* Gesture argument helpers
*   - Angle should be a double in the range of -2pi to +2pi
*   - Argument should be an unsigned 16-bit value
*/
#define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_)     ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65536.0))
#define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_)   ((((double)(_arg_) / 65536.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265)

备注:

To convert the raw angle to radians, divide the raw angle by 32768, then multiply that value by 360/32768. 32768 units represent one full circle.

(要转换原始角度到弧度,原始角度除以32768,然后再乘以(360/32768)。32768 代表一个整圆。)

原始角度和当前系统方向有关(设备是横向还是纵向并不可知)。当系统旋转,手势方向和角度自动调整匹配旋转。 

 

  GID_SCROLL_ANGLE

         GID_SCROLL_DIRECTION

         GID_SCROLL_VELOCITY

这些宏分别从ullArguments 字段提取Flick手势的角度、方向和速度。该宏在Gesture.h头文件中。

声明: 

GID_SCROLL_ANGLE(Arg)
GID_SCROLL_DIRECTION(Arg)
GID_SCROLL_VELOCITY(Arg)

 Arg为要转换的原始角度。

在头文件定义为:

// Macros to extract scroll angles directions and direction
#define GID_SCROLL_ANGLE(x)              ((LONG)(HIWORD(((ULONGLONG)(x)) >> 32) & 0xFFF0))
#define GID_SCROLL_DIRECTION(x)          ((LONG)(HIWORD(((ULONGLONG)(x)) >> 32) & 0x000F))
#define GID_SCROLL_VELOCITY(x)           ((LONG)((short)(LOWORD(((ULONGLONG)(x)) >> 32))))

备注:

原始角度和当前系统方向有关(设备是横向还是纵向并不可知)。当系统旋转,手势方向和角度自动调整匹配旋转。

 

  Gesture Messages (DTK)

下表显示支持手势的消息和用途。

名称

说明

WM_GESTURE    

WM_GESTURE消息被发送至某个窗口过程代表一个手势已经发送或正在发送中。

 

  WM_GESTURE

WM_GESTURE消息被发送至某个窗口过程代表一个手势已经发送或在Pan情况下,代表正在发送中。

WM_GESTURE消息可以从WndProc使用SendMessage(), SendMessageTimeout() 或 SendNotifyMessage() APIs同步发送。

注意WM_GESTURE消息不能从WndProc 使用PostMessage or PostThreadMessage异步发送。

窗口过程可以调用TKGetGestureInfo来检测手势的状态。

窗口通过WndProc 函数来接收消息。

语法:

WM_GESTURE
    WPARAM wParam
    LPARAM lParam

参数:

wParam:包含手势命令ID。

lParam:包含手势命令的HGESTUREINFO 句柄。

返回值:

如果程序处理了手势,它返回一个非0值。如果程序没有处理手势,应该把它传递给DefWindowProc ,返回值为DefWindowProc 的返回值。

备注:

根据手势ID,你要决定程序是否自己处理该手势或着是否传递该手势到DefWindowProc。GID_BEGIN 和 GID_END应该总被传给DefWindowProc。如果程序处理手势,那么它就不能把消息传递给默认窗口过程。

下面的代码显示如何根据手势ID来处理该手势。

GESTUREINFO gi;
memset(&gi, 0, sizeof(gi));
gi.cbSize = sizeof(GESTUREINFO);
if (GetGestureInfo((HGESTUREINFO)lParam, &gi))
{
    // Handle gesture indicated by wParam or gi.dwID
}
else
{
    // Error handling
}

 

HGESTUREINFO 句柄在WndProc调用前被创建,窗口过程返回时销毁。记住,程序不能为以后使用该句柄而保存HGESTUREINFO句柄。WM_GESTURE的lParam值在窗口过程外毫无意义,因为HGESTUREINFO 句柄直到DispatchMessage发送消息到窗口过程时