这个图表明的函数的调用顺序,主要代码如下:
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 // 10 // If you are not running WinNT4.0 or Win95 with DCOM, then you 11 // need to remove the following define from dlldatax.c 12 // #define _WIN32_WINNT 0x0400 13 // 14 // Further, if you are running MIDL without /Oicf switch, you also 15 // need to remove the following define from dlldatax.c. 16 // #define USE_STUBLESS_PROXY 17 // 18 // Modify the custom build rule for MyAddin.idl by adding the following 19 // files to the Outputs. 20 // MyAddin_p.c 21 // dlldata.c 22 // To build a separate proxy/stub DLL, 23 // run nmake -f MyAddinps.mk in the project directory. 24 25 #include "stdafx.h" 26 #include "resource.h" 27 #include <initguid.h> 28 #include "MyAddin.h" 29 #include "dlldatax.h" 30 31 #include "MyAddin_i.c" 32 #include "WordAddin.h" 33 34 #ifdef _MERGE_PROXYSTUB 35 extern "C" HINSTANCE hProxyDll; 36 #endif 37 38 CComModule _Module; 39 40 BEGIN_OBJECT_MAP(ObjectMap) 41 OBJECT_ENTRY(CLSID_WordAddin, CWordAddin) 42 END_OBJECT_MAP() 43 44 ///// 45 // DLL Entry Point 46 47 extern "C" 48 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 49 { 50 MessageBox(NULL,"DllMain",NULL,MB_OK); 51 lpReserved; 52 #ifdef _MERGE_PROXYSTUB 53 if (!PrxDllMain(hInstance, dwReason, lpReserved)) 54 return FALSE; 55 #endif 56 if (dwReason == DLL_PROCESS_ATTACH) 57 { 58 _Module.Init(ObjectMap, hInstance, &LIBID_MYADDINLib); 59 DisableThreadLibraryCalls(hInstance); 60 } 61 else if (dwReason == DLL_PROCESS_DETACH) 62 _Module.Term(); 63 return TRUE; // ok 64 } 65 66 ///// 67 // Used to determine whether the DLL can be unloaded by OLE 68 69 STDAPI DllCanUnloadNow(void) 70 { 71 MessageBox(NULL,"DllCanUnloadNow",NULL,MB_OK); 72 #ifdef _MERGE_PROXYSTUB 73 if (PrxDllCanUnloadNow() != S_OK) 74 return S_FALSE; 75 #endif 76 return (_Module.GetLockCount()==0) ? S_OK : S_FALSE; 77 } 78 79 ///// 80 // Returns a class factory to create an object of the requested type 81 82 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) 83 { 84 MessageBox(NULL,"DllGetClassObject",NULL,MB_OK); 85 #ifdef _MERGE_PROXYSTUB 86 if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK) 87 return S_OK; 88 #endif 89 90 return _Module.GetClassObject(rclsid, riid, ppv); 91 } 92 93 ///// 94 // DllRegisterServer - Adds entries to the system registry 95 96 STDAPI DllRegisterServer(void) 97 { 98 MessageBox(NULL,"DllRegisterServer",NULL,MB_OK); 99 #ifdef _MERGE_PROXYSTUB 100 HRESULT hRes = PrxDllRegisterServer(); 101 if (FAILED(hRes)) 102 return hRes; 103 #endif 104 // registers object, typelib and all interfaces in typelib 105 106 return _Module.RegisterServer(TRUE); 107 } 108 109 ///// 110 // DllUnregisterServer - Removes entries from the system registry 111 112 STDAPI DllUnregisterServer(void) 113 { 114 MessageBox(NULL,"DllUnregisterServer",NULL,MB_OK); 115 #ifdef _MERGE_PROXYSTUB 116 PrxDllUnregisterServer(); 117 #endif 118 119 return _Module.UnregisterServer(TRUE); 120 }
还有一份代码如下:
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); 100 ::CloseClipboard(); 101 ::DeleteObject(hBmp); 102 103 104 spCmdButton->PutStyle(Office::msoButtonIconAndCaption); 105 hr = spCmdButton->PasteFace(); 106 if (FAILED(hr)) 107 return hr; 108 109 spCmdButton->PutVisible(VARIANT_TRUE); 110 spCmdButton->PutCaption(OLESTR("myAddin")); 111 spCmdButton->PutEnabled(VARIANT_TRUE); 112 spCmdButton->PutTooltipText(OLESTR("test1")); 113 spCmdButton->PutTag(OLESTR("test1")); 114 115 spNewCmdBar->PutVisible(VARIANT_TRUE); 116 117 m_spCmdButton = spCmdButton; 118 119 CommandButton1Events::DispEventAdvise((IDispatch*)m_spCmdButton); 120 return S_OK; 121 } 122 STDMETHOD(OnDisconnection)(ext_DisconnectMode RemoveMode, SAFEARRAY * * custom) 123 { 124 MessageBox(NULL,"OnDisconnection",NULL,MB_OK); 125 if(m_spCmdButton != NULL) 126 CommandButton1Events::DispEventUnadvise((IDispatch*)m_spCmdButton); 127 return S_OK; 128 } 129 STDMETHOD(OnAddInsUpdate)(SAFEARRAY * * custom) 130 { 131 MessageBox(NULL,"OnAddInsUpdate",NULL,MB_OK); 132 return S_OK; 133 } 134 STDMETHOD(OnStartupComplete)(SAFEARRAY * * custom) 135 { 136 MessageBox(NULL,"OnStartupComplete",NULL,MB_OK); 137 return S_OK; 138 } 139 STDMETHOD(OnBeginShutdown)(SAFEARRAY * * custom) 140 { 141 MessageBox(NULL,"OnBeginShutdown",NULL,MB_OK); 142 return S_OK; 143 } 144 145 void __stdcall OnClickButton1(IDispatch * /*Office::_CommandBarButton**/ Ctrl,VARIANT_BOOL * CancelDefault); 146 147 // IRibbonExtensibility 148 STDMETHOD(raw_GetCustomUI)(BSTR RibbonID, BSTR * RibbonXml) 149 { 150 MessageBox(NULL,"raw_GetCustomUI",NULL,MB_OK); 151 OutputDebugString("raw_GetCustomUI"); 152 char szRibbon[MAX_PATH*10] = {0x00}; 153 LoadString(_Module.GetModuleInstance(),IDS_RIBBON_XML, \ 154 szRibbon, MAX_PATH*10); 155 if (RibbonXml == NULL) 156 return E_POINTER; 157 158 OutputDebugString(szRibbon); 159 160 CComBSTR bstr(szRibbon); 161 bstr.CopyTo(RibbonXml);//use this to avoid heap destroy 162 bstr.Empty(); 163 return S_OK; 164 } 165 }; 166 167 #endif //__WORDADDIN_H_
这是两个主要的文件。
注意两个问题:
160 CComBSTR bstr(szRibbon); 161 bstr.CopyTo(RibbonXml);//use this to avoid heap destroy 162 bstr.Empty();
这三行代码是为了防止程序退出时,插件对word的内存进行修改,导致堆错误,Word会Crash。函数的含义请参考MSDN。