如何妥善處理WebBrowser對Javascript的錯誤問題,阻止JS彈出框,提高用戶體驗


由於項目需求,最近轉戰客戶端,開始搞瀏覽器開發。眾所周知,現在在微軟平台上開發瀏覽器,最常用的方法就是擴展Webbrowser,但是首先要清楚的是,WebBrowser控件僅僅是對WebBrowser ActiveX 控件提供了托管包裝而已(詳細了解http://msdn.microsoft.com/zh-cn/library/w290k23d(VS.80).aspx),要寫一個像點樣子的瀏覽器,很多方面還是要自己去擴展的,否則開發出來的也只能是個樣子,沒多少實際功能。
     本篇隨筆重點將介紹如何處理WebBrowser對JS的錯誤處理問題。

     可能有些朋友看到上句話會覺得,這問題不是很簡單嘛,設置一下 ScriptErrorsSuppressed屬性不就完了嘛,殊不知這樣做,像其他的譬如網頁安全驗證的彈出框,甚至很多其他網頁內部彈出窗口也都被禁止掉了,如此當然是行不通的。可能還會有一部分朋友會說,那可以通過WebBrowser向網頁中注入JS錯誤處理腳本,捕獲JS錯誤,不是也可以嘛。那我會告訴你,這種方法在面對使用很多iframe的網站是也玩完。

     那么接下來,我將介紹,如何更好的避免WebBrowser中的JS錯誤。

     避免錯誤,首先要想到辦法去捕獲錯誤,查遍了網上的很多資料,發現是要去實現IOleCommandTarget接口,調用接口中的Exec方法來捕獲異常,然后解決,當然如果需要去調用IE的一些功能,也得需實現IObjectWithSite接口。

     定義IOleCommandTarget接口、OLECMD類:

public static class NativeMethods 
    {
        public enum OLECMDF
        {
            // Fields
            OLECMDF_DEFHIDEONCTXTMENU = 0x20,
            OLECMDF_ENABLED = 2,
            OLECMDF_INVISIBLE = 0x10,
            OLECMDF_LATCHED = 4,
            OLECMDF_NINCHED = 8,
            OLECMDF_SUPPORTED = 1
        }

        public enum OLECMDID
        {
            // Fields
            OLECMDID_PAGESETUP = 8,
            OLECMDID_PRINT = 6,
            OLECMDID_PRINTPREVIEW = 7,
            OLECMDID_PROPERTIES = 10,
            OLECMDID_SAVEAS = 4,
            OLECMDID_SHOWSCRIPTERROR = 40
        }
        public enum OLECMDEXECOPT
        {
            // Fields
            OLECMDEXECOPT_DODEFAULT = 0,
            OLECMDEXECOPT_DONTPROMPTUSER = 2,
            OLECMDEXECOPT_PROMPTUSER = 1,
            OLECMDEXECOPT_SHOWHELP = 3
        }

        [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), ComVisible(true)]
        public interface IOleCommandTarget
        {
            [return: MarshalAs(UnmanagedType.I4)]
            [PreserveSig]
            int QueryStatus(ref Guid pguidCmdGroup, int cCmds, [In, Out] NativeMethods.OLECMD prgCmds, [In, Out] IntPtr pCmdText);
            [return: MarshalAs(UnmanagedType.I4)]
            [PreserveSig]
            int Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, [In, MarshalAs(UnmanagedType.LPArray)] object[] pvaIn, ref int pvaOut);
        }

        [StructLayout(LayoutKind.Sequential)]
        public class OLECMD
        {
            [MarshalAs(UnmanagedType.U4)]
            public int cmdID;
            [MarshalAs(UnmanagedType.U4)]
            public int cmdf;
            public OLECMD()
            {
            }
        }

        public const int S_FALSE = 1;
        public const int S_OK = 0;

        public static readonly Guid CGID_DocHostCommandHandler = new Guid("f38bc242-b950-11d1-8918-00c04fc2c836");

        public const int VARIANT_TRUE = -1;
        public const int VARIANT_FALSE = 0;
        public const int OLECMDERR_E_NOTSUPPORTED = -2147221244;


    }

       然后定義一個類ExtendedWebBrowserSite,去實現接口:

class ExtendedWebBrowserSite : WebBrowserSite, NativeMethods.IOleCommandTarget
        {
            /// <summary>
            /// Creates a new instance of the <see cref="ExtendedWebBrowserSite"/> class
            /// </summary>
            /// <param name="host">The <see cref="ExtendedWebBrowser"/> hosting the browser</param>
            public ExtendedWebBrowserSite(ExtendedWebBrowser host)
                : base(host)
            {
                _host = host;
            }


            private ExtendedWebBrowser _host;
            private ExtendedWebBrowser Host
            {
                get
                {
                    return _host;
                }
            }

            #region IOleCommandTarget Members

            int NativeMethods.IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, int cCmds, NativeMethods.OLECMD prgCmds, IntPtr pCmdText)
            {
                return NativeMethods.S_FALSE;
            }

            int NativeMethods.IOleCommandTarget.Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, object[] pvaIn, ref int pvaOut)
            {
                int hResult = NativeMethods.S_OK;
                if (pguidCmdGroup == null)
                    return hResult;
                // Check for invalid pointers (or get a NullReferenceException on a value type???)
                //if (NativeMethods.CGID_DocHostCommandHandler.Equals(pguidCmdGroup))
                {
                    switch (nCmdID)
                    {
                        case (int)NativeMethods.OLECMDID.OLECMDID_SHOWSCRIPTERROR:
                            // Hide the dialog
                            pvaOut = NativeMethods.VARIANT_TRUE;


                            break;
                        default:
                            hResult = NativeMethods.OLECMDERR_E_NOTSUPPORTED;
                            break;
                    }
                }
                return hResult;
            }

            #endregion

        }
   } 

    當然這里主要是通過實現IOleCommandTarget.Exec方法去捕獲OLECMDID.OLECMDID_SHOWSCRIPTERROR消息,然后避免異常。

      最后在你的擴展的WebBrowser里面重載一下CreateWebBrowserSiteBase方法,完成調用。

        protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
        {
            return new ExtendedWebBrowserSite(this);
        } 

原文:http://blog.csdn.net/tangyanzhi1111/article/details/8990459


免責聲明!

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



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