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

 

接上两篇:

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

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

 

实现dwebbrowserevents2接口 

在这个例子中实现了下列事件:

l  newwindow2newwindow3(用于屏蔽弹出窗口和创建新窗口)

l  downloadbegindownloadcomplete(用于捕捉脚本错误)

l  beforenavigate2(用于在导航到一个页面前查看即将导航到的地址) 

    为了简洁的实现dwebbrowserevents接口,最好的方法是在组件中建立一个私有的嵌入类。这样,所有需要的事件都在一个地方并且轻易查找。当我们实例化这个类的时候,我们可以给调用者提供一个引用,利用该引用可以调用方法来触发我们需要的事件。

     在组件的构造过程中并没有附带这些事件,而是稍微晚一点。这里有两个方法来实现它并且它们是可以重载的。它们是createsink()detachsink()。当我们将这些都添加完以后,我们的代码会像下面这样(注重有些代码为了阅读方便而删掉了) 


   
   
   
   
  1. ///  
  2. /// An extended version of the  control. 
  3. ///     
  4. public class extendedwebbrowser : system.windows.forms.webbrowser 
  5.   //   (MORE CODE HERE) 
  6.  SYSTEM.WINDOWS.FORMS.AXHOST.CONNECTIONPOINTCOOKIE COOKIE; 
  7.  WEBBROWSEREXTENDEDEVENTS EVENTS; 
  8.  
  9.  ///  
  10.  /// THIS METHOD WILL BE CALLED TO GIVE 
  11.  /// YOU A CHANCE TO CREATE YOUR OWN EVENT SINK 
  12.  ///  
  13.  [PERMISSIONSET(SECURITYACTION.LINKDEMAND, NAME = "FULLTRUST")] 
  14.  PROTECTED OVERRIDE VOID CREATESINK() 
  15.  { 
  16.    // MAKE SURE TO CALL THE BASE CLASS OR THE NORMAL EVENTS WON'T FIRE 
  17.    BASE.CREATESINK(); 
  18.    EVENTS = NEW WEBBROWSEREXTENDEDEVENTS(THIS); 
  19.    COOKIE = NEW AXHOST.CONNECTIONPOINTCOOKIE(THIS.ACTIVEXINSTANCE, 
  20.                      EVENTS, TYPEOF(UNSAFENATIVEMETHODS.DWEBBROWSEREVENTS2)); 
  21.  } 
  22.  ///  
  23.  /// DETACHES THE EVENT SINK 
  24.  ///  
  25.  [PERMISSIONSET(SECURITYACTION.LINKDEMAND, NAME = "FULLTRUST")] 
  26.  PROTECTED OVERRIDE VOID DETACHSINK() 
  27.   { 
  28.    IF (NULL != COOKIE) 
  29.        { 
  30.         COOKIE.DISCONNECT(); 
  31.         COOKIE = NULL; 
  32.    } 
  33.  } 
  34.  
  35.   ///  
  36.  /// FIRES WHEN DOWNLOADING OF A DOCUMENT BEGINS 
  37.  ///  
  38.  PUBLIC EVENT EVENTHANDLER DOWNLOADING;  
  39.  
  40.  ///  
  41.  /// RAISES THE  EVENT 
  42.  ///  
  43.  /// EMPTY  
  44.  ///  
  45.  /// YOU COULD START AN ANIMATION 
  46.  /// OR A NOTIFICATION THAT DOWNLOADING IS STARTING 
  47.  ///  
  48.  PROTECTED VOID ONDOWNLOADING(EVENTARGS E) 
  49.   { 
  50.    IF (DOWNLOADING != NULL) 
  51.         DOWNLOADING(THIS, E); 
  52.  } 
  53.  
  54.   //   (MORE CODE HERE) 
  55.   THE IMPLEMENTATION OF DWEBBROWSEREVENTS2 FOR FIRING EXTRA EVENTS 

 

