检测深色 windows 任务栏

Detect dark windows taskbar

为了主题化的目的,我希望检测 Windows 任务栏的颜色(在我的例子中,是托盘图标)。

我正在使用 Java,但欢迎任何解决方案,因为我很乐意根据需要转换它们。

假设我不想依赖Windows标志的white/black颜色,有没有办法检测到这一点?

相关:

目前为止,我还没有遇到注册表中缺少SystemUsesLightThemeAppsUseLightTheme的情况

但我认为重新创建键值值得一试。

这是代码示例(C++):

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <Windows.h>

using namespace std;


int main() {


    HKEY key;
    if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"), &key) != ERROR_SUCCESS)
    {
        cout << "unable to open registry";
    }

    DWORD value_data = 0;

    if (RegSetValueEx(key, TEXT("SystemUsesLightTheme"), 0, REG_DWORD, (const BYTE*)&value_data, sizeof(value_data)) != ERROR_SUCCESS)
    {
        RegCloseKey(key);
        cout << "Unable to set registry value value_name";
    }
    else
    {
        cout << "value_name was set" << endl;
    }

}

当记录的注册表项丢失时,OS 中的某些内容被编码为回退以下设置:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\

  • 如果 AppsUseLightTheme 缺失,假设它是 1
    • ...然后根据此值做出 dark/light Windowing 决策。
  • 如果 SystemUsesLightTheme 缺失,假设它是 0
    • ... 然后根据此值做出 dark/light Taskbar/SystemTray 决策。

荣耀详情...

虽然全新 Windows 主页安装默认为 Light 主题,但这些全新安装程序也正确设置了注册表项,因此缺少注册表项和浅色任务栏的组合极不可能(并且可能是不可能的)。类似地,研究现代 OSs 可能——不正确地——建议默认值来自文件 C:\Windows\resources\Themes\aero.theme**,但不要被愚弄!较早的 OS 也没有区分条目... 更多内容如下。

直觉会建议 CurrentThemeInstallTheme 注册表值可以作为合理的后备值,但更改这些值似乎是出于历史目的,似乎并没有真正改变light/dark 主题。

reg query HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes /v InstallTheme
>>> returns the path to aero.theme

type %SystemRoot%\resources\Themes\aero.theme |find "SystemMode"
>>> returns SystemMode=dark

即使更改整个机器的 InstallTheme (HKEY_LOCAL_MACHINE) 也不会修改这种偏好 SystemMode=dark 的行为(请注意,即使此条目在旧 Windows 10 个版本。例如 Windows 10 v1507 主题文件中也没有此条目。

追逐 aero.theme 也遇到了一些死胡同。尝试直接修改aero.theme因权限问题失败,但将aero.theme复制到桌面并将SystemMode=dark更改为SystemMode=light然后双击主题文件会使任务栏消失白色,但仅适用于支持浅色主题的较新 Windows 版本。

所以,是的,我必须同意@strive-sun-msft 的观点,SystemUsesLightTheme 注册表项是最佳位置。测试时,甚至任务栏本身也会对此进行监控,将其删除会将其重置为黑色。不幸的是,后备黑色任务栏颜色仍然是个谜。我只能假设它被硬编码到任务栏本身。

此行为的另一种解决方法是,如果缺少注册表项,则通过 运行 再次安装 aero.theme 文件。在较新的 Windows 10 版本中,只需 运行 此文件即可创建缺少的条目。不幸的是,这不适用于较旧的 Windows 10 版本,更糟糕的是,这将重置用户设置的所有自定义首选项。

因此,检测任务栏颜色的侵入性最小的方法是读取注册表,如果缺少密钥,只需假设 Windows10 附带的主题仍然有效:Dark Taskbar, Light Windows.

您可以使用此注册表路径中可用的 Windows 注册表值 SystemUsesLightThemeSoftware\Microsoft\Windows\CurrentVersion\Themes\Personalize 用于检测 dark/light 主题。

我找到了一个名为 JRegistry 的库,它允许您访问 这个值。

        RegistryKey windowsPersonalizeKey = new RegistryKey("Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
        RegistryValue systemUsesLightThemeValue = windowsPersonalizeKey.getValue("SystemUsesLightTheme");
        if (systemUsesLightThemeValue != null) {
            //this value is available

            //getting the actual value
            byte[] data = systemUsesLightThemeValue.getByteData();
            byte actualValue = data[0];
            boolean windows10Dark = actualValue == 0;

            if (windows10Dark) {
               //the theme is dark
            } else {
                // the theme is light
            }
        }

另外,如果你想动态监听这个值:

        RegistryKey registryKey = new RegistryKey("Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
        RegistryWatcher.addRegistryListener((RegistryEvent registryEvent) -> {
            RegistryKey changedKey = registryEvent.getKey();
            if (changedKey.equals(registryKey)) {
                RegistryValue value = changedKey.getValue("SystemUsesLightTheme");
                //....
            }
        });
        RegistryWatcher.watchKey(registryKey);