如何在pyqt中給無邊框視窗新增DWM環繞陰影

專注的阿熊發表於2021-03-15

# coding:utf-8

from ctypes import POINTER, c_bool, c_int, pointer, sizeof, WinDLL, byref

from ctypes.wintypes import DWORD, HWND, LONG, LPCVOID

from win32 import win32api, win32gui

from win32.lib import win32con

from .c_structures import (

    ACCENT_POLICY,

    ACCENT_STATE,

    MARGINS,

    DWMNCRENDERINGPOLICY,

    DWMWINDOWATTRIBUTE,

    WINDOWCOMPOSITIONATTRIB,

    WINDOWCOMPOSITIONATTRIBDATA,

)

class WindowEffect:

    """ 呼叫 windows api 實現視窗效果 """

    def __init__(self):

        # 呼叫 api

        self.user32 = WinDLL("user32")

        self.dwmapi = WinDLL("dwmapi")

        self.SetWindowCompositionAttribute = self.user32.SetWindowCompositionAttribute

        self.DwmExtendFrameIntoClientArea = self.dwmapi.DwmExtendFrameIntoClientArea

        self.DwmSetWindowAttribute = self.dwmapi.DwmSetWindowAttribute

        self.SetWindowCompositionAttribute.restype = c_bool

        self.DwmExtendFrameIntoClientArea.restype = LONG

        self.DwmSetWindowAttribute.restype = LONG

        self.SetWindowCompositionAttribute.argtypes = [

            c_int,

            POINTER(WINDOWCOMPOSITIONATTRIBDATA),

        ]

        self.DwmSetWindowAttribute.argtypes = [c_int, DWORD, LPCVOID, DWORD]

        self.DwmExtendFrameIntoClientArea.argtypes = [c_int, POINTER(MARGINS)]

        # 初始化結構體

        self.accentPolicy = ACCENT_POLICY()

        self.winCompAttrData = WINDOWCOMPOSITIONATTRIBDATA()

        self.winCompAttrData.Attribute = 外匯跟單gendan5.comWINDOWCOMPOSITIONATTRIB.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):

        """ 給視窗開啟 Win10 的亞克力效果

        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 : 視窗控制程式碼

        """

        self.accentPolicy.AccentState = ACCENT_STATE.ACCENT_ENABLE_BLURBEHIND.value[0]

        # 開啟 Aero

        self.SetWindowCompositionAttribute(hWnd, pointer(self.winCompAttrData))

    def moveWindow(self, hWnd: int):

        """ 移動視窗

        Parameter

        ----------

        hWnd : 視窗控制程式碼

        """

        win32gui.ReleaseCapture()

        win32api.SendMessage(

            hWnd, win32con.WM_SYSCOMMAND, win32con.SC_MOVE + win32con.HTCAPTION, 0

        )

    def addShadowEffect(self, hWnd):

        """ 給視窗新增陰影

        Parameter

        ----------

        hWnd: int or `sip.voidptr`

             視窗控制程式碼

        """

        hWnd = int(hWnd)

        self.DwmSetWindowAttribute(

            hWnd,

            DWMWINDOWATTRIBUTE.DWMWA_NCRENDERING_POLICY.value,

            byref(c_int(DWMNCRENDERINGPOLICY.DWMNCRP_ENABLED.value)),

            4,

        )

        margins = MARGINS(-1, -1, -1, -1)

        self.DwmExtendFrameIntoClientArea(hWnd, byref(margins))


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2762977/,如需轉載,請註明出處,否則將追究法律責任。

相關文章