亚克力效果

《如何在pyqt中实现窗口磨砂效果》《如何在pyqt中实现win10亚克力效果》中,我们调用C++ dll来实现窗口效果,这种方法要求电脑上必须装有MSVC。Visual Studio装起来确实费时又占C盘空间,所以今天在python中直接调用 SetWindowCompositionAttribute,关于更多无边框窗体的解决方案可以参见《如何在pyqt中自定义无边框窗口》。下面是这次的亚克力效果(硝子太美了(๑¯∀¯๑)):

具体代码

结构体和枚举类

为了调用 Windows 的 API,我们需要定义一些结构体和枚举类,具体如下:

# coding:utf-8

from ctypes import POINTER, Structure
from ctypes.wintypes import DWORD, HWND, ULONG
from enum import Enum class WINDOWCOMPOSITIONATTRIB(Enum):
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_LAST = 23 class ACCENT_STATE(Enum):
""" 客户区状态枚举类 """
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3, # Aero效果
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, # 亚克力效果
ACCENT_INVALID_STATE = 5 class ACCENT_POLICY(Structure):
""" 设置客户区的具体属性 """
_fields_ = [
('AccentState', DWORD),
('AccentFlags', DWORD),
('GradientColor', DWORD),
('AnimationId', DWORD),
] class WINDOWCOMPOSITIONATTRIBDATA(Structure):
_fields_ = [
('Attribute', DWORD),
('Data', POINTER(ACCENT_POLICY)), # POINTER()接收任何ctypes类型,并返回一个指针类型
('SizeOfData', ULONG),
]

WindowEffect 类

WindowEffectsetAcrylicEffect 函数中新增了两个参数—— isEnableShadowanimationId,一个控制亚克力窗口的阴影,另一个控制磨砂动画。在demo中是看不出 animationId 的具体效果的,只有窗口最大化和还原时这个动画过程才会显现出来,具体过程可以参见上一篇博客,里面的动图显示得很清楚,下面是这个类的代码:

# coding:utf-8

from ctypes import POINTER, c_bool, sizeof, windll,pointer,c_int
from ctypes.wintypes import DWORD, HWND, ULONG from win32 import win32api, win32gui
from win32.lib import win32con from .c_structures import (ACCENT_POLICY, ACCENT_STATE,
WINDOWCOMPOSITIONATTRIB,
WINDOWCOMPOSITIONATTRIBDATA) class WindowEffect():
""" 调用windows api实现窗口效果 """ def __init__(self):
# 调用api
self.SetWindowCompositionAttribute = windll.user32.SetWindowCompositionAttribute
self.SetWindowCompositionAttribute.restype = c_bool
self.SetWindowCompositionAttribute.argtypes = [
c_int, POINTER(WINDOWCOMPOSITIONATTRIBDATA)]
# 初始化结构体
self.accentPolicy = ACCENT_POLICY()
self.winCompAttrData = WINDOWCOMPOSITIONATTRIBDATA()
self.winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY.value[0]
self.winCompAttrData.SizeOfData = sizeof(self.accentPolicy)
self.winCompAttrData.Data = pointer(self.accentPolicy) def setAcrylicEffect(self, hWnd: int, gradientColor: str = 'F2F2F230',
isEnableShadow: bool = True, animationId: int = 0):
""" 开启亚克力效果 Parameters
----------
hWnd: int
窗口句柄 gradientColor: str
十六进制亚克力混合色,对应 RGBA 四个分量 isEnableShadow: bool
是否启用窗口阴影 animationId: int
控制磨砂动画
"""
# 亚克力混合色
gradientColor = gradientColor[6:] + gradientColor[4:6] + \
gradientColor[2:4] + gradientColor[:2]
gradientColor = DWORD(int(gradientColor, base=16))
# 磨砂动画
animationId = DWORD(animationId)
# 窗口阴影
accentFlags = DWORD(0x20 | 0x40 | 0x80 |
0x100) if isEnableShadow else DWORD(0)
self.accentPolicy.AccentState = ACCENT_STATE.ACCENT_ENABLE_ACRYLICBLURBEHIND.value[0]
self.accentPolicy.GradientColor = gradientColor
self.accentPolicy.AccentFlags = accentFlags
self.accentPolicy.AnimationId = animationId
# 开启亚克力
self.SetWindowCompositionAttribute(hWnd, pointer(self.winCompAttrData)) def setAeroEffect(self, hWnd: int):
""" 开启 Aero 效果 Parameter
----------
hWnd: int
窗口句柄
"""
self.accentPolicy.AccentState = ACCENT_STATE.ACCENT_ENABLE_BLURBEHIND.value[0]
# 开启Aero
self.SetWindowCompositionAttribute(hWnd, pointer(self.winCompAttrData)) def moveWindow(self, hWnd: int):
""" 移动窗口 Parameter
----------
hWnd: int or `sip.voidptr`
窗口句柄
"""
win32gui.ReleaseCapture()
win32api.SendMessage(hWnd, win32con.WM_SYSCOMMAND,
win32con.SC_MOVE + win32con.HTCAPTION, 0)

demo

# coding:utf-8

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget from my_window_effect import WindowEffect class Demo(QWidget): def __init__(self, parent=None):
super().__init__(parent) self.windowEffect = WindowEffect()
self.resize(500, 500)
self.setWindowFlags(Qt.FramelessWindowHint)
# 必须用样式表使背景透明,别用 setAttribute(Qt.WA_TranslucentBackground),不然界面会卡顿
self.setStyleSheet("background:transparent")
self.windowEffect.setAcrylicEffect(int(self.winId())) def mousePressEvent(self, QMouseEvent):
""" 移动窗口 """
self.windowEffect.moveWindow(self.winId()) if __name__ == "__main__":
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())

写在最后

文中用到的文件我都放在了百度网盘(提取码:m1jr)中,可以自取,喜欢的话就点个赞吧~~

最新文章

  1. Delphi 获取系统时间后格式化输出
  2. How to export a template in Visual Studio?
  3. 基于jquery的inputlimiter 实现字数限制功能
  4. js按钮点击展开收起
  5. NOIP2015 运输计划(二分+LCA+差分)
  6. javascript将毫秒还原为可读时间格式
  7. Android - Animation 贝塞尔曲线之美
  8. 如何让Gridview在没有数据的时候显示表头(asp.net)
  9. js代码大全(各种方法、属性)《转载》
  10. [SDOI2016]游戏
  11. luoguo 1306 斐波那契公约数
  12. SQL Server数据库的兼容级别
  13. Lintcode: Sort Colors II 解题报告
  14. 计蒜客 31459 - Trace - [线段树][2018ICPC徐州网络预赛G题]
  15. ArcGIS Pro体验03——主界面
  16. Android将图片保存到相册并及时看到
  17. fieldset、legend、display html元素
  18. QGIS与Python
  19. 用Java axis2调用.net平台的Webservice出现的一些问题
  20. leetcode669

热门文章

  1. 一个简单的js时钟
  2. Improving Adversarial Robustness via Channel-Wise Activation Suppressing
  3. Java初学者作业——编写JAVA程序,根据用户输入课程名称,输出对应课程的简介,各门课程的简介见表
  4. 基于机器学习和TFIDF的情感分类算法,详解自然语言处理
  5. 怎样在idea添加log日志 以及log4j2配置文件解读
  6. Linux中ssh登陆慢的两种原因
  7. Word2010制作课程表
  8. LINUX学习-Nginx实现https
  9. less 循环模拟sass的for循环效果
  10. js对象方法