對ExtendedWebBrowser的再擴展(續)

<=======================
做者: 譚劍
關鍵字:C#,.NET,WebBrowser,alert,ExtendedWebBrowser,瀏覽器,對話框
=======================>
截獲"瀏覽器信息對話框"彈出消息:
    基於某些特殊需求的須要,程序須要知道瀏覽器控件信息對話框什麼時候彈出了,消息的內容是什麼,以及其它相關的信息.
    思路一:
    向瀏覽的頁面中添加以下代碼(爲避免與頁面中原有的元素相沖突,能夠將下面代碼內的方法名,元素名等替換成不一樣的guid)
<script language="JavaScrip\">
 window.alert=myFunction;                       //替換alert
 function myFunction(u1)                           //在自定義的方法中將alert內容賦值給本身添加的button,並click該button
 {
  document.myForm.myButton.value = u1;
  document.myForm.myButton.click();
 }
</script>
<form method="get" name="myForm">
 <input type="button" name = "myButton" value=""/> <!--本身添加button-->
</form>
    並在宿主程序中響應該button的click事件消息:
((ExtendedWebBrowser)sender).Document.All["myButton"].Click +=
                new HtmlElementEventHandler(myAlertElement_Click);
    這樣一來,即可以一種迂迴的方式巧妙獲取到alert消息框彈出事件.
    可是經過使用HtmlElement.AppendChild(..) / HtmlDocument.Write(..) 以及 HTMLWindow2.execScript(...) 等方法向載入的頁面中添加上述代碼,均未能獲得理想的結果,遂暫時放棄(哪位知道該怎麼弄的話,請不吝賜教!!!)
    思路二:
    額外開一監視線程,實時枚舉全部子窗口.以達到獲取該消息框彈出事件的目的.
    能夠預計,該方法會影響到整個系統的性能,會影響到程序的穩定性,同時其可靠性也不高(不能保證每次彈出消息框時恰好可以枚舉到).
    因此這隻能做爲備用方法,在沒有找到其它更好方法的狀況下,勉強用用.
    思路三:
    再一次擴展瀏覽器控件.
    查詢MSDN,能夠找到對WebBrowser.CreateWebBrowserSiteBase 方法的描述:
    『返回對非託管 WebBrowser ActiveX 控件站點的引用,擴展該站點能夠對託管 WebBrowser 控件進行自定義。
    若要使用此功能,請實現從   WebBrowser    WebBrowser.WebBrowserSite  類繼承的類。非託管   WebBrowser  ActiveX 控件使用受保護的 CreateWebBrowserSiteBase  方法檢索由   WebBrowser.WebBrowserSite  類實現的擴展性接口。重寫   CreateWebBrowserSiteBase  方法以返回本身的從 WebBrowser.WebBrowserSite  類繼承的類的實例。 WebBrowser.WebBrowserSite  類提供 OLE   IDocHostUIHandler  的默認實現。您能夠爲此接口提供本身的實現,或者實現任何其餘   WebBrowser  ActiveX 控件接口,從而對控件行爲進行自定義。』
    能夠看出,咱們只需重寫 CreateWebBrowserSiteBase  方法,擴展 WebBrowserSite  ,即可實現對瀏覽器控件的擴展。
    咱們知道,IDocHostUIHandler ,IDocHostUIHandler2 和 IDocHostShowUI 三個 接口是瀏覽器控件用戶界面的自定義核心。當一個容器提供對ActiveX   控件支持 時候 ,   當瀏覽器控件被實例化 ,若是 可能的話,它嘗試找來自 宿主的 IDocHostUIHandler , IDocHostUIHandler2 和 IDocHostShowUI   實現。當咱們修改 瀏覽器控件的時候 , 這些是咱們應該在程序中實現的 接口
    在這裏,咱們須要的僅僅是 截獲"瀏覽器信息 對話框"彈出消息,因此咱們也沒有必要把全部這些接口所有實現一遍。
    IDocHostShowUI 這個接口提供給咱們對瀏覽器控件顯示信息對話框和幫助的控制。咱們實現它,這樣在瀏覽器控件顯示它本身的任何的信息或幫助以前 ,能調用咱們定義的IDocHostShowUI方法。這樣咱們便有一個機會捕獲該信息對話框彈出的消息。IDocHostShowUI有兩個方法,IDocHostShowUI::ShowMessage和IDocHostShowUI::ShowHelp。
    已經準備得很充分了。如今開工!!!
    在文件UnsafeNativeMethods.cs的    public class UnsafeNativeMethods裏面添加以下代碼:
        #region IDocHostShowUI
        [StructLayout(LayoutKind.Explicit, Pack = 4)]
        public struct __MIDL_IWinTypes_0009
        {
            // Fields
            [FieldOffset(0)]
            public int hInproc;
            [FieldOffset(0)]
            public int hRemote;
        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct _RemotableHandle
        {
            public int fContext;
            public __MIDL_IWinTypes_0009 u;
        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct tagPOINT
        {
            public int x;
            public int y;
        }
        [ComImport, Guid("C4D244B0-D43E-11CF-893B-00AA00BDCE1A"), InterfaceType((short)1)]
        public interface IDocHostShowUI
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ShowMessage([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrText, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrCaption, [In] uint dwType, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrHelpFile, [In] uint dwHelpContext, [ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.LONG_PTR")] out int plResult);
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ShowHelp([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string pszHelpFile, [In] uint uCommand, [In] uint dwData, [In] tagPOINT ptMouse, [Out, MarshalAs(UnmanagedType.IDispatch)] object pDispatchObjectHit);
        }
        #endregion
    在文件ExtendedWebBrowser.cs的    public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser裏面添加以下代碼:
        #region ExtendedWebBrowserSite
        class ExtendedWebBrowserSite : WebBrowser.WebBrowserSite, UnsafeNativeMethods.IDocHostShowUI
        {
            public ExtendedWebBrowserSite(WebBrowser host)
                : base(host)
            {
            }
            void UnsafeNativeMethods.IDocHostShowUI.ShowMessage(ref UnsafeNativeMethods._RemotableHandle hwnd, string lpstrText, string lpstrCaption, uint dwType, string lpstrHelpFile, uint dwHelpContext, out int plResult)
            {
                //TODO:自定義
            }
            void UnsafeNativeMethods.IDocHostShowUI.ShowHelp(ref UnsafeNativeMethods._RemotableHandle hwnd, string pszHelpFile, uint uCommand, uint dwData, UnsafeNativeMethods.tagPOINT ptMouse, object pDispatchObjectHit)
            {
                //TODO:自定義
            }
        }
        protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
        {
            return new ExtendedWebBrowserSite(this);
        }
        #endregion
    OK,如今即可以添加相應的自定義事件了,這個輕車熟路,再也不贅述。
說明:本文爲《對ExtendedWebBrowser的再擴展》的續,某些地方請自行參看前文。
相關文章
相關標籤/搜索