实现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 转换
  • 弹窗窗口: 如果弹窗也需要跟随主题,需要对每个独立窗口调用
相关推荐
传奇开心果编程6 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
懒人87 小时前
Windows11系统优化指南
windows·经验分享
Vex2une7 小时前
Windows 磁盘管理发展史:从 FDISK 分区表到存储池与虚拟磁盘
windows·gpt·磁盘管理·mbr·fdisk·动态磁盘·储存池
今夕资源网7 小时前
从夯到拉模拟器RankPix windows本地版 exe
windows·exe·从夯到拉·从夯到拉模拟器·rankpix·本地版
kakakahahahaha8 小时前
Windows系统时间校准指南:time命令、date命令、w32tm /resync与CMOS排查
windows·笔记本电脑·软件需求
一技安身8 小时前
【mysql】Windows MySQL 8.4.10 绿色免安装喂饭教程
windows·mysql·adb
传奇开心果编程9 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
sukalot10 小时前
Windows 驱动实例分析系列:libwdi 驱动分析 - 应用篇(一)
windows·驱动开发
小道士写程序10 小时前
Windows Rust 环境安装指导
开发语言·windows·rust
传奇开心果编程10 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer