COM Sink-Event 实现

来源:互联网 发布:telnet文件linux 编辑:程序博客网 时间:2024/06/01 09:59



1、idl定义outgoing 接口(_ICtrlNetworkEvent)。

// 此文件将由 MIDL 工具处理以
// 产生类型库(Ctrl.tlb)和封送处理代码。

import "oaidl.idl";
import "ocidl.idl";

[
uuid(FFD6C786-5D9B-4206-9F63-ACD3BEFF6481),
version(1.0),
helpstring("MediaCtrl 1.0 类型库")
]
library CtrlLib
{
importlib("stdole2.tlb");

[
uuid(FFD6C786-5D9B-4206-9F63-ACD3BEFF648B),
helpstring("_ICtrlNetworkEvent")
]
dispinterface _ICtrlNetworkEvent
{
properties:
methods:
[id(1), helpstring("method OnNetStateChanged")] HRESULT OnNetworkStateChanged([in] BOOL bOnLine);
};


[
uuid(FFD6C786-5D9B-4206-9F63-ACD3BEFF6488),
helpstring("Ctrl Class")
]
coclass Ctrl
{
//[default] interface ICtrl;
//[default, source] dispinterface _ICtrlEvents;
[source] dispinterface _ICtrlNetworkEvent;
};
};
2、发布者(server)(com object)实现一个连接点类。增加连接点映射。

//_ICtrlNetworkEvent .h

#pragma once

template<class T>
class CProxy_ICtrlNetworkEvent : public IConnectionPointImpl<T, &__uuidof(_ICtrlNetworkEvent), CComDynamicUnkArray>
{
public:
HRESULT Fire_OnNetworkStateChanged(BOOL bOnline)
{
HRESULT hr = S_OK;
T * pThis = static_cast<T*> (this);

int s = m_vec.GetSize();
for (int i = 0; i < s; i++)
{
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(i);
pThis->Unlock();

IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

if (pConnection)
{
CComVariant avarParams[1];
avarParams[0] = bOnline;
avarParams[0].vt = VT_BOOL;
CComVariant varResult;

DISPPARAMS params = { avarParams, NULL, 1, 0 };
hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);//1 对应方法的dispid
}
}

return hr;
}
};


//发布者

#include "_CtrlNetworkEvent_CP.h"


class ATL_NO_VTABLE CCtrl :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CCtrl, &CLSID_Ctrl>,
public IConnectionPointContainerImpl<CCtrl>,
public CProxy_ICtrlNetworkEvent<CCtrl>,
public IDispatchImpl<ICtrl, &IID_ICtrl, &LIBID_CtrlLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
{
public:
    CCtrl();

DECLARE_REGISTRY_RESOURCEID(IDR_CTRL)

BEGIN_COM_MAP(CCtrl)
COM_INTERFACE_ENTRY(ICtrl)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CCtrl)
CONNECTION_POINT_ENTRY(__uuidof(_ICtrlNetworkEvent))
END_CONNECTION_POINT_MAP()

DECLARE_PROTECT_FINAL_CONSTRUCT()

//functions

};


3、订阅者(client)(com object)实现outgoing接口。增加sink映射。


//事件实现类,实现outgoing接口

//CtrlNetworkEvent.h

#pragma once

class CCtrlNetworkEvent :public IDispEventSimpleImpl<1, CCtrlNetworkEvent, &DIID__ICtrlNetworkEvent>
{
public:
CCtrlNetworkEvent(){};
virtual ~CCtrlNetworkEvent(){};


inline virtual void __stdcall OnNetworkStateChanged(BOOL bOnline){};


static _ATL_FUNC_INFO FuncInfo_OnNetworkStateChanged;


BEGIN_SINK_MAP(CCtrlNetworkEvent)
SINK_ENTRY_INFO(1, DIID__ICtrlNetworkEvent, 1, OnNetworkStateChanged,&FuncInfo_OnNetworkStateChanged)
END_SINK_MAP()
};


//CtrlNetworkEvent.c

#pragma once

#include "CtrlNetworkEvent.h"

_ATL_FUNC_INFO CCtrlNetworkEvent::FuncInfo_OnNetworkStateChanged= { CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};



//事件订阅者

//CtrlFrame.h

#include "CtrlNetworkEvent.h"

class CCtrlFrame :  public CCtrlNetworkEvent
{
public:
CCtrlFrame(void);
~CCtrlFrame(void);

//_ICtrlNetworkEvent
virtual void __stdcall OnNetworkStateChanged(BOOL bOnline);

//others

private:

CComPtr<ICtrl>m_spCtrl; 

};


4、通常在订阅者类中实现对发布者的事件连接。DispEventAdvise();/DispEvent


//CtrlFrame.cpp


//把事件实现编译进来,该头文件也可以加在工程中的任意cpp文件中。

#include "CtrlNetworkEvent.c"


void Init()

{

hr = CCtrlNetworkEvent::DispEventAdvise(m_spCtrl, &__uuidof(_ICtrlNetworkEvent));//m_spCtrl为Ctrl

}

void Finit()

{

CCtrlNetworkEvent::DispEventUnadvise(m_spCtrl, &__uuidof(_ICtrlNetworkEvent));

}







原创粉丝点击