以编程方式使用 Microsoft Office Visio 2003 ActiveX 控件

Mark Bukovec
Empire Down Development

适用于:
Microsoft® Office Visio® 2003

**摘要:**学习将 Microsoft® Office Visio® 2003 ActiveX® 控件(即 Visio 绘图控件)集成到应用程序中。查看最佳作法以及如何以编程方式使用 Visio 绘图控件。

本页内容

简介 简介
了解 Visio 绘制控件 了解 Visio 绘制控件
使用 Visio 绘图控件的场景 使用 Visio 绘图控件的场景
设计最佳作法 设计最佳作法
开始使用 开始使用
将控件与主机容器相结合  将控件与主机容器相结合
部署 部署
小结 小结

简介

Microsoft® Office Visio® 2003 ActiveX® Control(Visio 绘图控件)通过丰富的 Visio 对象模型,作为可嵌入组件来提供 Visio 应用程序的完整功能。您可以通过宿主应用程序中的事件或代码,以编程方式驱动 Visio 绘图控件。此外,Visio 绘图控件可以在您自己的应用程序用户界面 (UI) 的上下文中为应用程序用户提供图表制作环境。

在本文中,您将学到:

  • Visio 绘图控件的功能和示例使用场景。

  • 在 Visio 解决方案中使用 Visio 绘图控件的最佳作法。

  • 如何将 Visio 绘图控件嵌入到各种宿主应用程序中,包括 Microsoft Windows®窗体、Microsoft Visual Basic®6.0 窗体、Microsoft Office 文档以及 Microsoft Internet Explorer。

  • 如何使用 Visio 绘图控件 API 的属性。

  • 如何将 Visio 文档加载到绘图控件窗口并保存更改。

  • 如何获得对 Visio Application 对象的引用,以便以编程方式使用 Visio 文档。

  • 如何管理绘图画面的显示。

  • 如何将控件与宿主应用程序用户界面相结合。

  • 如何利用应用程序部署 Visio 绘图控件。

了解 Visio 绘制控件

Visio 绘图控件将在组件中提供 Visio 应用程序对象模型的功能。Visio 绘图控件可以嵌入使用 Microsoft Visual Studio®.NET 2003、Microsoft Office XP 和 Microsoft Office 2003 容器(如 Microsoft Office Word 2003、Microsoft Internet Explorer 5.0 以及更高版本和其他 Microsoft ActiveX® 控件容器)开发的宿主应用程序中。添加 Visio 绘图控件后,该控件就会为显示形状提供绘图画面。

Visio 绘图控件允许开发人员在另一个应用程序的上下文内提供 Visio 功能。这种新级别的集成允许开发人员完全控制与宿主应用程序相结合的 Visio 用户界面。该新增功能更为强大,而不仅仅是将 Visio 绘图嵌入到 OLE 容器文档(如 Word)中。将 Visio 绘图用作 OLE 对象允许您查看容器应用程序中的关系图、将 OLE 对象链接到实际 Visio 文档以反映更改以及通过从容器文档内激活 Visio 应用程序来编辑 Visio 绘图。

在就地 OLE 激活的情况下,您仍然工作于 Visio 用户界面内。您无法创建自己的 UI。无法通过使用包含应用程序的自动功能来以编程方式访问 Visio 文档。您还会受限于只能使用实现 OLE 容器的应用程序主机,这样就不能使用诸如 .NET Windows 窗体之类的技术。

但是,Visio 绘图控件提供了解决这些情况的新功能,并且允许您开发在以前不可能开发的新 Visio 解决方案,例如本文以下 “使用 Visio 绘图控件的场景” 部分中介绍的那些解决方案。

Visio 绘图控件通过 Visio 产品安装发行。还有一个可用于对 Visio 绘图控件 API 进行托管代码访问的主 interop 程序集。如果要从托管代码使用该控件,则必须安装 Visio 主 interop 程序集。请参阅本文的“部署”部分以获得有关安装 Visio 绘图控件和 Visio 主 interop 程序集的详细信息。

使用 Visio 绘图控件的场景

要演示 Visio 绘图控件的实用性,请考虑以下客户场景。

  • 公司的行政部门为行政助理提供了一个办公空间计划应用程序。Windows 窗体作为绘图控件的宿主,显示代表办公室布局的区域。绘图控件旁边是代表办公室家具的按钮。当行政助理单击一个按钮时,就会在绘图窗体上放置一个形状,然后他可以在绘图控件上重新定位该形状以查看办公室中的家具布置外观。

    Windows 窗体包含一个以 Visual Basic .NET 编写的事件处理程序,它响应添加的新形状并且跟踪家具选择以生成采购定单。通过在绘图控件中删除形状,行政助理可以重新布置和取消家具选择。因为行政助理是从窗体的 UI 来操纵绘图画面的,所以用户无需熟悉 Visio 应用程序。

  • 一个管理团队正致力于制订员工工作流程图。为了有助于协作,该团队使用了 Microsoft Office SharePoint™ Portal Server,它为团队文档和工具提供了一个集中存储点,以便团队协作和共享文档。经理们并不熟悉绘图工具,并且他们希望在 Microsoft Office Excel 电子表格中输入工作步骤,然后让 Visio 从这些数据中生成流程图绘图。而且,他们希望在同一浏览器页面上查看所有的数据。

    要实现这些要求,应用程序开发人员需修改 SharePoint 站点上的团队页面,方法是添加显示用于定义工作步骤的 Excel 电子表格的数据表 Web 部件。然后,开发人员创建一个宿主绘图控件的自定义 Web 部件。开发人员将两个 Web 部件链接在一起,而在绘图控件内部会自动生成源自 Excel 中的工作步骤信息的流程图。如果某位经理想要修改该流程图,她可以编辑数据表 Web 部件中的行,然后刷新该流程图形状以反映所做的更改。该解决方案允许经理们在同一浏览器页面内使用他们最喜好的工具来完成所有的更新操作。

