215 lines
8.5 KiB
C#
215 lines
8.5 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)),
|
|
|
|
LauncherThemeScheme.MGETBlueOrange => CreatePalette(
|
|
isLight,
|
|
LightDark(isLight, 0x1450A0, 0x78B4F0),
|
|
LightDark(isLight, 0xF4A000, 0xFFB400),
|
|
window: LightDark(isLight, 0xEEF3F9, 0x0D1424),
|
|
surface: LightDark(isLight, 0xFFFFFF, 0x141C2D),
|
|
panel: LightDark(isLight, 0xF5F8FC, 0x19243A),
|
|
control: LightDark(isLight, 0xFFF3DA, 0x2F2A20),
|
|
hover: LightDark(isLight, 0xE8F1FF, 0x203457),
|
|
text: LightDark(isLight, 0x162235, 0xEEF5FF),
|
|
muted: LightDark(isLight, 0x617086, 0xAAB8CC),
|
|
border: LightDark(isLight, 0xCBD7E7, 0x354762)),
|
|
|
|
_ => CreatePalette(
|
|
isLight,
|
|
LightDark(isLight, 0x146B52, 0x58D0A3),
|
|
LightDark(isLight, 0xB56B08, 0xF4BD54),
|
|
window: LightDark(isLight, 0xF9FBFA, 0x0D1A16),
|
|
surface: LightDark(isLight, 0xFFFFFF, 0x14231E),
|
|
panel: LightDark(isLight, 0xF9FBFA, 0x14231E),
|
|
control: LightDark(isLight, 0xEEF3F0, 0x1A2A24),
|
|
hover: LightDark(isLight, 0xE2F3EC, 0x163B2F),
|
|
text: LightDark(isLight, 0x192721, 0xEDF5F2),
|
|
muted: LightDark(isLight, 0x68766F, 0x9FB0A9),
|
|
border: LightDark(isLight, 0xD9E2DE, 0x30463D))
|
|
};
|
|
}
|
|
|
|
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);
|
|
}
|