You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3应用运行时切换主题,系统上下文菜单未更新求助

WinUI3 运行时切换主题同步标题栏右键菜单的解决方案

问题原因

SetPreferredAppMode(uxtheme.dll的#135入口)是仅在进程初始化阶段生效的API,它负责设置进程级的主题偏好,但运行时调用无法触发系统托管的非客户区元素(比如标题栏右键菜单)的主题重绘——这类控件属于窗口管理器维护范畴,不受应用自身UI刷新逻辑影响。

可行解决方案

要在运行时同步标题栏右键菜单的主题,需要结合进程级主题设置、应用主题切换,以及强制刷新窗口非客户区三个步骤:

  1. 确保应用自身主题正确切换
    先设置WinUI3应用的RequestedTheme,这是应用UI主题切换的基础:

    Application.Current.RequestedTheme = ApplicationTheme.Dark; // 切换为深色,或设为Light切换为浅色
    
  2. 调用SetPreferredAppMode更新进程主题偏好
    运行时调用该API仍会更新进程的主题标记,为后续系统控件刷新做准备:

    SetPreferredAppMode(2); // 2=强制深色,1=强制浅色,0=跟随系统
    
  3. 强制刷新窗口非客户区
    通过DwmSetWindowAttribute设置窗口的沉浸式深色模式属性,触发系统重绘标题栏及关联的右键菜单:
    首先定义所需的API:

    [DllImport("dwmapi.dll")]
    private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
    
    private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
    
    [DllImport("uxtheme.dll", EntryPoint = "#135", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern int SetPreferredAppMode(int preferredAppMode);
    
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    

    然后在切换主题的按钮点击事件中执行完整逻辑:

    private void ToggleThemeButton_Click(object sender, RoutedEventArgs e)
    {
        bool isCurrentDark = Application.Current.RequestedTheme == ApplicationTheme.Dark;
        // 切换到相反主题
        var targetTheme = isCurrentDark ? ApplicationTheme.Light : ApplicationTheme.Dark;
        int targetAppMode = isCurrentDark ? 1 : 2;
    
        Application.Current.RequestedTheme = targetTheme;
        SetPreferredAppMode(targetAppMode);
    
        // 获取当前窗口句柄
        var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
    
        // 设置沉浸式深色模式属性
        int useDarkMode = isCurrentDark ? 0 : 1;
        DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, ref useDarkMode, sizeof(int));
    
        // 发送WM_NCACTIVATE消息强制刷新非客户区
        SendMessage(hwnd, 0x86, IntPtr.Zero, IntPtr.Zero);
    }
    

系统应用的实现逻辑

Windows设置等系统应用直接与系统主题服务绑定,当系统主题变更时,系统会主动推送通知,触发所有系统控件同步更新主题;第三方应用则需要通过手动触发非客户区刷新的方式,同步系统托管控件的主题状态。

内容的提问来源于stack exchange,提问作者Chibako

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:27:59