diff --git a/src/MaterialDesignColors.Wpf/MaterialDesignColor.cs b/src/MaterialDesignColors.Wpf/MaterialDesignColor.cs index 31b4cd584f..b4a9d238de 100644 --- a/src/MaterialDesignColors.Wpf/MaterialDesignColor.cs +++ b/src/MaterialDesignColors.Wpf/MaterialDesignColor.cs @@ -2,6 +2,7 @@ public enum PrimaryColor { + Inherit, Red = MaterialDesignColor.Red500, Pink = MaterialDesignColor.Pink500, Purple = MaterialDesignColor.Purple500, @@ -25,6 +26,7 @@ public enum PrimaryColor public enum SecondaryColor { + Inherit, Red = MaterialDesignColor.RedSecondary, Pink = MaterialDesignColor.PinkSecondary, Purple = MaterialDesignColor.PurpleSecondary, diff --git a/src/MaterialDesignThemes.Wpf/BundledTheme.cs b/src/MaterialDesignThemes.Wpf/BundledTheme.cs index 152821a5f5..43da9550b4 100644 --- a/src/MaterialDesignThemes.Wpf/BundledTheme.cs +++ b/src/MaterialDesignThemes.Wpf/BundledTheme.cs @@ -1,4 +1,5 @@ -using MaterialDesignColors; +using System.Windows.Media; +using MaterialDesignColors; namespace MaterialDesignThemes.Wpf; @@ -10,9 +11,8 @@ public BaseTheme? BaseTheme get => _baseTheme; set { - if (_baseTheme != value) + if (SetField(ref _baseTheme, value)) { - _baseTheme = value; SetTheme(); } } @@ -24,9 +24,8 @@ public PrimaryColor? PrimaryColor get => _primaryColor; set { - if (_primaryColor != value) + if (SetField(ref _primaryColor, value)) { - _primaryColor = value; SetTheme(); } } @@ -38,9 +37,8 @@ public SecondaryColor? SecondaryColor get => _secondaryColor; set { - if (_secondaryColor != value) + if (SetField(ref _secondaryColor, value)) { - _secondaryColor = value; SetTheme(); } } @@ -52,9 +50,8 @@ public ColorAdjustment? ColorAdjustment get => _colorAdjustment; set { - if (_colorAdjustment != value) + if (SetField(ref _colorAdjustment, value)) { - _colorAdjustment = value; SetTheme(); } } @@ -62,17 +59,35 @@ public ColorAdjustment? ColorAdjustment private void SetTheme() { - if (BaseTheme is BaseTheme baseTheme && - PrimaryColor is PrimaryColor primaryColor && - SecondaryColor is SecondaryColor secondaryColor) + if (BaseTheme is not BaseTheme baseTheme || + PrimaryColor is not PrimaryColor primaryColor || + SecondaryColor is not SecondaryColor secondaryColor) { - Theme theme = Theme.Create(baseTheme, - SwatchHelper.Lookup[(MaterialDesignColor)primaryColor], - SwatchHelper.Lookup[(MaterialDesignColor)secondaryColor]); - theme.ColorAdjustment = ColorAdjustment; - - ApplyTheme(theme); + return; } + + // only perform the registry lookup if needed, and only once + Lazy accentColor = new(Theme.GetSystemAccentColor); + + Color colorPrimary = primaryColor == MaterialDesignColors.PrimaryColor.Inherit + ? (accentColor.Value ?? SwatchHelper.Lookup.First().Value) + : SwatchHelper.Lookup[(MaterialDesignColor)primaryColor]; + + Color colorSecondary = secondaryColor == MaterialDesignColors.SecondaryColor.Inherit + ? (accentColor.Value ?? SwatchHelper.Lookup.First().Value) + : SwatchHelper.Lookup[(MaterialDesignColor)secondaryColor]; + + Theme theme = Theme.Create(baseTheme, colorPrimary, colorSecondary); + theme.ColorAdjustment = ColorAdjustment; + + ApplyTheme(theme); + } + + protected static bool SetField(ref T field, T value) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + return true; } protected virtual void ApplyTheme(Theme theme) => diff --git a/src/MaterialDesignThemes.Wpf/Theme.cs b/src/MaterialDesignThemes.Wpf/Theme.cs index b4ad08734c..c35e59f549 100644 --- a/src/MaterialDesignThemes.Wpf/Theme.cs +++ b/src/MaterialDesignThemes.Wpf/Theme.cs @@ -1,4 +1,5 @@ -using System.Windows.Media; +using System.Diagnostics; +using System.Windows.Media; using MaterialDesignColors; using Microsoft.Win32; @@ -31,6 +32,44 @@ public partial class Theme } } + /// + /// Get the current Windows accent color. + /// Based on ControlzEx + /// https://github.com/ControlzEx/ControlzEx/blob/48230bb023c588e1b7eb86ea83f7ddf7d25be735/src/ControlzEx/Theming/WindowsThemeHelper.cs#L53 + /// + /// + public static Color? GetSystemAccentColor() + { + Color? accentColor = null; + + try + { + var registryValue = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", null); + + if (registryValue is null) + { + return null; + } + + // We get negative values out of the registry, so we have to cast to int from object first. + // Casting from int to uint works afterwards and converts the number correctly. + var pp = (uint)(int)registryValue; + if (pp > 0) + { + var bytes = BitConverter.GetBytes(pp); + accentColor = Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]); + } + + return accentColor; + } + catch (Exception exception) + { + Trace.TraceError(exception.ToString()); + } + + return accentColor; + } + public static Theme Create(BaseTheme baseTheme, Color primary, Color secondary) { Theme theme = new();