我使用的是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()事件初始化的,所以它不应该有这种行为虽然......)
答案 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
的原因,即使iEvent
每documentCompleted()
次调用已重新初始化。
答案 1 :(得分:2)
调试它,在事件处理程序上设置断点。这可能是其他情况,尽管我无法在您的问题中重新使用该网站。 DocumentCompleted为网页中的每个帧触发,可能有多个。除了使用bool字段跟踪您已经订阅了该事件之外,您还可以过滤掉这样的帧:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
if (e.Url != webBrowser1.Url) return;
// etc..
}