<=======================
作者: 谭剑
博客: http://hi.baidu.com/tanjian
关键字:C#,.NET,WebBrowser,ExtendedWebBrowser,浏览器,完全载入,新窗口,脚本
=======================>
.NET 2.0 提供了一个新的WebBrowser控件.该WebBrowser控件为我们带来了许多非常实用的新特性.举个简单的例子:
            HtmlDocument htmlDoc = webBrowser.Document;
            HtmlElement btnElement = htmlDoc.All["btnClose"];
            if (btnElement != null)
            {
                btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
            }
仅需类似这样简单易懂的几行代码,便可实现Windows Forms对Web页面各个HTML元素各种事件的响应.
在Windows Forms与Web页面交互这方面,在功能与易用性上,该WebBrowser控件达到了一个前所未有的高度.这样的特性,就已经为我们在进行相关的Windows Forms程序开发时选用它提供了足够的理由.
很显然,WebBrowser控件是对SHDocVw的AxWebBrowser这个非托管的ActiveX控件进行了封装.但是在实用中,我们很快可以发现,其在提供新特性的同时,并没有全部暴露出AxWebBrowser原有的属性和方法,在很多情况下,这样就使得它显得有点捉襟见肘了.
jlandheer对这个WebBrowser控件进行了扩展(见Extended .NET 2.0 WebBrowser Control).但是该ExtendedWebBrowser也仅仅是提供了一个结构和思路,真正实现的扩展也比较有限.
根据实际的需要,我又对ExtendedWebBrowser进行了再扩展.
判断页面是否完全载入:
1.新增DocumentCompleted事件:
在类ExtendedWebBrowser里面事件部分的末尾添加如下代码:
        public new event EventHandler<BrowserExtendedNavigatingEventArgs> DocumentCompleted;
        protected void OnDocumentCompleted(BrowserExtendedNavigatingEventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");
if (this.DocumentCompleted != null)
                this.DocumentCompleted(this, e);
        }
2.实现public void DocumentComplete(object pDisp, ref object URL)方法:
 在文件ExtendedWebBrowser.cs class WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2 的 Unused events区域里面可以找到未实现的方法:
            public void DocumentComplete(object pDisp, ref object URL)
            {
            }
将其剪贴到已实现的方法部分的末尾,并修改为:
            public void DocumentComplete(object pDisp, ref object URL)
            {
                BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(pDisp, new Uri(URL.ToString()), null, UrlContext.None);
                _Browser.OnDocumentCompleted(args);
            }
3.修改原有DocumentCompleted事件的响应:
由于上面重写了DocumentCompleted事件,所以需要修改原有的DocumentCompleted事件响应:
修改类BrowserControl中
            _browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(_browser_DocumentCompleted);
为:
            _browser.DocumentCompleted += new EventHandler<BrowserExtendedNavigatingEventArgs>(_browser_DocumentCompleted);
修改
        void _browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
为:
        void _browser_DocumentCompleted(object sender, BrowserExtendedNavigatingEventArgs e)
其它相应的地方进行同样的修改.
4.发送DocumentCompleted事件到最外层:
该ExtendedWebBrowser演示程序通过类WindowManager管理了一个标签浏览器,如果需要,我们可以将事件发送到最外层,提供给MainForm使用.
将WindowManager中的代码
        void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            CheckCommandState();
        }
改成:
        void WebBrowser_DocumentCompleted(object sender, BrowserExtendedNavigatingEventArgs e)
        {
            OnDocumentCompleted(sender, e);
            CheckCommandState();
        }
public event EventHandler<BrowserExtendedNavigatingEventArgs> DocumentCompleted;
/// <summary>
        /// Raises the DocumentCompleted event
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnDocumentCompleted(object sender, BrowserExtendedNavigatingEventArgs e)
        {
            if (DocumentCompleted != null)
                DocumentCompleted(sender, e);
        }
5.在需要的地方响应DocumentCompleted事件:
如:
            _windowManager.DocumentCompleted += new EventHandler<BrowserExtendedNavigatingEventArgs>(_windowManager_DocumentCompleted);
.
.
.
        void _windowManager_DocumentCompleted(object sender, BrowserExtendedNavigatingEventArgs e)
        {
            // 页面完全载入
            if (e.AutomationObject == ((ExtendedWebBrowser)sender).Application)
            {
                MessageBox.Show("DocumentCompleted:" + e.Url.ToString());
            }
        }
