UI(User Interface)是人機系統當中相當重要的部分,由於現代軟體的呈現模式非常多元,從傳統的 Desktop,到 Web、App,甚至 AR、MR、...等等,以致於一個開發者要通透所有 UI 設計工具幾乎是不可能的,所以當我們設計好一套 UI 之後,能夠有個工具幫忙照搬到其他的開發框架上是最好不過的,本文要介紹的 CefSharp 是一套可以將我們寫好的網頁,直接搬到 WinForms/WPF 上使用的套件,想要開發 Windows 視窗應用程式,身邊卻只有會網頁設計的開發人員可以配合設計 UI 時,CefSharp 就可以幫助我們把網頁設計師開發好的網頁,無縫地直接搬到 WinForms/WPF 上使用,省時又省力。
CefSharp 是基於 Chromium Embedded Framework(CEF)所開發出來的 .NET 套件,它將 Chromium 瀏覽器封裝成一個 WinForms/WPF 的控制項,直接跟 WinForms/WPF 整合在一起,雖然微軟自家有 Microsoft Edge WebView2,但是目前使用上還是有一些問題有待完善(參考:WebView2 使用及現狀),而且 CefSharp 還有一個吸引我的地方,就是我用 .NET Core 開發好獨立部署出去之後,無論使用者的電腦是 Windows PC,還是 Windows Server,主流版本幾乎都可以點兩下直接執行就好。
起手式
首先先透過 NuGet 把 CefSharp 安裝起來,它幾乎是跟著 Chromium 版本更新的,使用上也很簡單,我以 .NET Core 3.1 WinForms 專案為範例,只要三行程式碼就可以把 Chromium 瀏覽器加進來,並且開啟想要瀏覽的網頁。
public Form1()
{
this.InitializeComponent();
var browser = new ChromiumWebBrowser { Dock = DockStyle.Fill };
browser.LoadUrl("https://html5test.com/");
this.Controls.Add(browser);
}
載入自己開發的網頁檔
把 Chromium 瀏覽器內嵌進 Windows 視窗應用程式,主要當然不是為了要瀏覽線上某個網址,而是要來瀏覽我們自己開發的網頁檔,而且如果是正式的專案通常網頁不會只有一頁,下面我要來介紹兩種載入網頁檔的方式。
1. 內建的 FolderSchemeHandlerFactory
第一種方式是使用 CefSharp 內建的 FolderSchemeHandlerFactory
,我們將網頁檔加進專案之後,接著編輯專案檔,直接指定網頁檔資料夾底下的所有檔案為建置的內容,並且永遠複製到輸出目錄。
接著我們在 Program.cs
加入一段程式碼,用來自訂 Scheme 資訊,其中比較特別的是 SchemeName
及 DomainName
我們也可以自訂,最後 SchemeHandlerFactory
的部分我們就指定為 FolderSchemeHandlerFactory。
[STAThread]
static void Main()
{
var settings = new CefSettings();
settings.RegisterScheme(
new CefCustomScheme
{
SchemeName = "chef",
DomainName = "appcookhouse",
SchemeHandlerFactory = new FolderSchemeHandlerFactory(@"Views", defaultPage: "index.html")
});
Cef.Initialize(settings);
//...
}
然後在呼叫 browser.LoadUrl()
的時候,參數改傳入 chef://appcookhouse/
,我們指定的預設頁面就被載入了。
而我們指定的網頁檔資料夾就成了網站的根目錄,我們完全可以使用相對路徑來連結資料夾內的其他檔案。
2. 實作 ISchemeHandlerFactory 自訂 SchemeHandlerFactory
如果我們想把我們的網頁弄成內嵌資源,而不是以檔案的方式存在,那麼瀏覽路徑的檔案對應我們就得自製 SchemeHandlerFactory
來處理,我把網頁檔資料夾內的檔案全部指定為內嵌資源後,建立了一個 ResourcesSchemeHandlerFactory
並且實作 ISchemeHandlerFactory
。
public class ResourcesSchemeHandlerFactory : ISchemeHandlerFactory
{
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
var fileName = new Uri(request.Url).AbsolutePath;
if (fileName == "/") fileName = "/index.html";
// 網址轉換為資源名稱
var resourceName = Regex.Replace(fileName.Replace("/", "."), "\\.(\\d)", "._$1");
// 從內嵌資源讀取網頁檔
var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream($"NetCoreCefSharpLab.Views{resourceName}");
if (resource != null)
{
var fileExtension = Path.GetExtension(fileName);
fileExtension = string.IsNullOrEmpty(fileExtension) ? ".html" : fileExtension;
return ResourceHandler.FromStream(resource, mimeType: Cef.GetMimeType(fileExtension));
}
return null;
}
}
接著將 SchemeHandlerFactory 指定為 ResourcesSchemeHandlerFactory,此時網頁就改從內嵌資源載入。
CefSharp 的基本使用方式就先介紹到這邊,官方有一篇 General Usage 值得看一看,相當於是 CefSharp 的使用指南,希望對大家有一點幫助。