使用.NET 框架压缩版开发Windows Mobile 2003 for Smartphone
Andreas Sjöström, Christian Forsberg
businessanyplace.net
适用于:
Microsoft® Windows Mobile™ 2003-based Smartphone
Microsoft Visual Studio® .NET 2003
Microsoft .NET Compact Framework 1.0
摘要: 学习如何用 Visual Studio .NET、.NET 框架压缩版和 Smartphone 2003 SDK 开发和分发 Smartphone 2003 的应用程序。(本文包含一些指向英文站点的链接。)
从Microsoft下载中心下载 示例代码。
![*](http://img.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif)
本页内容
![]() |
简介 |
![]() |
开发电话应用程序 |
![]() |
用户界面设计 |
![]() |
应用程序数据存储 |
![]() |
使用 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 应用程序可以为提供商业价值的相关方案 |
有关详细信息,请参阅以下页面:
Microsoft MSDN Mobility & Embedded Development Center
Microsoft .NET Compact Framework
开发电话应用程序
无论开发者开发应用程序时的目标平台是什么,都需要有一些共同的设计和开发技能。 这些技能包括定义并了解方案和使用事例、构建并坚持系统结构、系统地定义并解决问题方面等等的能力。 从这方面来说,开发 Smartphone 的应用程序和开发其他平台的应用程序并无不同。 形式因素已经变得更小,通过 Windows Mobile for Smartphone,从大型机、服务器、桌面计算机、PDA,现在最终已经到了只有移动电话大小。 基于 Windows Mobile 的 Smartphone 软件有一个软件开发平台,与其较大型的同辈平台共享许多特性。
不过,要成功地设计和开发电话应用程序,不仅需要建立通常的开发惯例,还要考虑使用一组 Smartphone 特定方面,以开发出实用、易用且有效率的电话应用程序:
• |
Smartphone 主要是要设计为一种优秀的电话,在与其他许多设备不同设置和情况时可以同样使用。 应用程序需要是迅捷、稳定并且高度容错的。 需要定义关于异常处理的明确策略并跨整个应用程序实施。 |
• |
相较于在 PDA(如 Pocket PC)上,其屏幕空间更加宝贵。小型屏幕要求用户界面的设计要更干净、更有效率。 |
• |
Smartphone 没有触摸屏。 在设计用户界面和输入机制二者时都需要考虑小型硬件按键。 应用程序导航应该是有预测能力并直观的,且要求的击键次数越少越好。 实际上,大多数电话应用程序都设计成主要为对信息查看提供强大的支持,并且需要的输入越少越好。 |
• |
Smartphone 的固有连接,包括 SMS 和 Internet 标准支持,都应该是应用程序设计天然的组成部分。 XML Web 服务是作为.NET 框架压缩版的一个核心元素实施的,而通过使用平台调用,SMS 功能可以从平台本身来利用。. |
• |
基于 Windows Mobile 2003 的 Smartphone 软件包括多种内置应用程序,如“联系人”、“日历”和“收件箱”等等。 在适当处集成这些应用程序设计和这些应用程序,可以为用户增加更多的综合价值。 |
这些是在基于Windows Mobile 的Smartphone软件的应用程序设计和开发中应该针对的关键考虑事项。
用户界面设计
如果您来自本机(或非托管)开发环境,比如使用Microsoft eMbedded Visual C++®开发应用程序,您会注意到托管代码可以为您做许多事。 举例来说,当进行用户界面设计时,最显著的改变是无须一直跟踪控件的ID号以及其他用户界面元素 — 可以按名称来引用它们。 不必处理指针以及清除已分配的内存。
如果熟悉 Pocket PC 的 .NET 框架压缩版开发,许多事情对您来说将会是很常见的。 不过,在用户界面设计时有仍一些重大差异。 最重要的可能是没有触摸屏及其后果。 同样,没有标准输入面板(Standard Input Panel,SIP),此外在 Smartphone 中许多控件已经废弃了(请参看下面的“更多控件”以了解 .NET 框架压缩版在 Smartphone 2003 上所支持的控件)。
用户界面基础知识
作为简介,让我们看一个熟悉的示例,“Hello World”窗体:
![smartphone_2003fig1](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig1.gif)
图 1:示例窗体
这个窗体是根据包含在 Smartphone 2003 SDK 中的 Smartphone 界面指南设计的。 当诸如“应该是”和“应该有”这样的表达在本章后面部分使用时,表明是对设计指南的参考。 如果您在指南中找不到答案,了解如何解决用户界面设计问题的最好方法永远是:查看其他现有的 Smartphone 应用程序。
因为在一个窗体中的每行上都应该有一个控件,所以在第一行添加标签控件,在第二行添加文本框控件。 每个控件的高度应该是22个像素,并且窗体在顶部和底部需要有2个像素的缓冲空间。 在“Hello World”应用程序中一个明显的控件可能就是按钮控件,但是在Smartphone上是不允许用按钮的。 解决办法是使用主菜单控件,它是用 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方法)。 一个实例是“Name”文本框的高度(由生成的默认值25改为22):
为菜单项“发送”和“退出”声明的两个事件处理程序看起来如下:
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(); }
菜单项“退出”(在右 soft key 的菜单上)关闭主窗体,从而也关闭了应用程序。 菜单项“发送”(左soft key)会显示一个消息框,如下:
![smartphone_2003fig2](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig2.gif)
图2:消息框
一个消息框应该最多有两个选项(no Yes/No/Cancel),选定的图标控制标题(“Info”)和背景。
更多控件
当在Smartphone 2003上使用 .NET 框架压缩版时,下列控件是可用的:
• |
Label |
• |
TextBox |
• |
MainMenu |
• |
CheckBox |
• |
PictureBox |
• |
Panel |
• |
ComboBox |
• |
ListView |
• |
TreeView |
• |
HScrollBar |
• |
VScrollBar |
• |
Timer |
• |
ProgressBar |
• |
ImageList |
前三个都包括在上面的示例中,让我们再使用更多的控件。 添加过多个控件之后,窗体看起来如下:
![smartphone_2003fig3](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig3.gif)
图3:更多控件
前面的标签和文本框被添加到面板控件。 面板应始终覆盖整个窗体,在面板旁边则添加了一个VScrollBar(垂直滚动条)。 面板中添加了很多标签和文本框,以及一个复选框和一个组合框。 复选框相当明显,但是组合框(也被称为“项选择器”)不能像您可能习惯的那样下拉。 转而有两种方法来做选择: (1)可使用左右箭头键单步执行不同选项;(2)可以按动作键得到一个新屏,并在这里选择一个选项:
![smartphone_2003fig4](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig4.gif)
图4:全屏中的组合框选择
添加其他控件到面板及添加一个垂直滚动条的目的是展示如何令一个窗体可滚动。 这是处理添加到一个窗体的控件过多,超出一屏的范围时的一种方法。
达到此目的的方法是创建一个足够大,能容纳所有其他控件的面板,且垂直滚动条的高度应与屏幕工作区的高度相同(通常是180,但是可以用 Screen.PrimaryScreen.WorkingArea.Height 动态获取)。. 垂直滚动条应该有一个第一屏容纳不下的字段数的最大值。 这里的字段是指一个标签和另一个控件(文本框、复选框等等)的一个组合。 如果每个控制器都使用标准22点,那么就意味着我们一次可以在屏幕上放4个字段(8个控件)。 因此,如果我们有6个字段(12个控件),则垂直滚动条的最大属性应该设定为2。当全部都设定好之后,每个输入控件(不算标签)都应该将其 GotFocus 事件设定为以下代码:
private void ctl_GotFocus(object sender, System.EventArgs e) { if (((Control)sender).Top > Screen.PrimaryScreen.WorkingArea.Height - pnlForm.Top) vsbForm.Value++; if (((Control)sender).Top < -pnlForm.Top) vsbForm.Value--; }
这就是根据垂直滚动条的值滚动面板的代码。
private void vsbForm_ValueChanged(object sender, System.EventArgs e) { pnlForm.Top = -vsbForm.Value * 44; // Height of one label and other control }
使窗体滚动所需要做的就是这些。
处理超出一屏可容纳范围的更多控件的另一种方法是使用选项卡对话框。 我们使用这一术语是因为它是大多数Windows用户都熟悉的一个概念。 不过,在 Smartphone 上没有选项卡控件,那么可以用一个全屏列表视图控件作为替代。 不过,我们应该要能够处理按数字键的动作,但目前列表视图并未为其引发任何事件。 因此,一个叫做选择列表的控件(感谢 Robert Levy,其原始出处是Smartphone Thoughts ) 被用于选项卡选择列表。 其结果就是这一典型“选项”屏幕:
![smartphone_2003fig5](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig5.gif)
图5:选项屏幕(选项卡选择)
选择列表控件能够处理超出一个单屏可容纳的更多选项。 它只是添加了一个建议使用的“More…”选项作为最后选择(“9”键),并在一个新(逻辑)屏幕上显示更多选项。.
选项列表控件的实现非常简单直接,选项的实际绘制的完成使用了 Graphics.FillRectangle 和 Graphics.DrawString以及一种叫做双缓冲的标准技术(绘制到一个屏幕外的位图上,然后当完成时 Graphics.DrawImage 到屏幕上)。 查看示例代码以了解关于这一非常具使用价值的控件其他详细信息。
当用动作键或一个数字键选定一个选项卡时,选项显示在一个单独的全屏上:
![smartphone_2003fig6](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig6.gif)
图6:常规选项示例(选项卡)
注意每个选项卡都有一个“取消”选项作为右菜单项(soft key),但它不会出现在选项卡选择屏幕中。
上面的选项窗体实际上是用一个单一窗体实现的。 这样做的原因是为了展示,与每个选择屏幕和每个选项卡都使用单独窗体相比,有一种解决方案有着更高的性能,不过其代价是要编写更复杂的代码。 简而言之,选择屏幕就是选择列表控件,每个选项卡都是一个根据当前选择隐藏或显示的面板控件。 打开和关闭选项卡的代码如下所示:
private void selList_ItemSelected(object sender, ItemSelectedEventArgs e) { switch (selList.SelectedIndex) { case 0: this.Text = "General"; pnlTab1.Visible = true; pnlTab2.Visible = false; pnlTab3.Visible = false; selList.Visible = false; mnuBar.MenuItems.Add(mitCancel); currentTab = 0; break; case 1: this.Text = "More"; pnlTab1.Visible = false; pnlTab2.Visible = true; pnlTab3.Visible = false; selList.Visible = false; mnuBar.MenuItems.Add(mitCancel); currentTab = 1; break; case 2: this.Text = "Even More"; pnlTab1.Visible = false; pnlTab2.Visible = false; pnlTab3.Visible = true; selList.Visible = false; mnuBar.MenuItems.Add(mitCancel); currentTab = 2; break; } } private void CloseTab() { if (currentTab > -1) { this.Text = "Options"; pnlTab1.Visible = false; pnlTab2.Visible = false; pnlTab3.Visible = false; selList.Visible = true; mnuBar.MenuItems.Remove(mitCancel); selList.Focus(); currentTab = -1; } else this.Close(); } private void mitDone_Click(object sender, System.EventArgs e) { // Save switch (currentTab) { case 0: // Save General settings break; case 1: // Save More settings break; case 2: // Save Even More settings break; } this.CloseTab(); } private void mitCancel_Click(object sender, System.EventArgs e) { this.CloseTab(); }
注意窗体的标题随每个选项卡而改变;“取消”菜单项在选项卡为活动的时候添加,在选择屏幕中移除。
窗体导航
窗体导航对任何应用程序来说都是一个重要组成部分,它也是信息在窗体之间传输的方式。 当一个子窗体显示时,代码看起来如下:
Cursor.Current = Cursors.WaitCursor; SubForm subForm = new SubForm(this); subForm.ShowDialog();
注意当前窗体是作为一个参数传递到选项窗体的构造函数。 在构造函数中,父窗口用此代码保存:
private Form parentForm; public SubForm(Form parentForm) { InitializeComponent(); this.parentForm = parentForm; }
这使得我们能够做很多重要的事情。 首先,我们可以在选项窗体活动的时候隐藏父窗体。 这样就将防止在一个任务切换实用工具中应用程序有多于一个的窗口时活动的。 一般来说,我们在窗体初始化一完成就隐藏父窗体,这通常是在窗体加载事件结束时:
private void SubForm_Load(object sender, System.EventArgs e) { // Control initialization // ... parentForm.Hide(); Cursor.Current = Cursors.Default; }
在关闭窗体的时候关闭 事件负责重新显示父窗体:
private void SubForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) { parentForm.Show(); }
平台调用
要使用托管(.NET 框架压缩版)环境所没有的功能,其方式是使用一种叫做平台调用(或简称为P/Invoke)的机制。 使用 P/Invoke,可用以调用像 Windows API 之类的本地功能。 例如,当您想要遵从用户界面指南并允许特定文本框控件默认为接受数字而非字符时,这一方式就非常有用。 在上面的示例中,主窗体上的最后一个文本框是设置为数字输入模式:
![smartphone_2003fig7](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig7.gif)
图7:具有数字输入模式的文本框
这是由以下代码(在窗体的加载事件中)完成的:
txtEvenMore.Focus(); EditModeHandler.SetNumbersMode();
注意文本框控件需要将焦点设置为数字输入模式。 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 和 EIM_NUMBERS)可以在文件WINUSERM.H 中找到(包括winuser.h 的移动扩展)。. 这两个文件都包括在 Smartphone 2003 SDK 中。
注意 获得一个窗口的 HWND 和直接发送 Windows 消息并不是 .NET 框架压缩版1.0支持 功能。 虽然它在当前版本中可以运作,但这并不能保证它在未来能同样地运作,因此您应该认真考虑是否真的需要使用这一高级
关于如何调用本地代码,这是一个非常功能。简单而有用的实例。 即便 P/Invoke 有一些限制,使用这项技术还是可以获得很多先进功能。
小结
即使只用少量用户界面元素(控件),也能构建有效的用户界面。 要利用 Smartphone 2003 SDK 的帮助文件中详尽的用户界面指南。. 确定查看其他 Smartphone 应用程序 — 尤其是电话上已有的那些 — 如何解决用户界面问题。 如果一些托管性能失败,而您知道其在本地代码中是可行的,那么可以试试 P/Invoking。
应用程序数据存储
尽管 Smartphone 平台中已经内置了连接,在应用程序的设计和开发中包含应用程序数据存储仍是十分重要的。 无线带宽不是免费的,而且从性能的角度看,取得在本地存储的数据要比取得存储在远程服务器基础结构中的数据更有效率。
应用程序数据通常是关于两件事: 用户希望应用程序即便在其终止后仍能保留的设置和应用程序首选项,以及来自远程服务器或者由用户输入的事务性或引用数据。对于在 Pocket PCs 和其他 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 号码的文本框 |
• |
一个由来自 XML Web 服务的响应填充的列表视图 |
• |
允许用户提交请求、清除列表以及退出应用程序的菜单控件 |
为使 ISBN Anyplace 更完整,可以考虑添加代码来移除达到特定年限的数据,甚至加入用户界面增强功能来指出保持了什么数据,以及刚从最近一次的 XML Web 服务调用获取到了什么数据。
主窗体看起来如下:
![smartphone_2003fig8](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig8.gif)
图8:输入 ISBN 号码
一旦用户已经提交了请求,就会在列表视图中填充:
![smartphone_2003fig9](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig9.gif)
图9:输入的 ISBN 号码
数据、ISBN 和价格存储在应用程序目录中的一个本地 XML 文件里。 用户可以退出并重新启动应用程序,而仍可访问收集到的信息。
让我们看一下幕后是怎样进行的。
ISBN Anyplace 示例代码
示例代码项目包括:
• |
用户界面的主窗体 MainForm.cs |
• |
处理本机 XML 文件的代码的 ApplicationData 类 |
• |
保存数据集架构的 XML 架构(XSD)文件 |
当应用程序启动时,下列代码会执行:
private void MainForm_Load(object sender, System.EventArgs e) { // Populate listview PopulateListview(); txtBookISBN.Focus(); EditModeHandler.SetNumbersMode(); }
EditModeHandler.SetNumbersMode 方法是用来格式化文本框 ,使之更容易接受数字输入(如需详细信息,请参阅上一节“用户界面设计”中的“平台调用”)。
PopulateListview 是 MainForm 的私有方法。. 当列表视图应该输入时就会调用它。 注意下列各项:
• |
ApplicationData类已进行初始化。 |
• |
ApplicationData.GetAll 方法返回一个保存本机 XML 文件数据的数据集。 列表视图清除完毕。 |
• |
不使用 for…each 循环,改用简单的 for 循环回到 DataRows ,使项目得以用正确顺序列出。 |
以下是代码:
private void PopulateListview() { // Get application data ApplicationData applicationData = new ApplicationData(); // Get Dataset from ApplicationData class DataSet ds = new DataSet(); ds = ApplicationData.GetAll(); // Clear listview lvwBook.Items.Clear(); // Loop through rows backwards. The last value appears first. for(int i = ds.Tables["ApplicationData"].Rows.Count-1; i >= 0; i--) { DataRow dr = ds.Tables["ApplicationData"].Rows[i]; // New item ListViewItem book = new ListViewItem(dr["key"].ToString()); // Assign ISBN and Price book.SubItems.Add(dr["value"].ToString()); // Add the item to the listview lvwBook.Items.Add(book); } }
ApplicationData 类主要有三个方法:
• |
pplicationData.GetAll 以数据集返回所有项目。 |
• |
ApplicationData.ClearAll 删除本机 XML 文件。 |
• |
ApplicationData.New 在本机 XML 文件中新增项目。 |
下列代码可在 GetAll 方法中找到:
public DataSet GetAll() { // Initiate new dataset DataSet ds = new DataSet(); // Read schema and xml ds.ReadXmlSchema(xsdApplicationData); // Return the dataset regardless if ReadXml throws an exception or not // There is no dataset the first time the application runs try { ds.ReadXml(xmlApplicationData); } catch {} // Return dataset return ds; }
请注意,异常处理拦截到异常,但不会以任何特定方式加以处理。 因为异常通常是在第一次应用程序执行时抛出的,或是在删除了 XML 文件之后,而且没有本机 XML 文件可开启时才抛出。 在这种情况下,我只想要应用程序继续进行,稍后在其余应用程序进程中再建立 XML 文件。 新增项目时,下列代码会执行:
public void New(string dataKey, string dataValue) { // Add data to local XML file // Initiate dataset DataSet ds = new DataSet(); ds.ReadXmlSchema(xsdApplicationData); // Try reading applicationdata xml file. // If exception is thrown there's a problem reading the file (e.g. it does not exist), // then move on to create a new. try { ds.ReadXml(xmlApplicationData); } catch {} // New row DataRow dr = ds.Tables["ApplicationData"].NewRow(); // Set datarow properties dr["key"] = dataKey; dr["value"] = dataValue; // Add row to dataset ds.Tables["ApplicationData"].Rows.Add(dr); // Save data ds.AcceptChanges(); ds.WriteXml(xmlApplicationData); }
xsdApplicationData 和 xmlApplicationData 常数会在ApplicationData 类中声明及设置如下:
private const string xsdApplicationData = @"\Storage\Program Files\ISBNAnyplace\ApplicationData.xsd"; private const string xmlApplicationData = @"\Storage\Program Files\ISBNAnyplace\ISDNAnyplace.xml";
您可以利用平台调用 Windows CE API SHGetSpecialFolderLocation,并以 CSIDL_APPDATA (26) 参数来获取应用程序数据路径。
当 Smartphone 关机时,会清除RAM。 这意味着应用程序数据必须存放在 \Storage 文件夹中。 \Storage 文件夹是保存在快速内存中的。 有关其他信息,请参阅 Smartphone 2003 SDK 中的 Smartphone Guide 中的“Storing Data”。
ClearAll 方法只包含一行代码:
public void ClearAll() { // Delete XML file System.IO.File.Delete(xmlApplicationData); }
ClearAll删除 Smartphone 存储的实体 XML 文件。
小结
诚如您所看到的,.NET 框架压缩版的固有 XML 支持已提供应用程序数据存储的基石。 Smartphone 所需的代码很少,而且使用系统化方式建立 XML 结构模型,可以保存任何一种数据,而无须使用关系数据库引擎。
使用 XML Web 服务
本示例项目 ISBN Anyplace 使用 XML Web 服务,根据书的ISBN号检索到它的价格。 此 XML Web服务是XMethods.com提供的众多演示服务之一。 在Smartphone 2003文章里包含了 XML Web 服务段落,其目的是为了阐述由于 .NET 框架压缩版是内置在平台中的而且 XML Web 服务支持是在.NET 框架压缩版中固有的,对完整的基于.NET 框架的应用程序和运行在 Pocket PC 上基于 .NET 框架压缩版的应用程序来说,过程和功能是完全相同的。
初始化 XML Web 服务
在 Smartphone 2003 应用程序中设置 XML Web 服务的使用过程是非常简单易懂的。 为了使用 XML Web 服务,需要向项目中添加 Web 引用。项目通过 Web 引用来使用 XML Web Service。在项目中添加 Web 引用时,Visual Studio .NET 将自动生成一个“代理类”(其中包含用作 XML Web Service 每个公开方法的代理的方法)。默认情况下,代理类不会显示在 Solution Explorer(解决方案资源管理器)中。应用程序使用自动生成的类(而不是使用自己的代码修改的类)来访问 XML Web Service。
要向项目中添加 Web 引用,请执行以下操作:
1. |
在 Solution Explorer(解决方案资源管理器)中,选择要使用 XML Web Service 的项目。 |
2. |
在 Project 菜单上,选择 Add Web Reference. |
3. |
输入您想要使用的 XML Web 服务的 URL,然后点击 Go 。 |
4. |
在 Web reference name(Web 引用名称)字段中,输入将在代码中用于以编程方式访问选定 XML Web Service 的名称。 |
5. |
点击 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。
ISBN Anyplace 示例代码
在 ISBN Anyplace 中访问 Barnes & Noble XML Web 服务的代码,可在 Send 菜单项的 Click 事件中找到。 因为这个 XML Web 服务已经作为 Web 引用被加入了,所需要的只是用已经提到的代理类进行的简单类初始化。
private void mitSend_Click(object sender, System.EventArgs e) { // Call Barnes & Noble XML Web service // The XML Web service returns a book's price based on its ISBN // WSDL is located at: http://www.xmethods.net/sd/2001/BNQuoteService.wsdl Cursor.Current = Cursors.WaitCursor; // ApplicationData class ApplicationData applicationData = new ApplicationData(); try { // Initialize Web service net.xmethods.www.BNQuoteService bn = new ISBNAnyplace.net.xmethods.www.BNQuoteService(); // Call Web service float price = bn.getPrice(txtBookISBN.Text); // Store ISBN and price to XML file ApplicationData.New(txtBookISBN.Text, price.ToString()); // Populate listview PopulateListview(); } catch(Exception ex) { Cursor.Current = Cursors.Default; MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); } finally { txtBookISBN.Text = ""; } Cursor.Current = Cursors.Default; }
在一行代码中,调用外部的 XML Web 服务并捕获其响应。 大体上,这个示例代码展示了从编码角度来看在 Smartphone 应用程序中使用 XML Web 服务是非常简单有效的。
为分发而打包
当应用程序已经生成、测试并证明后,就到了部署它的时候了。 现在应将应用程序提供给用户,但是我们所谈的是 Smartphone,标准的 PC/CD 安装可能无法实行。 首先,因为用户的 PC 上可能根本没有安装 ActiveSync,其次,因为安装工作应该可以在任何地方进行才对。
打包
您可以使用 Visual Studio .NET 2003 来创建安装用的压缩文件(.cab)。 要这么做,请使用“Release”配置加载并生成项目。 选择 Build/Build Cab File 生成用来创建压缩文件的批处理文件。 批处理文件名为“BuildCAB.bat”,位于 <project path>/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 处理器/文件夹中)。 当这些改变完成并且批处理文件运行后,压缩文件会在项目文件夹下的一个文件夹(<project path>/cab/Release)中生成。 每个文件的前缀说明了它的目标处理器。 这就是 Smartphone 的安装,如果这个文件被拷贝到某一设备并被选择(比如说,用快捷键),这个应用程序就会被安装。
但是,如果将生成的压缩文件安装到设备上,您将会发现应用程序的名称与 Visual Basic .NET 中使用的项目名称是相同的。 此外,公司名称设置为“My Company”,您可能不想使用这个名称。 如果要自定义压缩文件的创建,您需要查看有批处理文件的那个文件夹(在 <project path>/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 文件”)
更新 .inf 文件时,您可以运行与 .inf 文件在同一文件夹中的批处理文件 (BuildCab.bat) 来生成一套新的压缩文件。
分发
用空中下载(over the air,OTA)分发应用程序的最简单方法,就是把压缩文件发布到Web页上去 有了上面创建的压缩文件(这里重命名为 sampleui.cab),用下面的 HTML 源码可以创建一个简单的Web页:
<html> <head> <title>Download</title> </head> <body> <h2>Download Sample</h2> This is where you download the application, just select the link to the <a href="sampleui.cab">sampleui.cab</a> file! </body> </html>
当这个页面加载到 Smartphone 浏览器上时,看起来像这样:
![smartphone_2003fig10](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig10.gif)
图10:在Internet Explorer 中下载页面
当链接被选中时,需要一个确认:
![smartphone_2003fig11](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig11.gif)
图11:确认下载
然后,当下载被确认时,显示出下面屏幕的序列:
![smartphone_2003fig12](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig12.gif)
图12:下载屏幕
![smartphone_2003fig13](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig13.gif)
![smartphone_2003fig14](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig14.gif)
在实际设备上,如果压缩文件没有签名,您还是会看到一个屏幕,它提示您确认安装。 以上就是与此有关的全部内容。
应用程序现在已经安装在 Smartphone 上,并且可以通过选择 Settings 和 Remove Programs 来卸载。
到压缩文件的链接也可以在邮件或短信(Short Message Service,SMS)中分发。 其他分发应用程序的方法还包括:
• |
把压缩文件作为邮件中的附件发送 |
• |
设置一个存储卡,当它插入时运行安装包 |
• |
使用一个包含压缩文件的桌面 ActiveSync 安装包 |
这里有一张来自 Smartphone 2003 SDK 帮助文件的图,它提供了一个很好的不同选项的概述:
![smartphone_2003fig15](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig15.gif)
图13: 应用程序分发选项
在实际方案中,最佳的解决方案经常是不同部署选项的组合。 由于带宽限制,您可能从一张存储卡中完成了首次安装,然后通过空中下载(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”)。
小结
这是您要分发 Managed Smartphone 应用程序所需使用的工具的初步介绍。 您有几个选项,如果想要为应用程序分发选择最佳解决方案,您需要仔细评估这些选项。
企业应用程序方案
自2002年以来在其企业中部署移动应用程序的公司数量剧增。 Pocket PC 平台(尤其包括 .NET 框架压缩版在内)使许多移动工作者更有效率地实现成本缩减及收益增加。 就像一般移动应用程序开发,最常使用 Smartphone 的方案包括如下:
• |
销售服务 |
• |
现场服务 |
• |
物流 |
• |
交通运输 |
• |
决策支持 |
有一些可用的技术和解决方案可在企业方案中支持移动工作者。 有一段时间,只有膝上型电脑、Tablet PC、Pocket PC和较简单的移动电话可用。 Smartphone 2003 已将 .NET 框架压缩版整合到 ROM,因此有新平台可供应用程序设计者和开发人员使用。 新平台的强大解决方案层面包括它的外观造型(大小)、它的内建电话功能、它的高级连接功能(包括 SMS 和 Internet),还有查看信息比输入数据更重要。
在企业方案中实施的 Smartphone 2003 解决方案可使信息系统和过程延伸到有移动工作的任何地方。 因为不需要手动处理步骤及减少人员管理资料的次数,所以移动连接型的应用程序有增加处理效率的能力。 由于减少二次处理表单的机会而使得信息质量提高,而且大量数据产生更少错误。 所有这些优点可提高效率(成本缩减)及客户满意度(收益)。
在现场服务的方案中,现场技术人员可以在途中迅速获得工作命令。 在现场,现场技术人员可以查看详细的工作命令信息,当工作完成时,可以很快填妥大部分工作命令明细,只剩下少部分明细交给 back office 员工填写。 典型的现场服务方案如下:
![smartphone_2003fig16](http://www.microsoft.com/china/MSDN/library/Mobility/pocketpc/art/smartphone_2003fig16.gif)
图14:典型现场服务方案
Smartphone 应用程序最可能提供适当支持的是“执行工作”和“报告工作”这两个处理步骤。 由于有越来越多的 Smartphone 包含内置相机,所以现场技术人员甚至可以在报告工作时包含现场图像,以便追踪或远程协助。
在决策支持方案中,经理和行政主管可以有效率地查看和监督重要商业事件和高层最新财务摘要。 由于 Smartphone 同时具有 SMS 和 Internet 功能,所以进入的 SMS 可以唤醒电话,并自动从公司的IT基础架构中获取重要信息。 决策支持解决方案的驱动性主题是把正确信息带给管理层,以加速决策的产生。 Smartphone 应用程序可以把许多这类解决方案带到许多不同类型的公司手中。
小结
本文旨在为开发电话应用程序、设计正确的用户界面、规划应用程序数据存储、使用和利用 XML Web 服务、为分发而打包应用程序以及了解有关适合 Smartphone 应用程序开发的主要企业方案而提供重要信息。
本文全篇的关键层面是如何在 Smartphone 2003中善用 Visual Studio .NET 和 .NET 框架压缩版支持。新平台已经为消费者市场和企业市场的成功作好准备。 Combined with appealing design, phone functionality, Internet connectivity and .NET Compact Framework support, the stage is set for you to start realizing your ideas.结合诱人的设计、电话功能、Internet 连接和 .NET 框架压缩版支持,这个舞台已经准备就绪,您可以开始实现梦想。
转自:MSDN