文章編號: 183599 - 上次校閱: 2007年2月12日 - 版次: 4.4

如何攔截 Word 使用 Visual C++ 應用程式事件

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。
全部展開 | 全部摺疊

結論

本文將告訴您,如何攔截使用 Microsoft Visual C++ 的 Microsoft Word 97 中的應用程式事件。不過,概念和本文的程式碼不是 Microsoft Word 的特定 ; 它們是適用於 Microsoft Office 應用程式,以及其他任何公開 (Expose) 事件的應用程式為整個組件。

其他相關資訊

下列步驟說明如何建立一個 MFC 應用程式會攔截 Microsoft Word 97 應用程式事件 Startup()、 DocumentChange() 和 Quit():
  1. 建立一個新對話方塊方塊架構應用程式使用 MFC AppWizard。命名您的專案 WordEvents,並接受預設設定。
  2. 將兩個按鈕加入至您的對話方塊並命名按鈕 」 啟動安裝及程式 」 和 「 結束 」 清潔向上,分別。
  3. 將下列程式碼加入至 「 開始安裝及程式 」 按鈕的處理常式:
          // Check to see if you've already started the server.
          if(m_app.m_lpDispatch != NULL) {
             AfxMessageBox("Server already started.");
             return;
          }
    
          char buf[256]; // General purpose buffer.
    
          // Start Automation server.
          COleException e;
          if(!m_app.CreateDispatch("Word.Application.8", &e)) {
             sprintf(buf, "Error on CreateDispatch(): %ld (%08lx)",
               e.m_sc, e.m_sc);
             AfxMessageBox(buf, MB_SETFOREGROUND);
             return;
    
          }
    
          // Make server visible through automation.
          // I.e.: Application.Visible = TRUE
          DISPID dispID;
          unsigned short *ucPtr;
          BYTE *parmStr;
          ucPtr = L"visible";
          m_app.m_lpDispatch->GetIDsOfNames(
               IID_NULL, &ucPtr, 1, LOCALE_USER_DEFAULT, &dispID
          );
          parmStr = (BYTE *)( VTS_VARIANT );
          m_app.InvokeHelper(
             dispID, DISPATCH_METHOD | DISPATCH_PROPERTYPUT, VT_EMPTY,
             NULL, parmStr, &COleVariant((short)TRUE)
          );
    
          // Declare the events you want to catch.
    
          // {000209F7-0000-0000-C000-000000000046}
          static const GUID IID_IWord8AppEvents =
          {0x000209f7,0x000,0x0000,{0xc0,0x00,0x0,0x00,0x00,0x00,0x00,0x46 } };
    
          //  Steps for setting up events.
          // 1. Get server's IConnectionPointContainer interface.
          // 2. Call IConnectionPointContainerFindConnectionPoint()
          //    to find the event you want to catch.
          // 3. Call IConnectionPoint::Advise() with the IUnknown
          //    interface of your implementation of the events.
    
          HRESULT hr;
    
          // Get server's IConnectionPointContainer interface.
          IConnectionPointContainer *pConnPtContainer;
          hr = m_app.m_lpDispatch->QueryInterface(
             IID_IConnectionPointContainer,
             (void **)&pConnPtContainer
          );
          ASSERT(!FAILED(hr));
    
          // Find connection point for events you're interested in.
          hr = pConnPtContainer->FindConnectionPoint(
             IID_IWord8AppEvents,
             &m_pConnectionPoint
          );
          ASSERT(!FAILED(hr));
    
          // Get the IUnknown interface of your event implementation.
          LPUNKNOWN pUnk = m_myEventSink.GetInterface(&IID_IUnknown);
          ASSERT(pUnk);
    
          // Setup advisory connection!
          hr = m_pConnectionPoint->Advise(pUnk, &m_adviseCookie);
          ASSERT(!FAILED(hr));
    
          // Release IConnectionPointContainer interface.
          pConnPtContainer->Release();
    					
  4. 將下列程式碼加入至"結束並正常上 」 按鈕的處理常式:
          // Check if you've started the server.
          if(m_app.m_lpDispatch == NULL) {
             AfxMessageBox("You haven't started the server yet.");
             return;
          }
          m_pConnectionPoint->Unadvise(m_adviseCookie);
    
          // Tell server to quit.
          // Application.Quit()
          DISPID dispID;                   // Temporary DISPID
          unsigned short *ucPtr;           // Temporary name holder
          ucPtr = L"quit";
          m_app.m_lpDispatch->GetIDsOfNames(
    
               IID_NULL, &ucPtr, 1, LOCALE_USER_DEFAULT, &dispID
          );
    
          m_app.InvokeHelper(dispID, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
    
          // Release application object.
          m_app.ReleaseDispatch();
    					
  5. 啟動 MFC ClassWizard (CTRL + W),並加入新的類別衍生從 CCmdTarget 並具有自動化支援 (請檢查 「 自動化 」 選項)。命名這個類別 MyEventSink ; 它就是我們的 Microsoft Word 應用程式事件的實作。
  6. 在 MFC ClassWizard,按一下 [自動化] 索引標籤,然後在順序中新增這些三種方法:
          void Startup()
          void Quit()
          void DocumentChange()
    					
  7. MyEventSink.cpp,在實作這些新方法來顯示訊息方塊,當它們呼叫,讓您知道它們觸發時:
          void MyEventSink::Startup()
          {
             AfxMessageBox("MyEventSink::Startup() called.");
          }
    
    
          void MyEventSink::Quit()
          {
             AfxMessageBox("MyEventSink::Quit() called.");
          }
    
          void MyEventSink::DocumentChange()
          {
             AfxMessageBox("MyEventSink::DocumentChange() called.");
          }
    					
  8. 開啟 MyEventSink.cpp 檔案,並尋找 IID_IMyEventSink 的宣告。[ClassWizard 產生新的隨機 GUID 為您的介面,但是因為您正在實作特定介面已經具有 GUID,您必須變更以符合您自己。修改 IID_IMyEventSink 的宣告如下: 靜態 const GUID IID_IMyEventSink = {0x000209f7、 0x000、 0x0000,{0xc0、 0x00,0x0、 0x00,0x00、 0x00,0x00,0x46}};
  9. 將下列的公用成員變數加入至您的 WordEventsDlg 類別中 WordEventsDlg.h:
          COleDispatchDriver m_app;
          IConnectionPoint *m_pConnectionPoint;
          DWORD m_adviseCookie;
          MyEventSink m_myEventSink;
    					
  10. 下面這一行 WordEventsDlg.h 右前會加入類別 CWordEventsDlg 宣告:
          #include "MyEventSink.h"
    					
  11. 開啟檔案 MyEventSink.h 並尋找解構函式的宣告] ; 它將會出現,如下所示:
          // Implementation
          protected:
          virtual ~MyEventSink();
    					
  12. 移動該宣告 Protected"這個字上面,讓幾行程式碼顯示如下:
          virtual ~MyEventSink();
          // Implementation
          protected:
          // virtual ~MyEventSink(); // Or this line may be removed.
    					
  13. 最後,請確定 OLE/COM 程式庫機會來初始化。加入下列程式碼右邊的 [開始安裝及程式] 按鈕處理常式之前。這會建立全域的類別取得建立在應用程式啟動和結束時被終結。建構函式和解構函式的這個類別提供便利的方式來執行初始化和清除:
          // Ole-initialization class.
          class OleInitClass {
          public:
             OleInitClass() {
                OleInitialize(NULL);
             }
             ~OleInitClass() {
                OleUninitialize();
             }
          };
          // This global class calls OleInitialize() at
          // application startup, and calls OleUninitialize()
          // at application exit.
          OleInitClass g_OleInitClass;
    					
  14. 編譯並執行。
執行 [應用程式後按一下 [「 開始時間] 及 [安裝程式 」] 按鈕,以啟動 Microsoft Word 並設定事件通知]。 在 Microsoft Word 中在 [檔案] 功能表上按一下 [新增],以建立新的文件]。DocumentChange() 事件應該取得引發。開啟另一份文件,並請注意它也取得發生於您切換到另一份文件從啟動。您可以按 「 結束並清洗向上 」] 按鈕,以停止事件通知,結束 Microsoft Word 或您可以從 Microsoft Word 結束 (按一下 [檔案] 功能表的 [結束]),並注意 Quit 通知。

