65.9K
CodeProject 正在变化。 阅读更多。
Home

为开发人员开发桌面自然用户界面 API

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012年10月23日

CPOL

14分钟阅读

viewsIcon

17082

为开发人员开发桌面自然用户界面 API

虽然计算机和技术的演进以惊人的速度发展,但用户体验在很大程度上一直局限于并依赖于可用的输入设备。自从个人计算机问世以来,我们看到了从依赖键盘的命令行界面(CLI)到由鼠标的引入而产生的图形用户界面(GUI),再到如今随着触摸屏的出现而被称为自然用户界面(NUI)的最新形式的演变。

触摸和笔式输入自20世纪90年代初就已存在(我第一台笔式计算机是1993年的Windows* 3.1机器),但它一直成本高昂且在开发者通常面向的设备上不可靠。如今情况已不再如此。智能手机、平板电脑,以及现在的笔记本电脑,如Ultrabook™设备,都标配了触摸功能。

今天,开发者和设计师必须考虑这些新功能,并构建他们的应用程序,使其至少能够感知,并最好地针对触摸优先或仅触摸的体验进行开发。在本文中,我们将探讨为触摸和NUI进行设计将如何影响创建优秀软件的设计和构建决策,并探讨将现有应用程序迁移到触摸环境需要什么。

多点触控的考量

当我们考虑触摸时,我们需要了解其作为输入设备的局限性。鼠标是一种像素级的精确选择设备,它允许用户在屏幕上移动一个指针的表示,并带有按钮,用户可以通过单击这些像素来实现特定的操作。

触摸是一种新的输入选项,它存在某些限制,例如手指的大小和能够捕捉触摸动作的屏幕技术类型。因此,为了在这个环境中有效运行,我们需要提供更大的目标区域和更多的目标之间间距。这必然限制了我们可以在屏幕上放置多少内容,而了解设备的符合人体工程学的设计有助于确定最常用控件的放置位置。

对于Ultrabook,它配备了键盘和触摸板(类似于鼠标)以及触摸功能,我们需要了解用户通常如何使用它来完成工作。虽然平板电脑可能完全脱离键盘,但Ultrabook以最有效的方式利用触摸,利用捏合和拉伸手势来缩放内容,通过简单的滑动或拖动来移动内容,以及通过简单的点击来选择操作。

页面上控件的放置需要反映设备预期的使用模式。当用户需要越过键盘进行操作时,最容易触摸的目标将位于屏幕边缘附近,顶部和侧面——在布局控件时,这些是需要牢记的要点。

触摸

幸运的是,在Windows中,操作系统负责响应触摸事件,并提供一个可以免费供应用程序使用的鼠标活动转换。这包括将点击转换为单击,将拖动转换为单击和拖动等。要使您的应用程序能够感知触摸,您需要订阅触摸和拖动事件,并在代码中处理它们。

为触摸设计的一些挑战包括,Windows早期版本中常见的、为鼠标和键盘优化的控件,如功能区和菜单,由于其大小和位置,用触摸操作可能很困难。例如,如果菜单使用悬停(当用户将鼠标指针移到控件上时触发的事件),触摸就没有相应的事件,这导致菜单在仅触摸环境中变得无用。

虽然为早期版本构建的应用程序对触摸的可能性有不同程度的认识,但现在既然它已成为现实,我们就需要调整并与技术协同工作。以下是一些方法以及适应触摸环境的策略。

按钮

按钮响应单击事件,因此开发者无需做太多就可以让它们与触摸配合使用。但是,开发者需要考虑到不支持悬停,因此如果渲染效果(如在鼠标悬停时高亮显示按钮)则触摸时不会有此效果。

主要考虑因素是确保按钮足够大以支持触摸。因此,确保它们至少有23 x 23像素大小,越大越好。其次,在控件之间留出足够的边距,以免触摸一个控件被误认为是另一个控件的操作。

菜单

菜单自图形用户界面(GUI)诞生以来就一直存在,甚至在DOS时代就已经存在,那时会显示一个选择列表,用户可以从中进行选择。菜单的优点在于它们提供了一种简单分层的方式来组织用户可能需要的命令。挑战在于,随着应用程序功能的增加,菜单中隐藏的命令数量会变得笨拙。

