所谓连接点,是com服务器和客户端交互的入口,说得简单点,就是一个回调过程,
客户端将一个实现了dispinterface 的com注册到服务器的相应的接口上面就可以实现服务器端对客户端的回调,许多activeX就是这样子的。
com对这个东西有着一大堆的约定(com就是这么个东西,大家应该早就知道了吧)
比如一定要实现IConnectionPointContainer,一定要实现ConnectionPoint等等。
这些过程很长啰唆,不过就是实现一个dispiinterface ,加个连接点的映射,
使用vs ,点几下鼠标就可以了。
这个不详细说。
关键是激发事件,它的实现比较巧妙,
在注册的时候就是保存了客户端的IUnknown接口,然后通过这个接口的IDispatch的invoke来调用客户端的函数,这个就是为什么dispinterface哪里一定有个id,这个id是给客户端用的,给服务器端来调。
废话说了一堆,我都烦了
class ATL_NO_VTABLE CFlashSink :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFlashSink, &CLSID_FlashSink>,
public IDispatchImpl<IFlashSink, &IID_IFlashSink, &LIBID_TestFlashSinkLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispEventImpl<FLASH_SOURCE_ID,CFlashSink,&_ATL_IIDOF(ShockwaveFlashObjects::_IShockwaveFlashEvents),&LIBID_TestFlashSinkLib,1,0>
{
public:
CFlashSink()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_FLASHSINK)
BEGIN_COM_MAP(CFlashSink)
COM_INTERFACE_ENTRY(IFlashSink)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
BEGIN_SINK_MAP(CFlashSink)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_OnReadyStateChange,OnReadyStateChange)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_OnProgress,OnProgress)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_FSCommand,FSCommand)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_FlashCall,FlashCall)
END_SINK_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
STDMETHOD(OnReadyStateChange) (long newState)
{
printf("OnReadyStateChange/n");
return S_OK;
}
STDMETHOD(OnProgress) (long percentDone)
{
printf("OnProgress/n");
return S_OK;
}
STDMETHOD(FSCommand) (BSTR command, BSTR args)
{
printf("FSCommand/n");
return S_OK;
}
STDMETHOD(FlashCall) ( BSTR request)
{
printf("FlashCall/n");
return S_OK;
}
STDMETHOD(Invoke)(DISPID id, REFIID refid, LCID lid, WORD ww,
DISPPARAMS* parms,VARIANT* vari, EXCEPINFO* exce, UINT* ii)
{
switch (id)
{
case 0xfffffd9f:
printf("Invoke-OnReadyStateChange--%d/n",parms->rgvarg->intVal);
break;
case 0x000007a6:
printf("Invoke-OnProgress/n");
break;
case 0x00000096:
printf("Invoke-FSCommand/n");
break;
case 0x000000c5:
printf("Invoke-FlashCall/n");
break;
default:;
}
return S_OK;
}
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
};
OBJECT_ENTRY_AUTO(__uuidof(FlashSink), CFlashSink)
这个是实现
其实简单的很
IDispEventImpl<FLASH_SOURCE_ID,CFlashSink,&_ATL_IIDOF(ShockwaveFlashObjects::_IShockwaveFlashEvents),&LIBID_TestFlashSinkLib,1,0>
写明你要sink的接口,FLASH_SOURCE_ID是自己定的,它主要是用来标记不同源的相应事件的,
这个可以帮你实现同一个sink注册不同的源
BEGIN_SINK_MAP(CFlashSink)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_OnReadyStateChange,OnReadyStateChange)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_OnProgress,OnProgress)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_FSCommand,FSCommand)
SINK_ENTRY_EX(FLASH_SOURCE_ID,__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents),DISPID_FlashCall,FlashCall)
END_SINK_MAP()
写清楚接口的映射关系,然后实现就ok,
接着就不用我说了吧,不管你是用CCOmObject来create或是CComCreator来做,随便你,
反正建个对象 advise一下就ok了,不过要记得unadive,不然后果自负。
成功后,你的invoke会有不少的回调,基本是第一个函数的id