代码之家  ›  专栏  ›  技术社区  ›  Yuval Peled

HTML-如何知道何时加载所有帧?

  •  11
  • Yuval Peled  · 技术社区  · 16 年前

    如何知道网页何时已完全加载?

    笔记:

    • 对于包含多个框架的网站,DocumentComplete/NavigateComplete事件可能会发生多次。
    12 回复  |  直到 16 年前
        1
  •  3
  •   Daniel Stutzbach Edward Leno    15 年前

    以下是我在应用程序中解决问题的方法:

    private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (e.Url != wbPost.Url)
            return;
        /* Document now loaded */
    }
    
        2
  •  2
  •   Kamil Szot    16 年前

    当页面完全加载时 (包括框架)是这样的:

    using System.Windows.Forms;
        protected delegate void Procedure();
        private void executeAfterLoadingComplete(Procedure doNext) {
            WebBrowserDocumentCompletedEventHandler handler = null;
            handler = delegate(object o, WebBrowserDocumentCompletedEventArgs e)
            {
                ie.DocumentCompleted -= handler;
                Timer timer = new Timer();
                EventHandler checker = delegate(object o1, EventArgs e1)
                {
                    if (WebBrowserReadyState.Complete == ie.ReadyState)
                    {
                        timer.Dispose();
                        doNext();
                    }
                };
                timer.Tick += checker;
                timer.Interval = 200;
                timer.Start();
            };
            ie.DocumentCompleted += handler;
        }
    

    从我的其他方法中,我学到了一些“不要”:

    • 不要试图使用DocumentComplete、Frames、HtmlWindow.Load事件构建复杂的构造。如果你的解决方案真的有效,那么它将是脆弱的。
    • 不要使用 System.Timers.Timer 而不是 Windows.Forms.Timer ,奇怪的错误将开始发生在奇怪的地方,如果你这样做,由于定时器运行在不同的线程,你的应用程序的其余部分。
    • 不要只使用没有DocumentComplete的计时器,因为它可能会在页面开始加载之前触发,并且会过早地执行代码。
        3
  •  2
  •   Rais Alam    12 年前

    这是我的测试版本。把这个当成你的 DocumentCompleted Event Handler 并放置您只希望调用的代码 一旦 入法 OnWebpageReallyLoaded() . 实际上,这种方法确定页面何时稳定了200毫秒,然后执行它的操作。

    // event handler for when a document (or frame) has completed its download
    Timer m_pageHasntChangedTimer = null;
    private void webBrowser_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e ) {
        // dynamic pages will often be loaded in parts e.g. multiple frames
        // need to check the page has remained static for a while before safely saying it is 'loaded'
        // use a timer to do this
    
        // destroy the old timer if it exists
        if ( m_pageHasntChangedTimer != null ) {
            m_pageHasntChangedTimer.Dispose();
        }
    
        // create a new timer which calls the 'OnWebpageReallyLoaded' method after 200ms
        // if additional frame or content is downloads in the meantime, this timer will be destroyed
        // and the process repeated
        m_pageHasntChangedTimer = new Timer();
        EventHandler checker = delegate( object o1, EventArgs e1 ) {
            // only if the page has been stable for 200ms already
            // check the official browser state flag, (euphemistically called) 'Ready'
            // and call our 'OnWebpageReallyLoaded' method
            if ( WebBrowserReadyState.Complete == webBrowser.ReadyState ) {
                m_pageHasntChangedTimer.Dispose();
                OnWebpageReallyLoaded();
            }
        };
        m_pageHasntChangedTimer.Tick += checker;
        m_pageHasntChangedTimer.Interval = 200;
        m_pageHasntChangedTimer.Start();
    }
    
    OnWebpageReallyLoaded() {
        /* place your harvester code here */
    }
    
        4
  •  0
  •   mbeckish    16 年前

    在每个帧中使用javascript在帧完成时设置一个标志,然后让C#查看标志如何?

        5
  •  0
  •   paulgreg    16 年前

    我不确定它是否有效,但尝试在您的框架集上添加JavaScript“onload”事件,如下所示:

    function everythingIsLoaded() { alert("everything is loaded"); }
    var frameset = document.getElementById("idOfYourFrameset");
    if (frameset.addEventListener)
        frameset.addEventListener('load',everythingIsLoaded,false); 
    else
        frameset.attachEvent('onload',everythingIsLoaded); 
    
        6
  •  0
  •   Community Mohan Dere    8 年前

    你会使用jQuery吗?然后可以轻松地在目标帧上绑定帧就绪事件。看见 this 问路。这 blog post plug-in

    这样做的目的是使用以下方法计算网页中的帧数:

    $("iframe").size()
    

        7
  •  0
  •   i_am_jorf    16 年前

    您将获得外部网页以及每个框架的BeforeNavigate和DocumentComplete事件。当您获得外部网页的DocumentComplete事件时,您就知道您已经完成了。您应该能够使用 IWebBrowser2::TopLevelContainer() 来确定这一点。

    然而,请注意,网站本身可以随时触发更多的框架导航,所以你永远不知道一个页面是否真的永远完成了。您所能做的最好的事情就是对您看到的所有预览进行计数,并在文档完成时减少计数。

    编辑:以下是托管文档: TopLevelContainer

        8
  •  0
  •   Yuval Peled    16 年前

    以下是最终对我有效的方法:

           public bool WebPageLoaded
        {
            get
            {
                if (this.WebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
                    return false;
    
                if (this.HtmlDomDocument == null)
                    return false;
    
                // iterate over all the Html elements. Find all frame elements and check their ready state
                foreach (IHTMLDOMNode node in this.HtmlDomDocument.all)
                {
                    IHTMLFrameBase2 frame = node as IHTMLFrameBase2;
                    if (frame != null)
                    {
                        if (!frame.readyState.Equals("complete", StringComparison.OrdinalIgnoreCase))
                            return false;
    
                    }
                }
    
                Debug.Print(this.Name + " - I think it's loaded");
                return true;
            }
        }
    

    这是相当可靠的,但正如jeffamaphone所说,我已经看到一些触发内部刷新的网站。 但是上面的代码满足了我的需要。

    编辑:每个帧都可以包含帧,因此我认为应该更新此代码,以递归方式检查每个帧的状态。

        9
  •  0
  •   Jeppoo    15 年前

    我只使用webBrowser.StatusText方法。当它说“完成”时,所有内容都已加载! 还是我遗漏了什么?

        10
  •  0
  •   thdoan    14 年前

    检查IE.readyState=readyState\u COMPLETE应该可以,但是如果这对您来说不可靠,并且您确实想知道“IE在其状态栏中写入“完成”的时刻”,那么您可以执行循环,直到IE.StatusText包含“完成”。

        11
  •  0
  •   Tim Cooper    14 年前

    你试过了吗 WebBrowser.IsBusy 所有物

        12
  •  0
  •   Coder12345    5 年前

    IsBusy 财产存在 true 在文档完整处理过程中,由于处理程序仍在运行,因此 WebBrowser

    最简单的解决方案是有一个循环,大约每100毫秒执行一次,直到 我很忙 标志被重置(出现错误时具有最大执行时间)。这当然是假设 我很忙 将不会设置为 false

    如果文档完成处理程序在另一个线程上执行,则可以使用锁将主线程发送到睡眠状态,并将其从文档完成线程中唤醒。然后检查 我很忙 标志,重新锁定主线程是它的静止状态 符合事实的