为什么HTMLDocumentEvent onclick多次激活?

时间:2011-03-23 01:57:07

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

我使用的是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事件一次,这会添加点击事件处理程序。

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

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

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

所以我非常确定documentCompleted() event内部, iEvent未正确清除。(通过查看代码,它是根据documentCompleted()事件初始化的,所以它不应该有这种行为虽然......)

2 个答案:

答案 0 :(得分:6)

花了一些时间之后,我想每次重新加载页面而不管是哪个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的原因,即使iEventdocumentCompleted()次调用已重新初始化。

答案 1 :(得分:2)

调试它,在事件处理程序上设置断点。这可能是其他情况,尽管我无法在您的问题中重新使用该网站。 DocumentCompleted为网页中的每个帧触发,可能有多个。除了使用bool字段跟踪您已经订阅了该事件之外,您还可以过滤掉这样的帧:

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