该控件可以让您使用各种主机容器构建如刚才介绍的事件驱动应用程序。您可以将绘图画面组件添加到现有的或规划的应用程序中,而不是构建宿主于 Visio 应用程序用户界面中的解决方案。对于 Visio 绘图控件,应用程序通常会反映如图 1 所示的体系结构。

图 1. 宿主 Visio 绘图控件的应用程序

在应用程序中使用 Visio 绘图控件提供以下优点:

  • Visio 绘图控件运行在应用程序的进程内,并且不要求运行 Visio 应用程序的单独实例。

  • 该控件针对每个实例显示单个 Visio 文档和单个窗口。可以通过将多个控件实例嵌入到宿主应用程序中来显示多个文档。Visio 绘图控件还公开了一个用于加载现有 Visio 文件的方法。

  • 该控件允许用户界面与宿主应用程序相结合。开发人员可以为不熟悉 Visio 的用户提供简化的用户界面。

  • 宿主应用程序可以通过嵌入控件实例来访问 Visio Automation 属性和方法。这允许宿主应用程序以编程方式修改包含的 Visio 文档。

  • 该控件直接公开 Visio Window 和 Document 事件。

您还可以使用托管代码来开发 Visio 绘图控件解决方案。托管代码互操作性通过 Visio 主 interop 程序集提供,这些程序集提供对 Visio 绘图控件 API 和 Visio Automation 库的托管代码访问。在出现该绘图控件之前,对于托管代码,只能使用托管语言编写 COM 加载项或可执行文件。使用该控件,您可以直接从应用程序执行 Visio Automation 代码。这种集成允许您将 Windows 窗体用作应用程序容器并且以托管语言(例如 Visual Studio C++、Visual.NET C# 或 Visual Basic .NET)编写代码。

设计最佳作法

因为 Visio 绘图控件是可编程组件,您可以直接将 Visio 解决方案代码集成到主机容器应用程序中。在以前的 Visio 版本中,开发人员为 Visio 客户端应用程序编写解决方案时,需要在 COM 加载项、Visio 解决方案库 (VSL)、进程外可执行文件或在文档中的 Visual Basic for Applications (VBA) 项目中打包解决方案代码。

通过允许从宿主应用程序对 Visio Application 对象进行编程,Visio 控件简化了解决方案体系结构和开发过程。在自定义应用程序(例如 C# 应用程序)或 Internet Explorer 中使用控件的开发人员应该直接针对宿主应用程序中的 Visio 对象模型进行编程,而不必将 Visio 逻辑分隔到 COM 加载项、VSL 或可执行文件中。从宿主应用程序中调用 Visio COM 加载项、VSL 或可执行文件,使得 Visio 集成的调试复杂化了,这毫无必要。

但是,如果希望在 Microsoft Office System 应用程序而不是在 Visio 中宿主 Visio 控件,则必须使用 COM 加载项。在这种情况下,为宿主应用程序(而不是 Visio)创建一个 COM 加载项。例如,如果您计划将 Visio 控件宿主于 Microsoft Office Word 2003 文档中,则创建一个 Word COM 加载项,然后通过该 Word 加载项访问 Visio 控件。确保该主机的目标是 COM 加载项,因为 Office 宿主应用程序将不会加载绘图控件的 Visio COM 加载项。

使用控件主机限制

Visio 绘图控件支持很多容器,其中包括构建在 Visual Studio.NET 2003、Visual Studio 6.0、Internet Explorer 5.0 或更高版本、ASP.NET 以及其他 ActiveX 控件容器中的宿主应用程序。但是,Visio 控件无法直接嵌入到:

  • 另一个 ActiveX 控件中,如 Internet Explorer 浏览器控件。

  • Visio 文档。

  • Microsoft Office InfoPath™ 2003 表单。

注 可以将 ActiveX 控件嵌入到 Visio 绘图控件中(而不是将 Visio 绘图控件嵌入另一个 ActiveX 控件中)。但是,因为 Visio 绘图控件无法在 Visio 文档中执行 VBA 代码,所以最好将其他 ActiveX 控件集成到宿主应用程序项目中,而不是集成到 Visio 文档中。

将 Visio 控件用于 Internet Explorer 浏览器控件中

即使无法直接将 Visio 绘图控件嵌入到另一个 ActiveX 控件中,您仍然可以利用依赖于 Internet Explorer 浏览器控件的应用程序来使用 Visio 绘图控件。

Internet Explorer 5.0 或更高版本为 Visio 绘图控件提供了非常优秀的主机容器,允许开发人员根据 Microsoft Visual Basic Scripting Edition (VBScript) 中的 Visio 对象模型或者根据由 European Computer Manufacturers Association 规范定义的 ECMAScript 来编写脚本,例如 JScript 或 JavaScript。

要将 Visio 绘图控件与基于 Internet Explorer 浏览器控件的应用程序相结合,例如 Microsoft Office Project Web Access 客户端,请执行以下操作:

  1. 在 Internet Explorer 浏览器控件中添加一个链接,该链接利用其自己的窗口启动新的 Internet Explorer 进程。

  2. 将 Visio 绘图控件嵌入到新的 Internet Explorer 窗口中以用于新的 Internet Explorer 进程。

  3. 使用您喜欢的脚本语言根据 Visio 绘图控件进行编程。

将 Visio 控件用于 Microsoft Office InfoPath 2003 中

尽管无法将 Visio 绘图控件直接嵌入到 InfoPath 2003 表单,InfoPath 还是提供了包含 Internet Explorer 窗口的解决方案任务窗格。您可以将 Visio 绘图控件直接嵌入到该 InfoPath 解决方案任务窗格窗口中,然后使用文档对象模型 (DOM) 以在 Visio 绘图和 InfoPath 表单之间共享数据。

了解 Visio 绘图控件的 SDI

当设计使用 Visio 绘图控件的应用程序时,了解 Visio 控件在单个窗口中支持单个文件非常重要。由于该控件的单文档界面 (SDI) 体系结构,所以在设计集成 Visio 绘图控件与应用程序时要考虑以下事项:

  • **使用 Visio 绘图控件的多个实例以在应用程序中显示多个 Visio 文档。**Visio 客户端应用程序可以同时显示多个文档和窗口,Visio 绘图控件与其不同,它只能针对每个控件的实例显示一个单一文档。如果开发人员要显示多个 Visio 文档,开发人员可将该控件的多个实例嵌入应用程序,每个实例加载一个单独的 Visio 文档。

  • **不依赖于 VBA 对逻辑进行编程。**VBA 没有包括在 Visio 绘图控件中。因此,在 Visio 绘图控件中加载的文档不会执行任何与该文档相关联的 VBA 代码。控件缺少 VBA 运行时环境会阻止通过由 Visio 控件加载的文档分发合法代码或恶意宏。它还意味着作为控件宿主的应用程序用户将永远不会看到 Visio 应用程序的警告有关文档中的宏的安全对话框。

  • 以编程方式使用 Visio ShapeSheet®**。**该控件不提供到 Visio ShapeSheet 用户界面的访问,该界面是 Visio 应用程序中的独立窗口。但是,ShapeSheet 本身仍然因为 Visio 绘图控件中加载文档中的 Visio 形状和页面而存在。您仍然可以使用Visio Automation 来编辑控件中 Visio 文档的 ShapeSheet 单元格。例如,您可以使用 Cell 对象的 Src 属性为 Visio 形状添加双击操作。

    注 对在控件中加载的文档的 ShapeSheet 进行编程时,您将无法使用 CALLTHIS 函数,该函数会调用文档中的 VBA 宏。Visio 绘图控件不执行 VBA 代码,因此所有对 CALLTHIS 函数的使用都会失败,同时不会出现任何提示。但是,您可以使用 Visio Page 和 Document 对象的鼠标事件,并在自定义容器应用程序逻辑中处理事件响应。(有关鼠标事件的详细信息,请参阅“处理事件”。)如果您使用的是 COM 加载项,则还可以使用 QUEUEMARKER 函数根据 ShapeSheet 中的双击事件队列 marker 事件。

迁移现有的 Visio 解决方案

在将代码从现有的 Visio 客户端应用程序解决方案迁移到 Visio 控件时,请将这些设计注意事项包括在您的计划中。

  • **迁移 VBA 代码。**您必须将所有现有的 VBA 代码迁移到 COM 加载项中,或者最好是迁移到宿主应用程序中。您可以保留大多数的相同算法和逻辑,只要它可以工作在控件的 SDI 体系结构中。

  • **将现有的 Visio 解决方案 COM 加载项、可执行文件或 VSL 迁移到容器应用程序。**尽管利用宿主应用程序使用现有 COM 加载项、可执行文件或 VSL 最初可能会比较简单,但还是建议您直接将 Visio 绘图控件编程直接与宿主应用程序结合使用。在花时间将代码从现有解决方案迁移到宿主应用程序后,您将简化解决方案的部署,之后随着时间推移会简化开发、调试和维护过程。无需使用 COM 加载项,除非您要使用另一个 Office 容器中的控件。

  • **重新评估形状中的数据存储。**如果当前的 Visio 解决方案在形状中存储了大量的数据,请考虑将数据存储从 Visio 形状中提出并重新设计为由宿主应用程序维护或访问的数据结构。Visio 可以根据需要存储任意多的数据,但如果将 Visio 作为表示层组件并将宿主应用程序用作数据存储或通过它来访问数据源,则会更有意义。如果数据是相对静态、但频繁地用其来修改形状的外观和布局,那么将信息存储在形状自定义属性中会更有意义。

  • **考虑将事件与宿主应用程序结合。**与 Visio 客户端应用程序解决方案不同,Visio 绘图界面可以响应用户事件和宿主应用程序事件。请考虑您希望绘图画面如何响应由宿主应用程序激发的事件,以及您的宿主应用程序需要如何响应 Visio 绘图画面中的事件。

  • **使用 COM 加载项的 marker 事件。**如果必须使用 COM 加载项,则需要一种通知 COM 加载项响应文档中用户操作的方法。使用 ShapeSheet 中 的 QUEUEMARKER 函数或文档中持久性事件来排队 COM 加载项要响应的 marker 事件。

启动新的 Visio 开发

如果您只启动集成应用程序的 Visio,则最好直接根据宿主应用程序代码中的 Visio 对象模型进行编程。除了本文档中的设计建议和实现指导外,还需参考以下资源以获得有关使用 Visio 对象模型的信息:

  • Microsoft Office Visio Automation Reference 提供有关 Visio 对象模型的技术文档。

  • Microsoft Office Visio ShapeSheet Reference 提供有关可以通过 Visio 对象模型进行编程的 ShapeSheet 单元格和函数的技术文档。

  • MSDN 上的 Visio 开发人员中心 为所有级别的 Visio 开发人员提供文章、教程和软件开发工具包 (SDK)。

开始使用

本部分包含在应用程序中使用 Visio 绘图控件的基本步骤。它将说明如何将控件嵌入到主机容器中、如何将 Visio 文档加载到控件窗口并保存更改以及如何获得对 Visio Application 对象的引用,以便您可以借助编程方式使用 Visio 文档。

创建 Visio 绘图控件实例

本部分将详细说明创建 Visio 绘图控件实例和设置下列容器引用的过程:Windows 窗体、基于 Visual Basic 6.0 窗体的应用程序、Office 文档和 Internet Explorer。

注 开发人员无法在设计阶段激活 Visio 控件中的 Visio 绘图。控件中的 Visio 绘图只能在运行时激活。

以托管代码方式创建 Visio 绘图控件实例

您可以轻松地以托管代码方式创建 Visio 绘图控件实例。

完成这个过程以将下列程序集引用添加到项目中:

  • VisioOcx Visio 绘图控件主 interop 程序集。

  • Visio Visio 类型库主 interop 程序集。

  • AxVisOcx 允许控件嵌入到 Windows 窗体中的 ActiveX 控件包装程序集。Windows 窗体 ActiveX 控件导入程序 (Aximp.exe) 会自动生成这个程序集并将其添加到项目中。这个包装程序集必须与应用程序一起重新发布。窗体上的多个 Visio 绘图控件实例共享派生自 AxHost 类的相同包装类。

要将 Visio 绘图控件添加到 Windows 窗体:

  1. 在 Visual Studio .NET 中,在设计模式中显示 Windows 窗体。单击工具箱。

  2. 在工具箱内右键单击,然后选择 Add/Remove Items 打开 Customize Toolbox 对话框。

  3. 单击 Customize Toolbox 对话框中的 COM Components 选项卡。为类型库选中 Microsoft Visio Drawing Control,如图 2 所示。

    图 2. 将 Visio 绘图控件添加到 Visual Studio .NET 工具箱中

  4. 单击 OK。Visio 绘图控件现在出现在工具箱中,如图 3 所示。

    图 3. Visual Studio .NET 工具箱中的 Visio 绘图控件

  5. 通过在工具箱中双击 Visio 绘图控件,或者单击 Visio 绘图控件然后将其拖动到窗体,可以将该控件添加到窗体。

在 Visual Basic 6.0 中创建 Visio 绘图控件实例

您可以简单地使用 Visual Basic 6.0 来创建 Visio 绘图控件实例。完成这个过程以将引用添加到 Visio 绘图控件类型库。如果要以编程方式更改包含在绘图控件实例中的 Visio 文档,则需要添加一个对 Microsoft Visio 11.0 类型库的引用。

要将 Visio 绘图控件添加到 Visual Basic 6.0 窗体:

  1. 在 Visual Basic 6.0 中,在设计模式中显示窗体,右键单击工具箱,然后选择 Components。

  2. 在 Components 对话框中的 Controls 选项卡上,选中 Microsoft Visio Drawing Control 11.0,如图 4 所示。

    图 4. 将 Visio 绘图控件添加到 Visual Basic 6.0 工具箱中

  3. 单击 OK。Visio 绘图控件现在出现在工具箱中。

    图 5. Visual Basic 6.0 工具箱中的 Visio 绘图控件

  4. 通过在工具箱中双击 Visio 绘图控件,或者单击 Visio 绘图控件然后将其拖动到窗体,可以将该控件添加到窗体。

在 Microsoft Office System 应用程序文档中创建 Visio 绘图控件

完成这个过程以将引用添加到 Visio 绘图控件类型库。如果要以编程方式更改包含在绘图控件实例中的 Visio 文档,则需要添加一个对 Microsoft Visio 11.0 类型库的引用。

要将 Visio 绘图控件添加到 Office 应用程序文档中:

  1. 右键单击 Office 应用程序的工具栏,然后选择 Control Toolbox。

  2. 在 Control Toolbox 工具栏上,单击 More Controls 按钮,然后选中 Microsoft Visio Drawing Control,如图 6 所示:

    图 6. 将 Visio 绘图控件添加到 Microsoft Office Word 工具箱中

在将 Visio 绘图控件插入到 Office 应用程序文档后,可以通过右键单击它,然后选择 Properties 来查看其属性。如果要从文档的 Visual Basic 项目中以编程方式访问 Visio 绘图控件,那么右键单击该控件,然后选择 View Code。

在 Internet Explorer 中创建 Visio 绘图控件实例

要将 Visio 绘图控件添加到 Web 窗体或 HTML 页,您要遵循“以托管代码方式创建 Visio 绘图控件实例”中的步骤,不同之处在于您要将 Visio 绘图控件拖动到 Web 页上,而不是 Windows 窗体上。Visual Studio .NET 将下面的 HTML 添加到 Web 页:

修改 Properties 窗口中的值以更新 Visio 绘图控件实例中的属性标记。例如,如果修改 Src 属性,Visual Studio .NET 会生成类似于下面的标记:

将 Visio 绘图控件宿主为客户端对象,并为脚本语言(例如,VBScript)支持限量属性。您可以编写脚本对 Visio 绘图控件所公开的属性进行更改。但是,您无法使用脚本语言访问 Visio 对象模型,这意味着您无法以编程方式更改由控件显示的 Visio 文档。用户可以通过单击绘图画面对 Visio 文档进行更改。

注 该控件将只初始化任意给定的 Internet Explorer 进程中的第一个线程。如果您希望在基于 Internet Explorer 的应用程序中使用该控件的多个实例,请为该控件的每个额外的实例创建一个新的 Internet Explorer 进程,然后在新的 Internet Explorer 进程中加载包含该控件的 HTML 页。

获得对 Visio 应用程序对象的引用

您可以通过 Visio 绘图控件的 API 来访问 Visio 对象模型。要获得对 Visio Application 对象的引用,请使用绘图控件的 Document 或 Window 属性。

例如,下面的 C# 代码说明如何使用该绘图控件的 Window 属性以获得对 Visio Application 对象的引用。

using Microsoft.Office.Interop.Visio;
private Microsoft.Office.Interop.Visio.Application application = null;
application = (Microsoft.Office.Interop.Visio.Application) drawingControl.Window.Application;

可以使用下面的 Visual Basic 6.0 代码来完成相同的任务:

Dim vsoApplication As Visio.Application
Set vsoApplication = DrawingControl.Window.Application

管理文档

当加载 Visio 绘图控件时,将会显示一个空白 Visio 绘图。如果希望显示现有的 Visio 文档,则绘图控件会公开一个 Src 属性以便将文档加载到控件中。然后,您可以使用文档的 SaveAs 方法保存所有更改。

加载 Visio 文档

使用 Visio 绘图控件的 Src 属性来将文档加载到该控件。例如,下面的 C# 示例将显示如何加载 Visio 绘图:

drawingControl.Src = "C:\\Drawing.vsd";

可以使用 Src 属性加载任意 Visio 文件类型(例如,.vsd、.vdx、.vst 或 .svg)。可以本地存储该文件或将其存储在远程文件服务器上。

Visio 控件的 Src 属性会加载在 Src 值中指定的文件副本。要将更改保存在控件的文档中,必须使用 SaveAs 方法来保存 Visio 文档。或者,还可以保存流中的更改。但是,在这两种情况下,都不能修改由 Src 属性加载的原始文档。

将 Visio 文档保存到文件

该控件加载由 Src 属性指定的文件副本。通过 SRC 加载的文件不能用于读取/写入操作,因此无法使用 Save 方法保存。要将更改保存到 Visio 绘图控件中加载的文档,请调用文档的 SaveAs 方法。下面的 C# 示例将说明如何使用绘图控件的 Document 属性来调用 SaveAs 方法:

Visio.Document document = drawingControl.Document;
document.SaveAs("C:\\Drawing.vsd");

您无法使用 SaveAsEx 方法将 Visio 2003 文档保存到 Visio ActiveX 控件中的 Visio 2002 格式。要将 Visio 绘图控件中加载的绘图保存到 Visio 2002 格式,请启动一个 Visio 的不可见实例,并在 Visio 应用程序实例中调用 SaveAsEx 方法,如同 Visual Basic 6.0 代码中的演示,该代码将 Visio 2003 绘图保存到 Visio 2003 文件格式中:

Application.Documents(1).SaveAsEx("C:\Documents and Settings" & _
    "\myusername\My Documents\Visio2002 file.vsd", visSaveAsWS + _
    visSaveAsListInMRU)

将控件中的 Visio 文档保存到流

开发人员可能要将更改保存到 Visio 绘图控件的绘图中,而无需将绘图保存到磁盘中。例如,如果用户修改 Word 文档中嵌入控件中的 Visio 文档,那么当用户将该 Word 文档以电子邮件消息形式转发时,所做的更改会丢失。当另一个用户打开该文档时,该控件会加载由 Src 属性指定的文件,覆盖所有修改。

要将流中的更改保存到控件中的 Visio 文档:

  1. 使用 Visio 控件的 Src 属性加载原始文档。

  2. 在加载该文档后,将 Src 属性设置为空字符串。

当控件在第一次初始化后在其容器文档中激活时,该控件会显示最后一个流中的图像,而不显示由 Src 属性指定的原始文档。

使用控件中的空白文档

要在第一次初始化该控件时将空白绘图加载到其中,请将 Src 属性设置为空字符串。但是,如果希望在加载现有绘图文档后在控件中模拟创建新的空白绘图,则有三种选择:

  • 全选并删除绘图中所有形状。该方法允许开发人员将所有现有样式保留在当前加载的文档中。

  • 使用 Src 属性加载新的空白文档。

  • 动态破坏并重新初始化文档中的 Visio 绘图控件。

将控件与主机容器相结合

您可以修改应用程序中的 Visio 绘图控件的外观。默认情况下,关闭所有 Visio 工具栏,并且不显示模具窗格。您可以选择通过显示滚动条、标尺或者更改窗口背景颜色来选择绘图控件画面出现的方式。

绘图控件公开一个 PageSizingBehavior 属性,该属性确定页面在绘图控件窗口内显示的方式。您可以选择调整与绘图控件大小相关的页面,或者提供类似于 Visio 的视图,以显示部分绘图页面。

因为该控件只支持单个窗口,所以无法访问 ShapeSheet 或诸如图标编辑器以及主控和分组编辑之类的窗口。默认情况下,启用页面和形状的右键单击菜单。控制形状行为的有限 Visio UI 会反映要与容器应用程序紧密结合的控件的意图。允许用户修改文档上形状的最佳方法就是使用自定义的 UI。但是,如果您希望使用 Visio 菜单和工具栏,则绘图控件确实支持与宿主应用程序结合的菜单和工具栏。

最具可能的是,Visio 绘图控件应用程序会由事件驱动,并且响应包含在应用程序中的用户单击按钮或菜单项。该绘图控件还公开 Visio 事件,以便您可以在控件本身内响应用户单击。

管理绘图画面显示

您可以通过控件的 Window 属性修改 Visio 绘图控件表面的外观。例如,下面的 C# 代码将隐藏绘图控件的滚动条:

drawingControl.Window.ShowScrollBars = (short)_ 
    Visio.VisScrollbarStates.visScrollBarNeither;

这个示例同时隐藏水平和垂直滚动条。VisScrollbarStates 枚举的其他可能值包括 visScrollBarBoth(同时显示两个滚动条)、visScrollBarHoriz(显示水平滚动条)和 visScrollBarVert(显示垂直滚动条)。

通过移除部分 Visio UI,您可以使得绘图控件看起来与应用程序结合的更紧密。下面的 C# 代码将隐藏标尺:

drawingControl.Window.ShowRulers = 0;

还可以更改窗口的背景颜色以适合应用程序的配色方案。例如,下面的 C# 代码会将窗口的背景颜色设置为纯红色:

drawingControl.Window.BackgroundColor = (uint) 
    ColorTranslator.ToOle(Color.Red);
drawingControl.Window.BackgroundColorGradient = (uint) 
    ColorTranslator.ToOle(Color.Red);

在此示例中,ColorTranslator 类用于将 .NET 颜色类型转换成 OLE_COLOR 类型,这就是 Visio Automation 指定颜色的方式。

Visio 控件的用户设置

Visio 绘图控件将相同的基本 Application 对象共享为 Visio 客户端应用程序。因此,如果用户更改 Visio 客户端应用程序的应用程序设置(例如将页面背景更改为蓝色),那么在宿主应用程序中运行时,相同的设置将会应用到 Visio 控件。Visio 控件的 HostID 属性允许您在注册表中存储该控件的不同用户设置。要设置 HostID 属性,请使用字符串来指示将要在 [HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\VisioHosts] 项中创建的子项的名称。尽管可以为控件的子项的名称使用任意字符串,但最好使用 GUID 来确保唯一性。

HostID 属性可以在设计阶段在控件的 Properties 窗口中进行设置,也可以借助编程方式在宿主应用程序代码中进行设置。

页面调整和缩放

使用 Visio 绘图控件的 PageSizingBehavior 属性根据控件窗口调整页面的大小。该属性 (visNeverResizePages) 的默认设置提供的视图类似于 Visio 的视图,可在该窗口内查看视图中页面的一部分。下面的 C# 代码示例调整页面大小以适配该控件:

drawingControl.PageSizingBehavior = 
    Visio.VisPageSizingBehaviors.visResizePages;

当 PageSizingBehavior 设置为 visResizePages 时,该页面的形状将不会根据该页面进行调整。形状会保留在 Visio 页面坐标系统的相对位置,其原点位于页面的左下角。在控件内调整页面的大小进行适配会隐藏页边界,在控件调整到绘图画面的最大区域时,这一点会非常有用。

要在绘图控件窗口中重新调整整个页面(包括其形状),请通过控件的 Window 属性设置 Zoom 属性,如下面的 C# 示例所示:

drawingControl.Window.Zoom = 2.0;

该代码将窗口的内容放大到 200%。要使其生效,必须在使用 Src 属性加载文档后对缩放设置进行设置。

要防止用户更改缩放设置,请设置 ZoomLock 属性,如下面 C# 示例所示:

drawingControl.Window.ZoomLock = true;

通过 VisZoomBehavior 属性可以设置 Visio 所控制的缩放的最大范围,该属性可以通过绘图控件的 Window 或 Document 属性进行访问。默认情况下,该控件使用文档的当前缩放设置。如果希望能够将缩放设置到任意级别,不要只设置为不连续设置(例如,50% 或 100%),在不对外观进行任何调整的情况下,可将 VisZoomBehavior 属性设置为 VisZoomVisioExact 值,如下面的 C# 示例所示:

drawingControl.Window.ZoomBehavior = 
    Visio.VisZoomBehavior.visZoomVisioExact;

注 无法在 Word 文档中调整 Visio 绘图控件大小。如果要调整绘图控件大小并保存更改,则在下一次打开该 Word 文档时该控件将重置为其默认大小。

形状搜索窗口管理

您可以使用 Visio ItemFromID 属性“关闭”文档的模具窗格中的 Visio 形状搜索窗口。要使形状搜索窗口在模具窗格中不可见,请将该属性的 Visible 属性设置为 false,例如:

Windows(1).ItemFromID(Visio.visWinIDShapeSearch).Visible = False

要在模具窗格中显示形状搜索窗口,请将相同的值设置为 True。

注 您只能管理基于每个窗口的形状搜索窗口的可见性。

集成菜单和工具栏

在使用 Visio 绘图控件构建应用程序时的最佳作法就是实现一个自定义 UI。如果您希望在容器应用程序中显示 Visio 菜单和工具栏,请设置绘图控件的 NegotatiateToolbars 和 NegotiateMenus 属性。下面的 C# 代码同时启用菜单和工具栏合并:

drawingControl.NegotiateMenus = True;
drawingControl.NegotiateToolbars = True;

最佳作法是将这两个参数设置为相同的值。该控件将不支持工具栏和菜单的独立协商。

容器应用程序必须支持 OLE 菜单合并以便显示 Visio 菜单或工具栏。例如,您可以在 Word 文档中启用工具栏合并。在 Word 文档的 Visual Basic 项目中,您可以借助编程方式显示 Visio 工具栏。下面的示例将显示 Layout & Routing 工具栏。

vsoApplication.CommandBars("Layout & Routing").Visible = True重要说明 请勿尝试将菜单和工具栏与 ActiveX 控件的多个活动实例合并。该控件的多个实例共享单个基本 Visio Application 对象。在尝试将菜单与单个 Application 对象和该控件的多个活动实例合并在一起时,可能会得到意外结果。

要要说明 请勿将菜单和工具栏与 Internet Explorer 用户界面合并。在 Internet Explorer 中合并菜单存在着已知的问题(请参阅 Microsoft 知识库文章 193098 PRB:Unexpected Menu Merging Behavior in Internet Explorer)。

非 OLE 菜单合并主机的菜单和工具栏集成

如果您的容器不支持 OLE 菜单合并(例如,Windows 窗体),您可以使用 IOleCommandTarget 接口运行 Visio 命令。您可以实现自己的菜单项和工具栏按钮,如下面的 C# 示例所示:

using System.Runtime.InteropServices;
using System;

namespace OleCommandTarget
{
    [StructLayout(LayoutKind.Sequential)]
    public struct OLECMDTEXT
    {
        public UInt32 cmdtextf;
        public UInt32 cwActual;
        public UInt32 cwBuf;
        public char rgwz;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct OLECMD
    {
        public UInt32 cmdID;
        public UInt64 cmdf;
    }

    [ComImport(), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleCommandTarget
    {
        [PreserveSig()]
        int QueryStatus( [In, MarshalAs(UnmanagedType.Struct)] ref Guid 
            pguidCmdGroup, [MarshalAs(UnmanagedType.U4)] int cCmds, 
            [In, Out] IntPtr prgCmds, [In, Out] IntPtr pCmdText);

        [PreserveSig()]
        int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdExecOpt, 
            object[] pvaIn, [In, Out, MarshalAs(UnmanagedType.LPArray)] 
            object[] pvaOut);
    }
}

在创建菜单项后,请使用 IOleCommandTarget 接口将适当的 Visio 用户界面命令用于该目标。下面的示例在单击菜单项时会启用 Connector 工具:

using OleCommandTarget;

private void menuItem_Click(object sender, System.EventArgs eventData)
{
    SendCommand();
}

private void SendCommand()
{
    const UInt32 VISCMD_DRCONNECTORTOOL = 
         (UInt32)Visio.VisUICmds.visCmdDRConnectorTool;
    IOleCommandTarget commandTarget = 
         (IOleCommandTarget)axDrawingControl1.GetOcx();

    try
    {
        Guid CLSID_Application = new Guid("{0x00021A20, 0x0000, 0x0000, 
            {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}");
        commandTarget.Exec(ref CLSID_Application, VISCMD_DRCONNECTORTOOL, 
            0, null, null);
    }
    catch(System.Runtime.InteropServices.COMException ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

处理事件

为了 Visio 事件的使用更为简便,Visio 绘图控件对象将公开所有 Visio Window 和 Document 事件。这允许开发人员可以直接从该控件访问这些事件,而无需通过 Visio Document 对象。

鼠标和键盘事件通常用于 Visio 控件编程中。您可以在 Visio 绘图控件上使用鼠标事件来显示自定义的 Windows 窗体以及更新宿主应用程序中的数据。

如果希望“锁定”Visio 控件的绘图画面,并防止最终用户直接修改绘图中的任何内容,您可以侦听所有键盘和鼠标事件并“丢弃这些事件”。如果宿主应用程序“抑制”了鼠标和键盘事件,则 Visio 绘图画面将不会响应用户的键入和鼠标单击操作。

鼠标和键盘事件对象

由 Visio AddAdvise 方法创建的事件对象提供了最佳的性能。您可以像使用任何其他 Visio 事件一样,将 Visio 鼠标和键盘事件与 AddAdvise 一起使用。

下面的代码示例将演示如何使用 Visual Basic 6.0 中的事件接收器来捕获鼠标事件:

Implements Visio.IVisEventProc
Private Function IVisEventProc_VisEventProc( _
    ByVal nEventCode As Integer, _
    ByVal pSourceObj As Object, _
    ByVal nEventID As Long, _
    ByVal nEventSeqNum As Long, _
    ByVal pSubjectObj As Object, _
    ByVal vMoreInfo As Variant) As Variant

    Dim strMessage As String
    
    ' Determine if mouse up event fired.
    If nEventCode = visEvtCodeMouseUp Then
        MsgBox ("MouseUp coordinates (" & pSubjectObj.X & ", " _
            & pSubjectObj.Y & ")")
    End If

End Function

下面的代码示例说明如何使用 AddAdvise 方法来创建鼠标对象的事件对象。

Private mEventSink As clsEventSink
Dim vsoMouseUpEvent As Visio.Event
Dim vsoWindowEvents As Visio.EventList

Set mEventSink = New clsEventSink

Set vsoWindowEvents = DrawingControl1.Window.EventList

Set vsoMouseUpEvent = vsoWindowEvents.AddAdvise( _
    visEvtCodeMouseUp, mEventSink, "", "Mouse up...")

委托鼠标单击事件

尽管使用 AddAdvise 创建的事件对象提供了最佳性能,您还可以在 Windows 窗体中定义 C# 委托来处理绘图控件窗口内的鼠标单击事件,如下所示:

this.drawingControl.MouseUpEvent += new 
    AxMicrosoft.Office.Interop.VisOcx.EVisOcx_MouseUpEventHandler(
    this.drawingControl_MouseUpEvent);

然后事件处理程序将会具有以下签名:

private void drawingControl_MouseUpEvent(
    object sender, AxVisOcx.EVisOcx_MouseUpEvent eventData)

形状的鼠标事件

Visio 鼠标事件在 Page 和 Window 对象上公开。要定位用户单击的页面或窗口中的特定形状,开发人员必须使用 Visio SpatialSearch 方法。下面的 C# 代码传入窗口上单击事件的 x- 和 y- 坐标、设置指示出如何建立选择对象的 Visio 常量,然后定义一个在 x- 和 y- 坐标周围进行搜索的较小容错范围。

MySelection = Window.SpatialSearch(x, y, visSpatialContainedIn, 
    0.001, visSpatialFrontToBack)

如果将该容错设置为相对于形状大小而言非常小的单位,则 SpatialSearch 方法返回的选择对象将只包含一个形状,即最终用户在该窗口内单击的形状。

部署

Visio 绘图控件是通过 Visio 产品安装过程进行发行的。这样,就不会有关于控件本身的附加许可问题了。宿主绘图控件的应用程序只有在 Visio 安装到计算机上之后才能工作。

Visio 绘图控件是作为 Minimal Install 选项的组成部分进行安装的。如果您的应用程序是以托管代码编写的,并且要利用 Visio 主 interop 程序集,则必须选择 Typical Install 选项才能安装 Visio 主 interop 程序集。

首先,确保该计算机已经安装了 .NET Framework 1.1;否则 Visio 主 interop 程序集将无法安装。.NET Framework 1.1 是随 Visual Studio .NET 2003 安装的版本。对于运行应用程序的客户端来说,还可以安装作为应用程序的安装程序组成部分的免费 .NET Framework 1.1 Redistributable。

此处有两个选项可用于通过 Visio 产品安装程序自动部署 Visio 绘图控件:

  • 编写 Windows Installer 安装程序,并为公司部署使用“无提示安装”。

  • 直接调用 Visio 产品 Windows Installer 软件包(Visio .msi 文件)。

下面的示例说明如何使用 Windows 脚本主机来利用 Typical Install 选项以无提示方式安装 Visio:

Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Exec("setup.exe /qn PIDKEY= INSTALLLEVEL=20")
To call the Visio product MSI directly, use the following code:
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Exec("msiexec.exe /qn /i " & _
    "PIDKEY= INSTALLLEVEL=20")

小结

Visio 绘图控件允许开发人员以丰富的 Visio 绘图功能来扩展自定义应用程序和解决方案。通过提供对控件的编程功能以及对完整 Visio 对象模型的访问,Visio 组件可以由用户绘图操作或宿主应用程序中的事件和数据来驱动。使用 Visio 绘图控件的解决方案的优点在于:

  • 自定义应用程序的用户无需具备 Visio 用户界面的知识就可以创建绘图。应用程序 UI 可以驱动绘图创建,并可以对用户的 Visio 特定任务进行概要。

  • 对于应用程序宿主和开发工具的选择,Visio 解决方案开发人员的选择范围更为宽广。Visio 绘图控件可以宿主于任意 ActiveX 容器中。通过使用 Visio 主 interop 程序集,还可以使用托管代码中的 Visio 绘图控件来开发解决方案。

  • 与涉及 COM 加载项或 VSL 的解决方案相比,提供对 Visio 编程模型的直接访问使得使用 Visio 绘图控件的解决方案更易于开发和调试。

关于作者

Mark Bukovec 是一位自由开发人员和技术作家。之前,Mark 曾在 Microsoft 工作过五年,最近是为 COM+ 组工作的程序经理。您可以通过 *empiredown@hotmail.com* 联系 Mark。

转到原英文页面