vc 6.0编写word2003插件

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

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

 

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

 

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

 

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

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

 

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

 

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

 

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

 

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

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

//文件SimAddin.rgs文件中添加一个代码

HKLM
    {
      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中添加以下代码

//我安装的office工具软件中没有mso.dll文件,然后从网上下载啦一个

#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作准备。
最后一步,编写代码。  

//在classview视图中OnConnection方法添加以下代码

 

CComPtr < Office::_CommandBars> spCmdBars;

   //word应用接口_Application
      CComQIPtr <Word::_Application> spApp(Application);
      ATLASSERT(spApp);

   //获取CommandBars接口
      HRESULT hr = spApp->get_CommandBars(&spCmdBars);
      if(FAILED(hr))
      return hr;
      ATLASSERT(spCmdBars);

   //新增一个工具条及一个位图
      CComVariant vName("MyAddin");
      CComPtr <Office::CommandBar> spNewCmdBar;

   //新增工具条位置
      CComVariant vPos(1);

      CComVariant vTemp(VARIANT_TRUE); //临时变量
      CComVariant vEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
   //用Add方法在指定位置新增一个工具条并让spNewCmdBar指向它
      spNewCmdBar = spCmdBars->Add(vName, vPos, vEmpty, vTemp);
     
    //application->word->commandbars->comandbar->
    // commandbarControls->commandbarcontrol:_commandbarButton
  
   //获取新增工具条的CommandBarControls,从而在其上添加按钮
      CComPtr < Office::CommandBarControls> spBarControls;
      spBarControls = spNewCmdBar->GetControls();
      ATLASSERT(spBarControls);
      
      //msoControlType::msoControlButton=1
      CComVariant vToolBarType(1);
   //显示工具条
      CComVariant vShow(VARIANT_TRUE);

      CComPtr < Office::CommandBarControl> spNewBar;

   //用CommandBarControls中的Add方法新增一个按钮,并让spNewBar z指向它
      spNewBar = spBarControls->Add(vToolBarType, vEmpty, vEmpty, vEmpty, vShow);
      ATLASSERT(spNewBar);
     
   //为每一个按钮指定_CommandBarButton接口,可以指定显示样式
      CComQIPtr < Office::_CommandBarButton> spCmdButton(spNewBar);
      ATLASSERT(spCmdButton);
      
   //设置显示风格,将其放入剪贴板中用PasteFace()贴在指定的按钮上
      HBITMAP hBmp =(HBITMAP)::LoadImage(_Module.GetResourceInstance(),
      MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS);
    //说明IDB_BITMAP1为你导入图片的标示名,这里为新建的一个图片
      ::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;
   //事件处理代码
   CommandButton1Events::DispEventAdvise((IDispatch*)m_spCmdButton);

   //m_spCmdButton为CSimAddin类添加的属性变量
   ::EmptyClipboard();
   return S_OK;

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

 

但是点击时没有响应,最后就让我们来解决这个问题。
1. 在CSimAddin继承类中加入IDispEventSimpleImpl接口实现,代码如下:

//在SimAddin.h文件中加入:

class ATL_NO_VTABLE CSimAddin :
 public CComObjectRootEx<CComSingleThreadModel>,
 public CComCoClass<CSimAddin, &CLSID_SimAddin>,
 public IDispatchImpl<ISimAddin, &IID_ISimAddin, &LIBID_TESTADDINLib>,
 public IDispatchImpl<_IDTExtensibility2, &IID__IDTExtensibility2, &LIBID_AddInDesignerObjects>,
 //加入的代码
 //public IDispEventSimpleImpl</*nID =*/ 1, CSimple, &__uuidof(Word::ApplicationEvents)>
 //继承IDispEventSimpleImpl接口

 //关键代码
 public IDispEventSimpleImpl<1,CSimAddin,&__uuidof(Office::_CommandBarButtonEvents)>       

2. 声明_ATL_SINK_INFO结构回调参数信息。

 

(1)在SimAddin.h文件中加入下面语句:

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

 

(2)在SimAddin.cpp文件中加入定义语句,如下:
 a.//按钮事件响应信息定义
_ATL_FUNC_INFO OnClickButtonInfo = {CC_STDCALL,VT_EMPTY,2,{VT_DISPATCH,VT_BYREF|VT_BOOL}};

  b.//按钮事件响应函数定义
void __stdcall CSimAddin::OnClickButton1(IDispatch* Ctrl,VARIANT_BOOL * CancelDefault)
{
    MessageBox(NULL,"Hello World","World",MB_OK);
}

3.在SimAddin.h中end_com_map()下

加入Sink映射,如下:

BEGIN_SINK_MAP(CSimAddin)
    SINK_ENTRY_INFO(1,__uuidof(Office::_CommandBarButtonEvents),0x01,OnClickButton1,&OnClickButtonInfo)
END_SINK_MAP()

4. 最后,打开或断开与接口的连接。方法如下
在OnConnection接口函数的最后部分,加入下面代码来打开连接:
//此定义在CSimAddin类中,类型定义
typedef IDispEventSimpleImpl<1,CSimAddin,&__uuidof(Office::_CommandBarButtonEvents)> CommandButton1Events; 
  a.在OnConnection接口函数的最后部分,加入下面代码来打开事件源: 

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

   b. 在OnDisconnection接口函数中,加入下面代码来断开事件源:

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值