在传统的非触摸Windows中,菜单项之间的标准距离很小,但使用触摸时,您需要确保有更大的边距,以尽量减少意外选择错误命令的可能性。

在Windows Presentation Foundation(WPF)等标记语言中,您可以重写菜单的ControlTemplate来指定您希望它如何行为。

工具栏

此控件在WinForms中被引入,作为一种在程序中添加图标来表示操作的方式。要使用它,开发者将一个ToolStrip 控件添加到其窗体,然后将控件添加到容器中。控件类型包括按钮、组合框、文本命令等。通常图标的大小相当小,控件之间的间距也很小。

在WinForms和WPF中,您可以通过设置ToolStrip的 ImageScalingSize,然后更改项目之间的边距来增加工具栏上控件的默认大小和边距。在本文稍后的示例中,我们将向您展示如何解决这些问题。

Ribbon

自Windows Vista*和Office 2007推出以来,功能区(Ribbon)一直被视为一个优点也是一个弊端。从基于菜单的环境转向全图形化的、带标签的界面,对于许多用户来说是一个巨大的转变。功能区的优点在于它提供了一种丰富的组织结构,用于添加控件,并且不受限于单一的图标行。图标的大小从小到大不等,它们之间的间距更加灵活。如今,功能区已成为许多核心应用程序的一部分,包括Windows资源管理器、画图等。

下拉列表和组合框

幸运的是,支持下拉列表无需太多操作,因为它们支持点击显示选择列表。与菜单一样,您应该注意列表中项目之间的间距。

平台选择

构建应用程序涉及技术决策,这些决策应考虑软件的生命周期。Windows提供了几种选项,各有优缺点,这些选项决定了用于构建应用程序的语言和框架。

这些通常包括三类技术:**基于标记**的,它们依赖HTML或XAML来描述界面,并且不为用于创建它们的工具所专有;**基于窗体**的,开发者使用提供界面设计界面的工具和功能代码文件;以及**原生应用程序**,其中代码在运行时构建界面。

技术选择通常取决于可用的技术人才。如果您有Visual Basic*开发者,那么您很可能会使用WinForms进行开发。如果应用程序需要速度和性能,您通常会看到原生代码,如C或C++(尽管随着新的Windows Runtime或WinRT的出现,这种情况将有所改变)。

WinForms

自Visual Basic 3.0发布以来,Microsoft工具一直支持基于窗体的编程范例,开发者从一个窗体开始,向其中添加控件,然后编写代码来支持所需行为。这种称为WinForms的方法使用用户界面的二进制表示,但支持一些使其能够快速开发的功能。

WinForms在Windows 8中继续得到支持,从触摸和Ultrabook的角度来看,使应用程序支持触摸的关键领域是确保控件具有最小尺寸并留有间距。

“少即是多”的原则在这里适用,最好是设计/开发团队花时间重新审视用户界面,以减少和简化设计。

一个例子——将LOB应用程序从WinForms迁移到触摸优化

提出的场景是将一个为旧版Windows构建的典型业务线(LOB)应用程序移植到Windows 8触摸感知桌面。使用Northwind场景(从 http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=23654 下载数据库架构),我们有一个HR应用程序,它提供员工信息,包括照片。我们将应用程序从.NET 2.0迁移到当前框架,并在此过程中解决问题。

开始——.NET 2.0中的WinForms应用程序

下面是我们旅程起点的屏幕截图;在这个界面中我们发现了哪些问题?至少我们需要使应用程序可触摸,即在仅触摸环境中运行。此时的问题包括:

  • 工具栏上按钮的大小……太小
  • 控件之间的间距
  • 2012年奖金的旋转控件
  • 鼠标悬停在图片上以获取当前照片路径
  • 拖放更新员工照片

步骤1——可触摸

