飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2001|回复: 0

用Delphi制作Office的Com AddIn

[复制链接]
  • TA的每日心情
    开心
    2019-9-19 16:05
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2007-2-8 16:11:24 | 显示全部楼层 |阅读模式
    最近想做一个像金山词霸那样在Word上面增加一个按钮的东西
    在网上找了一会儿,竟然没有Delphi的例子,没办法只好自己搞定,

    1. 新建一个Active Library
    2. 新建一个COM Object,在Class Name填一个名字,如Test。
    点一下Implemented Interface后面的List按钮。再点一下对话框中的Add Library按钮,
    选择“Program Files\Common Files\Designer”目录下的msaddndr.dll文件。
    然后在列表中找到msaddndr.dll里面的_IDTExtensibility2接口点击确定。
    3. 现在Com AddIn部分已经完成,现在要在Word里面加一个CommandBar和一个按钮,并且让按钮响应事件。

    4. 创建一个TcommandBarButton的OleServer类以连接到CommandButton并响应事件。代码:如下
    定义部分
    TCommandBarButtonClick = procedure(const Ctrl: OleVariant; var CancelDefault: OleVariant) of Object;
    TCommandBarButton = class(TOleServer)
    private
    FIntf:        CommandBarButton;
    FOnClick: TCommandBarButtonClick;
    function GetDefaultInterface: CommandBarButton;
    procedure SetOnClick(const Value: TCommandBarButtonClick);
    protected
    procedure InitServerData; override;
    procedure InvokeEvent(DispID: TDispID; var Params: TVariantArray); override;
    public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure Connect; override;
    procedure ConnectTo(svrIntf: CommandBarButton);
    procedure Disconnect; override;
    property DefaultInterface: CommandBarButton read GetDefaultInterface;
    published
    property OnClick : TCommandBarButtonClick read FOnClick write SetOnClick;
    end;
    实施部分
    { TCommandBarButton }

    procedure TCommandBarButton.Connect;
    var
    punk: IUnknown;
    begin
    if FIntf = nil then
    begin
    punk := GetServer;
    ConnectEvents(punk);
    Fintf:= punk as CommandBarButton;
    end;
    end;

    procedure TCommandBarButton.ConnectTo(svrIntf: CommandBarButton);
    begin
    Disconnect;
    FIntf := svrIntf;
    ConnectEvents(FIntf);
    end;

    constructor TCommandBarButton.Create(AOwner: TComponent);
    begin
    inherited;

    end;

    destructor TCommandBarButton.Destroy;
    begin

    inherited;
    end;

    procedure TCommandBarButton.Disconnect;
    begin
    if Fintf <> nil then
    begin
    DisconnectEvents(FIntf);
    FIntf := nil;
    end;
    end;

    function TCommandBarButton.GetDefaultInterface: CommandBarButton;
    begin
    if FIntf = nil then
    Connect;
    Assert(FIntf <> nil, 'DefaultInterface is NULL. Component is not connected to Server. You must call ''Connect'' or ''ConnectTo'' before this operation');
    Result := FIntf;
    end;

    procedure TCommandBarButton.InitServerData;
    const
    CServerData: TServerData = (
    ClassID:   '{55F88891-7708-11D1-ACEB-006008961DA5}';
    IntfIID:   '{000C030E-0000-0000-C000-000000000046}';
    EventIID:  '{000C0351-0000-0000-C000-000000000046}';
    LicenseKey: nil;
    Version: 500);
    begin
    ServerData := @CServerData;
    end;

    procedure TCommandBarButton.InvokeEvent(DispID: TDispID;
    var Params: TVariantArray);
    begin
    case DispID of
    -1: Exit;  // DISPID_UNKNOWN
    1: if Assigned(FOnClick) then
       FOnClick(Params[0], Params[1]);
    end; {case DispID}
    end;

    procedure TCommandBarButton.SetOnClick(
    const Value: TCommandBarButtonClick);
    begin
    FOnClick := Value;
    end;

    5. 继续完成Ttest类
    在类定义里面增加两项
    private
    FCommandBarButton : TCommandBarButton;
    procedure FClick(const Ctrl: OleVariant; var CancelDefault: OleVariant);

    在OnConnection写下面代码
    procedure TTest.OnConnection(const Application: IDispatch;
    ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
    var custom: PSafeArray);
    //这是从资源中读取一个Bitmap并复制到粘贴板
    procedure CopyBitMapToClipBoard;
    var
    aStream : TStream;
    aBitMap : Graphics.TBitmap;
    begin
    with TClipboard.Create do
    begin
       try
         aStream := TResourceStream.CreateFromID(HInstance, 1, RT_RCDATA);
         aBitMap := Graphics.TBitmap.Create;
         aBitMap.LoadFromStream(aStream);
         Assign(aBitMap);
       finally
         aStream.Free;
         aBitMap.Free;
         Free;
       end;
    end;
    end;
    var
    App : WordApplication;
    aCommandBar : CommandBar;
    aButton : _CommandBarButton;
    begin
    App := WordApplication(Application);
    aCommandBar := App.CommandBars.Add('Test', msoBarTop, False, True);
    aButton := aCommandBar.Controls.Add(msoControlButton, EmptyParam, EmptyParam, EmptyParam, True) as _CommandBarButton;
    aButton.Set_Style(msoButtonIconAndCaption);
    aButton.Set_Caption('Test');
    //CopyBitMapToClipBoard; //这两句话是给按钮设定一个外部图标,
    //aButton.PasteFace; //你要增加一个rcdata的bitmap资源bitmap大小为16*16,具体怎么做请参考其他文档
    aButton.Set_Tag('test111');
    FCommandBarButton := TCommandBarButton.Create(nil);
    FCommandBarButton.ConnectTo(aButton);
    FCommandBarButton.OnClick := FClick;
    aCommandBar.Set_Visible(True);
    end;

    在OnDisconnection写下面代码
    procedure TTest.OnDisconnection(RemoveMode: ext_DisconnectMode;
    var custom: PSafeArray);
    begin
    FCommandBarButton.Disconnect;
    FCommandBarButton.Free;
    end;

    写Click事件(在Word文档中插入当前时间)
    procedure TTest.FClick(const Ctrl: OleVariant;
    var CancelDefault: OleVariant);
    begin
    Ctrl.Application.Selection.TypeText(DateTimeToStr(Now) + #13#10);
    end;

    6. 最后用菜单->Run->Register Active Server注册Com对象
    7. 给Word增加Com AddIn打开RegEdit,增加一个项“HKEY_CURRENT_USER\Software\Microsoft\Office\Word\Addins\AddInTest.Test”
    在这个项下面增加一个字符串值“FriendlyName”随便给一个值,如“Test”
    再增加一个双字节值“LoadBehavior”把值设为3

    完成!现在打开Word你就可以看到增加了一个工具栏点一下上面的按钮就会在当前文档输出一个当前时间。
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表