4、使用这个组件

       上一节,我们创建了一个新的组件。现在,我们来使用这些新的事件并尽可能多的挖掘浏览器的功能。针对每一个目标,具体的解释如下:

 捕捉脚本错误

       在示例程序中,有一个工具窗口简单的显示了发生错误的列表并附带了错误的具体内容。一个单一实例类把握了脚本错误的信息并且当这个信息发生改变时通知所有订阅者,为了捕捉这些脚本错误,browsercontrol首先附加到downloadcomplete事件,其次它订阅了htmlwindow.error事件。当这个事件触发时,我们注册这个脚本错误并设置handled属性为true

 

   
   
   
   
  1. public partial class browsercontrol : usercontrol 
  2.  { 
  3.   public browsercontrol() 
  4.    { 
  5.     initializecomponent(); 
  6.     _browser = new extendedwebbrowser(); 
  7.     _browser.dock = dockstyle.fill; 
  8.  
  9.     // here's the new downloadcomplete event 
  10.     _browser.downloadcomplete += 
  11.       new eventhandler(_browser_downloadcomplete); 
  12.  
  13.     // some more code here 
  14.     this.containerpanel.controls.add(_browser); 
  15.     // some more code here 
  16.   } 
  17.  
  18.   void _browser_downloadcomplete(object sender, eventargs e) 
  19.    { 
  20.     // check wheter the document is available (it should be) 
  21.     if (this.webbrowser.document != null
  22.       // subscribe to the error event 
  23.       this.webbrowser.document.window.error += 
  24.         new htmlelementerroreventhandler(window_error); 
  25.   } 
  26.  
  27.   void window_error(object sender, htmlelementerroreventargs e) 
  28.    { 
  29.     // we got a script error, record it 
  30.     scripterrormanager.instance.registerscripterror(e.url, 
  31.                              e.description, e.linenumber); 
  32.     // let the browser know we handled this error. 
  33.     e.handled = true
  34.   } 
  35.   // some more code here 

 过滤弹出窗口,并且增加多标签页或多窗口浏览功能

        捕捉弹出窗口必须可以由用户来进行配置。为了示范的目的,我实现了四个级别,从不屏蔽任何窗口到屏蔽所有新窗口。下面的代码是browsercontorl的一部分,用来展现如何实现这一点。当一个新建窗口被答应后,示例程序展现了如何让新建窗口实现窗口名称的解决方案。  


   
   
   
   
  1. void _browser_startnewwindow(object sender, 
  2.             browserextendednavigatingeventargs e) 
  3.   { 
  4.    // here we do the pop-up blocker work 
  5.    // note that in windows 2000 or lower this event will fire, but the 
  6.    // event arguments will not contain any useful information 
  7.    // for blocking pop-ups. 
  8.    // there are 4 filter levels. 
  9.    // none: allow all pop-ups 
  10.    // low: allow pop-ups from secure sites 
  11.    // medium: block most pop-ups 
  12.    // high: block all pop-ups (use ctrl to override) 
  13.    // we need the instance of the main form, 
  14.    // because this holds the instance 
  15.    // to the windowmanager. 
  16.    mainform mf = getmainformfromcontrol(sender as control); 
  17.    if (mf == null
  18.      return
  19.  
  20.    // allow a popup when there is no information 
  21.    // available or when the ctrl key is pressed 
  22.    bool allowpopup = (e.navigationcontext == urlcontext.none) 
  23.         || ((e.navigationcontext & 
  24.         urlcontext.overridekey) == urlcontext.overridekey); 
  25.    if (!allowpopup) 
  26.     { 
  27.      // give none, low & medium still a chance. 
  28.      switch (settingshelper.current.filterlevel) 
  29.       { 
  30.        case popupblockerfilterlevel.none: 
  31.          allowpopup = true
  32.          break
  33.        case popupblockerfilterlevel.low: 
  34.          // see if this is a secure site 
  35.          if (this.webbrowser.encryptionlevel != 
  36.                  webbrowserencryptionlevel.insecure) 
  37.            allowpopup = true
  38.          else 
  39.            // not a secure site, handle this like the medium filter 
  40.            goto case popupblockerfilterlevel.medium; 
  41.          break
  42.        case popupblockerfilterlevel.medium: 
  43.          // this is the most dificult one. 
  44.          // only when the user first inited 
  45.          // and the new window is user inited 
  46.          if ((e.navigationcontext & urlcontext.userfirstinited) 
  47.               == urlcontext.userfirstinited && 
  48.               (e.navigationcontext & urlcontext.userinited) 
  49.               == urlcontext.userinited) 
  50.            allowpopup = true
  51.          break
  52.      } 
  53.    } 
  54.  
  55.    if (allowpopup) 
  56.     { 
  57.      // check wheter it's a html dialog box. 
  58.      // if so, allow the popup but do not open a new tab 
  59.      if (!((e.navigationcontext & 
  60.             urlcontext.htmldialog) == urlcontext.htmldialog)) 
  61.       { 
  62.        extendedwebbrowser ewb = mf.windowmanager.new(false); 
  63.        // the (in)famous application object 
  64.        e.automationobject = ewb.application; 
  65.      } 
  66.    } 
  67.    else 
  68.      // here you could notify the user that the pop-up was blocked 
  69.      e.cancel = true
  70.  }  

    这个事件称为startnewwindow的原因是编码设计规则不答应一个事件的名称以“before”或者“after”开头。“newwindowing”事件并没有在这一范围内。

 使用quit事件

       quit事件触发时,我们只需要找到正确的窗口或者标签页将其关闭,并且”dispose”这个示例即可。

 


作者: Edward  
出处: 
http://umplatform.blog.51cto.com/

微博: 腾讯

Email: [email protected]或 [email protected]

QQ 交流:406590790 (请注明:平台交流)

QQ×××流:16653241  237326100
关于作者:高级工程师、信息系统项目管理师、数据库系统工程师。专注于微软平台项目架构、管理和企业解决方案,多年项目开发与管理经验,曾多次组织并开发多个大型项目,精通DotNet(C#Asp.NETADO.NETWeb ServiceWCF)DB原理与技术、SqlServerOracle等。熟悉JavaDelhpiLinux操作系统,有扎实的网络知识。自认在面向对象、面向服务以及数据库领域有一定的造诣。现主要从事DB管理、DB开发、WinFormWCFWebService、网页数据抓取以及ASP.NET等项目管理、开发、架构等工作。如有问题或建议,请多多赐教!
本文版权归作者和51CTO博客共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过邮箱或QQ
 联系我,非常感谢。