原文:【WPF】监听WPF的WebBrowser控件弹出新窗口的事件

WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗口的,那么它会生生的弹出一个IE窗口来,而不是在内部跳到该链接。

如果使用Winform的WebBrowser控件,我们可以监听它的NewWindow事件,在这个事件中做一些处理,例如,在新建一个Tab来打开,或者控制它在当前WebBrowser中跳转。很不幸的是,WPF的WebBrowser没有这个事件。

说到底,Winform的WB或者是WPF的WB都是在调用IE的一个控件,因此,Winform能加上的,我们WPF一定也有办法加上。如此,那我们就请出神器Reflector,研究一把。

首先,我们打开Winform的WebBrowser,找到触发NewWindow事件的代码:

protectedvirtualvoidOnNewWindow(CancelEventArgs e)

{if(this.NewWindow!=null)

{this.NewWindow(this, e);

}

}

它是在OnNewWindow方法中触发的。那么,是谁调用了这个OnNewWindow呢?接着搜索,最后在一个叫WebBrowserEvent的类里面发现这么一段:

publicvoidNewWindow2(refobjectppDisp,refboolcancel)

{

CancelEventArgs e=newCancelEventArgs();this.parent.OnNewWindow(e);

cancel=e.Cancel;

}

我们接着搜NewWindow2,却发现没有地方显式地调用它了。既然从方法入手没找到,那我们就来研究一下定义这个方法的WebBrowserEvent,看看是谁在使用它。

仔细搜索一遍,最后发现在WebBrowser的CreateSink方法中有这么一段:

代码

protectedoverridevoidCreateSink()

{objectactiveXInstance=base.activeXInstance;if(activeXInstance!=null)

{this.webBrowserEvent=newWebBrowserEvent(this);this.webBrowserEvent.AllowNavigation=this.AllowNavigation;this.cookie=newAxHost.ConnectionPointCookie(activeXInstance,this.webBrowserEvent,typeof(UnsafeNativeMethods.DWebBrowserEvents2));

}

}

注意这句话:

this.cookie = new AxHost.ConnectionPointCookie(activeXInstance, this.webBrowserEvent, typeof(UnsafeNativeMethods.DWebBrowserEvents2));

很显然,这句话是关键。AxHost.ConnectionPointCookie类的作用是:“将一个ActiveX 控件连接到处理该控件的事件的客户端”。

上面的调用中有一个很奇怪的类型:DWebBrowserEvents2,熟悉COM的童鞋应该马上能想到,这其实是一个COM类型的定义。

代码

[ComImport, TypeLibType(TypeLibTypeFlags.FHidden), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]publicinterfaceDWebBrowserEvents2{......}

实际上,我们再去看WebBrowserEvent的定义,它恰恰是实现了这个接口的。

[ClassInterface(ClassInterfaceType.None)]privateclassWebBrowserEvent : StandardOleMarshalObject, UnsafeNativeMethods.DWebBrowserEvents2{......}

因此,上面这句话不难理解,就是定义一个实现了特定COM接口的类型,让浏览器控件的事件能够转发到这个类型实例去处理。因此,NewWindow2其实是浏览器控件去调用的。

Winform的WebBrowser我们搞清楚了,下面我们来看WPF的。其实,打开WPF的WebBrowser代码之后,我们会发现它跟Winform的WebBrowser机制是一样的。一个似曾相识的CreateSink方法映入眼中:

代码

[SecurityTreatAsSafe, SecurityCritical]internaloverridevoidCreateSink()

{this._cookie=newConnectionPointCookie(this._axIWebBrowser2,this._hostingAdaptor.CreateEventSink(),typeof(UnsafeNativeMethods.DWebBrowserEvents2));

}

