1. 程式人生 > >基於.net開發chrome核心瀏覽器【三】

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



本篇我們講解怎麼用CefGlue開發一個最簡單的瀏覽器

一:

CefGlue是建立在Cef專案之上的,
Cef專案是C/C++的專案;
CefGlue只不過是通過PInvoke來訪問Cef專案生成的一些dll
下面我們來看看Cef專案生成的一些dll和資源都是做什麼用的
開啟這個目錄\cef_binary_3.1453.1236_windows_xilium\Release
libcef.dll-------------------------->Cef的核心類庫
icudt.dll-------------------------->支援unicode的類庫
ffmpegsumo.dll------------------>支援音訊和視訊的類庫
d3dcompiler_43.dll--------------->WinXP下支援3D的類庫
d3dcompiler_46.dll--------------->Win7和之後的Win支援3D的類庫
libEGL.dll------------------------->用於支援3D
libGLESv2.dll--------------------->用於支援3D


開啟目錄:\cef_binary_3.1453.1236_windows_xilium\Resources
locales--------------------------->此資料夾存放了各種國家的語言資源
cef.pak-------------------------->為WebKit相關的資源(谷歌瀏覽器的核心是webkit)
devtools_resources.pak--------->偵錯程式的相關資源(我們做的專案是可以使用谷歌瀏覽器的偵錯程式的)

二:


建立一個winform工程,取名加CefDemo
在程式集中建立一個資料夾取名dll
在程式集的屬性裡設定此程式集的預先生成事件的命令


xcopy $(ProjectDir)dll $(TargetDir) /e /i /y
這個命令的目的是:每次編譯的時候把dll資料夾中的檔案拷貝的輸出目錄中


把\cef_binary_3.1453.1236_windows_xilium\Release此目錄下的所有檔案都拷貝到CefDemo的dll目錄中去
把\cef_binary_3.1453.1236_windows_xilium\Resources此目錄下的所有檔案和資料夾拷貝到dll目錄中去
注意:locales子目錄下的檔案大部分都沒有用,你可以把所有的檔案都刪掉,只留下zh-CN.pak檔案。
開啟Xilium.CefGlue工程,release編譯CefGlue程式集,把生成的Xilium.CefGlue.dll也拷貝到CefDemo的dll目錄中去
在CefDemo專案中新增Xilium.CefGlue.dll的引用


三:


修改Program.cs的程式碼:
static void Main()
        {
            CefRuntime.Load();
            var mainArgs = new CefMainArgs(new string[] { });
            var exitCode = CefRuntime.ExecuteProcess(mainArgs, null);
            if (exitCode != -1)
                return;
            var settings = new CefSettings
            {
                SingleProcess = false,
                MultiThreadedMessageLoop = true,
                LogSeverity = CefLogSeverity.Disable,
                Locale = "zh-CN"
            };
            CefRuntime.Initialize(mainArgs, settings, null);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if (!settings.MultiThreadedMessageLoop)
            {
                Application.Idle += (sender, e) => { CefRuntime.DoMessageLoopWork(); };
            }
            Application.Run(new CefBrowser());
            CefRuntime.Shutdown();
        }


我們來一點一點解釋這些程式碼:


CefRuntime.Load();
此行程式碼用於載入CEF的執行時
————————————————————————
var mainArgs = new CefMainArgs(new string[] { });
此行程式碼可以收集命令列引數,用於傳遞給CEF瀏覽器
————————————————————————
var exitCode = CefRuntime.ExecuteProcess(mainArgs, null);
if (exitCode != -1)
return;
以上程式碼用於啟動第二個程序,至於用第二個程序做什麼,我沒有深入研究過(可以是瀏覽器的第二個程序、也可以是一個可執行檔案的)
注意:CefRuntime.ExecuteProcess方法必須在程式的入口處呼叫;
——————————————————————————
var settings = new CefSettings
{
   SingleProcess = false,
   MultiThreadedMessageLoop = true,
   LogSeverity = CefLogSeverity.Disable,
   Locale = "zh-CN"
};


CEF的配置引數,有很多引數,我們這裡挑幾個解釋一下:
SingleProcess = false:此處目的是使用多程序。
注意:強烈不建議使用單程序,單程序不穩定,而且Chromium核心不支援
MultiThreadedMessageLoop = true:此處的目的是讓瀏覽器的訊息迴圈在一個單獨的執行緒中執行
注意:強烈建議設定成true,要不然你得在你的程式中自己處理訊息迴圈;自己呼叫CefDoMessageLoopWork()
Locale = "zh-CN":webkit用到的語言資源,如果不設定,預設將為en-US
注意:可執行檔案所在的目錄一定要有locals目錄,而且這個目錄下要有相應的資原始檔
——————————————————————————————
CefRuntime.Initialize(mainArgs, settings, null);
這句程式碼把建立的配置資訊和命令列資訊傳遞個cef的執行時
此函式必須在應用程式的主執行緒中呼叫
——————————————————————————————
if (!settings.MultiThreadedMessageLoop)
{
   Application.Idle += (sender, e) => { CefRuntime.DoMessageLoopWork(); };
}


