在设计时使用 Microsoft .NET Compact Framework 1.0 调试自定义控件

翻译|其它|编辑:郝浩|2006-03-28 21:20:00.000|阅读 1187 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>


适用于:
Microsoft .NET Compact Framework 1.0
自定义控件调试

摘要:利用本文描述的技巧研究如何调试 .NET Compact Framework 控件的设计时版本。

*
本页内容
简介
使用 Windows 窗体测试设计时控件的问题
在设计时调试 Windows 控件库
尝试在设计时调试 .NET Compact Framework 控件
解决方案:借用整个 .NET Framework
示例应用程序
设置并运行项目
小结

简介

作为 Microsoft .NET Compact Framework 1.0 开发人员,我们清楚地看到,只需很少的内存和处理能力,便能调整整个 .NET Framework,以使其在智能设备(例如,Microsoft Pocket PCs 和 Windows CE 掌上设备)上运行。.NET Compact Framework 1.0 最大程度地支持整个框架,以维护仅为 2 MB 的内存足迹,而这对于压缩设备进行处理来说是可行的。这不包括设计时功能,因为我们是在桌面计算机上编写并编译我们的 .NET Compact Framework 代码,而不是在设备本身上。该编译器足够智能,可以生成专门运行在这些微型设备上的库和可执行文件,只是当窗体在可视化设计器展开时,没有足够的空间来包括对仅在开发过程中使用的库的支持。

到目前为止,您可能想知道,为什么 Microsoft Visual Studio .NET 包含一些可以拖放到智能设备 Windows 窗体上的控件(例如,按钮和标签)?当 .NET Compact Framework 中缺少设计时支持时,Microsoft 开发人员如何添加对 .NET Compact Framework 控件的设计时支持?幸运的是,尽管 .NET Compact Framework 缺少这种支持,我们仍然可以使用该功能。为了使其工作,我们必须编译该库的两个不同版本 — 一个在运行时用在设备上,另一个导入工具箱以用于 IDE 设计时体验。

该库的设计时版本仅引用 System.dll 的 .NET Compact Framework 版本。我们库的设计时版本引用 System.dll 的两个实现 — 一个用于 .NET Compact Framework 版本,另一个用于整个框架。通过首次用我们的命令行生成指令引用 System.dll 的 .NET Compact Framework 版本,将使用 .NET Compact Framework 版本的冲突命名空间,而且 .NET Compact Framework 不包含的整体框架部分也会使用该库进行编译。其中也包含一些好的设计时功能,可以在开发过程中用到。

编译一个引用两个表面上相同的库(System.dllSystem.dll)的解决方案可能产生一些混淆,最初比较难掌握,特别是当我们仅能通过 C# 命令行编译器成功编译该项目类型时。在尝试编译此类解决方案时,Visual Basic .NET 命令行编译器会生成一个错误,因此不能用于开发带有设计时支持的 .NET Compact Framework 控件。至于这样对您来说是好消息还是坏消息,还要取决于您所使用的语言。如果您喜欢用 C#,但像我一样进行 Visual Basic .NET 方面的工作,这对您来说是非常好的消息。

本文的重点并不是介绍用 C# 开发设计时控件 — 关于该主题已经有了其他一些好文章(请参阅参考)。本文将介绍一个用于在设计时调试这些控件的方法,它借用了整个 .NET Framework。在解释它的工作机制之前,我首先概述一下许多 .NET Compact Framework 设计时控件开发人员所面对的问题,以及我撰写本文的动机。

使用 Windows 窗体测试设计时控件的问题

您有多少次修改控件的外观,然后仅为了看看控件外观如何而不得不在模拟器中运行您的测试项目呢?我们之所以这样做,只是因为该控件的设计时版本已过时,而且不显示新的更改。您可以看到,该测试项目必须物理地引用该控件的设计时版本(请参见图 1)。其结果需要我们确保在测试窗体中引用了正确的设计时版本;但是,我们会看到这有点麻烦。


在将控件添加到工具箱并拖到窗体上时,该控件的设计时版本会激活,因此会占用内存空间。具有交互式设计时功能的不利之处在于,如果不将控件从内存中释放,就无法在设计时模式中重新编译该控件。

另一方面,过时的设计时版本完全不能感知该代码的运行时版本。当该测试项目在模拟器中运行时,执行并显示最新的代码。对该库的运行时版本的引用与设计时版本是分开的,而且由于它当前没有运行在设计器中,因此它经过编译后只能在模拟器中很好地运行。

要编译该控件的设计时版本,我们需要执行以下操作:将测试项目从我们的解决方案中移出,重启 Visual Studio .NET,编译设计时版本,然后重新添加该测试项目。很多开发人员可能认为这样做太麻烦,而且如果控件没完成,就不能更新工具箱。遗憾的是,该控件的所有调试操作都必须从模拟器进行,根本不会使用设计时特定的代码。对此有一个更好的方式,而且它完全是以整个(而且优秀的).NET Framework 入手的。

