COM触发事件的常用方式

一般分为两种:

1、直接调用

  1. HRESULT CFirePropNotifyEvent::FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
  2. {
  3.     CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  4.     if (!pCPC)
  5.         return S_OK;
  6.     CComPtr<IConnectionPoint> pCP;
  7.     pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  8.     if (!pCP)
  9.         return S_OK;
  10.     CComPtr<IEnumConnections> pEnum;
  11.     if (FAILED(pCP->EnumConnections(&pEnum)))
  12.         return S_OK;
  13.     CONNECTDATA cd;
  14.     while (pEnum->Next(1, &cd, NULL) == S_OK)
  15.     {
  16.         if (cd.pUnk)
  17.         {
  18.             HRESULT hr = S_OK;
  19.             CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  20.             if (pSink)
  21.                 hr = pSink->OnRequestEdit(dispID);
  22.             cd.pUnk->Release();
  23.             if (hr == S_FALSE)
  24.                 return S_FALSE;
  25.         }
  26.     }
  27.     return S_OK;
  28. }

获得连接容器接口,进而获得容器中接收器IID_IPropertyNotifySink类型的连接点,再遍历这个连接点中各个IID_IPropertyNotifySink接收器,进而调用相应某事件。

这里的关键是:在事件对象中继承IID_IPropertyNotifySink接收器接口,并实现OnRequestEdit等事件函数。

