AtlEvnt.exe 範例會示範如何使用 ATL IDispEventImpl 和 IDispEventSimpleImpl 類別建立 ATL 接收

文章編號: 194179 - 檢視此文章適用的產品。
Microsoft Visual C++.NET (2002) 和 Microsoft Visual C++.NET 2003) 支援 Managed 程式碼模型所提供的.NET Framework 和不受管理的原生 Windows 程式碼模型。這份文件中的資訊適用於 Unmanaged Visual C++ 程式碼只。
全部展開 | 全部摺疊

在此頁中

結論

AtlEvnt.exe 示範如何實作事件接收使用 ATL IDispEventImpl 和 IDispEventSimpleImpl 類別。複合控制項或 ATL 對話方塊,精靈在繼承清單來設定接收器插入 IDispEventImpl。因此這個範例的重點在於,建立其他類型的 COM 物件和用戶端接收。這是只適用於來源介面的型別分配介面。

當您有存取權型別程式庫時,請使用 IDispEventImpl。當您不能存取型別程式庫,或您想藉由不載入型別程式庫是比較有效率的方法時,請使用 IDispEventSimpleImpl。

除了範例的連結,本文 < 更多資訊資訊 > 一節會包含專案和如何實作每個類別的資訊的概觀。

其他相關資訊

從 「 Microsoft 下載中心 」 下載下列檔案有:

Visual C++ 6.0

