using System.Windows; using System.Windows.Media; using Microsoft.Win32; namespace DeskCore; /// Übernimmt Hell/Dunkel-Modus und Akzentfarbe von Windows – auch live, wenn man sie ändert. public static class Theme { public static bool IsLight { get; private set; } = true; /// Vom Benutzer gewählter Modus; "System" folgt der Windows-Einstellung. public static DesignMode Mode => AppSettings.Current.Design; public static void Init() { Apply(); SystemEvents.UserPreferenceChanged += (_, e) => { if (e.Category is UserPreferenceCategory.General or UserPreferenceCategory.Color or UserPreferenceCategory.VisualStyle) Application.Current.Dispatcher.BeginInvoke(Apply); }; } public static void Apply() { IsLight = Mode switch { DesignMode.Light => true, DesignMode.Dark => false, _ => ReadDword(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme") != 0, }; var res = Application.Current.Resources; res.MergedDictionaries[0] = new ResourceDictionary { Source = new Uri($"pack://application:,,,/Themes/Colors.{(IsLight ? "Light" : "Dark")}.xaml") }; // DWM speichert die Akzentfarbe als ABGR int abgr = ReadDword(@"Software\Microsoft\Windows\DWM", "AccentColor") is var v and not -1 ? v : unchecked((int)0xFFD77800); var accent = Color.FromRgb((byte)abgr, (byte)(abgr >> 8), (byte)(abgr >> 16)); // Wie Windows 11: im Hellmodus etwas dunkler + weiße Schrift, im Dunkelmodus deutlich heller + schwarze Schrift var a = IsLight ? Mix(accent, Colors.Black, 0.12) : Mix(accent, Colors.White, 0.45); res["AccentBrush"] = Brush(a); res["AccentHoverBrush"] = Brush(IsLight ? Mix(a, Colors.White, 0.1) : Mix(a, Colors.Black, 0.1)); res["OnAccentBrush"] = Brush(IsLight ? Colors.White : Colors.Black); res["AccentSubtleBrush"] = Brush(Color.FromArgb(IsLight ? (byte)0x22 : (byte)0x30, a.R, a.G, a.B)); res["AccentSubtleStrokeBrush"] = Brush(Color.FromArgb(IsLight ? (byte)0x55 : (byte)0x60, a.R, a.G, a.B)); Changed?.Invoke(); } public static event Action? Changed; private static int ReadDword(string key, string name) { try { using var k = Registry.CurrentUser.OpenSubKey(key); return k?.GetValue(name) is int i ? i : -1; } catch { return -1; } } private static Color Mix(Color c, Color with, double t) => Color.FromRgb( (byte)(c.R + (with.R - c.R) * t), (byte)(c.G + (with.G - c.G) * t), (byte)(c.B + (with.B - c.B) * t)); private static SolidColorBrush Brush(Color c) { var b = new SolidColorBrush(c); b.Freeze(); return b; } }