这个图表明的函数的调用顺序,主要代码如下:
1 // MyAddin.cpp : Implementation of DLL Exports.
2
3
4 // Note: Proxy/Stub Information
5 // To merge the proxy/stub code into the object DLL, add the file
6 // dlldatax.c to the project. Make sure precompiled headers
7 // are turned off for this file, and add _MERGE_PROXYSTUB to the
8 // defines for the project.
9 //
// If you are not running WinNT4.0 or Win95 with DCOM, then you
// need to remove the following define from dlldatax.c
// #define _WIN32_WINNT 0x0400
//
// Further, if you are running MIDL without /Oicf switch, you also
// need to remove the following define from dlldatax.c.
// #define USE_STUBLESS_PROXY
//
// Modify the custom build rule for MyAddin.idl by adding the following
// files to the Outputs.
20 // MyAddin_p.c
// dlldata.c
// To build a separate proxy/stub DLL,
// run nmake -f MyAddinps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "MyAddin.h"
#include "dlldatax.h"
#include "MyAddin_i.c"
#include "WordAddin.h"
#ifdef _MERGE_PROXYSTUB
extern "C" HINSTANCE hProxyDll;
#endif
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_WordAddin, CWordAddin)
END_OBJECT_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
MessageBox(NULL,"DllMain",NULL,MB_OK);
lpReserved;
#ifdef _MERGE_PROXYSTUB
if (!PrxDllMain(hInstance, dwReason, lpReserved))
return FALSE;
#endif
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_MYADDINLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
MessageBox(NULL,"DllCanUnloadNow",NULL,MB_OK);
#ifdef _MERGE_PROXYSTUB
if (PrxDllCanUnloadNow() != S_OK)
return S_FALSE;
#endif
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
MessageBox(NULL,"DllGetClassObject",NULL,MB_OK);
#ifdef _MERGE_PROXYSTUB
if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
return S_OK;
#endif
return _Module.GetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
MessageBox(NULL,"DllRegisterServer",NULL,MB_OK);
#ifdef _MERGE_PROXYSTUB
HRESULT hRes = PrxDllRegisterServer();
if (FAILED(hRes))
return hRes;
#endif
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
MessageBox(NULL,"DllUnregisterServer",NULL,MB_OK);
#ifdef _MERGE_PROXYSTUB
PrxDllUnregisterServer();
#endif
return _Module.UnregisterServer(TRUE);
}
还有一份代码如下:
1 // WordAddin.h : Declaration of the CWordAddin
2
3 #ifndef __WORDADDIN_H_
4 #define __WORDADDIN_H_
5
6 #include "resource.h" // main symbols
7 #include "stdafx.h"
8 #include "StdAfx.h"
9 #import "C:\Program Files\Common Files\designer\MSADDNDR.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids
10
11 extern _ATL_FUNC_INFO OnClickButtonInfo;
12
13 /////////////////////////////////////////////////////////////////////////////
14 // CWordAddin
15 class ATL_NO_VTABLE CWordAddin :
16 public CComObjectRootEx<CComSingleThreadModel>,
17 public CComCoClass<CWordAddin, &CLSID_WordAddin>,
18 public IDispatchImpl<IWordAddin, &IID_IWordAddin, &LIBID_MYADDINLib>,
19 public IDispatchImpl<_IDTExtensibility2, &IID__IDTExtensibility2, &LIBID_AddInDesignerObjects>,
20 public IDispEventSimpleImpl<1,CWordAddin,&__uuidof(Office::_CommandBarButtonEvents)>,
21 public IDispatchImpl<IRibbonExtensibility, &IID_IRibbonExtensibility, &LIBID_Office>
22 {
23 public:
24 CWordAddin()
25 {
26 int i = 0;
27 }
28
29 DECLARE_REGISTRY_RESOURCEID(IDR_WORDADDIN)
30
31 DECLARE_PROTECT_FINAL_CONSTRUCT()
32
33 BEGIN_COM_MAP(CWordAddin)
34 COM_INTERFACE_ENTRY(IWordAddin)
35 //DEL COM_INTERFACE_ENTRY(IDispatch)
36 COM_INTERFACE_ENTRY2(IDispatch, IWordAddin)
37 COM_INTERFACE_ENTRY(_IDTExtensibility2)
38 COM_INTERFACE_ENTRY(IRibbonExtensibility)
39 END_COM_MAP()
40
41 BEGIN_SINK_MAP(CWordAddin)
42 SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/ 0x01, OnClickButton1, &OnClickButtonInfo)
43 END_SINK_MAP()
44
45 // IWordAddin
46 public:
47 STDMETHOD(OnMyButton)(/*[in]*/IDispatch* pIDispControl);
48 CComQIPtr <Word::_Application> m_spApp;
49 CComPtr < Office::_CommandBarButton> m_spCmdButton;
50 typedef IDispEventSimpleImpl</*nID =*/ 1,CWordAddin, &__uuidof(Office::_CommandBarButtonEvents)> CommandButton1Events;
51 // _IDTExtensibility2
52 STDMETHOD(OnConnection)(IDispatch * Application, ext_ConnectMode ConnectMode, IDispatch * AddInInst, SAFEARRAY * * custom)
53 {
54 ::MessageBox(NULL,"OnConnection","",MB_OK);
55 OutputDebugString("OnConnection");
56 //Delete it for the Office 2007
57
58 CComPtr < Office::_CommandBars> spCmdBars;
59 CComQIPtr <Word::_Application> spApp(Application);
60 m_spApp = spApp;
61 ATLASSERT(spApp);
62
63 HRESULT hr = spApp->get_CommandBars(&spCmdBars);
64 if(FAILED(hr))
65 return hr;
66
67 ATLASSERT(spCmdBars);
68
69
70 CComVariant vName("MyAddin");
71 CComPtr <Office::CommandBar> spNewCmdBar;
72 CComVariant vPos(1);
73 CComVariant vTemp(VARIANT_TRUE);
74 CComVariant vEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
75 spNewCmdBar = spCmdBars->Add(vName, vPos, vEmpty, vTemp);
76
77
78 CComPtr < Office::CommandBarControls> spBarControls;
79 spBarControls = spNewCmdBar->GetControls();
80 ATLASSERT(spBarControls);
81
82
83 CComVariant vToolBarType(1);
84 CComVariant vShow(VARIANT_TRUE);
85 CComPtr < Office::CommandBarControl> spNewBar;
86 spNewBar = spBarControls->Add(vToolBarType, vEmpty, vEmpty, vEmpty, vShow);
87 ATLASSERT(spNewBar);
88
89
90
91 CComQIPtr < Office::_CommandBarButton> spCmdButton(spNewBar);
92 ATLASSERT(spCmdButton);
93
94 HBITMAP hBmp =(HBITMAP)::LoadImage(_Module.GetResourceInstance(),
95 MAKEINTRESOURCE(IDB_BITMAP),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS);
96
97 ::OpenClipboard(NULL);
98 ::EmptyClipboard();
99 ::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);
return S_OK;
}
STDMETHOD(OnDisconnection)(ext_DisconnectMode RemoveMode, SAFEARRAY * * custom)
{
MessageBox(NULL,"OnDisconnection",NULL,MB_OK);
if(m_spCmdButton != NULL)
CommandButton1Events::DispEventUnadvise((IDispatch*)m_spCmdButton);
return S_OK;
}
STDMETHOD(OnAddInsUpdate)(SAFEARRAY * * custom)
{
MessageBox(NULL,"OnAddInsUpdate",NULL,MB_OK);
return S_OK;
}
STDMETHOD(OnStartupComplete)(SAFEARRAY * * custom)
{
MessageBox(NULL,"OnStartupComplete",NULL,MB_OK);
return S_OK;
}
STDMETHOD(OnBeginShutdown)(SAFEARRAY * * custom)
{
MessageBox(NULL,"OnBeginShutdown",NULL,MB_OK);
return S_OK;
}
void __stdcall OnClickButton1(IDispatch * /*Office::_CommandBarButton**/ Ctrl,VARIANT_BOOL * CancelDefault);
// IRibbonExtensibility
STDMETHOD(raw_GetCustomUI)(BSTR RibbonID, BSTR * RibbonXml)
{
MessageBox(NULL,"raw_GetCustomUI",NULL,MB_OK);
OutputDebugString("raw_GetCustomUI");
char szRibbon[MAX_PATH*10] = {0x00};
LoadString(_Module.GetModuleInstance(),IDS_RIBBON_XML, \
szRibbon, MAX_PATH*10);
if (RibbonXml == NULL)
return E_POINTER;
OutputDebugString(szRibbon);
CComBSTR bstr(szRibbon);
bstr.CopyTo(RibbonXml);//use this to avoid heap destroy
bstr.Empty();
return S_OK;
}
};
#endif //__WORDADDIN_H_
这是两个主要的文件。
注意两个问题:
CComBSTR bstr(szRibbon);
bstr.CopyTo(RibbonXml);//use this to avoid heap destroy
bstr.Empty();
这三行代码是为了防止程序退出时,插件对word的内存进行修改,导致堆错误,Word会Crash。函数的含义请参考MSDN。