在本轮项目中,我们将做最少必要的工作,使应用程序能够在仅触摸环境中运行。这将包括一些代码更改和一些UI调整。首先,我们将应用程序升级到最新的.NET 4.5框架,以启用操作系统提供的触摸感知和手势功能。通过这样做,我们不仅获得了将手势和拖动转换为鼠标事件的功能,还获得了应用程序上次更新以来添加的编程功能的访问权限,包括新的数据访问模式、LINQ、对新异步编码功能的支持、更好的线程等,这些我们将在后面详细介绍。

接下来,我们查看小于可触摸指南(23 x 23像素(6毫米))的控件,并根据需要调整属性。这包括调整工具栏的图像缩放尺寸,并在按钮之间添加更大的边距。

为此,我们修改了工具栏的属性,将 ImageScalingSize 设置为 23, 23,然后遍历菜单项集合,为每个项目添加 Padding(内边距) 2, 2, 2, 2

接下来,我们用适合触摸的控件替换旋转控件。有一些第三方控件可供选择,但标准的按钮通过一些代码同样有效。

最后,我们处理图片悬停问题,以便在触摸时可以看到图片路径。我们同样有两种方法,但都涉及向 MouseDown 事件(触摸或点击事件符合条件并会转换为鼠标按下)添加一些代码。最简单的方法可能是为图片控件添加一个 MouseDown 事件处理程序,并添加使 photoTextBox 可见的的代码。只需一行代码。

        private void photoPictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            photoPathTextBox.Visible = true;
        }

现在我们的应用程序已经可触摸了,请在您的Ultrabook上运行它来确认。请注意,工具栏上的图标变大了,奖励按钮已用绿色高亮显示,触摸图片会显示图片路径。

此时,工具栏图标更大,间距也更大,我们用易于触摸的控件替换了旋转控件。我们可能仍然需要考虑屏幕上的信息量,但至少它可以在触摸环境中使用了。

接下来的步骤包括重新审视屏幕内容,优先排序和删除不太相关的字段,并查看在哪里可以简化和减少。这是应用程序迁移下一阶段的目标,我们将添加功能区并迁移到一个基于标记的解决方案,在这种情况下是使用XAML的WPF。

触摸支持

接下来,我们来看看使应用程序“触摸支持”需要什么。正如我们之前定义的,这个级别的感知包括使常用控件至少为40 x 40像素(10毫米),以处理标准手势和基本多点触控操作。

对于我们的场景,我们选择集成功能区来支持触摸环境。因此,我们将应用程序迁移到WPF,并利用标记语言特性使其更容易支持触摸要求。例如,我们可以使用样式来定位控件类型,以确保它们足够大并且有足够的边距。

在添加一个数据集以连接到数据库并在“员工”页面上布局控件后,我们会得到类似这样的结果

Windows 8和WPF 4.5将功能区作为一等控件,但您需要通过“选择项”添加工具到工具箱,并添加相关的菜单项。

基于标记的应用程序——XAML

自.NET 4.0发布以来,触摸感知的控件和将触摸事件转换为鼠标行为的事件使得在应用程序中启用触摸变得更加容易。例如,带有可滚动区域的ListBox将接收并处理平移手势。

要使您的应用程序“亮起来”,您可以选择利用使控件感知拖动操作,通过将 IsManipulationEnabled 属性设置为 True。然后,在窗口本身中,您可以为 ManipulationStartedManipulationDelta 添加事件处理程序。为了获得更大的真实感,您可以通过添加 ManipulationInertiaStarting 的事件处理程序来启用惯性效果,并在处理程序中添加代码来模拟摩擦或重力。

例如,在一个基本的WPF应用程序中,您可能有以下XAML标记

<Window x:Class="WPFSimpleTouch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        ManipulationStarting="Window_ManipulationStarting_1"
        ManipulationDelta="Window_ManipulationDelta_1"
        ManipulationInertiaStarting="Window_ManipulationInertiaStarting_1"
        >
    <Grid>
        <Image IsManipulationEnabled="True" Source="myImage.png" Height="100" />
    </Grid>
</Window>

这个简化的WPF应用程序标记包含一个简单的网格控件,其中包含一个图像。下面是结果应用程序的渲染(假设myImage.png是Intel徽标,并且已包含在应用程序源代码的根目录下)。

