为WebBrowser的WEB页的Document注册事件的问题
当使用WebBrowser,并对其装载的Web页建立Document的事件后,WebBrowser里的页面元素都变得难于操作了,只响应建立的连接事件。有兴趣的朋友可以在您的代码中使用以下的代码来建立事件:
本文相关代码如下:
// 在WebBrowser的DocumentComplete中写下面的代码。
IHTMLDocument2 m_pHtmlDoc2 = (IHTMLDocument2)ChatInfoWebBrowser.Document;
HTMLDocumentEvents2_Event iEvent = (HTMLDocumentEvents2_Event)m_pHtmlDoc2;
iEvent.oncontextmenu += new HTMLDocumentEvents2_oncontextmenuEventHandler(ContextMenuEventHandler);
// 事件处理函数,目的,不使用WebBrowser自己的菜单。
private bool ContextMenuEventHandler(IHTMLEventObj e)
{
MessageBox.Show("ContextMenuEventHanderl");
return false;
}
你可以在WebBrowser中打开一个百度的页面,那么,在上面的代码加入后,你会发现,不能操作百度页面上的任何元素,你眼睁睁的看着编辑框中有了焦点,可是,就算你拿锤子敲键盘,编辑框也没有输入任何字符。呵呵,实在是太奇怪的问题了。
然后就到google上狂搜一通,我的上帝,那么多英文的材料让我头瞬间有2个大,没办法,硬着头皮上了。遇到这种问题的人还真不少,可是,都没有给出解答,后来,看多了,一句话印象深刻,那就是“这是一个公开的bug”,我不知道这时不时bug,毕竟微软官方没有明确说明这是bug,所以,我不敢确认。但是,为什么会出现这样的情况呢?
一篇文章的作者解释说,当WebBrowser监视了事件后,页面元素将不会接收到事件了,因为Web的DocumentEvent已经被注册了,只要一个事件被注册,WebBrowser就把所有的事件都接受过来,如果我们没有写对应事件的代码,那就忽略掉该事件。
那么,因为我以前一直用VC写程序,在实现这样的功能时并没有出现这种情况,因为使用的是同一个Dll,所以,我有理由怀疑是VS在C#环境下注册该Dll的引用的时候,可能在转换方面出现了某个致命的问题,导致了并没有释放对DocumentEvent的使用权。所以,可以理解成是一个bug吧。
废话不多说了,给出该问题的解决方法吧。
那就是,我们不使用DocumentEvent来实现我们的功能,不去实现C#转换过来的接口。
OK,请在您的程序中新建一个CS文件,然后把下面的代码复制上去,当然,命名空间随便您改。
本文相关代码如下:
/// programer : ricky
/// DataTime : 2007-04-16 15:49
/// Rights : Nanjing Desunsoft CO.,LTD
using System;
using mshtml;
using System.Runtime.InteropServices ;
namespace SimTrade4.ChatRoom
{
/// <summary>
/// WebBrowserDocument事件。
/// </summary>
public delegate void DHTMLEvent(IHTMLEventObj e);
/// <summary>
/// WebBrowser事件处理类。
/// </summary>
public class CHTMLEventHandler
{
/// <summary>
/// DHTMLEvent事件。
/// </summary>
public DHTMLEvent m_DHTMLEventHandler;
/// <summary>
/// HTMLDocument对象。
/// </summary>
private HTMLDocument m_Document;
/// <summary>
/// 构造函数。
/// </summary>
public CHTMLEventHandler(HTMLDocument doc)
{
m_Document = doc;
}
/// <summary>
/// DispId不能省略,它是Com自动化的重要步骤,所以,当事件触发后,就会
/// 自动调用该函数。
/// </summary>
[DispId(0)]
public void FireEvent()
{
m_DHTMLEventHandler(m_Document.parentWindow.@event);
}
}
}
然后用下面的方式进行调用:
本文相关代码如下:
private void axWebBrowser_DocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
{
HTMLDocument m_pHtmlDoc2 = (HTMLDocument)axWebBrowser.Document;
if (m_pHtmlDoc2 != null)
{
// 注册上下文事件。
CHTMLEventHandler ContextMenuDHandler = new CHTMLEventHandler(m_pHtmlDoc2);
ContextMenuDHandler.m_DHTMLEventHandler += new DHTMLEvent(ContextMenuEventHandler);
m_pHtmlDoc2.oncontextmenu = ContextMenuDHandler;
}
}
private void ContextMenuEventHandler(IHTMLEventObj e)
{
e.returnValue = false; // 这样就不会弹出IE菜单了,返回ture就会了。
}
OK,如果要添加别的事件,比如说单击,可以像下面一样使用:
本文相关代码如下:
// 注册单击事件。
CHTMLEventHandler ClickDHandler = new CHTMLEventHandler(m_pHtmlDoc2);
ClickDHandler.m_DHTMLEventHandler += new DHTMLEvent(ClickEventHandler);
m_pHtmlDoc2.onclick = ClickDHandler;
也就说,如果监视一个事件,就要new 一个 CHTMLEventHandler,OK,这个问题就告一段落了,终于可以继续做自己的项目了。希望今天写的对大家有所帮助。