IEwebbrowser中老生常谈的话题。
一般的解决都是通过
// webBrowser.Navigating += WebBrowser_Navigating; 注册转跳前事件 private void WebBrowser_Navigating(object sender, System.Windows.Forms.WebBrowserNavigatingEventArgs e) { webBrowser.Navigate("新的网页地址"); }
但是并不是特别的好用
正确的用法是通过AxHost类。
好在是C# 4.72开源了。不用反编译了。 有些东西也好解释了开源地址
搜索Webbrowser查看源代码,你会发现。很多功能都是由一个叫做AxWebbrowser的类是实现的。
很明显,webbrowser大部分都是Com控件的包装。
但是能够将地址强制在一个网页的打开的地方在于这里
找到Navigate
我们继续深挖
private void PerformNavigateHelper(string urlString, bool newWindow, string targetFrameName, byte[] postData, string headers) { object objUrlString = (object)urlString; object objFlags = (object) (newWindow ? 1 : 0); object objTargetFrameName = (object)targetFrameName; object objPostData = (object)postData; object objHeaders = (object)headers; PerformNavigate2(ref objUrlString, ref objFlags, ref objTargetFrameName, ref objPostData, ref objHeaders); } private void PerformNavigate2(ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers) { try { this.AxIWebBrowser2.Navigate2(ref URL, ref flags, ref targetFrameName, ref postData, ref headers); } catch (COMException ce) { if ((uint)unchecked(ce.ErrorCode) != (uint)unchecked(0x800704c7)) { // "the operation was canceled by the user" - navigation failed // ignore this error, IE has already alerted the user. throw; } } }
跳转都是用一个方法。
最终实现的是一个叫做PerformNaviagate2内的AxIWebbrowser2所实现的
继续深挖
最后发现在一个名为UnsafeNativeMethods的类中
这个类是用来做什么呢?
是实现win32API和COM的。(说句心里话写桌面软件,微软心里面还是C++是亲儿子。多少懂一些C++没有错。)
[DispId(500)] void Navigate2([In] ref object URL, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
我们知道具体的实现方法了。但是我们还是无法完成我想要的东西。
因为我们不知道何时经行处理或者Webbrowser会跳转。
所以我们重新回到了Webbrowser 了
我们发现Webbrowser继承了WebbroweserBase
重点是
/// <include file='doc\WebBrowserBase.uex' path='docs/doc[@for="WebBrowserBase.CreateSink"]/*' /> /// <devdoc> /// <para> /// This will be called when we are ready to start listening to events. /// Inheritors can override this method to hook their own connection points. /// </para> /// </devdoc> protected virtual void CreateSink() { }
百度翻译了一下
哈,找到了我们该如何触发事件的地方了。
很明显子类肯定要重写这个方法。重新到Webbrowser寻找这个方法
protected override void CreateSink() { object ax = this.activeXInstance; if (ax != null) { webBrowserEvent = new WebBrowserEvent(this); webBrowserEvent.AllowNavigation = AllowNavigation; this.cookie = new AxHost.ConnectionPointCookie(ax, webBrowserEvent, typeof(UnsafeNativeMethods.DWebBrowserEvents2)); } }
事情到这里已经很明显了
this.cookie = new AxHost.ConnectionPointCookie(ax, webBrowserEvent, typeof(UnsafeNativeMethods.DWebBrowserEvents2));