实现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 转换
  • 弹窗窗口: 如果弹窗也需要跟随主题,需要对每个独立窗口调用
相关推荐
软件课代表CiCi5 小时前
运行库是什么?电脑缺运行库怎么办?c++运行库缺失修复全攻略
开发语言·c++·windows·电脑·dll修复·dll丢失·运行库
梅孔立6 小时前
OpenCode + Windows PowerShell 完整安装使用教程
windows
2601_962364976 小时前
面向设备厂商:Windows Hello 认证摄像头核心要点
windows·安全·电脑
星间都市山脉14 小时前
Android16 SystemService.onBootPhase 调用时机
android·java·linux·windows·ubuntu
小羊没烦恼!15 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
公子小六19 小时前
基于.NET的Windows窗体编程之WinForms自定义控件(1)
windows·.net
江湖人称菠萝包1 天前
【Windows】《深入浅出Windows API程序设计:核心编程篇》笔记-Chapter4-进程
windows·笔记
www.021 天前
Codex额度用完怎么办?Windows定时自动继续VS Code Codex任务实战
人工智能·windows·vscode·自动化·openai·codex·autohotkey
StarDream-Online2 天前
Windows 下 uv 安装与配置完全指南(含环境变量设置)
windows·uv
空 白II2 天前
cuda toolkit 10.0 windows 安装实录
windows