注意:必须e.AutomationObject == ((ExtendedWebBrowser)sender).Application才说明页面已经完全载入.由于Web页面可能为多个框架嵌套的(可能还有其它的情况,尚未深究),那么载入过程中对应会有多个DocumentCompleted事件,而只有页面完全载入了,才会e.AutomationObject == ((ExtendedWebBrowser)sender).Application.这就是为什么要费尽千辛万苦把pDisp传递出来的原因.
不弹出页面,仍在当前浏览器浏览:
ExtendedWebBrowser中的StartNewWindow事件在弹出新页面的时候触发.其扩展的事件数据BrowserExtendedNavigatingEventArgs中已经提供了上下文,新页面的URL,ppDisp等所需的数据.所以我们只需改动类BrowserControl中的方法
        void _browser_StartNewWindow(object sender, BrowserExtendedNavigatingEventArgs e)
为:
        void _browser_StartNewWindow(object sender, BrowserExtendedNavigatingEventArgs e)
        {
            // Here we do the pop-up blocker work
// 这些弹出窗口过滤的代码如果不需要,就全部删除掉
if (allowPopup)
            {
                // Check wheter it's a HTML dialog box. If so, allow the popup but do not open a new tab
                if (!((e.NavigationContext & UrlContext.HtmlDialog) == UrlContext.HtmlDialog))
                {
                    ExtendedWebBrowser ewb = mf.WindowManager.New(false);
                    // The (in)famous application object
                    e.AutomationObject = ewb.Application;
                }
            }
            //在这里使用: e.AutomationObject = _browser.Application;似乎没有作用,
            //但是他原来的代码e.AutomationObject = ewb.Application;是有用的(见上面注释)
            //不知道是什么原因,只好暂时采用这个办法
            _browser.Navigate(e.Url);
            e.Cancel = true;
        }
