diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index 493a8c4..141af82 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -121,7 +121,7 @@ void MainWindow::changeEvent(QEvent *event) void MainWindow::paintEvent(QPaintEvent *event) { QMainWindow::paintEvent(event); - if (windowState() == Qt::WindowNoState) { + if ((windowState() == Qt::WindowNoState) && !Utilities::isWin11OrGreater()) { const int w = width(); const int h = height(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index 4cf6fd4..e71d536 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -22,11 +22,71 @@ * SOFTWARE. */ +#include "../../utilities.h" #include "../../framelessquickhelper.h" #include #include #include +FRAMELESSHELPER_USE_NAMESPACE + +static constexpr const char qtquicknamespace[] = "wangwenx190.Utils"; + +class UtilFunctions : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(UtilFunctions) + Q_PROPERTY(bool isWindowsHost READ isWindowsHost CONSTANT) + Q_PROPERTY(bool isWindows10OrGreater READ isWindows10OrGreater CONSTANT) + Q_PROPERTY(bool isWindows11OrGreater READ isWindows11OrGreater CONSTANT) + Q_PROPERTY(QColor activeFrameBorderColor READ activeFrameBorderColor CONSTANT) + Q_PROPERTY(QColor inactiveFrameBorderColor READ inactiveFrameBorderColor CONSTANT) + Q_PROPERTY(qreal frameBorderThickness READ frameBorderThickness CONSTANT) + +public: + explicit UtilFunctions(QObject *parent = nullptr) : QObject(parent) {} + ~UtilFunctions() override = default; + + inline bool isWindowsHost() const { +#ifdef Q_OS_WINDOWS + return true; +#else + return false; +#endif + } + + inline bool isWindows10OrGreater() const { +#ifdef Q_OS_WINDOWS + return Utilities::isWin10OrGreater(); +#else + return false; +#endif + } + + inline bool isWindows11OrGreater() const { +#ifdef Q_OS_WINDOWS + return Utilities::isWin11OrGreater(); +#else + return false; +#endif + } + + inline QColor activeFrameBorderColor() const { + const ColorizationArea area = Utilities::getColorizationArea(); + const bool colorizedBorder = ((area == ColorizationArea::TitleBar_WindowBorder) + || (area == ColorizationArea::All)); + return (colorizedBorder ? Utilities::getColorizationColor() : Qt::black); + } + + inline QColor inactiveFrameBorderColor() const { + return Qt::darkGray; + } + + inline qreal frameBorderThickness() const { + return 1.0; + } +}; + int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); @@ -48,7 +108,12 @@ int main(int argc, char *argv[]) QQuickStyle::setStyle(QStringLiteral("Default")); #endif - qmlRegisterType("wangwenx190.Utils", 1, 0, "FramelessHelper"); + qmlRegisterSingletonType(qtquicknamespace, 1, 0, "Utils", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * { + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + return new UtilFunctions(); + }); + qmlRegisterType(qtquicknamespace, 1, 0, "FramelessHelper"); const QUrl mainQmlUrl(QStringLiteral("qrc:///qml/main.qml")); const QMetaObject::Connection connection = QObject::connect( @@ -71,3 +136,5 @@ int main(int argc, char *argv[]) return QGuiApplication::exec(); } + +#include "main.moc" diff --git a/examples/quick/qml/main.qml b/examples/quick/qml/main.qml index 3a2a87b..0cc77cc 100644 --- a/examples/quick/qml/main.qml +++ b/examples/quick/qml/main.qml @@ -35,7 +35,7 @@ Window { title: qsTr("Hello, World!") color: "#f0f0f0" - property real _flh_margin: ((window.visibility === Window.Maximized) | (window.visibility === Window.FullScreen)) ? 0.0 : 1.0 + property real _flh_margin: ((window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen)) ? 0 : Utils.frameBorderThickness property var _win_prev_state: null FramelessHelper { @@ -140,8 +140,9 @@ Window { id: windowFrame anchors.fill: parent color: "transparent" + visible: !Utils.isWindows11OrGreater border { - color: window.active ? "black" : "darkGray" + color: window.active ? Utils.activeFrameBorderColor : Utils.inactiveFrameBorderColor width: window._flh_margin } } diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 78df163..a6d0809 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -136,18 +136,18 @@ void Widget::changeEvent(QEvent *event) void Widget::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); - if (!isMaximized() && !isFullScreen()) { - const auto w = static_cast(width()); - const auto h = static_cast(height()); + if ((windowState() == Qt::WindowNoState) && !Utilities::isWin11OrGreater()) { + const int w = width(); + const int h = height(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - using BorderLines = QList; + using BorderLines = QList; #else - using BorderLines = QVector; + using BorderLines = QVector; #endif const BorderLines lines = { {0, 0, w, 0}, - {w, 0, w , h}, - {w, h, 0, h}, + {w - 1, 0, w - 1, h}, + {w, h - 1, 0, h - 1}, {0, h, 0, 0} }; const ColorizationArea area = Utilities::getColorizationArea(); diff --git a/utilities.h b/utilities.h index c894206..82e2326 100644 --- a/utilities.h +++ b/utilities.h @@ -49,6 +49,7 @@ namespace Utilities [[nodiscard]] FRAMELESSHELPER_API bool isWin8OrGreater(); [[nodiscard]] FRAMELESSHELPER_API bool isWin8Point1OrGreater(); [[nodiscard]] FRAMELESSHELPER_API bool isWin10OrGreater(); +[[nodiscard]] FRAMELESSHELPER_API bool isWin11OrGreater(); [[nodiscard]] FRAMELESSHELPER_API bool isDwmCompositionAvailable(); FRAMELESSHELPER_API void triggerFrameChange(const WId winId); FRAMELESSHELPER_API void updateFrameMargins(const WId winId, const bool reset); diff --git a/utilities_win32.cpp b/utilities_win32.cpp index e5f6f9f..0076a6b 100644 --- a/utilities_win32.cpp +++ b/utilities_win32.cpp @@ -44,11 +44,23 @@ Q_DECLARE_METATYPE(QMargins) FRAMELESSHELPER_BEGIN_NAMESPACE -[[nodiscard]] static inline QPointF extractMousePositionFromLParam(const LPARAM lParam) +#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) +[[nodiscard]] static inline bool isWindowsVersionOrGreater(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild) { - const POINT nativePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - return QPointF(static_cast(nativePos.x), static_cast(nativePos.y)); + OSVERSIONINFOEXW osvi; + SecureZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = dwMajor; + osvi.dwMinorVersion = dwMinor; + osvi.dwBuildNumber = dwBuild; + DWORDLONG dwlConditionMask = 0; + const auto op = VER_GREATER_EQUAL; + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, op); + return (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask) != FALSE); } +#endif [[nodiscard]] static inline bool isWin10RS5OrGreater() { @@ -57,7 +69,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE #elif (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 17763)); #else - static const bool result = (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10); + static const bool result = isWindowsVersionOrGreater(10, 0, 17763); #endif return result; } @@ -69,7 +81,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE #elif (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 18362)); #else - static const bool result = (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10); + static const bool result = isWindowsVersionOrGreater(10, 0, 18362); #endif return result; } @@ -137,6 +149,18 @@ bool Utilities::isWin10OrGreater() return result; } +bool Utilities::isWin11OrGreater() +{ +#if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)) + static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11); +#elif (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 22000)); +#else + static const bool result = isWindowsVersionOrGreater(10, 0, 22000); +#endif + return result; +} + bool Utilities::isDwmCompositionAvailable() { // DWM composition is always enabled and can't be disabled since Windows 8. @@ -454,7 +478,10 @@ bool Utilities::isSystemMenuRequested(const void *data, QPointF *pos) } if (result) { if (pos) { - *pos = extractMousePositionFromLParam(msg->lParam); + *pos = [msg](){ + const POINT nativePos = {GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam)}; + return QPointF(static_cast(nativePos.x), static_cast(nativePos.y)); + }(); } } return result;