根据微软开发文档「在 Win32 应用中支持深色和浅色主题」,WinUI 3 可以实现深色和浅色主题的切换,但是标题栏却不在其列,好在我们有办法通过自定义标题栏来实现深色模式。然而,问题在于我们通常不会去自定义标题栏菜单,导致菜单与系统或软件的主题不匹配。
本文使用 Windows 的非公开 API 来支持标题栏原生菜单的深色主题。
相关 API
暗色模式 API 参考 ysc3839/win32-darkmode:
C++
// 1903 18362
enum PreferredAppMode
{
Default,
AllowDark,
ForceDark,
ForceLight,
Max
};
using fnSetPreferredAppMode = PreferredAppMode (WINAPI *)(PreferredAppMode appMode); // ordinal 135, in 1903
using fnFlushMenuThemes = void (WINAPI *)(); // ordinal 136
我们主要关注 PreferredAppMode
的三个值:AllowDark
、ForceDark
、ForceLight
。它们分别表示跟随系统主题,强制深色主题,强制浅色主题。
实现
创建调用代码:
C#
private enum PreferredAppMode
{
Default,
AllowDark,
ForceDark,
ForceLight,
Max
};
[DllImport("uxtheme.dll", EntryPoint = "#135")]
private static extern IntPtr SetPreferredAppMode(PreferredAppMode preferredAppMode);
[DllImport("uxtheme.dll", EntryPoint = "#136")]
private static extern IntPtr FlushMenuThemes();
创建辅助方法:
C#
public static void UpdateTitleBarContextMenu(Microsoft.UI.Xaml.ElementTheme theme)
{
var mode = theme switch
{
ElementTheme.Light => PreferredAppMode.ForceLight,
ElementTheme.Dark => PreferredAppMode.ForceDark,
_ => PreferredAppMode.AllowDark,
};
SetPreferredAppMode(mode);
FlushMenuThemes();
}
这样我们就可以通过传入元素主题来刷新菜单主题。
效果如下: