Webbrowser控件判断网页加载完毕的简单方法 (转)

摘自:http://blog.csdn.net/cometnet/article/details/5261192

一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,Webbrowser控件会通过触发DocumentCompleted事件来指示网页加载完毕。但当加载的网页包含frame时,可能会多次触发该事件,所以不能简单地通过它来判断网页加载完毕。

从微软的官方网站上了解到,并非每个frame都对应了一个DocumentCompleted事件,只有触发了DownloadBegin事件的frame才会有相应的DocumentCompleted事件。另外,最外层的frame总是最后触发DocumentCompleted事件。DocumentCompleted事件具有一个IDispatch *类型的参数,它指示了是在哪个frame上触发的该事件。所以,要判断文档是否加载完毕,只需要判断IDispatch *参数是否是Webbrowser控件的IDispatch。

微软support网站上关于这个问题的说明:

http://support.microsoft.com/?scid=kb%3Ben-us%3B180366&x=9&y=14

原文及译文如下:(我用Google翻译的,不一定正确,大家见谅)

The Internet Explorer WebBrowser control fires the DocumentComplete event when it is finished downloading a Web page. You can create a event handler function in your application for this event. This article describes the steps to take in determining if a the WebBrowser control is finished downloading a Web page.

在Internet Explorer WebBrowser控件激发DocumentComplete事件完成时下载网页。您可以在应用程序中创建的这一事件的事件处理函数。本文介绍的步骤可以参与决定,如果WebBrowser控件下载完成一个网页。

The WebBrowser control fires the DocumentComplete event when its ReadyState property is changed to READYSTATE_COMPLETE. This indicates that the WebBrowser control has completed downloading the Web page. Here are some important points regarding this event:

  • In the case of a page with no frames, DocumentComplete is fired once after everything is done.
  • In case of multiple frames, DocumentComplete gets fired multiple times. Not every frame fires this event, but each frame that fires a DownloadBegin event fires a corresponding DocumentComplete event.
  • The DocumentComplete event has a IDispatch* parameter, which is the IDispatch of the frame (shdocvw) for which DocumentComplete is fired.
  • The top-level frame fires the DocumentComplete in the end. So, to check if a page is done downloading, you need to check if the IDispatch* parameter is same as the IDispatch of the WebBrowser control.

WebBrowser控件激发DocumentComplete事件时,它的readyState属性更改为READYSTATE_COMPLETE。这表明,WebBrowser控件已完成下载的网页。以下是一些对这起事件的要点: 在网页的情况下,没有框架,一旦被激发的DocumentComplete一切完成之后。 在多个帧的情况,得到的DocumentComplete多次发射。不是每帧触发这一事件,但每个帧触发一个DownloadBegin事件触发相应的DocumentComplete事件。 DocumentComplete事件的IDispatch *有一个参数,它是框架(shdocvw),这些被激发的DocumentComplete的IDispatch。 在顶级框架火灾最终的DocumentComplete。因此,要检查一个页面完成下载,您需要检查的IDispatch *参数作为WebBrowser控件的IDispatch相同。

For Visual Basic, here is code that performs this check:

[vb] view plaincopyprint?

  1. Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object,URL As Variant)
  2. If (pDisp Is WebBrowser1.Object) Then
  3. Debug.Print "Web document is finished downloading"
  4. End If
  5. End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object,URL As Variant)
If (pDisp Is WebBrowser1.Object) Then
Debug.Print "Web document is finished downloading"
End If
End Sub

To handle the DocumentComplete event in Visual C++ and determine if the download of the Web page is complete, follow these steps.
Note that the steps you follow depend on the way you use the WebBrowser control.

  • If you are creating the WebBrowser control in a CWnd/CView object, you must follow steps 1 to 4.
  • If you are creating the WebBrowser control in a CDialog/CFormView object, only need to follow step 4.
  • If you are using the CHtmlView class provided with Visual C++ 6.0, override CHtmlView::DocumentComplete() and follow step 4, using the m_pBrowserApp member of the CHtmlView class to access the WebBrowser control.

为了处理在Visual C + + DocumentComplete事件,并确定如果网页下载完成后,按照下列步骤。
请注意,您按照步骤取决于你如何使用WebBrowser控件。 如果你在创建一个CWnd / CView对象WebBrowser控件,则必须按照步骤1至4。 如果您要创建一个CDialog在WebBrowser控件/ CFormView对象,只需要按照步骤4。 如果您使用的是CHtmlView类提供与Visual C + + 6.0,重写CHtmlView::的DocumentComplete()和后续步骤4,使用该CHtmlView类m_pBrowserApp成员访问WebBrowser控件。

1.Define the OnDocumentComplete method in the header file for your CWnd/CView-derived class:

[cpp] view plaincopyprint?

  1. afx_msg void OnDocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);

afx_msg void OnDocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);

