设为首页 加入收藏

TOP

使用VC++ ATL实现Office的COM插件(三)
2012-11-04 14:11:53 来源: 作者: 【 】 浏览:1128
Tags:使用 ATL 实现 Office COM 插件
  添加菜单项的过程与之相类似:

  首先通过调用CommandBars集合的get_ActiveMenuBar()方法得到一个CommandBar对象,这个对象代表当前的工程中的活动菜单,然后调用CommandBar的GetControls得到当前菜单的控件集合。尝试在Word的“格式”菜单(第5个菜单)中加入新的菜单项,调用CommandBarControls的GetItem(5)得到需要的“格式”菜单项,它也是一个CommandBarControls集合,(前面曾经提到,控件集是可以嵌套的),这样就可以通过调用它的Add方法添加新的菜单项了。具体的实现代码如下:

_bstr_t bstrNewMenuText(OLESTR("New Menu Item"));
CComPtr < Office::CommandBarControls> spCmdCtrls;
CComPtr < Office::CommandBarControls> spCmdBarCtrls;
CComPtr < Office::CommandBarPopup> spCmdPopup;
CComPtr < Office::CommandBarControl> spCmdCtrl;

// get CommandBar that is Word''s main menu
hr = spCmdBars->get_ActiveMenuBar(&spCmdBar);
if (FAILED(hr))
 return hr;

// get menu as CommandBarControls
spCmdCtrls = spCmdBar->GetControls();
ATLASSERT(spCmdCtrls);

// we want to add a menu entry to Outlook''s 6th(Tools) menu //item
CComVariant vItem(5);
spCmdCtrl= spCmdCtrls->GetItem(vItem);
ATLASSERT(spCmdCtrl);

IDispatchPtr spDisp;
spDisp = spCmdCtrl->GetControl();

// a CommandBarPopup interface is the actual menu item
CComQIPtr < Office::CommandBarPopup> ppCmdPopup(spDisp);
ATLASSERT(ppCmdPopup);
spCmdBarCtrls = ppCmdPopup->GetControls();
ATLASSERT(spCmdBarCtrls);

CComVariant vMenuType(1); // type of control - menu
CComVariant vMenuPos(6);
CComVariant vMenuEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
CComVariant vMenuShow(VARIANT_TRUE); // menu should be visible
CComVariant vMenuTemp(VARIANT_TRUE); // menu is temporary

CComPtr < Office::CommandBarControl> spNewMenu;

// now create the actual menu item and add it
spNewMenu = spCmdBarCtrls->Add(vMenuType, vMenuEmpty, vMenuEmpty,
vMenuEmpty, vMenuTemp);
ATLASSERT(spNewMenu);
spNewMenu->PutCaption(bstrNewMenuText);
spNewMenu->PutEnabled(VARIANT_TRUE);
spNewMenu->PutVisible(VARIANT_TRUE);

//we''d like our new menu item to look cool and display
// an icon. Get menu item as a CommandBarButton
CComQIPtr < Office::_CommandBarButton> spCmdMenuButton(spNewMenu);
ATLASSERT(spCmdMenuButton);
spCmdMenuButton->PutStyle(Office::msoButtonIconAndCaption);

// we want to use the same toolbar bitmap for menuitem too.
// we grab the CommandBarButton interface so we can add
// a bitmap to it through PasteFace().
spCmdMenuButton->PasteFace();

// show the menu
spNewMenu->PutVisible(VARIANT_TRUE);

return S_OK;

  这时运行程序,可以看到添加的按钮和菜单项已经出现在Word中,还需要为其加入响应事件,这样才能真正的通过插件扩展Word的功能。

  8、为我刚加入的按钮加入其响应事件:

  ATL为COM对象的Idispatch接口提供了两个模板类:IDispEventImpl<>和IDispEventSimpleImpl<>,选择IDispEventSimpleImpl<>,因为它不需要额外的类型库信息,从IDispEventSimpleImpl<>继承一个类:

class ATL_NO_VTABLE CAddin :
public CComObjectRootEx < CComSingleThreadModel>,
.....

public IDispEventSimpleImpl<1,CAddin,
&__uuidof(Office::_CommandBarButtonEvents>

  声明按钮点击事件的回调函数:

void __stdcall OnClickButton(Idispatch * /*Office::_CommandBarButton**/ Ctrl,VARIANT_BOOL * CancelDefault);

  用_ATL_SINK_INFO结构描述回调的参数信息:打开CAddin.h文件,在其最上加入以下声明:

extern _ATL_FUNC_INFO OnClickButtonInfo;(注意一定声明为外部变量)

  然后打开CAddin.cpp文件为其加入以下定义:

_ATL_FUNC_INFO OnClickButtonInfo ={CC_STDCALL,VT_EMPTY,2,{VT_DISPATCH,VT_BYREF | VT_BOOL}};

  加入按钮点击事件的具体实现:

void __stdcall CAddin::OnClickButton(IDispatch*
/*Office::_CommandBarButton* */ Ctrl,
VARIANT_BOOL * CancelDefault)
{
 USES_CONVERSION;
 CComQIPtr pCommandBarButton(Ctrl);

 //the button that raised the event. Do something with this...
 MessageBox(NULL, "Clicked Button1", "OnClickButton", MB_OK);
}

  在接口映射宏中加入以下信息:

BEGIN_SINK_MAP(CAddin)
SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),
/*dispid*/ 0x01,
OnClickButton, &OnClickButtonInfo)
END_SINK_MAP()

  最后在分别在CAddin 类的 OnConnection() 和OnDisconnection()中调用DispEventAdvise() 和 DispEventUnadvise()连接和断开连接消息来源。

  到这里就实现了一个简单的COM插件,运行程序,点击工具栏上新加入的按钮,就可以弹出("Clicked Button1")消息框。

  如果熟悉VBA编程(www.cppentry.com),就可以把编写的宏作为按钮响应事件,只需调用按钮的put_OnAction()方法:

spCmdButton->put_OnAction(OLESTR("YourMacroName"));
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Visual C++初学者指针学习指南 下一篇VC中利用FTP协议实现多线程断点续..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: