WebBrowser控件應用:彈出新窗體和關閉窗口


緣起:上次寫了一個《WebBrowser控件的簡單應用2》,提到了在NewWindow事件中打開新窗口的例子。有網友“隊長 ”提出那個事件得到的參數是本頁面的,而不是新頁面的,經過測試,果然url參數不是新頁面的。

Open新頁面要處理的:

1:<<a href=’xxxxx’ target=’_blank’>>; 
     2: onclick=’window.open’ ;

3:引用js文件 ;

4:ClientScript.RegisterStartupScript();等。

5:還有要實現在打開的頁面里能用window.opener對象

Close要處理的:

1:onclick=’window.close ;

2:引用js文件 ;

3:ClientScript.RegisterStartupScript()等。

 

經過在網上搜索,結果並不令人滿意。基本上,WebBrowser控件不提供這個(將要打開的新頁面的地址)功能,只能通過其他方法。

這里介紹一下網上的一個簡單的解決方案、我的一個簡單方案、微軟的回答、一個終極解決方法。

 

網上現在有人給出這樣的一個解決方案:在_NewWindow事件通過wb_Container.StatusText來獲得當前將要打開的頁面。代碼可以這樣寫:

        private void wb_Container_NewWindow(object sender, CancelEventArgs e)

        {

            e.Cancel = true;

             string newURL = wb_Container.StatusText;

            //'open

           

        }

我測試了一下,這樣做基本上只能處理<a href=’xxxxx’ target=’_blank’>的這種情況。對於<button>里面的onlcick事件window.open()毫無作用。

原因很簡單,他只是利用了WebBrower現實Status的特點來做,不全面,不安全。至於其他情況也是完全不能處理,比如js中使用window.Open,這個方案根本不能檢查。

 

我的處理方法

剛開始,我使用了這樣的思路:針對所有可能出現的情況,找個各個不同方法來處理。

比如說,對於<a herf=’’的這種情況,就用wb_Container.StatusText方法,但是要加入一個判斷。If(wb_Container.StatusText!=””)。對於window.open和RegisterStartupScript的,可以通過替換js來實現。

本來的window.open函數,在程序完成加載之后,我把這個函數修改成window.external.open,

然后,我把我的AppBrowser類里面加入幾個public的Open函數來對應原來的js的open函數就可以了。

這是一個代碼實現。

private void wb_Container_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

        {

            //for windows.open

            if (wb_Container.DocumentText.IndexOf("window.open(") > -1 || wb_Container.DocumentText.IndexOf("window.close()") > -1)

            {

                wb_Container.DocumentText = wb_Container.DocumentText.Replace("window.open(", "window.external.open(").Replace("window.close()", "window.external.close()");

            }

        }

這樣處理之后,保證了我的瀏覽器也能理解這些js。

這個方案唯一不能處理的就是js文件里面有處理的情況。

還有一個小問題,替換之后的document對象的action變化了。這個可以通過方法來實現,就是替換上邊的函數,改用遞歸document.all來實現,檢查每個element控件的內容來實現。

但是,畢竟美中不足。

 

微軟的解釋是這樣的:這個問題,下一個版本在解決(http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115195),開發者可以通過擴展WebBrower及其Event來實現。並且提供了一個簡單的代碼(但是顯示不完全)。是的,這是個好的解決方案,但不是我想要的。既然封裝了這個控件,為什么不提供這么重要的一個參數呢?

 

有高手已經做出了一個模型:(http://www.codeproject.com/csharp/ExtendedWebBrowser.asp

(作者實現了一個類似IE7效果的瀏覽器)

這個模型里面,作者自己封裝並且擴展了這個控件,是個最終極的解決方法。

主要思路:提供了一個將要打開新窗口的事件,並且提供更多的參數。這些參數來自IWebBrowser2等接口,還提供了一些WndProc重載來實現window.close。

下載之后,我保留了這些類,做了一個簡單的測試

ExtendedWebBrowser : System.Windows.Forms.WebBrowser

   .WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2

   .WindowsMessages(enum)

UnsafeNativeMethods

   .DWebBrowserEvents2([ComImport, TypeLibType((short)0x1010), InterfaceType((short)2), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")])

   .IWebBrowser2([ComImport, SuppressUnmanagedCodeSecurity, TypeLibType(TypeLibTypeFlags.FOleAutomation | (TypeLibTypeFlags.FDual | TypeLibTypeFlags.FHidden)), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")])

BrowserExtendedNavigatingEventArgs : CancelEventArgs

UrlContext

ScriptError

NativeMethods

結果非常不錯。

主要處理的幾個地方:

NewWindow2NewWindow3:處理新打開窗口

BeforeNavigate2:獲得將要打開的窗口的地址。

主要提供的新事件:_StartNewWindow(object sender, BrowserExtendedNavigatingEventArgs e)

 

下邊這一個是我的第二個AppBrowser類,使用上邊封裝擴展之后的WebBrower控件。

 


  1    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
  2    public partial class AppBrowser2 : Form
  3    {
  4        property
 19        cons.
 41 
 42        window : close and open
 55        other browser event
 92
 93        external function for js
114    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM