一、背景
最開始准備使用的 Chromely 做一個終端機項目,本來以為挺順利的一個事情折騰了兩天半。由於無法直接控制窗體的屬性,最后還是切換到 .NET Framework 4.8 + CefSharp,記錄一下遇到的坑和問題。
二、問題
2.1 輸入法無法彈出
終端機系統最開始是 Windows 7,系統自帶的輸入法無法輸入中文,后面使用的多文輸入法有時候能夠輸入有時候不能夠輸入。最后折騰了半天,咨詢廠家可以安裝 Windows 10,安裝后系統自帶輸入法可以輸入中文。
新的問題又出現了,如果窗口沒有全屏的情況下,輸入法是可以將內容輸入到網頁的文本框。但是窗口置頂且全屏,觸摸 輸入的內容就像無法獲取焦點一樣,無法輸入。
爬了很多網站,都沒有給出個明確的答案,最后在 某篇 Issue 里面說將 browser.FocusHandler
屬性設置為 null
,解決該問題。
2.2 重寫右鍵菜單
這個問題比較簡單,只需要重新實現 IMenuHandler
接口,替換掉 Cef Browser 的對應組件即可。
示例:
public class CustomMenuHandler : IContextMenuHandler
{
public void OnBeforeContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
{
model.Clear();
model.AddItem((CefMenuCommand) 21000, "菜單項1");
}
public bool OnContextMenuCommand(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId,
CefEventFlags eventFlags)
{
if (commandId == (CefMenuCommand) 21000)
{
MessageBox.Show("我是菜單項1");
}
return false;
}
public void OnContextMenuDismissed(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame)
{
}
public bool RunContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model,
IRunContextMenuCallback callback)
{
return false;
}
}
2.3 身份證讀卡器對接
身份證讀卡器終端機上面是集成新中新的,跟着 SDK 的 Demo 來,一跑程序就炸。沒有跑出任何異常,最后發現是 Chromely 吞掉了異常。實際的錯誤問題是 DLL 的版本不對,新中新只提供了 x86 的 DLL,但程序編譯的是 x64。最后將程序的目標平台改為 x86 解決問題。
2.4 前端同后端通訊
其實就是 JS 調用后端的接口,之前搜索的文章都是 CefSharp 的老版本代碼,最新的是使用 browser.JavascriptObjectRepository.Register()
注入處理器,然后前端再進行調用。具體代碼可以參考 CefSharp 的 官方 Demo。
2.5 打開調試窗口
CefSharp Browser 提供了一個 ShowDevTools()
方法用於打開調試窗口,需要注意的是,必須在瀏覽器完全初始化之后才能夠調用。所以你需要判斷一下 CefSharp Browser 的狀態。
browser.IsBrowserInitializedChanged += (sender, args) =>
{
if (browser.IsBrowserInitialized)
{
browser.ShowDevTools();
}
};
2.6 關於觸屏的其他配置
在 Cef 初始化的時候,需要對 Cef 進行一些其他的配置,例如開啟觸屏事件、禁用 USB 鍵盤等。
private static void InitializeCef()
{
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
Cef.EnableHighDPISupport();
var settings = new CefSettings();
settings.CefCommandLineArgs.Add("disable-usb-keyboard-detect", "1");
settings.CefCommandLineArgs.Add("enable-media-stream", "1");
settings.CefCommandLineArgs.Add("touch-events", "1");
Cef.Initialize(settings);
}
2.7 允許前端跨域和調用攝像頭
在 [2.6](#2.6 關於觸屏的其他配置) 一節中,我通過添加 enable-media-stream
參數讓前端可以直接調用攝像頭。如果想要讓前端發起跨域請求,就得在 Browser 里面將 WebSecurity
屬性設置為 Disabled
。
browser.BrowserSettings.WebSecurity = CefState.Disabled;
2.8 下載文件
CefSharp 針對於前端的下載文件動作進行了處理,如果你對於這個動作有自己的處理邏輯,可以實現 IDownloadHandler
接口。然后在 Browser 的對應屬性替換成你自己的實現即可。