From 12a6f868501b69f81ea1f10f77a40e5504414c06 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Thu, 6 Aug 2020 15:36:15 +0800 Subject: [PATCH] Update. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- main_windows.cpp | 48 ++-- resources/qml/main.qml | 12 +- winnativeeventfilter.cpp | 491 +++++++++++++++++++++++---------------- 3 files changed, 332 insertions(+), 219 deletions(-) diff --git a/main_windows.cpp b/main_windows.cpp index 19ca314..f58f4fc 100644 --- a/main_windows.cpp +++ b/main_windows.cpp @@ -26,41 +26,56 @@ #include #include #include +#include +#include #include +#include +#include #ifdef QT_QUICK_LIB #include "framelessquickhelper.h" #include +#include #endif -#include -#include -#include + +static inline bool shouldHaveWindowFrame() +{ + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10; +} class FramelessWidget : public QWidget { Q_OBJECT - // Q_DISABLE_COPY_MOVE(FramelessWidget) // Since Qt 5.13 + Q_DISABLE_COPY_MOVE(FramelessWidget) public: - explicit FramelessWidget(QWidget *parent = nullptr) : QWidget(parent) {} + explicit FramelessWidget(QWidget *parent = nullptr) : QWidget(parent) + { + isWin10OrGreater = shouldHaveWindowFrame(); + } ~FramelessWidget() override = default; + bool isNormaled() const { return !isMinimized() && !isMaximized() && !isFullScreen(); } + protected: void paintEvent(QPaintEvent *event) override { QWidget::paintEvent(event); - QPainter painter(this); - painter.save(); - painter.setPen(isActiveWindow() ? borderColor_active : borderColor_inactive); - painter.drawLine(0, 0, width(), 0); - painter.drawLine(0, height(), width(), height()); - painter.drawLine(0, 0, 0, height()); - painter.drawLine(width(), 0, width(), height()); - painter.restore(); + if (isWin10OrGreater && isNormaled()) { + QPainter painter(this); + painter.save(); + painter.setPen(isActiveWindow() ? borderColor_active : borderColor_inactive); + painter.drawLine(0, 0, width(), 0); + // painter.drawLine(0, height(), width(), height()); + // painter.drawLine(0, 0, 0, height()); + // painter.drawLine(width(), 0, width(), height()); + painter.restore(); + } } private: - const QColor borderColor_active = {"#707070"}; + const QColor borderColor_active = {/*"#707070"*/ "#ffffff"}; const QColor borderColor_inactive = {"#aaaaaa"}; + bool isWin10OrGreater = false; }; int main(int argc, char *argv[]) @@ -163,6 +178,11 @@ int main(int argc, char *argv[]) }, Qt::QueuedConnection); engine.load(mainQmlUrl); + QList rootObjs = engine.rootObjects(); + Q_ASSERT(!rootObjs.isEmpty()); + QObject *rootObj = rootObjs.at(0); + Q_ASSERT(rootObj); + QQmlProperty::write(rootObj, QString::fromUtf8("isWin10OrGreater"), shouldHaveWindowFrame()); #endif return QApplication::exec(); diff --git a/resources/qml/main.qml b/resources/qml/main.qml index 1b1ecc4..876eb1a 100644 --- a/resources/qml/main.qml +++ b/resources/qml/main.qml @@ -9,13 +9,21 @@ Window { height: 600 title: qsTr("Hello, World!") + property bool isWin10OrGreater: false + FramelessHelper { id: framelessHelper } Rectangle { - anchors.fill: parent - border.color: Qt.application.state === Qt.ApplicationActive ? "#707070" : "#aaaaaa" + visible: isWin10OrGreater && (window.visibility === Window.Windowed) + anchors { + top: parent.top + left: parent.left + right: parent.right + } + height: 1 + color: Qt.application.state === Qt.ApplicationActive ? /*"#707070"*/ "#ffffff" : "#aaaaaa" } Rectangle { diff --git a/winnativeeventfilter.cpp b/winnativeeventfilter.cpp index 09b5511..93161bd 100644 --- a/winnativeeventfilter.cpp +++ b/winnativeeventfilter.cpp @@ -100,7 +100,7 @@ const UINT m_defaultDotsPerInch = USER_DEFAULT_SCREEN_DPI; const qreal m_defaultDevicePixelRatio = 1.0; -bool isWin8OrGreator() +bool isWin8OrGreater() { #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8; @@ -109,7 +109,7 @@ bool isWin8OrGreator() #endif } -bool isWin8Point1OrGreator() +bool isWin8Point1OrGreater() { #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1; @@ -118,7 +118,7 @@ bool isWin8Point1OrGreator() #endif } -bool isWin10OrGreator(const int ver) +bool isWin10OrGreater(const int ver) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) return QOperatingSystemVersion::current() @@ -129,6 +129,15 @@ bool isWin10OrGreator(const int ver) #endif } +bool shouldHaveWindowFrame() +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10; +#else + return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10; +#endif +} + #ifndef WNEF_GENERATE_WINAPI #define WNEF_GENERATE_WINAPI(funcName, resultType, ...) \ using _WNEF_WINAPI_##funcName = resultType(WINAPI *)(__VA_ARGS__); \ @@ -411,19 +420,19 @@ void loadDPIFunctions() } resolved = true; // Available since Windows 8.1 - if (isWin8Point1OrGreator()) { + if (isWin8Point1OrGreater()) { WNEF_RESOLVE_WINAPI(SHCore, GetDpiForMonitor) WNEF_RESOLVE_WINAPI(SHCore, GetProcessDpiAwareness) } // Available since Windows 10, version 1607 (10.0.14393) - if (isWin10OrGreator(14393)) { + if (isWin10OrGreater(14393)) { WNEF_RESOLVE_WINAPI(User32, GetDpiForWindow) WNEF_RESOLVE_WINAPI(User32, GetDpiForSystem) WNEF_RESOLVE_WINAPI(User32, GetSystemMetricsForDpi) WNEF_RESOLVE_WINAPI(User32, AdjustWindowRectExForDpi) } // Available since Windows 10, version 1803 (10.0.17134) - if (isWin10OrGreator(17134)) { + if (isWin10OrGreater(17134)) { WNEF_RESOLVE_WINAPI(User32, GetSystemDpiForProcess) } } @@ -734,7 +743,7 @@ qreal GetDevicePixelRatioForWindow(const HWND handle) return GetPreferedNumber(result); } -RECT GetFrameSizeForWindow(const HWND handle, const bool includingTitleBar = false) +RECT GetFrameSizeForWindow(const HWND handle, const BOOL includingTitleBar = FALSE) { RECT rect = {0, 0, 0, 0}; if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { @@ -773,26 +782,38 @@ void UpdateFrameMarginsForWindow(const HWND handle) { if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { MARGINS margins = {0, 0, 0, 0}; - if (IsDwmCompositionEnabled()) { - // 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. - const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED; - WNEF_EXECUTE_WINAPI(DwmSetWindowAttribute, - handle, - DWMWA_NCRENDERING_POLICY, - &ncrp, - sizeof(ncrp)) - // Use negative values have the same effect, however, it will - // cause the window become transparent when it's maximizing or - // restoring from maximized. Just like flashing. Fixing it by - // passing positive values. - // The system won't draw the frame shadow if the window doesn't - // have a frame, so we have to extend the frame a bit to let the - // system draw the shadow. We won't see any frame even we have - // extended it because we have turned the whole window area into - // the client area in WM_NCCALCSIZE so we won't see it due to - // it's covered by the client area (in other words, it's still - // there, we just can't see it). + // 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. + const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED; + WNEF_EXECUTE_WINAPI(DwmSetWindowAttribute, + handle, + DWMWA_NCRENDERING_POLICY, + &ncrp, + sizeof(ncrp)) + // Use negative values have the same effect, however, it will + // cause the window become transparent when it's maximizing or + // restoring from maximized. Just like flashing. Fixing it by + // passing positive values. + // The system won't draw the frame shadow if the window doesn't + // have a frame, so we have to extend the frame a bit to let the + // system draw the shadow. We won't see any frame even we have + // extended it because we have turned the whole window area into + // the client area in WM_NCCALCSIZE so we won't see it due to + // it's covered by the client area (in other words, it's still + // there, we just can't see it). + if (shouldHaveWindowFrame()) { + const auto GetTopBorderHeight = [](const HWND handle) -> int { + if (handle && WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { + if (IsMaximized(handle) || IsFullScreen(handle) || !IsDwmCompositionEnabled()) { + return 0; + } + } + return 1; + }; + if (GetTopBorderHeight(handle) != 0) { + margins.cyTopHeight = GetFrameSizeForWindow(handle, TRUE).top; + } + } else { margins.cyTopHeight = 1; } WNEF_EXECUTE_WINAPI(DwmExtendFrameIntoClientArea, handle, &margins) @@ -1157,6 +1178,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // it. So things will become quite complicated if you want to // preserve the four window borders. So we just remove the whole // window frame, otherwise the code will become much more complex. + const auto mode = static_cast(msg->wParam); // If the window bounds change, we're going to relayout and repaint // anyway. Returning WVR_REDRAW avoids an extra paint before that of @@ -1167,6 +1189,25 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, const auto clientRect = mode ? &( reinterpret_cast(msg->lParam)->rgrc[0]) : reinterpret_cast(msg->lParam); + if (shouldHaveWindowFrame()) { + // Store the original top before the default window proc + // applies the default frame. + const LONG originalTop = clientRect->top; + // Apply the default frame + const LRESULT ret = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW, + 0, + msg->hwnd, + WM_NCCALCSIZE, + msg->wParam, + msg->lParam); + if (ret != 0) { + *result = ret; + return true; + } + // Re-apply the original top from before the size of the + // default frame was applied. + clientRect->top = originalTop; + } // We don't need this correction when we're fullscreen. We will // have the WS_POPUP size, so we don't have to worry about // borders, and the default frame will be fine. @@ -1178,12 +1219,14 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // The value of border width and border height should be // identical in most cases, when the scale factor is 1.0, it // should be eight pixels. - const int bw = getSystemMetric(msg->hwnd, SystemMetric::BorderWidth, true); const int bh = getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, true); clientRect->top += bh; - clientRect->bottom -= bh; - clientRect->left += bw; - clientRect->right -= bw; + if (!shouldHaveWindowFrame()) { + clientRect->bottom -= bh; + const int bw = getSystemMetric(msg->hwnd, SystemMetric::BorderWidth, true); + clientRect->left += bw; + clientRect->right -= bw; + } } // Attempt to detect if there's an autohide taskbar, and if // there is, reduce our size a bit on the side with the taskbar, @@ -1205,7 +1248,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // Due to ABM_GETAUTOHIDEBAREX only exists from Win8.1, // we have to use another way to judge this if we are // running on Windows 7 or Windows 8. - if (isWin8Point1OrGreator()) { + if (isWin8Point1OrGreater()) { const MONITORINFO monitorInfo = GetMonitorInfoForWindow(msg->hwnd); // This helper can be used to determine if there's a // auto-hide taskbar on the given edge of the monitor @@ -1286,50 +1329,62 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // area. *result = 0; } + if (shouldHaveWindowFrame()) { + *result = 0; + } return true; } + // These undocumented messages are sent to draw themed window + // borders. Block them to prevent drawing borders over the client + // area. case WM_NCUAHDRAWCAPTION: case WM_NCUAHDRAWFRAME: { - // These undocumented messages are sent to draw themed window - // borders. Block them to prevent drawing borders over the client - // area. - *result = 0; - return true; + if (shouldHaveWindowFrame()) { + break; + } else { + *result = 0; + return true; + } } case WM_NCPAINT: { // 边框阴影处于非客户区的范围,因此如果直接阻止非客户区的绘制,会导致边框阴影丢失 - if (!IsDwmCompositionEnabled()) { + if (!IsDwmCompositionEnabled() && !shouldHaveWindowFrame()) { // Only block WM_NCPAINT when DWM composition is disabled. If // it's blocked when DWM composition is enabled, the frame // shadow won't be drawn. *result = 0; return true; + } else { + break; } - break; } case WM_NCACTIVATE: { - if (IsDwmCompositionEnabled()) { - // DefWindowProc won't repaint the window border if lParam - // (normally a HRGN) is -1. See the following link's "lParam" - // section: - // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate - // Don't use "*result = 0" otherwise the window won't respond to - // the window active state change. - *result = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW, - 0, - msg->hwnd, - msg->message, - msg->wParam, - -1); + if (shouldHaveWindowFrame()) { + break; } else { - if (static_cast(msg->wParam)) { - *result = FALSE; + if (IsDwmCompositionEnabled()) { + // DefWindowProc won't repaint the window border if lParam + // (normally a HRGN) is -1. See the following link's "lParam" + // section: + // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate + // Don't use "*result = 0" otherwise the window won't respond + // to the window active state change. + *result = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW, + 0, + msg->hwnd, + msg->message, + msg->wParam, + -1); } else { - *result = TRUE; + if (static_cast(msg->wParam)) { + *result = FALSE; + } else { + *result = TRUE; + } } + return true; } - return true; } case WM_NCHITTEST: { // 原生Win32窗口只有顶边是在窗口内部resize的,其余三边都是在窗口 @@ -1396,175 +1451,205 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, // looks terrible on old systems. I'm testing this solution in // another branch, if you are interested in it, you can give it a // try. + if (data->windowData.mouseTransparent) { // Mouse events will be passed to the parent window. *result = HTTRANSPARENT; return true; } - const auto getHTResult = - [](const HWND _hWnd, const LPARAM _lParam, const WINDOWDATA &_data) -> LRESULT { - const auto isInSpecificAreas = [](const int x, - const int y, - const QList &areas, - const qreal dpr) -> bool { - if (!areas.isEmpty()) { - for (auto &&area : qAsConst(areas)) { - if (!area.isValid()) { - continue; - } - if (QRectF(area.x() * dpr, - area.y() * dpr, - area.width() * dpr, - area.height() * dpr) + const auto isInSpecificAreas = + [](const int x, const int y, const QList &areas, const qreal dpr) -> bool { + if (!areas.isEmpty()) { + for (auto &&area : qAsConst(areas)) { + if (!area.isValid()) { + continue; + } + if (QRectF(area.x() * dpr, + area.y() * dpr, + area.width() * dpr, + area.height() * dpr) + .contains(x, y)) { + return true; + } + } + } + return false; + }; +#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) + const auto isInSpecificObjects = [](const int x, + const int y, + const QList> &objects, + const qreal dpr) -> bool { + if (!objects.isEmpty()) { + for (auto &&object : qAsConst(objects)) { + if (!object) { + continue; + } +#ifdef QT_WIDGETS_LIB + const auto widget = qobject_cast(object); + if (widget) { + const QPoint pos = widget->mapToGlobal({0, 0}); + if (QRectF(pos.x() * dpr, + pos.y() * dpr, + widget->width() * dpr, + widget->height() * dpr) .contains(x, y)) { return true; } } - } - return false; - }; -#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) - const auto isInSpecificObjects = [](const int x, - const int y, - const QList> &objects, - const qreal dpr) -> bool { - if (!objects.isEmpty()) { - for (auto &&object : qAsConst(objects)) { - if (!object) { - continue; - } -#ifdef QT_WIDGETS_LIB - const auto widget = qobject_cast(object); - if (widget) { - const QPoint pos = widget->mapToGlobal({0, 0}); - if (QRectF(pos.x() * dpr, - pos.y() * dpr, - widget->width() * dpr, - widget->height() * dpr) - .contains(x, y)) { - return true; - } - } #endif #ifdef QT_QUICK_LIB - const auto quickItem = qobject_cast(object); - if (quickItem) { - const QPointF pos = quickItem->mapToGlobal({0, 0}); - if (QRectF(pos.x() * dpr, - pos.y() * dpr, - quickItem->width() * dpr, - quickItem->height() * dpr) - .contains(x, y)) { - return true; - } + const auto quickItem = qobject_cast(object); + if (quickItem) { + const QPointF pos = quickItem->mapToGlobal({0, 0}); + if (QRectF(pos.x() * dpr, + pos.y() * dpr, + quickItem->width() * dpr, + quickItem->height() * dpr) + .contains(x, y)) { + return true; } -#endif } +#endif } - return false; - }; + } + return false; + }; #endif - RECT clientRect = {0, 0, 0, 0}; - WNEF_EXECUTE_WINAPI(GetClientRect, _hWnd, &clientRect) - const LONG ww = clientRect.right; - const LONG wh = clientRect.bottom; - // Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor - // coordinates because their results are unsigned numbers, - // however the cursor position may be negative due to in a - // different monitor. - const POINT globalMouse{GET_X_LPARAM(_lParam), GET_Y_LPARAM(_lParam)}; - POINT mouse = globalMouse; - WNEF_EXECUTE_WINAPI(ScreenToClient, _hWnd, &mouse) - // These values should be DPI-aware. - const LONG bw = getSystemMetric(_hWnd, SystemMetric::BorderWidth, true); - const LONG bh = getSystemMetric(_hWnd, SystemMetric::BorderHeight, true); - const LONG tbh = getSystemMetric(_hWnd, SystemMetric::TitleBarHeight, true); - const qreal dpr = GetDevicePixelRatioForWindow(_hWnd); - const bool isInIgnoreAreas = isInSpecificAreas(mouse.x, - mouse.y, - _data.ignoreAreas, - dpr); - const bool customDragAreas = !_data.draggableAreas.isEmpty(); - const bool isInDraggableAreas = customDragAreas - ? isInSpecificAreas(mouse.x, - mouse.y, - _data.draggableAreas, - dpr) - : true; + // Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor + // coordinates because their results are unsigned numbers, + // however the cursor position may be negative due to in a + // different monitor. + const POINT globalMouse{GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam)}; + POINT localMouse = globalMouse; + WNEF_EXECUTE_WINAPI(ScreenToClient, msg->hwnd, &localMouse) + const auto &_data = data->windowData; + const qreal dpr = GetDevicePixelRatioForWindow(msg->hwnd); + const bool isInIgnoreAreas = isInSpecificAreas(localMouse.x, + localMouse.y, + _data.ignoreAreas, + dpr); + const bool customDragAreas = !_data.draggableAreas.isEmpty(); + const bool isInDraggableAreas = customDragAreas + ? isInSpecificAreas(localMouse.x, + localMouse.y, + _data.draggableAreas, + dpr) + : true; #if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) - const bool isInIgnoreObjects = isInSpecificObjects(globalMouse.x, - globalMouse.y, - _data.ignoreObjects, - dpr); - const bool customDragObjects = !_data.draggableObjects.isEmpty(); - const bool isInDraggableObjects = customDragObjects - ? isInSpecificObjects(globalMouse.x, - globalMouse.y, - _data.draggableObjects, - dpr) - : true; + const bool isInIgnoreObjects = isInSpecificObjects(globalMouse.x, + globalMouse.y, + _data.ignoreObjects, + dpr); + const bool customDragObjects = !_data.draggableObjects.isEmpty(); + const bool isInDraggableObjects = customDragObjects + ? isInSpecificObjects(globalMouse.x, + globalMouse.y, + _data.draggableObjects, + dpr) + : true; #else - // Don't block resizing if both of the Qt Widgets module and Qt - // Quick module are not compiled in, although there's not much - // significance of using this code in this case. - const bool isInIgnoreObjects = false; - const bool isInDraggableObjects = true; - const bool customDragObjects = false; + // Don't block resizing if both of the Qt Widgets module and Qt + // Quick module are not compiled in, although there's not much + // significance of using this code in this case. + const bool isInIgnoreObjects = false; + const bool isInDraggableObjects = true; + const bool customDragObjects = false; #endif - const bool customDrag = customDragAreas || customDragObjects; - const bool isResizePermitted = !isInIgnoreAreas && !isInIgnoreObjects; - const bool isTitleBar = (customDrag ? (isInDraggableAreas && isInDraggableObjects) - : (mouse.y <= (tbh + bh))) - && isResizePermitted && !_data.disableTitleBar; - if (IsMaximized(_hWnd)) { + const bool customDrag = customDragAreas || customDragObjects; + const bool isResizePermitted = !isInIgnoreAreas && !isInIgnoreObjects; + const LONG bh = getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, true); + const LONG tbh = getSystemMetric(msg->hwnd, SystemMetric::TitleBarHeight, true); + const bool isTitleBar = (customDrag ? (isInDraggableAreas && isInDraggableObjects) + : (localMouse.y <= (tbh + bh))) + && isResizePermitted && !_data.disableTitleBar; + const bool isTop = (localMouse.y <= bh) && isResizePermitted; + if (shouldHaveWindowFrame()) { + // This will handle the left, right and bottom parts of the frame + // because we didn't change them. + const LRESULT originalRet = WNEF_EXECUTE_WINAPI_RETURN(DefWindowProcW, + 0, + msg->hwnd, + WM_NCHITTEST, + msg->wParam, + msg->lParam); + if (originalRet != HTCLIENT) { + *result = originalRet; + return true; + } + // At this point, we know that the cursor is inside the client area + // so it has to be either the little border at the top of our custom + // title bar or the drag bar. Apparently, it must be the drag bar or + // the little border at the top which the user can use to move or + // resize the window. + if (!IsMaximized(msg->hwnd) && isTop) { + *result = HTTOP; + return true; + } + if (isTitleBar) { + *result = HTCAPTION; + return true; + } + *result = HTCLIENT; + return true; + } else { + const auto getHTResult = + [isTitleBar, localMouse, bh, isTop](const HWND _hWnd, + const WINDOWDATA &_data) -> LRESULT { + RECT clientRect = {0, 0, 0, 0}; + WNEF_EXECUTE_WINAPI(GetClientRect, _hWnd, &clientRect) + const LONG ww = clientRect.right; + const LONG wh = clientRect.bottom; + const LONG bw = getSystemMetric(_hWnd, SystemMetric::BorderWidth, true); + if (IsMaximized(_hWnd)) { + if (isTitleBar) { + return HTCAPTION; + } + return HTCLIENT; + } + const bool isBottom = (localMouse.y >= (wh - bh)); + // Make the border a little wider to let the user easy to resize + // on corners. + const int factor = (isTop || isBottom) ? 2 : 1; + const bool isLeft = (localMouse.x <= (bw * factor)); + const bool isRight = (localMouse.x >= (ww - (bw * factor))); + const bool fixedSize = _data.fixedSize; + const auto getBorderValue = [fixedSize](int value) -> int { + // HTBORDER: non-resizeable window border. + return fixedSize ? HTBORDER : value; + }; + if (isTop) { + if (isLeft) { + return getBorderValue(HTTOPLEFT); + } + if (isRight) { + return getBorderValue(HTTOPRIGHT); + } + return getBorderValue(HTTOP); + } + if (isBottom) { + if (isLeft) { + return getBorderValue(HTBOTTOMLEFT); + } + if (isRight) { + return getBorderValue(HTBOTTOMRIGHT); + } + return getBorderValue(HTBOTTOM); + } + if (isLeft) { + return getBorderValue(HTLEFT); + } + if (isRight) { + return getBorderValue(HTRIGHT); + } if (isTitleBar) { return HTCAPTION; } return HTCLIENT; - } - const bool isTop = (mouse.y <= bh) && isResizePermitted; - const bool isBottom = (mouse.y >= (wh - bh)); - // Make the border a little wider to let the user easy to resize - // on corners. - const int factor = (isTop || isBottom) ? 2 : 1; - const bool isLeft = (mouse.x <= (bw * factor)); - const bool isRight = (mouse.x >= (ww - (bw * factor))); - const bool fixedSize = _data.fixedSize; - const auto getBorderValue = [fixedSize](int value) -> int { - // HTBORDER: non-resizeable window border. - return fixedSize ? HTBORDER : value; }; - if (isTop) { - if (isLeft) { - return getBorderValue(HTTOPLEFT); - } - if (isRight) { - return getBorderValue(HTTOPRIGHT); - } - return getBorderValue(HTTOP); - } - if (isBottom) { - if (isLeft) { - return getBorderValue(HTBOTTOMLEFT); - } - if (isRight) { - return getBorderValue(HTBOTTOMRIGHT); - } - return getBorderValue(HTBOTTOM); - } - if (isLeft) { - return getBorderValue(HTLEFT); - } - if (isRight) { - return getBorderValue(HTRIGHT); - } - if (isTitleBar) { - return HTCAPTION; - } - return HTCLIENT; - }; - *result = getHTResult(msg->hwnd, msg->lParam, data->windowData); - return true; + *result = getHTResult(msg->hwnd, _data); + return true; + } } case WM_GETMINMAXINFO: { // We can set the maximum and minimum size of the window in this @@ -1573,7 +1658,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, const RECT rcWorkArea = monitorInfo.rcWork; const RECT rcMonitorArea = monitorInfo.rcMonitor; const auto mmi = reinterpret_cast(msg->lParam); - if (isWin8OrGreator()) { + if (isWin8OrGreater()) { // Works fine on Windows 8/8.1/10 mmi->ptMaxPosition.x = qAbs(rcWorkArea.left - rcMonitorArea.left); mmi->ptMaxPosition.y = qAbs(rcWorkArea.top - rcMonitorArea.top);