Ribbon界面的Office插件开发

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

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

开发工具:Delphi 7 企业版

系统环境:Win7 64位系统 安装WPS Office 2003SP3(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_USER\Software\Microsoft\Office\Word\Addins\Yulinsoft.TestRibbon]
"FriendlyName"="测试Ribbon插件"
"Description"="测试插件"
"LoadBehavior"=dword:00000003
"CommandLineSafe"=dword:00000001

[HKEY_CURRENT_USER\Software\Kingsoft\Office\WPS\AddinsWL]
"Yulinsoft.TestRibbon"=""

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

本文参考内容如下:

http://gregmaxey.mvps.org/word_tip_pages/customize_ribbon_main.html

Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)

Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)

Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

初来贵地交流技术,如有不对之处,欢迎大家批评指证。下节我们将讲解如何给按钮添加图像!

时间: 2024-09-30 20:50:55

Ribbon界面的Office插件开发的相关文章

setup界面的network configuration 进不去的原因

setup界面的network configuration 进不去的原因 这个问题在百度上搜了好久都没搜到能解决的答案,最后还是自己琢磨出来的. 目前我遇进不去的原因是,因为在刚装好系统(装的是最小化的)后直接暴力装的system-config-network-tui,导致缺少依赖包,造成了点不进去. 解决办法: rpm-qa | grep 'system-config-network-tui' 查看所有安装包并过滤出网络安装包            rpm-e system-config-ne

Android新浪微博客户端(六)——Home界面的ListView

原文出自:方杰|http://fangjie.sinaapp.com/?p=184转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54该项目代码已经放到github:https://github.com/JayFang1993/SinaWeibo 一.首先是ListView的adapter. 因为微博列表的Item不是规则的,比如说有些微博有转发子微博,有些没有,有些有图片,有些没有图片,所以说很不固定.这里就采用BaseAdapter,要自

office 插件开发 -- 64位系统注册表问题

1 HKLM 2 { 3 NoRemove SOFTWARE 4 { 5 NoRemove Microsoft 6 { 7 NoRemove Office 8 { 9 NoRemove Word 10 { 11 NoRemove Addins 12 { 13 ForceRemove WordClientDemo.WordAddinDemo 14 { 15 var 'FriendlyName' = s 'WordAddinDemo' 16 var 'LoadBehavior' = d '3' 17

Linux环境下使用图形化界面的SVN客户端软件-RabbitVCS

如果想在Linux环境下使用图形化界面的SVN客户端软件,那么RabbitVCS绝对是首选,可以媲美Windows环境下用的TortoiseSVN,甚至连操作都基本一样,所以强烈推荐给各位童鞋. RabbitVCS基本支持所有的Linux发行版本包括Ubuntu.Debian.Fedora.Arch Linux.Gentoo.Mandriva.OpenSUSE.RHEL.CentOS 5等.其官网地址为http://www.rabbitvcs.org/ 在ubuntu下安装 首先添加源: sud

Android新浪微博客户端(五)——主界面的TabHost和WeiboUtil

原文出自:方杰|http://fangjie.sinaapp.com/?p=183转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到github:https://github.com/JayFang1993/SinaWeibo 一.TabHost的实现 之前的一篇文章讲的就是TabHost,但是那个是用Fragment实现TabHost,这里我就尝试用另一种方式,继承TabActivity的方式实现TabHost. Ma

android-多种方式实现主界面的Tab

本人水平有限,文章中如果出现什么不正确或者模糊的地方,还请各位小伙伴留下评论,多多指教 : ) 前言 使用Fragment实现 思路 效果 具体讲解 底部布局 顶部布局 Fragment的布局 Java控制代码 使用ViewPager实现 思路 效果 具体实现 使用ViewPagerFragmentPagerAdapter方法实现 思路 效果 补充 具体代码 使用框架 前言 这篇文章主要介绍多种方式实现主界面的tab,包括: (1)使用Fragment实现 (2)使用ViewPage实现 (3)

.Net MVC&amp;&amp;datatables.js&amp;&amp;bootstrap做一个界面的CRUD有多简单

我们在项目开发中,做得最多的可能就是CRUD,那么我们如何在ASP.NET MVC中来做CRUD呢?如果说只是单纯实现功能,那自然是再简单不过了,可是我们要考虑如何来做得比较好维护比较好扩展,如何做得比较漂亮.做开发要有工匠精神,不要只求完成开发任务,那样的话,永远停留在只是简单的写业务逻辑代码水平,我们要做有追求的程序员.本来这么简单的东西,我真是懒得写,但是看到即便是一些工作了好些年的人,做东西也是只管实现功能,啥都不管,还有些界面css样式要么就硬编要么就毫无规则的在页面中进行穿插,遇到要

iOS native如何获取web界面的title、image等

转载地址:http://blog.csdn.net/justinjing0612/article/details/34127597 最近几年都很流行hybrid开发模式,这样就少不了native和Html界面的一些交互,或者方法的调用. 微信的分享火热我想也说大部门app模仿的一个典范.今天我们就说微信分享的一个细节. 我们浏览朋友的朋友圈后,如果想分享到自己朋友圈,那我们就需要知道webview 的title 和 image,问题来了,我们怎么知道呢? 分享界面 以前我没有接触过的时候感觉好神

新手必备:最佳类 Windows 界面的 Linux 发行版

Linux 世界的新同学们,大家好,当你看到这么多基于 Linux 内核的发行版后,是不是在选择的过程中无从下手呢.很多同学都是刚刚从熟悉的 Windows 系统来到陌生的 Linux 世界里,都希望使用一款既简单易用,又跟 Windows 长得很像的 Linux 发行版,因此我今天将给大家介绍几款这样的 Linux 发行版,它们的桌面环境跟 Windows 系统界面十分相似,咱们开始吧! Linux Mint 我给大家介绍的第一款非常流行的 Linux 发行版就是 "Linux Mint 操作