Skip to content

Commit

Permalink
feat: changable System Menu Theme
Browse files Browse the repository at this point in the history
  • Loading branch information
emako committed Jan 7, 2025
1 parent 8694a9f commit d3ef7ab
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 30 deletions.
1 change: 0 additions & 1 deletion build/MicaSetup/Design/Controls/Window/WindowBackdrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public static bool ApplyBackdrop(nint hWnd, WindowBackdropType backdropType = Wi
break;

case ApplicationTheme.Light:
case ApplicationTheme.HighContrast:
WindowDarkMode.RemoveWindowDarkMode(hWnd);
break;
}
Expand Down
82 changes: 82 additions & 0 deletions build/MicaSetup/Design/Themes/SystemMenuThemeManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using MicaSetup.Helper;
using MicaSetup.Natives;
using Microsoft.Win32;
using System;

namespace MicaSetup.Design.Themes;

internal static class SystemMenuThemeManager
{
public static void Apply(SystemMenuTheme theme = SystemMenuTheme.Auto)
{
// Enable dark mode for context menus if using dark theme
if (Environment.OSVersion.Version.Build >= 18362) // Windows 10 1903
{
if (theme == SystemMenuTheme.Auto)
{
// UxTheme methods will apply all of menus.
// However, the Windows style system prefers that
// Windows System Menu is based on `Apps Theme`,
// and Tray Context Menu is based on `System Theme` when using a custom theme.
// But actually we can't have our cake and eat it too.
// Finally, we synchronize the theme styles of tray with higher usage rates.
if (OSThemeHelper.SystemUsesDarkTheme())
{
_ = UxTheme.SetPreferredAppMode(UxTheme.PreferredAppMode.ForceDark);
UxTheme.FlushMenuThemes();
}

// Synchronize the theme with system settings
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChangedEventHandler;
SystemEvents.UserPreferenceChanged += OnUserPreferenceChangedEventHandler;
}
else if (theme == SystemMenuTheme.Dark)
{
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChangedEventHandler;
_ = UxTheme.SetPreferredAppMode(UxTheme.PreferredAppMode.ForceDark);
UxTheme.FlushMenuThemes();
}
else if (theme == SystemMenuTheme.Light)
{
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChangedEventHandler;
_ = UxTheme.SetPreferredAppMode(UxTheme.PreferredAppMode.ForceLight);
UxTheme.FlushMenuThemes();
}
}
}

private static void OnUserPreferenceChangedEventHandler(object sender, UserPreferenceChangedEventArgs e)
{
if (OSThemeHelper.SystemUsesDarkTheme())
{
_ = UxTheme.SetPreferredAppMode(UxTheme.PreferredAppMode.ForceDark);
UxTheme.FlushMenuThemes();
}
else
{
_ = UxTheme.SetPreferredAppMode(UxTheme.PreferredAppMode.ForceLight);
UxTheme.FlushMenuThemes();
}
}
}

/// <summary>
/// Theme in which an system menu is displayed.
/// </summary>
public enum SystemMenuTheme
{
/// <summary>
/// Auto system theme.
/// </summary>
Auto = ApplicationTheme.Unknown,

/// <summary>
/// Dark system theme.
/// </summary>
Dark = ApplicationTheme.Dark,

/// <summary>
/// Light system theme.
/// </summary>
Light = ApplicationTheme.Light,
}
12 changes: 10 additions & 2 deletions build/MicaSetup/Design/Themes/ThemeService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MicaSetup.Helper;
using MicaSetup.Design.Themes;
using MicaSetup.Helper;
using MicaSetup.Natives;
using System;
using System.Windows;
Expand Down Expand Up @@ -59,12 +60,19 @@ private void SetWindowBackdrop(Window window, BackdropType micaType)

private WindowsTheme GetTheme()
{
return currentTheme == WindowsTheme.Auto ? WindowsThemeHelper.GetCurrentWindowsTheme() : currentTheme;
return currentTheme == WindowsTheme.Auto ? (OSThemeHelper.AppsUseDarkTheme() ? WindowsTheme.Dark : WindowsTheme.Light) : currentTheme;
}

public void SetTheme(WindowsTheme theme)
{
CurrentTheme = theme;

SystemMenuThemeManager.Apply(theme switch
{
WindowsTheme.Dark => SystemMenuTheme.Dark,
WindowsTheme.Light => SystemMenuTheme.Light,
WindowsTheme.Auto or _ => SystemMenuTheme.Auto,
});
SyncThemeResource();
}

Expand Down
21 changes: 0 additions & 21 deletions build/MicaSetup/Design/Themes/WindowsThemeHelper.cs

This file was deleted.

2 changes: 1 addition & 1 deletion build/MicaSetup/Helper/JsonHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace MicaSetup.Helper;

internal static class JsonHelper
public static class JsonHelper
{
public static string SerializeObject(IDictionary<string, dynamic?> obj)
{
Expand Down
24 changes: 24 additions & 0 deletions build/MicaSetup/Helper/OSThemeHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.Win32;

namespace MicaSetup.Helper;

public static class OSThemeHelper
{
public static bool AppsUseDarkTheme()
{
object? value = Registry.GetValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
"AppsUseLightTheme", 1);

return value != null && (int)value == 0;
}

public static bool SystemUsesDarkTheme()
{
object? value = Registry.GetValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
"SystemUsesLightTheme", 0);

return value == null || (int)value == 0;
}
}
5 changes: 0 additions & 5 deletions build/MicaSetup/Natives/NativeEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,4 @@ public enum ApplicationTheme
/// Light application theme.
/// </summary>
Light,

/// <summary>
/// High contract application theme.
/// </summary>
HighContrast,
}
15 changes: 15 additions & 0 deletions build/MicaSetup/Natives/UxTheme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ namespace MicaSetup.Natives;

public static class UxTheme
{
[DllImport(Lib.UxTheme, EntryPoint = "#135", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetPreferredAppMode(PreferredAppMode preferredAppMode);

[DllImport(Lib.UxTheme, EntryPoint = "#136", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern void FlushMenuThemes();

[DllImport(Lib.UxTheme, SetLastError = false, ExactSpelling = true)]
public static extern int SetWindowThemeAttribute(nint hwnd, WINDOWTHEMEATTRIBUTETYPE eAttribute, in WTA_OPTIONS pvAttribute, uint cbAttribute);

Expand Down Expand Up @@ -62,4 +68,13 @@ public struct WTA_OPTIONS
public WTNCA Flags;
public uint Mask;
}

public enum PreferredAppMode : int
{
Default,
AllowDark,
ForceDark,
ForceLight,
Max,
};
}

0 comments on commit d3ef7ab

Please sign in to comment.