How come HTMLDocumentEvent onclick fires up multiple times?
I am using Visual C# Express 2010 (.NET Framework 4.0), Windows 7 32bit.
I created WinForm project which only has WebBrowser control and ListItem object that displays the html information by onclick event.
My goal is to run the project and click text field in web site in the webbrowser control and display the html document info that has been clicked (such as text field tag etc)
code
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
The problem is while it works, the ListItem object displays same output generated by ClickEventHandler. For instance, if I go to www.google.com and just mouse click into the search text field, the output is:
----- ClickEventHandler ---------
click: INPUT <INPUT style=.....
----- ClickEventHandler ---------
click: INPUT <INPUT style=.....
----- ClickEventHandler ---------
click: INPUT <INPUT style=.....
and so on. The click events are fired multiple times.
I've followed the example here: http://support.microsoft.com/kb/312777
I was thinking myBrowser_DocumentCompleted() is called multiple times somehow and adding same event handlers in the line,
iEvent.onclick += new HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
But HTMLDocumentEvents2_Event method like onclick() only accept with += or -= so I can't really change this line.
Has anyone encountered this?
UPDATE
Figured that the webbrowser control URL is initially set to www.msn.com
and when the project is run, documentCompleted event is called once which adds click event handler.
Then FormLoad() event which navigate to another URL that adds click event handler.
So now 2 click event handlers exists.
Plus, every time I go to different URL, somehow click event handlers are being added.
So I'm pretty sure inside of documentCompleted() event
, iEvent is not properly cleared. (by looking at code, it is initialized per documentComp开发者_JAVA技巧leted() event so it shouldn't have this behavior though...)
After spent some time, I figured that each time the page is reloaded regardless to which URL, documentCompleted() event is triggered and same clickEvent() is added to iEvent.
The workaround is to check if doc is null.
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);
}
}
I'm not convinced this is the best solution but for now this works. (though still not sure why it was adding the clickEvent
even though iEvent
is re-initialized per documentCompleted()
call.
Debug it, set a breakpoint on the event handler. This is otherwise likely, although I couldn't repro with the web site in your question. DocumentCompleted fires for each frame in the web page, there might be more than one. Short from using a bool field to track that you already subscribed the event, you could also filter out frames like this:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
if (e.Url != webBrowser1.Url) return;
// etc..
}
精彩评论