PySide2开发中如何用pywin32修改Windows标题栏颜色
Windows 10/11 PySide2 修改窗口标题栏颜色实现方案
前置准备
先安装pywin32依赖,执行命令:pip install pywin32
实现核心是调用Windows桌面窗口管理器(DWM)开放的DwmSetWindowAttribute接口,从Windows 10 1809版本开始,该接口支持单独为指定窗口设置标题栏颜色,无需修改系统全局主题配置。Win11及以上版本额外支持自定义标题栏文字颜色。
注意:必须等PySide2窗口完成原生Win32句柄创建后再调用接口,刚初始化的窗口还未分配句柄,会导致调用失败。
关键参数说明
DWMWA_CAPTION_COLOR:属性值为35,对应标题栏背景色设置DWMWA_TEXT_COLOR:属性值为36,对应标题栏文字颜色设置,仅Win11 22000+版本生效- Windows接口接收的颜色为BGR格式(COLORREF标准,存储顺序为0x00BBGGRR),Qt使用RGB格式,需要做简单转换。
- 若要还原系统默认标题栏样式,给背景色传入
0xFFFFFFFF即可。
完整可运行示例
import sys import ctypes from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton from PySide2.QtGui import QColor # 加载系统DWM接口库 dwmapi = ctypes.WinDLL("dwmapi") DWMWA_CAPTION_COLOR = 35 DWMWA_TEXT_COLOR = 36 def rgb_to_bgr(color: QColor) -> int: """Qt RGB颜色转Windows要求的BGR格式""" return color.blue() << 16 | color.green() << 8 | color.red() class TestWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("自定义标题栏测试") self.resize(800, 600) # 测试按钮:点击切换标题栏颜色 self.switch_btn = QPushButton("切换标题栏颜色", self) self.switch_btn.clicked.connect(self.switch_color) self.color_idx = 0 # 预设颜色组:(背景色, 文字色) self.color_presets = [ (QColor(30, 136, 229), QColor(255,255,255)), (QColor(67, 160, 71), QColor(255,255,255)), (QColor(229, 57, 53), QColor(255,255,255)), (QColor(251, 192, 45), QColor(0,0,0)) ] def showEvent(self, event): super().showEvent(event) # 首次显示时窗口句柄已生成,初始化标题栏颜色 if not hasattr(self, "_title_initialized"): bg, text = self.color_presets[0] self.set_title_color(bg, text) self._title_initialized = True def set_title_color(self, bg_color: QColor, text_color: QColor): hwnd = self.winId().__int__() # 获取窗口原生Win32句柄 bg_val = ctypes.c_uint(rgb_to_bgr(bg_color)) text_val = ctypes.c_uint(rgb_to_bgr(text_color)) # 设置标题栏背景 dwmapi.DwmSetWindowAttribute( ctypes.c_void_p(hwnd), DWMWA_CAPTION_COLOR, ctypes.byref(bg_val), ctypes.sizeof(bg_val) ) # 设置标题栏文字颜色 dwmapi.DwmSetWindowAttribute( ctypes.c_void_p(hwnd), DWMWA_TEXT_COLOR, ctypes.byref(text_val), ctypes.sizeof(text_val) ) def switch_color(self): self.color_idx = (self.color_idx + 1) % len(self.color_presets) bg, text = self.color_presets[self.color_idx] self.set_title_color(bg, text) if __name__ == "__main__": app = QApplication(sys.argv) win = TestWindow() win.show() sys.exit(app.exec_())
效果参考

兼容说明
- Windows 10 1809以下版本调用接口不会报错,但不会生效,不会引发程序崩溃
- 系统开启深色/浅色模式时,接口设置的颜色会自动和系统主题做适配,无需额外调整参数
- 如果窗口自定义了无边框样式自行绘制标题栏,该接口不生效,需要自行处理绘制逻辑
内容的提问来源于stack exchange,提问作者Fakhreddine
相关产品推荐
相关产品推荐

