在Office 2000中提供了基于COM的插件开发框架,这使得
我们可以利用Delphi来扩展Office的功能。
在Delphi 3,4中编写基于COM的插件,
我们需要自己创建COM接口的封装类,更糟糕的是要想支持事件的话还需要使用连接点(connection points)对象来实现事件回调,这是非常麻烦的。但在Delphi 5中这一切就变得非常轻松了,Delphi 5的类型库引入工具提供了/L+的开关,可以自动为
我们生成封装好的OLE Server。这下子再也没有什么好抱怨的了。
Office 2000 插件框架
在Microsoft的网站上,知识库文章(Knowledge Base article Q230689)中有一篇:Office 2000 COM Add-In Written in Visual C++ 。文章中提供了一个例子(http://support.microsoft.com/download/support/mslfiles/ COMADDIN.EXE)。这篇文章详细地描述了插件框架中的COM接口。仔细研究一下C++代码就可以了解如何编写Office 2000插件。
Office 2000插件其实就是一个实现了IDTExtensibility2接口的自动化对象。IDTExtensibility2 接口相当简单,插件需要实现接口定义的全部5个函数:
OnConnection:当应用程序连接到插件时会调用这个函数。插件在函数中接收下列初始化信息——应用程序对象模型进入点的指针,连接模式(是手工加入还是通过命令行载入), 应用程序的对象模型指针和用户自定义的信息。
OnDisconnection:当应用程序断开插件时被调用,插件应该在这里清除先前分配的资源,删除它添加到应用程序的界面元素。
OnStartupComplete:这个函数是当应用程序自动启动插件时被调用的。调用时,其他的插件都已经被加载到了内存,这时可以同其他插件进行通信。这个函数还适合添加用户界面元素。
OnBeginShutdown:当应用程序准备关闭并将要断开插件时会被调用,这时插件应该停止接收用户输入。
OnAddInsUpdate:当注册的插件列表被改变后会被调用。如果
我们的插件不依赖于其他插件,这个函数可以为空。
接口、类型库和常数
创建插件前,
我们需要引入COM对象的接口类型库。这里使用Delphi 5带的TlibImp.exe (Delphi5\Bin目录下)来引入类型库。新版的TlibImp.exe支持新的/L+开关,可以自动创建一个OLE Server的Delphi封装。IDTExtensibility2接口是在MSADDNDR.DLL文件中声明的,位于\Program Files\Common Files\Designer\ 目录下。调用TLIBIMP\L+\Program Files\Common Files\ Designer\MSADDNDR.DLL会生成AddInDesignerObjects_TLB.pas 和 AddInDesignerObjects_TLB.dcr两个文件。在项目的uses部分加上对上面文件的引用以便使用接口。clause of our project to gain access to the interface.使用时注意:TLIBIMP重命名接口为_IDTExtensibility2。
本文中将使用Word 2000作为例子,如果想编写Outlook、Excel或其他Office程序的插件需要引入相应特定的类型库。比如Word的类型库是定义在\Program Files\Microsoft Office\Office\MSWORD9.OLB文件中。类似的,Excel、Access和OutLook类型库分别定义在EXCEL9.OLB、MSACC9.OLB和MSOUTL9.OLB文件中。引入的接口生成在Office_TLB.pas和Word_TLB.pas单元中。
注意:Office 2000的插件无法工作在Office 97的应用程序中。
最简单的插件
现在让
我们来实现一个最简单的插件,它只实现了IDTExtensibility2接口而没有实现任何比较有意义的功能,但对于演示如何实现插件是一个很好的开始。
插件可以以进程内或进程外COM服务器的形式实现,在本文中,
我们创建的是进程内COM服务器。在Delphi中,选择菜单File | New命令,然后创建一个ActiveX Library,保存生成的文件,再创建一个自动化对象(Automation Object),类名定义为AddIn,把实现单元保存为AddInMain.pas。在AddInMain.pas单元的uses部分添加对AddinDesignerObjects_TLB,Word_TLB和Office_TLB单元的引用。最后添加 IDTExtensibility2 接口到类定义部分定义类要实现的接口。类定义如下:
type
TAddIn = class(TAutoObject, IAddIn, IDTExtensibility2)
...
在类声明的protected部分,添加IDTExtensibility2 接口声明的方法定义,代码示意如下:
// IDTExtensibility2 methods
procedure OnConnection(const Application: IDispatch;
ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
var custom: PSafeArray); safecall;
procedure OnDisconnection(RemoveMode: ext_DisconnectMode;
var custom: PSafeArray); safecall;
procedure OnAddInsUpdate(var custom: PSafeArray); safecall;
procedure OnStartupComplete(var custom: PSafeArray); safecall;
procedure OnBeginShutdown(var custom: PSafeArray); safecall;
使用快捷键[Ctrl][Shift][C]来完成类定义,并添加方法的实现部分的框架到单元中。为了测试插件,可添加下面代码到OnConnection方法中:
ShowMessage(连接到 + WordApp.Name);
添加下面代码到OnDisconnection方法的实现部分:
ShowMessage(断开插件);
这样就完成了一个最简单的插件了,接下来就是编译并注册插件到Word中去。