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

运行时切换#32768(菜单)窗口类主题的问题

关于插件DLL中启用暗色模式后菜单弹窗未自动切换的问题

我通过插件DLL启用暗色模式时,主窗口已存在,导致菜单弹窗无法自动切换到暗色主题,缺少触发机制。

当我从全屏切换为普通窗口,或在Windows 11设置中修改主题时,菜单下拉框会自动启用暗色模式。目前找到的方法是调用SendMessage(hWnd, WM_DWMNCRENDERINGCHANGED, FALSE, 0);,但该操作会破坏主窗口的全屏布局。请问推荐的解决方式是什么?我可以自定义绘制弹窗,但既然某些事件能触发正常切换,能否明确这些事件并找到官方解决方案?

HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
ASSERT(hUxtheme);
SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
ASSERT(SetPreferredAppMode);
AllowDarkModeForWindow = (fnAllowDarkModeForWindow)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133));
ASSERT(AllowDarkModeForWindow);
SetPreferredAppMode(PreferredAppMode::ForceDark);

void enableImmersiveDarkMode(HWND hWnd) {
    BOOL USE_DARK_MODE = true;
    BOOL SET_IMMERSIVE_DARK_MODE_SUCCESS = SUCCEEDED(DwmSetWindowAttribute(
        hWnd, DWMWINDOWATTRIBUTE::DWMWA_USE_IMMERSIVE_DARK_MODE,
        &USE_DARK_MODE, sizeof(USE_DARK_MODE)));
}

推荐解决方案

1. 触发菜单主题切换的系统事件

你观察到的全屏/窗口切换、系统主题修改时菜单自动切换,本质是系统向窗口发送了主题变更相关通知,核心消息包括:

  • WM_THEMECHANGED:系统主题(含明暗模式)变更时发送,所有窗口都会收到,触发控件重新加载主题资源
  • WM_DWMCOLORIZATIONCOLORCHANGED:DWM着色颜色变更(通常关联明暗模式切换)时发送
  • WM_SETTINGCHANGE:系统设置(如主题)变更时,可能附带主题相关参数

这些消息不会修改窗口布局,只会通知控件更新主题渲染。

2. 官方合规的触发方式

无需使用破坏布局的WM_DWMNCRENDERINGCHANGED,按以下步骤操作即可:

步骤1:确保菜单窗口允许暗色模式

在启用暗色模式后,对菜单窗口的HWND调用AllowDarkModeForWindow:

// 假设hMenuWnd是菜单弹窗的句柄
AllowDarkModeForWindow(hMenuWnd, TRUE);

步骤2:发送主题变更消息触发更新

在你的暗色模式启用代码执行完成后,向主窗口和已存在的菜单窗口发送WM_THEMECHANGED:

// 通知主窗口更新主题
SendMessage(hMainWnd, WM_THEMECHANGED, 0, 0);
// 若能获取菜单窗口句柄,直接通知它
if (hMenuWnd != NULL) {
    SendMessage(hMenuWnd, WM_THEMECHANGED, 0, 0);
}

步骤3:处理动态创建的菜单

如果是右键菜单这类动态创建的控件,需在创建后立即配置暗色模式并触发更新:

HMENU hMenu = CreatePopupMenu();
// 添加菜单项逻辑...
HWND hMenuWnd = GetMenuOwnerWindow(hMenu);
AllowDarkModeForWindow(hMenuWnd, TRUE);
SendMessage(hMenuWnd, WM_THEMECHANGED, 0, 0);
TrackPopupMenu(hMenu, TPM_LEFTALIGN, x, y, 0, hMainWnd, NULL);

3. 完善暗色模式启用流程

现有代码中SetPreferredAppMode(ForceDark)是全局设置,还需确保主窗口和所有子窗口都完成暗色模式配置:

// 启用主窗口沉浸式暗色模式
enableImmersiveDarkMode(hMainWnd);
// 允许主窗口使用暗色模式
AllowDarkModeForWindow(hMainWnd, TRUE);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:32:51