基於.net開發chrome核心瀏覽器【五】

liulun發表於2013-06-19

一:本篇將解決的問題

本章主要為了解決一下幾個問題:

1.JsDialog的按鈕錯位的問題

  我們開發出的瀏覽器,在有些操系統上呼叫alert,confirm之類的對話方塊時,確定和取消按鈕會出現錯位的情況

2.右鍵選單問題

  我們開發的瀏覽器,在網頁上點右鍵,會出現一些討厭的英文選單。

3.列印的問題

  我們開發的瀏覽器,網頁在呼叫window.print的時候,沒有任何反應。

4.開啟chrome的偵錯程式

  谷歌瀏覽器除錯網頁的偵錯程式非常好用,我們開發的瀏覽器也可以用這個工具。

二:JsDialog的按鈕錯位的問題

先在BS資料夾中新建一個類,取名為JsDialogHandler,讓這個類繼承自CefJSDialogHandler

然後在這個類中重寫OnJSDialog函式,程式碼如下:

protected override bool OnJSDialog(CefBrowser browser, string originUrl, string acceptLang, CefJSDialogType dialogType, string message_text, string default_prompt_text, CefJSDialogCallback callback, out bool suppress_message)
        {
            switch (dialogType)
            {
                case CefJSDialogType.Alert:
                    MessageBox.Show(message_text, "XXX系統提示");
                    suppress_message = true;
                    return false;
                    break;
                case CefJSDialogType.Confirm:
                    var dr = MessageBox.Show(message_text, "XXX系統提示", MessageBoxButtons.YesNo);
                    if (dr == DialogResult.Yes)
                    {
                        callback.Continue(true, string.Empty);
                        suppress_message = false;
                        return true;
                    }
                    else
                    {
                        callback.Continue(false, string.Empty);
                        suppress_message = false;
                        return true;
                    }
                    break;
                case CefJSDialogType.Prompt:
                    MessageBox.Show("系統不支援prompt形式的提示框", "UTMP系統提示");
                    break;
            }
            suppress_message = true;
            return false;
        }

下面我們來解釋一下程式碼中的內容

default_prompt_text引數:

為prompt型別的dialog服務的(這種dialog可以接收使用者的輸入,一般已經很少見了,我們沒有實現這種型別的dialog);

suppress_message引數:

如果這個引數被設定為true,並且函式返回值為false,將阻止頁面開啟JS的彈出視窗。

如果這個引數被設定為false,並且函式返回值也是false,頁面將會開啟這個JS彈出視窗。

message_text引數:

是彈出視窗將要顯示的內容

dialogType引數:

是彈出視窗的型別(alert,confirm,Prompt)

callback引數:

當使用者點選了彈出視窗的確定按鈕,可以用callback.Continue(true, string.Empty);回撥確定函式

當使用者點選了彈出視窗的取消按鈕,可以用callback.Continue(false, string.Empty);回撥取消函式

------------------

在函式內部,我們使用系統的彈出框替換了CEF的彈出框,從以解決彈出框按鈕顯示的問題。

------------------

在這個類中還需要重寫兩個虛方法:

OnResetDialogState

此方法可以取消掉所有即將彈出的對話方塊,一般在頁面跳轉時會被呼叫。

OnBeforeUnloadDialog

當使用者離開頁面的時候,彈出的詢問對話方塊,返回false將使用預設的彈出視窗

這兩個方法只要簡單重寫一下就可以了。不用有其他實現

-------------------

這個類建立好之後,要在BsClient類中,增加一個私有屬性

private readonly CefJSDialogHandler jsDialogHandler;

然後在建構函式中為這個屬性賦值

jsDialogHandler = new JsDialogHandler();

然後重寫父類的一個方法:

        protected override CefJSDialogHandler GetJSDialogHandler()
        {
            return jsDialogHandler;
        }

至此:我們的jsDialogHandler才能生效。

三:右鍵選單的問題

要想去掉系統預設的右鍵選單,

只要實現CefContextMenuHandler的子類

然後重寫OnBeforeContextMenu方法,

下面我們看看這個方法:

        protected override void OnBeforeContextMenu(CefBrowser browser, CefFrame frame, CefContextMenuParams state, CefMenuModel model)
        {
            model.Clear();
        }

model包括預設的右鍵選單中的所有的項,如果想不顯示右鍵選單,只要Clear一下就可以了

然後和jsDialogHandler一樣,重寫CefClient的 GetContextMenuHandler方法

把這個類的例項返回就可以了。

四:列印的問題

我是這麼處理的:

在前面提到的OnJsDialog方法中

加入如下程式碼

                case CefJSDialogType.Alert:
                    if (message_text.StartsWith("$Print$"))
                    {
                        var str = message_text.Substring(7);
                        var ieb = new IEBrow();
                        ieb.Print(str);
                        ieb.Show();
                        suppress_message = true;
                        return false;
                    }

彈出框的內容字首如果是“$Print$”就進入列印的流程

(這是多麼蛋疼的做法!!首先window.print是不能用了,只能用alert(“$Print$balabalabala”)。)

ieb是一個iebrowser

裡面的關鍵程式碼如下:

        public void Print(string doc)
        {
            webBrowser1.DocumentText = doc;
        }
        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            webBrowser1.Print();
        }

五:開啟偵錯程式

想開啟偵錯程式,我想看過下面這段程式碼你就知道了

        /// <summary>
        /// 顯示除錯視窗
        /// </summary>
        public void ShowDevWin()
        {
            try
            {
                if (string.IsNullOrEmpty(devToolsUrl))
                {
                    devToolsUrl = web_view.Browser.GetHost().GetDevToolsUrl(true);
                }
                var frame = web_view.Browser.GetMainFrame();
                //frame.ExecuteJavaScript(string.Format("window.open('{0}');", devToolsUrl), "about:blank", 0);
                var p = Process.Start(devToolsUrl);
            }
            catch
            {
                MessageBox.Show("請等待頁面載入完成之後再開啟偵錯程式");
            }
        }

注意!一定要把相關資源放在指定的位置!

六:讓瀏覽器執行JS指令碼

        /// <summary>
        /// 執行JS指令碼
        /// </summary>
        /// <param name="js">"CreatePage(1,2,3);"</param>
        public void RunScirpt(string js)
        {
            var frame = web_view.Browser.GetMainFrame();
            frame.ExecuteJavaScript(js, frame.Url, 0);
        }

就這樣,不多做解釋了。

--------------------------------

PS:說明:

再次感謝各位關注這個系列的朋友。

我想你們可能會對這一篇文章比較失望。

(列印那部分雖然官方沒有支援,但是我想肯定有更好的辦法解決這個問題,在做專案的時候,我偷懶了,現在寫文章,我又偷懶了。沒有做深入研究。對不起)

(文章寫的也有點匆忙,寫的不夠詳細,比前幾篇要差多了,我甚至沒有做DEMO,也無法提供原始碼了)

接下去,短期內,我估計我不會再更新這個系列了。太忙,太累。

謝謝各位!

相關文章