Reputation: 7922
For theming purposes, I'm looking to detect the color of the Windows taskbar (in my case, for a tray icon).
I'm using Java, but any solutions are welcome as I'd happily convert them over as needed.
My second attempt was to take a screenshot of the taskbar and try to guess if it's dark or light themed.
This even works when autohide is on. Unfortunately it returns a black background regardless of what I do:
WinDef.HWND tray = User32.INSTANCE.FindWindow("Shell_TrayWnd", null);
BufferedImage bi = GDI32Util.getScreenshot(tray);
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, new JLabel((new ImageIcon(bi)))));
Assuming I don't want to rely on the white/black color of the Windows logo, is there a way to detect this?
Related:
Upvotes: 4
Views: 1633
Reputation: 21
You can use the Windows Registry Value SystemUsesLightTheme
that is available at this Registry Path: Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
for detecting the dark/light theme.
I found a library called JRegistry that allows you to access this value.
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
}
}
Also, if you want to listen to this value dynamically:
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);
Upvotes: 2
Reputation: 7922
When the documented registry entries are missing, it appears something in the OS is coded to fallback the following settings:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\
AppsUseLightTheme
is missing, assume it's 1
SystemUsesLightTheme
is missing, assume it's 0
The glory details...
Although fresh Windows Home installs defaults to the Light
theme, these fresh installers also set the registry keys properly, so the combination of a missing registry key and a light taskbar is extremely unlikely (and probably impossible). To a similar point, studying modern OSs may -- improperly -- suggest the defaults come from the file C:\Windows\resources\Themes\aero.theme
**, but don't be fooled! Older OSs didn't have a differentiating entry either... More below.
Instinct would suggest that the CurrentTheme
or perhaps the InstallTheme
registry values would serve as a sane fallback value, but changing these values appear to be for historical purposes and do not appear to actually change the light/dark theme.
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
Even changing the InstallTheme
for the entire machine (HKEY_LOCAL_MACHINE
) doesn't modify this behavior of preferring SystemMode=dark
(note, even this entry wasn't available in older Windows 10 versions. For example, Windows 10 v1507 doesn't have this entry in the theme file either).
Chasing the aero.theme
hit some dead ends too. Attempts to directly modify aero.theme
failed due to permissions, but copying aero.theme
to the Desktop and changing SystemMode=dark
to SystemMode=light
and then double-clicking the theme file will make the taskbar go white, but only on newer Windows versions that supported the light theme.
So, yes, I have to agree with @strive-sun-msft the SystemUsesLightTheme
registry entry is the best location. When testing, even the Task Bar itself monitors this, deleting it will reset it back to black. Unfortunately that fallback black Task Bar color remains to be a mystery. I can only assume it's hard-coded into the task bar itself.
Another workaround for this behavior is to just install the aero.theme
file again by running it if the registry entries are missing. On newer Windows 10 versions, simply running this file will create the missing entries. Unfortunately, this doesn't work on older Windows 10 versions and worse, this will reset any custom preferences set by the user.
So the least intrusive way to detect the color of the taskbar is to read the registry and if the keys are missing, simply assume the theme Windows 10 shipped with is still in effect: Dark Taskbar, Light Windows.
Upvotes: 4
Reputation: 6299
So far, I have not encountered the lack of SystemUsesLightTheme
and AppsUseLightTheme
in the registry.
But I think recreating the key-values is worth trying.
Here is code sample(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;
}
}
Upvotes: 3