织梦CMS - 轻松建站从此开始!

罗索

Windows Mobile 6.5 手势识别API(Gesture)

落鹤生 发布于 2010-07-20 20:10 点击:次 
在WM6.5没有出来之前,自己也实现过手势识 别的引擎,包括方向识别、画圈识别。微软为了大家不至于对他失去信心,还是在6.5上了点点东西。 对于开发者来说,其实只要添加了Gesture API 和widget。
TAG:

一、背景:

还是不得不提及iPhone的伟大创造性工作,用手势识别来操作手机,特别是对于滚动条,想想之前是何等的痛苦,拿着触摸 板,在那个只有几个像素的滚动条上又是拉又是点的。在WM6.5没有出来之前,自己也实现过手势识 别的引擎,包括方向识别、画圈识别。微软为了大家不至于对他失去信心,还是在6.5上了点点东西。 对于开发者来说,其实只要添加了Gesture API 和widget。 最近做个新的项目,需要在WM6.5上实现,需要用到Gesture API,自己学习了下,随便写下来,自己做个备忘。

二、轨迹识别:
当对屏幕有操作时,微软会发送WM_GESTURE消息。wParam是Gesture ID, lParam指向HGESTUREINFO,通过GetGestureInfo得到GESTUREINFO。

BOOL GetGestureInfo(

        HGESTUREINFO hGestureInfo,
        PGESTUREINFO pGestureInfo
);
GESTUREINFO 定义

typedef struct tagGESTUREINFO {

    UINT cbSize;
    DWORD dwFlags;

    DWORD dwID;         // Gesture command ID

        HWND hwndTarget;
    POINTS ptsLocation;
    DWORD dwInstanceID;    // not use
    DWORD dwSequenceID;
    ULONGLONG ullArguments; //

    UINT cbExtraArguments; // 扩 展参数buffer大小

} GESTUREINFO, *PGESTUREINFO;

微软定义了一个Gesture ID
ID

宏 定义

意 义

1
GID_BEGIN

按 下时发送,与GID_END成对出现

2
GID_END

抬 起,与GID_BEGIN成对出现

4
GID_PAN

移 动的

5
GID_SCROLL

只 有当加速滑动的时候,会产生GID_SCROLL

9
GID_HOLD

按 住不动一定时间

10
GID_SELECT

单 击,并马上弹起

11
GID_DOUBLESELECT

双 击

在GID_SCROLL、GID_HOLD、GID_SELECT、GID_DOUBLESELECT这 四个为连续的数值,说明四个状态时互质的。很容易明白滚动、选择、双击、长按是不可能同时发生的。

其中GID_SCROLL是相对复杂一些的,滚动我们不仅要知道当前坐标,还需要知道方向、速度和角度。微软在ullArguments保持了这三个信息,并定义了三个宏来从参数ullArguments中 得到。

GESTUREINFO gi = {sizeof(gi)};

if (GetGestureInfo(reinterpret_cast<HGESTUREINFO>(lParam), &gi))

{
    static POINT ptsLast = {0};
    switch (wParam)
    {
        case GID_PAN:
        break;
        case GID_SCROLL:
            {
                // 速度

                int iVelocity = (int)GID_SCROLL_VELOCITY(gi.ullArguments);

                // 角度

                int iAngle = (int)GID_SCROLL_ANGLE(gi.ullArguments);

                // 方向

                int iDirection = (int)GID_SCROLL_DIRECTION(gi.ullArguments);

            }
        break;
    }
}
角度的值是从0到65535,代表0到2PI。定义了四个方向

#define ARG_SCROLL_NONE

#define ARG_SCROLL_RIGHT

#define ARG_SCROLL_UP

#define ARG_SCROLL_LEFT

#define ARG_SCROLL_DOWN

通过上面的介绍,我们了解了如何 获取手势轨迹。

下面是微软Gesture API,部分API SDK中没有公 布,只给OEM公布的。

Function
Description

CloseGestureInfoHandle

This function cleans up any gesture handle that is not processed by DefWindowProc.

DisableGestures

设置指定窗体或者进程Gesture command ID无效

EnableGestures

设置指定窗体或者进程Gesture command ID有效

Gesture

This function enables asynchronous recognizers to produce gesture messages.

GetAnimateMessageInfo

Retrieves the animation message associated with flicks or pans for window auto gestures.

GetGestureExtraArguments
得到扩展参数
GetGestureInfo

接收到WM_GESTURE时 消息,获取GESTUREINFO信息

GetWindowAutoGesture

Returns the current settings for a window's flick and pan gestures.

QueryGestures

得到指定窗体或者进程所支持的Gesture ID

RegisterGesture
自定义Gesture

RegisterDefaultGestureHandler

接收未处理的WM_GESTURE消 息

SetWindowAutoGesture

自动处理Gesture消 息

 
三、滑动

一般情况下在GID_PAN和GID_ SCROLL处理滑动。GID_PAN处理拖动,GDI_SCROLL处理滑动。GID_PAN时,只要 处理每次位移是多少就可以了。然后刷新窗体。GID_SCROLL需要调用

CreatePhysicsEngine来设置负的加速度,使其最终停下来。然后再设置一个TIMER去, 在TIMER处理函数中用QueryPhysicsEngine去 得到移动的相对位移。然后计算,重新刷新。

SDK参考代 码:

HRESULT hr = S_OK;

//int nYExtendedPan = 0;

//int nXExtendedPan = 0;

PHYSICSENGINEINIT initState = {sizeof(initState)};

RECT rctClient = {0};

 
initState.dwEngineType              = 0;
initState.dwFlags                   = 0;

initState.lInitialVelocity          = -nTransitionSpeed;    // 设置初始速度

initState.dwInitialAngle            = nTransitionAngle; // 设置角度

initState.bXAxisMovementMode        = PHYSICSENGINE_MOVEMENT_MODE_DECELERATE;
initState.bYAxisMovementMode        = PHYSICSENGINE_MOVEMENT_MODE_DECELERATE;
initState.bXAxisBoundaryMode        = PHYSICSENGINE_BOUNDARY_MODE_RUBBERBAND;
initState.bYAxisBoundaryMode        = PHYSICSENGINE_BOUNDARY_MODE_RUBBERBAND;

GetClientRect(hwnd, &rctClient);

initState.rcBoundary.left           = 0;

initState.rcBoundary.right          = rctClient.right + g_nMaxXExtent; // 设置边界

initState.rcBoundary.top            = 0;

initState.rcBoundary.bottom         = rctClient.bottom + g_nMaxYExtent; // 设置边界

initState.sizeView.cx               = rctClient.right;
initState.sizeView.cy               = rctClient.bottom;
initState.ptInitialPosition.x       = g_nXPos;
initState.ptInitialPosition.y       = g_nYPos;
initState.sizeItem.cx               = 1;      
initState.sizeItem.cy               = 1;      
 

// create the physics engine and store it

if (SUCCEEDED(CreatePhysicsEngine(&initState, &g_hPhysicsEngine)))

{
    g_fAnimating = true; // we are now animating
    // Setup the timer
    g_uTimerId = SetTimer( hwnd,
        GESTURE_ANIMATION_TIMER_ID,
        20,
        AnimationTimerProc);
}
 

OK,终于写完 了,有什么不对的地方,请指正。

(jinhaijian)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201007/9855.html]
本文出处:CSDN博客 作者:jinhaijian
顶一下
(0)
0%
踩一下
(1)
100%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容