在设计时调试 Windows 控件库

在整个 .NET Framework 中,对于在设计时调试控件的过程,可以使用内置在 IDE 中的一个灵活功能,它允许我们在 IDE 的另一个实例中进行调试。该功能节省了很多开发时间,因为它使我们能够轻松地调试控件的设计器部分,从而使控件在被拖到 Windows 窗体上时可以正确显示其本身。

要在 IDE 的另一个实例中进行调试,需要修改该项目的属性页,以便将调试模式设置为“程序”,并将启动应用程序设置为 Visual Studio .NET IDE 的可执行文件 — devenv.exe。在将启动项目设置为控件库时,该调试器会在调试会话期间打开 IDE 的第二个实例。在该调试会话期间,应该打开宿主 Windows 窗体应用程序,并将正在测试的控件添加到工具箱中。在将控件拖到窗体上后,控件便激活了,并开始执行初始化方法,以及从属性页设置属性。在控件方法中设置的断点将在 IDE 的第一个实例中被点击,可以在将控件拖到窗体之前单步执行这些断点。

要更清晰地掌握上述步骤,请阅读 Steve Lasker 的文章 Debugging Design-Time Controls。这篇文章中用于调试设备控件的技术非常类似于本文中的技术,只是进行了少量调整。

尝试在设计时调试 .NET Compact Framework 控件

我们也可以使用一些指令来修改 .NET Compact Framework 类库的属性页,以便在部署期间启动 devenv.exe 程序。图 2 中的屏幕快照显示了已设置为只进行此操作的 Pocket PC 类库的属性页。


遗憾的是,当我们尝试使用设置为启动项目的类库运行我们的应用程序时,Visual Studio 最初开始正常部署,然后显示如图 3 所示的错误消息,其内容为“带有类库输出类型的项目无法直接启动。”单击 OK 后,该项目会退出调试模式,而且输出窗口会显示有关前面的生成和部署方法已成功的消息。但我们知道它们并没有成功,因为我们根本无法调试我们的类库。


解决方案:借用整个 .NET Framework

解决该问题的方法是添加一个 Microsoft Windows 控件库,并将该项目用作启动项目,就像我们要调试一个正规桌面控件库一样。该解决方案中的不同之处在于,Windows 控件库不会包含我们的控件 — 它只作为将打开 IDE 的调试实例的启动程序。启动该调试会话时,我们会打开一个将宿主要测试控件的智能设备 Windows 应用程序。在将智能设备控件放到宿主应用程序中的窗体上之后,可以设置控件中的断点。

图 4 描述了该解决方案的可视化模型。Visual Studio .NET 的第一个实例包含三个项目 — 用于宿主 .NET Compact Framework 设计时控件的智能设备类库(设计时控件);一个用于生成设计时版本控件的 C++ 生成文件项目(设计器);一个用于启动 Visual Studio .NET 的第二个实例的 Windows 控件库项目(设计调试器)。该设计调试器项目设置为启动项目,并配置为在另一个 Visual Studio .NET 实例中进行调试。在调试模式中运行该项目之后,启动 Visual Studio 的第二个实例。Visual Studio 的第二个实例包含一个智能设备 Windows 应用程序(测试宿主解决方案)。在将设计时控件从工具箱拖到测试宿主解决方案中的窗体上时,可以在 Visual Studio 的第一个实例中单击在控件代码中设置的断点,并使用该调试器逐句通过设计时代码。


示例应用程序

为了体会它的工作原理,我们将添加对 DateTimePicker 控件的设计时调试支持,该控件来自于 Jim Wilson 的文章 Adding Designer Support to the .NET Compact Framework DateTimePicker Control。Jim Wilson 文章中的项目包含:DateTimePickerControl,它宿主该控件;DateTimePickerControl.Design,它编译该控件的设计时版本;DateTimePickerControl.Deployment,它生成该控件的安装文件。我们还将向其中添加一个项目:DateTimePickerControl.DesignDebugging,它是一个 Windows 控件库,用于在设计时帮助调试 DateTimePickerControl

设置并运行项目

要获取设计时调试以使用 DateTimePickerControl,所需的步骤如下所示。我们会详细介绍每个步骤。

1.

添加一个 Windows 控件库项目。

2.

移除不必要的文件和引用。

3.

修改属性页。

4.

设置启动项目。

5.

设置断点。

6.

创建一个测试项目。

7.

运行DateTimePicker 项目。

8.

打开测试项目并安装工具箱。

9.

从设计器初始化断点。

步骤 1:添加一个 Windows 控件库项目

我们的新 DateTimePickerControl.DesignDebugging 项目(一个 Windows 控件库)应该添加到我们现有的 DateTimePicker 项目中。


添加完项目后,该解决方案资源管理器

步骤 2:移除不必要的文件和引用

