2.1《他山之石──ArcMap插件机制》
ArcMap并不是基于.NET机制开发的程序,它使用C++开发而成,尽管如此,除了在插件识别时.NET框架与COM插件框架有所差别外,其它步骤都非常类似,可以为读者在设计一个插件式GIS应用框架的过程提供借鉴。
插件式架构的核心在于框架宿主程序与插件对象的通讯。即宿主程序如何识别插件对象并与插件对象建立事件关联。这个过程包括下面几点:
宿主程序如何识别插件对象?
ArcMap是一个基于COM机制的应用程序,与MS Office System类似,当它安装到硬盘上时, ArcMap的所有动态链接库DLL文件的相关注册信息都会被写入注册表中的不同“组件目录”(Component Categories)中。
ArcMap.exe程序启动时,将从注册表中ArcMap的相关Component Categories中查找出相关插件对象的信息并依据这些信息进行初始化工作。
本书所指的插件,是指可以形成用户界面(User Interface,UI)并能够与用户进行人机交互的组件,它们在ArcMap中表现为一个命令按钮(ICommand)、一个工具按钮(ITool),一个工具条(IToolBarDef)、一个菜单栏(IMenuDef)或一个浮动窗体(IDockableWindow)。如图 2‑2所示,这些在界面上出现的按钮、工具条等UI对象都是根据插件对象的属性生成的,它们是各自插件对象的UI层表现形式。
图 2‑2 ArcMap程序界面
当宿主程序获取相应的插件对象信息后,便根据信息动态创建不同类型插件对象的UI对象。
插件的UI对象如何被初始化?
当宿主程序ArcMap.exe从注册表中获得插件对象的信息并在内存中生成插件对象后(注意,此时还是插件对象而非插件对象的UI对象),才开始根据插件对象产生各自的插件UI对象。
插件UI对象的初始化包括三个方面,一是宿主程序根据插件对象携带的UI信息生成实际的UI层对象,以ICommand插件对象为例,宿主程序获得这个对象的Icon、ToolTip、Name、Category、Message和HelpFile等信息后,在宿主程序的UI层面上生成一个可以供交互的UI Command命令对象,如图 2‑2所示。
第二是宿主程序将创建两个公共变量,它们将携带宿主程序的信息和交互方法,在ArcMap中就是Application和ThisDocument两个对象。ArcMap.exe将Application对象通过插件UI对象的初始化函数传递给插件UI对象,该初始化函数如下:
Private Sub ICommand_OnCreate(ByVal hook As Object)
' hook参数是一个指向ArcMap宿主程序的指针
' m_pApp是供插件使用了宿主程序的变量,插件可以通过这个变量获得主程序的信息
Set m_pApp = hook
End Sub
这样,宿主程序与插件对象之间的通讯桥梁便建立起来了。
第三是宿主程序将一个插件对象的UI对象与插件对象之间的交互通道建立起来。宿主程序通过“事件机制”实现这一点,当用户在UI界面上点击一个插件UI对象后,宿主程序将能够将这个操作通过函数指针和回调函数调用正确的插件对象,以完成特定的操作。
插件对象如何产生它们的UI对象?
插件对象以不同的UI形式出现在宿主程序上,这是插件UI对象初始化工作的一部分。由于ArcMap中的可视化组件分为ICommand、ITool、IToolBarDef、IMenuDef和IDockableWindow等类型,当宿主程序获得一个插件组件的信息后,它会依据这些插件对象的类型的差别和各自定义的属性来生成不同的UI层组件。
如果编写一个扩展DLL,它包括一个ICommand类型和一个IToolBarDef类型,并将ICommand类型的UI对象放置在IToolBarDef的UI对象上,在解析时,宿主程序将分别生成一个ICommand对象的UI对象和IToolBarDef的UI对象,然后将ICommand的UI对象关联到IToolBarDef之上,它们在UI层上的效果就是一个有命令按钮的工具条。
这些UI层解析和生成的过程都将由宿主程序负责进行,插件开发人员无需考虑这个问题。
插件的UI对象被触发时如何与插件产生互动的?
插件对象的UI对象在被用户触发时如何与插件对象产生互动,也许是整个插件式框架中最有趣的一部分。在COM机制中,通过绑定函数指针和回调函数的方式,宿主程序将知道当某个按钮按下时,需要调用哪一个对象的函数来实现该事件需要执行的功能。在.NET Framework中,事件关联被一种称为“委托”(Delegate)的机制来完成,我们将在后面的章节中讲解委托机制的原理和应用。
图 2‑3展示了ArcMap.exe程序启动并加载插件的全过程:
图 2‑3 ArcMap启动过程