2.Declare the event sink in the same header file:

[cpp] view plaincopyprint?

  1. DECLARE_EVENTSINK_MAP()

DECLARE_EVENTSINK_MAP()

3.In the implementation file (.cpp) for your CWnd/CView-derived class, implement the event sink map:

[cpp] view plaincopyprint?

  1. BEGIN_EVENTSINK_MAP(CYourView, CView)
  2. ON_EVENT(CWBTstView, ID_WEB_BROWSE, 259 /* DocumentComplete */,
  3. OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
  4. END_EVENTSINK_MAP()

BEGIN_EVENTSINK_MAP(CYourView, CView)
ON_EVENT(CWBTstView, ID_WEB_BROWSE, 259 /* DocumentComplete */,
OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
END_EVENTSINK_MAP()

4.Implement the OnDocumentComplete method:

[cpp] view plaincopyprint?

  1. void CWBTstView::OnDocumentComplete(LPDISPATCH lpDisp,
  2. VARIANT FAR* URL)
  3. {
  4. IUnknown*  pUnk;
  5. LPDISPATCH lpWBDisp;
  6. HRESULT    hr;
  7. pUnk = m_webBrowser.GetControlUnknown();
  8. ASSERT(pUnk);
  9. hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
  10. ASSERT(SUCCEEDED(hr));
  11. if (lpDisp == lpWBDisp )
  12. {
  13. // Top-level Window object, so document has been loaded
  14. TRACE("Web document is finished downloading/n");
  15. }
  16. lpWBDisp->Release();
  17. }

void CWBTstView::OnDocumentComplete(LPDISPATCH lpDisp,
VARIANT FAR* URL)
{
IUnknown* pUnk;
LPDISPATCH lpWBDisp;
HRESULT hr;

pUnk = m_webBrowser.GetControlUnknown();
ASSERT(pUnk);

hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
ASSERT(SUCCEEDED(hr));

if (lpDisp == lpWBDisp )
{
// Top-level Window object, so document has been loaded
TRACE("Web document is finished downloading/n");
}

lpWBDisp->Release();
}

This approach works when the WebBrowser control navigates to a page that changes the top-level frame. Say if the navigation occurs within a frame itself, then the final DocumentComplete that is fired is that of the frame and not the top-level frame. For example, consider the following scenario.
The WebBrowser control is hosting a frameset. Within one frame of the frameset, the user clicks on a link that opens a new page in the frame itself and keeps the rest of the frameset intact. The new page could contain multiple frames again. So, there will be multiple DocumentComplete notifications (one for each new frame). But, since the top-level frame has not changed, the final DocumentComplete would be that of the frame that has changed.
If you are interested in checking for the final document complete in this scenario, you could do the following:

Check if the IDispatch parameter of the DocumentComplete is the same as the IDispatch parameter of first NavigateComplete2 event. Since the first NavigateComplete2 is of the top-level frame and the last DocumentComplete is also of the top-level frame, doing a comparison in such a fashion will tell whether the page is done downloading.

这种方法在WebBrowser控件时,导航到一个网页,更改顶级框架。说,如果出现导航本身的框架内,那么最后一个DocumentComplete是发射的是,框架,而不是顶级框架。例如,考虑以下情况。
WebBrowser控件主持一个框架。在一个框架集框架,在用户点击链接打开在框架本身就是一种新的一页,保持完整的框架休息。新的页面可能包含多个帧了。因此,将有多个(每个新的框架之一)的DocumentComplete通知。但是,由于顶级框架没有改变,最后的DocumentComplete将是该改变了框架。
如果您是在为最后文件在这种情况下完成检查感兴趣,你可以做以下操作: 检查的一个DocumentComplete的IDispatch参数是相同的第一NavigateComplete2事件的IDispatch参数。自第一NavigateComplete2是顶级帧和最后一个DocumentComplete也是顶级框架,做了这样的方式比较,判断该页面进行下载。

Here is some sample C++ code:

[cpp] view plaincopyprint?

  1. LPDISPATCH glpDisp = NULL; // global LPDISPATCH, can also
  2. // be of class scope
  3. // NavigateComplete2 event
  4. void CWebbrDlg::OnNavigateComplete2Explorer1(LPDISPATCH pDisp,
  5. VARIANT FAR* URL)
  6. {
  7. // Check if glpDisp is NULL. If NULL, that means it is
  8. // the top level NavigateComplete2. Save the LPDISPATCH
  9. if (!glpDisp)
  10. glpDisp = pDisp;
  11. }
  12. void CWebbrDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp,
  13. VARIANT FAR* URL)
  14. {
  15. if (glpDisp && glpDisp == pDisp)
  16. {
  17. // if the LPDISPATCH are same, that means
  18. // it is the final DocumentComplete. Reset glpDisp
  19. TRACE("Document is done downloading");
  20. glpDisp = NULL;
  21. }
  22. }

LPDISPATCH glpDisp = NULL; // global LPDISPATCH, can also
// be of class scope

// NavigateComplete2 event
void CWebbrDlg::OnNavigateComplete2Explorer1(LPDISPATCH pDisp,
VARIANT FAR* URL)
{
// Check if glpDisp is NULL. If NULL, that means it is
// the top level NavigateComplete2. Save the LPDISPATCH
if (!glpDisp)
glpDisp = pDisp;
}

void CWebbrDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp,
VARIANT FAR* URL)
{
if (glpDisp && glpDisp == pDisp)
{
// if the LPDISPATCH are same, that means
// it is the final DocumentComplete. Reset glpDisp
TRACE("Document is done downloading");
glpDisp = NULL;
}
}