我们的新项目仅用于启动一个 Visual Studio 调试实例,不会使用任何文件或引用。为了避免混淆,我们会移除该项目中的所有引用和默认文件。


步骤 3:修改属性页

为了启动设计时调试,我们需要修改 Windows 控件库的属性页。在“配置属性”部分和“调试”子部分中,将调试模式设置为“程序”并单击 Apply。“启动应用程序”字段应该由灰(禁用)变黑(启用)。单击“启动应用程序”字段中的“…”按钮,并浏览到 Visual Studio .NET 的可执行文件 (devenv.exe) 所处的位置。在我的计算机上(我使用了默认安装),该文件位于:

C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO .NET 2003\COMMON7\IDE\devenv.exe

选择该文件夹中的“devenv.exe”并单击 Open

步骤 4:设置启动项目

该 Windows 控件库项目应该设置为启动项目,如图 9 所示,当我们在调试模式中运行该解决方案时,DateTimePickerControl.DesignerDebugging 项目将启动 Visual Studio.NET 的第二个实例。


步骤 5:设置断点

为了在调试时逐句通过我们的设计时代码,我们需要在将控件放到窗体上之后,在将要执行的方法内设置断点。这包括初始化该控件的方法,例如,构造函数、在将控件拖到窗体之前激发的 OnEvents,如 OnPaintBackgroundOnPaint 事件。对于我们的示例,我们会在 DateTimePicker 类中代码的 OnPaint 部分中设置一个断点。

步骤 6:创建测试项目

既然我们已经使用 DateTimePickerControl.DesignDebugging 项目添加了设计时调试支持,现在就让我们创建一个在调试会话期间作为测试主机运行的新项目。该项目应该是一个智能设备 Windows 应用程序,而且应该放在其自己单独的解决方案中,

当该智能设备应用程序向导弹出来之后,请确保该项目类型设置为“Windows 应用程序”,如图 12 所示。在本例中,我们选择 Pocket PC 作为目标平台,但也会用到 Windows CE 平台。


步骤 7:运行 DateTimePicker 项目

当我们运行 DateTimePicker 项目时,会弹出图 13 中显示的 Compact Framework 部署窗口,就像我们要在模拟器中或设备上调试该项目一样。在选择 Pocket PC 模拟器并单击“部署”后,会打开该 Pocket PC 模拟器。这可能引起一些混淆,因为我们的启动项目是一个根本不用 Compact Framework 或模拟器的 Windows 控件库。但是,当模拟器打开后,将打开 Visual Studio .NET 的第二个实例,并作为调试程序运行,而且我们可以忽略该模拟器的运行实例。


步骤 8:打开测试项目并安装工具箱

在 Visual Studio .NET 的第二个实例中,打开我们在前面的步骤 6 中创建的 SmartDeviceTestHost 项目。将 DateTimePickerControl 的设计时版本添加到工具箱中。请确保添加该控件的调试版本,因为该发布版本不包括允许我们从设计器初始化断点的任何调试符号。图 14 显示了 Visual Studio .NET 调试实例工具箱中的 DateTimePicker 控件。


步骤 9:从设计器初始化断点

打开 Form1.cs 的设计视图(如图 14 所示),并将 DateTimePicker 控件添加到窗体上。这应该初始化放在 Visual Studio 第一个实例的控件代码中的断点。当控件代码处在初始化以及将其自身显示到窗体的过程中时,我们可以单步执行控件代码。

小结

在本文中,我们已经探讨了如何调试 .NET Compact Framework 控件的设计时版本。我们已经看到,向控件添加设计时支持的过程是复杂的,因为我们需要生成两个单独的库 — 一个用于运行时,另一个用于设计时。一旦您理解了该解决方案,您会认识到,在设计时调试 .NET Compact Framework 控件的过程基本上和调试整个框架的控件是相同的。在设计时测试控件最容易令人混淆的方面(无论这些控件是用于 .NET Framework 还是 .NET Compact Framework),就是打开并作为调试程序的第二个 IDE 实例。对于 .NET Compact Framework,我们看到,要让它工作,需要进行一个轻微调整,即从整个框架借用一个 Windows 控件库,并将该项目用作设计时调试启动程序。

虽说我们的设计时测试项目的初始安装可能是多余的工作,但在编写自定义控件的实际情况中,在设计时测试控件的功能常常可以帮助您节省大量时间和精力。首先,该控件在模拟器或设备上的外观甚至是行为方式与在窗体设计器上都不可能相同。在控件显示在 Windows 窗体设计器上之前,逐句通过控件的唯一方式就是通过设计时调试。

其次,经过论证可知,通过 IDE 调试控件外观比用模拟器快得多,通过物理设备本身尤为如此。该模拟器是调试动态控件行为和交互不可或缺的,但是当我们生成控件外观,能够在 IDE 中快速调试它将非常好。总之,该控件的设计部分借用了整个框架,因此我们也可以利用这个丰富的环境,而不是只局限于在模拟器和设备中进行调试。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP