是否可以确定WebBrowser是否正在导航?

Jua*_*uan 7 .net c# browser webbrowser-control

我正试图找到一种方法让我的程序知道WebBrowser何时导航以及何时不导航.这是因为程序将通过将在文档中注入的JavaScript与加载的文档进行交互.我没有任何其他方式知道它何时开始导航而不是处理导航事件,因为不是我的程序,而是将通过与文档交互进行导航的用户.但是,当DocumentCompleted发生时并不一定意味着它已完成导航.我一直在谷歌搜索,发现两个伪解决方案:

  1. 在事件中检查WebBrowser的ReadyState属性DocumentCompleted.这里的问题是,如果没有这个文件,但该文件加载的框架中,ReadyStateCompleted即使没有完成主文档.

  2. 为了防止这种情况,他们建议,看是否网址参数传递到DocumentCompleted比赛地址WebBrowser.这样我就会知道DocumentCompleted文档中的某些其他框架没有调用它.

2的问题在于,正如我所说,我必须知道页面导航的唯一方法是处理Navigating(或Navigated)事件.因此,例如,如果我在Google地图中并点击搜索,Navigating则会调用,但只是一个框架正在导航; 不是整个页面(在特定的Google案例中,我可以使用TargetFrameName属性WebBrowserNavigatingEventArgs来检查它是否是正在导航的帧,但帧并不总是有名称).所以在那之后,DocumentCompleted将被调用,但不会与UrlWebBrowserUrl属性相同,因为它只是一个导航的框架,所以我的程序将会永远导航它.

添加调用Navigating和减去调用也DocumentCompleted不会工作.它们并不总是一样的.我已经好几个月没有找到这个问题的解决方案; 我一直在使用解决方案1和2,并希望它们适用于大多数情况.我的计划是使用计时器,以防某些网页出现错误或其他问题,但我认为Google地图没有任何错误.我仍然可以使用它,但唯一更丑陋的解决方案是烧毁我的电脑.

编辑:到目前为止,这是我最接近解决方案的:

partial class SafeWebBrowser
{
    private class SafeNavigationManager : INotifyPropertyChanged
    {
        private SafeWebBrowser Parent;
        private bool _IsSafeNavigating = false;
        private int AccumulatedNavigations = 0;
        private bool NavigatingCalled = false;

        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsSafeNavigating
        {
            get { return _IsSafeNavigating; }
            private set { SetIsSafeNavigating(value); }
        }

        public SafeNavigationManager(SafeWebBrowser parent)
        {
            Parent = parent;
        }

        private void SetIsSafeNavigating(bool value)
        {
            if (_IsSafeNavigating != value)
            {
                _IsSafeNavigating = value;
                OnPropertyChanged(new PropertyChangedEventArgs("IsSafeNavigating"));
            }
        }

        private void UpdateIsSafeNavigating()
        {
            IsSafeNavigating = (AccumulatedNavigations != 0) || (NavigatingCalled == true);
        }

        private bool IsMainFrameCompleted(WebBrowserDocumentCompletedEventArgs e)
        {
            return Parent.ReadyState == WebBrowserReadyState.Complete && e.Url == Parent.Url;
        }

        protected void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null) PropertyChanged(this, e);
        }

        public void OnNavigating(WebBrowserNavigatingEventArgs e)
        {
            if (!e.Cancel) NavigatingCalled = true;
            UpdateIsSafeNavigating();
        }

        public void OnNavigated(WebBrowserNavigatedEventArgs e)
        {
            NavigatingCalled = false;
            AccumulatedNavigations++;
            UpdateIsSafeNavigating();
        }

        public void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
        {
            NavigatingCalled = false;
            AccumulatedNavigations--;
            if (AccumulatedNavigations < 0) AccumulatedNavigations = 0;
            if (IsMainFrameCompleted(e)) AccumulatedNavigations = 0;
            UpdateIsSafeNavigating();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SafeWebBrowser继承WebBrowser.方法OnNavigating,OnNavigatedOnDocumentCompleted在相应的WebBrowser重写方法上调用.该物业IsSafeNavigating是让我知道它是否正在导航的物业.

Laj*_*pad 0

首先,我将文档转换为 XML,然后使用我的神奇方法:

    nodeXML = HtmlToXml.ConvertToXmlDocument((IHTMLDocument2)htmlDoc.DomDocument);
    if (ExitWait(false))
        return false;
Run Code Online (Sandbox Code Playgroud)

转换:

public static XmlNode ConvertToXmlDocument(IHTMLDocument2 doc2)
{
    XmlDocument xmlDoc = new XmlDocument();
    IHTMLDOMNode htmlNodeHTML = null;
    XmlNode xmlNodeHTML = null;

    try
    {
        htmlNodeHTML = (IHTMLDOMNode)((IHTMLDocument3)doc2).documentElement;
        xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", ""/*((IHTMLDocument2)htmlDoc.DomDocument).charset*/, ""));
        xmlNodeHTML = xmlDoc.CreateElement("html"); // create root node
        xmlDoc.AppendChild(xmlNodeHTML);
        CopyNodes(xmlDoc, xmlNodeHTML, htmlNodeHTML);
    }
    catch (Exception err)
    {
        Utils.WriteLog(err, "Html2Xml.ConvertToXmlDocument");
    }
Run Code Online (Sandbox Code Playgroud)

魔术方法:

private bool ExitWait(bool bDelay)
{
    if (m_bStopped)
        return true;
    if (bDelay)
    {
        DateTime now = DateTime.Now;
        DateTime later = DateTime.Now;
        TimeSpan difT = (later - now);
        while (difT.TotalMilliseconds < MainDef.IE_PARSER_DELAY)
        {
            Application.DoEvents();
            System.Threading.Thread.Sleep(10);
            later = DateTime.Now;
            difT = later - now;
            if (m_bStopped)
                return true;
        }
    }
    return m_bStopped;
}
Run Code Online (Sandbox Code Playgroud)

其中 m_bStopped 默认为 false,IE_PARSER_DELAY 是超时值。我希望这有帮助。