UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解三
接上兩篇:
UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解一
UMPLatForm.NET 中MiNiWeb瀏覽器核心技術詳解二
實現dwebbrowserevents2接口
在這個例子中實現了下列事件:
l newwindow2和newwindow3(用於屏蔽彈出窗口和創建新窗口)
l downloadbegin和downloadcomplete(用於捕捉腳本錯誤)
l beforenavigate2(用於在導航到一個頁面前查看即將導航到的地址)
爲了簡潔的實現dwebbrowserevents接口,最好的方法是在組件中建立一個私有的嵌入類。這樣,所有需要的事件都在一個地方並且輕易查找。當我們實例化這個類的時候,我們可以給調用者提供一個引用,利用該引用可以調用方法來觸發我們需要的事件。
在組件的構造過程中並沒有附帶這些事件,而是稍微晚一點。這裏有兩個方法來實現它並且它們是可以重載的。它們是createsink()和detachsink()。當我們將這些都添加完以後,我們的代碼會像下面這樣(注重有些代碼爲了閱讀方便而刪掉了)
- /// <summary>
- /// An extended version of the <see cref="WebBrowser"/> control.
- /// </summary>
- public class extendedwebbrowser : system.windows.forms.webbrowser
- {
- // (MORE CODE HERE)
- SYSTEM.WINDOWS.FORMS.AXHOST.CONNECTIONPOINTCOOKIE COOKIE;
- WEBBROWSEREXTENDEDEVENTS EVENTS;
- /// <SUMMARY>
- /// THIS METHOD WILL BE CALLED TO GIVE
- /// YOU A CHANCE TO CREATE YOUR OWN EVENT SINK
- /// </SUMMARY>
- [PERMISSIONSET(SECURITYACTION.LINKDEMAND, NAME = "FULLTRUST")]
- PROTECTED OVERRIDE VOID CREATESINK()
- {
- // MAKE SURE TO CALL THE BASE CLASS OR THE NORMAL EVENTS WON'T FIRE
- BASE.CREATESINK();
- EVENTS = NEW WEBBROWSEREXTENDEDEVENTS(THIS);
- COOKIE = NEW AXHOST.CONNECTIONPOINTCOOKIE(THIS.ACTIVEXINSTANCE,
- EVENTS, TYPEOF(UNSAFENATIVEMETHODS.DWEBBROWSEREVENTS2));
- }
- /// <SUMMARY>
- /// DETACHES THE EVENT SINK
- /// </SUMMARY>
- [PERMISSIONSET(SECURITYACTION.LINKDEMAND, NAME = "FULLTRUST")]
- PROTECTED OVERRIDE VOID DETACHSINK()
- {
- IF (NULL != COOKIE)
- {
- COOKIE.DISCONNECT();
- COOKIE = NULL;
- }
- }
- /// <SUMMARY>
- /// FIRES WHEN DOWNLOADING OF A DOCUMENT BEGINS
- /// </SUMMARY>
- PUBLIC EVENT EVENTHANDLER DOWNLOADING;
- /// <SUMMARY>
- /// RAISES THE <SEE CREF="DOWNLOADING"/> EVENT
- /// </SUMMARY>
- /// <PARAM NAME="E">EMPTY <SEE CREF="EVENTARGS"/></PARAM>
- /// <REMARKS>
- /// YOU COULD START AN ANIMATION
- /// OR A NOTIFICATION THAT DOWNLOADING IS STARTING
- /// </REMARKS>
- PROTECTED VOID ONDOWNLOADING(EVENTARGS E)
- {
- IF (DOWNLOADING != NULL)
- DOWNLOADING(THIS, E);
- }
- // (MORE CODE HERE)
- THE IMPLEMENTATION OF DWEBBROWSEREVENTS2 FOR FIRING EXTRA EVENTS
- }
4、使用這個組件
上一節,我們創建了一個新的組件。現在,我們來使用這些新的事件並儘可能多的挖掘瀏覽器的功能。針對每一個目標,具體的解釋如下:
捕捉腳本錯誤
在示例程序中,有一個工具窗口簡單的顯示了發生錯誤的列表並附帶了錯誤的具體內容。一個單一實例類把握了腳本錯誤的信息並且當這個信息發生改變時通知所有訂閱者,爲了捕捉這些腳本錯誤,browsercontrol首先附加到downloadcomplete事件,其次它訂閱了htmlwindow.error事件。當這個事件觸發時,我們註冊這個腳本錯誤並設置handled屬性爲true。
- public partial class browsercontrol : usercontrol
- {
- public browsercontrol()
- {
- initializecomponent();
- _browser = new extendedwebbrowser();
- _browser.dock = dockstyle.fill;
- // here's the new downloadcomplete event
- _browser.downloadcomplete +=
- new eventhandler(_browser_downloadcomplete);
- // some more code here
- this.containerpanel.controls.add(_browser);
- // some more code here
- }
- 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;
- }
- // some more code here
- }
過濾彈出窗口,並且增加多標籤頁或多窗口瀏覽功能
捕捉彈出窗口必須可以由用戶來進行配置。爲了示範的目的,我實現了四個級別,從不屏蔽任何窗口到屏蔽所有新窗口。下面的代碼是browsercontorl的一部分,用來展現如何實現這一點。當一個新建窗口被答應後,示例程序展現瞭如何讓新建窗口實現窗口名稱的解決方案。
- void _browser_startnewwindow(object sender,
- browserextendednavigatingeventargs e)
- {
- // here we do the pop-up blocker work
- // note that in windows 2000 or lower this event will fire, but the
- // event arguments will not contain any useful information
- // for blocking pop-ups.
- // there are 4 filter levels.
- // none: allow all pop-ups
- // low: allow pop-ups from secure sites
- // medium: block most pop-ups
- // high: block all pop-ups (use ctrl to override)
- // we need the instance of the main form,
- // because this holds the instance
- // to the windowmanager.
- mainform mf = getmainformfromcontrol(sender as control);
- if (mf == null)
- return;
- // allow a popup when there is no information
- // available or when the ctrl key is pressed
- bool allowpopup = (e.navigationcontext == urlcontext.none)
- || ((e.navigationcontext &
- urlcontext.overridekey) == urlcontext.overridekey);
- if (!allowpopup)
- {
- // give none, low & medium still a chance.
- switch (settingshelper.current.filterlevel)
- {
- case popupblockerfilterlevel.none:
- allowpopup = true;
- break;
- case popupblockerfilterlevel.low:
- // see if this is a secure site
- if (this.webbrowser.encryptionlevel !=
- webbrowserencryptionlevel.insecure)
- allowpopup = true;
- else
- // not a secure site, handle this like the medium filter
- goto case popupblockerfilterlevel.medium;
- break;
- case popupblockerfilterlevel.medium:
- // this is the most dificult one.
- // only when the user first inited
- // and the new window is user inited
- if ((e.navigationcontext & urlcontext.userfirstinited)
- == urlcontext.userfirstinited &&
- (e.navigationcontext & urlcontext.userinited)
- == urlcontext.userinited)
- allowpopup = true;
- break;
- }
- }
- 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;
- }
- }
- else
- // here you could notify the user that the pop-up was blocked
- e.cancel = true;
- }
這個事件稱爲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.NET、ADO.NET、Web Service、WCF),DB原理與技術、SqlServer、Oracle等。熟悉Java、Delhpi及Linux操作系統,有紮實的網絡知識。自認在面向對象、面向服務以及數據庫領域有一定的造詣。現主要從事DB管理、DB開發、WinForm、WCF、WebService、網頁數據抓取以及ASP.NET等項目管理、開發、架構等工作。如有問題或建議,請多多賜教!
本文版權歸作者和51CTO博客共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,可以通過郵箱或QQ 聯繫我,非常感謝。