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);
}
}


看起来复杂的东西就是这样

posted @ 2015-10-25 16:26  赛提斯特  阅读(437)  评论(0编辑  收藏  举报