概述
Windows 7 支持用户通过手指接触来管理应用程序,无需使用触笔。这种新的手势功能允许多个输入 事件在不同的指向位置上同时发生,它还支持复杂的场景,比如通过十个手指或多个并发用户来管理应用 程序。但是,要实现这些功能,我们必须调整应用程序
目标
在本次动手实验中,您将学习如何管理手势事件,包括:
• 理解使用手势 事件操作对象的含义
• 查看多点触控硬件是否存在及其就绪情况
• 从手势 Windows 消息中提取信息
系统要求
您必须拥有以下工具才能完成本实验:
• Microsoft Visual Studio 2010 Beta 2(或更高版本)
• Windows 7
• 多点触控硬件设备
简介
要创建一个多点触控驱动的应用程序,您应 该将触控功能设计到应用程序的用户界面中。例如,您使用的控件应该相对较大,以支持手指而不是鼠标 或触笔。除此之外,您还可以考虑 3 中不同的方法:
1.依赖触控功能已经是现有 Win32 控件的 一部分。例如,Win32 控件已经支持一些触控功能,比如无需额外编码即可滚动应用程序。尝试使用手指 滚动您正在阅读的文档。
2.阅读并处理低水平的触控事件,创建您自己的高级触控处理界面。这 是用户可以同时操作的多个复杂滑块,以及“Piano”或 MS 等应用程序所使用的方法。例如 ,运行 MS Paint,从库中选择绘制工具并使用四个手指进行绘制(如果硬件允许):
3.使用新的多点触控手势让应用程序获得触控事件,以支持缩放、旋转、平移等自定义操作, 无需读取和操作原始触控事件。这是本动手实验使用的方法。
关于多点触控手势演示
多点触控手势演示展示一个简单的窗口,其中包含一个矩形,可以使用 多点触控手势对它进行修改。在 Sources\MFC_GestureDemoSource 文件夹中,您可以找到一个 Starter 文件夹,其中包含本实验所需的一些文件,以及本实验的一个完成版本,位于 Final 文件夹中。
该应用程序通过与绘制的矩形交互来响应多点触控手势输入。矩形响应以下手势:
平移
要 平移图像,将一个或两个手指放在应用程序窗口中,并向您期望的方向拖动。确保两个手指之间留有空间 ,以便触控界面将其视为不同的接触点。
查看原图(大图)
旋转
使用两个手指接触矩形并在一个圆中旋转手指。
缩放
用两个手 指接触屏幕,将它们分离或靠拢。
双指点击
使用 两个手指同时点击可以切换红色矩形内的对角线开关状态。
双指交替点击
按住一个手指,然后使用另一个手指点击,并移开第一个手指可以更改矩形的颜色。
练习 1:构建多点触控手势应用程序
任务 1 –使用 Application Wizard 创建 MFC 应用程序
1.启动 Visual Studio 2010
2.新建一个 MFC 应用程序项目,将其命名为 TouchGestureDemo 并按 OK
3.在 MFC Application Wizard 的 Application Type 对话框中,选择 Single Document。为了保持应用程序简单 ,根据以下屏幕截图在 MFC Application Wizard 的各种对话框中选择(或不选择)选项,然后在每个对 话框后按 Next > 。
4.继续单击 Next,直到最后在 Generated Classes 向导对话框中单击 Finish:
任务 2 –检查多点触控硬件是否存在及就绪情况
1.我们正在构建的应用程序需要支持触 控的硬件,因此我们需要在应用程序中查看这一点。在 TouchGestureDemo.cpp 中,在 CTouchGestureDemoApp::InitInstance() 后添加以下代码:
C++
BYTE digitizerStatus = (BYTE) GetSystemMetrics(SM_DIGITIZER);
if ((digitizerStatus & (0x80 + 0x40)) == 0) //Stack Ready + MultiTouch
{
AfxMessageBox (L"No touch input is currently available.");
return false;
}
BYTE nInputs = (BYTE) GetSystemMetrics(SM_MAXIMUMTOUCHES);
CString str;
str.Format(L"Touch input available with %d touch points.", nInputs);
AfxMessageBox(str);
return true;
2.您可以看到,除了查看触控可用性 以外,我们还可以发现硬件支持的触控输入数量。
3.编译并运行。
4.根据机器上触控输入 的数量,您应该看到类似以下屏幕截图的输出:
任务 3 –向项 目添加绘制对象源和头文件并绘制矩形
在 Starter 文件夹中,您将找到两个文件: DrawingObject.h 和 DrawingObject.cpp。将它们复制到项目文件夹下并使用“Add Existing item…”将其添加到项目中。
1.将一个 #include DrawingObject.h 行添 加到 of stdafx.h 头文件尾部的 #include 之后:
C++
#include "DrawingObject.h"
2.将以下 protected 成员变量定义 添加到 ChildView.h 中。这是主绘制对象:
C++
// The drawing object
CDrawingObject m_drawingObject;
3.此外,将以下 protected 成员变量添加 到 ChildView.h 中。有了它们才能够支持定位和调整绘制对象的大小:
C++
// Needed for drawing object position and size calculations
double m_dblZoomRatioStart;
double m_dblZoomRatioTotal;
CPoint m_ptCenter;
4.要绘制矩形,将 ChildView.cpp 中的以下行添加 到 CChildCiew::OnPaint()末尾:
C++
m_drawingObject.Paint(&dc);
5.重新 调整窗口时,我们希望将绘制矩形重置为默认位置和大小(如果移出客户端区域边界,可以让其更容易查 找),因此我们添加一个 WM_SIZE 消息处理程序。
6.切换到 Class View(在 Solution Explorer 窗口底部切换)并选择 CChildView 类。
7.在 Properties 页面中,转到 Messages 属 性表(按 按钮)并导航到 WM_SIZE,然后从下拉框中添加 OnSize() 消息处理程序:
8.在 CChildView::OnSize() 处理程序中(TODO 注释之后),添加以下代码以重置绘制对象:
C++
m_drawingObject.ResetObject(cx, cy);
9.编译并运行。
10.响应有关触控输入可用性的初始消息后,窗口中央应该出现一个红色矩形:
任务 4 –立即开始触控!
现在可以开始触控了!默认情况下,支持触控的系统会 向目标窗口提供 WM_GESTURE 消息。这类似于鼠标和键盘消息。系统使用低级触控输入事件并为我们计算 得到的手势。MFC 提供许多重写的消息处理程序,它们可以接受每种手势类型,每个程序都返回一个 Boolean 值。如果应用程序可以处理手势输入,则相应的重写方法应该返回 TRUE;否则返回 FALSE。
1.让我们继续!将以下 5 个 protected 方法定义添加到 ChildView.h 中:
C++
// Overrides
protected:
// Gesture handlers
virtual BOOL OnGestureZoom (CPoint ptCenter, long lDelta);
virtual BOOL OnGesturePan(CPoint ptFrom, CPoint ptTo);
virtual BOOL OnGestureRotate(CPoint ptCenter, double dblAngle);
virtual BOOL OnGesturePressAndTap(CPoint ptFirstFinger, long lDelta);
virtual BOOL OnGestureTwoFingerTap(CPoint ptCenter);
2.从 Pan Gesture 处理程序处开始,将以下代码添加到 ChildView.cpp 中:
C++
BOOL CChildView::OnGesturePan(CPoint ptFrom, CPoint ptTo)
{
int dx = ptTo.x - ptFrom.x;
int dy = ptTo.y - ptFrom.y;
if (dx != 0 || dy != 0)
{
m_drawingObject.Move(dx, dy);
RedrawWindow();
}
return true;
}
3.现在轮到 Zoom Gesture 实现了,将以下代码添加到 ChildView.cpp 中:
C++
BOOL CChildView::OnGestureZoom(CPoint ptCenter, long lDelta)
{
if ((m_pCurrentGestureInfo->dwFlags & GF_BEGIN) == GF_BEGIN)
{
m_dblZoomRatioStart = m_dblZoomRatioTotal = lDelta;
}
else if (lDelta != 0)
{
m_dblZoomRatioTotal += lDelta;
double zoomFactor = (double) m_dblZoomRatioTotal / m_dblZoomRatioStart;
m_drawingObject.Zoom(zoomFactor, ptCenter.x, ptCenter.y);
m_dblZoomRatioStart = m_dblZoomRatioTotal;
RedrawWindow();
}
return true;
}
4.将 Rotate Gesture 处理程序添加到 ChildView.cpp 中:
C++
BOOL CChildView::OnGestureRotate(CPoint ptCenter, double dblAngle)
{
if ((m_pCurrentGestureInfo->dwFlags & GF_BEGIN) == GF_BEGIN)
{
// Make the first center, the rotating one
m_ptCenter = ptCenter;
}
else if (dblAngle != 0.)
{
m_drawingObject.Rotate(dblAngle * PI / 100.0, m_ptCenter.x, m_ptCenter.y);
RedrawWindow();
}
return true;
}
5.类似地,将“按下并点击”和“双指点 击”手势的处理程序添加到 ChildView.cpp 中:
C++
BOOL CChildView::OnGesturePressAndTap(CPoint ptFirstFinger, long lDelta)
{
if ((m_pCurrentGestureInfo->dwFlags & GF_BEGIN) != 0)
{
m_drawingObject.ShiftColor();
RedrawWindow();
}
return true;
}
BOOL CChildView::OnGestureTwoFingerTap(CPoint ptCenter)
{
m_drawingObject.TogleDrawDiagonals();
RedrawWindow ();
return true;
}
6.编译并运行。
7.尝试使用两个手指移动矩形;您可以看到举行会跟随您的手指移动。
8.尝试在不接触矩形的情况下移动它;我们在窗口的空区域中触摸屏幕。它动了!我们不执行“ 单击测试”来查看触控位置是否位于矩形边界内部。我们会响应整个客户端区域内的任何手势。
9.尝试使用其他手势:旋转、放缩、双指点击和双指交替点击。
任务 5 –存在一个 Bug!
1.尝试旋转矩形。发生了什么?默认情况下,窗口接受旋转之外的所有手势。但是,我们可 以配置触控引擎来提供我们想要的任何手势。MFC 提供了一个有用的类 CGestureConfig,它支持您自定 义窗口手势功能,比如缩放、平移或旋转。
2.将以下成员变量添加到 ChildView.h 中:
C++
// Fields
protected:
// Holds gesture configuration
CGestureConfig m_gestureConfig;
3.切换到 Class View 并选择 CChildView 类。在 Properties 页面中 ,转到 Messages 属性表并导航到 WM_CREATE,然后从下拉框中添加 OnCreate() 消息处理程序:
4.在 CChildView::OnCreate() 处理程序中(TODO 注释之后),添加以下代码以接受旋转手势:
C++
GetGestureConfig(&m_gestureConfig);
// Only rotation is not enabled by default
m_gestureConfig.EnableRotate();
SetGestureConfig(&m_gestureConfig);
5.编译并运行。
6. 尝试旋转矩形。成功了!干得好!
7.以下是一个实际的演示屏幕截图,应用了“旋转 ”、“按下并点击”和“双指点击”这些手势:
总结
在本实验中,您学习了如何使用触控手势消息来通过 MFC 在屏幕上操作对象。您还学习了如何确 定支持多点触控硬件的可用性,以及如何轻松提取手势消息信息并对其采取操作。