
在我的博客《C#開發BIMFACE系列52 CS客戶端集成BIMFACE應用的技術方案》中介紹了多種集成BIMFACE到客戶端程序中的方案。最后推薦大家使用 CefSharp組件與WebView2組件。本篇文章介紹使用CefSharp組件如何集成BIMFACE到客戶端程序中。
CefSharp是一個圍繞Chromium Embedded Framework(CEF)的輕量級.NET包裝器。它是用C++/CLI編寫的。允許開發者在.NET應用程序中嵌入Chromium。可以在C#或VB或任何其他CLR語言中使用。CefSharp同時提供WPF和WinForms Web瀏覽器控件實現。
功能特點
- 免費、開源:https://github.com/cefsharp/CefSharp
- 完善的文檔
- 支持JS、C#、WinForm窗體之間相互通訊與調用
- 兼容性較好,支持H5、CSS5、WebGL等
- 支持獲取Cookies較全面
- 其他
步驟1 新建WinForm項目
新建一個WinForm窗體應用程序,目標框架選擇 .NET Framework 4.5.2,因為新版本的CefSahrp組件最低支持 .NET Framework 4.5.2。
步驟2 通過 NeGet 下載
打開NeGet
(1)搜索 CefSharp
(2)選擇 CefSharp.WinForms
(3)選擇最新版本
(4)點擊【安裝】按鈕
點擊【確定】開始安裝。
安裝完成后,項目中自動添加了CefSharp.dll、CefSharp.Core.dll、CefSharp.WinForms.dll 類庫引用。
工具箱中也增加了CefSharp控件
步驟3 編譯項目
編譯 BIMFace.SDK.CSharp.Sample.WinForm 項目,生成如下內容
與 CefSharp 相關的共計32個文件,2個目錄,文件大小總計216M。這個尺寸相對於業務系統本身來說已經非常大了,最后制作的安裝包尺寸也會很大。
其中 locales 目錄下是語言包,刪除 zh-CN.pak 之外的所有文件,總文件大小可以減少22M左右。
測試功能設計如下
功能說明
(1)WinForm中加載的網頁來自於 BIMFace.SDK\BIMFace.SDK.CSharp.Sample\Pages\BIMFaceDemo7_3.html,所以Web項目要首先運行。
(2)WinForm 窗體中輸入 BIMFACE FileId,點擊【加載模型/圖紙】按鈕,調用CefSahrp組件,加載步驟(1)中的網頁。代碼如下:
1 // 加載模型/圖紙 2 private void btnLaodBIMFaceFile_Click(object sender, EventArgs e) 3 { 4 string fileId = txtBIMFaceFileId.Text.Trim(); 5 if (string.IsNullOrEmpty(fileId)) 6 { 7 MessageBox.Show("請填寫 BIMFACE FileId。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); 8 return; 9 } 10 // 將 ChromiumWebBrowserBindObject 實例對象注入到 js 對象中。網頁中即可調用 ChromiumWebBrowserBindObject 類中定義的屬性、方法 11 var objToBind = new ChromiumWebBrowserBindObject(); 12 chromiumWebBrowser1.JavascriptObjectRepository.Register("_chromeBrowser", objToBind, true, BindingOptions.DefaultBinder); 13 14 string url = "https://localhost:44389/Pages/BIMFaceDemo7_3.html?fileId=" + fileId; 15 chromiumWebBrowser1.Load(url); 16 }
(3)網頁中點擊【JS 調用 C# 方法】按鈕。代碼如下:
在入口函數中,獲取注入的 ChromiumWebBrowser 對象,名稱為 _chromeBrowser。
按鈕對應的js方法
1 // js 調用 C# 方法 2 function callCharpMethod() { 3 // 特別提醒:C# 類中定義的方法名稱采用 Pascal 命名。網頁中調用的時候必須將方法名稱的第一個字母改為小寫。否則調用不成功。 4 _chromeBrowser.testCalcAdd(6,8) 5 .then(function (response) { 6 alert(response); 7 }); 8 }
特別提醒:C# 類中定義的方法名稱采用 Pascal 命名。網頁中調用的時候必須將方法名稱的第一個字母改為小寫。否則調用不成功。
調用的C#方法。定義一個單獨的類,用於在CefSahrp組件加載網頁之前,將其注入到網頁中
(4)WinForm窗體中點擊【 C# 調用 JS 方法】按鈕。代碼如下:
1 // C# 調用 JS 方法 2 private void btnCsharpCallJsMethod_Click(object sender, EventArgs e) 3 { 4 Task<JavascriptResponse> jsResponse = chromiumWebBrowser1.EvaluateScriptAsync("jsMethodForCSharpTestCalcSub", 25, 7); 5 6 if (jsResponse.Result != null && jsResponse.Result.Success == false) 7 { 8 MessageBox.Show("C#調用JS方法發生異常。" + jsResponse.Result.Message 9 , "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 10 } 11 }
網頁中定義的 jsMethodForCSharpTestCalcSub() 方法如下:
1 // js 方法,供C#調用 2 function jsMethodForCSharpTestCalcSub(num1, num2) { 3 /*如果參數需要是復雜類型,則傳遞Json格式的字符串,然后反序列化為對象即可使用*/ 4 5 alert('傳入的參數num1:' + num1 + ", num2:" + num2 + ' 減法運算 num1 - num2 = ' + (num1 - num2)); 6 }
特別說明:
(1)C#定義的方法供JS調用,C#方法的返回值類型、參數類型都只能是簡單數據類型,如:int、string、bool 等。
(2)JS定義的方法供C#調用,JS方法的返回值類型、參數類型都只能是簡單數據類型,如:int、string、bool 等。
一般來說復雜類型就是一個實體類。如果確實想使用復雜類型,建議的解決方案如下:
將復雜類型序列化為字符串,調用方將其反序列化之后再使用。
關於C#與JS互相通訊,請參考CefSahrp官方文檔:https://github.com/cefsharp/CefSharp/wiki/General-Usage#3-how-do-you-expose-a-net-class-to-javascript
1、進程分析
(1)啟動應用程序,CefSharp組件未加載Web網頁時,默認啟動了2個 CefSharp.BrowserSubProcess 子進程。原因是我當前使用的CefSharp是94.4.50版本,每當new CefSharp.WinForms.ChromiumWebBrowser() 一個時,會啟動2個子進程。
(2)CefSharp組件加載Web網頁后,又啟動了2個 CefSharp.BrowserSubProcess 子進程,共計4個子進程。原因是 當 chromiumWebBrowser1.Load(url) 時啟動2個子進程。不同版本的 CefSharp 組件,啟動的子進程數量不同。
2、運行日志分析
GPUCache目錄內容如下。BIMFACE加載模型/圖紙時利用了本地電腦的GPU強大的計算功能,所以產生了緩存內容。
debug.txt 內如如下,里面記錄了網頁的執行過程
- 通過NeGet安裝SDK時,運行時環境會被自動下載到當前項目的bin\debug 或者 bin\Release目錄下。導致整個項目非常大,大約220M左右。
- 以獨立進程方式運行,消耗內存較多。
如下是我的一個WinForm程序中使用CefSharp組件的運行狀態,其中一個子進程消耗內存達到1.5G,太可怕了
- 當控件Dock屬性設置為 Fill,客戶端電腦的縮放與布局不是100%時,窗體呈現黑邊(嚴重bug),並沒有完全填充父容器。
《BIMFace.SDK.CSharp》開源SDK。歡迎大家下載使用。