摺疊此圖像展開此圖像
Download
Download Atlevnt.exe now
如需有關如何下載 Microsoft 支援檔案的詳細資訊,按一下 [下列面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
119591如何從線上服務取得 Microsoft 的支援檔案
Microsoft 已掃描這個檔案有無病毒。Microsoft 使用已張貼檔案的日期中的 [可用的最新病毒偵測軟體。檔案儲存在安全性強化的伺服器上,協助防止未經授權的任何變更的檔案。

Visual C++.NET

摺疊此圖像展開此圖像
Download
Download Atlevntvcnet.exe now
發行日期: 2002 年 6 月 25日,

如需有關如何下載 Microsoft 支援檔案的詳細資訊,按一下 [下列面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
119591如何從線上服務取得 Microsoft 的支援檔案
Microsoft 已掃描這個檔案有無病毒。Microsoft 使用已張貼檔案的日期中的 [可用的最新病毒偵測軟體。檔案儲存在安全性強化的伺服器上,協助防止未經授權的任何變更的檔案。 ATLEVNT 工作區是由兩個專案 AtlEvnt 和 EventSrc 所組成。當您執行 AtlEvnt.exe 時,請使用-d 選項:
AtlEvnt.exe-d

專案概觀

AtlEvnt 工作區是由兩個專案 AtlEvnt 和 EventSrc 所組成。

EventSrc 專案是預設值有一個 「 簡單物件"的 ATL DLL 專案。簡單的物件沒有方法,而且已被修改,以支援連接點和 IPersist 介面。COM 物件公開一個預設來源介面 (如下) 具有單一方法呼叫標籤刻度分隔。[COM 物件所有連接到它計時器為基礎的接收器物件上呼叫這個方法:
   dispinterface _EventSink
   {

      properties:
      methods:
      [id(1), helpstring("method Tick")] HRESULT Tick([in] long tckcnt);

   }

				
[AltEvnt 專案是 ATL EXE 專案。一個 ATL CDialogImpl 類別已加入至專案變成簡單的對話方塊應用程式。四個面盆已加入至專案 (兩個使用 IDispEventImpl 和兩個使用 IDispEventSimpleImpl)。每一個接收說明以不同的方式提供接收器物件在處理由 EventSrc COM 物件引發的 Tick 事件。

這個對話方塊有四個按鈕,並按下按鈕讓連線對應接收到 EventSrc COM 物件。清單方塊會顯示表單的字串"Sinkn: Tick 事件接收到-x 」 每次呼叫中,接收的事件處理常式 Tick。一旦建立連接該按鈕會停用。如果沒有任何問題建立連線按鈕文字將取代表單 」 連線 Err-hr"其中 hr"代表失敗 HRESULT 的字串。使用 [Visual C++,以取得錯誤的說明的 6.0 版的 [船的 「 錯誤查詢 」 工具]。

若要執行此範例,先建置 EventSrc 專案,並確保 EventSrc 物件成功註冊。然後建置 AtlEvnt 專案並執行它。顯示包含 (分開 [確定] 和 [取消]) 的四個按鈕的對話方塊和清單方塊。 四個按鈕代表四個接收器。按一下按鈕將接收器連接到來源。一旦連線建立字串會加入至清單方塊每次呼叫處理常式。

若要實作 IDispEventImpl 步驟

  1. 建立新的類別衍生自 IDispEventImpl。在 [插入] 功能表來產生新的類別,您可以按一下 新的類別。針對每個不同的接收器將 IDispEventImpl 類別加入至繼承清單具有唯一的識別碼,做為第一個參數。接收器類別可以是 (如同在複合控制項) 的 COM 物件或只是從 IdispEventImpl 衍生的類別:
    // Just a sink.
          class CSinkObj : public IDispEventImpl<IDC_OBJ, CSinkObj>
          {
             ...
          }
    -或-
    // COM object that also implements a sink (as in a composite
          // control).
          class ATL_NO_VTABLE CSinkObj :
             public CComObjectRootEx<CComSingleThreadModel>,
             public CComCoClass<CSinkObj, &CLSID_SinkObj>,
             public IDispatchImpl<ISinkObj, &IID_ISinkObj, &LIBID_SINKPROJLib>,
             public IDispEventImpl<IDC_SRCOBJ, CSinkObj>
          {
             ...
          }
  2. 您可以指定來源介面識別碼、 型別程式庫 ID、 做為參數 IdispEventImpl,明確地包含來源介面的型別程式庫的主要和次要版本號碼,或使用 [AtlGetObjectSourceInterface() 從型別程式庫擷取這項資訊。使用 AtlGetObjectSourceInterface() 需要引發事件的 COM 物件實作 IProvideClassInfo2 或 IPersist * 可能是:
    class CSinkObj : public IDispEventImpl<IDC_OBJ, CSinkObj>
          {
             ...
          }
    -或-
    class CSinkObj : public IDispEventImpl<IDC_OBJ, CSinkObj,
             &DIID__EventSink, // Source interface GUID.
             &LIBID_COMOBJLib, // typelib ID containing source interface.
             1,                // Major version # of LIBID_COMOBJLib.
             0>                // Minor version # of LIBID_COMOBJLib.
          {
             ...
          }
  3. 接收對應加入上述類別對應至您想要處理的來源介面的每個事件的接收器項目中。使用 SINK_ENTRY_EX(),否則來源介面指定當做 IDispEventImpl,在參數時,請將 SINK_ENTRY():
    class CSinkObj : public IDispEventImpl<IDC_SRCOBJ, CSinkObj>
          {
          public:
             BEGIN_SINK_MAP(CSinkObj)
                SINK_ENTRY(IDC_SRCOBJ, 1 /*DISPID*/, OnTick /*Event Handler*/)
             END_SINK_MAP()
             ...
          }
    -或-
    class CSinkObj : public IDispEventImpl<IDC_OBJ, CSinkObj,
                                  &DIID__EventSink, &LIBID_COMOBJLib, 1, 0>
          {
          public:
             BEGIN_SINK_MAP(CSinkObj)
                SINK_ENTRY_EX(IDC_SRCOBJ, DIID__EventSink, 1, OnTick)
             END_SINK_MAP()
             ...
          }
  4. 將事件處理常式方法加入至您的類別。請確定它們有呼叫慣例 __stdcall:
    class CSinkObj : public IDispEventImpl<IDC_SRCOBJ, CSinkObj3>
          {
          public:
             BEGIN_SINK_MAP(CSinkObj)
                SINK_ENTRY(IDC_SRCOBJ, 1 , OnTick)
             END_SINK_MAP()
    
    
             // event handler for event defined in idl as
             // [id(1)] HRESULT Tick([in] long tckcnt);
             HRESULT __stdcall OnTick(long tickcnt)
             {
                ATLTRACE("CSinkObj::OnTick\n");
                return S_OK;
             }
             ...
          }
  5. 連接 COM 物件來呼叫 DispEventAdvise() 接收器。如果來源介面指定為 IDispEventImpl 的參數,然後呼叫:
    // pUnk is the IUnknown pointer of the COM object that fires events.
       // pSinkObj is an instance of the CSinkObj class.
          pSinkObj->DispEventAdvise(pUnk);
    或其他呼叫:
    // Make sure the COM object corresponding to pUnk implements
          // IProvideClassInfo2 or IPersist*.
          // Call this method to extract info about source type library if you
          // specified only two parameters to IdispEventImpl.
          AtlGetObjectSourceInterface(pUnk, &pSinkObj->m_libid,
             &pSinkObj->m_iid, &pSinkObj->m_wMajorVerNum,
             &pSinkObj->m_wMinorVerNum);
    
          hr = pSinkObj->DispEventAdvise(pUnk, &pSinkObj->m_iid);
  6. 藉由呼叫 DispEventUnadvise() 中斷接收器:
    pSinkObj->DispEventUnadvise(pUnk);

若要實作 IDispEventSimpleImpl 步驟

  1. 建立衍生自 IDispEventSimpleImpl 類別。來源介面都被指定。
  2. 依照步驟 3 上述除了新增 SINK_ENTRY_INFO() 為所要處理的來源介面的每個方法。由於 IDispEventSimpleImpl 並無法存取型別程式庫,您必須提供透過 _ATL_FUNC_INFO 結構的每個事件處理常式、 一個為每個事件處理常式的相關資訊。

    您可以使用 [SINK_ENTRY_EX() 代替 SINK_ENTRY_INFO() 中指定 _ATL_FUNC_INFO 結構,巨集和覆寫虛擬函式來填入 _ATL_FUNC_INFO GetFuncInfoFromId() 的結構,如下列程式碼所示。
  3. 請遵循上述的步驟 4 到 6:
    static _ATL_FUNC_INFO OnTickInfo = {
             CC_STDCALL,   // Calling convention.
             VT_I4,        // Return type.
             1,            // Number of arguments.
             {VT_I4}       // Argument types.
          };
    
          class CSinkObj :
             public IDispEventSimpleImpl<IDC_SRCOBJ, CSinkObj,
                    &DIID__EventSink>
          {
          public:
          BEGIN_SINK_MAP(CSinkObj)
             SINK_ENTRY_INFO(IDC_SRCOBJ, DIID__EventSink, 1, OnTick,
                             &OnTickInfo)
          END_SINK_MAP()
    
             HRESULT __stdcall OnTick(long tickcnt)
             {
                ATLTRACE("CSinkObj::OnTick\n");
                return S_OK;
             }
             ...
    
          }
    -或-
    class CSinkObj :
             public IDispEventSimpleImpl<IDC_SRCOBJ, CSinkObj,
                    &DIID__EventSink>
          {
          public:
          BEGIN_SINK_MAP(CSinkObj4)
             SINK_ENTRY_EX(IDC_SRCOBJ, DIID__EventSink, 1, OnTick)
             // Equivalent to:
             // SINK_ENTRY_INFO(IDC_SRCOBJ, DIID__EventSink, 1, OnTick, NULL)
          END_SINK_MAP()
    
             HRESULT GetFuncInfoFromId(const IID& iid, DISPID dispidMember,
                LCID lcid, _ATL_FUNC_INFO& info)
             {
                if (InlineIsEqualGUID(iid, DIID__EventSink))
                {
                   info.cc = CC_STDCALL;
                   switch(dispidMember)
                   {
                      case 1:
                         info.vtReturn = VT_I4;
                         info.nParams = 1;
                         info.pVarTypes[0] =  VT_I4;
                         return S_OK;
    
                      default:
                         return E_FAIL;
                   }
                }
                return E_FAIL;
             }
    
             HRESULT __stdcall OnTick(long tickcnt)
             {
                ATLTRACE("CSinkObj::OnTick\n");
                return S_OK;
             }
             ...
          }

?考

如需詳細資訊,請按一下下列的文件編號,檢視 「 Microsoft 知識庫 」 中的文件:
181277AtlSink 使用 ATL 來建立分配介面接收器

屬性

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

提供意見