作者:lingling2502852417 | 来源:互联网 | 2023-09-12 10:23
一般分为两种:1、直接调用HRESULTCFirePropNotifyEvent::FireOnRequestEdit(IUnknown*pUnk,DISPIDdi
一般分为两种:
1、直接调用
- HRESULT CFirePropNotifyEvent::FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
- {
- CComQIPtr pCPC(pUnk);
- if (!pCPC)
- return S_OK;
- CComPtr pCP;
- pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
- if (!pCP)
- return S_OK;
- CComPtr pEnum;
- if (FAILED(pCP->EnumConnections(&pEnum)))
- return S_OK;
- CONNECTDATA cd;
- while (pEnum->Next(1, &cd, NULL) == S_OK)
- {
- if (cd.pUnk)
- {
- HRESULT hr = S_OK;
- CComQIPtr pSink(cd.pUnk);
- if (pSink)
- hr = pSink->OnRequestEdit(dispID);
- cd.pUnk->Release();
- if (hr == S_FALSE)
- return S_FALSE;
- }
- }
- return S_OK;
- }
获得连接容器接口,进而获得容器中接收器IID_IPropertyNotifySink类型的连接点,再遍历这个连接点中各个IID_IPropertyNotifySink接收器,进而调用相应某事件。
这里的关键是:在事件对象中继承IID_IPropertyNotifySink接收器接口,并实现OnRequestEdit等事件函数。
2、间接调用。
- template<typename host_t, const IID* pIID_ToHookEvent>
- class ComEventIntercepter : public IDispatch
- {
- typedef HRESULT (STDMETHODCALLTYPE host_t::*invok_t)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
- DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr);
- public:
- ComEventIntercepter(host_t* pHost &#61; NULL, invok_t notifier &#61; NULL) :
- m_pHost(pHost), m_notifier(notifier), m_dwCOOKIE(0)
- {
- }
- HRESULT Intercept(IUnknown* pUnkCP)
- {
- if(pUnkCP &#61;&#61; NULL)
- return E_INVALIDARG;
- CComPtr pCPC;
- CComPtr pCP;
- HRESULT hRes &#61; pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
- if (SUCCEEDED(hRes))
- hRes &#61; pCPC->FindConnectionPoint(*pIID_ToHookEvent, &pCP);
- if (SUCCEEDED(hRes))
- hRes &#61; pCP->Advise(this, &m_dwCOOKIE);
- return hRes;
- }
- public:
- STDMETHODIMP QueryInterface(REFIID iid, void ** ppvObject)
- {
- if(ppvObject &#61;&#61; NULL) return E_INVALIDARG;
- *ppvObject &#61; NULL;
- if(iid &#61;&#61; IID_IUnknown)
- *ppvObject &#61; (IUnknown*)this;
- else if(iid &#61;&#61; *pIID_ToHookEvent || iid &#61;&#61; IID_IDispatch)
- *ppvObject &#61; this;
- if(*ppvObject &#61;&#61; NULL) return E_NOINTERFACE;
- return S_OK;
- }
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return 0;
- }
- ULONG STDMETHODCALLTYPE Release()
- {
- return 0;
- }
- HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR* pctinfo)
- { return E_NOTIMPL; }
- HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID lcid,
- ITypeInfo FAR* FAR* ppTInfo)
- { return E_NOTIMPL; }
- HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
- OLECHAR FAR* FAR* rgszNames,
- unsigned int cNames,
- LCID lcid,
- DISPID FAR* rgDispId)
- { return E_NOTIMPL; }
- HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
- DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,
- EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr)
- {
- if(m_pHost && m_notifier)
- {
- return (m_pHost->*m_notifier)(dispIdMember, riid, lcid, wFlags, pDispParams, parResult, pExcepInfo, puArgErr);
- }
- return E_NOTIMPL;
- }
- protected:
- host_t* m_pHost;
- invok_t m_notifier;
- DWORD m_dwCOOKIE;
- };
- HRESULT CWebBrowser::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
- DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult,
- EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr)
- {
- switch (dispIdMember)
- {
- case DISPID_DOCUMENTCOMPLETE:
-
- break;
- case DISPID_DOWNLOADBEGIN:
-
-
-
- break;
- case DISPID_NAVIGATECOMPLETE:
- {
-
-
-
-
- }
- break;
- case DISPID_NAVIGATECOMPLETE2:
- {
-
-
-
-
- }
- break;
- case DISPID_DOWNLOADCOMPLETE:
-
-
-
- break;
-
-
-
-
- case DISPID_STATUSTEXTCHANGE:
-
- break;
-
-
-
-
- case DISPID_TITLECHANGE:
- {
-
-
-
-
-
-
-
-
-
-
-
-
- }
- break;
-
-
-
- case DISPID_AMBIENT_DLCONTROL:
- {
-
-
- }
- break;
- default:
- return DISP_E_MEMBERNOTFOUND;
- }
- return S_OK;
- }
这里的关键是&#xff1a;在事件对象中定义IDispatch接口&#xff0c;通过在Invoke()函数中实现各事件分支语句&#xff0c;实现各事件具体功能。
而上一种需要为各个事件实现各自的函数&#xff0c;针对某个事件&#xff0c;会有相应的触发函数和响应函数。
而间接调用中&#xff0c;Invoke()把所有事件响应都集成在自己函数里&#xff0c;通过dispid的不同来进行分支处理。触发函数也只需一个&#xff0c;只需在输入参数中用dispid来区别。
间接调用的好处就是可以方便脚本语言中的实现&#xff0c;只是效率低很多而已。