Original posts: http://blog.csdn.net/wangjia184/article/details/3684862
On the forum, someone asked how to Judge page loading in CHtmlView. Here's a little idea.
First of all think about this question if it is in JS inside how to achieve.
JS inside the simplest way is to use the OnLoad event to let a section of JS after the page load is completed.
The advantage of using the OnLoad event is to ensure that the image image on the page is loaded.
Like what:
window.onload = function () { // do something } // window.attachevent ("onload" , function () { // do something });
These two types of writing are slightly different.
For the former, the handle of the onload is replaced directly, that is, if the page already has onload, then executing this sentence will result in the original onload processing being replaced (of course, the code must be guaranteed to execute before onload).
While the latter attachevent, it is able to add multiple handle handles to the onload event.
In one sentence, the sequence of events executed by multiple attachevent is indeterminate. Some people used to compare attachevent and AddEventListener.
It is found that the execution order of multiple handles on attachevent is completely uncontrolled. This is why in some JS framework, such as EXT, the introduction of their own event processing stream, to achieve multi-browser consistency. So, if the page has been attachevent, and you attachevent, then the result is very difficult to predict, try to avoid.
The front is all nonsense, how to come to the chtmlview inside to realize?
In CHtmlView, the following 2 interface functions correspond to the above 2 kinds of JS notation.
IHTMLWindow2::p ut_onload (VARIANT v); // or Event , *pdisp, *pfresult);
See, in the mshtml, there are completely interface functions to achieve the same function in JS.
First, look at the C + + code corresponding to the first JS notation
voidCtesthtmlviewview::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);}
Then look at the 2nd kind of JS corresponding C + + code.
voidCtesthtmlviewview::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); } }}
The specific use of the wording, according to your own actual situation depends on.
Careful you must have found, Cdomeventhandler is what?
What is Ctesthtmlviewview::onload?
Ctesthtmlviewview::onload is the response function of the OnLoad event, which is passed here as a function pointer, and the function pointer prototype is:
void
Cdomeventhandler is a class derived from the IDispatch. Well, don't say that much. How do we do that?
The first step is to add the Cdomeventhandler class to your project
#pragmaOnce//DOMEventHandler.h//-------------------------------------------------------------------------//created:2009-1-2 Wangjia//-------------------------------------------------------------------------typedefvoid(*pfn_dom_event_callback) (variant*Pvarresult, Long_ptr lpuserdata);classCdomeventhandler: PublicIDispatch { 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) (unsignedintfar* pctinfo) {returnE_NotImpl;} STDMETHOD (GetTypeInfo) (unsignedintItinfo, lcid lcid, ITypeInfo far* far* pptinfo) {returnE_NotImpl;} STDMETHOD (GetIDsOfNames) (REFIID riid, Olechar far* far* Rgsznames, unsignedintCNAMEs, lcid lcid, dispid far* rgdispid) {returnS_OK;} STDMETHOD (Invoke) (DispID dispidmember, REFIID riid, lcid lcid, WORD wflags, DISPPARAMS*pDispParams, VARIANT*Pvarresult, Excepinfo*Pexcepinfo, UINT*Puargerr); Staticlpdispatch Createeventhandler (pfn_dom_event_callback pfncallback, long_ptr lpuserdata); StaticVARIANT createeventhandlervariant (pfn_dom_event_callback pfncallback, long_ptr lpuserdata);Private: Pfn_dom_event_callback m_pfcallback; LongM_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 (); returnS_OK; } Else { returnE_nointerface; }}dword __stdcall Cdomeventhandler::addref () {returnInterlockedIncrement (&m_lrefcount);} DWORD __stdcall Cdomeventhandler::release () {if(InterlockedDecrement (&m_lrefcount) = =0) { Delete This; return 0; } returnM_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); } returnS_OK;} Lpdispatch Cdomeventhandler::createeventhandler (Pfn_dom_event_callback pfncallback, LONG_PTR lpUserData) { Cdomeventhandler* Phandler =NewCdomeventhandler (Pfncallback, lpuserdata); returnReinterpret_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); returnvariant;}
2nd step, add your own callback function. Here is just an example.
class Public chtmlview{ staticvoid OnLoad (variant* pvarresult, long_ptr lpuserdata);}; void Ctesthtmlviewview::onload (variant* pvarresult, long_ptr lpuserdata) { * pThis = reinterpret_cast< Ctesthtmlviewview*>(Lpuserdata); :: MessageBox (NULL, _t ("OnLoad" ), NULL, MB_OK);}
3rd step, according to your own situation, mount the onload, code reference above.
Basically, if your page has a frame, the window in the IFrame is also able to hook up the onload, oh, anyway, everything is consistent with JS. JS can be how to achieve, VC can be achieved.
"MFC" goto: Determine page load completion in CHtmlView