在CHtmlView中,有下面2个接口函数对应上面的2种JS写法。
- IHTMLWindow2::put_onload(VARIANT v);
- // 或者
- IHTMLWindow3::attachEvent( BSTR event,
- IDispatch *pDisp,
- VARIANT_BOOL *pfResult
- );
看到了吧,在MSHTML中,完全有接口函数来实现JS中同样的功能。
首先看看 第一种JS写法对应的 C++ 代码
- void CTestHtmlViewView::OnDocumentComplete(LPCTSTR lpszURL)
- {
- IHTMLDocument * pDoc = (IHTMLDocument *)GetHtmlDocument();
- CComQIPtr<IHTMLDocument2> pDoc2(pDoc);
- if( pDoc2 )
- {
- CComPtr<IHTMLWindow2> pWnd2;
- pDoc2->get_parentWindow(&pWnd2);
- if( pWnd2 )
- {
- VARIANT vEvent = CDOMEventHandler::CreateEventHandlerVariant( &CTestHtmlViewView::OnLoad, (LONG_PTR)this);
- pWnd2->put_onload( vEvent );
- }
- }
- CHtmlView::OnDocumentComplete(lpszURL);
- }
再看看 第2种JS对应的C++代码。
- void CTestHtmlViewView::OnDocumentComplete(LPCTSTR lpszURL)
- {
- IHTMLDocument * pDoc = (IHTMLDocument *)GetHtmlDocument();
- CComQIPtr<IHTMLDocument2> pDoc2(pDoc);
- if( pDoc2 )
- {
- CComPtr<IHTMLWindow2> pWnd2;
- pDoc2->get_parentWindow(&pWnd2);
- CComQIPtr<IHTMLWindow3> pWnd3(pWnd2);
- if( pWnd3 )
- {
- VARIANT_BOOL vbSuccess = VARIANT_FALSE;
- pWnd3->attachEvent( _bstr_t(_T("onload"))
- , CDOMEventHandler::CreateEventHandler( &CTestHtmlViewView::OnLoad, (LONG_PTR)this)
- , &vbSuccess
- );
- }
- }
- }
具体使用哪种写法,依据你自己的实际情况而定。
细心的你一定发现了, CDOMEventHandler是什么?
CTestHtmlViewView::OnLoad是什么?
CTestHtmlViewView::OnLoad是onload事件的响应函数,它在这里作为函数指针传递,函数指针原型为:
- typedef void (*PFN_DOM_EVENT_CALLBACK)(VARIANT* pVarResult, LONG_PTR lpUserData);
CDOMEventHandler是一个派生自IDispatch的类。好了,不说那么多了。 那应该具体怎么做呢?
第一步,将CDOMEventHandler类加入到你的工程
- #pragma once
- // DOMEventHandler.h
- //-------------------------------------------------------------------------
- // Created :2009-1-2 WangJia
- //-------------------------------------------------------------------------
- typedef void (*PFN_DOM_EVENT_CALLBACK)(VARIANT* pVarResult, LONG_PTR lpUserData);
- class CDOMEventHandler : public IDispatch
- {
- public:
- CDOMEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
- ~CDOMEventHandler(void);
- HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
- DWORD __stdcall AddRef();
- DWORD __stdcall Release();
- STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo) { return E_NOTIMPL; }
- STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) { return E_NOTIMPL; }
- STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return S_OK; }
- STDMETHOD(Invoke)(DISPID dispIdMember
- , REFIID riid
- , LCID lcid
- , WORD wFlags
- , DISPPARAMS* pDispParams
- , VARIANT* pVarResult
- , EXCEPINFO * pExcepInfo
- , UINT * puArgErr
- );
- static LPDISPATCH CreateEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
- static VARIANT CreateEventHandlerVariant(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
- private:
- PFN_DOM_EVENT_CALLBACK m_pfCallback;
- long m_lRefCount;
- LONG_PTR m_lpUserData;
- };
- #include "StdAfx.h"
- #include "DOMEventHandler.h"
- // DOMEventHandler.cpp
- //-------------------------------------------------------------------------
- // Created :2009-1-2 WangJia
- //-------------------------------------------------------------------------
- CDOMEventHandler::CDOMEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
- : m_lRefCount(0)
- , m_pfCallback(pfnCallback)
- , m_lpUserData(lpUserData)
- {
- }
- CDOMEventHandler::~CDOMEventHandler(void)
- {
- }
- HRESULT __stdcall CDOMEventHandler::QueryInterface(REFIID riid, void** ppvObject)
- {
- *ppvObject = NULL;
- if (IsEqualGUID(riid, IID_IUnknown))
- *ppvObject = reinterpret_cast<void**>(this);
- if (IsEqualGUID(riid, IID_IDispatch))
- *ppvObject = reinterpret_cast<void**>(this);
- if (*ppvObject)
- {
- ((IUnknown*)*ppvObject)->AddRef();
- return S_OK;
- }
- else
- {
- return E_NOINTERFACE;
- }
- }
- DWORD __stdcall CDOMEventHandler::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- DWORD __stdcall CDOMEventHandler::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) == 0)
- {
- delete this;
- return 0;
- }
- return m_lRefCount;
- }
- HRESULT CDOMEventHandler::Invoke(DISPID dispIdMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- DISPPARAMS* pDispParams,
- VARIANT* pVarResult,
- EXCEPINFO * pExcepInfo,
- UINT * puArgErr)
- {
- if (dispIdMember == DISPID_VALUE)
- {
- if( m_pfCallback )
- (*m_pfCallback)(pVarResult, m_lpUserData);
- }
- return S_OK;
- }
- LPDISPATCH CDOMEventHandler::CreateEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
- {
- CDOMEventHandler * pHandler = new CDOMEventHandler( pfnCallback, lpUserData);
- return reinterpret_cast<LPDISPATCH>(pHandler);
- }
- VARIANT CDOMEventHandler::CreateEventHandlerVariant(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
- {
- VARIANT variant;
- variant.vt = VT_DISPATCH;
- variant.pdispVal = CDOMEventHandler::CreateEventHandler( pfnCallback, lpUserData);
- return variant;
- }
第2步,添加你自己的回调函数。这里只是举例。
- class CTestHtmlViewView : public CHtmlView
- {
- static void OnLoad(VARIANT* pVarResult, LONG_PTR lpUserData);
- };
- void CTestHtmlViewView::OnLoad(VARIANT* pVarResult, LONG_PTR lpUserData)
- {
- CTestHtmlViewView * pThis = reinterpret_cast<CTestHtmlViewView*>(lpUserData);
- ::MessageBox( NULL, _T("OnLoad"), NULL, MB_OK);
- }
第3步,根据你自己的情况,挂接onload, 代码参考上面。
基本就这样,如果你的页面有框架,iframe中的window也是能够挂接onload的哦, 反正一切都和JS的一致。JS能够怎么实现,VC就能如何实现。