这儿也有一个ConnectionPointCookie,但是它的访问权限是internal的:(

第二个参数,_hostingAdapter.CreateEventSink返回的是什么呢:

代码

[SecurityCritical]internalvirtualobjectCreateEventSink()

{returnnewWebBrowserEvent(this._webBrowser);

}

[ClassInterface(ClassInterfaceType.None)]internalclassWebBrowserEvent : InternalDispatchObject, UnsafeNativeMethods.DWebBrowserEvents2

{

......

}

仍然是一个WebBrowserEvent!悲剧的是,这个WPF的WebBrowserEvent,并没有触发NewWindowEvent:

publicvoidNewWindow2(refobjectppDisp,refboolcancel)

{

}

现在知道为什么WPF的WB控件没有NewWindow事件了吧?微软的童鞋压根儿就没写!

既然微软的童鞋不写,那我们就自己折腾一把,反正原理已经搞清楚了。

首先,我们也得定义一个DWebBrowserEvents2接口,这个我们直接通过Reflector复制一份就好了。代码就不贴上来了。

接着,我们再仿造一个WebBrowserEvent,关键是要触发NewWindow事件:

代码

publicpartialclassWebBrowserHelper{privateclassWebBrowserEvent : StandardOleMarshalObject, DWebBrowserEvents2{privateWebBrowserHelper _helperInstance=null;publicWebBrowserEvent(WebBrowserHelper helperInstance){_helperInstance=helperInstance;}......publicvoidNewWindow2(refobjectpDisp,refboolcancel){_helperInstance.OnNewWindow(refcancel);}......}}

最后,我们需要仿造Framework中的代码,也来CreateSink一把(我承认,用了反射来取WebBrowser内部的东东,谁让这些类型都是internal的呢):

代码

privatevoidAttach(){var axIWebBrowser2=_webBrowser.ReflectGetProperty("AxIWebBrowser2");var webBrowserEvent=newWebBrowserEvent(this);var cookieType=typeof(WebBrowser).Assembly.GetType("MS.Internal.Controls.ConnectionPointCookie");_cookie=Activator.CreateInstance(cookieType,ReflectionService.BindingFlags,null,new[] { axIWebBrowser2, webBrowserEvent,typeof(DWebBrowserEvents2) },CultureInfo.CurrentUICulture);}

最后的使用:

var webBrowserHelper=newWebBrowserHelper(webBrowser);

......

webBrowserHelper.NewWindow+=WebBrowserOnNewWindow;

【效果图】

初始网页:

点击一个链接,默认情况下,将是弹出一个IE窗口,现在是在新的Tab中打开:

【示例代码】

(新建按钮点击后,请输入完整的网址,例如:http://www.sina.com)

wpf 监听退出事件_【WPF】监听WPF的WebBrowser控件弹出新窗口的事件相关推荐

  1. 【WPF】监听WPF的WebBrowser控件弹出新窗口的事件

    WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗口的,那么它会生生的弹出一个IE窗口来,而不是在内部跳到该链接. 如果 ...

  2. Android 点击事件,如何在界面上或者某个控件上添加点击事件

    说到点击事件,第一印象 setOnClickListener() 方法,这也是用的最多的控件点击事件方法,这篇文章不分享这个方法,使用该方法的前提是你要拿到这个控件的 View 才可以调用这个方法 通 ...

  3. vb检测html事件,VB代码VB小程序:捕获 WebBrowser 控件的鼠标事件

    49. 捕获 WebBrowser 控件的鼠标事件 VB 的网页浏览控件 WebBrowser 没有 MouseDown.MouseMove.MouseUp 等鼠标事件,要在程序中捕获这些事件,必须另 ...

  4. pb调用计算机默认游览器,PB打开ole控件IE浏览器版本问题_指定Webbrowser控件所用IE内核版本(转)...

    如果电脑上安装了IE8或者之后版本的IE浏览器,Webbrowser控件会使用IE7兼容模式来显示网页内容.解决方法是在注册表中为你的进程指定引用IE的版本号. 比如我的程序叫做a.exe 对于32位 ...

  5. WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件

    原文:WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件 版权声明:本文为博主原创文章,需要转载尽管转载. https://blog.csdn.net/z ...

  6. 在WPF的WebBrowser控件中抑制脚本错误

    在WPF的WebBrowser控件中抑制脚本错误 原文:在WPF的WebBrowser控件中抑制脚本错误 今天用WPF的WebBrowser控件的时候,发现其竟然没有ScriptErrorsSuppr ...

  7. WebBrowser控件的常用方法、属性和事件

    1. 属性 属性 说明 Application 如果该对象有效,则返回掌管WebBrowser控件的应用程序实现的自动化对象(IDispatch).如果在宿主对象中自动化对象无效,这个程序将返回Web ...

  8. 一个WinForm记事本程序(包含主/下拉/弹出菜单/打开文件/保存文件/打印/页面设置/字体/颜色对话框/剪切版操作等等控件用法以及记事本菜单事件/按键事件的具体代码)...

    (一).说明 功能类似Windows 操作系统自带的记事本.  一个WinForm记事本程序(包含主/下拉/弹出 菜单/打开保存对话框等控件用法以及记事本菜单事件的具体代码) (二).图片示例 (三) ...

  9. ajax获取单选按钮的值_【自学C#】|| 笔记 31 控件,按钮

    一.Button:按钮控件 按钮主要用于提交页面的内容,或者是确认某种操作等.     按钮常用的属性包括在按钮中显示的文字 (Text) 以及按钮外观设置的属性,最常用的事件是单击事件. 1.例: ...

  10. 谨慎注意WebBrowser控件的DocumentCompleted事件

    引言 WebBrowser控件的DocumentCompleted事件一般就被认定为是在页面完全加载完毕后产生,而注释中也是这么写的: 但事实却并非如此. 首先它不一定会在完全加载完毕时才触发,有时就 ...

最新文章

  1. numpy使用[]语法索引二维numpy数组中指定数据列的数值内容(accessing the specific column in numpy array)
  2. 4 流程控制》4.5 比较for循环和while循环
  3. Asp.Net生命周期系列一
  4. Nhibernate3.3.3 GA使用初探
  5. 超几何分布_概率小题——分布列专题
  6. php和js哪个更像C语言,js和php存在着什么区别
  7. 未能加载文件或程序集 CrystalDecisions.Web Version=10.2.3600解决方法
  8. AJAX核心对象-- XMLHttpRequest 对象使用详解 (一)
  9. HDU 1269 裸奔的强联通分量
  10. 高品质深圳市地图shp数据arcgis软件道路地名县区边界水系地铁站点2021年
  11. [沈航软工教学] 学生项目Coding地址汇总
  12. 【教3妹学算法-每日3题(2)】分割字符串的最大得分
  13. 青春对白,邮寄我的时光
  14. 开源项目之:SharpDevelop
  15. 鬼谷八荒逆天改命修改教程(3月亲测有效)
  16. 【金融项目】尚融宝项目(十五)
  17. 官场直升机 鸿蒙笔著,担当:老衲笔尖无墨水,要从空处想鸿蒙
  18. 电信卡 LTE 无法短信发送
  19. 隐藏应用计算机器的密码,隐私计算器:将你的密码隐藏在一个工作的计算器中...
  20. 她26岁成中科大博导:我是工作上灭绝师太,生活中女汉子

热门文章

  1. 声音均衡器怎么调好听_均衡器调节(人声处理)
  2. PHP:pack、unpack用法大全
  3. (杂谈二) 看看别人是怎么写程序的(程序员的自我修养)
  4. Linux救援(rescue)模式知识点
  5. HTML基础之 小白入门
  6. 《Java编程思想第五章》:初始化与内存
  7. 微信公众号推广分享二维码,关联扫码关注的客户
  8. 服务器智能阵列,HPE ProLiant Gen10 服务器智能阵列卡S100i SR Gen10 BIOS下开启阵列功能配置阵列并安装win2016系统...
  9. 什么电子邮箱最安全,什么邮箱更具私密性?
  10. 星际迷航4之抢救未来