您可能會注意到永遠不會觸發啟動事件。這是因為它引發之前您設定事件。請注意沒有真正處理這個事件沒有理由因為應用程式必須已經開始,然後再呼叫並設定自動化方法和屬性。

Microsoft Excel 支援許多的有趣且有用事件,而且您可以遵循此處的步驟來捕捉它們。不過,是要記住的幾個事項:
  • 使用 OLE/COM 物件檢視器隨附 Microsoft Visual C++ 5.0 來檢視的伺服器您感興趣的型別程式庫。若要尋找之事件開啟 coclass 宣告 (通常是在樹狀目錄的底部) ; 會列出每一個 Coclass 關聯的事件。當您按一下) 您可以看到哪些事件是可用的事件介面、 其 DISPID 和它們在右側檢視中的宣告方式。
  • 您不需要修改 DISPID 對於我們我們 MyEventSink 類別中的方法,因為 Microsoft Word 應用程式事件、 Startup()、 Quit(),DocumentChange() 有 DISPID 1、 2 和 3,分別。 如果您建立這些方法的順序,您沒有修改它們符合型別程式庫,因為 ClassWizard 從 DISPID 1 開始。不過,像 Microsoft Excel 活頁簿事件的大部分事件無法啟動與 DISPID 1。在這種情況下,您必須明確地修改分派對應中 MyEventSink.cpp 符合之 DISPID 的正確方法。

?考

如需詳細資訊,有關建立接收器介面,],然後簡化連線程序,按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中上的 []:
181845? (http://support.microsoft.com/kb/181845/ ) HOWTO: 建立在以 MFC 為基礎的 COM 用戶端接收器介面
一般範例的以及更多的資訊,有關,連接點請參閱下列文章 「 Microsoft 知識庫 」 中所述的 Connpts.exe 範例:
152087? (http://support.microsoft.com/kb/152087/ ) Connpts.exe 在 MFC 應用程式中實作連接點

這篇文章中的資訊適用於:
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
  • Microsoft Word 2002 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Word 97 Standard Edition
關鍵字:?
kbmt kbprogramming kbautomation kbcode kbfaq kbhowto kbinterop KB183599 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:183599? (http://support.microsoft.com/kb/183599/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。