Files
Taskbar-Launcher/Services/ThemeService.cs
2026-08-25 17:31:54 -04:00

202 lines
7.8 KiB
C#

using System.Windows;
using System.Windows.Media;
using Microsoft.Win32;
using TaskbarLauncher.Models;
using MediaColor = System.Windows.Media.Color;
namespace TaskbarLauncher.Services;
public static class ThemeService
{
private const string PersonalizeKey = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
private const string DwmKey = @"Software\Microsoft\Windows\DWM";
public static void Apply(LauncherThemeScheme scheme = LauncherThemeScheme.MarkHaven)
{
bool isLight = IsLightTheme();
ThemePalette palette = GetPalette(scheme, isLight);
MediaColor accent = palette.Accent;
MediaColor selectedText = IsDark(accent) ? System.Windows.Media.Colors.White : System.Windows.Media.Colors.Black;
SetBrush("AppWindowBrush", palette.Window);
SetBrush("AppSurfaceBrush", palette.Surface);
SetBrush("AppPanelBrush", palette.Panel);
SetBrush("AppControlBrush", palette.Control);
SetBrush("AppControlHoverBrush", palette.Hover);
SetBrush("AppTextBrush", palette.Text);
SetBrush("AppMutedTextBrush", palette.Muted);
SetBrush("AppBorderBrush", palette.Border);
SetBrush("AppAccentBrush", accent);
SetBrush("AppAccentSoftBrush", palette.AccentSoft);
SetBrush("AppOrangeBrush", palette.Orange);
SetBrush("AppOrangeSoftBrush", palette.OrangeSoft);
SetBrush("AppSelectedTextBrush", selectedText);
SetBrush(System.Windows.SystemColors.WindowBrushKey, palette.Surface);
SetBrush(System.Windows.SystemColors.WindowTextBrushKey, palette.Text);
SetBrush(System.Windows.SystemColors.ControlBrushKey, palette.Control);
SetBrush(System.Windows.SystemColors.ControlTextBrushKey, palette.Text);
SetBrush(System.Windows.SystemColors.ControlDarkBrushKey, palette.Border);
SetBrush(System.Windows.SystemColors.HighlightBrushKey, accent);
SetBrush(System.Windows.SystemColors.HighlightTextBrushKey, selectedText);
}
private static bool IsLightTheme()
{
object? value = Registry.CurrentUser.OpenSubKey(PersonalizeKey)?.GetValue("AppsUseLightTheme");
return value is null || Convert.ToInt32(value) != 0;
}
private static MediaColor GetAccentColor()
{
object? value = Registry.CurrentUser.OpenSubKey(DwmKey)?.GetValue("AccentColor");
if (value is int colorValue)
{
byte r = (byte)(colorValue & 0xFF);
byte g = (byte)((colorValue >> 8) & 0xFF);
byte b = (byte)((colorValue >> 16) & 0xFF);
return MediaColor.FromRgb(r, g, b);
}
return MediaColor.FromRgb(0x00, 0x78, 0xD4);
}
private static ThemePalette GetPalette(LauncherThemeScheme scheme, bool isLight)
{
MediaColor windowsAccent = GetAccentColor();
MediaColor orange = MediaColor.FromRgb(0xD8, 0x78, 0x1D);
return scheme switch
{
LauncherThemeScheme.System => CreatePalette(
isLight,
windowsAccent,
orange,
window: LightDark(isLight, 0xF7F7F7, 0x202020),
surface: LightDark(isLight, 0xFFFFFF, 0x2B2B2B),
panel: LightDark(isLight, 0xF3F3F3, 0x333333),
control: LightDark(isLight, 0xF3F3F3, 0x333333),
hover: LightDark(isLight, 0xEAF3FF, 0x3B4A5C),
text: LightDark(isLight, 0x1A1A1A, 0xF3F3F3),
muted: LightDark(isLight, 0x666666, 0xB8B8B8),
border: LightDark(isLight, 0xC8C8C8, 0x555555)),
LauncherThemeScheme.WindowsClassic => CreatePalette(
isLight,
windowsAccent,
orange,
window: LightDark(isLight, 0xF0F0F0, 0x1F1F1F),
surface: LightDark(isLight, 0xFAFAFA, 0x2D2D30),
panel: LightDark(isLight, 0xFFFFFF, 0x252526),
control: LightDark(isLight, 0xF5F5F5, 0x333337),
hover: LightDark(isLight, 0xEDEDED, 0x3E3E42),
text: LightDark(isLight, 0x111111, 0xF1F1F1),
muted: LightDark(isLight, 0x5F5F5F, 0xBDBDBD),
border: LightDark(isLight, 0xD0D0D0, 0x565656)),
LauncherThemeScheme.MGETOrange => CreatePalette(
isLight,
orange,
orange,
window: LightDark(isLight, 0xF6F1EA, 0x181614),
surface: LightDark(isLight, 0xFFFCF8, 0x221F1B),
panel: LightDark(isLight, 0xFFF7EE, 0x2A241E),
control: LightDark(isLight, 0xFAF1E7, 0x322B24),
hover: LightDark(isLight, 0xFFEDDA, 0x423428),
text: LightDark(isLight, 0x241D17, 0xF8F2EA),
muted: LightDark(isLight, 0x75685C, 0xC3B5A6),
border: LightDark(isLight, 0xE4D1BC, 0x5B4B3C)),
_ => CreatePalette(
isLight,
LightDark(isLight, 0x146B52, 0x58D0A3),
LightDark(isLight, 0xB56B08, 0xF4BD54),
window: LightDark(isLight, 0xEEF1F0, 0x111816),
surface: LightDark(isLight, 0xFFFFFF, 0x18201E),
panel: LightDark(isLight, 0xFBFCFB, 0x15201D),
control: LightDark(isLight, 0xEEF3F0, 0x1A2A24),
hover: LightDark(isLight, 0xE2F3EC, 0x183B30),
text: LightDark(isLight, 0x1B2824, 0xEDF5F2),
muted: LightDark(isLight, 0x66746F, 0x9CAAA5),
border: LightDark(isLight, 0xDCE3E0, 0x33423D))
};
}
private static ThemePalette CreatePalette(
bool isLight,
MediaColor accent,
MediaColor orange,
MediaColor window,
MediaColor surface,
MediaColor panel,
MediaColor control,
MediaColor hover,
MediaColor text,
MediaColor muted,
MediaColor border)
{
return new ThemePalette(
window,
surface,
panel,
control,
hover,
text,
muted,
border,
accent,
Blend(accent, surface, isLight ? 0.14 : 0.24),
orange,
Blend(orange, surface, isLight ? 0.16 : 0.30));
}
private static MediaColor LightDark(bool isLight, int lightRgb, int darkRgb)
{
int rgb = isLight ? lightRgb : darkRgb;
return MediaColor.FromRgb((byte)(rgb >> 16), (byte)(rgb >> 8), (byte)rgb);
}
private static MediaColor Blend(MediaColor foreground, MediaColor background, double foregroundAmount)
{
double amount = Math.Clamp(foregroundAmount, 0, 1);
byte r = (byte)Math.Round((foreground.R * amount) + (background.R * (1 - amount)));
byte g = (byte)Math.Round((foreground.G * amount) + (background.G * (1 - amount)));
byte b = (byte)Math.Round((foreground.B * amount) + (background.B * (1 - amount)));
return MediaColor.FromRgb(r, g, b);
}
private static void SetBrush(string key, MediaColor color)
{
SolidColorBrush brush = new(color);
brush.Freeze();
System.Windows.Application.Current.Resources[key] = brush;
}
private static void SetBrush(ResourceKey key, MediaColor color)
{
SolidColorBrush brush = new(color);
brush.Freeze();
System.Windows.Application.Current.Resources[key] = brush;
}
private static bool IsDark(MediaColor color)
{
double luminance = (0.299 * color.R) + (0.587 * color.G) + (0.114 * color.B);
return luminance < 140;
}
private sealed record ThemePalette(
MediaColor Window,
MediaColor Surface,
MediaColor Panel,
MediaColor Control,
MediaColor Hover,
MediaColor Text,
MediaColor Muted,
MediaColor Border,
MediaColor Accent,
MediaColor AccentSoft,
MediaColor Orange,
MediaColor OrangeSoft);
}