在窗口声明中,我们使用了XAML来注册三个拖动和惯性事件,包括 ManipulationStarting(我们指定受影响的控件)、 ManipulationDelta(在手势操作期间触发)和 ManipulationInertiaStarting(我们可以添加逻辑来模拟摩擦和重力,在用户结束手势时加入阻尼效果)。下面的基本实现

    private void Window_ManipulationStarting_1(object sender, ManipulationStartingEventArgs e)
    {
        e.ManipulationContainer = this;
        e.Handled = true;
    }

    private void Window_ManipulationDelta_1(object sender, ManipulationDeltaEventArgs e)
    {
        Image imgToMove = e.OriginalSource as Image;
        Matrix myMatrix = ((MatrixTransform)imgToMove.RenderTransform).Matrix;

        myMatrix.RotateAt(e.DeltaManipulation.Rotation, e.ManipulationOrigin.X, 
  e.ManipulationOrigin.Y);
        myMatrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y, 
 e.ManipulationOrigin.X, e.ManipulationOrigin.Y);
        myMatrix.Translate(e.DeltaManipulation.Translation.X, 
 e.DeltaManipulation.Translation.Y);

        imgToMove.RenderTransform = new MatrixTransform(myMatrix);
        Rect myRec = new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);
        Rect myBounds = imgToMove.RenderTransform.TransformBounds ( 
                            new Rect(imgToMove.RenderSize));
        if (e.IsInertial && !myRec.Contains(myBounds))
            e.Complete();
        e.Handled = true;
    }

    private void Window_ManipulationInertiaStarting_1(object sender, 
ManipulationInertiaStartingEventArgs e)
    {
        e.TranslationBehavior.DesiredDeceleration = 1.0 * 96.0 / (1000.0 * 1000.0);
        e.ExpansionBehavior.DesiredDeceleration = 0.1 * 96 / (1000.0 * 1000.0);
        e.RotationBehavior.DesiredDeceleration = 720 / (1000.0 * 1000.0);

        e.Handled = true;
    }

结果应用程序允许用户使用触摸手势,如触摸拖动、捏合和缩放来操作屏幕上的图像。您可以从 http://bit.ly/bqtwpfst 下载示例代码。

原生应用程序

在原生应用程序类软件中,开发者通常使用C或C++等低级语言,并编写需要感知在该级别触发事件的代码。要使应用程序能够感知触摸,您需要注册应用程序以接收Windows触摸消息,然后添加代码来处理这些消息。默认情况下,您的应用程序将接收WM_GESTURE消息,但如果您调用RegisterTouchWindow,您将能够处理更低级别的输入。

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;

	...
	RegisterTouchWindow(hWnd, 0);

       ...
}

您的应用程序直接处理WM_TOUCH消息,但与鼠标不同,触摸只生成一个WM_TOUCH消息。没有WM_TOUCH_DOWN、WM_TOUCH_MOVE或WM_TOUCH_UP。这与托管代码不同,因为原始触摸事件被组合起来模拟鼠标事件。您在WndProc方法中处理WM_TOUCH消息,在那里您可以调用GetTouchInputInfo来获取触摸点的状态。这会返回一个TOUCHINPUT结构数组,每个结构代表一个手指触摸点。

手势的处理方式类似,您需要处理WM_GESTURENOTIFY消息,以告知操作系统您希望在程序中启用哪些手势。默认情况下,除旋转和简单的单指平移外的手势都是启用的。在注册了您想要支持的手势后,您就可以处理WM_GESTURE消息了。

MSDN*示例 http://msdn.microsoft.com/en-us/library/dd562174(VS.85).aspx 演示了如何注册触摸和手势,并展示了惯性如何为触摸环境增添行为。

摘要

构建触摸感知应用程序是一项直接的任务,开发者需要学习的支持量并不大。最低限度,尽可能将应用程序升级到新框架,注意控件的大小和间距,并通过注册和处理触摸事件来启用Ultrabook上的新功能。

参考文献

© . All rights reserved.