• 热门专题

Ribbon界面的Office插件开发

作者:平淡如盐  发布日期:2015-06-28 21:21:28
Tag标签:插件  界面  
  •       此乃开博第一篇也。Office插件开发是一项古老的技术,似乎从office2000开始,Office的插件体系就已经固定下来,后续版本也只是在不断完善和加入新功能。Office插件是在COM模型的基础上,实现了特定的接口,进而通过COM技术进行相互操作的一个dll文件。通过在相应的注册表位置进行注册,就可以被Office程序调用。

    在继续本篇教程之前,先来介绍一下本次开发的基本环境:

    开发工具:Delphi 7 企业版

    系统环境:Win7 64位系统 安装WPS Office 2013SP3(9.1.0.4953)

          基于WPS V9版的API,这个版本基本兼容 MS Office 2007,你也可以基于MS Office的API接口,效果是一样的。本教程同时可用于MS Office 和 WPS Office。

    Office插件是一个实现了IDTExtensibility2接口的COM组件,在导入相应的类型库后就可以引用AddInDesignerObjects_TLB.pas的相关接口,它的声明如下:

      _IDTExtensibility2 = interface(IDispatch)
        ['{B65AD801-ABAF-11D0-BB8B-00A0C90F2744}']
        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;
      end;

    在此不多做介绍,具体可参考MSDN,里面有详细的介绍。

    Ribbon界面是Office2007新增的界面,这个界面的插件开发,将界面设计与功能实现进行了分离,界面以XML文件进行定义,功能实现以回调函数的形式调用,与传统的工具栏和菜单形式的插件相比,开发效率要高的多,本教程要介绍的就是这一技术。

    在实现Ribbon界面,在插件中除了要实现IDTExtensibility2接口外,还要实现Ribbon界面的专用接口IRibbonExtensibility,这个接口定义在Office的类型库中,声明如下:

      IRibbonExtensibility = interface(IDispatch)
        ['{000C0396-0000-0000-C000-000000000046}']
        function GetCustomUI(const RibbonID: WideString): WideString; safecall;
      end;

    这个接口只有一个方法GetCustomUI,返回值为界面设计的XML文件内容。我们本次要实现的界面XML内容如下:

    <customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'>
        <ribbon startFromScratch='false'>
            <tabs>
                <tab id='DemoTab' label='育林软件'>
                    <group id='loadFormsGroup' label='测试分组'>
                        <button id='btn1' label='测试功能' onAction='OnAction' getImage='GetImage'/>
                        <button id='btn2' label='关于我们' onAction='OnAction' getImage='GetImage'/>
                    </group>
                </tab>
            </tabs>
        </ribbon>
    </customUI>

    关于XML的定义规则请参考MSDN,上面有详细介绍。OnAction是回调函数,用于响应按钮点击,GetImage用于返回按钮的图片。

    我们的COM对象定义如下:

    type
      TTestRibbon = class(TAutoObject, IDTExtensibility2, IRibbonExtensibility, ITestRibbon)
      private
    
      protected
        {实现IRibbonExtensibility接口}
        function GetCustomUI(const RibbonID: WideString): WideString; safecall;
        {实现IDTExtensibility2接口}
        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;
        {实现ITestRibbon接口,这两个方法就是我们要用的回调函数}
        procedure OnAction(const ctrl: IDispatch); safecall;
        function GetImage(const ctrl: IDispatch): IDispatch; safecall;
      public
    
      end;

    ITestRibbon是我们com对象定义的接口,它有两个方法OnAction和GetImage,如果XML中定义的控件较多,我们需要添加的回调函数就越多,每种控件的回调函数都是大同小异,我们实现的就是针对普通按钮的回调函数,需要在delphi的类型库编辑器中添加,如下图。

         OnAction你也可以定义为其它名称,只要参数类型相同,什么名字都可以,但要注意名称一定要跟XML中定义的一样,也就是说你这里定义的什么名字,XML文件中onActon后面也要用什么名字。类型库导入完成,接口定义完成就开始实现部分了,这才是重点。说实话,在接口定义部分我也走了不少弯路,研究了几个晚上才搞明白,网上基于.net的相关内容不少,但参考性不强,.net将com的实现进行了封装,开发者不用关心定义,只要写代码就可以了,但delphi要做的工作还有很多。虽然麻烦,但好处还是有的,.net开发的插件要附带很多文件,delphi开发的插件只要发布一个dll就可以了。

    下面我们来看实现部分,先看GetCustomUI:

    function TTestRibbon.GetCustomUI(const RibbonID: WideString): WideString;
    var Str:TStrings;
    begin
      Str:=TStringList.Create;
      Str.LoadFromFile('C:CustomUI.xml');
      Result := Str.Text;
      Str.Free;
    end;

         这里我们选择从文件载入XML数据,主要是为了后期修改与调试方便,等到发布的时候,完全可以将XML文件加入进资源文件,从资源中载入。

    到这里,如果我们编译后安装插件,就可以在Office中显示我们的按钮了,但由于没有实现OnAction,所以点击按钮是没有任何反应的,下面我们来实现OnAction回调函数。它的定义如下:

    procedure OnAction(const ctrl: IDispatch); safecall;

    根据微软的定义,ctrl是一个IRibbonControl接口的参数,这个接口定义在Office的通用类型库中,这个参数是我们判断到底是哪个按钮调用了这个函数的基础,就是依据IRibbonControl的ID属性,这个ID就是XML中定义的Id,我们的实现如下:

    procedure TTestRibbon.OnAction(const ctrl: IDispatch);
    begin
      if (ctrl as IRibbonControl).Id = 'btn1' then
        MessageBox(0, '您点击了按“测试功能”!', '提示', MB_OK + MB_ICONINFORMATION)
      else
        MessageBox(0, '您点击了按钮“关于我们”!', '提示', MB_OK + MB_ICONINFORMATION);
    end;

    到此一个简单的插件就已经完成了,下面说一下插件安装。

    将以下内容保存为注册表文件.reg,并双击导入注册表。

    Windows Registry Editor Version 5.00
    
    [HKEY_CURRENT_USERSoftwareMicrosoftOfficeWordAddinsYulinsoft.TestRibbon]
    'FriendlyName'='测试Ribbon插件'
    'Description'='测试插件'
    'LoadBehavior'=dword:00000003
    'CommandLineSafe'=dword:00000001
    
    [HKEY_CURRENT_USERSoftwareKingsoftOfficeWPSAddinsWL]
    'Yulinsoft.TestRibbon'=''

    然后再用命令行regsvr32注册我们的dll,注意文件路径正确,注册成功后打开Word2007或WPS,就可以看到我们的按钮了,如下图:

    【原创文章,转载请注明出处】 

    本教程全部代码与资源文件下载:

    http://pan.baidu.com/s/1eQrSOSE

     

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规