Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-07-06 16:25:44 +08:00
parent 3c227fa383
commit 7073c4a259
2 changed files with 218 additions and 142 deletions

View File

@ -12,7 +12,7 @@ CONFIG += c++17 strict_c++ utf8_source warn_on windeployqt
DEFINES += WIN32_LEAN_AND_MEAN QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII DEFINES += WIN32_LEAN_AND_MEAN QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
flh_link_syslib { flh_link_syslib {
DEFINES += WNEF_LINK_SYSLIB DEFINES += WNEF_LINK_SYSLIB
LIBS += -luser32 -lgdi32 -ldwmapi LIBS += -luser32 -lgdi32 -ldwmapi -lshcore
} }
CONFIG -= embed_manifest_exe CONFIG -= embed_manifest_exe
RC_FILE = resources.rc RC_FILE = resources.rc

View File

@ -160,38 +160,27 @@ bool isWin10OrGreator(const int ver)
} }
#endif #endif
#ifndef WNEF_EXECUTE_WINAPI
#ifdef WNEF_LINK_SYSLIB #ifdef WNEF_LINK_SYSLIB
#define WNEF_EXECUTE_WINAPI(funcName, ...) funcName(__VA_ARGS__);
#define m_lpDwmIsCompositionEnabled DwmIsCompositionEnabled
#define m_lpIsWindow IsWindow
#define m_lpGetWindowInfo GetWindowInfo
#define m_lpMonitorFromWindow MonitorFromWindow
#define m_lpGetMonitorInfoW GetMonitorInfoW
#define m_lpEqualRect EqualRect
#define m_lpGetWindowLongPtrW GetWindowLongPtrW
#define m_lpGetAncestor GetAncestor
#define m_lpGetDesktopWindow GetDesktopWindow
#define m_lpGetDC GetDC
#define m_lpGetDeviceCaps GetDeviceCaps
#define m_lpReleaseDC ReleaseDC
#define m_lpDwmSetWindowAttribute DwmSetWindowAttribute
#define m_lpDwmExtendFrameIntoClientArea DwmExtendFrameIntoClientArea
#define m_lpAdjustWindowRectEx AdjustWindowRectEx
#define m_lpGetSystemMetrics GetSystemMetrics
#define m_lpSetWindowLongPtrW SetWindowLongPtrW
#define m_lpDefWindowProcW DefWindowProcW
#define m_lpSetLayeredWindowAttributes SetLayeredWindowAttributes
#define m_lpSHAppBarMessage SHAppBarMessage
#define m_lpFindWindowW FindWindowW
#define m_lpGetClientRect GetClientRect
#define m_lpScreenToClient ScreenToClient
#define m_lpSetWindowPos SetWindowPos
#define m_lpRedrawWindow RedrawWindow
#define m_lpMoveWindow MoveWindow
#define m_lpGetCurrentProcess GetCurrentProcess
#define m_lpIsProcessDPIAware IsProcessDPIAware
#else #else
#define WNEF_EXECUTE_WINAPI(funcName, ...) \
if (m_lp##funcName) { \
m_lp##funcName(__VA_ARGS__); \
}
#endif
#endif
#ifndef WNEF_EXECUTE_WINAPI_RETURN
#ifdef WNEF_LINK_SYSLIB
#define WNEF_EXECUTE_WINAPI_RETURN(funcName, defVal, ...) funcName(__VA_ARGS__)
#else
#define WNEF_EXECUTE_WINAPI_RETURN(funcName, defVal, ...) \
(m_lp##funcName ? m_lp##funcName(__VA_ARGS__) : defVal)
#endif
#endif
#ifndef WNEF_LINK_SYSLIB
// All the following enums, structs and function prototypes are copied from // All the following enums, structs and function prototypes are copied from
// Windows 10 SDK directly, without any modifications. // Windows 10 SDK directly, without any modifications.
@ -205,10 +194,10 @@ bool isWin10OrGreator(const int ver)
#endif #endif
// Only available since Windows 2000 // Only available since Windows 2000
#define IsMinimized m_lpIsIconic #define IsMinimized(h) WNEF_EXECUTE_WINAPI_RETURN(IsIconic, FALSE, h)
// Only available since Windows 2000 // Only available since Windows 2000
#define IsMaximized m_lpIsZoomed #define IsMaximized(h) WNEF_EXECUTE_WINAPI_RETURN(IsZoomed, FALSE, h)
#ifndef GET_X_LPARAM #ifndef GET_X_LPARAM
// Only available since Windows 2000 // Only available since Windows 2000
@ -222,7 +211,8 @@ bool isWin10OrGreator(const int ver)
#ifndef GetStockBrush #ifndef GetStockBrush
// Only available since Windows 2000 // Only available since Windows 2000
#define GetStockBrush(i) ((HBRUSH) m_lpGetStockObject(i)) #define GetStockBrush(i) \
(reinterpret_cast<HBRUSH>(WNEF_EXECUTE_WINAPI_RETURN(GetStockObject, 0, i)))
#endif #endif
#ifndef ABM_GETSTATE #ifndef ABM_GETSTATE
@ -569,7 +559,8 @@ BOOL IsDwmCompositionEnabled()
// In other words, DwmIsCompositionEnabled will always return TRUE on // In other words, DwmIsCompositionEnabled will always return TRUE on
// systems newer than Win7. // systems newer than Win7.
BOOL enabled = FALSE; BOOL enabled = FALSE;
return SUCCEEDED(m_lpDwmIsCompositionEnabled(&enabled)) && enabled; return SUCCEEDED(WNEF_EXECUTE_WINAPI_RETURN(DwmIsCompositionEnabled, E_FAIL, &enabled))
&& enabled;
} }
WINDOWINFO GetInfoForWindow(const HWND handle) WINDOWINFO GetInfoForWindow(const HWND handle)
@ -577,8 +568,8 @@ WINDOWINFO GetInfoForWindow(const HWND handle)
WINDOWINFO windowInfo; WINDOWINFO windowInfo;
SecureZeroMemory(&windowInfo, sizeof(windowInfo)); SecureZeroMemory(&windowInfo, sizeof(windowInfo));
windowInfo.cbSize = sizeof(windowInfo); windowInfo.cbSize = sizeof(windowInfo);
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
m_lpGetWindowInfo(handle, &windowInfo); WNEF_EXECUTE_WINAPI(GetWindowInfo, handle, &windowInfo)
} }
return windowInfo; return windowInfo;
} }
@ -588,10 +579,13 @@ MONITORINFO GetMonitorInfoForWindow(const HWND handle)
MONITORINFO monitorInfo; MONITORINFO monitorInfo;
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo)); SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo); monitorInfo.cbSize = sizeof(monitorInfo);
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const HMONITOR monitor = m_lpMonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST); const HMONITOR monitor = WNEF_EXECUTE_WINAPI_RETURN(MonitorFromWindow,
nullptr,
handle,
MONITOR_DEFAULTTONEAREST);
if (monitor) { if (monitor) {
m_lpGetMonitorInfoW(monitor, &monitorInfo); WNEF_EXECUTE_WINAPI(GetMonitorInfoW, monitor, &monitorInfo)
} }
} }
return monitorInfo; return monitorInfo;
@ -599,26 +593,32 @@ MONITORINFO GetMonitorInfoForWindow(const HWND handle)
BOOL IsFullScreen(const HWND handle) BOOL IsFullScreen(const HWND handle)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const WINDOWINFO windowInfo = GetInfoForWindow(handle); const WINDOWINFO windowInfo = GetInfoForWindow(handle);
const MONITORINFO monitorInfo = GetMonitorInfoForWindow(handle); const MONITORINFO monitorInfo = GetMonitorInfoForWindow(handle);
// The only way to judge whether a window is fullscreen or not // The only way to judge whether a window is fullscreen or not
// is to compare it's size with the screen's size, there is no official // is to compare it's size with the screen's size, there is no official
// Win32 API to do this for us. // Win32 API to do this for us.
return m_lpEqualRect(&windowInfo.rcWindow, &monitorInfo.rcMonitor) return WNEF_EXECUTE_WINAPI_RETURN(EqualRect,
|| m_lpEqualRect(&windowInfo.rcClient, &monitorInfo.rcMonitor); FALSE,
&windowInfo.rcWindow,
&monitorInfo.rcMonitor)
|| WNEF_EXECUTE_WINAPI_RETURN(EqualRect,
FALSE,
&windowInfo.rcClient,
&monitorInfo.rcMonitor);
} }
return FALSE; return FALSE;
} }
BOOL IsTopLevel(const HWND handle) BOOL IsTopLevel(const HWND handle)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
if (m_lpGetWindowLongPtrW(handle, GWL_STYLE) & WS_CHILD) { if (WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWL_STYLE) & WS_CHILD) {
return FALSE; return FALSE;
} }
const HWND parent = m_lpGetAncestor(handle, GA_PARENT); const HWND parent = WNEF_EXECUTE_WINAPI_RETURN(GetAncestor, nullptr, handle, GA_PARENT);
if (parent && (parent != m_lpGetDesktopWindow())) { if (parent && (parent != WNEF_EXECUTE_WINAPI_RETURN(GetDesktopWindow, nullptr))) {
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@ -647,11 +647,11 @@ UINT GetDotsPerInchForWindow(const HWND handle)
} }
#endif #endif
// Available since Windows 2000. // Available since Windows 2000.
const HDC hdc = m_lpGetDC(nullptr); const HDC hdc = WNEF_EXECUTE_WINAPI_RETURN(GetDC, nullptr, nullptr);
if (hdc) { if (hdc) {
const int dpiX = m_lpGetDeviceCaps(hdc, LOGPIXELSX); const int dpiX = WNEF_EXECUTE_WINAPI_RETURN(GetDeviceCaps, 0, hdc, LOGPIXELSX);
const int dpiY = m_lpGetDeviceCaps(hdc, LOGPIXELSY); const int dpiY = WNEF_EXECUTE_WINAPI_RETURN(GetDeviceCaps, 0, hdc, LOGPIXELSY);
m_lpReleaseDC(nullptr, hdc); WNEF_EXECUTE_WINAPI(ReleaseDC, nullptr, hdc)
// The values of dpiX and dpiY are identical actually, just to // The values of dpiX and dpiY are identical actually, just to
// silence a compiler warning. // silence a compiler warning.
return dpiX == dpiY ? dpiY : dpiX; return dpiX == dpiY ? dpiY : dpiX;
@ -661,32 +661,41 @@ UINT GetDotsPerInchForWindow(const HWND handle)
bool dpiEnabled = false; bool dpiEnabled = false;
if (m_lpGetProcessDpiAwareness) { if (m_lpGetProcessDpiAwareness) {
PROCESS_DPI_AWARENESS awareness = PROCESS_DPI_UNAWARE; PROCESS_DPI_AWARENESS awareness = PROCESS_DPI_UNAWARE;
m_lpGetProcessDpiAwareness(m_lpGetCurrentProcess(), &awareness); WNEF_EXECUTE_WINAPI(GetProcessDpiAwareness,
WNEF_EXECUTE_WINAPI_RETURN(GetCurrentProcess, nullptr),
&awareness)
dpiEnabled = awareness != PROCESS_DPI_UNAWARE; dpiEnabled = awareness != PROCESS_DPI_UNAWARE;
} else { } else {
dpiEnabled = m_lpIsProcessDPIAware(); dpiEnabled = WNEF_EXECUTE_WINAPI_RETURN(IsProcessDPIAware, FALSE);
} }
if (!dpiEnabled) { if (!dpiEnabled) {
// Return hard-coded DPI if DPI scaling is disabled. // Return hard-coded DPI if DPI scaling is disabled.
return m_defaultDotsPerInch; return m_defaultDotsPerInch;
} }
if (!handle || !m_lpIsWindow(handle)) { if (!handle || !WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
if (m_lpGetSystemDpiForProcess) { if (m_lpGetSystemDpiForProcess) {
return m_lpGetSystemDpiForProcess(m_lpGetCurrentProcess()); return WNEF_EXECUTE_WINAPI_RETURN(GetSystemDpiForProcess,
0,
WNEF_EXECUTE_WINAPI_RETURN(GetCurrentProcess,
nullptr));
} else if (m_lpGetDpiForSystem) { } else if (m_lpGetDpiForSystem) {
return m_lpGetDpiForSystem(); return WNEF_EXECUTE_WINAPI_RETURN(GetDpiForSystem, 0);
} }
return getScreenDpi(m_defaultDotsPerInch); return getScreenDpi(m_defaultDotsPerInch);
} }
if (m_lpGetDpiForWindow) { if (m_lpGetDpiForWindow) {
return m_lpGetDpiForWindow(handle); return WNEF_EXECUTE_WINAPI_RETURN(GetDpiForWindow, 0, handle);
} }
if (m_lpGetDpiForMonitor) { if (m_lpGetDpiForMonitor) {
UINT dpiX = m_defaultDotsPerInch, dpiY = m_defaultDotsPerInch; UINT dpiX = m_defaultDotsPerInch, dpiY = m_defaultDotsPerInch;
m_lpGetDpiForMonitor(m_lpMonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST), WNEF_EXECUTE_WINAPI(GetDpiForMonitor,
MDT_EFFECTIVE_DPI, WNEF_EXECUTE_WINAPI_RETURN(MonitorFromWindow,
&dpiX, nullptr,
&dpiY); handle,
MONITOR_DEFAULTTONEAREST),
MDT_EFFECTIVE_DPI,
&dpiX,
&dpiY)
// The values of *dpiX and *dpiY are identical. // The values of *dpiX and *dpiY are identical.
return dpiX; return dpiX;
} }
@ -745,7 +754,7 @@ qreal GetPreferedNumber(const qreal num)
qreal GetDevicePixelRatioForWindow(const HWND handle) qreal GetDevicePixelRatioForWindow(const HWND handle)
{ {
qreal result = m_defaultDevicePixelRatio; qreal result = m_defaultDevicePixelRatio;
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
result = static_cast<qreal>(GetDotsPerInchForWindow(handle)) result = static_cast<qreal>(GetDotsPerInchForWindow(handle))
/ static_cast<qreal>(m_defaultDotsPerInch); / static_cast<qreal>(m_defaultDotsPerInch);
} }
@ -755,22 +764,23 @@ qreal GetDevicePixelRatioForWindow(const HWND handle)
RECT GetFrameSizeForWindow(const HWND handle, const bool includingTitleBar = false) RECT GetFrameSizeForWindow(const HWND handle, const bool includingTitleBar = false)
{ {
RECT rect = {0, 0, 0, 0}; RECT rect = {0, 0, 0, 0};
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const auto style = m_lpGetWindowLongPtrW(handle, GWL_STYLE); const auto style = WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWL_STYLE);
// It's the same with using GetSystemMetrics, the returned values // It's the same with using GetSystemMetrics, the returned values
// of the two functions are identical. // of the two functions are identical.
if (m_lpAdjustWindowRectExForDpi) { if (m_lpAdjustWindowRectExForDpi) {
m_lpAdjustWindowRectExForDpi(&rect, WNEF_EXECUTE_WINAPI(AdjustWindowRectExForDpi,
includingTitleBar ? (style | WS_CAPTION) &rect,
: (style & ~WS_CAPTION), includingTitleBar ? (style | WS_CAPTION) : (style & ~WS_CAPTION),
FALSE, FALSE,
m_lpGetWindowLongPtrW(handle, GWL_EXSTYLE), WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWL_EXSTYLE),
GetDotsPerInchForWindow(handle)); GetDotsPerInchForWindow(handle))
} else { } else {
m_lpAdjustWindowRectEx(&rect, WNEF_EXECUTE_WINAPI(AdjustWindowRectEx,
includingTitleBar ? (style | WS_CAPTION) : (style & ~WS_CAPTION), &rect,
FALSE, includingTitleBar ? (style | WS_CAPTION) : (style & ~WS_CAPTION),
m_lpGetWindowLongPtrW(handle, GWL_EXSTYLE)); FALSE,
WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWL_EXSTYLE))
const qreal dpr = GetDevicePixelRatioForWindow(handle); const qreal dpr = GetDevicePixelRatioForWindow(handle);
rect.top = qRound(rect.top * dpr); rect.top = qRound(rect.top * dpr);
rect.bottom = qRound(rect.bottom * dpr); rect.bottom = qRound(rect.bottom * dpr);
@ -788,13 +798,17 @@ RECT GetFrameSizeForWindow(const HWND handle, const bool includingTitleBar = fal
void UpdateFrameMarginsForWindow(const HWND handle) void UpdateFrameMarginsForWindow(const HWND handle)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
MARGINS margins = {0, 0, 0, 0}; MARGINS margins = {0, 0, 0, 0};
if (IsDwmCompositionEnabled()) { if (IsDwmCompositionEnabled()) {
// The frame shadow is drawn on the non-client area and thus we have // The frame shadow is drawn on the non-client area and thus we have
// to make sure the non-client area rendering is enabled first. // to make sure the non-client area rendering is enabled first.
const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED; const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
m_lpDwmSetWindowAttribute(handle, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp)); WNEF_EXECUTE_WINAPI(DwmSetWindowAttribute,
handle,
DWMWA_NCRENDERING_POLICY,
&ncrp,
sizeof(ncrp))
// Use negative values have the same effect, however, it will // Use negative values have the same effect, however, it will
// cause the window become transparent when it's maximizing or // cause the window become transparent when it's maximizing or
// restoring from maximized. Just like flashing. Fixing it by // restoring from maximized. Just like flashing. Fixing it by
@ -808,19 +822,22 @@ void UpdateFrameMarginsForWindow(const HWND handle)
// there, we just can't see it). // there, we just can't see it).
margins.cyTopHeight = 1; margins.cyTopHeight = 1;
} }
m_lpDwmExtendFrameIntoClientArea(handle, &margins); WNEF_EXECUTE_WINAPI(DwmExtendFrameIntoClientArea, handle, &margins)
} }
} }
int GetSystemMetricsForWindow(const HWND handle, const int index) int GetSystemMetricsForWindow(const HWND handle, const int index)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
if (m_lpGetSystemMetricsForDpi) { if (m_lpGetSystemMetricsForDpi) {
return m_lpGetSystemMetricsForDpi(index, return WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetricsForDpi,
0,
index,
static_cast<UINT>(qRound(GetPreferedNumber( static_cast<UINT>(qRound(GetPreferedNumber(
GetDotsPerInchForWindow(handle))))); GetDotsPerInchForWindow(handle)))));
} else { } else {
return qRound(m_lpGetSystemMetrics(index) * GetDevicePixelRatioForWindow(handle)); return qRound(WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics, 0, index)
* GetDevicePixelRatioForWindow(handle));
} }
} }
return -1; return -1;
@ -828,9 +845,9 @@ int GetSystemMetricsForWindow(const HWND handle, const int index)
void createUserData(const HWND handle, const WinNativeEventFilter::WINDOWDATA *data = nullptr) void createUserData(const HWND handle, const WinNativeEventFilter::WINDOWDATA *data = nullptr)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const auto userData = reinterpret_cast<WinNativeEventFilter::WINDOW *>( const auto userData = reinterpret_cast<WinNativeEventFilter::WINDOW *>(
m_lpGetWindowLongPtrW(handle, GWLP_USERDATA)); WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWLP_USERDATA));
if (userData) { if (userData) {
if (data) { if (data) {
userData->windowData = *data; userData->windowData = *data;
@ -842,7 +859,10 @@ void createUserData(const HWND handle, const WinNativeEventFilter::WINDOWDATA *d
if (data) { if (data) {
_data->windowData = *data; _data->windowData = *data;
} }
m_lpSetWindowLongPtrW(handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(_data)); WNEF_EXECUTE_WINAPI(SetWindowLongPtrW,
handle,
GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(_data))
WinNativeEventFilter::updateWindow(handle, true, false); WinNativeEventFilter::updateWindow(handle, true, false);
} }
} }
@ -850,7 +870,7 @@ void createUserData(const HWND handle, const WinNativeEventFilter::WINDOWDATA *d
QWindow *findQWindowFromRawHandle(const HWND handle) QWindow *findQWindowFromRawHandle(const HWND handle)
{ {
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const auto wid = reinterpret_cast<WId>(handle); const auto wid = reinterpret_cast<WId>(handle);
const auto windows = QGuiApplication::topLevelWindows(); const auto windows = QGuiApplication::topLevelWindows();
for (auto &&window : qAsConst(windows)) { for (auto &&window : qAsConst(windows)) {
@ -932,7 +952,8 @@ void WinNativeEventFilter::addFramelessWindow(const HWND window,
const int height) const int height)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (window && m_lpIsWindow(window) && !m_framelessWindows.contains(window)) { if (window && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, window)
&& !m_framelessWindows.contains(window)) {
m_framelessWindows.append(window); m_framelessWindows.append(window);
createUserData(window, data); createUserData(window, data);
install(); install();
@ -1002,7 +1023,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
return false; return false;
} }
const auto data = reinterpret_cast<WINDOW *>( const auto data = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(msg->hwnd, GWLP_USERDATA)); WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, msg->hwnd, GWLP_USERDATA));
if (!data) { if (!data) {
// Work-around a long existing Windows bug. // Work-around a long existing Windows bug.
// Overlapped windows will receive a WM_GETMINMAXINFO message before // Overlapped windows will receive a WM_GETMINMAXINFO message before
@ -1010,9 +1031,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// handling anyway. // handling anyway.
if (msg->message == WM_NCCREATE) { if (msg->message == WM_NCCREATE) {
const auto userData = reinterpret_cast<LPCREATESTRUCTW>(msg->lParam)->lpCreateParams; const auto userData = reinterpret_cast<LPCREATESTRUCTW>(msg->lParam)->lpCreateParams;
m_lpSetWindowLongPtrW(msg->hwnd, WNEF_EXECUTE_WINAPI(SetWindowLongPtrW,
GWLP_USERDATA, msg->hwnd,
reinterpret_cast<LONG_PTR>(userData)); GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(userData))
// Copied from MSDN without any modification: // Copied from MSDN without any modification:
// If you have changed certain window data using SetWindowLong, // If you have changed certain window data using SetWindowLong,
// you must call SetWindowPos for the changes to take effect. // you must call SetWindowPos for the changes to take effect.
@ -1020,7 +1042,12 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED. // SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED.
updateWindow(msg->hwnd, true, false); updateWindow(msg->hwnd, true, false);
} }
*result = m_lpDefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam); *result = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW,
0,
msg->hwnd,
msg->message,
msg->wParam,
msg->lParam);
return false; return false;
} }
if (!data->initialized) { if (!data->initialized) {
@ -1041,9 +1068,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// the window into a popup window, losing all the functions // the window into a popup window, losing all the functions
// a normal window should have. // a normal window should have.
// WS_CLIPCHILDREN | WS_CLIPSIBLINGS: work-around strange bugs. // WS_CLIPCHILDREN | WS_CLIPSIBLINGS: work-around strange bugs.
m_lpSetWindowLongPtrW(msg->hwnd, WNEF_EXECUTE_WINAPI(SetWindowLongPtrW,
GWL_STYLE, msg->hwnd,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); GWL_STYLE,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
updateWindow(msg->hwnd, true, false); updateWindow(msg->hwnd, true, false);
} }
if (data->windowData.enableLayeredWindow) { if (data->windowData.enableLayeredWindow) {
@ -1054,13 +1082,22 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// SetWindowCompositionAttribute to enable it for this window, // SetWindowCompositionAttribute to enable it for this window,
// the whole window will become totally black. Don't know why // the whole window will become totally black. Don't know why
// currently. // currently.
m_lpSetWindowLongPtrW(msg->hwnd, WNEF_EXECUTE_WINAPI(SetWindowLongPtrW,
GWL_EXSTYLE, msg->hwnd,
m_lpGetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); GWL_EXSTYLE,
WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW,
0,
msg->hwnd,
GWL_EXSTYLE)
| WS_EX_LAYERED)
updateWindow(msg->hwnd, true, false); updateWindow(msg->hwnd, true, false);
// A layered window can't be visible unless we call // A layered window can't be visible unless we call
// SetLayeredWindowAttributes or UpdateLayeredWindow once. // SetLayeredWindowAttributes or UpdateLayeredWindow once.
m_lpSetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0, LWA_COLORKEY); WNEF_EXECUTE_WINAPI(SetLayeredWindowAttributes,
msg->hwnd,
RGB(255, 0, 255),
0,
LWA_COLORKEY)
} }
// Bring our frame shadow back through DWM, don't draw it manually. // Bring our frame shadow back through DWM, don't draw it manually.
UpdateFrameMarginsForWindow(msg->hwnd); UpdateFrameMarginsForWindow(msg->hwnd);
@ -1174,7 +1211,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
APPBARDATA abd; APPBARDATA abd;
SecureZeroMemory(&abd, sizeof(abd)); SecureZeroMemory(&abd, sizeof(abd));
abd.cbSize = sizeof(abd); abd.cbSize = sizeof(abd);
const UINT taskbarState = m_lpSHAppBarMessage(ABM_GETSTATE, &abd); const UINT taskbarState = WNEF_EXECUTE_WINAPI_RETURN(SHAppBarMessage,
0,
ABM_GETSTATE,
&abd);
// First, check if we have an auto-hide taskbar at all: // First, check if we have an auto-hide taskbar at all:
if (taskbarState & ABS_AUTOHIDE) { if (taskbarState & ABS_AUTOHIDE) {
bool top = false, bottom = false, left = false, right = false; bool top = false, bottom = false, left = false, right = false;
@ -1193,7 +1233,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
_abd.uEdge = edge; _abd.uEdge = edge;
_abd.rc = monitorInfo.rcMonitor; _abd.rc = monitorInfo.rcMonitor;
const auto hTaskbar = reinterpret_cast<HWND>( const auto hTaskbar = reinterpret_cast<HWND>(
m_lpSHAppBarMessage(ABM_GETAUTOHIDEBAREX, &_abd)); WNEF_EXECUTE_WINAPI_RETURN(SHAppBarMessage,
0,
ABM_GETAUTOHIDEBAREX,
&_abd));
return hTaskbar != nullptr; return hTaskbar != nullptr;
}; };
top = hasAutohideTaskbar(ABE_TOP); top = hasAutohideTaskbar(ABE_TOP);
@ -1207,14 +1250,23 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
APPBARDATA _abd; APPBARDATA _abd;
SecureZeroMemory(&_abd, sizeof(_abd)); SecureZeroMemory(&_abd, sizeof(_abd));
_abd.cbSize = sizeof(_abd); _abd.cbSize = sizeof(_abd);
_abd.hWnd = m_lpFindWindowW(L"Shell_TrayWnd", nullptr); _abd.hWnd = WNEF_EXECUTE_WINAPI_RETURN(FindWindowW,
nullptr,
L"Shell_TrayWnd",
nullptr);
if (_abd.hWnd) { if (_abd.hWnd) {
const HMONITOR windowMonitor const HMONITOR windowMonitor
= m_lpMonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST); = WNEF_EXECUTE_WINAPI_RETURN(MonitorFromWindow,
nullptr,
msg->hwnd,
MONITOR_DEFAULTTONEAREST);
const HMONITOR taskbarMonitor const HMONITOR taskbarMonitor
= m_lpMonitorFromWindow(_abd.hWnd, MONITOR_DEFAULTTOPRIMARY); = WNEF_EXECUTE_WINAPI_RETURN(MonitorFromWindow,
nullptr,
_abd.hWnd,
MONITOR_DEFAULTTOPRIMARY);
if (taskbarMonitor == windowMonitor) { if (taskbarMonitor == windowMonitor) {
m_lpSHAppBarMessage(ABM_GETTASKBARPOS, &_abd); WNEF_EXECUTE_WINAPI(SHAppBarMessage, ABM_GETTASKBARPOS, &_abd)
edge = _abd.uEdge; edge = _abd.uEdge;
} }
} }
@ -1280,7 +1332,12 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate
// Don't use "*result = 0" otherwise the window won't respond to // Don't use "*result = 0" otherwise the window won't respond to
// the window active state change. // the window active state change.
*result = m_lpDefWindowProcW(msg->hwnd, msg->message, msg->wParam, -1); *result = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW,
0,
msg->hwnd,
msg->message,
msg->wParam,
-1);
} else { } else {
if (static_cast<BOOL>(msg->wParam)) { if (static_cast<BOOL>(msg->wParam)) {
*result = FALSE; *result = FALSE;
@ -1424,7 +1481,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
}; };
#endif #endif
RECT clientRect = {0, 0, 0, 0}; RECT clientRect = {0, 0, 0, 0};
m_lpGetClientRect(_hWnd, &clientRect); WNEF_EXECUTE_WINAPI(GetClientRect, _hWnd, &clientRect)
const LONG ww = clientRect.right; const LONG ww = clientRect.right;
const LONG wh = clientRect.bottom; const LONG wh = clientRect.bottom;
// Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor // Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor
@ -1433,7 +1490,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// different monitor. // different monitor.
const POINT globalMouse{GET_X_LPARAM(_lParam), GET_Y_LPARAM(_lParam)}; const POINT globalMouse{GET_X_LPARAM(_lParam), GET_Y_LPARAM(_lParam)};
POINT mouse = globalMouse; POINT mouse = globalMouse;
m_lpScreenToClient(_hWnd, &mouse); WNEF_EXECUTE_WINAPI(ScreenToClient, _hWnd, &mouse)
// These values should be DPI-aware. // These values should be DPI-aware.
const LONG bw = getSystemMetric(_hWnd, SystemMetric::BorderWidth, true); const LONG bw = getSystemMetric(_hWnd, SystemMetric::BorderWidth, true);
const LONG bh = getSystemMetric(_hWnd, SystemMetric::BorderHeight, true); const LONG bh = getSystemMetric(_hWnd, SystemMetric::BorderHeight, true);
@ -1568,16 +1625,21 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
case WM_SETTEXT: { case WM_SETTEXT: {
// Disable painting while these messages are handled to prevent them // Disable painting while these messages are handled to prevent them
// from drawing a window caption over the client area. // from drawing a window caption over the client area.
const auto oldStyle = m_lpGetWindowLongPtrW(msg->hwnd, GWL_STYLE); const auto oldStyle = WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW,
0,
msg->hwnd,
GWL_STYLE);
// Prevent Windows from drawing the default title bar by temporarily // Prevent Windows from drawing the default title bar by temporarily
// toggling the WS_VISIBLE style. // toggling the WS_VISIBLE style.
m_lpSetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle & ~WS_VISIBLE); WNEF_EXECUTE_WINAPI(SetWindowLongPtrW, msg->hwnd, GWL_STYLE, oldStyle & ~WS_VISIBLE)
updateWindow(msg->hwnd, true, false); updateWindow(msg->hwnd, true, false);
const LRESULT ret = m_lpDefWindowProcW(msg->hwnd, const LRESULT ret = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW,
msg->message, 0,
msg->wParam, msg->hwnd,
msg->lParam); msg->message,
m_lpSetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle); msg->wParam,
msg->lParam);
WNEF_EXECUTE_WINAPI(SetWindowLongPtrW, msg->hwnd, GWL_STYLE, oldStyle)
updateWindow(msg->hwnd, true, false); updateWindow(msg->hwnd, true, false);
*result = ret; *result = ret;
return true; return true;
@ -1621,7 +1683,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
void WinNativeEventFilter::setWindowData(const HWND window, const WINDOWDATA *data) void WinNativeEventFilter::setWindowData(const HWND window, const WINDOWDATA *data)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (window && m_lpIsWindow(window) && data) { if (window && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, window) && data) {
createUserData(window, data); createUserData(window, data);
} }
} }
@ -1629,10 +1691,11 @@ void WinNativeEventFilter::setWindowData(const HWND window, const WINDOWDATA *da
WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::windowData(const HWND window) WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::windowData(const HWND window)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (window && m_lpIsWindow(window)) { if (window && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, window)) {
createUserData(window); createUserData(window);
return &( return &(reinterpret_cast<WINDOW *>(
reinterpret_cast<WINDOW *>(m_lpGetWindowLongPtrW(window, GWLP_USERDATA))->windowData); WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, window, GWLP_USERDATA))
->windowData);
} }
return nullptr; return nullptr;
} }
@ -1657,22 +1720,24 @@ void WinNativeEventFilter::updateWindow(const HWND handle,
const bool redraw) const bool redraw)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
if (triggerFrameChange) { if (triggerFrameChange) {
m_lpSetWindowPos(handle, WNEF_EXECUTE_WINAPI(SetWindowPos,
nullptr, handle,
0, nullptr,
0, 0,
0, 0,
0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE 0,
| SWP_NOZORDER | SWP_NOOWNERZORDER); SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE
| SWP_NOZORDER | SWP_NOOWNERZORDER)
} }
if (redraw) { if (redraw) {
m_lpRedrawWindow(handle, WNEF_EXECUTE_WINAPI(RedrawWindow,
nullptr, handle,
nullptr, nullptr,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); nullptr,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN)
} }
} }
} }
@ -1683,18 +1748,19 @@ int WinNativeEventFilter::getSystemMetric(const HWND handle,
{ {
ResolveWin32APIs(); ResolveWin32APIs();
const qreal dpr = dpiAware ? GetDevicePixelRatioForWindow(handle) : m_defaultDevicePixelRatio; const qreal dpr = dpiAware ? GetDevicePixelRatioForWindow(handle) : m_defaultDevicePixelRatio;
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
createUserData(handle); createUserData(handle);
const auto userData = reinterpret_cast<WINDOW *>( const auto userData = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(handle, GWLP_USERDATA)); WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW, 0, handle, GWLP_USERDATA));
switch (metric) { switch (metric) {
case SystemMetric::BorderWidth: { case SystemMetric::BorderWidth: {
const int bw = userData->windowData.borderWidth; const int bw = userData->windowData.borderWidth;
if (bw > 0) { if (bw > 0) {
return qRound(bw * dpr); return qRound(bw * dpr);
} else { } else {
const int result_nondpi = m_lpGetSystemMetrics(SM_CXSIZEFRAME) const int result_nondpi
+ m_lpGetSystemMetrics(SM_CXPADDEDBORDER); = WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics, 0, SM_CXSIZEFRAME)
+ WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics, 0, SM_CXPADDEDBORDER);
const int result_dpi = GetSystemMetricsForWindow(handle, SM_CXSIZEFRAME) const int result_dpi = GetSystemMetricsForWindow(handle, SM_CXSIZEFRAME)
+ GetSystemMetricsForWindow(handle, SM_CXPADDEDBORDER); + GetSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
const int result = dpiAware ? result_dpi : result_nondpi; const int result = dpiAware ? result_dpi : result_nondpi;
@ -1706,8 +1772,9 @@ int WinNativeEventFilter::getSystemMetric(const HWND handle,
if (bh > 0) { if (bh > 0) {
return qRound(bh * dpr); return qRound(bh * dpr);
} else { } else {
const int result_nondpi = m_lpGetSystemMetrics(SM_CYSIZEFRAME) const int result_nondpi
+ m_lpGetSystemMetrics(SM_CXPADDEDBORDER); = WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics, 0, SM_CYSIZEFRAME)
+ WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics, 0, SM_CXPADDEDBORDER);
const int result_dpi = GetSystemMetricsForWindow(handle, SM_CYSIZEFRAME) const int result_dpi = GetSystemMetricsForWindow(handle, SM_CYSIZEFRAME)
+ GetSystemMetricsForWindow(handle, SM_CXPADDEDBORDER); + GetSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
const int result = dpiAware ? result_dpi : result_nondpi; const int result = dpiAware ? result_dpi : result_nondpi;
@ -1719,7 +1786,9 @@ int WinNativeEventFilter::getSystemMetric(const HWND handle,
if (tbh > 0) { if (tbh > 0) {
return qRound(tbh * dpr); return qRound(tbh * dpr);
} else { } else {
const int result_nondpi = m_lpGetSystemMetrics(SM_CYCAPTION); const int result_nondpi = WNEF_EXECUTE_WINAPI_RETURN(GetSystemMetrics,
0,
SM_CYCAPTION);
const int result_dpi = GetSystemMetricsForWindow(handle, SM_CYCAPTION); const int result_dpi = GetSystemMetricsForWindow(handle, SM_CYCAPTION);
const int result = dpiAware ? result_dpi : result_nondpi; const int result = dpiAware ? result_dpi : result_nondpi;
return result > 0 ? result : qRound(m_defaultTitleBarHeight * dpr); return result > 0 ? result : qRound(m_defaultTitleBarHeight * dpr);
@ -1754,20 +1823,21 @@ void WinNativeEventFilter::setWindowGeometry(
const HWND handle, const int x, const int y, const int width, const int height) const HWND handle, const int x, const int y, const int width, const int height)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (handle && m_lpIsWindow(handle) && (x > 0) && (y > 0) && (width > 0) && (height > 0)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle) && (x > 0) && (y > 0)
&& (width > 0) && (height > 0)) {
const qreal dpr = GetDevicePixelRatioForWindow(handle); const qreal dpr = GetDevicePixelRatioForWindow(handle);
// Why not use SetWindowPos? Actually we can, but MoveWindow // Why not use SetWindowPos? Actually we can, but MoveWindow
// sends the WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, // sends the WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE,
// WM_SIZE, and WM_NCCALCSIZE messages to the window. // WM_SIZE, and WM_NCCALCSIZE messages to the window.
// SetWindowPos only sends WM_WINDOWPOSCHANGED. // SetWindowPos only sends WM_WINDOWPOSCHANGED.
m_lpMoveWindow(handle, x, y, qRound(width * dpr), qRound(height * dpr), TRUE); WNEF_EXECUTE_WINAPI(MoveWindow, handle, x, y, qRound(width * dpr), qRound(height * dpr), TRUE)
} }
} }
void WinNativeEventFilter::moveWindowToDesktopCenter(const HWND handle) void WinNativeEventFilter::moveWindowToDesktopCenter(const HWND handle)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const WINDOWINFO windowInfo = GetInfoForWindow(handle); const WINDOWINFO windowInfo = GetInfoForWindow(handle);
const MONITORINFO monitorInfo = GetMonitorInfoForWindow(handle); const MONITORINFO monitorInfo = GetMonitorInfoForWindow(handle);
// If we want to move a window to the center of the desktop, // If we want to move a window to the center of the desktop,
@ -1777,7 +1847,13 @@ void WinNativeEventFilter::moveWindowToDesktopCenter(const HWND handle)
const LONG mh = qAbs(monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top); const LONG mh = qAbs(monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
const LONG ww = qAbs(windowInfo.rcWindow.right - windowInfo.rcWindow.left); const LONG ww = qAbs(windowInfo.rcWindow.right - windowInfo.rcWindow.left);
const LONG wh = qAbs(windowInfo.rcWindow.bottom - windowInfo.rcWindow.top); const LONG wh = qAbs(windowInfo.rcWindow.bottom - windowInfo.rcWindow.top);
m_lpMoveWindow(handle, qRound((mw - ww) / 2.0), qRound((mh - wh) / 2.0), ww, wh, TRUE); WNEF_EXECUTE_WINAPI(MoveWindow,
handle,
qRound((mw - ww) / 2.0),
qRound((mh - wh) / 2.0),
ww,
wh,
TRUE)
} }
} }
@ -1805,7 +1881,7 @@ void WinNativeEventFilter::updateQtFrame(QWindow *window, const int titleBarHeig
void WinNativeEventFilter::updateQtFrame_internal(const HWND handle) void WinNativeEventFilter::updateQtFrame_internal(const HWND handle)
{ {
ResolveWin32APIs(); ResolveWin32APIs();
if (handle && m_lpIsWindow(handle)) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const int tbh = getSystemMetric(handle, SystemMetric::TitleBarHeight); const int tbh = getSystemMetric(handle, SystemMetric::TitleBarHeight);
#ifdef QT_WIDGETS_LIB #ifdef QT_WIDGETS_LIB
const QWidget *widget = QWidget::find(reinterpret_cast<WId>(handle)); const QWidget *widget = QWidget::find(reinterpret_cast<WId>(handle));