在WinForm/WPF中使用CefSharp混合開發時,通常需要自定義捲軸樣式,以保證應用的整體風格統一。本文將給出一個簡單的示例介紹如何自定義CefSharp中捲軸的樣式。
基本思路
在前端開發中,透過CSS來控制捲軸的樣式是件尋常的事情。CefSharp也提供了功能強大的API方便開發人員使用c#與JS進行互動。這也給我們提供了一個思路:在CefSharp載入完成後,使用其提供的ExecuteJavaScriptAsync
方法注入JS和CSS程式碼來自定義捲軸樣式。
實現細節
為了排除干擾以及方便介紹,本文直接從GitHub上下載CefSharp.MinimalExample的示例程式碼進行修改。
首先用CSS定義捲軸的樣式,介紹捲軸組成部分以及透過CSS控制其樣式的文章挺多,比如MDN Web Docs。這裡直接貼程式碼。
/*定義捲軸高寬及背景 高寬分別對應橫豎捲軸的尺寸*/
::-webkit-scrollbar
{
width: 6px;
height: 6px;
background-color: #FFF;
cursor:pointer;
}
/*定義捲軸軌道 內陰影+圓角 */
::-webkit-scrollbar-track
{
box-shadow: inset 0 0 6px rgba(155,155,155,0.3);
border-radius: 5px;
background-color: #FFF;
cursor:pointer;
}
::-webkit-scrollbar-button
{
display: none;
}
/*定義滑塊 內陰影+圓角*/
::-webkit-scrollbar-thumb
{
border:1px solid #c6c6c6;
border-radius: 5px;
background: #c6c6c6;
cursor:pointer;
background-repeat: no-repeat;
background-position:center;
}
接下來就是把CSS樣式注入到CefSharp中,按照CefSharp的wiki描述,JavaScript指令碼只能在V8Context
中執行,並且是在Frame級別執行。對於沒有上下文的在Frame,一旦在Frame載入,就可以使用IFrame.ExecuteJavaScriptAsync
建立V8Context
。
在CefSharp中,IBrowser
和IFrame
物件用於向瀏覽器傳送命令和在回撥方法中獲取狀態資訊,每個IBrowser
物件都有一個主IFrame
物件表示頂層frame(MainFrame),零個或多個IFrame物件表示子frame。
為了儘早把CSS樣式注入到CefSharp中,可以在監聽Browser.FrameLoadEnd
事件並執行指令碼。
public MainWindow()
{
InitializeComponent();
Browser.FrameLoadEnd += Browser_FrameLoadEnd;
}
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
if (e.Frame.IsMain)
{
//這裡的style就是上一個程式碼片段中css樣式的字串
AddStyle(style);
}
}
/// <summary>
/// 新增CSS樣式表
/// </summary>
/// <param name="style">樣式內容</param>
public void AddStyle(string style)
{
if (string.IsNullOrEmpty(style)) return;
StringBuilder sb = new StringBuilder();
sb.AppendLine("{let script = document.createElement('style');");
sb.Append("let node=document.createTextNode('").Append(style.Replace("\n", string.Empty).Replace("\r", string.Empty)).Append("');");
sb.AppendLine("script.appendChild(node);");
sb.AppendLine("let elements = document.getElementsByTagName('head');");
sb.AppendLine("if(elements.length>0){elements[0].appendChild(script);}");
sb.AppendLine("else if( (elements = document.getElementsByTagName('body')).length>0){elements[0].appendChild(script);}}");
Browser.GetMainFrame().ExecuteJavaScriptAsync(sb.ToString());
}
實現效果如下,捲軸的樣式已被修改。在CefSharp的開發者工具中也可以看到注入的CSS樣式。