其他參考資料 http://www.vckbase.com/document/viewdoc/?id=1749 用VC6.0編寫Word插件(Office2007篇) http://www.vckbase.com/document/viewdoc/?id=1737 用VC6.0編寫Word插件(Office2K、XP、03) ------------------------------------------------------------------------------------ 以上為本人轉載 下面是作者ZDNet China 的文章 |
實作Office的COM插件 |
作者: ZDNet China 2003-08-11 01:43 PM |
當軟體開發者考慮擴充Microsoft Office時,最常想到方法就是是使用VB了。實際上,用C++和ATL擴充Office是相當容易的。 我将向你示範如何建立項目以及如何把Office插件作為COM對象注冊到Office中去。(本文用Outlook來作為插件的主程式。) 項目的建立讓我們建立一個新的ATL項目。首先,添加一個叫着Plugin的簡單COM對象。用類向導把_IDTExtensibility2接口添加到Plugin類中。(别忘了選中IsupportErrorInfo複選框。) 類向導會把下述方法添加到Plugin類中:OnConnection、OnDisconnection、OnAddinsUpdate、 OnStartupComplete、OnBeginShutdown。本文隻處理OnConnection和OnDisconnection方法。 然後,在Plugin頭檔案中建立一個類型定義(typedef,它隻是用來簡化代碼的),如下所示: #define APPID 102 class CPlugin; typedef IDispEventImpl<APPID, CPlugin, &DIID_ApplicationEvents, &LIBID_Outlook,9,0> OutLookSink; 我們現在需要在Plugin類的繼承清單中添加OutLookSink類: class ATL_NO_VTABLE CPlugin : public IPlugin, public IDispatchImpl<_IDTExtensibility2, &__uuidof(_IDTExtensibility2), &LIBID_AddInDesignerObjects, 1, 0>, public OutLookSink 在Plugin.h檔案中為Mso9.dll和Msoutl9.olb引入聲明,如下所示: #import "C:\Program Files\Common Files\Designer\msaddndr.dll" \ raw_interfaces_only, \ raw_native_types, no_namespace, named_guids, auto_search #import "C:\Program Files\Microsoft Office\Office\mso9.dll" \ rename_namespace("Office") named_guids #import "C:\Program Files\Microsoft \ Office\Office\msoutl9.olb" \ rename_namespace("Outlook"), raw_interfaces_only, \ named_guids using namespace Office; using namespace Outlook; 注意,你需要按照你的系統中的檔案路徑來修正上面那些被引入檔案的路徑。 你必須把Office擴充作為COM元件注冊到Office中去。Visual C++自動産生.rgs檔案來控制COM注冊。我們将需要添加額外的項目加到.rgs檔案來支援Office的自動注冊。 在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office鍵下,有若幹個子鍵,每一個子鍵對應于系統中安裝的每一個Office應用程式。在這些鍵中有插件關鍵字(add-in key)。 為了在Office中注冊我們的COM對象,我們需要在插件鍵中添加新鍵。在HKEY_CURRENT_USER下同樣有對應的樹來控制單個使用者的插件,而HKEY_LOCAL_MACHINE控制整個機器的插件。 下面是.rgs檔案中Outlook的插件注冊碼: HKCU { NoRemove Software { NoRemove Microsoft { NoRemove Office { NoRemove Outlook { NoRemove Addins { ForceRemove OutlookDemo.Plugin.1 { val FriendlyName = s 'Outlook Plugin' val Description = s 'An Outlook plugin' val LoadBehavior = d 3 val CommandLineSafe = d 0 } } } } } } } 這套注冊項是為特定使用者注冊插件的,為了把插件設定為整個系統範圍之内可用,隻需把HKCU改為HKLM。 LoadBehavior的值控制了主程式運作後插件的行為。為了讓主程式開始運作後插件自動運作,把LoadBehavior的值設定為3。如果想讓使用者手工載入插件,就把LoadBehavior設定為8。 如果你編譯了這個項目,你就有了一個Outlook 插件;這個插件實際上沒有做任何事,但是它的确是一個可以工作的插件。 我們現在向這個插件添加一些功能。首先,添加一個新的成員變量: _ApplicationPtr m_pApp; 然後設定OnConnection方法: STDMETHOD(OnConnection)(LPDISPATCH Application, ext_ConnectMode ConnectMode, LPDISPATCH AddInInst, SAFEARRAY * * custom) { HRESULT rslt = S_OK; try{ m_pApp = Application; OutLookSynch::DispEventAdvise(m_pApp); }catch(_com_error &e){ OutputDebugString(e.ErrorMessage()); rslt = E_UNEXPECTED; } return rslt; } 再設定與之對應的OnDisconnection方法,如下所示: STDMETHOD(OnDisconnection)(ext_DisconnectMode RemoveMode,SAFEARRAY * * custom) { HRESULT rslt = S_OK; try{ OutLookSynch::DispEventUnadvise(m_pApp); }catch(_com_error &e){ OutputDebugString(e.ErrorMessage()); rslt = E_UNEXPECTED; } return rslt; } 現在我們可以收到好幾種事件,例如,OnNewMail事件。得到事件的資訊以及它們的ID的最好方法就是打開MSVC工具菜單上的OLE/COM觀察器(viewer)。
BEGIN_SINK_MAP(CPlugin) SINK_ENTRY_EX(APPID, Outlook::DIID_ApplicationEvents, / 0x0000f003, OnNewMail) END_SINK_MAP() 現在我們隻需要完成OnNewMail事件處理函數了。 void _stdcall OnNewMail(){ MessageBox(NULL, "New Mail", NULL, MB_OK); } 如果你想消除這些讨厭的彈出式對話框(由該項目所建立),那麼最簡單方法就是遵循下面的步驟:
|