实现Windows系统标题栏颜色跟随主题动态切换

前言

使用Qt实现Windows桌面程序,如果使用了系统默认的标题栏,标题栏的颜色可能和软件UI的主题色不太搭配,如果还有不同主题的切换,那么修改系统标题栏颜色就是个必要的需求了,本文使用Windows接口实现系统标题栏颜色的自定义,然后配合在Qt中使用。

技术方案

推荐方案:使用 Windows DWM API
Windows 10 1809+Windows 11 支持通过 DwmSetWindowAttribute 函数设置标题栏颜色:

  • DWMWA_CAPTION_COLOR (35): 设置标题栏背景颜色
  • DWMWA_TEXT_COLOR (36): 设置标题栏文字颜色
  • DWMWA_USE_IMMERSIVE_DARK_MODE (20): 启用深色模式

代码实现

1. 创建 TitleBarHelper 工具类

复制代码
// TitleBarHelper.h
#pragma once
#include <QObject>
#include <QWindow>
#include <QColor>

class TitleBarHelper : public QObject
{
    Q_OBJECT
public:
    explicit TitleBarHelper(QObject *parent = nullptr);

    // 设置标题栏颜色
    Q_INVOKABLE void setTitleBarColor(QWindow *window, const QColor &color);

    // 设置标题栏文字颜色
    Q_INVOKABLE void setTitleBarTextColor(QWindow *window, const QColor &color);

    // 设置深色/浅色模式(影响系统按钮图标颜色)
    Q_INVOKABLE void setDarkMode(QWindow *window, bool dark);

    // 一键应用主题
    Q_INVOKABLE void applyTheme(QWindow *window, int themeMode);

private:
    bool setWindowAttribute(HWND hwnd, DWORD attribute, LPCVOID pvAttribute, DWORD cbAttribute);
};

2. 实现 TitleBarHelper.cpp

复制代码
#include "TitleBarHelper.h"

#ifdef Q_OS_WIN
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")

// Windows 11/10 1809+ DWM 属性
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
#ifndef DWMWA_CAPTION_COLOR
#define DWMWA_CAPTION_COLOR 35
#endif
#ifndef DWMWA_TEXT_COLOR
#define DWMWA_TEXT_COLOR 36
#endif
#endif

void TitleBarHelper::applyTheme(QWindow *window, int themeMode)
{
    if (!window) return;

#ifdef Q_OS_WIN
    HWND hwnd = (HWND)window->winId();

    if (themeMode == 0) {
        // 深色主题
        setDarkMode(window, true);
        setTitleBarColor(window, QColor("#2E2F33"));    // titleBgClr for dark
        setTitleBarTextColor(window, QColor("#FFFFFF"));
    } else {
        // 浅色主题
        setDarkMode(window, false);
        setTitleBarColor(window, QColor("#E4E3E3"));    // titleBgClr for light
        setTitleBarTextColor(window, QColor("#131A29"));
    }
#endif
}

3. 注册到 QML

复制代码
qmlRegisterType<TitleBarHelper>("Utils", 1, 0, "TitleBarHelper");

4. 在 QML 中使用

复制代码
在 MainWindow.qml 中:


import VoiceAI.Utils 1.0

ApplicationWindow{
    id: mainWindow

    TitleBarHelper {
        id: titleBarHelper
    }

    Component.onCompleted: {
        // 初始化标题栏颜色
        titleBarHelper.applyTheme(mainWindow, customizeSetting.getTheme())
    }

    onSigAppThemeChange: {
        // 主题切换时更新标题栏颜色
        titleBarHelper.applyTheme(mainWindow, themeMode)
    }
}

5. 修改 .pro 文件

确保链接 dwmapi 库:

复制代码
win32:{
    LIBS += -ldwmapi
}

注意事项

  • Windows版本兼容性: DWMWA_CAPTION_COLOR 需要 Windows 10 1809+,建议添加版本检测
  • 颜色格式: DWM API 使用 COLORREF (0x00BBGGRR),需要从 QColor 转换
  • 弹窗窗口: 如果弹窗也需要跟随主题,需要对每个独立窗口调用
相关推荐
埃博拉酱3 天前
VS Code Remote SSH 连接 Windows 服务器卡在"下载 VS Code 服务器":prcdn DNS 解析失败的诊断与 BITS 断点续传
windows·ssh·visual studio code
唐宋元明清21884 天前
.NET 本地Db数据库-技术方案选型
windows·c#
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
tryCbest4 天前
Windows环境下配置pip镜像源
windows·pip
呉師傅4 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑
百事牛科技4 天前
保护文档安全:PDF限制功能详解与实操
windows·pdf
一个人旅程~4 天前
如何用命令行把win10/win11设置为长期暂停更新?
linux·windows·经验分享·电脑
一个假的前端男4 天前
[特殊字符] Flutter 安装完整指南 Windows—— 2026最新版
windows·flutter
倚肆4 天前
在 Windows Docker 中安装并配置 Nginx (映射 Windows 端口与路径)
windows·nginx·docker
破无差4 天前
拯救你的C盘
windows