2、间接调用。

  1. template<typename host_t, const IID* pIID_ToHookEvent>
  2. class ComEventIntercepter : public IDispatch
  3. {
  4. typedef HRESULT (STDMETHODCALLTYPE host_t::*invok_t)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
  5.             DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr);
  6. public:
  7.     ComEventIntercepter(host_t* pHost = NULL, invok_t notifier = NULL) :
  8.         m_pHost(pHost), m_notifier(notifier), m_dwCookie(0)
  9.     {
  10.     }
  11.     HRESULT Intercept(IUnknown* pUnkCP)
  12.     {
  13.         if(pUnkCP == NULL)
  14.             return E_INVALIDARG;
  15.         CComPtr<IConnectionPointContainer> pCPC;
  16.         CComPtr<IConnectionPoint> pCP;
  17.         HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
  18.         if (SUCCEEDED(hRes))
  19.             hRes = pCPC->FindConnectionPoint(*pIID_ToHookEvent, &pCP);
  20.         if (SUCCEEDED(hRes))
  21.             hRes = pCP->Advise(this, &m_dwCookie);
  22.         return hRes;
  23.     }
  24. public:
  25.     STDMETHODIMP QueryInterface(REFIID iid, void ** ppvObject)
  26.     {
  27.         if(ppvObject == NULL) return E_INVALIDARG;
  28.         *ppvObject = NULL;
  29.         if(iid == IID_IUnknown)
  30.             *ppvObject = (IUnknown*)this;
  31.         else if(iid == *pIID_ToHookEvent || iid == IID_IDispatch)
  32.             *ppvObject = this;
  33.         if(*ppvObject == NULL) return E_NOINTERFACE;
  34.         return S_OK;
  35.     }
  36.     ULONG STDMETHODCALLTYPE AddRef()
  37.     {
  38.         return 0;
  39.     }
  40.     ULONG STDMETHODCALLTYPE Release()
  41.     {
  42.         return 0;
  43.     }
  44.     HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR* pctinfo)
  45.     { return E_NOTIMPL; }
  46.     HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID  lcid,
  47.         ITypeInfo FAR* FAR*  ppTInfo)
  48.     { return E_NOTIMPL; }
  49.     HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
  50.         OLECHAR FAR* FAR* rgszNames,
  51.         unsigned int cNames,
  52.         LCID lcid,
  53.         DISPID FAR* rgDispId)
  54.     { return E_NOTIMPL; }
  55.     HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
  56.         DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,
  57.         EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr)
  58.     {
  59.         if(m_pHost && m_notifier)
  60.         {
  61.             return (m_pHost->*m_notifier)(dispIdMember, riid, lcid, wFlags, pDispParams, parResult, pExcepInfo, puArgErr);
  62.         }
  63.         return E_NOTIMPL;
  64.     }
  65. protected:
  66.     host_t* m_pHost;
  67.     invok_t m_notifier;
  68.     DWORD   m_dwCookie;
  69. };
  1. HRESULT CWebBrowser::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
  2.                                      DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,
  3.                                      EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr)
  4. {
  5.     switch (dispIdMember)
  6.     {
  7.     case DISPID_DOCUMENTCOMPLETE:
  8.         //ATLTRACE("DISPID_DOCUMENTCOMPLETE/n");
  9.         break;
  10.     case DISPID_DOWNLOADBEGIN:
  11.         // Enable the stop menu item and toolbar button
  12.         //EnableMenuItem(m_hMenu, ID_VIEW_STOP, MF_BYCOMMAND|MF_ENABLED);
  13.         //m_wndToolBar.SendMessage(TB_ENABLEBUTTON, ID_VIEW_STOP, MAKELONG(TRUE, 0));
  14.         break;
  15.     case DISPID_NAVIGATECOMPLETE:
  16.         {
  17.             // Set the text of the combobox to the current URL
  18.             //CComBSTR bstrURL;
  19.             //m_spWebBrowser->get_LocationURL(&bstrURL);
  20.             //m_wndUrlCombo.SetWindowText(OLE2T(bstrURL));
  21.         }
  22.         break;
  23.     case DISPID_NAVIGATECOMPLETE2:
  24.         {
  25.             // Set the text of the combobox to the current URL
  26.             //CComBSTR bstrURL;
  27.             //m_spWebBrowser->get_LocationURL(&bstrURL);
  28.             //m_wndUrlCombo.SetWindowText(OLE2T(bstrURL));
  29.         }
  30.         break;
  31.     case DISPID_DOWNLOADCOMPLETE:
  32.         // Disable the stop menu item and toolbar button
  33.         //EnableMenuItem(m_hMenu, ID_VIEW_STOP, MF_BYCOMMAND|MF_GRAYED);
  34.         //m_wndToolBar.SendMessage(TB_ENABLEBUTTON, ID_VIEW_STOP, MAKELONG(FALSE, 0));
  35.         break;
  36.         //
  37.         // The parameters for this DISPID:
  38.         // [0]: New status bar text - VT_BSTR
  39.         //
  40.     case DISPID_STATUSTEXTCHANGE:
  41.         //m_wndStatusBar.SetWindowText(OLE2T(pDispParams->rgvarg[0].bstrVal));
  42.         break;
  43.         //
  44.         // The parameters for this DISPID:
  45.         // [0]: Document title - VT_BSTR
  46.         //
  47.     case DISPID_TITLECHANGE:
  48.         {
  49.             //strstream strTitle;
  50.             //if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == VT_BSTR)
  51.             //{
  52.             //    strTitle << OLE2T(pDispParams->rgvarg[0].bstrVal);
  53.             //    strTitle << " - AtlBrowser";
  54.             //}
  55.             //else
  56.             //{
  57.             //    strTitle << "AtlBrowser";
  58.             //}
  59.             //strTitle << ends;
  60.             //SetWindowText(strTitle.str());
  61.         }
  62.         break;
  63.         //
  64.         // DISPID for Download Control
  65.         //
  66.     case DISPID_AMBIENT_DLCONTROL:
  67.         {
  68.             //CComVariant vtResult(static_cast<long>(m_dwDLControl));
  69.             //*pvarResult = vtResult;
  70.         }
  71.         break;
  72.     default:
  73.         return DISP_E_MEMBERNOTFOUND;
  74.     }
  75.     return S_OK;
  76. }

这里的关键是:在事件对象中定义IDispatch接口,通过在Invoke()函数中实现各事件分支语句,实现各事件具体功能。

而上一种需要为各个事件实现各自的函数,针对某个事件,会有相应的触发函数和响应函数。

而间接调用中,Invoke()把所有事件响应都集成在自己函数里,通过dispid的不同来进行分支处理。触发函数也只需一个,只需在输入参数中用dispid来区别。

间接调用的好处就是可以方便脚本语言中的实现,只是效率低很多而已。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值