用VC6.0编写Word插件(Office2K、XP、2003)(转)

作者:hjphy
发布日期:2007-01-26 16:15
浏览次数:6484次

标  签:图形用户界面,windows

操  作:下载源文件

文章概要:本文详细介绍了office插件的编写方法,并提供详细源代码。

最近因为工作的需要,学习了一下Office插件的编写方法。在走了不少弯路以后,最后终于把编写插件的原理给搞清楚了,不敢独享,拿出来跟大家共享一下。下面就以Word 2003为例,向大家简单介绍一下。

第一步,利用向导生成一个ATL COM AppWizard的新工程。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第1张图片 

图1

在向导的第一个对话框中,服务器类型选择Dynamic Link Library(DLL),然后单击Finish即可。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第2张图片 

图2

然后,选取菜单Insert->New ATL Object项,在弹出的ATL对象向导对话框中选中相应Objects对应右侧的Simple Object选项,点击下一步。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第3张图片 

图3

在弹出的对话框中ShortName中输入相应名称,点确定完成插入ATL对象。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第4张图片 

图4

这样一个简单的基于ATL的COM组件工程就建立成功了。

第二步,通过导入类型库来实现_IDTExtensibility2接口。在ClassView中的新加的类上点鼠标右键,在弹出的右键菜单中选Implement Interface项。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第5张图片 

图5

在弹出的实现接口对话框中点击Add Typelib

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第6张图片 

图6

在弹出的Browse Type Libraries对话框中,选取Microsoft Add-in Designer(1.0)子项,点OK按

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第7张图片 

图7

在弹出的接口列表对话框中选中_IDTExtensibility2接口,点OK按钮完成导入

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第8张图片 

这样的话,系统将会自动为你生成空的五个所需接口函数,分别是OnConnection、OnDisconnection、OnAddInsUpdate、OnStartupComplete、OnBeginShutdown。

第三步,通过上面的两个步骤,我们的插件框架已经形成,但是Office怎么知道启动的时候要来把我们的插件Load起来呢?Office的不同组件,例如Word、Excel、Outlook等怎么知道去Load自己的插件呢?答案就是在注册表中加入相应的键值。打开文件视图FileView―>Resource File中的rgs文件,加入以下代码:

HKCU
    {
      Software
       {
        Microsoft
        {
          Office
             { 
            Word
               {
             Addins
               {
               ''TestAddin.SimAddin''
                { 
                 val FriendlyName = s ''WORD Custom Addin''
                 val Description = s ''Word Custom Addin''
                 val LoadBehavior = d ''00000003''
                 val CommandLineSafe = d ''00000001''
                 }
               }
             }
          }
       }
   }
}

以上代码由三个需要注意的地方:

1. Office下面的那个子项代表了这个插件是属于那个组件,Word、Excel、Outlook等等。

2. Addins下面的那个子项要写成你添加的COM组件的名字,千万不要照着我的工程的名字照抄。

3. 所有的值两边加的都是单引号,而且要用英文下的单引号,不能用双引号。

这样一个Office插件的框架才算完成,你可以在OnConnection函数中加一些测试代码,看看有没有执行到,如果执行成功才能继续,否则检查上面的步骤有没有错误。

第四步,同时需要import两个office的文件,一个是MSO.dll,另一个是MSWORD.OLB。这两个文件可以在以下位置找到(具体位置与office安装路径有关):
C:\Program Files\Common Files\Microsoft Shared\OFFICE11

C:\Program Files\Microsoft Office\OFFICE11

然后在stdafx.h中加入如下语句:

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE11\\mso.dll" 
        \
        rename_namespace("Office") named_guids,exclude("Pages")
using namespace Office;

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.olb" rename_namespace("VBE6")
using namespace VBE6;

#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\MSWORD.OLB" rename("ExitWindows","ExitWindowsEx")
#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\MSWORD.OLB" 
        \
        rename_namespace("Word"), raw_interfaces_only, named_guids ,exclude("Pages")
using namespace Word;

加完以上代码以后一定要编译一下,看看是否能够成功。引入这两个文件的原因,主要是为了引入一些变量类型,为后面的创建UI作准备。
最后一步,编写代码。在OnConnection加入如下代码:

CComPtr < Office::_CommandBars> spCmdBars; 
CComQIPtr  spApp(Application); 
ATLASSERT(spApp);
HRESULT hr = spApp->get_CommandBars(&spCmdBars);
if(FAILED(hr))
return hr;
ATLASSERT(spCmdBars);
CComVariant vName("MyAddin");
CComPtr  spNewCmdBar;
CComVariant vPos(1); 
CComVariant vTemp(VARIANT_TRUE); 
CComVariant vEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR); 
spNewCmdBar = spCmdBars->Add(vName, vPos, vEmpty, vTemp);
 
CComPtr < Office::CommandBarControls> spBarControls;
spBarControls = spNewCmdBar->GetControls();
ATLASSERT(spBarControls);
 
