From 6221eb4178e63befe0fcee28f5136b3f7cfb2579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=AD=90=E6=A5=9A=5Czhuzi?= Date: Fri, 29 Dec 2023 23:09:46 +0800 Subject: [PATCH] update --- example/qml-Qt6/window/AboutWindow.qml | 2 +- example/qml/window/AboutWindow.qml | 2 +- src/FluFramelessHelper.cpp | 98 +++++++++++-------- src/FluFramelessHelper.h | 2 + src/FluTools.cpp | 39 ++++++-- src/FluTools.h | 2 + .../imports/FluentUI/Controls/FluWindow.qml | 26 ++++- .../imports/FluentUI/Controls/FluWindow.qml | 26 ++++- 8 files changed, 141 insertions(+), 56 deletions(-) diff --git a/example/qml-Qt6/window/AboutWindow.qml b/example/qml-Qt6/window/AboutWindow.qml index a830d3df..1e28956a 100644 --- a/example/qml-Qt6/window/AboutWindow.qml +++ b/example/qml-Qt6/window/AboutWindow.qml @@ -9,7 +9,7 @@ FluWindow { id:window title:"关于" width: 600 - height: 600 + height: 580 fixSize: true launchMode: FluWindowType.SingleTask diff --git a/example/qml/window/AboutWindow.qml b/example/qml/window/AboutWindow.qml index ef929418..74d2b406 100644 --- a/example/qml/window/AboutWindow.qml +++ b/example/qml/window/AboutWindow.qml @@ -10,7 +10,7 @@ FluWindow { id:window title:"关于" width: 600 - height: 600 + height: 580 fixSize: true launchMode: FluWindowType.SingleTask diff --git a/src/FluFramelessHelper.cpp b/src/FluFramelessHelper.cpp index 4b5fa3cd..8ad340ac 100644 --- a/src/FluFramelessHelper.cpp +++ b/src/FluFramelessHelper.cpp @@ -23,6 +23,24 @@ static inline bool isTaskbarAutoHide() { return lParam & ABS_AUTOHIDE; } +static inline QColor getAccentColor(){ + typedef HRESULT (WINAPI* DwmGetColorizationColorPtr)(DWORD* pcrColorization,BOOL* pfOpaqueBlend); + HMODULE module = LoadLibraryW(L"dwmapi.dll"); + if (module) + { + DwmGetColorizationColorPtr dwm_get_colorization_color; + dwm_get_colorization_color= reinterpret_cast(GetProcAddress(module, "DwmGetColorizationColor")); + DWORD color = 0; + BOOL bOpaque = FALSE; + if (dwm_get_colorization_color) + { + dwm_get_colorization_color(&color,&bOpaque); + } + return QColor(color); + } + return QColor(); +} + static inline bool isCompositionEnabled(){ typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled); HMODULE module = LoadLibraryW(L"dwmapi.dll"); @@ -41,22 +59,17 @@ static inline bool isCompositionEnabled(){ } static inline void showShadow(HWND hwnd){ - if(isCompositionEnabled()){ - const MARGINS shadow = { 0, 0, 1, 0 }; - typedef HRESULT (WINAPI* DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset); - HMODULE module = LoadLibraryW(L"dwmapi.dll"); - if (module) + const MARGINS shadow = { 0, 0, 1, 0 }; + typedef HRESULT (WINAPI* DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset); + HMODULE module = LoadLibraryW(L"dwmapi.dll"); + if (module) + { + DwmExtendFrameIntoClientAreaPtr dwm_extendframe_into_client_area_; + dwm_extendframe_into_client_area_= reinterpret_cast(GetProcAddress(module, "DwmExtendFrameIntoClientArea")); + if (dwm_extendframe_into_client_area_) { - DwmExtendFrameIntoClientAreaPtr dwm_extendframe_into_client_area_; - dwm_extendframe_into_client_area_= reinterpret_cast(GetProcAddress(module, "DwmExtendFrameIntoClientArea")); - if (dwm_extendframe_into_client_area_) - { - dwm_extendframe_into_client_area_(hwnd, &shadow); - } + dwm_extendframe_into_client_area_(hwnd, &shadow); } - }else{ - ULONG_PTR cNewStyle = GetClassLongPtr(hwnd, GCL_STYLE) | CS_DROPSHADOW; - SetClassLongPtr(hwnd, GCL_STYLE, cNewStyle); } } @@ -108,25 +121,16 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void * } if(IsZoomed(hwnd)){ _helper->setOriginalPos(QPoint(originalLeft,originalTop)); + if(isTaskbarAutoHide()){ + clientRect->bottom -= 1; + } }else{ _helper->setOriginalPos({}); } clientRect->top = originalTop; *result = WVR_REDRAW; return true; - }else if(uMsg == WM_NCPAINT){ - if(!isCompositionEnabled()){ - *result = WVR_REDRAW; - return true; - } - return false; - }else if(uMsg == WM_NCACTIVATE){ - if(!isCompositionEnabled()){ - *result = 1; - return true; - } - return false; - }else if(uMsg == WM_NCHITTEST){ + }if(uMsg == WM_NCHITTEST){ if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){ if (*result == HTNOWHERE) { *result = HTZOOM; @@ -256,24 +260,34 @@ void FluFramelessHelper::componentComplete(){ o = o->parent(); } if(!window.isNull()){ + _stayTop = QQmlProperty(window,"stayTop"); + _screen = QQmlProperty(window,"screen"); + _fixSize = QQmlProperty(window,"fixSize"); + _originalPos = QQmlProperty(window,"_originalPos"); + _accentColor = QQmlProperty(window,"_accentColor"); #ifdef Q_OS_WIN - // window->setFlags(window->flags() | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint); - _nativeEvent =new FramelessEventFilter(this); - qApp->installNativeEventFilter(_nativeEvent); - HWND hwnd = reinterpret_cast(window->winId()); - DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); - if(resizeable()){ - SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); + if(isCompositionEnabled()){ + _accentColor.write(getAccentColor()); + _nativeEvent =new FramelessEventFilter(this); + qApp->installNativeEventFilter(_nativeEvent); + HWND hwnd = reinterpret_cast(window->winId()); + DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); + if(resizeable()){ + SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); + }else{ + SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION); + } + SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + if(_fixSize.read().toBool()){ + window->setMaximumSize(window->size()); + window->setMinimumSize(window->size()); + } }else{ - SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION); + window->setFlags((window->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window); } - SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); #else window->setFlags((window->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window); #endif - _stayTop = QQmlProperty(window,"stayTop"); - _screen = QQmlProperty(window,"screen"); - _originalPos = QQmlProperty(window,"_originalPos"); _onStayTopChange(); _stayTop.connectNotifySignal(this,SLOT(_onStayTopChange())); _screen.connectNotifySignal(this,SLOT(_onScreenChanged())); @@ -334,8 +348,10 @@ FluFramelessHelper::~FluFramelessHelper(){ if (!window.isNull()) { window->setFlags(Qt::Window); #ifdef Q_OS_WIN - qApp->removeNativeEventFilter(_nativeEvent); - delete _nativeEvent; + if(isCompositionEnabled()){ + qApp->removeNativeEventFilter(_nativeEvent); + delete _nativeEvent; + } #endif window->removeEventFilter(this); } diff --git a/src/FluFramelessHelper.h b/src/FluFramelessHelper.h index e271c485..5a22f581 100644 --- a/src/FluFramelessHelper.h +++ b/src/FluFramelessHelper.h @@ -56,6 +56,8 @@ private: QQmlProperty _stayTop; QQmlProperty _screen; QQmlProperty _originalPos; + QQmlProperty _fixSize; + QQmlProperty _accentColor; }; #endif // FLUFRAMELESSHELPER_H diff --git a/src/FluTools.cpp b/src/FluTools.cpp index 046922e8..f28ac368 100644 --- a/src/FluTools.cpp +++ b/src/FluTools.cpp @@ -196,17 +196,42 @@ int FluTools::cursorScreenIndex(){ return screenIndex; } +int FluTools::windowBuildNumber(){ +#if defined(Q_OS_WIN) + QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat}; + if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) { + auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt(); + return buildNumber; + } +#endif + return -1; +} + bool FluTools::isWindows11OrGreater(){ static QVariant var; if(var.isNull()){ #if defined(Q_OS_WIN) - QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat}; - if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) { - auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt(); - if(buildNumber>=22000){ - var = QVariant::fromValue(true); - return true; - } + auto buildNumber = windowBuildNumber(); + if(buildNumber>=22000){ + var = QVariant::fromValue(true); + return true; + } +#endif + var = QVariant::fromValue(false); + return false; + }else{ + return var.toBool(); + } +} + +bool FluTools::isWindows10OrGreater(){ + static QVariant var; + if(var.isNull()){ +#if defined(Q_OS_WIN) + auto buildNumber = windowBuildNumber(); + if(buildNumber>=10240){ + var = QVariant::fromValue(true); + return true; } #endif var = QVariant::fromValue(false); diff --git a/src/FluTools.h b/src/FluTools.h index d297d3df..04ecf631 100644 --- a/src/FluTools.h +++ b/src/FluTools.h @@ -51,7 +51,9 @@ public: Q_INVOKABLE QPoint cursorPos(); Q_INVOKABLE QIcon windowIcon(); Q_INVOKABLE int cursorScreenIndex(); + Q_INVOKABLE int windowBuildNumber(); Q_INVOKABLE bool isWindows11OrGreater(); + Q_INVOKABLE bool isWindows10OrGreater(); }; #endif // FLUTOOLS_H diff --git a/src/Qt5/imports/FluentUI/Controls/FluWindow.qml b/src/Qt5/imports/FluentUI/Controls/FluWindow.qml index eeb68b8b..38f1676f 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluWindow.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluWindow.qml @@ -40,7 +40,12 @@ Window { property bool showStayTop: true property bool autoMaximize: false property bool useSystemAppBar - property color resizeBorderColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + property color resizeBorderColor: { + if(window.active){ + return _accentColor + } + return FluTheme.dark ? "#3D3D3E" : "#A7A7A7" + } property int resizeBorderWidth: 1 property var closeListener: function(event){ if(closeDestory){ @@ -55,6 +60,7 @@ Window { signal firstVisible() property point _offsetXY : Qt.point(0,0) property var _originalPos + property color _accentColor : FluTheme.dark ? "#333333" : "#6E6E6E" id:window color:"transparent" Component.onCompleted: { @@ -192,7 +198,7 @@ Window { id:layout_container anchors{ fill:parent - topMargin: _offsetXY.x + topMargin: _offsetXY.y } onWidthChanged: { window.appBar.width = width @@ -245,7 +251,21 @@ Window { border.width: window.resizeBorderWidth border.color: window.resizeBorderColor visible: { - if(window.useSystemAppBar){ + if(window.useSystemAppBar || FluTools.isWindows10OrGreater()){ + return false + } + if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){ + return false + } + return true + } + } + Rectangle{ + height: 1 + width: parent.width + color: window.resizeBorderColor + visible: { + if(window.useSystemAppBar || !FluTools.isWin()){ return false } if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluWindow.qml b/src/Qt6/imports/FluentUI/Controls/FluWindow.qml index 485e33a2..5b4ad259 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluWindow.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluWindow.qml @@ -39,7 +39,12 @@ Window { property bool showStayTop: true property bool autoMaximize: false property bool useSystemAppBar - property color resizeBorderColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + property color resizeBorderColor: { + if(window.active){ + return _accentColor + } + return FluTheme.dark ? "#3D3D3E" : "#A7A7A7" + } property int resizeBorderWidth: 1 property var closeListener: function(event){ if(closeDestory){ @@ -54,6 +59,7 @@ Window { signal firstVisible() property point _offsetXY : Qt.point(0,0) property var _originalPos + property color _accentColor : FluTheme.dark ? "#333333" : "#6E6E6E" id:window color:"transparent" Component.onCompleted: { @@ -191,7 +197,7 @@ Window { id:layout_container anchors{ fill:parent - topMargin: _offsetXY.x + topMargin: _offsetXY.y } onWidthChanged: { window.appBar.width = width @@ -244,7 +250,21 @@ Window { border.width: window.resizeBorderWidth border.color: window.resizeBorderColor visible: { - if(window.useSystemAppBar){ + if(window.useSystemAppBar || FluTools.isWindows10OrGreater()){ + return false + } + if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){ + return false + } + return true + } + } + Rectangle{ + height: 1 + width: parent.width + color: window.resizeBorderColor + visible: { + if(window.useSystemAppBar || !FluTools.isWin()){ return false } if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){