Webbrowser控件判断网页加载完毕的简单方法 (转)

时间: 2024-08-09 06:18:46

Webbrowser控件判断网页加载完毕的简单方法 (转)的相关文章

Webbrowser控件判断网页加载完毕的简单方法

一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,Webbrowser控件会通过触发DocumentCompleted事件来指示网页加载完毕.但当加载的网页包含frame时,可能会多次触发该事件,所以不能简单地通过它来判断网页加载完毕.从微软的官方网站上了解到,并非每个frame都对应了一个DocumentCompleted事件,只有触发了DownloadBegin事件的frame才会有相应的DocumentCompleted事件.另外,最外层的frame总是最

VB判断webbrowser网页加载完毕

'====VB判断webbrowser网页加载完毕 Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant) If (pDisp Is WebBrowser1.Object) Then Msgbox "网页下载完毕!" End If End Sub

MFC WebBrowser判断网页加载完成

mfc 的webbrowser是大家使用非常多的一种查看操作网页的一种控件,在使用中,判断网页什么时候加载完成就显得非常重要了.下面介绍我采用的一种方法,这种方法可以判断网页内部即使有frame网页也是可以判断成功.在对话框里添加一个webbrowser控件,在对话框的初始化函数OnInitDialog()中加入web控件默认加载的网页. //禁用IE脚本错误 m_web.put_Silent(TRUE); //默认打开百度网页 m_web.Navigate(L"https://www.baid

delphi WebBrowser控件上网页验证码图片识别教程(一)

步骤一:获取网页中验证码图片的url地址 在delphi中加入一个BitBtn和一个memo以及WebBrowser控件实现网页中验证码图片的url地址的获取 程序如下:procedure TForm1.BitBtn1Click(Sender: TObject); var I:Integer; begin for I:=0 to WebBrowser1.OleObject.document.images.length-1 do Memo1.Lines.Add(WebBrowser1.OleObj

JS判断页面加载完毕

//JS判断页面加载完毕,再隐藏加载效果层,一个简单的JS加载效果. document.onreadystatechange = function () { if (document.readyState == "complete") { var page = DF.URLHash.get("page"); if (typeof (page) != "undefined" && page != "page1.html&q

使用SplashScreenManager控件定制程序加载页面

需要devexpress版本在12.0及以上才支持 https://www.cnblogs.com/wuhuacong/p/6112461.html 在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口 http://blog.csdn.net/archielau/article/details/37401443 ProgressPanel.WaitForm.SplashScreenManager http://blog.csdn.net/qq99

Delphi安装DevExpress控件后,加载图片自动调用dxGDIPlusClasses的问题

Delphi安装DevExpress控件后, image控件用 Picture.LoadFromFile()  加载图片,会自动调用dxGDIPlusClasses,可以正常显示图片. FastReport中的image控件 Picture.LoadFromFile()  加载图片,也会自动调用dxGDIPlusClasses,这可能导致image控件中的图片无法显示. 解决办法是: 修改控件源码: dxGDIPlusClasses 单元中,注释掉一行代码: {$DEFINE DXREGISTE

Duilib中Webbrowser事件完善,使其支持判断页面加载完毕

在多iframe的页面中,需要结合DISPID_DOCUMENTCOMPLETE和DISPID_BEFORENAVIGATE2两个事件判断页面是否加载完毕,而duilib中没有提供对DISPID_DOCUMENTCOMPLETE的支持. 要支持DISPID_DOCUMENTCOMPLETE,需要修改UIWebBrowser.cpp.UIWebBrowser.h和WebBrowserEventHandler.h三个文件,修改之后的文件见附件.

jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法

转自:http://www.cnblogs.com/sunjie9606/archive/2012/09/13/2683636.html 现象: AJAX返回的html无法做到自动渲染为EasyUI的样式.比如:class="easyui-layout" 等 处理方法: 在html片段加载完毕后使用 Js代码 $.parser.parse(context) 即可重新渲染. 实现原理: 首先附上jquery.parser.js的源码 Js代码 (function($){ $.parser