CComVariant vToolBarType(1);
CComVariant vShow(VARIANT_TRUE);
CComPtr < Office::CommandBarControl> spNewBar; 
spNewBar = spBarControls->Add(vToolBarType, vEmpty, vEmpty, vEmpty, vShow); 
ATLASSERT(spNewBar);
  
CComQIPtr < Office::_CommandBarButton> spCmdButton(spNewBar);
ATLASSERT(spCmdButton);
  
HBITMAP hBmp =(HBITMAP)::LoadImage(_Module.GetResourceInstance(),
MAKEINTRESOURCE(IDB_BITMAP),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS);
  
::OpenClipboard(NULL);
::EmptyClipboard();
::SetClipboardData(CF_BITMAP, (HANDLE)hBmp);
::CloseClipboard();
::DeleteObject(hBmp); 
  
spCmdButton->PutStyle(Office::msoButtonIconAndCaption);
hr = spCmdButton->PasteFace();
if (FAILED(hr))
return hr;
  
spCmdButton->PutVisible(VARIANT_TRUE); 
spCmdButton->PutCaption(OLESTR("myAddin")); 
spCmdButton->PutEnabled(VARIANT_TRUE);
spCmdButton->PutTooltipText(OLESTR("test1")); 
spCmdButton->PutTag(OLESTR("test1")); 
spNewCmdBar->PutVisible(VARIANT_TRUE); 
  
m_spCmdButton = spCmdButton;

这样,再次打开word,就可以看到如图一所示的界面效果了。

用VC6.0编写Word插件(Office2K、XP、2003)(转)_第9张图片 

图9

但是点击时没有响应,最后就让我们来解决这个问题。

1. 在COutlookAddin继承类中加入IDispEventSimpleImpl继承,代码如下:

class ATL_NO_VTABLE COutlookAddin : 
        public CComObjectRootEx,
        ……
        public IDispEventSimpleImpl<1,COutlookAddin,&__uuidof(Office::_CommandBarButtonEvents)> 

2. 声明_ATL_SINK_INFO结构回调参数信息。在OutlookAddin.h文件中加入下面语句:

// 按钮事件响应信息声明
extern _ATL_FUNC_INFO OnClickButtonInfo;

在OutlookAddin.cpp文件中加入定义语句,如下:

// 按钮事件响应信息定义
_ATL_FUNC_INFO OnClickButtonInfo ={CC_STDCALL,VT_EMPTY,2,{VT_DISPATCH,VT_BYREF
        | VT_BOOL}};

3. 加入Sink映射,如下:

EGIN_SINK_MAP(COutlookAddin)
      SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/
      0x01, OnClickButton1, &OnClickButtonInfo)
      SINK_ENTRY_INFO(2, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/
      0x01, OnClickButton2, &OnClickButtonInfo)
      SINK_ENTRY_INFO(3, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/
      0x01, OnClickMenu, &OnClickButtonInfo)
      END_SINK_MAP()

4. 加入事件函数。在OutlookAddin.h中加入声明:

void __stdcall OnClickButton1(IDispatch * /*Office::_CommandBarButton**/
Ctrl,VARIANT_BOOL * CancelDefault);

在OutlookAddin.cpp中加入实现:

// 工具条按钮1点击事件响应函数

void __stdcall CWordAddin::OnClickButton1(IDispatch * 
	/*Office::_CommandBarButton**/ Ctrl,VARIANT_BOOL * CancelDefault)
{
		MessageBox(NULL, "hello", "world", MB_OK);
}

5. 最后,打开或断开与接口的连接。方法如下

在OnConnection接口函数的最后部分,加入下面代码来打开连接:

在OnConnection接口函数的最后部分,加入下面代码来打开连接:

CommandButton1Events::DispEventAdvise((IDispatch*)m_spButton);

在OnDisconnection接口函数中,加入下面代码来断开连接:

CommandButton1Events::DispEventUnadvise((IDispatch*)m_spButton);

综上所述,编写一个简单的office的插件,其实并不难,只要按照步骤一步一步进行,肯定能成功,如果大家在使用过程中有什么疑问,欢迎一起探讨。

相关链接:Office2000下内部COM插件的编程实现


转自:http://www.vckbase.com/index.php/wv/1442

源代码地址:http://www.vckbase.com/Public/Uploads/attach/code/98/myaddin.rar


评论:

    lhw978 评论道:
    http://www.vckbase.com/index.php/wv/1109《使用VC++ ATL实现Office的COM插件》的帖子,除了错误百出外,似乎源代码只适合word 2000,我在word2003编译都失败了。
        2013-08-02 03:09 发表


   lhw978 评论道:
    这个帖子至少源代码能编译运行通过。相比http://www.vckbase.com/index.php/wv/1109</span>《使用VC++ ATL实现Office的COM插件》的帖子,除了错误
        2013-08-02 03:08 发表


    lhw978 评论道:
    文字上的少量错误,通过用beyond compare 工具对比源代码,最终却是编译通过了。
        2013-08-02 03:05 发表


    DeltaCao 评论道:
    内容是对的,文字上不少错误。
        2013-01-16 15:35 发表


你可能感兴趣的:(word,VC6)