UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解三(接上篇)

  UMPLatForm.NET MiNiWeb瀏覽器核心技術詳解三

 

接上兩篇:

        UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解一

        UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解二

 

實現dwebbrowserevents2接口 

在這個例子中實現了下列事件:

l  newwindow2newwindow3(用於屏蔽彈出窗口和創建新窗口)

l  downloadbegindownloadcomplete(用於捕捉腳本錯誤)

l  beforenavigate2(用於在導航到一個頁面前查看即將導航到的地址) 

    爲了簡潔的實現dwebbrowserevents接口,最好的方法是在組件中建立一個私有的嵌入類。這樣,所有需要的事件都在一個地方並且輕易查找。當我們實例化這個類的時候,我們可以給調用者提供一個引用,利用該引用可以調用方法來觸發我們需要的事件。

     在組件的構造過程中並沒有附帶這些事件,而是稍微晚一點。這裏有兩個方法來實現它並且它們是可以重載的。它們是createsink()detachsink()。當我們將這些都添加完以後,我們的代碼會像下面這樣(注重有些代碼爲了閱讀方便而刪掉了) 


  1. /// <summary> 
  2. /// An extended version of the <see cref="WebBrowser"/> control. 
  3. /// </summary>    
  4. public class extendedwebbrowser : system.windows.forms.webbrowser 
  5.   //   (MORE CODE HERE) 
  6.  SYSTEM.WINDOWS.FORMS.AXHOST.CONNECTIONPOINTCOOKIE COOKIE; 
  7.  WEBBROWSEREXTENDEDEVENTS EVENTS; 
  8.  
  9.  /// <SUMMARY> 
  10.  /// THIS METHOD WILL BE CALLED TO GIVE 
  11.  /// YOU A CHANCE TO CREATE YOUR OWN EVENT SINK 
  12.  /// </SUMMARY> 
  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.  /// <SUMMARY> 
  23.  /// DETACHES THE EVENT SINK 
  24.  /// </SUMMARY> 
  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.   /// <SUMMARY> 
  36.  /// FIRES WHEN DOWNLOADING OF A DOCUMENT BEGINS 
  37.  /// </SUMMARY> 
  38.  PUBLIC EVENT EVENTHANDLER DOWNLOADING;  
  39.  
  40.  /// <SUMMARY> 
  41.  /// RAISES THE <SEE CREF="DOWNLOADING"/> EVENT 
  42.  /// </SUMMARY> 
  43.  /// <PARAM NAME="E">EMPTY <SEE CREF="EVENTARGS"/></PARAM> 
  44.  /// <REMARKS> 
  45.  /// YOU COULD START AN ANIMATION 
  46.  /// OR A NOTIFICATION THAT DOWNLOADING IS STARTING 
  47.  /// </REMARKS> 
  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
 聯繫我,非常感謝。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章