CefSharp自定義捲軸樣式

czwy發表於2023-10-07

在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中,IBrowserIFrame物件用於向瀏覽器傳送命令和在回撥方法中獲取狀態資訊,每個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樣式。
image

相關文章