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

如何通过WinAPI重置主题,恢复Windows C++应用的浅色上下文菜单?

强制Windows应用保持浅色主题的WinAPI方案

核心思路

CEF更新后可能修改了全局主题偏好,我们需要通过WinAPI强制重置应用的主题设置,覆盖系统和第三方库的修改,确保所有窗口(包括上下文菜单)始终使用浅色主题。

具体实现步骤

1. 全局强制应用浅色模式

使用SetPreferredAppMode API(Windows 10 1809+)设置应用级别的主题偏好为浅色,这会覆盖全局的主题设置:

#include <windows.h>
#include <uxtheme.h>

// 定义API枚举和函数指针
typedef enum APP_PREFERENCES_MODE {
    APPMODE_DEFAULT = 0,
    APPMODE_LIGHT,
    APPMODE_DARK
} APP_PREFERENCES_MODE;

typedef HRESULT(WINAPI* SetPreferredAppModeFunc)(APP_PREFERENCES_MODE mode);

void SetGlobalLightTheme() {
    HMODULE hUxTheme = LoadLibrary(L"uxtheme.dll");
    if (!hUxTheme) return;

    SetPreferredAppModeFunc pSetPreferredAppMode = reinterpret_cast<SetPreferredAppModeFunc>(
        GetProcAddress(hUxTheme, "SetPreferredAppMode")
    );
    if (pSetPreferredAppMode) {
        pSetPreferredAppMode(APPMODE_LIGHT);
    }

    FreeLibrary(hUxTheme);
}

2. 对现有窗口禁用深色模式

对应用的主窗口和已有窗口,调用AllowDarkModeForWindow禁用深色模式,并设置浅色主题样式:

#include <dwmapi.h>

void ApplyLightThemeToWindow(HWND hWnd) {
    if (!hWnd) return;

    // 禁用该窗口的深色模式支持
    typedef BOOL(WINAPI* AllowDarkModeForWindowFunc)(HWND, BOOL);
    HMODULE hUxTheme = LoadLibrary(L"uxtheme.dll");
    if (hUxTheme) {
        AllowDarkModeForWindowFunc pAllowDarkMode = reinterpret_cast<AllowDarkModeForWindowFunc>(
            GetProcAddress(hUxTheme, "AllowDarkModeForWindow")
        );
        if (pAllowDarkMode) {
            pAllowDarkMode(hWnd, FALSE);
        }
        FreeLibrary(hUxTheme);
    }

    // 设置窗口使用浅色主题样式
    SetWindowTheme(hWnd, L"Explorer", nullptr);
}

3. 监听新窗口创建,强制浅色主题

使用WH_CBT钩子捕获所有新创建的窗口,自动应用浅色主题设置,确保后续弹出的上下文菜单、对话框等都保持浅色:

HHOOK g_hWndCreateHook = nullptr;

LRESULT CALLBACK CbtHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HCBT_CREATEWND) {
        HWND hNewWnd = reinterpret_cast<HWND>(wParam);
        ApplyLightThemeToWindow(hNewWnd);
    }
    return CallNextHookEx(g_hWndCreateHook, nCode, wParam, lParam);
}

void InstallWindowCreationHook() {
    g_hWndCreateHook = SetWindowsHookEx(WH_CBT, CbtHookProc, GetModuleHandle(nullptr), GetCurrentThreadId());
}

void UninstallWindowCreationHook() {
    if (g_hWndCreateHook) {
        UnhookWindowsHookEx(g_hWndCreateHook);
        g_hWndCreateHook = nullptr;
    }
}

4. 兜底:强制上下文菜单颜色

如果主题设置仍未生效,处理WM_CTLCOLORMENU消息直接设置菜单的背景和文本颜色:

static HBRUSH g_hLightMenuBrush = CreateSolidBrush(RGB(255, 255, 255));

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CTLCOLORMENU: {
            HDC hdcMenu = reinterpret_cast<HDC>(wParam);
            // 设置菜单背景为白色,文本为黑色
            SetBkColor(hdcMenu, RGB(255, 255, 255));
            SetTextColor(hdcMenu, RGB(0, 0, 0));
            return reinterpret_cast<LRESULT>(g_hLightMenuBrush);
        }
        // 其他消息处理...
        case WM_DESTROY:
            DeleteObject(g_hLightMenuBrush);
            UninstallWindowCreationHook();
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}

使用流程

  1. 在应用初始化(或CEF初始化完成后)调用SetGlobalLightTheme()
  2. 对主窗口调用ApplyLightThemeToWindow(hMainWnd)
  3. 安装窗口创建钩子InstallWindowCreationHook()
  4. 确保窗口过程处理WM_CTLCOLORMENU消息

注意事项

  • 上述API仅支持Windows 10 1809(版本10.0.17763)及以上系统,可通过GetVersionEx或VerifyVersionInfo做系统版本判断。
  • 钩子需在应用退出前卸载,避免资源泄漏。
  • 链接时需包含uxtheme.lib和dwmapi.lib。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:37:23