Bienz.UI - 跨设备用户控件






3.75/5 (4投票s)
一个 .NET 库,包含多个可在 Windows 和 Pocket PC 上运行的控件
![]() |
![]() |
Windows 中的示例控件 |
Pocket PC 上的示例控件 |
![]() |
![]() |
Windows 中的示例向导 |
Pocket PC 上的示例向导 |
前言
Bienz.UI
是一个控件集合,旨在简化程序员的用户界面开发。目前,库中只有三个控件,但这个数量会继续增加。最重要的是,我从一开始就解决了跨设备支持的问题。这要求我学习一些关于 Visual Studio 如何处理项目文件的知识,但最终我拥有了一个极易维护的、可为多个平台编译的库。
本文讨论了我必须克服的一些困难,以及 Pocket PC 的智能设备扩展和 Compact Framework 的一些限制。智能设备扩展 (SDE) 和 Compact Framework (CF) 目前都可通过 Microsoft 的 Beta 版获得。您可以通过以下网址申请获取 Beta 版
http://www.gotdotnet.com/team/netcf/default.aspx
请记住,此 Beta 版仅通过提名提供(这意味着 Microsoft 可以选择谁可以下载它)。
注意
您必须安装智能设备扩展/Compact Framework Beta 版才能使用任何 Pocket PC 源代码或示例程序。与 Bienz.UI
的 Windows 部分交互时,它不是必需的。
框架的差异
Compact Framework 顾名思义,是完整 .Net 框架的一个子集。即便如此,我没有发现任何我需要的对象缺失(请记住这是一个相当简单的项目)。然而,我发现的是,一些对象已被重命名,一些方法的参数不同,以及一些对象的行为略有不同。对我来说,这不太能接受——我怀疑 Microsoft 在最终产品中也不会接受(我们只能希望如此)。
下面,我列出了我在完整框架和 Compact Framework 之间发现的主要差异。我确信还有许多其他差异,这些是影响本项目的差异
- 不包含控件设计器
我很高兴看到表单设计器如期出现在这个 Beta 版中,但控件设计器仍然缺失。我对此有点困惑,因为它们非常相似。事实上,当我需要处理 Pocket PC 控件时,我只需将基类更改为Form
,然后就可以使用表单设计器。我甚至使用了条件编译语句来为我完成此操作,并设置了两个项目配置文件,以便我可以“切换”此功能。
- 无法设计继承的表单
尽管表单设计器在此 Beta 版中有效,但您仍然无法设计继承自其他表单的表单。(因此,您无法设计继承自其他控件的控件——即使您使用上面提到的条件编译技巧)。
- 无法设置控件的名称
事实上,似乎根本没有 name 属性……?
- 无法设置控件的 Tab 索引或 Tab 停止
Pocket PC 上显然没有 Tab 键,但控件的寻址顺序(绘制、Z 顺序等)似乎是它们在 .CS 文件中定义的顺序。
- 无法使用设计器设置图像属性
即使控件具有Image
属性,也无法在此 Beta 版的表单设计器中设置。Microsoft 展示了一种解决方法,即将图像作为资源添加到程序集中,然后按名称加载。我在Bienz.UI
的 Pocket PC 版本中频繁使用这种解决方法,但它非常耗时。
- 控件数组不支持 AddRangeWindows 表单设计器定义控件,然后使用
Controls.AddRange
一步将所有控件添加到 Controls 集合中。由于 Pocket PC 不支持AddRange
方法,因此必须通过调用Controls.Add(Control)
分别添加每个控件。
- 对话框和消息框的 Owner 参数被省略
我不确定这是为什么;也许 Pocket PC 中的所有对话框都在系统级别,没有所有者?
- MessageBox 实现不同
消息框图标在外观上仍然相似(如果不是相同),但名称不同。Windows 上的MessageBoxIcon.Information
在 Pocket PC 上是MessageBoxIcon.Asterisk
。Pocket PC 版本还有一个必需的第三个参数,用于指定哪个按钮将是默认按钮(当用户按下 Pocket PC 上的操作按钮时将单击的按钮)。此参数是一个枚举,但枚举只是 Button1、Button2 和 Button3。
- Checkbox 控件缺少 CheckChanged 事件您仍然可以使用 click 事件。
- Control.Font 导致异常
Control
基类的Font
属性存在,但尝试读取或写入它会导致抛出异常。这对我来说是一个很大的麻烦,因为我必须使用new
修饰符创建自己的Font
属性,但如果我需要将派生控件转换为Control
,我将无法访问此属性。如果您找到解决方法,请告诉我。
Bienz.UI 包含的控件
DriveCombo (仅限 Windows)
驱动器下拉列表显示机器中当前所有可用的驱动器,包括本地驱动器、可移动驱动器和网络驱动器。此控件继承自标准下拉列表,并使用我的 Bienz.SysInfo
类获取渲染控件所需的系统信息。您可以在这篇文章中阅读有关 Bienz.SysInfo
的信息。
如果驱动器标签可用,列表将显示驱动器标签;如果不可用,则显示驱动器类型的描述。还会使用 Bienz.SysInfo
提供的图标(该图标又来自 shell)为驱动器绘制一个图标。其他文章已经讨论过获取此图标并以类似方式使用它,但用户注意到 Windows XP 中图标周围出现的黑色边框。我通过使用 shell 提供的 32x32 图标并将其重新采样到 16x16 来避免这个丑陋的黑色边框。这需要更多的开销,但由于列表永远不会包含超过 26 个项目,我觉得这是值得的权衡。此外,它使图标具有漂亮的模糊高彩外观。
此控件的 SelectedItem
属性返回 Bienz.SysInfo
中内置的 VolumeInformation
类的实例。此类别提供有关所选驱动器的详细信息。同样,请阅读本文以获取更多信息。
ImageButton (Windows 和 Pocket PC)
ImageButton
的构建有两个原因。首先,最重要的是 Pocket PC 不支持其完整框架按钮对应项的图像属性。其次,我希望能够制作支持鼠标悬停图像等类似 Flash 的按钮。该按钮支持以下状态的图像和事件
- 正常
- 鼠标悬停(仅限 Windows)
- 按压
- 禁用
ImageButton
还支持在按钮中心以任何字体/大小绘制文本。您还可以定义当按钮按下时文本偏移的像素数量。文本可以在 X 和 Y 方向上偏移,也可以偏移负值。
向导 (Windows & Pocket PC)
Wizard 组件是 Bienz.UI
中最酷的补充。它确实需要自己的文档,希望我很快会有时间编写它。Wizard 组件提供了一个框架,用于在您自己的应用程序中创建高度可定制的向导步骤。这是通过三个主要类实现的
- Wizard
Wizard
是一个表单类。该表单的尺寸与您在 Windows 中找到的大多数标准向导相同。它包含可更改文本的标题和副标题标签、可更改的股票图像,以及可显示、隐藏、启用和禁用的后退、下一步、取消和帮助按钮。
在 Windows 中,按钮显示为普通的带文本按钮,描述了单击时将执行的操作。然而,在 Pocket PC 上,我希望为页面保留尽可能多的空间。我决定将按钮移到“任务栏”区域,并使用图像按钮代替标准文本按钮。如果有人觉得这是一个问题,或者您认为有更好的解决方案,请告诉我。
- WizPage
WizPage
是一个基控件,您可以从中派生以设计自己的自定义页面或步骤。在 Windows 和 Pocket PC 中,WizPage
基控件的尺寸都适合相应的Wizard
。此基控件还提供了对您有用的内置属性。例如,Wizard
属性将返回您页面正在显示的Wizard
实例。
- WizPageCollection
WizPageCollection
不单独使用,而是作为Wizard
类的一个属性使用。WizPageCollection
包含已添加到Wizard
的所有页面,并且还包括搜索功能。
由于您可能希望根据用户输入动态地从Wizard
中添加和删除页面,因此WizPages
可能并不总是在固定索引处。WizPageCollection
允许您使用FindFirst(Type)
和FindLast(Type)
等方法按类型搜索集合中的页面,还可以使用FindNext(WizPage)
和FindPrevious(WizPage)
等方法按相对位置搜索。WizPageCollection
还会自动通知Wizard
更改,这反过来又允许Wizard
启用或禁用按钮,并酌情将“下一步”按钮更改为“完成”。
并排设计
我面临的一个问题是让两个不同的项目共享相同的源文件。这显然很重要,因为我不想在两个单独的 .CS 文件中维护更改。然而,无论何时您为另一个目录中的文件选择 添加现有项,它都会被 复制 到您的项目目录中。解决这个问题的方法是将两个项目放在同一个文件夹中并给它们不同的名称。
这种方法的明显缺点是,编译器会将两个项目的输出文件都放到同一个文件夹中(bin\Debug 和 bin\Release)。我意识到了这一点,并将项目设置更改为将文件输出到它们自己的文件夹中(bin\PocketPC\Debug、 bin\Windows\Debug 等)。
接下来,我担心编译器会在 obj 文件夹中互相干扰。每当执行构建时,中间文件都会进入 obj 文件夹。我担心构建总是将文件放在例如 obj\Debug 中,然后稍后将它们移动到 bin\PocketPC\Debug。事实证明,编译器比那要智能一些(谢天谢地),它实际上会自动将中间文件放入 obj\PocketPC\Debug 中。
最后,我需要解决完整框架和 Compact Framework 之间的差异。这很容易通过条件编译语句解决。这里唯一需要注意的是在自动生成的代码块中使用条件语句。在我养成正确使用它的习惯之前,这给我带来了几次问题。例如,您几乎肯定需要在 InitializeComponent
方法中使用条件语句。但该代码是由表单设计器自动生成的,这意味着您下次打开设计器时,您的条件语句将被清除。诀窍是 复制整个方法 并在整个方法周围放置条件语句。至少设计器似乎在这种方式下找到了正确版本的方法,并且您的更改不会丢失。
摘要
在开发这个多设备库时,我学到了更多关于 Visual Studio .NET 和 Compact Framework 的知识,超出了我真正想知道的范围。即便如此,它比预期的要顺利得多,而且显然比任何其他平台上的任何多设备集成都要 顺利得多。
微软已经大踏步地将此作为设备应用程序开发的未来,即使在测试版中,我也给予他们充分的赞扬。我焦急地等待最终版本的发布,但即使还有几个月的时间,我也不会劝退任何人开始编写自己的 .Net Pocket PC 应用程序。