AciveX接口事件的手动实现
为了理解ActiveX事件的运作原理,特意做了如下实验
初试化过程:
try { CLSID clsid; HRESULT hr=::CLSIDFromProgID(L"MSWinsock.Winsock",&clsid); if(FAILED(hr)) throw "获得对象的CLSID失败"; hr=::CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMSWinsockControl),(void**)&pMSWinsockControl); if(FAILED(hr)) throw "创建对象失败..."; hr=pMSWinsockControl->put_Protocol(sckUDPProtocol); if(FAILED(hr)) throw "设置协议类型失败..."; IConnectionPoint *cp=NULL; SinkDMSWinsockControlEvents * TheEventSink=NULL; IConnectionPointContainer *cps=NULL; hr=pMSWinsockControl->QueryInterface(IID_IConnectionPointContainer,(void**)&cps); if(FAILED(hr)) throw "查询事件容器失败..."; hr=cps->FindConnectionPoint(__uuidof(DMSWinsockControlEvents),&cp); if(FAILED(hr)) throw "查找连接点失败..."; cps->Release(); hr=cp->Advise(&TheEventSink,&ConnectPointCookie); if(FAILED(hr)) throw "连接连接点失败..."; cp->Release(); } catch(char* msg) { MessageBox(CString(msg)); return S_FALSE; } return S_OK; }
事件的实现类:
class SinkDMSWinsockControlEvents : public IDispatch { 。。。。。。 //DISPID是一个长整数,它标识的是一个函数。对于IDispatch的某一个特定的实现,DISPID都是唯一的。IDispatch的每一个实现都有其自己的IID,这里dispidMemeber实际上是可以认为是和IE实例所发生的每一个事件相关的方法,比如:DISPID_BEFORENAVIGATE2,DISPID_NAVIGATECOMPLETE2 STDMETHODIMP Invoke( DISPID dispID, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr) { int i; switch(dispID) { case 0: OnDataArrive(pdispparams->rgvarg->intVal); break; default: break; } return S_OK; } void SinkDMSWinsockControlEvents::OnDataArrive(long bytesTotal) { VARIANT vtData; vtData.vt=VT_BSTR; vtData.bstrVal=CString("").AllocSysString(); pMSWinsockControl->GetData(&vtData); CString str(vtData.bstrVal); pCommunucationCtrl->m_CurrentCommand=vtData.bstrVal; pCommunucationCtrl->Fire_OnCommandComming(vtData.bstrVal); } }
看起来复杂的东西就是这样
浮沙之上勿筑高台