如何在pyqt中实现win10亚克力效果

亚克力效果的实现思路

上一篇博客《如何在pyqt中优雅地实现窗口磨砂效果》 中实现了win7中的Aero效果,但是我还是觉得和win10的亚克力效果相比,Aero还是差了点内味。所以今天早上又在网上搜了一圈,无意中发现了这篇博客《使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景》,点进去认真看了一遍之后深受启发,于是又去改了一下上次实现Aero效果时所用的函数,重新编译为dll给python调用。

具体实现流程

  1. WindowCompositionAttribute.h的枚举类ACCENT_STATE中新增一个ACCENT_ENABLE_ACRYLICBLURBEHIND参数,初值为4;
  2. 定义setBlur()函数的时候,ACCENT_POLICY accent = { ACCENT_ENABLE_ACRYLICBLURBEHIND, 0, gradientColor, 0 },和上次相比列表的第一个参数变成了ACCENT_ENABLE_ACRYLICBLURBEHIND,第三个参数由0变为了gradientColor,这个参数用来设置窗口的背景色;
  3. 在VS2019里面把写好的函数编译为acrylic.dll
  4. 在python中通过hWnd=ctypes.wintypes.HWND(int(self.winId())),把WId类型强制转换为HWND类型,接着设置背景色gradientColor = DWORD(0x50F2F2F2),0x50F2F2F2的前两位是透明度,后面六位是rgb,最后ctypes.cdll.LoadLibrary(‘acrylic_dll\\acrylic.dll’).setBlur(hWnd,gradientColor),实现动态链接库的载入和接口函数的调用,源代码如下:
import sys

from ctypes import cdll
from ctypes.wintypes import HWND, DWORD

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget


class Demo(QWidget):
    """ 亚克力效果的实现 """

    def __init__(self):
        super().__init__()

        self.resize(500, 500)
        # 去除边框,没有这一步的话窗口阴影也会加上亚克力效果
        self.setWindowFlags(Qt.FramelessWindowHint)
        # 背景透明
        self.setAttribute(Qt.WA_TranslucentBackground)

        # 调用api
        hWnd = HWND(int(self.winId()))      # 直接HWND(self.winId())会报错
        gradientColor = DWORD(0x50F2F2F2)   # 设置和亚克力效果相叠加的背景颜色
        cdll.LoadLibrary('acrylic_dll\\acrylic.dll').setBlur(hWnd, gradientColor)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

运行效果如下(老婆依旧如此美丽٩(๑>◡<๑)۶ 如何在pyqt中实现win10亚克力效果

C++、python源代码以及dll

百度网盘(提取码:2la9):链接

上一篇:如何在pyqt中实现纵享新丝滑的的动态Menu


下一篇:PyQt各类对话框的使用案例