这里如果使用e.AutomationObject = _browser.Application的话,似乎同他原来的代码e.AutomationObject = ewb.Application唯一的区别就是一个browser是浏览过页面了的,一个browser.是新建的,难道会同这个有关?哪位如果知道原因,还请不吝赐教!
不弹出脚本错误提示框:
ExtendedWebBrowser通过响应事件WebBrowser.Document.Window.Error来捕获脚本错误提示框弹出的消息:
        void _browser_DownloadComplete(object sender, EventArgs e)
        {
            // Check wheter the document is available (it should be)
            if (this.WebBrowser.Document != null)
            {
                // Subscribe to the Error event
                this.WebBrowser.Document.Window.Error += new HtmlElementErrorEventHandler(Window_Error);
.
.
.
        void Window_Error(object sender, HtmlElementErrorEventArgs e)
        {
            // We got a script error, record it
            ScriptErrorManager.Instance.RegisterScriptError(e.Url, e.Description, e.LineNumber);
            // Let the browser know we handled this error.
            e.Handled = true;
        }
但是似乎还是由于前面提到的Web页面存在多个框架嵌套的原因,其能够捕获到的消息比较有限,有很大一部分脚本错误提示消息仍然会捕获不到.这样一个问题困扰了我几天.后来突然发现ExtendedWebBrowser里面有如下的代码:
        /// <summary>
        /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. 
        /// Called by the control when the underlying ActiveX control is created. 
        /// </summary>
        /// <param name="nativeActiveXObject"></param>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void AttachInterfaces(object nativeActiveXObject)
        {
            this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
            base.AttachInterfaces(nativeActiveXObject);
        }
原来AxWebBrowser在这里!于是简单的设置了axIWebBrowser2.Silent属性:
        protected override void AttachInterfaces(object nativeActiveXObject)
        {
            this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
            this.axIWebBrowser2.Silent = true;//不弹脚本错误框
            base.AttachInterfaces(nativeActiveXObject);
        }
不再弹出任何提示框,Silent属性真的是恰如其名,整个世界清静了...*^_^*
从上面的内容可以看出,ExtendedWebBrowser截取了AxWebBrowser接口.那么,不难想象,虽然我的"再扩展"只扩展了如上三项功能,其实我们现在可以做我们任何想做的!
<=======================
作者: 谭剑

转载于:https://blog.51cto.com/ccj188/333434

对ExtendedWebBrowser的再扩展相关推荐

  1. 恢复SQL Server被误删除的数据(再扩展)

    原文:恢复SQL Server被误删除的数据(再扩展) 恢复SQL Server被误删除的数据(再扩展) 大家对本人之前的文章<恢复SQL Server被误删除的数据> 反应非常热烈,但是 ...

  2. 三言|从小事做起,然后再扩展

    从小事做起,然后再扩展 . 熬夜低效率写代码,不如好好睡觉. 让自己变得更好,是解决一切问题的关键.

  3. 4、叉叉助手逆向分析续集--模拟实现游戏插件框架--再扩展到脱壳机

    这里以HOOK程序启动后调用天天星联盟为例,下面是2014年4月30日抠出来的天天星联盟插件APK代码: package com.xxAssistant.UI; import android.app. ...

  4. 物联网技术应用再扩展 可监测蜂巢状态

    2019独角兽企业重金招聘Python工程师标准>>> 据了解,BuzzBox搭载了许多感应器,可以测量温度.湿度等,同时它还能够与智能手机连接,通过WiFi或其他网络将资料传送至专 ...

  5. WebBrowser控件使用技巧分享

    原文地址为: WebBrowser控件使用技巧分享 在发布"淘宝登货员"时发现不少朋友对WebBrowser控件比较感兴趣,故在此分享一下使用心得. 首先分享一个WebBrowse ...

  6. 专利分析与申请(1):法国汤姆森公司关于在有损编码器上扩展无损编码器的专利分析...

    框架专利的重要性 ---法国汤姆森公司有损扩展无损专利分析 在国内专利申请中,汤姆森许可贸易公司(就是那个和fraunfor IIS 等公司共同持有MP3专利的那个法国企业)在中国申请了4个与在现在的 ...

  7. 在OpenCV中图像边界扩展 copyMakeBorder 的实现

    原文:http://blog.csdn.net/viewcode/article/details/8287599 1. 边界处理的类型 2. OpenCV的实现 在图像处理中,经常需要空域或频域的滤波 ...

  8. 爱说说技术原理:与TXT交互及MDataTable对Json的功能扩展(二)

    关于爱说说在技术选型的文章见:"爱说说"技术原理方案的定选思考过程 本篇将讲述"爱说说"比较重大的技术问题点及解决手段: 爱说说:http://speak.cy ...

  9. Hadoop集群扩展子节点

    上次发了部署八节点hadoop集群的博客,本来想把master也做为一个datanode,后来感觉不太合适,最后决定还是扩展一个子节点吧. 首先是准备新的节点 安装jdkhttp://blog.csd ...

最新文章

  1. python最适合做什么生意赚钱投资小_2018做什么投资小赚钱快(适合穷人做的简单生意)...
  2. @change=“change()“与@change=“change“的区别
  3. C/C++|Qt工作笔记-4种方法判断当前对象(类)名或标识(继承发,typeid法,元对象className()法,Q_CLASSINFO法)
  4. 阿里数据人标配的高端鼠标垫,我的粉丝每人包邮送一块
  5. The easy way to implement a Red-Black tree
  6. Redis实战(七)
  7. python从入门到精通-Python从入门到精通
  8. Linux-eval命令
  9. linux 查看端口占用命令 亲测可用
  10. springboot批量更新实体_springboot快速集成swagger
  11. 十载寒冰,难凉热血——2020CSDN年度博客之星Top10心路历程
  12. SPOJ 28270 BIPCSMR16 - Team Building(水~)
  13. C语言编程练习:猜数游戏
  14. TQ2440之内核3.15.6移植
  15. css3制作吃豆豆动画
  16. 屏幕扩展之将手机变成显示器-Wired Xdisplay
  17. 计算机小高考成绩,小高考成绩公布!各校4A人数排名出炉!快来看看最牛学校数据!...
  18. 入侵检测技术是为保证计算机系统安全,计算机数据库的入侵检测技术
  19. Apache NIFI InvokeHTTP
  20. P4VASP的安装 使用P4VASP画DOS(态密度)图

热门文章

  1. kodi刮削器 中文_教你PLEX插件播放4K不能使用KODI解码导致卡顿的解决办法
  2. mysql实验步骤_MySQL双方配置实验步骤
  3. 2013计算机一级考试综合试题答案,2013全国计算机等级考试试题题库及答案.doc
  4. 鼠标移动响应php程序,jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】...
  5. Node.js开发入门(一)——安装Node.js及编辑器配置
  6. 互联网晚报 | 4月14日 星期四 | 山东六地银行下调房贷利率;​茅台一瓶降1000元;康师傅回应老坛酸菜面重新上架;...
  7. 了不起的女子力:美妆消费蓝海与趋势赛道
  8. LeetCode刷题——最长回文子串
  9. 快乐数(Leetcode第202题)
  10. python redis pipeline使用方法_Redis中的管道Pipeline操作