如何在VC程式碼中監聽ArcEngine的COM事件

jianzhanger發表於2011-05-17

ArcEngine 中,許多元件採用事件方式傳送資訊。比如, MapControl 中有滑鼠按下事件、滑鼠移動等事件, IworkspaceEdit 也有開始編輯、結束編輯等事件。

 

有時候,我們需要知道這些事件的發生,以便在發生時候處理必要資訊。

 

那麼,如何監聽元件的事件呢?下面以監聽編輯事件作為例子說明監聽的處理方式。

 

開啟幫助,我們會看見如下程式碼:

struct __declspec (uuid ("0b437962-89f9-11d4-8b5f-000000000000" ))

IWorkspaceEditEvents : IUnknown

{

    //

    // Raw methods provided by interface

    //

 

    virtual HRESULT __stdcall OnStartEditing (

        VARIANT_BOOL withUndoRedo ) = 0;

    virtual HRESULT __stdcall OnStopEditing (

        VARIANT_BOOL saveEdits ) = 0;

    virtual HRESULT __stdcall OnStartEditOperation ( ) = 0;

    virtual HRESULT __stdcall OnAbortEditOperation ( ) = 0;

    virtual HRESULT __stdcall OnStopEditOperation ( ) = 0;

    virtual HRESULT __stdcall OnUndoEditOperation ( ) = 0;

    virtual HRESULT __stdcall OnRedoEditOperation ( ) = 0;

};

 

從上述程式碼看到編輯事件的函式定義。我們需要建立一個類,過載上述函式。

class CAEEditEvents :

    public CComObjectRoot,

    public IWorkspaceEditEvents

{

public :

    CAEEditEvents(void );

    ~CAEEditEvents(void );

 

    BEGIN_COM_MAP(CAEEditEvents)

       COM_INTERFACE_ENTRY(IWorkspaceEditEvents)

    END_COM_MAP()

 

    STDMETHOD(OnStartEditing)(VARIANT_BOOL withUndoRedo)

    {

       ::MessageBox(NULL, _T(" 開始編輯了呢?" ), _T(" 注意了!!!" ), MB_OK);

       return E_NOTIMPL;

    }

    STDMETHOD(OnStopEditing)(VARIANT_BOOL saveEdits)

    {

       return E_NOTIMPL;

    }

    STDMETHOD(OnStartEditOperation)()

    {

       return E_NOTIMPL;

    }

    STDMETHOD(OnAbortEditOperation)()

    {

       return E_NOTIMPL;

    }

    STDMETHOD(OnStopEditOperation)()

    {

       return E_NOTIMPL;

    }

    STDMETHOD(OnUndoEditOperation)()

    {

       return E_NOTIMPL;

    }

    STDMETHOD(OnRedoEditOperation)()

    {

       return E_NOTIMPL;

    }

};

 

STDMETHOD 的定義弄不明白?唉,其實就是一個巨集定義,簡化虛擬函式的定義而已的。

STDMETHOD(OnRedoEditOperation)() 其實就是:

virtual HRESULT __stdcall OnRedoEditOperation ( )

簡單得很啊!!要是還有很多不明白,那麼趕緊看看關於COM 方面的知識吧。

 

看見了吧?我們把 IworkspaceEditEvents 的介面 函式都實現一次。注意,我們在類定義時候增加了一個 public CcomObjectRoot ,為什麼呢?這裡不再解釋,權當必須的吧。想知道原因,自己參考COM 方面的知識。

 

這樣,我們把監聽的類都準備好了。類只做一個事情,就是當開始編輯這個事件發生時候,發出一個詢問,該詢問也沒有做任何事情,僅僅詢問而已。

 

下面,就正式開始了。先定義變數:

CAEEditEvents *g_pEvents;

    DWORD m_dwCookie;

這個變數定義在什麼地方? 看你喜歡定義在什麼地方啦。

 

定義完畢,就應該讓Iworkspace 知道,你想做什麼的時候,要告訴我呀!怎麼告訴呢?看下面:

g_pEvents = new CComObject<CAEEditEvents>;

    CComPtr<IUnknown> ptrEventUnk = g_pEvents;

    AtlAdvise(ipWorkspace, ptrEventUnk, IID_IWorkspaceEditEvents, &m_dwCookie);

 

好了,到這裡就結束了。等會 Iworkspace 有什麼動作的時候,自然會告訴CAEEditEvents 的。

 

 

最後,在不需要的時候,不要忘記下面的程式碼啊:

AtlUnadvise(ipWorkspace, IID_IWorkspaceEditEvents, m_dwCookie);

這個程式碼幹什麼的,自己琢磨好了。

 

 

------------------------------------------------------------------

注意:

(1) 自定義的類必須過載介面的全部虛擬函式,如GetTypeInfoCount,GetTypeInfo等

(2) CComModule _Module; 必須要寫在全域性位置

(3) IID 可以由__uuidof(IMapControlEvents2)得到


相關文章