CefSharp自定义滚动条样式

在WinForm/WPF中使用CefSharp混合开发时,通常需要自定义滚动条样式,以保证应用的整体风格统一。本文将给出一个简单的示例介绍如何自定义CefSharp中滚动条的样式。

基本思路

在前端开发中,通过CSS来控制滚动条的样式是件寻常的事情。CefSharp也提供了功能强大的API方便开发人员使用c#与JS进行交互。这也给我们提供了一个思路:在CefSharp加载完成后,使用其提供的ExecuteJavaScriptAsync方法注入JS和CSS代码来自定义滚动条样式。

实现细节

为了排除干扰以及方便介绍,本文直接从GitHub上下载CefSharp.MinimalExample的示例代码进行修改。

首先用CSS定义滚动条的样式,介绍滚动条组成部分以及通过CSS控制其样式的文章挺多,这里直接贴代码。

复制代码
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-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样式。

相关推荐
码界奇点1 天前
基于eBPF技术的高性能网络防火墙系统设计与实现
开发语言·网络·毕业设计·php·wpf·go语言·源代码管理
cjp5601 天前
022.WPF 封装TextBox控件限制只输入数字自定义属性
wpf
cjp5601 天前
021.WPF 以MVVM模式控制combox控件显示/隐藏
wpf
小北方城市网2 天前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
流水线上的指令侠2 天前
补充说明——针对《C#:从 0 到 1 创建基于 NUnit + FlaUI 的 WPF UI 自动化测试项目》
功能测试·ui·c#·自动化·wpf
流水线上的指令侠2 天前
C# 实战:从 0 到 1 搭建基于 NUnit + FlaUI 的 WPF UI 自动化测试项目
功能测试·ui·c#·自动化·wpf·visual studio
贾修行2 天前
.NET 全栈开发学习路线:从入门到分布式
c#·.net·wpf·asp.net core·web api·winforms·services
晓13132 天前
第四章:Redis实战应用及常见问题(下篇)
java·数据库·缓存·wpf
掘根3 天前
【jsonRpc项目】客户端的Requestor模块,RpcCaller模块
wpf
FuckPatience3 天前
WPF ListBoxItem绑定自己在ListBox中的顺序
wpf