如何在.NET 中为 CefSharp Web 浏览器启用暗模式?

Ele*_*ios 7 .net c# chromium-embedded cefsharp .net-core

设想

\n

我对CefSharp很陌生,事实上,这是我第一次使用它。我在 net core 6.0 winforms 应用程序下使用它,但同样的问题和场景也适用于 .NET Framework。

\n

我正在运行 Windows 10,并且启用了操作系统暗模式,以防万一。

\n

这是我调用来初始化CefSharp环境的方法:

\n
public bool InitializeCefSharp()\n{\n    if (Cef.IsInitialized)\n    {\n        throw new InvalidOperationException("CefSharp is already initialized.");\n    }\n\n    string cachePath = $"{System.Windows.Forms.Application.StartupPath}\\\\cache\\\\CefSharp";\n\n    var settings = new CefSettings\n    {\n        CachePath = cachePath,\n        RootCachePath = cachePath,\n        CommandLineArgsDisabled = false,\n        IgnoreCertificateErrors = true,\n        Locale = "en-US",\n        PersistSessionCookies = true,\n        PersistUserPreferences = false,\n        WindowlessRenderingEnabled = false\n    };\n\n    bool success = Cef.Initialize(settings, performDependencyCheck: true);\n    return success;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注意:虽然这是 C# 代码,但我实际上使用 VB.NET 和Startup 应用程序事件来初始化CefSharp

\n
\n

问题

\n

如何为初始化的CefSharp浏览器启用深色模式?

\n

我的意图是,当在基于 CEF 的浏览器中加载网页时,它将自动使用深色主题着色。

\n

或者至少,作为最后的手段,只有一个网站解决方案,检查网络浏览器是否使用深色或浅色模式,然后网站自动调整其颜色。

\n
\n

研究

\n

请注意,正如我所说,我对CefsharpCEF API 总体来说非常陌生。

\n

关于 SetAutoDarkModeOverrideAsync 方法

\n

我发现了这个名为SetAutoDarkModeOverrideAsync的有趣方法,其描述如下:

\n
\n

使用深色主题自动渲染所有网页内容。

\n
\n

这可能是一个解决方案,但我无法找到有关如何使用它的示例。

\n

使用命令行参数

\n

这个答案显示了为基于 CEF 启用暗模式的不同命令行参数?浏览器。我们以这两个为例:

\n
    \n
  • --enable-features=WebContentsForceDark

    \n
  • \n
  • --enable-features=WebContentsForceDark:inversion_method/hsl_based/image_behavior/none/text_lightness_threshold/256/background_lightness_threshold/0

    \n
  • \n
\n

好吧,我尝试以这种方式使用这些命令行参数(在我的自定义InitializeCefSharp方法中):

\n
settings.CefCommandLineArgs.Add("--enable-features=WebContentsForceDark");\n
Run Code Online (Sandbox Code Playgroud)\n

和:

\n
settings.CefCommandLineArgs.Add("--enable-features=WebContentsForceDark:inversion_method/hsl_based/image_behavior/none/text_lightness_threshold/256/background_lightness_threshold/0");\n
Run Code Online (Sandbox Code Playgroud)\n

但没有任何效果。

\n

使用网络浏览器扩展(LoadExtensionFromDirectory 方法)

\n

在我放弃尝试命令行参数后,我想到了一种不同的方法:使用像Darkreader这样的第三方扩展

\n

所以我下载了 zip 文件,将其解压到一个文件夹中,然后使用 LoadExtensionFromDirectory方法在浏览器上加载扩展程序:

\n
string extensionDirectory = @"C:\\darkreader-chrome";\nvar extensionHandler = new ExtensionHandler();\nChromiumWebBrowser1.GetBrowserHost().RequestContext.LoadExtensionFromDirectory(extensionDirectory, extensionHandler);\n
Run Code Online (Sandbox Code Playgroud)\n

但它实际上破坏了网络浏览器实例;它不会加载/导航到任何网页,也不会响应。

\n

它就是行不通,或者至少不是我尝试过的方式。

\n

使用网络浏览器扩展(LoadExtension 方法)

\n

如果我以这种方式使用LoadExtension方法:

\n
string extensionDirectory = @"C:\\darkreader-chrome";\nvar extensionHandler = new ExtensionHandler();\nChromiumWebBrowser1.GetBrowserHost().RequestContext.LoadExtension(extensionDirectory, null, extensionHandler);\n
Run Code Online (Sandbox Code Playgroud)\n

我得到了相同的结果:网络浏览器坏了。

\n

深入研究网络浏览器扩展的使用情况

\n

我还尝试使用此问题中显示的命令行参数集来遵循相同的步骤并最大化扩展加载兼容性,但没有成功。

\n

在该问题的评论部分有一个有用的超链接,指向本文,其中提到了以下重要内容:

\n
\n

CefSharp 的实现很少,并且大多数扩展都不起作用。

\n

CefSharp 支持这些扩展,但大多数都不起作用。这是因为扩展需要特殊的浏览器 API,其中超过 70 个。而 CEF 只有 4\xe2\x80\x94 是内置 PDF 查看器所需的一小部分。

\n
\n

所以在我看来,使用像DarkReader这样的扩展来启用黑暗模式并不是一个可行的解决方案。

\n

然而,我还发现这个答案证实了上述命令行参数和DarkReader扩展都适用于基于 chrome 的浏览器。但我无法在CefSharp中使用任何这些解决方法。

\n

关于prefers-color-scheme

\n

我找到了关于CefSharp的答案,其中提到了来自 Mozilla 的文档文章prefers-color-scheme

\n

老实说,我对如何使用或修改该 CSS 以及在哪里使用它一无所知,所以我向ChatGPTprefers-color-scheme寻求有关使用CefSharp的帮助,而我得到的答案对我来说毫无用处,是使用这样的代码在加载的网页文档中设置自定义属性:

\n
string script = "document.documentElement.setAttribute(\'data-theme\', \'dark\');";\nbrowser.ExecuteScriptAsync(script);\n
Run Code Online (Sandbox Code Playgroud)\n

...是的,ChatGPT再次愚弄了我,回答了一些似乎与我刚才问他的问题无关的问题。

\n

而且我在 CSS 方面没有足够的经验,无法使用prefers-color-scheme.

\n

更改背景颜色

\n

BrowserSettings.BackgroundColor /属性描述了如何更改CefSharp Web 浏览器控件的背景颜色,但正如预期的那样,它仅在 Web 浏览器中没有加载页面时才会生效CefSettings.BackgroundColor

\n

关于使用自定义深色配色方案

\n

无论如何,我的目的不是创建自定义深色方案或任意将所有加载页面的背景设置为深色,因为根据哪些页面及其文本颜色以及其他 html 元素的颜色,这会太冲突。所以我认为制作一个与所有类型的网页完美兼容的自定义深色配色方案太复杂了。

\n

我确信一定有一个更优化和“安全”或兼容的解决方案(比创建自定义深色方案颜色),例如我在本研究部分开头提到的基于 HSL 颜色反转方法的命令行参数。

\n
\n

最后的话

\n

这是我第一次使用CefSharp,我花了很多时间和精力尽力找到这个问题的解决方案,一般来说我对 CEF 和 Chromium (以及 Html / CSS)知之甚少,但是执行一些应该像在该死的CefSharp浏览器中设置深色或浅色模式一样简单和容易的事情。对我来说这似乎很复杂,但其实不应该如此。

\n

Jan*_*ann 3

正如您链接的问题中所述,CEF 能够检测操作系统设置本身。就我而言,我必须在app.manifest文件中取消注释 Windows 10 的兼容性条目:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
  <application>
    <!-- ... -->

    <!-- Windows 10 -->
    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

  </application>
</compatibility>
Run Code Online (Sandbox Code Playgroud)

设置此选项后,带有单个ChromiumWebBrowser控件的最小 Windows 窗体应用程序会自动检测系统的颜色设置。


但是,您也可以通过以下方式在 CEF 浏览器控件中强制使用深色模式(即)prefers-color-scheme: dark

browser.GetDevToolsClient().Emulation.SetAutoDarkModeOverrideAsync(true);
Run Code Online (Sandbox Code Playgroud)

这会检索浏览器DevToolsClient和相应的设备模拟功能,该功能允许配置许多设置,包括强制使用暗模式。


我已经使用以下最小 HTML 页面(存储在浏览器中path/to/test.html然后通过file:///path/to/test.html浏览器加载)测试了这两种方法:

<!DOCTYPE html>
<html>
  <head>
    <title>Test page</title>
    <style>
        body {
            background-color: white;
            color: black;
        }

        @media (prefers-color-scheme: dark) {
          body {
            background-color: black;
            color: white;
          }
        }
    </style>
  </head>
  <body>
    <h1>Dark mode test</h1>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)