From 2a0626a9cd544f66c8023881b4d534f5199d4e74 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Wed, 12 Feb 2020 20:03:11 +0800 Subject: Add a function to change non-client area rendering policy Documentation and a manual test are added at the same time. Change-Id: I1e70e9b01fb13d0e67559024531f9ad015849032 Reviewed-by: Friedemann Kleint --- src/imports/winextras/plugins.qmltypes | 9 +++ src/imports/winextras/qquickdwmfeatures.cpp | 27 ++++++++ src/imports/winextras/qquickdwmfeatures_p.h | 4 ++ src/imports/winextras/qquickdwmfeatures_p_p.h | 1 + src/imports/winextras/qquickwin_p.h | 8 +++ src/winextras/qwinfunctions.cpp | 97 ++++++++++++++++++++++++++- src/winextras/qwinfunctions.h | 27 ++++++-- tests/manual/dwmfeatures/testwidget.cpp | 25 +++++-- tests/manual/dwmfeatures/testwidget.h | 1 + tests/manual/dwmfeatures/testwidget.ui | 68 +++++++++++++++++-- 10 files changed, 252 insertions(+), 15 deletions(-) diff --git a/src/imports/winextras/plugins.qmltypes b/src/imports/winextras/plugins.qmltypes index 2c4c390..fff1181 100644 --- a/src/imports/winextras/plugins.qmltypes +++ b/src/imports/winextras/plugins.qmltypes @@ -26,6 +26,7 @@ Module { Property { name: "excludedFromPeek"; type: "bool" } Property { name: "peekDisallowed"; type: "bool" } Property { name: "flip3DPolicy"; type: "QQuickWin::WindowFlip3DPolicy" } + Property { name: "nonClientAreaRenderingPolicy"; type: "QQuickWin::WindowNonClientRenderingPolicy" } } Component { name: "QQuickJumpList" @@ -144,6 +145,14 @@ Module { "FlipExcludeAbove": 2 } } + Enum { + name: "WindowNonClientRenderingPolicy" + values: { + "NonClientRenderingUseWindowStyle": 0, + "NonClientRenderingDisabled": 1, + "NonClientRenderingEnabled": 2 + } + } } Component { name: "QWinTaskbarProgress" diff --git a/src/imports/winextras/qquickdwmfeatures.cpp b/src/imports/winextras/qquickdwmfeatures.cpp index a7ca158..124d957 100644 --- a/src/imports/winextras/qquickdwmfeatures.cpp +++ b/src/imports/winextras/qquickdwmfeatures.cpp @@ -293,6 +293,32 @@ void QQuickDwmFeatures::setFlip3DPolicy(QQuickWin::WindowFlip3DPolicy policy) emit flip3DPolicyChanged(); } +/*! + \qmlproperty QtWin::WindowNonClientRenderingPolicy DwmFeatures::nonClientAreaRenderingPolicy + + The current non-client area rendering policy for the window. + */ +QQuickWin::WindowNonClientRenderingPolicy QQuickDwmFeatures::nonClientAreaRenderingPolicy() const +{ + Q_D(const QQuickDwmFeatures); + if (window()) + return static_cast(QtWin::windowNonClientAreaRenderingPolicy(window())); + else + return d->nonClientRenderingPolicy; +} + +void QQuickDwmFeatures::setNonClientAreaRenderingPolicy(QQuickWin::WindowNonClientRenderingPolicy policy) +{ + Q_D(QQuickDwmFeatures); + if (d->nonClientRenderingPolicy == policy) + return; + + d->nonClientRenderingPolicy = policy; + if (window()) + QtWin::setWindowNonClientAreaRenderingPolicy(window(), static_cast(d->nonClientRenderingPolicy)); + emit nonClientAreaRenderingPolicyChanged(); +} + bool QQuickDwmFeatures::eventFilter(QObject *object, QEvent *event) { Q_D(QQuickDwmFeatures); @@ -349,6 +375,7 @@ void QQuickDwmFeaturesPrivate::updateAll() QtWin::setWindowExcludedFromPeek(w, peekExcluded); QtWin::setWindowDisallowPeek(w, peekDisallowed); QtWin::setWindowFlip3DPolicy(w, static_cast(flipPolicy)); + QtWin::setWindowNonClientAreaRenderingPolicy(w, static_cast(nonClientRenderingPolicy)); if (blurBehindEnabled) QtWin::enableBlurBehindWindow(w); else diff --git a/src/imports/winextras/qquickdwmfeatures_p.h b/src/imports/winextras/qquickdwmfeatures_p.h index d98aa00..3887d24 100644 --- a/src/imports/winextras/qquickdwmfeatures_p.h +++ b/src/imports/winextras/qquickdwmfeatures_p.h @@ -77,6 +77,7 @@ class QQuickDwmFeatures : public QQuickItem Q_PROPERTY(bool excludedFromPeek READ isExcludedFromPeek WRITE setExcludedFromPeek NOTIFY excludedFromPeekChanged) Q_PROPERTY(bool peekDisallowed READ isPeekDisallowed WRITE setPeekDisallowed NOTIFY peekDisallowedChanged) Q_PROPERTY(QQuickWin::WindowFlip3DPolicy flip3DPolicy READ flip3DPolicy WRITE setFlip3DPolicy NOTIFY flip3DPolicyChanged) + Q_PROPERTY(QQuickWin::WindowNonClientRenderingPolicy nonClientAreaRenderingPolicy READ nonClientAreaRenderingPolicy WRITE setNonClientAreaRenderingPolicy NOTIFY nonClientAreaRenderingPolicyChanged) public: explicit QQuickDwmFeatures(QQuickItem *parent = nullptr); @@ -105,6 +106,8 @@ public: void setPeekDisallowed(bool disallow); QQuickWin::WindowFlip3DPolicy flip3DPolicy() const; void setFlip3DPolicy(QQuickWin::WindowFlip3DPolicy policy); + QQuickWin::WindowNonClientRenderingPolicy nonClientAreaRenderingPolicy() const; + void setNonClientAreaRenderingPolicy(QQuickWin::WindowNonClientRenderingPolicy policy); bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; @@ -123,6 +126,7 @@ Q_SIGNALS: void excludedFromPeekChanged(); void peekDisallowedChanged(); void flip3DPolicyChanged(); + void nonClientAreaRenderingPolicyChanged(); protected: void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE; diff --git a/src/imports/winextras/qquickdwmfeatures_p_p.h b/src/imports/winextras/qquickdwmfeatures_p_p.h index 4ec1244..acf9dd6 100644 --- a/src/imports/winextras/qquickdwmfeatures_p_p.h +++ b/src/imports/winextras/qquickdwmfeatures_p_p.h @@ -70,6 +70,7 @@ public: bool peekDisallowed = false; bool peekExcluded = false; QQuickWin::WindowFlip3DPolicy flipPolicy = QQuickWin::FlipDefault; + QQuickWin::WindowNonClientRenderingPolicy nonClientRenderingPolicy = QQuickWin::NonClientRenderingUseWindowStyle; QColor originalSurfaceColor; void updateAll(); diff --git a/src/imports/winextras/qquickwin_p.h b/src/imports/winextras/qquickwin_p.h index 0f4e510..4ed9015 100644 --- a/src/imports/winextras/qquickwin_p.h +++ b/src/imports/winextras/qquickwin_p.h @@ -77,6 +77,14 @@ public: FlipExcludeAbove = QtWin::FlipExcludeAbove }; Q_ENUM(WindowFlip3DPolicy) + + enum WindowNonClientRenderingPolicy + { + NonClientRenderingUseWindowStyle = QtWin::NonClientRenderingUseWindowStyle, + NonClientRenderingDisabled = QtWin::NonClientRenderingDisabled, + NonClientRenderingEnabled = QtWin::NonClientRenderingEnabled + }; + Q_ENUM(WindowNonClientRenderingPolicy) }; QT_END_NAMESPACE diff --git a/src/winextras/qwinfunctions.cpp b/src/winextras/qwinfunctions.cpp index 4dcf8f0..68f2c99 100644 --- a/src/winextras/qwinfunctions.cpp +++ b/src/winextras/qwinfunctions.cpp @@ -1640,6 +1640,69 @@ QtWin::WindowFlip3DPolicy QtWin::windowFlip3DPolicy(QWindow *window) return policy; } +/*! + \since 6.0 + + Sets the non-client area rendering policy \a policy for the specified \a window. + + \note Disabling non-client area rendering will cause any previous calls to + QtWin::enableBlurBehindWindow() or to QtWin::extendFrameIntoClientArea() to be disabled. + */ +void QtWin::setWindowNonClientAreaRenderingPolicy(QWindow *window, QtWin::WindowNonClientRenderingPolicy policy) +{ + Q_ASSERT_X(window, Q_FUNC_INFO, "window is null"); + + HWND handle = reinterpret_cast(window->winId()); + + DWORD value = DWMNCRP_USEWINDOWSTYLE; + + switch (policy) { + default : + case NonClientRenderingUseWindowStyle : + break; + case NonClientRenderingDisabled : + value = DWMNCRP_DISABLED; + break; + case NonClientRenderingEnabled : + value = DWMNCRP_ENABLED; + break; + } + + QtDwmApiDll::setWindowAttribute(handle, DWMWA_NCRENDERING_POLICY, value); +} + +/*! + \fn QtWin::WindowNonClientRenderingPolicy QtWin::windowNonClientAreaRenderingPolicy(QWidget *window) + \since 6.0 + \overload QtWin::windowNonClientAreaRenderingPolicy() + */ + +/*! + \since 6.0 + + Returns the current non-client area rendering policy for the specified \a window. + */ +QtWin::WindowNonClientRenderingPolicy QtWin::windowNonClientAreaRenderingPolicy(QWindow *window) +{ + Q_ASSERT_X(window, Q_FUNC_INFO, "window is null"); + + const auto value = + QtDwmApiDll::windowAttribute(reinterpret_cast(window->winId()), + DWMWA_NCRENDERING_POLICY, DWORD(DWMNCRP_USEWINDOWSTYLE)); + WindowNonClientRenderingPolicy policy = NonClientRenderingUseWindowStyle; + switch (value) { + case DWMNCRP_DISABLED : + policy = NonClientRenderingDisabled; + break; + case DWMNCRP_ENABLED : + policy = NonClientRenderingEnabled; + break; + default : + break; + } + return policy; +} + void qt_ExtendFrameIntoClientArea(QWindow *window, int left, int top, int right, int bottom) { QWinEventFilter::setup(); @@ -1659,7 +1722,9 @@ void qt_ExtendFrameIntoClientArea(QWindow *window, int left, int top, int right, using the \a left, \a top, \a right, and \a bottom margin values. Pass -1 as values for any of the four margins to fully extend the frame, - creating a \e {sheet of glass} effect. + creating a \e {sheet of glass} effect. If it doesn't work, change + non-client area rendering policy to QtWin::NonClientRenderingEnabled and + try again. If you want the extended frame to act like a standard window border, you should handle that yourself. @@ -1667,7 +1732,7 @@ void qt_ExtendFrameIntoClientArea(QWindow *window, int left, int top, int right, \note Qt::WA_NoSystemBackground must not be set on widgets for extendFrameIntoClientArea() to work. - \sa resetExtendedFrame() + \sa resetExtendedFrame(), setWindowNonClientAreaRenderingPolicy() */ void QtWin::extendFrameIntoClientArea(QWindow *window, int left, int top, int right, int bottom) { @@ -2041,4 +2106,32 @@ void QtWin::taskbarDeleteTab(QWindow *window) \sa setWindowFlip3DPolicy() */ +/*! + \enum QtWin::WindowNonClientRenderingPolicy + + \since 6.0 + + This enum type specifies the non-client area rendering policy. + + \value NonClientRenderingUseWindowStyle + The non-client rendering area is rendered based on the window + style. + + \value NonClientRenderingDisabled + The non-client area rendering is disabled and the window style + is ignored. + Note that disabling non-client area rendering will cause any + previous calls to QtWin::enableBlurBehindWindow() or to + QtWin::extendFrameIntoClientArea() to be disabled. + + \value NonClientRenderingEnabled + The non-client area rendering is enabled and the window style + is ignored. + If you want to bring frame shadow back to a frameless window, + enable this policy and call QtWin::extendFrameIntoClientArea() + with a negative height. + + \sa setWindowNonClientAreaRenderingPolicy() + */ + QT_END_NAMESPACE diff --git a/src/winextras/qwinfunctions.h b/src/winextras/qwinfunctions.h index ef2aece..8f27a6f 100644 --- a/src/winextras/qwinfunctions.h +++ b/src/winextras/qwinfunctions.h @@ -77,6 +77,13 @@ namespace QtWin FlipExcludeAbove }; + enum WindowNonClientRenderingPolicy + { + NonClientRenderingUseWindowStyle, + NonClientRenderingDisabled, + NonClientRenderingEnabled + }; + Q_WINEXTRAS_EXPORT HBITMAP createMask(const QBitmap &bitmap); Q_WINEXTRAS_EXPORT HBITMAP toHBITMAP(const QPixmap &p, HBitmapFormat format = HBitmapNoAlpha); Q_WINEXTRAS_EXPORT QPixmap fromHBITMAP(HBITMAP bitmap, HBitmapFormat format = HBitmapNoAlpha); @@ -100,6 +107,8 @@ namespace QtWin Q_WINEXTRAS_EXPORT bool isWindowPeekDisallowed(QWindow *window); Q_WINEXTRAS_EXPORT void setWindowFlip3DPolicy(QWindow *window, WindowFlip3DPolicy policy); Q_WINEXTRAS_EXPORT WindowFlip3DPolicy windowFlip3DPolicy(QWindow *); + Q_WINEXTRAS_EXPORT void setWindowNonClientAreaRenderingPolicy(QWindow *window, WindowNonClientRenderingPolicy policy); + Q_WINEXTRAS_EXPORT WindowNonClientRenderingPolicy windowNonClientAreaRenderingPolicy(QWindow *); Q_WINEXTRAS_EXPORT void extendFrameIntoClientArea(QWindow *window, int left, int top, int right, int bottom); Q_WINEXTRAS_EXPORT void extendFrameIntoClientArea(QWindow *window, const QMargins &margins); @@ -155,10 +164,20 @@ namespace QtWin inline WindowFlip3DPolicy windowFlip3DPolicy(QWidget *window) { - if (!window->windowHandle()) - return FlipDefault; - else - return windowFlip3DPolicy(window->windowHandle()); + auto handle = window->windowHandle(); + return handle ? windowFlip3DPolicy(handle) : FlipDefault; + } + + inline void setWindowNonClientAreaRenderingPolicy(QWidget *window, WindowNonClientRenderingPolicy policy) + { + window->createWinId(); + setWindowNonClientAreaRenderingPolicy(window->windowHandle(), policy); + } + + inline WindowNonClientRenderingPolicy windowNonClientAreaRenderingPolicy(QWidget *window) + { + auto handle = window->windowHandle(); + return handle ? windowNonClientAreaRenderingPolicy(handle) : NonClientRenderingUseWindowStyle; } inline void extendFrameIntoClientArea(QWidget *window, const QMargins &margins) diff --git a/tests/manual/dwmfeatures/testwidget.cpp b/tests/manual/dwmfeatures/testwidget.cpp index 09b25ac..e289946 100644 --- a/tests/manual/dwmfeatures/testwidget.cpp +++ b/tests/manual/dwmfeatures/testwidget.cpp @@ -40,11 +40,14 @@ TestWidget::TestWidget(QWidget *parent) : { ui->setupUi(this); - connect(ui->btnPeekDisallow, &QAbstractButton::clicked, this, &TestWidget::onDisallowPeekClicked); - connect(ui->btnPeekExclude, &QAbstractButton::clicked, this, &TestWidget::onExcludeFromPeekClicked); - connect(ui->radioFlipDefault, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); - connect(ui->radioFlipAbove, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); - connect(ui->radioFlipBelow, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); + connect(ui->btnPeekDisallow, &QAbstractButton::clicked, this, &TestWidget::onDisallowPeekClicked); + connect(ui->btnPeekExclude, &QAbstractButton::clicked, this, &TestWidget::onExcludeFromPeekClicked); + connect(ui->radioFlipDefault, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); + connect(ui->radioFlipAbove, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); + connect(ui->radioFlipBelow, &QAbstractButton::clicked, this, &TestWidget::onFlip3DPolicyChanged); + connect(ui->radioNcrpUseWindowStyle, &QAbstractButton::clicked, this, &TestWidget::onNonClientAreaRenderingPolicyChanged); + connect(ui->radioNcrpDisable, &QAbstractButton::clicked, this, &TestWidget::onNonClientAreaRenderingPolicyChanged); + connect(ui->radioNcrpEnable, &QAbstractButton::clicked, this, &TestWidget::onNonClientAreaRenderingPolicyChanged); connect(ui->btnFrameReset, &QAbstractButton::clicked, this, &TestWidget::onResetGlassFrameClicked); connect(ui->frameTop, QOverload::of(&QSpinBox::valueChanged), this, &TestWidget::onGlassMarginsChanged); @@ -106,6 +109,18 @@ void TestWidget::onFlip3DPolicyChanged() QtWin::setWindowFlip3DPolicy(this, policy); } +void TestWidget::onNonClientAreaRenderingPolicyChanged() +{ + QtWin::WindowNonClientRenderingPolicy policy; + if (ui->radioNcrpDisable->isChecked()) + policy = QtWin::NonClientRenderingDisabled; + else if (ui->radioNcrpEnable->isChecked()) + policy = QtWin::NonClientRenderingEnabled; + else + policy = QtWin::NonClientRenderingUseWindowStyle; + QtWin::setWindowNonClientAreaRenderingPolicy(this, policy); +} + void TestWidget::onGlassMarginsChanged() { if (!QtWin::isCompositionEnabled()) diff --git a/tests/manual/dwmfeatures/testwidget.h b/tests/manual/dwmfeatures/testwidget.h index 137e8ce..70c39c6 100644 --- a/tests/manual/dwmfeatures/testwidget.h +++ b/tests/manual/dwmfeatures/testwidget.h @@ -60,6 +60,7 @@ private slots: void onDisallowPeekClicked(); void onExcludeFromPeekClicked(); void onFlip3DPolicyChanged(); + void onNonClientAreaRenderingPolicyChanged(); void onGlassMarginsChanged(); void onResetGlassFrameClicked(); }; diff --git a/tests/manual/dwmfeatures/testwidget.ui b/tests/manual/dwmfeatures/testwidget.ui index 329ba61..2ef17d8 100644 --- a/tests/manual/dwmfeatures/testwidget.ui +++ b/tests/manual/dwmfeatures/testwidget.ui @@ -7,7 +7,7 @@ 0 0 569 - 331 + 451 @@ -31,7 +31,16 @@ 3 - + + 4 + + + 4 + + + 4 + + 4 @@ -155,7 +164,16 @@ 3 - + + 4 + + + 4 + + + 4 + + 4 @@ -185,6 +203,39 @@ + + + + Non-client area rendering + + + + + + Use window style + + + true + + + + + + + Disable + + + + + + + Enable + + + + + + @@ -197,7 +248,16 @@ 3 - + + 4 + + + 4 + + + 4 + + 4 -- cgit v1.2.3