From 3da5662a90e114449ab1d411ad9d8c828155e4fb Mon Sep 17 00:00:00 2001
From: NaBian <836904362@qq.com>
Date: Sun, 30 May 2021 14:50:38 +0800
Subject: [PATCH] support for sync with system theme
---
.../HandyControl_Net_40/Themes/Theme.xaml | 2 +-
.../Controls/Attach/DataGridAttach.cs | 2 +-
.../Controls/Attach/DropDownElement.cs | 2 +-
.../Controls/Attach/WindowAttach.cs | 2 +-
.../Controls/Other/Empty.cs | 2 +-
.../Controls/Window/BlurWindow.cs | 11 +-
.../HandyControl_Shared.projitems | 1 +
.../HandyControl_Shared/Themes/Theme.cs | 102 ++++++++++++------
.../Tools/Helper/ResourceHelper.cs | 4 +-
.../Tools/Helper/SystemHelper.cs | 29 +++++
10 files changed, 111 insertions(+), 46 deletions(-)
create mode 100644 src/Shared/HandyControl_Shared/Tools/Helper/SystemHelper.cs
diff --git a/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml b/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
index 25ce5453..79b31966 100644
--- a/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
+++ b/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
@@ -11752,7 +11752,7 @@
-
+
diff --git a/src/Shared/HandyControl_Shared/Controls/Attach/DataGridAttach.cs b/src/Shared/HandyControl_Shared/Controls/Attach/DataGridAttach.cs
index c46040a3..1e20f87b 100644
--- a/src/Shared/HandyControl_Shared/Controls/Attach/DataGridAttach.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Attach/DataGridAttach.cs
@@ -337,7 +337,7 @@ namespace HandyControl.Controls
}
public static void SetCanUnselectAllWithBlankArea(DependencyObject element, bool value)
- => element.SetValue(CanUnselectAllWithBlankAreaProperty, value);
+ => element.SetValue(CanUnselectAllWithBlankAreaProperty, ValueBoxes.BooleanBox(value));
public static bool GetCanUnselectAllWithBlankArea(DependencyObject element)
=> (bool) element.GetValue(CanUnselectAllWithBlankAreaProperty);
diff --git a/src/Shared/HandyControl_Shared/Controls/Attach/DropDownElement.cs b/src/Shared/HandyControl_Shared/Controls/Attach/DropDownElement.cs
index 3ac8d63b..7a8561f2 100644
--- a/src/Shared/HandyControl_Shared/Controls/Attach/DropDownElement.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Attach/DropDownElement.cs
@@ -20,7 +20,7 @@ namespace HandyControl.Controls
new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetAutoWidth(DependencyObject element, bool value)
- => element.SetValue(AutoWidthProperty, value);
+ => element.SetValue(AutoWidthProperty, ValueBoxes.BooleanBox(value));
public static bool GetAutoWidth(DependencyObject element)
=> (bool) element.GetValue(AutoWidthProperty);
diff --git a/src/Shared/HandyControl_Shared/Controls/Attach/WindowAttach.cs b/src/Shared/HandyControl_Shared/Controls/Attach/WindowAttach.cs
index f6b2e193..14441d40 100644
--- a/src/Shared/HandyControl_Shared/Controls/Attach/WindowAttach.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Attach/WindowAttach.cs
@@ -141,7 +141,7 @@ namespace HandyControl.Controls
}
public static void SetHideWhenClosing(DependencyObject element, bool value)
- => element.SetValue(HideWhenClosingProperty, value);
+ => element.SetValue(HideWhenClosingProperty, ValueBoxes.BooleanBox(value));
public static bool GetHideWhenClosing(DependencyObject element)
=> (bool) element.GetValue(HideWhenClosingProperty);
diff --git a/src/Shared/HandyControl_Shared/Controls/Other/Empty.cs b/src/Shared/HandyControl_Shared/Controls/Other/Empty.cs
index 459a6cc0..e2e05252 100644
--- a/src/Shared/HandyControl_Shared/Controls/Other/Empty.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Other/Empty.cs
@@ -28,7 +28,7 @@ namespace HandyControl.Controls
"ShowEmpty", typeof(bool), typeof(Empty), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowEmpty(DependencyObject element, bool value)
- => element.SetValue(ShowEmptyProperty, value);
+ => element.SetValue(ShowEmptyProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowEmpty(DependencyObject element)
=> (bool) element.GetValue(ShowEmptyProperty);
diff --git a/src/Shared/HandyControl_Shared/Controls/Window/BlurWindow.cs b/src/Shared/HandyControl_Shared/Controls/Window/BlurWindow.cs
index 1eb6fe9d..b68db22e 100644
--- a/src/Shared/HandyControl_Shared/Controls/Window/BlurWindow.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Window/BlurWindow.cs
@@ -2,6 +2,7 @@
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
+using HandyControl.Tools.Helper;
using HandyControl.Tools.Interop;
namespace HandyControl.Controls
@@ -14,17 +15,9 @@ namespace HandyControl.Controls
EnableBlur(this);
}
- private static SystemVersionInfo GetSystemVersionInfo()
- {
- var osv = new InteropValues.RTL_OSVERSIONINFOEX();
- osv.dwOSVersionInfoSize = (uint) Marshal.SizeOf(osv);
- InteropMethods.Gdip.RtlGetVersion(out osv);
- return new SystemVersionInfo((int) osv.dwMajorVersion, (int) osv.dwMinorVersion, (int) osv.dwBuildNumber);
- }
-
internal static void EnableBlur(Window window)
{
- var versionInfo = GetSystemVersionInfo();
+ var versionInfo = SystemHelper.GetSystemVersionInfo();
if (versionInfo < SystemVersionInfo.Windows10 ||
versionInfo >= SystemVersionInfo.Windows10_1903)
diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
index 34a1414f..4818b28e 100644
--- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
+++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
@@ -372,6 +372,7 @@
+
diff --git a/src/Shared/HandyControl_Shared/Themes/Theme.cs b/src/Shared/HandyControl_Shared/Themes/Theme.cs
index 17219c41..70f2223f 100644
--- a/src/Shared/HandyControl_Shared/Themes/Theme.cs
+++ b/src/Shared/HandyControl_Shared/Themes/Theme.cs
@@ -1,8 +1,10 @@
using System;
-using System.Linq;
+using System.Collections.Generic;
using System.Windows;
using HandyControl.Data;
using HandyControl.Tools;
+using HandyControl.Tools.Helper;
+using Microsoft.Win32;
namespace HandyControl.Themes
{
@@ -12,14 +14,8 @@ namespace HandyControl.Themes
{
if (DesignerHelper.IsInDesignMode)
{
- MergedDictionaries.Add(new()
- {
- Source = new Uri("pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml")
- });
- MergedDictionaries.Add(new()
- {
- Source = new Uri("pack://application:,,,/HandyControl;component/Themes/Theme.xaml")
- });
+ MergedDictionaries.Add(ResourceHelper.GetSkin(SkinType.Default));
+ MergedDictionaries.Add(ResourceHelper.GetTheme());
}
else
{
@@ -35,6 +31,8 @@ namespace HandyControl.Themes
set => _source = value;
}
+ private SkinType _manualSkinType;
+
private SkinType _skin;
public virtual SkinType Skin
@@ -54,32 +52,43 @@ namespace HandyControl.Themes
private static void OnSkinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
- if (d is FrameworkElement element)
+ if (d is not FrameworkElement element)
{
- var skin = (SkinType) e.NewValue;
+ return;
+ }
- if (element.Resources is Theme resource)
+ var skin = (SkinType) e.NewValue;
+
+ var themes = new List();
+ GetAllThemes(element.Resources, ref themes);
+
+ if (themes.Count > 0)
+ {
+ foreach (var theme in themes)
{
- resource.Skin = skin;
+ theme.Skin = skin;
}
- else
+ }
+ else
+ {
+ element.Resources.MergedDictionaries.Add(new Theme
{
- var themes = element.Resources.MergedDictionaries.OfType();
- if (!themes.Any())
- {
- element.Resources.MergedDictionaries.Add(new Theme
- {
- Skin = skin
- });
- }
- else
- {
- foreach (var subResource in element.Resources.MergedDictionaries.OfType())
- {
- subResource.Skin = skin;
- }
- }
- }
+ Skin = skin
+ });
+ }
+ }
+
+ private static void GetAllThemes(ResourceDictionary resourceDictionary, ref List themes)
+ {
+ if (resourceDictionary is Theme theme)
+ {
+ themes.Add(theme);
+ }
+
+ // we must consider it's MergedDictionaries
+ foreach (var dictionaryMergedDictionary in resourceDictionary.MergedDictionaries)
+ {
+ GetAllThemes(dictionaryMergedDictionary, ref themes);
}
}
@@ -89,6 +98,39 @@ namespace HandyControl.Themes
public static SkinType GetSkin(DependencyObject element)
=> (SkinType) element.GetValue(SkinProperty);
+ private bool _syncWithSystem;
+
+ public bool SyncWithSystem
+ {
+ get => _syncWithSystem;
+ set
+ {
+ _syncWithSystem = value;
+
+ if (value)
+ {
+ _manualSkinType = Skin;
+ SyncWithSystemTheme();
+ SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
+ }
+ else
+ {
+ SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
+ Skin = _manualSkinType;
+ }
+ }
+ }
+
+ private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
+ {
+ if (e.Category == UserPreferenceCategory.General)
+ {
+ SyncWithSystemTheme();
+ }
+ }
+
+ private void SyncWithSystemTheme() => Skin = SystemHelper.DetermineIfInLightThemeMode() ? SkinType.Default : SkinType.Dark;
+
public string Name { get; set; }
public virtual ResourceDictionary GetSkin(SkinType skinType) => ResourceHelper.GetSkin(skinType);
diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/ResourceHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/ResourceHelper.cs
index 6debc387..3eef1295 100644
--- a/src/Shared/HandyControl_Shared/Tools/Helper/ResourceHelper.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Helper/ResourceHelper.cs
@@ -54,7 +54,7 @@ namespace HandyControl.Tools
{
try
{
- var uri = new Uri($"pack://application:,,,/{assembly.GetName().Name};component/{themePath}/Skin{skin.ToString()}.xaml");
+ var uri = new Uri($"pack://application:,,,/{assembly.GetName().Name};component/{themePath}/Skin{skin}.xaml");
return new ResourceDictionary
{
Source = uri
@@ -64,7 +64,7 @@ namespace HandyControl.Tools
{
return new ResourceDictionary
{
- Source = new Uri($"pack://application:,,,/{assembly.GetName().Name};component/{themePath}/Skin{SkinType.Default.ToString()}.xaml")
+ Source = new Uri($"pack://application:,,,/{assembly.GetName().Name};component/{themePath}/Skin{SkinType.Default}.xaml")
};
}
}
diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/SystemHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/SystemHelper.cs
new file mode 100644
index 00000000..a2349722
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Helper/SystemHelper.cs
@@ -0,0 +1,29 @@
+using System.Runtime.InteropServices;
+using HandyControl.Data;
+using HandyControl.Tools.Interop;
+using Microsoft.Win32;
+
+namespace HandyControl.Tools.Helper
+{
+ internal class SystemHelper
+ {
+ public static SystemVersionInfo GetSystemVersionInfo()
+ {
+ var osv = new InteropValues.RTL_OSVERSIONINFOEX();
+ osv.dwOSVersionInfoSize = (uint) Marshal.SizeOf(osv);
+ InteropMethods.Gdip.RtlGetVersion(out osv);
+ return new SystemVersionInfo((int) osv.dwMajorVersion, (int) osv.dwMinorVersion, (int) osv.dwBuildNumber);
+ }
+
+ private const string SkinTypeRegistryKeyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
+
+ private const string SkinTypeRegistryValueName = "AppsUseLightTheme";
+
+ public static bool DetermineIfInLightThemeMode()
+ {
+ var value = Registry.GetValue(SkinTypeRegistryKeyName, SkinTypeRegistryValueName, "0");
+
+ return value != null && value.ToString() != "0";
+ }
+ }
+}