如果你在前面設定的MultiThreadedMessageLoop為false,
那麼你可以加入如上程式碼,自行呼叫CefRuntime.DoMessageLoopWork();
——————————————————————————————
CefRuntime.Shutdown();
主程序結束時,要釋放CEF的資源,並結束瀏覽器的程序。


四:


在工程中建立一個窗體,
在設計檢視中,把視窗調整到合適的大小
(你想讓瀏覽器變成多大,就調整到多大)
然後我們調整一下這個窗體的一些屬性
  this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "CefBrowser";
            this.Text = "最簡單的實現";


在這篇文章提供的例子,還沒有實現瀏覽器隨著容器窗體的大小變化而變化
所以:我們在這裡禁用了視窗的最大化功能,也禁用了拖動改變視窗大小的功能。


五:


在視窗的建構函式中加入如下程式碼:
var cwi = CefWindowInfo.Create();
cwi.SetAsChild(this.Handle, new CefRectangle(0, 0, this.Width, this.Height));
var bc = new BrowserClient();
var bs = new CefBrowserSettings() { };
CefBrowserHost.CreateBrowser(cwi,bc, bs,"http://www.cnblogs.com/liulun");

然後執行程式,你就看到了一個瀏覽器,如下圖:


雖然沒有滾動條,視窗也不能拖動改變大小
但是當你把滑鼠移動到網頁上之後,滾動滑鼠滾輪,網頁還是會跟著滾動的。

六:

下面我們來詳細解釋一下上面幾句程式碼的意義

CefWindowInfo是CEF瀏覽器視窗實現的類,其中包含了在windows、linux、MAC下的具體實現
此類中的Create靜態方法負責建立這個類的例項,
我在windows下執行這一句,將得到windows下CEF瀏覽器的實現方式
------------------
cwi.SetAsChild(this.Handle, new CefRectangle(0, 0, this.Width, this.Height));
此行程式碼負責把建立的CEF瀏覽器視窗與我們建立的winform視窗結合起來
this.Handle就是我們建立的winform視窗的控制代碼
SetAsChild函式使CEF瀏覽器視窗作為winform視窗的子視窗呈現
CefRectangle標誌著CEF瀏覽器視窗將出現在父視窗中的位置和大小
-------------------
var bc = new BrowserClient();
BrowserClient是我在工程中新建的一個類
這個類沒有任何邏輯和屬性,只是繼承了CefClient類
CefClient類有很多虛方法以供重寫,
比如GetDisplayHandler、GetDownloadHandler、GetJSDialogHandler等等
注意:此類很重要,我們將在接下來的章節中為這個類新增很多內容
---------------------
var bs = new CefBrowserSettings() { };
之前我們在Program中設定的是CefSettings
那是針對CEF環境的一些全域性設定
這裡是CefBrowserSettings
這是針對CEF瀏覽器環境的一些全域性設定
可以在這裡配置的引數有很多
比如:
DefaultEncoding(用於所有網頁內容的編碼方式,預設為ISO-8859-1)
UserStyleSheetLocation(用於所有網頁的樣式,應該按照這樣的格式設定這個欄位:data:text/css;charset=utf-8;base64,[csscontent])
RemoteFonts(用於所有網頁的字型)
JavaScript(用於所有網頁是否可以執行JS指令碼)
JavaScriptOpenWindows(用於所有網頁是否可以通過JS來開啟視窗)
(還有很多類似的設定,讀者可以自己去研究)
----------------------------
CefBrowserHost.CreateBrowser(cwi,bc, bs,"http://www.cnblogs.com/liulun");
程式碼執行到這一行即開始建立瀏覽器子視窗
CreateBrowser前面三個引數不用多說了
最後一個引數就是你想讓瀏覽器訪問的頁面
注意:這個方法是非同步執行的(非阻塞的),也就是說你無法知道什麼時候視窗被創建出來,(通過其他方式可以註冊視窗建立成功的事件,以後再講。)

原始碼下載:

修改記錄:
2013-4-22:建立文章,並完成了一部分內容
2013-4-29:添加了文章的一部分內容,碰到問題停滯不前。
2013-5-02:解決掉問題,更新並添加了大部分內容,修改了文章的排版
2013-5-11:增加了最後一部分內容,修改了排版,通讀文章,糾正錯別字