UMPLatForm.NET MiNiWeb浏览器核心技术详解一

 

目录

1  简介2  目标、挑战和解决方案

l  捕捉脚本错误

l  过滤弹出窗口

l  添加多标签页或多窗口浏览功能

l  当一个窗口是由脚本关闭时,需要确认

3  创建webbrowser扩展控件

l  实现 iwebbrowser2接口

l  实现 dwebbrowserevents2接口

4  使用该扩展控件

l  捕捉脚本错误

l  过滤弹出窗口并添加多标签页或多窗口浏览功能

l  使用退出事件 

平台内置MiNiWeb浏览器如下图所示:

UMPLatForm.NET 中MiNiWeb浏览器核心技术详解一_第1张图片

 1简介

            .net 2.0system.windows.forms命名空间中新增了webbrowser控件,该控件本身是非常有用的,但是它没有提供在某些情况下需要的事件。这篇文章描述了如何扩展webbrowser控件并增加一些功能,例如:屏蔽弹出窗口、捕捉脚本错误以及捕捉新窗口并将其显示在多标签浏览窗口环境中。
       在扩展webbrowser控件时,某些功能没有写入.net framework的帮助文件,不用理会“这个方法是用于支持.net基础架构的,不推荐直接用于您的代码中”的提示信息,我们可以创建一个实现iwebbrowser2接口的对象,并使用浏览器对象的全部功能,此外,使用dwebbrowserevents2接口可以向控件中添加事件。

      我们假设你已经了解了iwebbrowser2接口和dwebbrowserevents2接口,对com的互操作和相关的接口知识也是需要了解的。

2、目标、挑战和解决方案

这个组件要实现的目标是:

l  用简洁的方式捕捉脚本错误

l  过滤弹出窗口

l  加入多标签页浏览或多窗口浏览功能

l  当窗口被脚本关闭时需要确认

       这一节简要讲解实现这些目标所碰到的问题和相关的解决方案,下一节中会给出更多的代码细节。

捕捉脚本错误

       webbrowser控件有一个scripterrorsuppressed属性,将这个属性设置为true时,该控件确实会比原来多做了一点事情,它不仅禁用了脚本出错的对话框,而且还禁用了登陆到需要用户证书的安全站点时出现的登陆对话框。但是假如我们仍然需要这个功能,或者我们想获得脚本出错的通知,或者我们想知道全部的脚本出错的细节时该怎么办呢?

       脚本错误可以在htmlwindow.error事件中捕捉,这个事件会在脚本发生错误时触发并包含全部的错误细节信息,但是难点在于htmlwindow是需要通过htmldocument对象才能访问,而该对象并不是什么时候都有效,htmldocument对象只在navigated事件触发时才有效,而假如用户是按f5键刷新浏览器时呢,抱歉,navigated事件是不会触发的。在经过了很多的尝试后,我发现唯一可行的方法是使用并不是默认webbrowser控件一部分的downloadcomplete事件。

 解决方案:

1.       实现dwebbrowserevents接口

2.       创建一个downloadcomplete事件

3.       downloadcomplete事件触发时,订阅htmlwindow.error事件

4.       利用这个error事件来获得脚本出错的具体信息

5.       设置handled属性为true来阻止脚本出错

 过滤弹出窗口

       弹出窗口大部分情况都是不怎么受欢迎的或者是不适宜的,屏蔽这些弹出窗口需要一些额外的信息。当用户使用windows xp sp2或者windows 2003 sp1 或更高版本时,newwindow3事件可以提供这些辅助信息,假如这个事件没有触发,那么newwindows2事件会替代该事件。当newwindow3事件触发时,你可以检查以下内容:

l  是否是用户的操作才导致了新开窗口

l  用户是否按住了覆盖键(ctrl 键)

l  是否因为当一个窗口正在关闭才导致显示弹出窗口

l  获得将要打开窗口的url地址

l  更多...

     使用newwindows3事件可以很明显的实现这个目的,假如要使用这个事件,就必须实现dwebbrowserevents2接口。

 解决方案:

1.     实现dwebbrowserevents2接口

2.     创建一个新的事件和一个新的事件参数类

3.     执行这个事件并附带适当的信息

4.     当这个事件触发后,检查这次的导航是否需要取消

 添加多标签页或多窗口浏览功能

       多标签页方式浏览在目前似乎变得越来越流行,例如在ie7中,这就是一个新增功能。实现多标签页方式浏览的难点是,你需要在当脚本或者超链接创建一个新窗口的时候去创建相应的新的标签页或子窗口,除此之外,还需要解析出多窗口或者多标签页的窗口名称。(例如:)要实现这一点,一些自动化对象(如:newwindowx事件中的ppdispiwebbrowser2接口中的application)就需要从新开窗口传回到该事件中。而访问application属性需要获得iwebbrowser2接口的引用。 

解决方案:

1.       重载attachinterfacesdetachinterfaces接口

2.       保存iwebbrowser2接口对象的引用

3.       创建一个application属性来暴露该接口中的application属性

4.       实现dwebbrowserevent2接口

5.       监听newwindows2/newwindow3事件

6.       当一个事件触发时,创建一个新的browser控件的实例

7.       ppdisp事件参数指派给新实例的application属性          

 当一个窗口被脚本关闭时需要确认

       当你在jscript中调用window.close()方法,webbrowser控件很可能出现假死。因为某种原因,他不能用于导航页面,也不能做其他任何事情。假如我们知道它什么时候发生可能会好一些。当它发生时会触发一系列的事件,但是这些事件没有给我们需要的信息。重载wndproc方法并检测父窗口是否通知该浏览器已经被销毁是唯一可行的解决方法(假如谁知道如何得到windowsclosing事件来实现这一点是更好的方法)

 解决方案:

1.       重载wndproc方法

2.       检查wm_parentnotify消息

3.       检查wm_destriy参数

4.       假如检测到了上述的内容,则触发一个新的事件(这个事件在例子中称为quit