Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-04-17 21:39:36 +08:00
parent b789c050cc
commit 4e1d324100
5 changed files with 168 additions and 124 deletions

View File

@ -54,9 +54,12 @@ FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {
connect(this, &FramelessHelper::framelessWindowsChanged, connect(this, &FramelessHelper::framelessWindowsChanged,
[this]() { updateQtFrame_internal(m_titlebarHeight); }); [this]() { updateQtFrame_internal(m_titlebarHeight); });
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
m_borderWidth = WinNativeEventFilter::borderWidth(nullptr); m_borderWidth = WinNativeEventFilter::getSystemMetric(
m_borderHeight = WinNativeEventFilter::borderHeight(nullptr); nullptr, WinNativeEventFilter::SystemMetric::BorderWidth, false);
m_titlebarHeight = WinNativeEventFilter::titlebarHeight(nullptr); m_borderHeight = WinNativeEventFilter::getSystemMetric(
nullptr, WinNativeEventFilter::SystemMetric::BorderHeight, false);
m_titlebarHeight = WinNativeEventFilter::getSystemMetric(
nullptr, WinNativeEventFilter::SystemMetric::TitleBarHeight, false);
#else #else
// TODO: The default border width and height on Windows is 8 pixels if DPI // TODO: The default border width and height on Windows is 8 pixels if DPI
// is 96. Don't know how to acquire these values on UNIX platforms. // is 96. Don't know how to acquire these values on UNIX platforms.

View File

@ -18,14 +18,11 @@ int main(int argc, char *argv[]) {
#endif #endif
#endif #endif
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QApplication application(argc, argv); QApplication application(argc, argv);
FramelessHelper helper; FramelessHelper helper;
QWidget widget; QWidget widget;
widget.setAttribute(Qt::WA_DontCreateNativeAncestors);
helper.setFramelessWindows({&widget}); helper.setFramelessWindows({&widget});
widget.show(); widget.show();

View File

@ -26,8 +26,8 @@
</compatibility> </compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings> <windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings> </windowsSettings>
</application> </application>

View File

@ -25,11 +25,7 @@
#include "winnativeeventfilter.h" #include "winnativeeventfilter.h"
#include <QDebug> #include <QDebug>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
#include <QGuiApplication> #include <QGuiApplication>
#else
#include <QCoreApplication>
#endif
#include <QLibrary> #include <QLibrary>
#include <QOperatingSystemVersion> #include <QOperatingSystemVersion>
#include <cmath> #include <cmath>
@ -105,12 +101,12 @@
#endif #endif
#ifndef WM_DPICHANGED #ifndef WM_DPICHANGED
// Only available since Windows 7 // Only available since Windows 8.1
#define WM_DPICHANGED 0x02E0 #define WM_DPICHANGED 0x02E0
#endif #endif
#ifndef ABM_GETAUTOHIDEBAREX #ifndef ABM_GETAUTOHIDEBAREX
// Only available since Windows 8 // Only available since Windows 8.1
#define ABM_GETAUTOHIDEBAREX 0x0000000b #define ABM_GETAUTOHIDEBAREX 0x0000000b
#endif #endif
@ -174,6 +170,12 @@ using APPBARDATA = struct _APPBARDATA {
LPARAM lParam; LPARAM lParam;
}; };
using PROCESS_DPI_AWARENESS = enum _PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
};
WNEF_GENERATE_WINAPI(GetSystemDpiForProcess, UINT, HANDLE) WNEF_GENERATE_WINAPI(GetSystemDpiForProcess, UINT, HANDLE)
WNEF_GENERATE_WINAPI(GetDpiForWindow, UINT, HWND) WNEF_GENERATE_WINAPI(GetDpiForWindow, UINT, HWND)
WNEF_GENERATE_WINAPI(GetDpiForSystem, UINT) WNEF_GENERATE_WINAPI(GetDpiForSystem, UINT)
@ -232,6 +234,10 @@ WNEF_GENERATE_WINAPI(DeleteObject, BOOL, HGDIOBJ)
WNEF_GENERATE_WINAPI(IsThemeActive, BOOL) WNEF_GENERATE_WINAPI(IsThemeActive, BOOL)
WNEF_GENERATE_WINAPI(BeginPaint, HDC, HWND, LPPAINTSTRUCT) WNEF_GENERATE_WINAPI(BeginPaint, HDC, HWND, LPPAINTSTRUCT)
WNEF_GENERATE_WINAPI(EndPaint, BOOL, HWND, CONST LPPAINTSTRUCT) WNEF_GENERATE_WINAPI(EndPaint, BOOL, HWND, CONST LPPAINTSTRUCT)
WNEF_GENERATE_WINAPI(GetCurrentProcess, HANDLE)
WNEF_GENERATE_WINAPI(GetProcessDpiAwareness, HRESULT, HANDLE,
PROCESS_DPI_AWARENESS *)
WNEF_GENERATE_WINAPI(IsProcessDPIAware, BOOL)
BOOL IsDwmCompositionEnabled() { BOOL IsDwmCompositionEnabled() {
// Since Win8, DWM composition is always enabled and can't be disabled. // Since Win8, DWM composition is always enabled and can't be disabled.
@ -347,18 +353,6 @@ void WinNativeEventFilter::clearFramelessWindows() {
} }
} }
int WinNativeEventFilter::borderWidth(HWND handle) {
return getBorderWidthForWindow(handle, false);
}
int WinNativeEventFilter::borderHeight(HWND handle) {
return getBorderHeightForWindow(handle, false);
}
int WinNativeEventFilter::titlebarHeight(HWND handle) {
return getTitlebarHeightForWindow(handle, false);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
void *message, qintptr *result) void *message, qintptr *result)
@ -391,12 +385,15 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
if (!data->initialized) { if (!data->initialized) {
// Avoid initializing a same window twice. // Avoid initializing a same window twice.
data->initialized = TRUE; data->initialized = TRUE;
// Restore default window style.
m_lpSetWindowLongPtrW(msg->hwnd, GWL_STYLE,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS);
// The following two lines can help us get rid of the three system // The following two lines can help us get rid of the three system
// buttons (minimize, maximize and close). But they also break the // buttons (minimize, maximize and close). But they also break the
// Arcylic effect (introduced in Win10 1709), don't know why. // Arcylic effect (introduced in Win10 1709), don't know why.
m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE, m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE,
m_lpGetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE) | WS_EX_APPWINDOW | WS_EX_LAYERED);
WS_EX_LAYERED);
m_lpSetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0, m_lpSetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0,
LWA_COLORKEY); LWA_COLORKEY);
// Make sure our window have it's frame shadow. // Make sure our window have it's frame shadow.
@ -412,10 +409,13 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
<< getDotsPerInchForWindow(msg->hwnd) << getDotsPerInchForWindow(msg->hwnd)
<< "Window DPR:" << "Window DPR:"
<< getDevicePixelRatioForWindow(msg->hwnd); << getDevicePixelRatioForWindow(msg->hwnd);
qDebug().noquote() << "Window border width:" << borderWidth(msg->hwnd) qDebug().noquote()
<< "Window border height:" << borderHeight(msg->hwnd) << "Window border width:"
<< "Window titlebar height:" << getSystemMetric(msg->hwnd, SystemMetric::BorderWidth, false)
<< titlebarHeight(msg->hwnd); << "Window border height:"
<< getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, false)
<< "Window titlebar height:"
<< getSystemMetric(msg->hwnd, SystemMetric::TitleBarHeight, false);
#endif #endif
} }
switch (msg->message) { switch (msg->message) {
@ -434,8 +434,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
if (IsMaximized(_hWnd) || IsFullScreened(_hWnd)) { if (IsMaximized(_hWnd) || IsFullScreened(_hWnd)) {
// Windows automatically adds a standard width border to all // Windows automatically adds a standard width border to all
// sides when a window is maximized. // sides when a window is maximized.
int frameThickness_x = getBorderWidthForWindow(_hWnd); int frameThickness_x =
int frameThickness_y = getBorderHeightForWindow(_hWnd); getSystemMetric(_hWnd, SystemMetric::BorderWidth);
int frameThickness_y =
getSystemMetric(_hWnd, SystemMetric::BorderHeight);
// The following two lines are two seperate functions in // The following two lines are two seperate functions in
// Chromium, it uses them to judge whether the window // Chromium, it uses them to judge whether the window
// should draw it's own frame or not. But here we will always // should draw it's own frame or not. But here we will always
@ -478,30 +480,56 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
abd.cbSize = sizeof(abd); abd.cbSize = sizeof(abd);
const UINT taskbarState = m_lpSHAppBarMessage(ABM_GETSTATE, &abd); const UINT taskbarState = m_lpSHAppBarMessage(ABM_GETSTATE, &abd);
if (taskbarState & ABS_AUTOHIDE) { if (taskbarState & ABS_AUTOHIDE) {
const HMONITOR hMonitor = const HMONITOR windowMonitor =
m_lpMonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST); m_lpMonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo; bool top = false, bottom = false, left = false, right = false;
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo)); if (QOperatingSystemVersion::current() >=
monitorInfo.cbSize = sizeof(monitorInfo); QOperatingSystemVersion::Windows8_1) {
m_lpGetMonitorInfoW(hMonitor, &monitorInfo); MONITORINFO monitorInfo;
const auto hasAutohideTaskbar = SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
[&monitorInfo](const UINT edge) -> bool { monitorInfo.cbSize = sizeof(monitorInfo);
m_lpGetMonitorInfoW(windowMonitor, &monitorInfo);
const auto hasAutohideTaskbar =
[&monitorInfo](const UINT edge) -> bool {
APPBARDATA _abd;
SecureZeroMemory(&_abd, sizeof(_abd));
_abd.cbSize = sizeof(_abd);
_abd.uEdge = edge;
_abd.rc = monitorInfo.rcMonitor;
const auto hTaskbar = reinterpret_cast<HWND>(
m_lpSHAppBarMessage(ABM_GETAUTOHIDEBAREX, &_abd));
return hTaskbar != nullptr;
};
top = hasAutohideTaskbar(ABE_TOP);
bottom = hasAutohideTaskbar(ABE_BOTTOM);
left = hasAutohideTaskbar(ABE_LEFT);
right = hasAutohideTaskbar(ABE_RIGHT);
} else {
int edge = -1;
APPBARDATA _abd; APPBARDATA _abd;
SecureZeroMemory(&_abd, sizeof(_abd)); SecureZeroMemory(&_abd, sizeof(_abd));
_abd.cbSize = sizeof(_abd); _abd.cbSize = sizeof(_abd);
_abd.uEdge = edge; _abd.hWnd = m_lpFindWindowW(L"Shell_TrayWnd", nullptr);
_abd.rc = monitorInfo.rcMonitor; if (_abd.hWnd) {
const auto hTaskbar = reinterpret_cast<HWND>( const HMONITOR taskbarMonitor = m_lpMonitorFromWindow(
m_lpSHAppBarMessage(ABM_GETAUTOHIDEBAREX, &_abd)); _abd.hWnd, MONITOR_DEFAULTTOPRIMARY);
return hTaskbar != nullptr; if (taskbarMonitor == windowMonitor) {
}; m_lpSHAppBarMessage(ABM_GETTASKBARPOS, &_abd);
if (hasAutohideTaskbar(ABE_TOP)) { edge = _abd.uEdge;
}
}
top = edge == ABE_TOP;
bottom = edge == ABE_BOTTOM;
left = edge == ABE_LEFT;
right = edge == ABE_RIGHT;
}
if (top) {
clientRect->top += kAutoHideTaskbarThicknessPy; clientRect->top += kAutoHideTaskbarThicknessPy;
} else if (hasAutohideTaskbar(ABE_BOTTOM)) { } else if (bottom) {
clientRect->bottom -= kAutoHideTaskbarThicknessPy; clientRect->bottom -= kAutoHideTaskbarThicknessPy;
} else if (hasAutohideTaskbar(ABE_LEFT)) { } else if (left) {
clientRect->left += kAutoHideTaskbarThicknessPx; clientRect->left += kAutoHideTaskbarThicknessPx;
} else if (hasAutohideTaskbar(ABE_RIGHT)) { } else if (right) {
clientRect->right -= kAutoHideTaskbarThicknessPx; clientRect->right -= kAutoHideTaskbarThicknessPx;
} }
} }
@ -578,9 +606,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
mouse.y = GET_Y_LPARAM(_lParam); mouse.y = GET_Y_LPARAM(_lParam);
m_lpScreenToClient(_hWnd, &mouse); m_lpScreenToClient(_hWnd, &mouse);
// These values are DPI-aware. // These values are DPI-aware.
const LONG bw = getBorderWidthForWindow(_hWnd); const LONG bw = getSystemMetric(_hWnd, SystemMetric::BorderWidth);
const LONG bh = getBorderHeightForWindow(_hWnd); const LONG bh = getSystemMetric(_hWnd, SystemMetric::BorderHeight);
const LONG tbh = getTitlebarHeightForWindow(_hWnd); const LONG tbh =
getSystemMetric(_hWnd, SystemMetric::TitleBarHeight);
const qreal dpr = getDevicePixelRatioForWindow(_hWnd); const qreal dpr = getDevicePixelRatioForWindow(_hWnd);
const bool isTitlebar = (mouse.y < tbh) && const bool isTitlebar = (mouse.y < tbh) &&
!isInSpecificAreas(mouse.x, mouse.y, !isInSpecificAreas(mouse.x, mouse.y,
@ -765,14 +794,25 @@ UINT WinNativeEventFilter::getDotsPerInchForWindow(HWND handle) {
} }
return defaultValue; return defaultValue;
}; };
bool dpiEnabled = false;
if (m_lpGetProcessDpiAwareness) {
PROCESS_DPI_AWARENESS awareness = PROCESS_DPI_UNAWARE;
m_lpGetProcessDpiAwareness(m_lpGetCurrentProcess(), &awareness);
dpiEnabled = awareness != PROCESS_DPI_UNAWARE;
} else if (m_lpIsProcessDPIAware) {
dpiEnabled = m_lpIsProcessDPIAware();
}
if (!dpiEnabled) {
// Return hard-coded DPI if DPI scaling is disabled.
return m_defaultDotsPerInch;
}
if (!handle) { if (!handle) {
if (m_lpGetSystemDpiForProcess) { if (m_lpGetSystemDpiForProcess) {
return m_lpGetSystemDpiForProcess(GetCurrentProcess()); return m_lpGetSystemDpiForProcess(m_lpGetCurrentProcess());
} else if (m_lpGetDpiForSystem) { } else if (m_lpGetDpiForSystem) {
return m_lpGetDpiForSystem(); return m_lpGetDpiForSystem();
} else {
return getScreenDpi(m_defaultDotsPerInch);
} }
return getScreenDpi(m_defaultDotsPerInch);
} }
if (m_lpGetDpiForWindow) { if (m_lpGetDpiForWindow) {
return m_lpGetDpiForWindow(handle); return m_lpGetDpiForWindow(handle);
@ -896,16 +936,20 @@ void WinNativeEventFilter::initWin32Api() {
WNEF_RESOLVE_WINAPI(Gdi32, DeleteObject) WNEF_RESOLVE_WINAPI(Gdi32, DeleteObject)
// Available since Windows XP. // Available since Windows XP.
WNEF_RESOLVE_WINAPI(Shell32, SHAppBarMessage) WNEF_RESOLVE_WINAPI(Shell32, SHAppBarMessage)
WNEF_RESOLVE_WINAPI(Kernel32, GetCurrentProcess)
// Available since Windows Vista. // Available since Windows Vista.
WNEF_RESOLVE_WINAPI(User32, IsProcessDPIAware)
WNEF_RESOLVE_WINAPI(Dwmapi, DwmIsCompositionEnabled) WNEF_RESOLVE_WINAPI(Dwmapi, DwmIsCompositionEnabled)
WNEF_RESOLVE_WINAPI(Dwmapi, DwmExtendFrameIntoClientArea) WNEF_RESOLVE_WINAPI(Dwmapi, DwmExtendFrameIntoClientArea)
WNEF_RESOLVE_WINAPI(Dwmapi, DwmSetWindowAttribute) WNEF_RESOLVE_WINAPI(Dwmapi, DwmSetWindowAttribute)
WNEF_RESOLVE_WINAPI(UxTheme, IsThemeActive) WNEF_RESOLVE_WINAPI(UxTheme, IsThemeActive)
// Available since Windows 8.1
if (QOperatingSystemVersion::current() >= if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion::Windows8_1) { QOperatingSystemVersion::Windows8_1) {
WNEF_RESOLVE_WINAPI(SHCore, GetDpiForMonitor) WNEF_RESOLVE_WINAPI(SHCore, GetDpiForMonitor)
WNEF_RESOLVE_WINAPI(SHCore, GetProcessDpiAwareness)
} }
// Windows 10, version 1607 (10.0.14393) // Available since Windows 10, version 1607 (10.0.14393)
if (QOperatingSystemVersion::current() >= if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0,
14393)) { 14393)) {
@ -913,7 +957,7 @@ void WinNativeEventFilter::initWin32Api() {
WNEF_RESOLVE_WINAPI(User32, GetDpiForSystem) WNEF_RESOLVE_WINAPI(User32, GetDpiForSystem)
WNEF_RESOLVE_WINAPI(User32, GetSystemMetricsForDpi) WNEF_RESOLVE_WINAPI(User32, GetSystemMetricsForDpi)
} }
// Windows 10, version 1803 (10.0.17134) // Available since Windows 10, version 1803 (10.0.17134)
if (QOperatingSystemVersion::current() >= if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0,
17134)) { 17134)) {
@ -1005,7 +1049,8 @@ void WinNativeEventFilter::updateWindow(HWND handle, bool triggerFrameChange) {
} }
} }
int WinNativeEventFilter::getBorderWidthForWindow(HWND handle, bool dpiAware) { int WinNativeEventFilter::getSystemMetric(HWND handle, SystemMetric metric,
bool dpiAware) {
initWin32Api(); initWin32Api();
const qreal dpr = dpiAware ? getDevicePixelRatioForWindow(handle) const qreal dpr = dpiAware ? getDevicePixelRatioForWindow(handle)
: m_defaultDevicePixelRatio; : m_defaultDevicePixelRatio;
@ -1013,64 +1058,69 @@ int WinNativeEventFilter::getBorderWidthForWindow(HWND handle, bool dpiAware) {
createUserData(handle); createUserData(handle);
const auto userData = reinterpret_cast<WINDOW *>( const auto userData = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(handle, GWLP_USERDATA)); m_lpGetWindowLongPtrW(handle, GWLP_USERDATA));
const int bw = userData->windowData.borderWidth; switch (metric) {
if (bw > 0) { case SystemMetric::BorderWidth: {
return std::round(bw * dpr); const int bw = userData->windowData.borderWidth;
if (bw > 0) {
return std::round(bw * dpr);
}
break;
}
case SystemMetric::BorderHeight: {
const int bh = userData->windowData.borderHeight;
if (bh > 0) {
return std::round(bh * dpr);
}
break;
}
case SystemMetric::TitleBarHeight: {
const int tbh = userData->windowData.titlebarHeight;
if (tbh > 0) {
return std::round(tbh * dpr);
}
break;
}
} }
} }
if (m_borderWidth > 0) { switch (metric) {
return std::round(m_borderWidth * dpr); case SystemMetric::BorderWidth: {
} if (m_borderWidth > 0) {
const int result = m_lpGetSystemMetrics(SM_CXSIZEFRAME) + return std::round(m_borderWidth * dpr);
m_lpGetSystemMetrics(SM_CXPADDEDBORDER); } else {
const int result_dpi = getSystemMetricsForWindow(handle, SM_CXSIZEFRAME) + const int result = m_lpGetSystemMetrics(SM_CXSIZEFRAME) +
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER); m_lpGetSystemMetrics(SM_CXPADDEDBORDER);
return dpiAware ? result_dpi : result; const int result_dpi =
} getSystemMetricsForWindow(handle, SM_CXSIZEFRAME) +
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
int WinNativeEventFilter::getBorderHeightForWindow(HWND handle, bool dpiAware) { return dpiAware ? result_dpi : result;
initWin32Api();
const qreal dpr = dpiAware ? getDevicePixelRatioForWindow(handle)
: m_defaultDevicePixelRatio;
if (handle && m_lpIsWindow(handle)) {
createUserData(handle);
const auto userData = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(handle, GWLP_USERDATA));
const int bh = userData->windowData.borderHeight;
if (bh > 0) {
return std::round(bh * dpr);
} }
} }
if (m_borderHeight > 0) { case SystemMetric::BorderHeight: {
return std::round(m_borderHeight * dpr); if (m_borderHeight > 0) {
} return std::round(m_borderHeight * dpr);
const int result = m_lpGetSystemMetrics(SM_CYSIZEFRAME) + } else {
m_lpGetSystemMetrics(SM_CXPADDEDBORDER); const int result = m_lpGetSystemMetrics(SM_CYSIZEFRAME) +
const int result_dpi = getSystemMetricsForWindow(handle, SM_CYSIZEFRAME) + m_lpGetSystemMetrics(SM_CXPADDEDBORDER);
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER); const int result_dpi =
return dpiAware ? result_dpi : result; getSystemMetricsForWindow(handle, SM_CYSIZEFRAME) +
} getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
return dpiAware ? result_dpi : result;
int WinNativeEventFilter::getTitlebarHeightForWindow(HWND handle,
bool dpiAware) {
initWin32Api();
const qreal dpr = dpiAware ? getDevicePixelRatioForWindow(handle)
: m_defaultDevicePixelRatio;
if (handle && m_lpIsWindow(handle)) {
createUserData(handle);
const auto userData = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(handle, GWLP_USERDATA));
const int tbh = userData->windowData.titlebarHeight;
if (tbh > 0) {
return std::round(tbh * dpr);
} }
} }
if (m_titlebarHeight > 0) { case SystemMetric::TitleBarHeight: {
return std::round(m_titlebarHeight * dpr); if (m_titlebarHeight > 0) {
return std::round(m_titlebarHeight * dpr);
} else {
const int result = m_lpGetSystemMetrics(SM_CYSIZEFRAME) +
m_lpGetSystemMetrics(SM_CXPADDEDBORDER) +
m_lpGetSystemMetrics(SM_CYCAPTION);
const int result_dpi =
getSystemMetricsForWindow(handle, SM_CYSIZEFRAME) +
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER) +
getSystemMetricsForWindow(handle, SM_CYCAPTION);
return dpiAware ? result_dpi : result;
}
} }
const int result = getBorderHeightForWindow(handle, false) + }
m_lpGetSystemMetrics(SM_CYCAPTION); return -1;
const int result_dpi = getBorderHeightForWindow(handle) +
getSystemMetricsForWindow(handle, SM_CYCAPTION);
return dpiAware ? result_dpi : result;
} }

