QtCanpool 3.3.0
载入中...
搜索中...
未找到
windowkit_win_p.h
浏览该文件的文档.
1
5#ifndef WINDOWKIT_WIN_P_H
6#define WINDOWKIT_WIN_P_H
7
8//
9// W A R N I N G !!!
10// -----------------
11//
12// This file is not part of the QxWindow API. It is used purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or may even be removed.
15//
16
17// it is known to be 6.5.3
18#if defined(Q_CC_MINGW) && (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3))
19#define Q_CC_MINGW_SUPPORT_DPI_API
20#endif
21
22#include <QtCore/private/qsystemlibrary_p.h>
23#include <QtGui/QGuiApplication>
24#include <QtGui/QPalette>
25#include <QtGui/QStyleHints>
26
27#include "windowkit_win.h"
28#include <dwmapi.h>
29#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
30#include <shellscalingapi.h>
31#include <timeapi.h>
32#endif
33
34// Don't include this header in any header files.
35
37
38enum _DWMWINDOWATTRIBUTE {
39 // [set] BOOL, Allows the use of host backdrop brushes for the window.
40 _DWMWA_USE_HOSTBACKDROPBRUSH = 17,
41
42 // Undocumented, the same with DWMWA_USE_IMMERSIVE_DARK_MODE, but available on systems
43 // before Win10 20H1.
44 _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,
45
46 // [set] BOOL, Allows a window to either use the accent color, or dark, according to the
47 // user Color Mode preferences.
48 _DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
49
50 // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners
51 _DWMWA_WINDOW_CORNER_PREFERENCE = 33,
52
53 // [get] UINT, width of the visible border around a thick frame window
54 _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37,
55
56 // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window,
57 // including behind the non-client area.
58 _DWMWA_SYSTEMBACKDROP_TYPE = 38,
59
60 // Undocumented, use this value to enable Mica material on Win11 21H2. You should use
61 // DWMWA_SYSTEMBACKDROP_TYPE instead on Win11 22H2 and newer.
62 _DWMWA_MICA_EFFECT = 1029
63};
64
65// Types used with DWMWA_SYSTEMBACKDROP_TYPE
66enum _DWM_SYSTEMBACKDROP_TYPE {
67 _DWMSBT_AUTO, // [Default] Let DWM automatically decide the system-drawn backdrop for this
68 // window.
69 _DWMSBT_NONE, // [Disable] Do not draw any system backdrop.
70 _DWMSBT_MAINWINDOW, // [Mica] Draw the backdrop material effect corresponding to a
71 // long-lived window.
72 _DWMSBT_TRANSIENTWINDOW, // [Acrylic] Draw the backdrop material effect corresponding to a
73 // transient window.
74 _DWMSBT_TABBEDWINDOW, // [Mica Alt] Draw the backdrop material effect corresponding to a
75 // window with a tabbed title bar.
76};
77
78enum WINDOWCOMPOSITIONATTRIB {
79 WCA_UNDEFINED = 0,
80 WCA_NCRENDERING_ENABLED = 1,
81 WCA_NCRENDERING_POLICY = 2,
82 WCA_TRANSITIONS_FORCEDISABLED = 3,
83 WCA_ALLOW_NCPAINT = 4,
84 WCA_CAPTION_BUTTON_BOUNDS = 5,
85 WCA_NONCLIENT_RTL_LAYOUT = 6,
86 WCA_FORCE_ICONIC_REPRESENTATION = 7,
87 WCA_EXTENDED_FRAME_BOUNDS = 8,
88 WCA_HAS_ICONIC_BITMAP = 9,
89 WCA_THEME_ATTRIBUTES = 10,
90 WCA_NCRENDERING_EXILED = 11,
91 WCA_NCADORNMENTINFO = 12,
92 WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
93 WCA_VIDEO_OVERLAY_ACTIVE = 14,
94 WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
95 WCA_DISALLOW_PEEK = 16,
96 WCA_CLOAK = 17,
97 WCA_CLOAKED = 18,
98 WCA_ACCENT_POLICY = 19,
99 WCA_FREEZE_REPRESENTATION = 20,
100 WCA_EVER_UNCLOAKED = 21,
101 WCA_VISUAL_OWNER = 22,
102 WCA_HOLOGRAPHIC = 23,
103 WCA_EXCLUDED_FROM_DDA = 24,
104 WCA_PASSIVEUPDATEMODE = 25,
105 WCA_USEDARKMODECOLORS = 26,
106 WCA_CORNER_STYLE = 27,
107 WCA_PART_COLOR = 28,
108 WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
109 WCA_LAST = 30
110};
111
112enum ACCENT_STATE {
113 ACCENT_DISABLED = 0,
114 ACCENT_ENABLE_GRADIENT = 1,
115 ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
116 ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
117 ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
118 ACCENT_ENABLE_HOST_BACKDROP = 5, // RS5 1809
119 ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
120};
121
122enum ACCENT_FLAG {
123 ACCENT_NONE = 0,
124 ACCENT_ENABLE_ACRYLIC = 1,
125 ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY = 482
126};
127
128struct ACCENT_POLICY {
129 DWORD dwAccentState;
130 DWORD dwAccentFlags;
131 DWORD dwGradientColor; // #AABBGGRR
132 DWORD dwAnimationId;
133};
134using PACCENT_POLICY = ACCENT_POLICY *;
135
136struct WINDOWCOMPOSITIONATTRIBDATA {
137 WINDOWCOMPOSITIONATTRIB Attrib;
138 PVOID pvData;
139 SIZE_T cbData;
140};
141using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
142
143enum PREFERRED_APP_MODE {
144 PAM_DEFAULT = 0, // Default behavior on systems before Win10 1809. It indicates the
145 // application doesn't support dark mode at all.
146 PAM_AUTO = 1, // Available since Win10 1809, let system decide whether to enable dark mode or not.
147 PAM_DARK = 2, // Available since Win10 1903, force dark mode regardless of the system theme.
148 PAM_LIGHT = 3, // Available since Win10 1903, force light mode regardless of the system theme.
149 PAM_MAX = 4
150};
151
152using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
153
154// Win10 1809 (10.0.17763)
155using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(VOID); // Ordinal 104
156using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL); // Ordinal 133
157using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL); // Ordinal 135
158using FlushMenuThemesPtr = VOID(WINAPI *)(VOID); // Ordinal 136
159// Win10 1903 (10.0.18362)
160using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); // Ordinal 135
161
162namespace
163{
164
165struct DynamicApis {
166 static const DynamicApis &instance()
167 {
168 static const DynamicApis inst{};
169 return inst;
170 }
171
172#define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = nullptr
173
174 DYNAMIC_API_DECLARE(DwmFlush);
175 DYNAMIC_API_DECLARE(DwmIsCompositionEnabled);
176 DYNAMIC_API_DECLARE(DwmGetCompositionTimingInfo);
177 DYNAMIC_API_DECLARE(DwmGetWindowAttribute);
178 DYNAMIC_API_DECLARE(DwmSetWindowAttribute);
179 DYNAMIC_API_DECLARE(DwmExtendFrameIntoClientArea);
180 DYNAMIC_API_DECLARE(DwmEnableBlurBehindWindow);
181#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
182 DYNAMIC_API_DECLARE(GetDpiForWindow);
183 DYNAMIC_API_DECLARE(GetSystemMetricsForDpi);
184 DYNAMIC_API_DECLARE(AdjustWindowRectExForDpi);
185 DYNAMIC_API_DECLARE(GetDpiForMonitor);
186#endif
187 DYNAMIC_API_DECLARE(timeGetDevCaps);
188 DYNAMIC_API_DECLARE(timeBeginPeriod);
189 DYNAMIC_API_DECLARE(timeEndPeriod);
190
191#undef DYNAMIC_API_DECLARE
192
193 SetWindowCompositionAttributePtr pSetWindowCompositionAttribute = nullptr;
194 RefreshImmersiveColorPolicyStatePtr pRefreshImmersiveColorPolicyState = nullptr;
195 AllowDarkModeForWindowPtr pAllowDarkModeForWindow = nullptr;
196 AllowDarkModeForAppPtr pAllowDarkModeForApp = nullptr;
197 FlushMenuThemesPtr pFlushMenuThemes = nullptr;
198 SetPreferredAppModePtr pSetPreferredAppMode = nullptr;
199private:
200 DynamicApis()
201 {
202#define DYNAMIC_API_RESOLVE(DLL, NAME) p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
203
204 QSystemLibrary user32(QStringLiteral("user32"));
205#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
206 DYNAMIC_API_RESOLVE(user32, GetDpiForWindow);
207 DYNAMIC_API_RESOLVE(user32, GetSystemMetricsForDpi);
208 DYNAMIC_API_RESOLVE(user32, AdjustWindowRectExForDpi);
209#endif
210 DYNAMIC_API_RESOLVE(user32, SetWindowCompositionAttribute);
211
212#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
213 QSystemLibrary shcore(QStringLiteral("shcore"));
214 DYNAMIC_API_RESOLVE(shcore, GetDpiForMonitor);
215#endif
216
217 QSystemLibrary dwmapi(QStringLiteral("dwmapi"));
218 DYNAMIC_API_RESOLVE(dwmapi, DwmFlush);
219 DYNAMIC_API_RESOLVE(dwmapi, DwmIsCompositionEnabled);
220 DYNAMIC_API_RESOLVE(dwmapi, DwmGetCompositionTimingInfo);
221 DYNAMIC_API_RESOLVE(dwmapi, DwmGetWindowAttribute);
222 DYNAMIC_API_RESOLVE(dwmapi, DwmSetWindowAttribute);
223 DYNAMIC_API_RESOLVE(dwmapi, DwmExtendFrameIntoClientArea);
224 DYNAMIC_API_RESOLVE(dwmapi, DwmEnableBlurBehindWindow);
225
226 QSystemLibrary winmm(QStringLiteral("winmm"));
227 DYNAMIC_API_RESOLVE(winmm, timeGetDevCaps);
228 DYNAMIC_API_RESOLVE(winmm, timeBeginPeriod);
229 DYNAMIC_API_RESOLVE(winmm, timeEndPeriod);
230
231#undef DYNAMIC_API_RESOLVE
232
233#define UNDOC_API_RESOLVE(DLL, NAME, ORDINAL) \
234 p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(MAKEINTRESOURCEA(ORDINAL)))
235
236 QSystemLibrary uxtheme(QStringLiteral("uxtheme"));
237 UNDOC_API_RESOLVE(uxtheme, RefreshImmersiveColorPolicyState, 104);
238 UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForWindow, 133);
239 UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForApp, 135);
240 UNDOC_API_RESOLVE(uxtheme, FlushMenuThemes, 136);
241 UNDOC_API_RESOLVE(uxtheme, SetPreferredAppMode, 135);
242
243#undef UNDOC_API_RESOLVE
244 }
245
246 ~DynamicApis() = default;
247
248 Q_DISABLE_COPY(DynamicApis)
249};
250
251}
252
253static inline constexpr bool operator==(const POINT &lhs, const POINT &rhs) noexcept
254{
255 return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
256}
257
258static inline constexpr bool operator!=(const POINT &lhs, const POINT &rhs) noexcept
259{
260 return !operator==(lhs, rhs);
261}
262
263static inline constexpr bool operator==(const SIZE &lhs, const SIZE &rhs) noexcept
264{
265 return ((lhs.cx == rhs.cx) && (lhs.cy == rhs.cy));
266}
267
268static inline constexpr bool operator!=(const SIZE &lhs, const SIZE &rhs) noexcept
269{
270 return !operator==(lhs, rhs);
271}
272
273static inline constexpr bool operator>(const SIZE &lhs, const SIZE &rhs) noexcept
274{
275 return ((lhs.cx * lhs.cy) > (rhs.cx * rhs.cy));
276}
277
278static inline constexpr bool operator>=(const SIZE &lhs, const SIZE &rhs) noexcept
279{
280 return (operator>(lhs, rhs) || operator==(lhs, rhs));
281}
282
283static inline constexpr bool operator<(const SIZE &lhs, const SIZE &rhs) noexcept
284{
285 return (operator!=(lhs, rhs) && !operator>(lhs, rhs));
286}
287
288static inline constexpr bool operator<=(const SIZE &lhs, const SIZE &rhs) noexcept
289{
290 return (operator<(lhs, rhs) || operator==(lhs, rhs));
291}
292
293static inline constexpr bool operator==(const RECT &lhs, const RECT &rhs) noexcept
294{
295 return ((lhs.left == rhs.left) && (lhs.top == rhs.top) && (lhs.right == rhs.right) && (lhs.bottom == rhs.bottom));
296}
297
298static inline constexpr bool operator!=(const RECT &lhs, const RECT &rhs) noexcept
299{
300 return !operator==(lhs, rhs);
301}
302
303static inline constexpr QPoint point2qpoint(const POINT &point)
304{
305 return QPoint{int(point.x), int(point.y)};
306}
307
308static inline constexpr POINT qpoint2point(const QPoint &point)
309{
310 return POINT{LONG(point.x()), LONG(point.y())};
311}
312
313static inline constexpr QSize size2qsize(const SIZE &size)
314{
315 return QSize{int(size.cx), int(size.cy)};
316}
317
318static inline constexpr SIZE qsize2size(const QSize &size)
319{
320 return SIZE{LONG(size.width()), LONG(size.height())};
321}
322
323static inline constexpr QRect rect2qrect(const RECT &rect)
324{
325 return QRect{QPoint{int(rect.left), int(rect.top)}, QSize{int(RECT_WIDTH(rect)), int(RECT_HEIGHT(rect))}};
326}
327
328static inline constexpr RECT qrect2rect(const QRect &qrect)
329{
330 return RECT{LONG(qrect.left()), LONG(qrect.top()), LONG(qrect.right()), LONG(qrect.bottom())};
331}
332
333static inline constexpr QMargins margins2qmargins(const MARGINS &margins)
334{
335 return {margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight};
336}
337
338static inline constexpr MARGINS qmargins2margins(const QMargins &qmargins)
339{
340 return {qmargins.left(), qmargins.right(), qmargins.top(), qmargins.bottom()};
341}
342
343static inline /*constexpr*/ QString hwnd2str(const WId windowId)
344{
345 // NULL handle is allowed here.
346 return QLatin1String("0x") + QString::number(windowId, 16).toUpper().rightJustified(8, u'0');
347}
348
349static inline /*constexpr*/ QString hwnd2str(HWND hwnd)
350{
351 // NULL handle is allowed here.
352 return hwnd2str(reinterpret_cast<WId>(hwnd));
353}
354
355static inline bool isDwmCompositionEnabled()
356{
357 if (isWin8OrGreater()) {
358 return true;
359 }
360 const DynamicApis &apis = DynamicApis::instance();
361 if (!apis.pDwmIsCompositionEnabled) {
362 return false;
363 }
364 BOOL enabled = FALSE;
365 return SUCCEEDED(apis.pDwmIsCompositionEnabled(&enabled)) && enabled;
366}
367
368static inline bool isWindowFrameBorderColorized()
369{
370 WindowsRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
371 if (!registry.isValid()) {
372 return false;
373 }
374 QString value = registry.stringValue(L"ColorPrevalence");
375 if (value == "0") {
376 return false;
377 }
378 return true;
379}
380
381static inline bool isHighContrastModeEnabled()
382{
383 HIGHCONTRASTW hc{};
384 hc.cbSize = sizeof(hc);
385 ::SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, FALSE);
386 return (hc.dwFlags & HCF_HIGHCONTRASTON);
387}
388
389static inline bool isDarkThemeActive()
390{
391#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
392 return QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark;
393#else
394 WindowsRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
395 if (!registry.isValid()) {
396 return false;
397 }
398 auto value = registry.dwordValue(L"AppsUseLightTheme");
399 if (!value.second) {
400 return false;
401 }
402 return !value.first;
403#endif
404}
405
406static inline bool isDarkWindowFrameEnabled(HWND hwnd)
407{
408 BOOL enabled = FALSE;
409 const DynamicApis &apis = DynamicApis::instance();
410 if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE, &enabled, sizeof(enabled)))) {
411 return enabled;
412 } else if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &enabled,
413 sizeof(enabled)))) {
414 return enabled;
415 }
416 return false;
417}
418
419static inline QColor getAccentColor()
420{
421#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
422 return QGuiApplication::palette().color(QPalette::Accent);
423#else
424 WindowsRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
425 if (!registry.isValid()) {
426 return {};
427 }
428 auto value = registry.dwordValue(L"AccentColor");
429 if (!value.second) {
430 return {};
431 }
432 // The retrieved value is in the #AABBGGRR format, we need to
433 // convert it to the #AARRGGBB format which Qt expects.
434 QColor color = QColor::fromRgba(value.first);
435 if (!color.isValid()) {
436 return {};
437 }
438 return QColor::fromRgb(color.blue(), color.green(), color.red(), color.alpha());
439#endif
440}
441
442static inline quint32 getDpiForWindow(HWND hwnd)
443{
444#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
445 const DynamicApis &apis = DynamicApis::instance();
446 if (apis.pGetDpiForWindow) { // Win10
447 return apis.pGetDpiForWindow(hwnd);
448 } else if (apis.pGetDpiForMonitor) { // Win8.1
449 HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
450 UINT dpiX{0};
451 UINT dpiY{0};
452 apis.pGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
453 return dpiX;
454 } else { // Win2K
455#else
456 {
457 Q_UNUSED(hwnd)
458#endif
459 HDC hdc = ::GetDC(nullptr);
460 const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX);
461 // const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY);
462 ::ReleaseDC(nullptr, hdc);
463 return quint32(dpiX);
464 }
465}
466
467static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi)
468{
469#if defined(Q_CC_MSVC) || defined(Q_CC_MINGW_SUPPORT_DPI_API)
470 const DynamicApis &apis = DynamicApis::instance();
471 if (apis.pGetSystemMetricsForDpi) {
472 return ::GetSystemMetricsForDpi(index, dpi);
473 }
474#else
475 Q_UNUSED(dpi)
476#endif
477 return ::GetSystemMetrics(index);
478}
479
480static inline quint32 getWindowFrameBorderThickness(HWND hwnd)
481{
482 const DynamicApis &apis = DynamicApis::instance();
483 if (UINT result = 0;
484 SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &result, sizeof(result)))) {
485 return result;
486 }
487 return getSystemMetricsForDpi(SM_CXBORDER, getDpiForWindow(hwnd));
488}
489
490static inline quint32 getResizeBorderThickness(HWND hwnd)
491{
492 const quint32 dpi = getDpiForWindow(hwnd);
493 return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
494}
495
496static inline quint32 getTitleBarHeight(HWND hwnd)
497{
498 const quint32 dpi = getDpiForWindow(hwnd);
499 return getSystemMetricsForDpi(SM_CYCAPTION, dpi) + getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
500 getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
501}
502
504
505#endif // WINDOWKIT_WIN_P_H
QWinRegistryKey WindowsRegistryKey
bool enabled
Definition qxlogger.cpp:27
#define QX_WINDOW_END_NAMESPACE
#define QX_WINDOW_BEGIN_NAMESPACE
#define SM_CXPADDEDBORDER
#define RECT_HEIGHT(rect)
#define RECT_WIDTH(rect)
#define UNDOC_API_RESOLVE(DLL, NAME, ORDINAL)
#define DYNAMIC_API_RESOLVE(DLL, NAME)
#define DYNAMIC_API_DECLARE(NAME)