【问题标题】:How come HTMLDocumentEvent onclick fires up multiple times?HTMLDocumentEvent onclick 怎么会触发多次?
【发布时间】:2011-07-20 23:28:30
【问题描述】:

我正在使用 Visual C# Express 2010 (.NET Framework 4.0),Windows 7 32 位。

我创建的 WinForm 项目只有 WebBrowser 控件和 ListItem 对象,通过 onclick 事件显示 html 信息。

我的目标是运行项目并在 webbrowser 控件中单击网站中的文本字段并显示已单击的 html 文档信息(例如文本字段标签等)

代码

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        private mshtml.HTMLDocument doc = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        object oUrl = "http://livemocha.com/";
        object oEmpty = "";
        myBrowser.Navigate(oUrl.ToString());

        }


        private void myBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            try
            {
                doc = (mshtml.HTMLDocument)myBrowser.Document.DomDocument;
                mshtml.HTMLDocumentEvents2_Event iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;

                iEvent.onclick += new HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);

            }
            catch (UnauthorizedAccessException err)
            {
                Console.WriteLine("OOPS: " + err);
            }

        }

        //event handler when user clicks mouse
        //and just display info such as html tag and its attributes
        private bool ClickEventHandler(mshtml.IHTMLEventObj e) 
        {
            actionList.Items.Add("------- ClickEventHandler -----------");

            actionList.Items.Add(e.type + " : " + e.srcElement.tagName + " : " + e.srcElement.outerHTML + " : " + e.srcElement.innerText + " : " + e.srcElement.id);

            return true;
        }
    }//end class
}//end namespace

问题在于,当它工作时,ListItem 对象显示由 ClickEventHandler 生成的相同输出。例如,如果我访问 www.google.com 并在搜索文本字段中单击鼠标,则输出为:

----- ClickEventHandler ---------
click: INPUT <INPUT style=.....
----- ClickEventHandler ---------
click: INPUT <INPUT style=.....
----- ClickEventHandler ---------
click: INPUT <INPUT style=.....

等等。点击事件被触发多次。

我已按照此处的示例进行操作: http://support.microsoft.com/kb/312777

我在想 myBrowser_DocumentCompleted() 以某种方式被多次调用并在行中添加相同的事件处理程序,

 iEvent.onclick += new HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);

但是像 onclick() 这样的 HTMLDocumentEvents2_Event 方法只接受 +=-= 所以我不能真正改变这一行。

有人遇到过吗?

更新

认为 webbrowser 控件 URL 最初设置为 www.msn.com,并且当项目运行时,documentCompleted 事件被调用一次,它添加了点击事件处理程序。

然后是 FormLoad() 事件,该事件导航到另一个添加点击事件处理程序的 URL。

所以现在存在 2 个单击事件处理程序。

另外,每次我访问不同的 URL 时,都会以某种方式添加点击事件处理程序。

所以我很确定在 documentCompleted() event 内部,iEvent 没有被正确清除。(通过查看代码,它是按 documentCompleted() 事件初始化的,所以它不应该有这种行为不过……)

【问题讨论】:

  • 看起来这个导航到另一个站点的 form_load 可能正在添加重复的事件处理程序...?
  • 想通了,首先,将我引导到另一个站点的 form_load 正在添加重复的点击事件处理程序。但即使没有它,它仍然会添加事件处理程序,因为文档完成事件处理程序内部有一些东西不正确。看起来代码还可以..hmm

标签: c# .net webbrowser-control event-handling


【解决方案1】:

花了一些时间后,我发现每次重新加载页面时,无论是哪个 URL,都会触发 documentCompleted() 事件并将相同的 clickEvent() 添加到 iEvent。

解决方法是检查 doc 是否为空。

private void myBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            try
            {
                if (doc == null)
                {
                    doc = (mshtml.HTMLDocument)myBrowser.Document.DomDocument;
                    mshtml.HTMLDocumentEvents2_Event iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;

                    iEvent.onclick += new HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
                    iEvent.onkeypress += new HTMLDocumentEvents2_onkeypressEventHandler(KeyStrokeEventHandler);
                } 
            }
            catch (UnauthorizedAccessException err)
            {
                Console.WriteLine("OOPS: " + err);
            }
        }

我不相信这是最好的解决方案,但目前可行。 (尽管仍然不确定为什么要添加 clickEvent,即使 iEvent 已根据 documentCompleted() 调用重新初始化。

【讨论】:

  • 感谢您发布此信息。我在其他代码示例中看到过 null 检查,但不知道为什么会出现。
  • 相当老的线程,但@masato-san 谢谢。我花了几个小时研究同一个问题(C++)。由于存在多个帧(或 dhtml),一旦“某些”内容准备好显示,就会多次触发 DocumentComplete。因此,在 DocumentComplete 中订阅的更多事件像疯了一样成倍增加:)
【解决方案2】:

调试它,在事件处理程序上设置断点。否则,这是可能的,尽管我无法在您的问题中使用该网站进行复制。 DocumentCompleted 为网页中的每一帧触发,可能不止一个。除了使用 bool 字段来跟踪您已经订阅了该事件之外,您还可以像这样过滤掉帧:

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
        if (e.Url != webBrowser1.Url) return;
        // etc..
    }

【讨论】:

  • 我不熟悉调试器,但是当我使用它时,每次触发 documentCompleted() 时,iEvent 首先设置为 null 直到它被分配,所以它不应该添加重复的点击事件。 . 嗯我也试试过滤
猜你喜欢
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多