View File

@ -50,6 +50,8 @@ public:
WINDOWDATA windowData; WINDOWDATA windowData;
}; };
enum class SystemMetric { BorderWidth, BorderHeight, TitleBarHeight };
explicit WinNativeEventFilter(); explicit WinNativeEventFilter();
~WinNativeEventFilter() override; ~WinNativeEventFilter() override;
@ -84,15 +86,10 @@ public:
static void setBorderHeight(int bh); static void setBorderHeight(int bh);
static void setTitlebarHeight(int tbh); static void setTitlebarHeight(int tbh);
// DPI-unaware border width of the given window (if the pointer is null, // System metric value of the given window (if the pointer is null,
// return the system's standard value). // return the system's standard value).
static int borderWidth(HWND handle); static int getSystemMetric(HWND handle, SystemMetric metric,
// DPI-unaware border height of the given window (if the pointer is null, bool dpiAware = true);
// return the system's standard value).
static int borderHeight(HWND handle);
// DPI-unaware titlebar height (including the border height) of the given
// window (if the pointer is null, return the system's standard value).
static int titlebarHeight(HWND handle);
static void updateWindow(HWND handle, bool triggerFrameChange = true); static void updateWindow(HWND handle, bool triggerFrameChange = true);
@ -112,7 +109,4 @@ private:
static UINT getDotsPerInchForWindow(HWND handle); static UINT getDotsPerInchForWindow(HWND handle);
static qreal getDevicePixelRatioForWindow(HWND handle); static qreal getDevicePixelRatioForWindow(HWND handle);
static int getSystemMetricsForWindow(HWND handle, int index); static int getSystemMetricsForWindow(HWND handle, int index);
static int getBorderWidthForWindow(HWND handle, bool dpiAware = true);
static int getBorderHeightForWindow(HWND handle, bool dpiAware = true);
static int getTitlebarHeightForWindow(HWND handle, bool dpiAware = true);
}; };