Skip to content

Commit 4bbdf8d

Browse files
committed
修复 Win11 Mica 特效开启"在标题栏和窗口边框上显示强调色"时强调色渲染位置错误的问题 (#186)
1 parent a7a20b6 commit 4bbdf8d

File tree

6 files changed

+125
-13
lines changed

6 files changed

+125
-13
lines changed

qframelesswindow/linux/window_effect.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# coding:utf-8
2+
from PyQt5.QtGui import QColor
3+
24

35
class LinuxWindowEffect:
46
""" Linux window effect """
@@ -25,6 +27,29 @@ def setAcrylicEffect(self, hWnd, gradientColor="F2F2F230", isEnableShadow=True,
2527
"""
2628
pass
2729

30+
def setBorderAccentColor(self, hWnd, color: QColor):
31+
""" Set the border color of the window
32+
33+
Parameters
34+
----------
35+
hWnd: int or `sip.voidptr`
36+
Window handle
37+
38+
color: QColor
39+
Border Accent color
40+
"""
41+
pass
42+
43+
def removeBorderAccentColor(self, hWnd):
44+
""" Remove the border color of the window
45+
46+
Parameters
47+
----------
48+
hWnd: int or `sip.voidptr`
49+
Window handle
50+
"""
51+
pass
52+
2853
def setMicaEffect(self, hWnd, isDarkMode=False, isAlt=False):
2954
""" Add mica effect to the window (Win11 only)
3055

qframelesswindow/mac/window_effect.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import objc
33
import Cocoa
44
from PyQt5.QtWidgets import QMacCocoaViewContainer
5+
from PyQt5.QtGui import QColor
56
from ..utils.mac_utils import getNSWindow
67

78
class MacWindowEffect:
@@ -46,6 +47,29 @@ def setAcrylicEffect(self, hWnd, gradientColor="F2F2F230", isEnableShadow=True,
4647
content.addSubview_positioned_relativeTo_(
4748
visualEffectView, Cocoa.NSWindowBelow, container)
4849

50+
def setBorderAccentColor(self, hWnd, color: QColor):
51+
""" Set the border color of the window
52+
53+
Parameters
54+
----------
55+
hWnd: int or `sip.voidptr`
56+
Window handle
57+
58+
color: QColor
59+
Border Accent color
60+
"""
61+
pass
62+
63+
def removeBorderAccentColor(self, hWnd):
64+
""" Remove the border color of the window
65+
66+
Parameters
67+
----------
68+
hWnd: int or `sip.voidptr`
69+
Window handle
70+
"""
71+
pass
72+
4973
def setMicaEffect(self, hWnd, isDarkMode=False, isAlt=False):
5074
""" Add mica effect to the window (Win11 only)
5175

qframelesswindow/utils/win32_utils.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# coding:utf-8
2+
import sys
3+
import warnings
24
from ctypes import Structure, byref, sizeof, windll, c_int, c_ulong, c_bool, POINTER, WinDLL, wintypes
35
from ctypes.wintypes import DWORD, HWND, LPARAM, RECT, UINT
46
from platform import platform
5-
import sys
6-
import warnings
7+
from winreg import OpenKey, HKEY_CURRENT_USER, KEY_READ, QueryValueEx, CloseKey
78

89
import win32api
910
import win32con
@@ -37,6 +38,21 @@ def getSystemAccentColor():
3738
return QColor(color.value)
3839

3940

41+
def isSystemBorderAccentEnabled():
42+
""" Check whether the border accent is enabled """
43+
if not isGreaterEqualWin11():
44+
return False
45+
46+
try:
47+
key = OpenKey(HKEY_CURRENT_USER, r"SOFTWARE\Microsoft\Windows\DWM", 0, KEY_READ)
48+
value, _ = QueryValueEx(key, "ColorPrevalence")
49+
CloseKey(key)
50+
51+
return bool(value)
52+
except:
53+
return False
54+
55+
4056
def isMaximized(hWnd):
4157
""" Determine whether the window is maximized
4258

qframelesswindow/windows/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from ..titlebar import TitleBar
1414
from ..utils import win32_utils as win_utils
15-
from ..utils.win32_utils import Taskbar
15+
from ..utils.win32_utils import Taskbar, isSystemBorderAccentEnabled, getSystemAccentColor
1616
from .c_structures import LPNCCALCSIZE_PARAMS
1717
from .window_effect import WindowsWindowEffect
1818

@@ -178,6 +178,12 @@ def nativeEvent(self, eventType, message):
178178

179179
result = 0 if not msg.wParam else win32con.WVR_REDRAW
180180
return True, result
181+
elif msg.message == win32con.WM_SETFOCUS and isSystemBorderAccentEnabled():
182+
self.windowEffect.setBorderAccentColor(self.winId(), getSystemAccentColor())
183+
return True, 0
184+
elif msg.message == win32con.WM_KILLFOCUS:
185+
self.windowEffect.removeBorderAccentColor(self.winId())
186+
return True, 0
181187

182188
return super().nativeEvent(eventType, message)
183189

qframelesswindow/windows/c_structures.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,14 @@ class DWMWINDOWATTRIBUTE(Enum):
9494
DWMWA_FREEZE_REPRESENTATION = 15
9595
DWMWA_PASSIVE_UPDATE_MODE = 16
9696
DWMWA_USE_HOSTBACKDROPBRUSH = 17
97-
DWMWA_USE_IMMERSIVE_DARK_MODE = 18
98-
DWMWA_WINDOW_CORNER_PREFERENCE = 19
99-
DWMWA_BORDER_COLOR = 20
100-
DWMWA_CAPTION_COLOR = 21
101-
DWMWA_TEXT_COLOR = 22
102-
DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 23
103-
DWMWA_LAST = 24
97+
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
98+
DWMWA_WINDOW_CORNER_PREFERENCE = 33
99+
DWMWA_BORDER_COLOR = 34
100+
DWMWA_CAPTION_COLOR = 35
101+
DWMWA_TEXT_COLOR = 36
102+
DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37
103+
DWMWA_SYSTEMBACKDROP_TYPE = 38
104+
DWMWA_LAST = 39
104105

105106

106107
class MARGINS(Structure):

qframelesswindow/windows/window_effect.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import win32api
88
import win32con
99
import win32gui
10+
from PyQt5.QtGui import QColor
1011

1112
from .c_structures import (ACCENT_POLICY, ACCENT_STATE, DWMNCRENDERINGPOLICY,
1213
DWMWINDOWATTRIBUTE, MARGINS,
@@ -82,6 +83,44 @@ def setAcrylicEffect(self, hWnd, gradientColor="F2F2F299", enableShadow=True, an
8283
self.winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY.value
8384
self.SetWindowCompositionAttribute(hWnd, pointer(self.winCompAttrData))
8485

86+
def setBorderAccentColor(self, hWnd, color: QColor):
87+
""" Set the border color of the window
88+
89+
Parameters
90+
----------
91+
hWnd: int or `sip.voidptr`
92+
Window handle
93+
94+
color: QColor
95+
Border Accent color
96+
"""
97+
if not isGreaterEqualWin11():
98+
return
99+
100+
hWnd = int(hWnd)
101+
colorref = DWORD(color.red() | (color.green() << 8) | (color.blue() << 16))
102+
self.DwmSetWindowAttribute(hWnd,
103+
DWMWINDOWATTRIBUTE.DWMWA_BORDER_COLOR.value,
104+
byref(colorref),
105+
4)
106+
107+
def removeBorderAccentColor(self, hWnd):
108+
""" Remove the border color of the window
109+
110+
Parameters
111+
----------
112+
hWnd: int or `sip.voidptr`
113+
Window handle
114+
"""
115+
if not isGreaterEqualWin11():
116+
return
117+
118+
hWnd = int(hWnd)
119+
self.DwmSetWindowAttribute(hWnd,
120+
DWMWINDOWATTRIBUTE.DWMWA_BORDER_COLOR.value,
121+
byref(DWORD(0xFFFFFFFF)),
122+
4)
123+
85124
def setMicaEffect(self, hWnd, isDarkMode=False, isAlt=False):
86125
""" Add the mica effect to the window (Win11 only)
87126
@@ -101,7 +140,8 @@ def setMicaEffect(self, hWnd, isDarkMode=False, isAlt=False):
101140
return
102141

103142
hWnd = int(hWnd)
104-
margins = MARGINS(-1, -1, -1, -1)
143+
# fix issue #125
144+
margins = MARGINS(16777215, 16777215, 0, 0)
105145
self.DwmExtendFrameIntoClientArea(hWnd, byref(margins))
106146

107147
self.winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY.value
@@ -115,9 +155,9 @@ def setMicaEffect(self, hWnd, isDarkMode=False, isAlt=False):
115155
if sys.getwindowsversion().build < 22523:
116156
self.DwmSetWindowAttribute(hWnd, 1029, byref(c_int(1)), 4)
117157
else:
118-
self.DwmSetWindowAttribute(hWnd, 38, byref(c_int(4 if isAlt else 2)), 4)
158+
self.DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE.value, byref(c_int(4 if isAlt else 2)), 4)
119159

120-
self.DwmSetWindowAttribute(hWnd, 20, byref(c_int(1*isDarkMode)), 4)
160+
self.DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE.value, byref(c_int(1*isDarkMode)), 4)
121161

122162
def setAeroEffect(self, hWnd):
123163
""" Add the aero effect to the window

0 commit comments

Comments
 (0)