实现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 转换
  • 弹窗窗口: 如果弹窗也需要跟随主题,需要对每个独立窗口调用
相关推荐
无巧不成书02181 天前
Rust开发环境完全指南:Windows/Linux双平台配置与实战
linux·windows·rust·gnu·msvc·mingw-w64安装·镜像配置
xiaoshuaishuai81 天前
C# ZLibrary数字资源分发
开发语言·windows·c#
私人珍藏库1 天前
[Windows] 电子教鞭演示工具 PointerStick v7.11
windows·自动化·工具·软件·多功能
Full Stack Developme1 天前
Hutool TreeUtil 教程
大数据·windows
破阵子443281 天前
PowerShell-7 下载安装教程(如何更新 PowerShell)
windows
安当加密1 天前
指纹一按,安全上线:指纹登录如何为生产线 Windows 电脑实现低成本防勒索?
windows·安全·电脑
不做超级小白1 天前
解密Win11的Win+S搜索:从索引原理到自启动的攻防战
windows·安全
卵男(章鱼)1 天前
系统终端命令对比大全(Linux发行/macOS/Windows)
linux·运维·服务器·windows·macos
songjunwei11 天前
MFC应用程序是文档/视图结构支持的时候对工具栏加载图片的问题
windows
余衫马1 天前
在 Windows 服务中托管 ASP.NET Core Web API (.net6)
运维·windows·后端·asp.net·.net