Windows Mobile-一个新时代的开始
作者:Jim Wilson
相关技术:Windows Mobile,Visual Studio .NET 2003
难度等级:★★★☆☆
读者类型:移动设备开发人员,.NET开发人员
相关技术:Windows Mobile,Visual Studio .NET 2003
[导读]
- Whidbey新的移动功能简介和Windows Mobile的发展趋势
- GUI开发涉及相关方面的更新
- SQL Server CE 介绍及其改进
- Windows Mobile开发体验以及其它功能
[编者注:本文是“You Can Take It with You”专栏的第一部分,因此本文中提到的专栏都指这个专栏,我们在未来的几期内也会陆续介绍专栏的相关内容]
我们向何处去
作为企业开发人员,我们处理大量的数据、复杂的用户交互、困难的用户个性化和极具挑战性的业务流程。我们面临的问题是找到走出可用的类、工具和技术的迷宫的方法、以及将它们应用于创建有意义的移动解决方案的方式,从而可以有效地处理我们的数据、用户和流程。
在撰写本文时,我的目标是从我称之为“实用编程”的角度解决企业开发人员在移动领域面对的各种问题。在我看来,实用编程意味着对解决方案可以提供的类、工具和技术进行考察。这也意味着我们常常必须将各种类、工具和技术看作是相互关联的,并且可以采用一定的方式将它们组合成整个解决方案的一部分。简而言之,实用编程着眼于将技术作为一种达到最终目标的手段,而不是将技术本身作为最终目标。
在未来的几个月中,我们将介绍企业开发人员在创建移动应用程序时面对的大量问题。我们将用几个月的时间详细介绍如何构建特定的解决方案,在其他的几个月中,我们将介绍一些有帮助的工具,而在另外的一些时间里,我们将深入探讨特别有用的类或库。无论是哪个主题,目标都是相同的:共享有意义的信息将有助于Windows Mobile平台构建企业应用程序的开发人员。
Whidbey和Windows Mobile
我发现决定从何处开始新专栏的第一部分有点困难。后来我想到,由于Whidbey的移动功能促使我开辟了这个专栏,所以我们可以首先简要地介绍一些在我看来最值得对Whidbey进行的添加和修改,它们会影响移动应用程序的开发。
注:本文是在包含Windows Mobile增强的Whidbey测试版实际发布之前撰写的,基于测试版前的信息。这些功能都没有最终确定,并且可能会在目前、测试版的发布和最终产品的发布之间发生改变。在使用任何一种功能之前,一定要查看产品文档。
下面是一些我喜欢的Whidbey移动功能,没有采用特别的顺序。未来有太多的东西需要深入研究,不过,请别离开,因为在未来的日子里,我们将详细地介绍这些功能。
GUI
让我们面对现实吧:图形用户界面(GUI)大量的用户体验都集中在这里。虽然当前版本的Microsoft .NET框架精简版提供了Microsoft Windows Forms库,并且是比较好的一个版本,但它还是有或多或少的限制。不过,随着Whidbey的来临,这种情况正在发生改变。
对多屏幕方向和分辨率的支持
多年以来,所有的基于Microsoft Windows Mobile的Pocket PC都有共同的纵向分辨率为240x320的显示布局。这种分辨率不再是事实。最新一代Pocket PC设备现在具有各种屏幕性能,其中包括对纵向和横向模式的支持(有一些甚至是直角的)。一些设备甚至支持480x640的屏幕分辨率,这种分辨率与最初的桌面计算机的分辨率相同。Whidbey已经升级为支持所有这些显示,从而允许您构建能够充分利用目标设备功能的应用程序。应用程序甚至可以在运行时响应显示设置中的改变。
增强的控件行为
构建必须使用不同的分辨率和方向的应用程序提出了以前并不存在的挑战。令人欣慰的是,Whidbey通过添加对控件停靠和锚定的支持为我们提供了非常必要的帮助。停靠允许控件直接附加到窗体的一个边缘。锚定允许将控件的位置设置为与一个或多个边缘相对。停靠或锚定的控件自动维持它们的相对位置,并且在需要时根据父窗体的大小的变化调整大小。
当然,.NET框架精简版Service Pack 1和2中添加的许多控件功能也包括在Whidbey中,例如Tabbing支持、键盘事件和ForeColor/BackColor支持。
所见即所得(WYSIWYG)窗体设计器
那些从未使用过Whidbey前的智能设备应用程序的人可能想知道“所见即所得”的妙处是什么。而那些已经使用过Whidbey前的智能设备应用程序的人则对这个问题知道得一清二楚。真正让人感到失望的是,Visual Studio.NET 2003中的字体和控件大小与实际设备中显示的不同。简单地说,这个问题已经解决了。
这一个改变将足够了,但是还有一些。窗体设计器现在支持各种Pocket PC显示模式,其中包括纵向、横向和直角。模式在设计时可以修改,因此可以确保应用程序在以任何模式运行的设备上看起来都不错。
而如果这还不够,窗体设计器现在支持外观(skin)。借助于外观,您就可以真切地看到相对于实际的设备窗体看起来是什么样子的,如图1所示。
图1 带有外观的Whidbey智能设备设计器。
SQL Server CE
当构建.NET框架精简版应用程序时,Microsoft SQL Server 2000 Windows CE版本(SQL Server CE)是我们的本地数据存储。下一代SQL Server CE(代号为Laguna)是向前迈出的一大步。下面是一些增强功能。
可更新、可滚动的游标
当操作大量数据时,我有时发现使用.NET框架精简版中的SQL Server CE有点困难。问题在于.NET框架精简版数据库类只允许用户有限地利用SQL Server CE的本地特性。记住,SQL Server CE完全运行在设备本地,并且完全支持滚动和就地更新功能,而这些功能在.NET框架精简版中仍然只是受到有限支持。这个问题最终通过添加SqlCeResultSet类解决了。通过使用这个类,.NET框架精简版应用程序可以滚动、更新和直接绑定到SQL Server CE中的数据。当需要这些功能时,不必再担负DataSet类的高开销。我认为这是Whidbey中的最重要的增强。
多用户访问
闻如其名,SQL Server CE现在支持多用户访问。对多个应用程序访问和修改SQL Server CE数据库有充分的支持。该数据库通过锁升级现在完全支持行和页面的锁定。虽然改动比较小,但是这个改变对许多开发人员产生的最值得注意的影响是,在启动使用该数据库的应用程序之前,他们不必再在SQL Server CE Query Analyzer中关闭他们的数据库。
桌面管理和访问
微软已经为SQL Server CE添加了桌面计算机支持。可以从下一代SQL Server Enterprise Manager中查看、管理SQL Server CE数据库并且与其进行交互。
您还可以编写能够读取和创建SQL Server CE数据库的应用程序。现在不要担心微软是否有一些异乎寻常的计划来使SQL Server CE成为一个桌面计算机数据库。从事实情况来看,没有什么可以走得更远。提供此功能的目的是进行测试和数据库生产。在许多情况下,一些桌面计算机或服务器应用程序需要创建SQL Server CE数据库,以便智能设备应用程序能够访问该应用程序的数据。此处的这些API用于解析这种特定的情况。
开发体验
Visual Studio .NET 2003和.NET 框架精简版极大地改善了设备开发人员的体验。与其他的设备开发工具相比,它更加稳定且更易于使用。设备开发要像构建桌面应用程序那么容易还有很长的一段路要走,但Whidbey让我们朝着这个方向又迈出了一大步。
改进的调试
设备调试总是十分缓慢。其中一个原因是移动设备和桌面计算机之间的连接速度相对较慢(大多数情况下是串行或USB连接),但这并不是造成调试缓慢的唯一原因。造成调试缓慢的另一个重要因素是许多调试功能是在设备上进行的,它只占用桌面计算机中的可用内存和CPU时间的一部分。那么,有什么办法解决吗?
要是将更多的调试功能转移到桌面计算机上进行呢?为此,Whidbey设备调试器已经进行了彻底的重新设计。新的调试器可以使原本必须在设备上完成的工作转移到在调试器中进行。现在,大部分的调试行为实际上是在桌面计算机上执行,这样,调试速度就明显加快了,调试器的响应也更加迅速了。
更好的模拟器
对模拟器所做的改进有很多,在此,我真的无法将它们逐一罗列出来。我将重点介绍一些我认为是最佳的改进。
该模拟器现在支持作为一个Microsoft ActiveSync客户端进行连接,这样就使它更像是一个真正的设备。
该模拟器支持存储多个模拟器映像。这一存储允许您设置多个模拟器配置(设置、已安装的程序等等),并在需要时恢复它们,这样就简化了测试和错误恢复。通过使用当前的Visual Studio .NET 2003模拟器,我们只能有一个保存的映像,而如果模拟器由于某种原因需要重置,则必须完全重新安装该映像。
该模拟器支持将桌面计算机文件夹映射为存储卡。这一支持使桌面计算机和模拟器之间的数据共享变得容易得多。它同时也使公共数据跨越各个模拟器映像变得容易。
这个新的模拟器也支持在各种屏幕分辨率和方向(纵向和横向)之间进行切换。
C++项目
为了构建针对移动设备的应用程序,除了需要使用.NET框架精简版之外,有时还需要我们使用C++。迄今为止,这一要求意味着我们不得不使用两个独立的集成开发环境:用于编写.NET框架精简版代码的Visual Studio .NET 2003和用于编写C++代码的eMbedded Visual C++ IDE。通过添加对移动设备C++项目的支持,Whidbey解决了这个问题。
通过Whidbey,我们现在可以在用于开发.NET框架精简版项目相同的Visual Studio环境中创建、编辑和调试针对移动设备的C++项目。我们不再需要一个独立的eMbedded Visual C++ IDE,并且现在可以进行所有的移动设备开发,其中包含单个IDE中的托管项目(.NET Compact Framework)和非托管项目(C++)。
改进的Win32和COM Interop
.NET框架精简版显著改进了Microsoft Win32和COM Interop。许多常见的封送问题(例如,传递嵌入的字符串或带有嵌入的引用类型的类)都已经解决了。现在,我们还可以支持COM Interop。.NET框架精简版可以调用COM对象,并且只需要做很少的工作,而COM对象可以调用.NET框架精简版对象。.NET框架精简版运行库现在可以采用与完整的.NET Framework大致相同的方式进行托管。这方面的许多细节我们将在下一期的专题中进行讨论。
改进的智能感知(IntelliSense)
由于需要保持与桌面计算机一致的对象模型,并且还要考虑平台功能的特定现状,所以在某些情况下,.NET框架精简版类所公开的继承属性和方法对于调用不是合法的。通常将这些情况称之为“继承的但不是受支持的”。遗憾的是,在Visual Studio.NET 2003中,这些无效的方法依然出现在Microsoft IntelliSense 技术功能中,并且常常导致应用程序接收到运行时错误。
Whidbey将那些“继承但不受支持的(inherited-but-not-supported)”方法和属性从智能感知功能中移除,从而修正了这些错误。这些“继承但不受支持的”的方法和属性在.NET框架精简版程序集中,因此仍有可能调用它们(并得到错误),但至少智能感知不会将它们显示出来。
其他重要功能
我们已经看到了许多非常好的功能,但还有好多没有看到。随着时间的推移,我们将接触许多不同的新功能,但这里我将要介绍一些我特别喜欢的其他功能。
Smartphone支持
Smartphone被视为Whidbey的第一个类成员,它完全支持创建基于Microsoft Windows Mobile的Smartphone应用程序(目前仅限于.NET框架精简版版本1的功能)。窗体设计器和IntelliSense能够自动地进行自适应,以便适当地为Smartphone进行工作,并且只公开那些受支持的控件、类和方法。
对新的Whidbey语言功能的支持
.NET框架精简版不仅提供对自身的改进,而且还包括对来自Whidbey的更丰富的语言功能的支持。对于Microsoft Visual Basic.NET开发人员来说,新的“My.*”命名空间是受支持的。C#开发人员可以期望支持泛型、匿名方法和迭代程序。
通知代理(Notification Broker)
通知代理是一个非常值得关注的的Windows Mobile功能增强,它不是Whidbey的功能,而是未来的Windows Mobile平台本身的功能。通知代理用作可能在设备上发生的几乎每个事件的集中式发布和订阅机制。它允许应用程序对重要事件的兴趣进行注册,其中包括网络状态的改变、动态同步的改变、来电和短消息服务消息的到达。当事件发生时,应用程序会自动得到通知。其优点在于体系结构是完全可扩展和集中式的,从而为所有这些事件提供了通用的编程模型。
小结
这就结束了我们的第一期。我希望您像我一样将这些新的Whidbey设备功能作为未来的Windows Mobile开发的灵魂。我们即将迎来全新的一天。
在未来的几个月中,我们将更详细地讨论我们在这里介绍的许多主题。我们还将介绍一些更一般的移动开发主题,这些主题与Whidbey无关。我希望您等着我。
现在,我需要回到准备我的MDC演示稿的工作中。希望在那里看到你们中的许多人;要不,我们下个月见。
使用 .NET 框架精简版开发Smartphone应用程序
http://editblog.csdn.net/msdncolumn/archive/2005/01/04/1190.aspx
作者:Andreas Sj?str?m、Christian Forsberg
相关技术:Windows Mobile? 2003-based Smartphone、Visual Studio .NET 2003、Microsoft .NET Compact Framework 1.0
难度等级:★★★☆☆
读者类型:手机应用开发人员、.NET开发人员
[导读]
- Smartphone应用程序开发简介
- 用户界面设计以及应用程序存储
- 在应用程序中调用XML Web服务
- 介绍程序打包及分发
- 企业级应用案例介绍
简介
本文目的是概述使用Microsoft .NET框架精简版的Microsoft Windows Mobile 2003 for Smartphone的几个要素。作为.NET系列中的一员,.NET框架精简版拓宽了平台和开发人员对新设备和外形因素的认识。熟悉.NET框架和Microsoft Visual Studio .NET的开发人员现在就可以着手构建针对于智能电话的应用程序了。
总体上,本文提供了以下几个领域的相关信息:
- 开发电话应用程序:Smartphone应用程序开发的要素
- 用户界面设计:可用的控件和用法的最佳实践
- 应用程序数据存储:管理XML文件和注册表
- 使用XML Web服务:发挥XML Web服务
- 为分发而打包:分发Smartphone应用程序
- 企业级应用程序方案:Smartphone应用程序可以为企业提供有价值的相关方案
开发电话应用程序
无论开发人员开发应用程序时的目标平台是什么,有一些共同的设计和开发技能是必需的。这些技能包括定义并了解方案和用例、构建并贯彻系统体系结构、系统地定义并解决问题等方面的能力。从这个角度看,开发Smartphone的应用程序与开发其他任何平台的应用程序并无不同之处。外形因素已变得微乎其微,从大型机、服务器、桌面计算机、PDA,一路走来,现在通过Windows Mobile for Smartphone,最终实现了在大小如移动电话上的应用。针对Smartphone的Windows Mobile软件的软件开发平台,有许多特性是与其较大型的同辈平台共有的。
不过,要成功地设计和开发电话应用程序,不仅需要认可通常的开发准则,还必须考虑使用一组Smartphone特定的开发准则,以开发出有用、易用且高效率的电话应用程序:
- Smartphone的主要设计目标是要成为一种优秀的电话,因此它与其他许多设备使用的设置和场合不同。应用程序需要是迅捷、稳定并且高度容错的。需要定义关于异常处理的明确策略并跨整个应用程序实现。
- 与PDA(如Pocket PC)相比,Smartphone的屏幕尺寸更加宝贵。小型屏幕要求用户界面的设计要更简洁、更有效率。
- Smartphone没有触摸屏。在设计用户界面和输入机制这二者时,都需要考虑小型硬件按键。应用程序导航应该具备预测能力且直观的,而且要求的击键次数越少越好。实际上,大多数电话应用程序都设计成主要是为信息查看提供强大的支持,并且需要的输入越少越好。
- Smartphone的固有连接,包括短信和互联网标准支持,都应该是应用程序设计最基本的组成部分。XML Web服务作为.NET框架精简版的一个核心元素实施,而短信功能可以通过使用平台调用在平台本身利用。
- 针对Smartphone的Windows Mobile软件包括多种内置应用程序,如“联系人”、“日历”和“收件箱”等等。集成应用程序设计(将适当的应用程序集成在一起)可以为用户增加更多的综合价值。
这些是在针对Smartphone的Windows Mobile软件的应用程序设计和开发中应该考虑的关键事项。
用户界面设计
如果您是在本机(或非托管)开发环境中工作,如使用Microsoft eMbedded Visual C++开发应用程序,您会注意到托管代码可以为您做许多事。举例来说,当进行用户界面设计时,最显著的改变是无需一直跟踪控件以及其他用户界面元素的ID号:可以按名称来引用它们。不必处理指针以及清除已分配的内存。
用户界面基础知识
作为入门,让我们看一个熟悉的示例,"Hello World"窗体:
图1 示例窗体
这个窗体是根据包含在Smartphone 2003 SDK中的Smartphone界面指南而设计的。当诸如“应该是”和“应该有”这样的表达在本章后面的文字中出现时,表明是对设计指南的参考。如果您在指南中找不到答案,那么了解如何解决用户界面设计问题的最好方法永远是:查看其他现有的Smartphone应用程序。
因为在一个窗体中的每行上都应该有一个控件,所以在第一行添加Label控件,在第二行添加文本框控件。每个控件的高度应该是22个像素,并且窗体在顶部和底部需要有2个像素的缓冲空间。在“Hello World”应用程序中一个明显的控件可能就是按钮控件,但在Smartphone上是不允许用按钮的。解决的办法是使用MainMenu控件,它是用soft key(在手机屏幕下方的两个硬件按钮)进行访问的。左菜单项(左侧soft key)应该没有任何子项,且这个选项应该是最常用的用户任务(在本示例中为“发送”)。右菜单项(右侧soft key)通常有一个带子项的菜单,但它也可以是第二常用的用户任务或是空白。根据优秀的Smartphone设计,在窗体上创建控件的代码如下所示(声明略):
this.mnuBar = new System.Windows.Forms.MainMenu();
this.mitSend = new System.Windows.Forms.MenuItem();
this.mitMenu = new System.Windows.Forms.MenuItem();
this.mitExit = new System.Windows.Forms.MenuItem();
this.lblName = new System.Windows.Forms.Label();
this.txtName = new System.Windows.Forms.TextBox();
// mnuBar
this.mnuBar.MenuItems.Add(this.mitSend);
this.mnuBar.MenuItems.Add(this.mitMenu);
// mitSend
this.mitSend.Text = "Send";
this.mitSend.Click += new System.EventHandler(this.mitSend_Click);
// mitMenu
this.mitMenu.MenuItems.Add(this.mitExit);
this.mitMenu.Text = "Menu";
// mitExit
this.mitExit.Text = "Exit";
this.mitExit.Click += new System.EventHandler(this.mitExit_Click);
// lblName
this.lblName.Location = new System.Drawing.Point(3, 2);
this.lblName.Size = new System.Drawing.Size(165, 22);
this.lblName.Text = "Name:";
// txtName
this.txtName.Location = new System.Drawing.Point(4, 24);
this.txtName.Size = new System.Drawing.Size(164, 20);
this.txtName.Text = "Chris";
// MainForm
this.Controls.Add(this.lblName);
this.Controls.Add(this.txtName);
this.Menu = this.mnuBar;
this.Text = "Sample UI";
this.txtName.Size = new System.Drawing.Size(162, 22);
注意,象此控件的命名便于代码的阅读,还要注意控件添加到窗体的顺序就是控件获得焦点的顺序(也被称作“Tab键顺序”)。当设计窗体时,可能需要修改由设计器生成的代码,以获得正确的焦点顺序。同样,如果希望文本框的高度与规定的符合,则当窗体设计完成时,需要手动修改所生成的代码。要完成此操作,可以编辑由窗体设计器中生成的代码(InitializeComponent方法)。为菜单项“Send”和“Exit”声明的两个事件处理程序如下所示:
private void mitSend_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Hello " + txtName.Text + "!", this.Text,
MessageBoxButtons.OK, MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
private void mitExit_Click(object sender, System.EventArgs e)
{
this.Close();
}
菜单项“Exit”(在右侧soft key的菜单上)关闭主窗体,从而也关闭了应用程序。菜单项“Send”(左侧soft key)会显示一个消息框,如下所示:
图2 消息框
一个消息框应该最多有两个选项(而不是Yes/No/Cancel),选定的图标控制标题(“Info”)和背景。
平台调用
要使用托管(.NET框架精简版)环境所没有的功能,其方式是使用一种叫做平台调用(或简称为P/Invoke)的机制。使用P/Invoke,可用以调用像Windows API这样的本机函数。例如,当您要遵从用户界面规则并允许某些TextBox控件默认为接受数字而非字符时,这一方式就非常有用。在上面的示例中,主窗体上的最后一个TextBox被设置为数字输入模式:
图3 具有数字输入模式的TextBox
由以下代码(在窗体的Load事件中)完成:
txtEvenMore.Focus();
EditModeHandler.SetNumbersMode();
注意TextBox控件需要获得焦点,以设置数字输入模式。SetNumbersMode的实现如下所示(稍有简化):
public static int SetNumbersMode()
{
int hWnd = GetFocus();
return SendMessage(hWnd, EM_SETINPUTMODE, 0, EIM_NUMBERS);
}
// API declarations
private const uint EM_SETINPUTMODE = 0x00DE;
private const uint EIM_NUMBERS = 2;
[DllImport("coredll.dll")]
private static extern int SendMessage(int hWnd, uint wMsg, uint wParam, uint lParam);
[DllImport("coredll.dll")]
private static extern int GetFocus();
Windows API(SendMessage和GetFocus)的声明可以在包含文件WINUSER.H中找到,而常数(EM_SETINPUTMODE oíEIM_NUMBERS)的定义可以在文件WINUSERM.H中找到(包括winuser.h的移动扩展)。这两个文件都包括在Smartphone 2003 SDK中。
注:获得一个窗口的HWND和直接发送Windows消息并不是.NET框架精简版1.0支持的功能。虽然它在当前版本中可以使用,但这并不能保证它在以后也能使用,因此您应该认真考虑是否真的需要使用这一高级功能。
关于如何调用本机代码,这是一个非常简单而有用的示例。即便P/Invoke有一些限制,使用这项技术还是可以获得很多先进功能。
即使只用少量用户界面元素(控件),也能构建高效的用户界面。要利用Smartphone 2003 SDK的帮助文件中详尽的用户界面指南。一定要查看其他Smartphone应用程序-尤其是电话上已有的那些-如何解决用户界面问题。如果未能得到一些托管函数,而您知道其在本机代码中是可行的,那么可以试试P/Invoking。
应用程序数据存储
尽管Smartphone平台中已经内置了连接,在应用程序的设计和开发中包含应用程序数据存储仍是十分重要的。无线带宽不是免费的,而且从性能的角度看,取得在本地存储的数据要比取得驻留在远程服务器基础结构中的数据更有效率。
应用程序数据通常是关于两种数据:用户希望应用程序即使在其终止后仍能保留的设置和应用程序首选项,以及来自远程服务器或者由用户输入的事务性或引用数据。对于在Pocket PC和其他Windows CE设备上的应用程序数据存储来说,Microsoft SQL Server? 2000 for Windows CE版(SQL Server CE)是一个普遍的选择。由于SQL Server CE在该平台上不可用,在Smartphone应用程序中必须使用其他选项。一般不建议在注册表中保持数据,因为转储注册表到永久存储区是非常耗费资源的。对于Smartphone应用程序,使用本地XML文件是一种常见的替代选择。
使用XML存储数据
.NET框架精简版中的XML支持主要是在System.Xml和System.Data命名空间中实现。以XML存储数据有两种基本方式。首先,您可以利用XmlDocument、XmlTextReader和XmlTextWriter类。另外,您可以运用XML驱动、基于ADO.NET的数据集。下面的示例使用ADO.NET方式将数据存储在一个本地XML文件中。
ISBN Anyplace示例演练
ISBN Anyplace是一个示例应用程序,可以让用户按每本图书唯一的ISBN号码检索Barnes & Noble的任何书籍的价格。应用程序会保持其检索到的数据,从而用户在以后可以更迅速地访问这些数据。此应用程序由一个外部XML Web服务支持,在稍后的阶段我们将详细探讨。
主窗体包括:
- 一个用户可以在其中输入ISBN号码的TextBox
- 一个由来自XML Web服务的响应填充的列表视图
- 允许用户提交请求、清除列表以及退出应用程序的Menu控件
为使ISBN Anyplace更完善,可以考虑添加代码来移除达到特定年限的数据,甚至加入用户界面增强功能来指出保留了什么数据,以及刚从最近一次的XML Web服务调用获取到了什么数据。
主窗体如下所示:
图4 输入ISBN号码
一旦用户已经提交了请求,就会在列表视图中填充:
图5 输入的ISBN号码
数据、ISBN和价格存储在应用程序目录中的一个本地XML文件里。用户可以退出并重新启动应用程序,而仍可访问收集到的信息。
.NET框架精简版的固有XML支持为应用程序数据存储奠定了坚实的基础。Smartphone所需的代码很少,而且使用系统化方式建立XML结构模型,可以保存任何一种数据,而无需使用关系数据库引擎。
使用XML Web服务
本示例项目ISBN Anyplace使用XML Web服务,根据书的ISBN号检索到它的价格。此XML Web服务是 XMethods.com 提供的众多演示服务之一。在Smartphone 2003的文章中包含了XML Web服务的内容,其目的是阐述由于.NET框架精简版内置于平台之中且在.NET框架精简版中已提供了XML Web服务支持,所以,对于完整的基于.NET框架的应用程序和运行在Pocket PC上,基于.NET框架精简版的应用程序来说,过程和功能是完全一样的。
初始化XML Web服务
在Smartphone 2003应用程序中设置XML Web服务的使用过程是非常简单易懂的。为了使用XML Web服务,需要向项目中添加Web引用。项目通过Web引用来使用XML Web服务。在项目中添加Web引用时,Visual Studio .NET将自动生成一个"代理类"(其中包含用作XML Web服务每个公开方法的代理的方法)。默认情况下,代理类不会显示在Solution Explorer(解决方案资源管理器)中。应用程序使用自动生成的类(而不是使用自己的代码修改的类)来访问XML Web服务。
要向项目中添加Web引用,请执行以下操作:
- 在"Solution Explorer"(解决方案资源管理器)中,选择要使用XML Web服务的项目。
- 在"Project"菜单上,选择"Add Web Reference"。
- 输入您要使用的XML Web服务的URL,然后单击"Go"。
- 在Web引用名称字段中,输入将在代码中用于以编程方式访问选定XML Web服务的名称。
- 单击Add Reference来创建应用程序中对XML Web服务的引用。
新引用将显示在Solution Explorer(解决方案资源管理器)中选定项目的Web References(Web引用)节点下。
Visual Studio .NET在添加Web引用时生成的代理类还包含用于同步或异步访问Web服务的方法。有关同步和异步XML Web服务访问的更多信息,请阅读文章 Consuming XML Web Services with the Microsoft .NET Compact Framework。
为分发而打包
当应用程序已经生成、测试并证明后,接下来就到了部署它的时候。现在应该将应用程序提供给用户,但是我们所谈的是Smartphone,标准的PC/CD安装可能无法实行。首先,因为用户的PC上可能根本没有安装ActiveSync,其次,因为安装工作应该可以在任何地方进行才对。
打包
您可以使用Visual Studio .NET 2003来创建安装用的压缩文件(.cab)。要这么做,请使用"Release"配置加载并生成项目。选择Build/Build Cab File生成用来创建压缩文件的批处理文件。批处理文件名为"BuildCAB.bat",位于<项目路径>/obj/Release。批处理文件包括对x86和ARMV4处理器的支持。
要生成压缩文件,还需要对批处理文件做一些手动的更改。您需要替换"cabwiz.exe"命令,改成指向"CabwizSP.exe"(默认安装,它位于C:\Program Files\Windows CE Tools\wce420\SMARTPHONE 2003\Tools)。您还需要将"vsd_setup.dll"从C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce400\x96复制到C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Smartphone\wce400\x86(对于实际设备,相同的文件还必须被复制到ARMV4处理器/文件夹中)。当这些更改完成并且批处理文件运行后,压缩文件会生成到项目文件夹下的一个文件夹(<项目路径>/cab/Release)中。每个文件的后缀说明了它的目标处理器。这就是Smartphone的安装过程,如果这个文件被复制到某一设备并被选中(例如,使用快捷键),则应用程序将执行安装过程。
但是,如果获取生成的压缩文件并将其安装到设备上,您将会发现应用程序的名称与Visual Basic .NET中使用的项目名称是相同的。此外,公司名称设置为"My Company",您可能不想使用这个名称。如果要自定义压缩文件的创建,您需要查看包含批处理文件的那个文件夹(在<项目路径>/obj/Release)。您可以在其中找到创建压缩文件所需的安装信息文件(.inf)。在该文件中,有应用程序条目和公司名称条目。以下示例是此文件的节选(不包括用句点标记的小节):
[Version]
Signature="$Windows NT$"
Provider="CompanyName"
CESignature="$Windows CE$"
[CEStrings]
AppName="SampleUI"
InstallDir=%CE1%\%AppName%
.
[SourceDisksFiles]
SampleUI.exe=1
.
[Files.Common]
SampleUI.exe,,,0
.
[Shortcuts]
Sample User Interface,0,SampleUI.exe,%CE11%
生成此文件的Visual Basic .NET项目名称是"ProjectName",在生成的文件中,Version节中的Provider值从"My Company"变为"CompanyName"。此外,注意在Shortcuts节中第一个值是生成的快捷方式名称,这可能应该比项目的名称更容易让人明白。这只是一个非常简要的介绍,因为.inf文件是一个很大的主题(有关更多信息,请参阅Visual Studio .NET帮助文件,索引主题"inf files for device projects")。
更新.inf文件时,您可以运行与.inf文件在同一文件夹中的批处理文件(BuildCab.bat)来生成一套新的压缩文件。
分发
用空中下载(OTA)分发应用程序的最简单方法,就是将压缩文件发布到Web页。有了上面创建的压缩文件(这里重命名为sampleui.cab),用下面的HTML源代码可以创建一个简单的Web页:
Download Sample
This is where you download the application, just select the link to the sampleui.cab file!
当这个页面加载到Smartphone浏览器上时,如下所示:
图6 在Internet Explorer中的下载页面
当链接被选中时,需要一个确认:
图7 确认下载
然后,当下载被确认时,显示出下面屏幕的序列:
图8 下载屏幕
在实际设备上,如果压缩文件没有签名,您还是会看到一个屏幕,它提示您确认安装。以上就是与此有关的全部内容。
应用程序现在已经安装到Smartphone,并且可以通过选择Settings和Remove Programs进行卸载。
到压缩文件的链接也可以通过邮件或短信服务(Short Message Service,SMS)消息分发。其他分发应用程序的方法还包括:
- 将压缩文件作为邮件的附件发送
- 设置一个存储卡,当它插入时运行安装包
- 使用一个包含压缩文件的桌面ActiveSync安装包
这里有一张来自Smartphone 2003 SDK帮助文件的图,它提供了一个很棒的不同选择的概括:
图9 应用程序分发选项
在实际方案中,最佳的解决方案经常是不同部署选项的组合。由于带宽的限制,您可能从一张存储卡中完成了首次安装,然后通过空中下载(OTA)分发更新文件。
签名
尽管使用模拟器开发Smartphone应用程序时签名不是必要的,但是在您要部署到实际设备上进行不时,应用程序签名无疑是绝对需要的。不过,可以在Smartphone SDK工具文件夹(默认安装,位于C:\Program Files\Windows CE Tools\wce420\SMARTPHONE 2003\Tools)中运行命令行spdps /device /create来创建一个开发证书。如果您已经有了一个证书,用spdps /device命令从个人存储区选择一个证书来进行特权的应用程序签名。
Smartphone应用程序的安全模型是基于证书的。设备可以由设备管理员(通常是网络操作员)进行配置,只允许签名的应用程序运行。一个应用程序是否可以运行取决于:
- 这个设备是否有一层或二层安全模型
- 设备当前的安全模式:Open、Locked或Prompt
- 应用程序是如何签署的:有特权的证书、无特权的证书或者什么都没有
一层设备可访问能够运行的应用程序的所有API。在二层设备上,除非应用程序以特权证书签名,否则会有无法访问的API。
如果设备具有Open安全模式,则所有应用程序可用签名和未签名的方式运行。如果模式是Locked,只能在设备上运行签名的应用程序。如果模式是Prompt,所有签名的应用程序运行时不会出现提示,但会提示用户拒绝或接受所有未签名的应用程序。
有关更多信息,请参阅Visual Studio .NET帮助文件中的"Security in Managed Code"部分(查找索引主题"Managed Code"和副主题"Security")。
企业级应用程序方案
自2002年以来,在其企业中部署移动应用程序的公司数量剧增。Pocket PC平台(尤其包括.NET框架精简版在内)使许多移动工作者更有效地实现成本减缩及收益增加。就像一般移动应用程序开发,最常使用Smartphone的方案,包括:
- 销售服务
- 现场服务
- 物流
- 交通运输
- 决策支持
一些可用的技术和解决方案,可在企业方案中提供对移动工作者的支持。一段时间内,只有膝上型电脑、Tablet PC、Pocket PC和较简单的移动电话是可用的。Smartphone 2003已将.NET框架精简版集成到ROM,因此有新平台可供应用程序设计者和开发人员使用。新平台的强大解决方案层面,包括外形因素(尺寸)、内置电话功能、高度连通性(包括SMS和Internet),此外就是查看信息比输入数据更重要。
在企业方案中实施的Smartphone 2003解决方案,可使信息系统和处理能延伸到需要移动办公的任何地方。因为不需要手动处理过程并减少了人员管理资料的次数,所以移动连接型的应用程序具有提高处理效率的能力。由于减少二次处理纸张表单的机会而使信息质量提高,并且在大量数据的处理中降低了出错的可能性。所有这些优点可提高效率(缩减成本)及客户满意度(收益)。
在现场服务的方案中,现场技术人员可以在旅途中迅速获得新的工作指令。在现场,现场技术人员可以查看详细的工作命令信息,当工作完成时,可以很快填妥大部分工作命令明细,只剩下少部分明细交给内勤员工填写。典型的现场服务方案,如下所示:
图10 典型现场服务方案
Smartphone应用程序最可能提供适当支持的是"执行工作"和"报告工作"这两个处理步骤。由于有越来越多的Smartphone包含内置相机,所以现场技术人员甚至可以在报告工作时包含现场图像,以便追踪或远程协助。
在决策支持方案中,经理和行政主管可以有效率地查看和监督重要商业事件和高层最新财务摘要。由于Smartphone同时具有SMS和Internet功能,所以进入的SMS可以唤醒电话,并自动从公司的IT基础结构中获取重要信息。决策支持解决方案中的主导思想是让管理层接收到适当的信息,以加速决策的产生。Smartphone应用程序可以将大量的这类解决方案带给许多不同类型的公司。
小结
本文旨在为开发电话应用程序、设计正确的用户界面、规划应用程序数据存储、使用和利用XML Web服务、为分发而打包应用程序以及了解有关适合Smartphone应用程序开发的主要企业方案而提供重要信息。
本文全篇的要点是如何在Smartphone 2003中善用Visual Studio .NET和.NET框架精简版支持。新平台已经为消费者市场和企业市场的成功作好准备。结合了吸引人的设计、电话功能、Internet连接和.NET框架精简版支持-一切准备就绪,在此您就可以放飞梦想。
设计“可脱机”的 Microsoft .NET 框架压缩版应用程序
http://editblog.csdn.net/msdncolumn/archive/2005/01/04/1191.aspx
相关技术:Visual Studio 2003、.NET Compact Framework、 Windows Powered Pocket PC
难度等级:★★★☆☆
读者类型:Pocke PC开发人员、.NET开发人员
[导读]本文通过介绍一些设计方案,学习"可脱机"的应用程序如何与服务器同步,并讲述了使用Web服务实现的一个应用程序示例。
简介
随着越来越多微软的Pocket PC与网络连接,就为分布式应用程序的设计提供了新的可能性。尽管有很多Web应用程序可以在这些设备上使用,但还是经常需要离线操作的支持。要保持企业环境内信息的一致性,离线应用程序需要与后台办公室系统同步数据。让我们从一些体系结构基础知识开始。
在现代的应用程序设计中,多层模式更多的是作为惯例(而非个别情况)使用。在服务器上我们越来越习惯于分离的用户服务(通常是演示)、企业服务和数据服务。通过使用像Microsoft Visual Studio .NET 2003这样支持移动设备开发的工具,同一模式可以被应用到移动应用程序。提及“可脱机”的应用程序时,是指一个应用程序在未与服务器连接的设备上运行。该应用程序必须有多层设计以获得与服务器端应用程序相同的好处(基于组件的、可重用性、可维护性等等)。图1显示了一个可能的分布式设计的高级概括。
图1 设备与服务器中的应用层
使用诸如ASP.NET技术来开发移动Web应用,移动应用程序可以在服务器上完全实现。然后,客户端只使用内置的浏览器来访问应用程序。如果需要支持离线功能,那么应用程序就必须在设备本身运行。与此相关的技术是智能设备可编程性与Microsoft .NET框架的精简版。
同步策略
分布式应用程序通常需要与服务器连接以获得关键任务信息;而且因为“始终连接”设备的梦想距离现实太遥远,所以也经常需要支持离线操作。因此,数据需要在设备本地进行维护,然后再与服务器进行同步。对于与服务器同步离线设备数据来说,最令人感兴趣的选项是数据库同步和应用程序同步。图2概括了两种选择的概念。
图2 数据库与应用程序同步
数据库同步是一种保持设备与服务器上数据最新的非常有效的方法。只有必要的信息进行传输而且甚至以压缩模式传输。但是,如果在同步过程中涉及到逻辑,那么需要用更程序化的方法来解决这个问题。让我们将它称为“应用程序同步”,即,同步时设备上的业务逻辑层与服务器上的业务逻辑连接。在许多真实的应用程序中,结合了这两种选择的设计会是最好的设计。
数据库同步
如果设备上的数据是在SQL Server for Windows CE(SQLCE)数据库中维护的,那么在.NET框架精简版中提供与SQL Server数据库同步这些数据的支持。该功能是在System.Data.SqlServerCe命名空间的SqlCeReplication类中实现的。可以采用的两种途径是远程数据访问(Remote Data Access,RDA)与合并复制。RDA是导入导出表数据的轻量级方法。另一方面,合并复制用于更高级的同步。
当数据同步过程中不涉及到太多逻辑时,数据库同步是很有趣的。这是一个快速选择,尤其当是大量数据需要传输时。它要求设备数据被存储在SQLCE数据库中。
如图2中虚线表示,且如果只涉及到客户端同步逻辑,使用System.Data.SqlClient名称空间访问服务器数据库也是可能的。
应用程序同步
在很多情况下,数据同步涉及到的逻辑需要有比数据库同步许可更完善的机制。应用程序同步很像应用程序集成,两个应用程序连接起来以进行数据交换。在.NET框架精简版中要实现它最显而易见的构造是使用XML Web服务。使用Web服务,设备可以以一种松耦合方式且基于诸如XML和HTTP等标准与服务器端逻辑连接。.NET框架精简版中对Web服务的支持可以在System.Web.Services名称空间中找到。
如果需要更高级的同步方案,应用程序同步是应该选择的。让我们看一个实现示例。
Reading Anyplace示例
Reading Anyplace示例应用程序展示了一个检查员如何离线记录计量器读数然后将其与服务器同步。这个应用程序由一个窗体组成,如图3所示。
图3 Reading Anyplace示例
可以输入计数器ID和位置,当按下“Record”按钮时,记录被添加到列表中。每一个新的记录被标注为“New”。如果同一个计数器ID被再次使用,那么相应的记录就会随之更新。当“Synchronize”按钮被按下时,每一个记录都会通过Web服务送到服务器。接着,响应会在列表中的“Remark”列中更新。一个正确的读数被标注为“OK”,同时不正确的读数也会被标注,说明验证的错误(如图3中ID为1234的计量器被标注为“Too high!”)。按下“Clean up”按钮清除列表中所有标注设为“OK”的记录。
此处的逻辑是这样的,直到设备数据与服务器同步之后,计数器读数验证才能发生。由于应用程序同步设计,这样的反馈是可能实现的;如果使用数据库同步这将更难以实现。
代码演练
因为这个示例的主要目的并不是展示一个完整的服务器实现,所以服务器端Web服务实现仅为如下所示:
[WebMethod]
public string SyncReading(string ID, int Position)
{
if (ID == "1234" && Position > 1000)
return "Too high!";
else
return "OK";
}
示例Web服务是采用硬编码的,只检查计数器中ID为1234、位置大于1000的计数位置。在实际方案中,可以将存储在服务器数据库中以往读数的位置与估计位置进行一个比较。同样,如果来自其他检查员的以往读数要提供给客户端,则这个示例在服务器端将需要更多的同步逻辑。
在客户端,当为这个Web服务创建一个Web引用时,“Synchronization”按钮的代码如下所示:
Cursor.Current = Cursors.WaitCursor;
Reading.Server.Sync sync = new Reading.Server.Sync();
try
{
foreach (ListViewItem lvi in lvwItems.Items)
if (lvi.SubItems[2].Text == "New")
lvi.SubItems[2].Text = sync.SyncReading(lvi.Text,
Convert.ToInt32(lvi.SubItems[1].Text));
}
catch (Exception ex)
{
MessageBox.Show("Could not call Web Service!", this.Text);
}
finally
{
Cursor.Current = Cursors.Default;
}
首先显示等待光标,创建Web服务对象(sync)。然后,在ListView中的每一个新记录(Remark为“New”)被发送到Web服务方法(SyncReading),ListView中的Remarks列由Web服务响应进行更新。如果发生错误,则显示一个消息框,无论发生什么情况,光标都被还原。
在本示例中,本地数据只在ListView控件中维护,当示例应用程序结束时,数据就丢失了。在实际方案中,这些数据可能被传输到一个DataSet并作为一个XML文件存储或在一个SQLCE数据库中存储。
小结
当需要诸如服务器端验证这样的逻辑时,应用程序同步是“可脱机”应用程序中实现同步的优先选择。因为允许客户端逻辑与服务器端逻辑连接,所以Web服务是实现应用程序同步的稳妥方法。因此,从一个基于.NET框架精简版的Pocket PC应用程序调用Web服务来说,本地支持是真正有价值的。
Windows Mobile开发FAQ
编译:刘铁锋 http://editblog.csdn.net/msdncolumn/archive/2005/01/04/1193.aspx
[摘要]本文为Pocket PC以及Smartphone开发者或对此感兴趣者提出的常见问题提供了解答。
常见问题
问:什么是Windows Mobile?
答:Window Mobile是微软公司Pocket PC以及Smartphone的软件平台。Windows Mobile把熟悉的Windows桌面系统扩展到了个人手持设备之上。
问:Pocket PC与Smartphone区别何在?
答:我们根据主要的使用用途来区分Pocket PC与Smartphone。Smartphone在外形和功能上都主要设计为电话设备。它非常适合接打电话以及作为信息管理设备。Pocket PC主要设计为可以方便查看、管理数据以及增强信息管理功能的小型个人电脑。有些Pocket PC设备也会带有电话功能。您可以根据您的Windows Mobile设备的不同用途来选择您的应用程序。
问:Pocket PC以及Smartphone的不同版本有何区别,比如2002与2003?
答:每一个新的Windows Mobiles software版本都是构建在原有的强大的开发平台之上。同时,对于开发者来说,每个新的Windows Mobile software版本都维持了原有核心的一致性以便更好的兼容设备。现在主要有如下三种Windows Mobile software版本:
- Windows Mobile 2002 software:该软件主要运行在被称为Pocket PC 2002以及Smartphone 2002的设备上。它包括了MAPI以及连接管理(Connection Manager)的新功能。
- Windows Mobile 2003 software:该软件版本在基于2003的设备中的ROM中附加了.NET CF。该功能可以让开发者为基于Windows Mobile 2003的设备编写托管代码(Managed Code)。它还包括了配置管理(Configuration Manager)、支持蓝牙编程、以及支持SMS侦听的新功能。
- Windows Mobile 2003第二版:该版本提供了如支持屏幕横向阅览模式(Landscape)、为Pocket PC提供的高分辨率屏幕支持以及Square屏幕支持、为Smartphone提供的QVGA屏幕等革新功能。在该版本中所有开发平台上的所有命名没有做任何改变,所有支持新屏幕方向和分辨率的API都已经成为了该平台的一部分。
问:如何识别不同的软件版本?
答:不管是Pocket PC还是Smartphone在“设置”中都有“关于”面板。在两种设备中都可以通过“开始”菜单来找到“设置”。
在编程的代码中,您可以使用GetVersionEx方法来获得操作系统的主、次版本号以及软件的具体编译数据。具体如下:
- Windows Mobile 2002–OS Version : 3.0
- Windows Mobile 2003–OS Version : 4.20
- Windows Mobile 2003第二版–OS Version : 4.21
Pocket PC开发
问:有哪些工具可以支持Pocket PC 2003开发?
答:如果使用C++为Pocket PC 2003开发程序,您需要使用Microsoft eMbedded Visual C++ 4.0,Microsoft eMbedded Visual C++ 4.0 Service Pack 3,以及Pocket PC 2003 SDK。
您可以使用Windows Mobile 2003第二版的模拟器工具包来在模拟在第二版的设备上测试您的程序。
请注意:Pocket PC 2003 SDK中不支持Microsoft eMbedded Visual Basic开发。您将需要使用Visual Studion.NET 2003以及Pocket PC 2003 SDK来编译托管代码(Managed Code)编写的程序。
问:Pocket PC 2002上的应用程序也适用于Pocket PC 2003吗?
答:一般来说,使用文档中注明的API开发的能在Pocket PC 2002上正常工作的程序,可以不用重新编译直接在Pocket PC 2003上运行。
问:为什么Pocket PC 2003不再提供对eVB开发环境的支持?
答:我们在Pocket PC 2003设备上将一直支持作为在RAM上的安装组件方式来支持eVB运行,因此旧版本的eVB程序也可以在新设备上运行。但是我们不再为Pocket PC 2003设备提供新的eVB开发环境的支持,因为我们提供了更为强大也更为健壮的Visual Basic .NET,Visual C# .NET以及Microsoft.NET Compact Framework。
根据用户的反馈,Pocket PC 2003设备中将在ROM中包括.NET CF。.NET CF是.NET Framework完整版的一个子集,它是专门为智能设备开发而设计的。它不仅仅是类似在Pocket PC 2000以及Pocket PC 2002设备中提供的eVB运行环境这么简单,它同样也是一个完备的语言中立的程序引擎。
问:如何由eVB向Visual Basic .NET迁移?
答:虽然由eVB向Visual Basic .NET迁移并不容易,但是您绝对值得这么做。
- 更加丰富的数据类型;eVB仅仅提供了16位的VARIANT;Visual Basic NET可以使用.NET Framework中的所有基础数据类型。
- 更快的执行速度:eVB是解释执行的;Visual Basic .NET通过JIT(Just-In-Time)在执行前先编译为本地代码。
- 更好的错误处理机制:eVB仅仅支持“ON Error”;Visual Basic .NET支持结构化的错误处理。
- 提供对结构(structures)支持:eVB没有结构的概念;Visual Basic .NET中支持命名空间(namespaces),类(classes),以及结构(structures)。
- 对面向对象的支持:eVB是基于过程的;Visual Basic .NET完全支持OOP(Object-Orientated Programming)
- 更好的特性:eVB仅仅支持MFC;Visual Basic .NET是纯.NET
- 与生俱来的XML支持:eVB不支持XML;Visual Basic.NET支持XML以及XML Web Services。
- 更好的数据模型:作为我们最好的数据模型,ADO.NET远远超过了ADOCE。
- 更加安全、可靠的执行:eVB是脚本语言;Visual Basic .NET是托管代码(Managed Code)。
同样,从范例到技术文章,我们有各种丰富的资源协助开发者完成这个转变。
问:如果需要为Pocket PC开发基于.NET CF的程序,可以采用何种开发工具?
答:Microsoft Visual Studio .NET 2003可以让Visual Basic .NET或C#开发者为Pocket PC 2000,Pocket PC 2002,Pocket PC 2003等相关设备编写托管代码(Managed Code,也就是所这些程序将在.NET CLR下运行)。毫无疑问,您可以使用Visual Studio .NET 2003为Pocket PC 2000以及Pocket PC 2002的相关设备开发托管代码程序。Visual Studio .NET 2003可以自动在开发中在这些设备的RAM上安装.NET CF。在Pocket PC 2003的ROM中已经存在了.NET CF,同时也通过Pocket PC 2003 SDK被Visual Studio .NET 2003支持。
问:有哪些相关资源是关于Windows Mobile 2003第二版开发的?
答:下载新的Windows Mobile 2003 Second Edtion Developer Resources Kit,里面包括了最新以及更新的代码例子以及白皮书。并且这个版本不需要新的SDK。您可以通过使用新的模拟器工具包来测试您的程序。eMbedded Visual C++ 4.0开发者应该先下载eMbedded Visual C++ 4.0 Service Pack 3
Smartphone开发
问:有哪些工具可以支持Smartphone 2002开发?
答:您可以使用eMbedded Visual C++ 3.0以及Smartphone 2002 SDK来为Microsoft Smartphone 2002开发程序。这些软件都可以从MSDN网站上获得。
问:什么时候会有支持Smartphone 2002开发的.NET CF?
答:第一个版本的.NET Compact Framework主要是为了更好的支持比较成功的Pocket PC相关的智能设备上程序开发。我们将在Smartphone的Smartphone 2003的版本中增加.NET CF。我们暂时没有计划发布支持Smartphone 2002的.NET CF。
问:是否有支持Smartphone 2002开发的MFC或ATL?
答:没有,MFC或者ATL都不支持Smartphone 2002。
问:可以使用eMbedded Visual Basic 3.0为Smartphone 2002开发程序吗?
答:不行。没有针对于Smartphone 2002的eVB开发环境。
问:有哪些工具可以支持Microsoft的Smartphone 2003编程?
答:随着Smartphone 2003的发布,您将有两项开发工具可供选择:使用带有Server Pack 3的eMbedded Visual C++ 4.0(采用本地代码)或者使用Visual Studio .NET 2003(使用托管代码)。不管怎样,您都必须下载Smartphone 2003 SDK。同时,使用Windows Mobile 2003第二版的模拟器可以让你模拟在第二版的设备上测试程序。
这些软件都可以从MSDN网站上获得。
问:在Smartphone 2003上可以使用哪个版本的.NET CF?
答:Smartphone 2003允许开发者使用.NET Compact Framework 1.0 Service Pack 1来开发程序。.NET Compact Framework将被包括在Smartphone 2003的ROM中。同时.NET Compact Framework 1.0 Service Pack 2将在Smartphone 2003第二版的ROM中存在。
问:Smartphone 2002上的应用程序也适用于Smartphone 2003的相关设备吗?
答:一般来说,使用文档中注明的API开发的能在Smartphone 2002上正常工作的程序,可以不用重新编译直接在Smartphone 2003上运行。
问:有哪些典型的基于Smartphone 2002以及Smartphone 2003的设备?
答:最初的Orange SPV以及Orange SPV e100都是运行在Windows Mobile 2002之上。MPX200同样基于Orange,AT&T也构建在基于Windows Mobile 2002的Smpartphone上。Orange SPV e200运行在Windows Mobile 2003之上。
问:是否有支持Smartphone 2003开发的MFC或ATL?
答:MFC不支持Smartphone 2003。您可以使用ATL 4.0来为Smartphone 2003做开发。请查看SDK文档来获得更多关于ATL 4.0的信息。
问:哪里可以获得关于Smartphone应用程序安全模型的更多信息?
答:为了便于开发者理解基于Windows Mobile的Smartphone的应用程序安全模型,我们创建了相关的白皮书。具体可以参考:http://msdn.microsoft.com/library/en-us/dnsmtphn2k3/html/smartphone_security.asp。
问:什么是命令行模式?
答:OEM或者操作者可以在程序中提供命令行模式。可以通过设置他们的Smartphone应用程序安全策略中来让使用者在安装或者运行程序时决定是否安装或者运行程序的方式来提供命令行模式。
问:eMbedded Visual Basic 3.0可以为Smartphone 2003开发程序吗?
答:不行。没有支持Smartphone的eVB开发环境。如果您希望使用您的Visual Basic的开发技巧,您可以考虑采用Visual Basic .NET以及.NET CF。
问:有哪些相关资源是关于Windows Mobile 2003第二版开发的?
答:下载新的Windows Mobile 2003 Second Edtion Developer Resources Kit,里面包括了最新以及更新的代码例子以及白皮书。并且这个版本不需要新的SDK。您可以通过使用新的模拟器工具包来测试您的程序。eMbedded Visual C++ 4.0开发者应该先下载eMbedded Visual C++ 4.0 Service Pack 3。
Mobile开发工具
问:什么是Microsoft eMbedded Visual Tools 3.0?
答:eMbedded Visual Tools 3.0是一个集成化开发工具。该开发工具主要针对基于使用Microsoft Windows CE操作系统的32位设备移动应用程序的开发者而提供的开发工具。该开发环境的完全版包括了Microsoft eMbedded Visual C++ 3.0语言,Microsoft eMbedded Visual Basic 3.0语言,专有平台SDK,远程工具以及文档。
问:eMbedded Visual Tools 3.0支持哪些设备平台?
答:eMbedded Visual Tools 3.0 - 2002 Edition以及SDK主要支持Pocket PC 2000、Pocket PC 2002、Smartphone 2002以及其他基于Windows CE 3.0的设备。
请注意:Pocket PC 2002 SDK可以使用eMbedded Visual Basic 3.0或者eMbedded Visual C++ 3.0,而不论Smartphone 2002 SDK是否仅仅支持eMbedded Visual C++ 3.0。
问:什么是eMbedded Visual C++ 4.0?
答:eMbedded Visual C++ 4.0是一个强大的开发工具。它为使用本地代码(Native Code)开发下一代的基于Windows CE设备,包括Pocket PC 2003以及Smartphone 2003的程序提供了最大的便利。这个独立的集成化开发工具为Windows CE程序开发带来了更高水平的生产力,同时在开发的灵活性、性能以及控制上却没有任何损失。如果使用eMbedded Visual C++工具为Pocket PC 2003或Smartphone 2003开发,您同样需要下载eMbedded Visual C++ 4.0。Service Pack 3、Pocket PC 2003 SDK以及Smartphone 2003 SDK。
问:可以使用eMbedded Visual C++ 4.0为Pocket PC或Smartphone开发程序吗?
答:您可以使用eMbedded Visual C++ 4.0加上Service Pack 2来为Pocket PC 2003以及包括了Windows Mobile 2003第二版的Smartphone 2003开发应用程序。但它不能用于Pocket PC 2002以及Smartphone 2002的开发。
问:可以使用Windows CE标准SDK为Pocket PC或Smartphone开发程序吗?
答:Windows CE SDK提供了一组特性的公共子集。这些子集可以允许遵照标准SDK开发的程序在基于Windows CE .NET平台上运行。为了更好的为Pocket PC以及Smartphone这样的智能设备开发程序,建议最好使用提供了更多特性的专有设备SDK。
问:eMbedded Visual Tools 3.0和Visual Studio.NET有何区别?
答:eMbedded Visual Tools 3.0是一个独立的开发环境。它主要面向于移动或者是嵌入式开发者。对于Pocket PC以及Smartphone,可以使用eMbedded Visual工具加上合适了平台SDK来构建强大的本地代码(Native Code)客户端程序。使用Visual Studio .NET 2003可以构建基于.NET Compact Framework的Pocket PC智能客户端程序。同样使用Visual Studio .NET以及ASP.NET移动开发控件可以开发基于浏览器的程序,这种程序可以支持更多的设备,其中包括向Pocket PC以及Smartphone这样的设备。
问:为什么Visual Studion.NET中没有整合eMbedded Visual C++4.0?
答:根据用户反馈,我们最初的努力都集中在如何让Visual Basic .NET开发者能够更加便利的开发程序。然而,我们将在下一个版本的Visual Studio中集成使用本地代码(C++)开发移动设备程序的能力。
问:什么是.NET Compact Framework(简称.NET CF)?
答:.NET Compact Framework是.NET Framework的一个子集。它的主要目标针对于资源有限设备而设计,提供对托管代码(Managed Code)以及XML Web Services的支持。.NET Compact Framework大大的介绍了开发者在开发运行在类似Pocket PC这样的设备的程序的代码量。因为.NET Compact Framework是.NET Framework的一个子集,因此如果开发者有开发桌面或服务器应用程序的经验,他们同样也可以应用相应的技巧来为Pocket PC以及Smartphone 2003相关设备开发程序。
问:使用.NET CF的最大优点何在?
答:为不同设备开发程序最大的障碍在于,大多数设备都需要开发者学习比开发桌面程序更多的API以及编程工具。因为.NET CF采用与.NET Framework同样的编程模型以及采用与开发桌面程序或服务器程序相同的开发工具,因此,它大大的提高的开发者的生产力。反过来,同样为会促进公司使用智能设备开辟新的途径提高业务量。同样,.NET CF也是唯一的为本地代码提供XML Web Services支持的移动开发平台。
问:.NET CF可以在哪些设备上运行?
答:.NET Compact Framework可以安装在Pocket PC 2000或者Pocket PC 2002相关设备(包括智能手机版本)的RAM中。同时在Pocket PC 2003相关设备的ROM中以及包括了.NET CF。Smartphone 2003设备中以及包括了.NET CF 1.0以及Server pack 1。所有的Windows Mobile 2003第二版的设备中都包括了.NET CF 1.0 Server Pack 2。
问:.NET CF将在什么时候可以使用?
答:.NET CF 1.0的版本已经作为了Visual Studio .NET 2003的一部分。
问:.NET CF上可以支持所有的.NET语言吗?
答:最初的.NET CF可以支持Visual C#以及Visual Basic。只要采用了遵照.NET CF支持的CLR语言,其他语言一样也可以运行。
问:.NET CF将会和eMbedded Visual C++一样出色吗?
答:在大部分情况下,使用eMbedded Visual C++开发的程序将比使用Visual Basic .NET或者Visual C# .NET开发的程序运行速度要快。但是,在程序中的某些地方进行详细的比较,会发现使用Visual Basic .NET的应用程序将比eMbedded Visual Basic相同的应用程序的性能有实质上的提升。
问:.NET CF和ASP.NET Mobile Controls的区别何在?
答:有两种不同的方案为移动设备开发程序。一种是直接让程序在智能设备上运行;另外一种是让程序在服务器端运行,而通过浏览器在客户端显示。.NET CF支持前者,而ASP.NET Mobile Controls(即Microsoft Mobile Internet toolkit)支持后者。
如果开发的程序需要在没有网络连接的情况下运行或者要求有更强大的用户界面支持或者需要与操作系统紧密相关,比如多媒体或者其他设备,那么使用.NET CF将为开发这类智能设备程序提供最大的便利。
当然,开发在服务器段运行的程序也有相应的好处。这种结构尤其对需要有大范围的需要通过网络访问的程序最有价值。因为服务器端采用与台式机相同的设备,因此这些程序不会受到资源的限制。我们一般利用Visual Studio .NET中的ASP.NET Mobile Controls来开发相关程序。
使用 Microsoft .NET框架精简版编写移动游戏
http://editblog.csdn.net/msdncolumn/archive/2005/01/04/1192.aspx作者:Ravi Krishnaswamy
相关技术:Visual Studio 2003、.NET Compact Framework、 Windows Powered Pocket PC
难度等级:★★★☆☆
读者类型:Windows CE 开发人员、移动设备游戏开发人员
[导读]本文讲述了如何创建基于.NET框架精简版的游戏以及编写面向小型设备的游戏的主要要求。在提高游戏性能方面,本文介绍了一些高级性能优化技术帮助我们突破游戏的速度瓶颈。
简介
Microsoft .NET框架精简版是完整Microsoft .NET框架的子集。它是对完整的.NET框架进行精简后得到的版本虽然其规模大大减小,但多数功能仍然保持完整。
使用.NET框架精简版:可以针对Pocket PC和其他Windows CE .NET设备进行单一的二进制部署,提高开发人员的工作效率,加快产品投放市场的速度。
本文将讨论编写面向小型设备的游戏的主要环节以及部分高级性能优化技术,我们可以使用这些技术来突破游戏的极限。总之,我们将了解到使用.NET框架精简版来开发和优化游戏是多么容易。这将是一次有趣的旅行,请系好安全带并充分享受其中的乐趣吧。
全屏游戏窗体
在游戏应用程序中,我们经常会使用设备的全屏显示功能。占据整个屏幕区域的窗体称为全屏窗体(也称为游戏窗体)。换句话说,全屏窗体占据桌面(即工作区)以及非工作区,如顶部的标题/导航栏、边框和底部的菜单栏。
应用程序通过将其WindowState设置为Maximized来创建全屏窗体,如下所示:
form.WindowState = FormWindowState.Maximized;
如果该窗体附加了菜单栏(和/或Pocket PC中的工具栏),则不能使其成为全屏窗体。
在Pocket PC的.NET框架精简版1.0中,要创建全屏应用程序,必须在窗体的OnLoad内部设置WindowState属性。
下面的图1和图2阐明了Pocket PC中的全屏窗体和非全屏窗体之间的区别。
图1 非全屏窗体
图2 全屏窗体
拥有全屏窗体的主要特征是没有标题/导航栏或菜单栏。应用程序必须考虑这些因素,并且在必要时提供尽量回避调用菜单功能的手段。
如果我们只是希望我们的窗体仅填充可用的桌面区域(而不是全屏),则无须做任何事情。默认情况下,.NET框架精简版会自动调整窗体的大小以填充Pocket PC的屏幕。
事实上,我们最好不要明确设置窗体的ClientSize以达到这种效果,因为这可能会妨碍应用程序在各种Windows CE.NET设备之间的互操作性。例如,如果我们明确调整应用程序的大小以匹配其中一个设备的窗体指数,则该大小在其他设备上可能并不理想。明智的做法是采用窗体的默认大小。
重写OnPaint和OnPaintBackground
典型的游戏应用程序会对窗体内容进行自定义绘制。它采取的办法是重写控件的OnPaint()事件并对窗体的绘制进行自定义处理。
protected override void OnPaint(PaintEventArgs paintg)
{
Graphics gx = paintg.Graphics;
// Custom draw using the graphics object
}
每当控件开始绘制时,都会首先自动刷新其背景。例如,OnPaint事件将首先用this.Backcolor中指定的颜色来绘制背景。但如果应用程序前景绘制完成之前调用了自动背景绘制,则屏幕会出现瞬间的闪烁。
要避免这一情况,我们建议每当应用程序重写OnPaint方法时,都要重写OnPaintBackground方法并自己来绘制背景。应用程序可以选择在OnPaint内部处理所有绘制工作,并将OnPaintBackground保留为空,如下面的示例所示。
protected override void OnPaintBackground(PaintEventArgs paintg)
{
// Left empty, avoids undesirable flickering
}
用于绘画的屏外[1](Off-Screen)位图技术
通过控件的this.CreateGraphics方法来获取屏幕的图形对象并直接向其进行绘制,我们可以进行屏上绘制。必须记住在不再需要屏上图形对象时将其处理。如果不这样做,可能导致有限的显示设备资源出现不足。
如上一节所示,我们可以在OnPaint和OnPaintBackground方法内通过PaintEventArgs.Graphics来访问屏幕的图形对象。在执行绘图方法以后,这些图形对象将被自动处理。
对于直接在屏幕上绘制的游戏应用程序,,当我们在屏幕上绘制多个对象时,将会看到屏幕闪烁。为避免这种现象,游戏开发人员通常会采用屏外绘制技术。
这一技术的思想是创建屏外位图,为其获取图形对象,在内存中执行所有绘图操作,然后将得到的屏外位图复制到屏幕上。
// Create off-screen graphics
Bitmap bmpOff = new Bitmap(this.ClientRectangle.Width,
this.ClientRectangle.Height);
Graphics gxOff = Graphics.FromImage(bmpOff);
在该例中,我将创建一个大小恰好与游戏窗体的工作区相同的屏外位图。在离屏和屏上绘图界限之间保持1:1的大小关系将有很大好处,尤其是在屏内(On-Screen)和屏外之间变换子图形的坐标时。
// Draw to off-screen graphics, using Graphics.Draw APIs
// Create on-screen graphics
Graphics gxOn = this.CreateGraphics();
// Copy off-screen image onto on-screen
gxOn.DrawImage(bmpOff, 0, 0, this.ClientRectangle, GraphicsUnit.Pixel);
// Destroy on-screen graphics
gxOn.Dispose();
这一技术可以避免屏幕闪烁,并且速度更快,因为所有屏外绘图操作都发生在内存中。
子图形(Sprites)
像位图这样的栅格图形都以矩形表示,而大多数实际的子图形都具有不规则的形状(不是矩形)。因此,我们需要找到相应的方法,以便从矩形光栅图形表示中提取形状不规则的子图形。
颜色键透明
游戏开发人员常用的一种技术是颜色键技术,即在渲染时忽略位图中的指定颜色键。这一技术也称为色度键屏蔽、颜色取消和透明混合。
图3 子图形
图4 带有颜色键透明
图5 不带颜色键透明
在子图形位图(图3)中,非对象区域被填充了品红色,该颜色被用作颜色键。使用以及不使用该技术时得到的混合效果分别在图4和图5中进行了说明。
透明混合的第一步是设置需要在渲染时屏蔽的颜色键(色度键)。我们需要指定精确的颜色键值。
ImageAttributes imgattr = new ImageAttributes();
imgattr.SetColorKey(Color.Magenta, Color.Magenta);
与使用Color类提供的标准颜色集不同,我们可以通过指定红色、绿色和蓝色(RGB)值来直接构建自己的颜色,如下所示:
imgattr.SetColorKey(Color.FromArgb(255, 0, 255),
Color.FromArgb(255, 0, 255));
我们经常用来指定颜色键的另外一种技术是直接使用像素值。这可以避免处理RGB值的需要。而且,颜色键不是硬编码的,可以在位图中独立进行更改。
imgattr.SetColorKey(bmpSprite.GetPixel(0,0), bmpSprite.GetPixel(0,0));
现在,让我们看一下如何使用已经设置的颜色键来透明地绘制子图形。
gxOff.DrawImage(bmpSprite, new Rectangle(x, y, bmpSprite.Width,
bmpSprite.Height), 0, 0, bmpSprite.Width, bmpSprite.Height,
GraphicsUnit.Pixel, imgattr);
在上述代码中,目标矩形被指定为new Rectangle(x, y, bmpSprite.Width, bmpSprite.Height),其中x和y是子图形的预期坐标。
通常,在绘制时可能需要放大或缩小子图形。我们可以通过调整目标矩形的宽度和高度来做到这一点。同样,还可以调整源矩形以便仅绘制子图形的一部分。
在设置子图形位图时,最好考虑一下目标设备的颜色分辨率。例如,24位颜色位图在12位颜色分辨率设备上可能不会按预期方式渲染;由于所用颜色的差异,这两者之间的颜色梯度差异可能非常明显。而且,在选择要屏蔽的ColorKey时,请确保颜色值在目标显示器所支持的范围之内。请记住,只有精确的ColorKey匹配才会受到支持。
颜色键透明是.NET框架精简版中唯一受支持的混合技术。
作为嵌入式资源的图像
我们可以将图形资源嵌入到我们的程序集中,方法是将该图形添加到项目中,并将其Build Action属性设置为“Embedded Resource”。这样,我们就可以按如下方式使用嵌入的bmp资源:
Assembly asm = Assembly.GetExecutingAssembly();
Bitmap bmpSprite = new Bitmap(asm.GetManifestResourceStream("Sprite"));
BMP、JPG、GIF和PNG图形格式受到Bitmap类的支持。
优化绘图方法
游戏中的绘图例程需要进行优化以便得到最佳的性能。比较笨拙的屏幕绘图方法是以离屏方式擦除并重绘所有子图形,然后用以离屏方式得到的图形进行屏上刷新。这样做效率很低,因为我们每次都不必要地重绘整个屏幕。这时,我们的帧速率将取决于框架精简版刷新整个屏幕的速率。
一种更好的办法是计算游戏中子图形的脏区,并且只刷新屏幕变脏的部分。子图形可能因为多种原因而变脏,例如,移动、图形/颜色发生改变或者与其他子图形发生冲突,等等。在本章中,我们将讨论可用于有效计算脏区的各种技术。
脏区计算
让我们考虑一个移动的子图形,一种计算脏区的简单方法是获取旧界限和新界限的并集。
RefreshScreen(Rectangle.Union(sprite.PreviousBounds, sprite.Bounds));
其中,RefreshScreen()是一个以屏上方式刷新指定矩形区域的方法。
图6 脏区:旧界限和新界限的并集
图7 巨大的增量产生巨大的脏区
注: 如图7所示,如果旧坐标和新坐标之间的增量很高并且/或者子图形很大,则这种技术会产生过大的脏矩形(为便于说明,旧的界限用不同颜色显示)。
这种情况下,更有效的方法是将子图形的脏区计算为多个单元矩形,这些矩形放到一起时表示脏区。
首先,让我们弄清楚旧的界限和新的界限有没有相互重叠。如果没有,则可以简单地将脏区计算为两个单独的矩形,分别表示旧的界限和新的界限。因此,对于图7说明的情形,明智的做法是将旧的界限和新的界限视为两个单独的脏区。
if (Rectangle.Intersection(sprite.PreviousBounds,
sprite.Bounds).IsEmpty)
{
// Dirty rectangle representing old bounds
RefreshScreen(sprite.PreviousBounds);
// Dirty rectangle representing current bounds
RefreshScreen(sprite.Bounds);
}
当我们并不介意将重叠区域重绘两次时,上述技术也将有效,如下面的图8所示。
图8 将脏区拆分为旧的界限和新的界限
现在,让我们看一下如何将脏区计算为多个单元矩形(这些矩形共同表示部分重叠的旧界限和新界限),以便不会重绘任何脏区,也就是说所有单元矩形都是互斥的。
首先,包含新的界限作为一个完整单元。请注意,这包括旧界限和新界限之间的重叠区域。
单元脏区1:表示当前界限的脏矩形
RefreshScreen(sprite.Bounds);
图9 脏区拆分为多个单元
现在,将旧界限的非重叠部分拆分为两个独立的单元,如下面的代码所示:
Rectangle rcIx, rcNew;
// Calculate the overlapping intersection
rcIx = Rectangle.Intersection(sprite.PreviousBounds, sprite.Bounds);
单元脏区2:
rcNew = new Rectangle();
if (sprite.PreviousBounds.X < rcIx.X)
{
rcNew.X = sprite.PreviousBounds.X;
rcNew.Width = rcIx.X - sprite.PreviousBounds.X;
rcNew.Y = rcIx.Y;
rcNew.Height = rcIx.Height;
}
else
{
// Means sprite.PreviousBounds.X should equal to rcIx.X
rcNew.X = rcIx.X + rcIx.Width;
rcNew.Width = (sprite.PreviousBounds.X +
sprite.PreviousBounds.Width) - (rcIx.X + rcIx.Width);
rcNew.Y = rcIx.Y;
rcNew.Height = rcIx.Height;
}
RefreshScreen(rcNew);
单元脏区3:
rcNew = new Rectangle();
if (sprite.PreviousBounds.Y < rcIx.Y)
{
rcNew.Y = sprite.PreviousBounds.Y;
rcNew.Height = rcIx.Y - sprite.PreviousBounds.Y;
rcNew.X = sprite.PreviousBounds.X;
rcNew.Width = sprite.PreviousBounds.Width;
}
else
{
rcNew.Y = rcIx.Y + rcIx.Height;
rcNew.Height = (sprite.PreviousBounds.Y +
sprite.PreviousBounds.Height) - (rcIx.Y + rcIx.Height);
rcNew.X = sprite.PreviousBounds.X;
rcNew.Width = sprite.PreviousBounds.Width;
}
RefreshScreen(rcNew);
冲突检测
现在,让我们看一下一个子图形与另一个子图形冲突的情形。从绘图角度来看,可以简单地忽略两个子图形之间的冲突,而只是使用前面讨论的技术逐个更新这些子图形的脏区。
但是,我们经常需要检测子图形的冲突以便使游戏做出响应。例如,在射击游戏中,当子弹击中目标时,我们可能希望通过爆炸或类似形式直观地做出反应。
在本文中,我们将所有重点讨论冲突检测技术其中的常用的几种技术。
可以回忆一下,大多数子图形的形状都是不规则的,但用于表示它们的光栅图形是矩形。很难将子图形的界限(或包络线)表示为开放的区域,因此我们将通过封闭的矩形来表示它。
当玩家看到屏幕上的子图形时,他/她实际上看到的是子图形区域,而觉察不到非子图形区域。因此,子图形之间的任何冲突检测都必须仅发生在其各自的子图形区域之间,而不应包括非子图形区域。
对于较小的子图形,在计算冲突并直观地避免冲突时,通常可以使用整个子图形界限。因为对象较小并且移动迅速,肉眼将不会注意到错觉。简单地计算两个子图形界限的矩形交集就足够了。
Rectangle.Intersect(sprite1.Bounds, sprite2.Bounds);
如果子图形的形状是圆形,则可以简单地计算它们的圆心之间的距离并减去其半径;如果结果小于零,则表明存在冲突。
对于逐个像素的碰撞检测,可以使用Rectangle.Contains方法:
if (sprite.Bounds.Contains(x,y))
DoHit();
首先应该应用快速边界相交技术来检测子图形之间的边界冲突。如果发生了冲突,则我们可以使用一种更为精确的方法(如冲突位图屏蔽技术)来确定相互重叠的像素。
如果我们不关心像素粒度,则可以使用我们已经在脏区计算一节中看到的技术来计算冲突区域。我们将处理两个发生冲突的子图形的界限,而不是处理一个子图形的旧界限和新界限。
冲突检测技术是专用的,应该根据具体情况加以确定。应该根据多种因素来选择特定的技术,如子图形的大小和形状、游戏的特性等。在一个游戏中使用上述技术中的多个技术是很常见的。
子图形速度
帧速率经常被单纯理解为移动子图形的速度,我们还应该控制子图形在每帧中移动的距离,以获得期望的净速度。
让我们考虑下面的示例,在该示例中,我们希望子图形每秒钟纵向移动100个像素单位。现在,我们可以将帧速率固定为10fps,并且将子图形每帧纵向移动10个像素,以便达到上述净速度,或者我们还可以将帧速率增加到20fps,并且使子图形的每帧纵向移动距离下降至5个像素。
采用任一种方法都可以达到相同的净速度,区别在于:在前一种情形下,子图形的移动看起来可能有一点跳跃性,因为与后一种情形相比,它移动相同距离所用的刷新周期要短一些。但是,在后一种情形中,我们依赖于游戏以20fps的帧速率渲染。因此,在决定使用哪一种方法之前,我们需要绝对确定硬件、系统和.NET 框架精简版的功能。
游戏前进技术
当屏幕随着时间的推移而发生变化并且直观地响应用户交互时,就说游戏正在前进。
游戏循环
在游戏内部,我们开始、维护和破坏循环,这使我们在必要时有机会渲染屏幕。通常,当游戏启动时,游戏循环开始,然后根据需要休眠和循环返回来进行维护,直到游戏结束为止,此时游戏循环将被弹出。
这种技术可以提供动作游戏所需的最大的灵活性和快速的周转速度。现在,我们将为我们的足球游戏实现一个游戏循环。让我们假设该游戏具有多个级别。
private void DoGameLoop()
{
// Create and hold onto on-screen graphics object
// for the life time of the loop
m_gxOn = this.CreateGraphics();
do
{
// Init game parameters such as level
DoLevel();
// Update game parameters such as level
// Ready the game for the next level
}
while (alive);
// End game loop
// Dispose the on-screen graphics as we don't need it anymore
m_gxOn.Dispose();
// Ready the game for next time around
}
private void DoLevel()
{
int tickLast = Environment.TickCount;
int fps = 8;
while ((alive) && (levelNotCompleted))
{
// Flush out any unprocessed events from the queue
Application.DoEvents();
// Process game parameters and render game
// Regulate the rate of rendering (fps)
// by sleeping appropriately
Thread.Sleep(Math.Abs(tickLast + 1000/fps) - Environment.TickCount));
tickLast = Environment.TickCount;
}
}
注意,在循环返回之前我们每次都要在循环内部调用Application.DoEvents(),我们这样做的目的是保持与系统之间的活动通讯,以及便于对事件队列中挂起的消息进行处理。这是有必要的,因为当我们的应用程序处于循环中时,我们基本上失去了处理任何来自系统的传入消息的能力;除非我们明确调用Application.DoEvents(),否则我们的应用程序将不会响应系统事件,并因此具有不合需要的副作用。
在游戏循环中需要考虑的另一个重要因素是渲染速率。大多数游戏动画至少需要每秒钟8-10帧(fps)的速率。为了使我们有一个大致的概念,以典型的卡通影片为例,它的渲染速率是每秒钟14-30帧。
一种简单的帧速率控制技术是决定所需的fps以及循环内部的休眠(1000/fps)毫秒。但是,我们还需要将处理当前走时所需的时间考虑在内。否则,我们的渲染速率将比期望的速率慢。处理时间可能相当可观,对于速度较慢的硬件尤其如此,因为这涉及到开销较高的操作,如处理用户输入、渲染游戏等等。
因此,在继续循环之前,我们需要休眠1000/fps减去处理当前走时所需的时间(毫秒)。
Thread.Sleep(Math.Abs(tickLast + (1000 / fps) - Environment.TickCount));
tickLast = Environment.TickCount;
计时器回调
另一项技术是设置一个定期回调的系统计时器。对于游戏循环而言,通常情况下,在游戏启动时实例化计时器,在游戏结束(此时计时器被处理)之前对计时器计时事件(定期发生)进行处理。
这要比游戏循环简单,因为我们让系统为我们处理计时器循环。我们只需要处理计时器回调,并且通过一次绘制一个帧来使游戏前进。
但是,我们必须非常小心地选择计时器的走时间隔,因为它决定了游戏的帧速率。
在游戏循环技术中,两次走时之间的时间间隔完全在我们的控制之下,并且正如前面所看到的,可以轻松地对其进行控制以便将处理时间考虑在内。另一方面,计时器回调意味着该时间间隔不能变化。因此,我们需要选择足够大的走时间隔以便完成每个回调的处理,或者通过显式跟踪处理一次走时所需的时间来控制走时的处理,并且在必要时跳过走时以保持节奏。
计时器回调的一个主要缺陷是我们需要依赖于操作系统计时器的分辨率。可能存在的最短走时间隔由该计时器可能具有的最高分辨率决定。在计时器分辨率较低的Pocket PC上,这可能成为一个限制因素,从而意味着这种方法中可能具有的fps也会比较低。另外,操作系统计时器事件的优先级非常低,这意味着游戏的响应速度也比较低。
虽然有这些局限,但对于前进速度较低的游戏(此时帧速率不太重要)而言,这一技术比较适用。例如,屏幕保护程序
private void StartTimer ()
{
int fps = 8;
// Create and hold onto on-screen graphics object
// for the life of the game/timer
m_gxOn = this.CreateGraphics();
// Setup timer callback to happen every (1000/fps) milliseconds
m_tmr = new System.Windows.Forms.Timer();
m_tmr.Interval = 1000/fps;
// Specify the timer callback method
m_tmr.Tick += new EventHandler(this.OnTimerTick);
// Start the timer
m_tmr.Enabled = true;
// Init game params such as level
}
protected void OnTick(object sender, EventArgs e)
{
if (alive)
{
// Regulate tick to include processing time,
// skip tick(s) if necessary
if (processTick)
{
// Process game parameters and render game
if (levelCompleted)
{
// Update game params such as level
}
}
}
else
EndTimer ();
}
private void EndTimer ()
{
// End game
// Dispose timer
m_tmr.Dispose();
// Dispose the on-screen graphics as we don't need it anymore
m_gxOn.Dispose();
m_gxOn= null; // Make sure the garbage collector gets it
// Ready the game for next time around
}
注:游戏结束时必须处理计时器。
请注意,没有必要使用Application.DoEvents(),因为我们既未循环也未阻塞任何系统事件,而计时器回调实际上只是一个系统事件。同时,请注意大多数游戏逻辑序列被放入到OnTimerTick()事件处理程序中。
无效-更新
另一种使游戏前进的方式是adhoc(内置动态寻址) 的基础上渲染它。每当游戏逻辑检测到屏幕需要刷新时,我们可以请求系统使屏幕的相应部分无效并对其进行刷新。
这一技术是最简单的,并且最适合基于用户交互前进的游戏。这是指那些不是持续不断地走时和渲染(如游戏循环、计时器回调中那样)的游戏,而是仅当用户与其交互时才前进的游戏,例如智力测验游戏。
我们可以通过调用this.Invalidate()使游戏窗体的整个工作区无效,或者通过调用this.Invalidate(dirtyRect)仅使其一部分无效。
只调用this.Invalidate()不能保证绘图操作会及时发生。我们必须通过调用this.Update()来确保屏幕在继续前进之前被刷新。在某些情况下,异步调用Invalidate()和Update()可能有助于获得更高的性能。但是如果不使用适当的帧同步技术,可能导致屏幕上出现不自然的画面,或者帧被丢弃。
如果我们能够承担得起每次都刷新整个屏幕的开销,则可以简单地调用this.Refresh(),它可以确保Invalidate()和Update()依次发生。
当我们作为所有者绘制窗体时,我们可以在屏幕的某个部分需要刷新时调用this.Refresh(),并且在内部跟踪屏幕的脏区,以及在OnPaint()和OnPaintBackground()内部有选择地刷新屏幕。
优化启动时间
在游戏中,开发人员通常会预先初始化所有游戏参数,从而在游戏进行过程中避免不必要的运行时延迟。这一方法的缺陷在于延迟被转移到游戏启动过程中,如果游戏花费太长的时间加载,然后用户才能与其交互,则尤其会令人感到不快。
这种情况下,可取的做法是尽可能快地显示一个含有与游戏相关信息的启动画面,以便吸引用户。然后,我们可以在后台执行启动活动,如加载资源、初始化游戏参数等等。
我们可以使用单独的全屏窗体作为启动画面,也可以使用仅含有基本游戏信息的主游戏窗体本身。
public Game()
{
// Set visibility first
this.Visible = true;
// Create on-screen graphics
Graphics gxOn = this.CreateGraphics();
// Display Splash screen
DoSplashScreen(gxOn);
// Destroy on-screen graphics
gxOn.Dispose();
// Proceed with your Game Screen
}
void DoSplashScreen(Graphics gxPhys)
{
// Load minimal resources such as title bitmap
Assembly asm = Assembly.GetExecutingAssembly();
Bitmap bmpTitle =
new Bitmap(asm.GetManifestResourceStream("title"));
// Draw the title screen a€_ this is your splash screen
gxPhys.DrawImage(bmpTitle, 0, 0);
// Now proceed with loading rest of the resources
// and initializing the game
// Regulate the splash time if necessary
}
重要的是不要在启动画面中提供任何功能,而只应该将其用作简介信息页。并不总是需要通过启动画面来启动。
游戏按钮
导航键
在Pocket PC中,导航键(即向左键、向右键、向上键和向下键)在游戏中发挥着至关重要的作用。我们可以通过重写游戏窗体的各个事件方法,访问这些键的KeyDown、KeyPress和KeyUp事件。
通常,我们需要处理这些导航键的KeyDown事件,并提供游戏级功能。
protected override void OnKeyDown(KeyEventArgs keyg)
{
switch(keyg.KeyData)
{
case Keys.Left:
// Provide game functionality for Left key
break;
case Keys.Right:
// Provide game functionality for Right key
break;
case Keys.Up:
// Provide game functionality for Up key
break;
case Keys.Down:
// Provide game functionality for Down key
break;
default:
// We don't care
break;
}
// Always call the base implementation
// so that the registered delegates for this event are raised.
base.OnKeyDown(keyg);
}
Pocket PC笔针
Pocket PC的笔针类似于台式电脑的鼠标。我们可以通过重写游戏窗体的各个事件方法来访问MouseDown、MouseMove和MouseUp事件。
protected override void OnMouseDown(MouseEventArgs mouseg)
{
Point ptHit = new Point(mouseg.X, mouseg.Y));
}
在Pocket PC上,到1.0版为止,.NET框架精简版不支持鼠标右键和硬件按钮。
其他技术
如有可能,应绘制图形,而不是使用位图。这将减小内存占用提高性能。例如,在太空射击游戏中,最好不要使用滚动的位图作为背景,可以通过用黑色的矩形填充背景然后绘制星星来获得相同的效果。
尝试将类似的位图逻辑地组合为一个大型位图,以后根据需要使用相关坐标提取适当的单元位图。拥有一个大位图而不是多个小位图可以降低资源大小。
尽可能尝试使用其他图形格式而不是BMP,以便利用更好的图形压缩技术(例如JPEG)。
避免在所有者绘制的游戏窗体上使用控件。我们应该作为所有者绘制所有内容。例如,如果我们需要一个Label,应该使用Graphics.DrawString()而不是创建自定义的子图形。
以静态方式尽可能多地初始化游戏逻辑,从而在运行时避免执行开销较大的计算。例如,在智力测验游戏中,应该尽可能地预先静态存储获胜组合,而不是在游戏运行过程中使用开销较大的动态算法以及类似的功能。
小结
在为诸如Pocket PC这样的设备编写游戏时,需要记住显示屏幕尺寸要比桌面计算机小得多,并且硬件的功能也没有桌面计算机那样强大。
因此,对于这些小型设备,应该比桌面计算机更加严格地优化游戏。同时在设计游戏时,还应该认真考虑目标硬件、操作系统和.NET框架精简版的功能。
游戏的性能高低主要取决于它的绘图例程。高效的绘图技术决定了游戏的响应速度,尤其是在诸如Pocket PC这样的小型设备中。因此,应该使用前面讨论的所有绘图优化技术(如脏区计算),以便节省每帧的绘图时间。
帧速率是另一个需要记住的重要参数,请基于目标设备的功能明智地加以选择。