强制所有网页链接在同一页面打开或者TabControl

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));

猜你喜欢

转载自www.cnblogs.com/T-ARF/p/9428121.html