From 01ad24aae1acf2613b81f8b8397d1d50b552da9d Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Fri, 11 Mar 2022 21:57:24 +0800 Subject: [PATCH] wip Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/images.qrc | 16 +-- examples/images/README.txt | 5 - examples/images/button_close_black.svg | 6 - examples/images/button_close_white.svg | 6 - examples/images/button_maximize_black.svg | 3 - examples/images/button_maximize_white.svg | 3 - examples/images/button_minimize_black.svg | 3 - examples/images/button_minimize_white.svg | 3 - examples/images/button_restore_black.svg | 11 -- examples/images/button_restore_white.svg | 11 -- examples/images/dark/chrome-close.svg | 3 + examples/images/dark/chrome-maximize.svg | 3 + examples/images/dark/chrome-minimize.svg | 3 + examples/images/dark/chrome-restore.svg | 4 + examples/images/light/chrome-close.svg | 3 + examples/images/light/chrome-maximize.svg | 3 + examples/images/light/chrome-minimize.svg | 3 + examples/images/light/chrome-restore.svg | 4 + examples/widget/widget.cpp | 127 ++++++++++++++++------ examples/widget/widget.h | 8 +- 20 files changed, 131 insertions(+), 97 deletions(-) delete mode 100644 examples/images/README.txt delete mode 100644 examples/images/button_close_black.svg delete mode 100644 examples/images/button_close_white.svg delete mode 100644 examples/images/button_maximize_black.svg delete mode 100644 examples/images/button_maximize_white.svg delete mode 100644 examples/images/button_minimize_black.svg delete mode 100644 examples/images/button_minimize_white.svg delete mode 100644 examples/images/button_restore_black.svg delete mode 100644 examples/images/button_restore_white.svg create mode 100644 examples/images/dark/chrome-close.svg create mode 100644 examples/images/dark/chrome-maximize.svg create mode 100644 examples/images/dark/chrome-minimize.svg create mode 100644 examples/images/dark/chrome-restore.svg create mode 100644 examples/images/light/chrome-close.svg create mode 100644 examples/images/light/chrome-maximize.svg create mode 100644 examples/images/light/chrome-minimize.svg create mode 100644 examples/images/light/chrome-restore.svg diff --git a/examples/images.qrc b/examples/images.qrc index 7d61a10..17c3dbc 100644 --- a/examples/images.qrc +++ b/examples/images.qrc @@ -1,12 +1,12 @@ - images/button_minimize_black.svg - images/button_minimize_white.svg - images/button_maximize_black.svg - images/button_maximize_white.svg - images/button_restore_black.svg - images/button_restore_white.svg - images/button_close_black.svg - images/button_close_white.svg + images/dark/chrome-close.svg + images/dark/chrome-maximize.svg + images/dark/chrome-minimize.svg + images/dark/chrome-restore.svg + images/light/chrome-close.svg + images/light/chrome-maximize.svg + images/light/chrome-minimize.svg + images/light/chrome-restore.svg diff --git a/examples/images/README.txt b/examples/images/README.txt deleted file mode 100644 index 11c3729..0000000 --- a/examples/images/README.txt +++ /dev/null @@ -1,5 +0,0 @@ -All the SVG images in this folder are created by me, using Inkscape. No images are downloaded from the Internet, not even one pixel. - -Since I copied the screenshot (when the scale factor is 1.0) pixel by pixel, they should be exactly the same with the real system buttons, in theory. - -Anyone can use them freely. diff --git a/examples/images/button_close_black.svg b/examples/images/button_close_black.svg deleted file mode 100644 index 6f1f03b..0000000 --- a/examples/images/button_close_black.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/examples/images/button_close_white.svg b/examples/images/button_close_white.svg deleted file mode 100644 index b69095a..0000000 --- a/examples/images/button_close_white.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/examples/images/button_maximize_black.svg b/examples/images/button_maximize_black.svg deleted file mode 100644 index 28ed556..0000000 --- a/examples/images/button_maximize_black.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/examples/images/button_maximize_white.svg b/examples/images/button_maximize_white.svg deleted file mode 100644 index a892dc7..0000000 --- a/examples/images/button_maximize_white.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/examples/images/button_minimize_black.svg b/examples/images/button_minimize_black.svg deleted file mode 100644 index d48db11..0000000 --- a/examples/images/button_minimize_black.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/examples/images/button_minimize_white.svg b/examples/images/button_minimize_white.svg deleted file mode 100644 index b46afc9..0000000 --- a/examples/images/button_minimize_white.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/examples/images/button_restore_black.svg b/examples/images/button_restore_black.svg deleted file mode 100644 index 9d4e17a..0000000 --- a/examples/images/button_restore_black.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/examples/images/button_restore_white.svg b/examples/images/button_restore_white.svg deleted file mode 100644 index af2605d..0000000 --- a/examples/images/button_restore_white.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/examples/images/dark/chrome-close.svg b/examples/images/dark/chrome-close.svg new file mode 100644 index 0000000..0b61504 --- /dev/null +++ b/examples/images/dark/chrome-close.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/dark/chrome-maximize.svg b/examples/images/dark/chrome-maximize.svg new file mode 100644 index 0000000..40db442 --- /dev/null +++ b/examples/images/dark/chrome-maximize.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/dark/chrome-minimize.svg b/examples/images/dark/chrome-minimize.svg new file mode 100644 index 0000000..da89f42 --- /dev/null +++ b/examples/images/dark/chrome-minimize.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/dark/chrome-restore.svg b/examples/images/dark/chrome-restore.svg new file mode 100644 index 0000000..c0715cd --- /dev/null +++ b/examples/images/dark/chrome-restore.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/images/light/chrome-close.svg b/examples/images/light/chrome-close.svg new file mode 100644 index 0000000..5a1ff32 --- /dev/null +++ b/examples/images/light/chrome-close.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/light/chrome-maximize.svg b/examples/images/light/chrome-maximize.svg new file mode 100644 index 0000000..a72b77b --- /dev/null +++ b/examples/images/light/chrome-maximize.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/light/chrome-minimize.svg b/examples/images/light/chrome-minimize.svg new file mode 100644 index 0000000..75b9915 --- /dev/null +++ b/examples/images/light/chrome-minimize.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/images/light/chrome-restore.svg b/examples/images/light/chrome-restore.svg new file mode 100644 index 0000000..25a00d1 --- /dev/null +++ b/examples/images/light/chrome-restore.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 51b662b..db0245f 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -29,14 +29,14 @@ #include #include #include +#include FRAMELESSHELPER_USE_NAMESPACE static const QColor systemLightColor = QStringLiteral("#f0f0f0"); static const QColor systemDarkColor = QColor::fromRgb(32, 32, 32); -static constexpr const char mainStyleSheet[] = R"( -#MainWidget { +static const QString mainStyleSheet = QStringLiteral(R"(#MainWidget { background-color: %1; } @@ -72,14 +72,14 @@ static constexpr const char mainStyleSheet[] = R"( #ClockLabel { color: %4; } -)"; +)"); Widget::Widget(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_DontCreateNativeAncestors); createWinId(); - //setupUi(); - //startTimer(500); + setupUi(); + startTimer(500); } Widget::~Widget() = default; @@ -87,11 +87,7 @@ Widget::~Widget() = default; void Widget::showEvent(QShowEvent *event) { QWidget::showEvent(event); - static bool inited = false; - if (!inited) { - inited = true; - FramelessWindowsManager::addWindow(windowHandle()); - } + initOnce(); } void Widget::timerEvent(QTimerEvent *event) @@ -105,17 +101,18 @@ void Widget::timerEvent(QTimerEvent *event) void Widget::changeEvent(QEvent *event) { QWidget::changeEvent(event); -#if 0 bool shouldUpdate = false; if (event->type() == QEvent::WindowStateChange) { - if (isMaximized() || isFullScreen()) { - setContentsMargins(0, 0, 0, 0); - } else if (!isMinimized()) { - const auto margin = static_cast(qRound(frameBorderThickness())); - setContentsMargins(margin, margin, margin, margin); +#ifdef Q_OS_WIN + if (Utilities::isWin10OrGreater()) { + if (isMaximized() || isFullScreen()) { + setContentsMargins(0, 0, 0, 0); + } else if (!isMinimized()) { + resetContentsMargins(); + } } +#endif updateSystemButtonIcons(); - updateTitleBarSize(); shouldUpdate = true; } else if (event->type() == QEvent::ActivationChange) { shouldUpdate = true; @@ -123,23 +120,48 @@ void Widget::changeEvent(QEvent *event) if (shouldUpdate) { updateStyleSheet(); } -#endif } void Widget::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); +#ifdef Q_OS_WIN + if ((windowState() == Qt::WindowNoState) && Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater()) { + QPainter painter(this); + painter.save(); + QPen pen = {}; + pen.setColor(Utilities::getFrameBorderColor(isActiveWindow())); + const int frameBorderThickness = Utilities::getFrameBorderThickness(winId(), false); + pen.setWidth(frameBorderThickness); + painter.setPen(pen); + painter.drawLine(0, frameBorderThickness, width(), frameBorderThickness); + painter.restore(); + } +#endif +} + +void Widget::initOnce() +{ + if (m_inited) { + return; + } + m_inited = true; + resetContentsMargins(); + FramelessWindowsManager::addWindow(windowHandle()); } void Widget::setupUi() { -#if 0 + const int titleBarHeight = /*Utilities::getTitleBarHeight(winId(), false)*/30; + const QSize systemButtonSize = {int(qRound(qreal(titleBarHeight) * 1.5)), titleBarHeight}; + const QSize systemIconSize = {16, 16}; setObjectName(QStringLiteral("MainWidget")); setWindowTitle(tr("Hello, World!")); resize(800, 600); m_titleBarWidget = new QWidget(this); m_titleBarWidget->setObjectName(QStringLiteral("TitleBarWidget")); m_titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_titleBarWidget->setFixedHeight(titleBarHeight); m_windowTitleLabel = new QLabel(m_titleBarWidget); m_windowTitleLabel->setObjectName(QStringLiteral("WindowTitleLabel")); m_windowTitleLabel->setFrameShape(QFrame::NoFrame); @@ -150,19 +172,30 @@ void Widget::setupUi() connect(this, &Widget::windowTitleChanged, m_windowTitleLabel, &QLabel::setText); m_minimizeButton = new QPushButton(m_titleBarWidget); m_minimizeButton->setObjectName(QStringLiteral("MinimizeButton")); + m_minimizeButton->setFixedSize(systemButtonSize); + m_minimizeButton->setIconSize(systemIconSize); + m_minimizeButton->setToolTip(tr("Minimize")); connect(m_minimizeButton, &QPushButton::clicked, this, &Widget::showMinimized); m_maximizeButton = new QPushButton(m_titleBarWidget); m_maximizeButton->setObjectName(QStringLiteral("MaximizeButton")); + m_maximizeButton->setFixedSize(systemButtonSize); + m_maximizeButton->setIconSize(systemIconSize); + m_maximizeButton->setToolTip(tr("Maximize")); connect(m_maximizeButton, &QPushButton::clicked, this, [this](){ if (isMaximized() || isFullScreen()) { showNormal(); + m_maximizeButton->setToolTip(tr("Maximize")); } else { showMaximized(); + m_maximizeButton->setToolTip(tr("Restore")); } updateSystemButtonIcons(); }); m_closeButton = new QPushButton(m_titleBarWidget); m_closeButton->setObjectName(QStringLiteral("CloseButton")); + m_closeButton->setFixedSize(systemButtonSize); + m_closeButton->setIconSize(systemIconSize); + m_closeButton->setToolTip(tr("Close")); connect(m_closeButton, &QPushButton::clicked, this, &Widget::close); updateSystemButtonIcons(); const auto titleBarLayout = new QHBoxLayout(m_titleBarWidget); @@ -197,38 +230,66 @@ void Widget::setupUi() mainLayout->addStretch(); setLayout(mainLayout); updateStyleSheet(); -#endif } void Widget::updateStyleSheet() { + const bool active = isActiveWindow(); + const bool dark = Utilities::shouldAppsUseDarkMode(); + const DwmColorizationArea area = Utilities::getDwmColorizationArea(); + const bool colorizedTitleBar = ((area == DwmColorizationArea::TitleBar_WindowBorder) || (area == DwmColorizationArea::All)); + const QColor colorizationColor = Utilities::getDwmColorizationColor(); + const QColor mainWidgetBackgroundColor = (dark ? systemDarkColor : systemLightColor); + const QColor titleBarWidgetBackgroundColor = [active, colorizedTitleBar, &colorizationColor, dark]() -> QColor { + if (active) { + if (colorizedTitleBar) { + return colorizationColor; + } else { + if (dark) { + return QColor(Qt::black); + } else { + return QColor(Qt::white); + } + } + } else { + if (dark) { + return systemDarkColor; + } else { + return QColor(Qt::white); + } + } + }(); + const QColor windowTitleLabelTextColor = (active ? (dark ? Qt::white : Qt::black) : Qt::darkGray); + const QColor clockLabelTextColor = (dark ? Qt::white : Qt::black); + setStyleSheet(mainStyleSheet.arg(mainWidgetBackgroundColor.name(), titleBarWidgetBackgroundColor.name(), + windowTitleLabelTextColor.name(), clockLabelTextColor.name())); + update(); } void Widget::updateSystemButtonIcons() { -#if 0 Q_ASSERT(m_minimizeButton); Q_ASSERT(m_maximizeButton); Q_ASSERT(m_closeButton); if (!m_minimizeButton || !m_maximizeButton || !m_closeButton) { return; } - const QString suffix = (Utilities::shouldAppsUseDarkMode() ? QStringLiteral("white") : QStringLiteral("black")); - m_minimizeButton->setIcon(QIcon(QStringLiteral(":/images/button_minimize_%1.svg").arg(suffix))); + const QString prefix = (Utilities::shouldAppsUseDarkMode() ? QStringLiteral("light") : QStringLiteral("dark")); + m_minimizeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-minimize.svg").arg(prefix))); if (isMaximized() || isFullScreen()) { - m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/button_restore_%1.svg").arg(suffix))); + m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-restore.svg").arg(prefix))); } else { - m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/button_maximize_%1.svg").arg(suffix))); + m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-maximize.svg").arg(prefix))); } - m_closeButton->setIcon(QIcon(QStringLiteral(":/images/button_close_%1.svg").arg(suffix))); -#endif + m_closeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-close.svg").arg(prefix))); } -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -bool Widget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) -#else -bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result) -#endif +void Widget::resetContentsMargins() { - return QWidget::nativeEvent(eventType, message, result); +#ifdef Q_OS_WIN + if (Utilities::isWin10OrGreater()) { + const int frameBorderThickness = Utilities::getFrameBorderThickness(winId(), false); + setContentsMargins(0, frameBorderThickness, 0, 0); + } +#endif } diff --git a/examples/widget/widget.h b/examples/widget/widget.h index f6f5afa..9dfdc2d 100644 --- a/examples/widget/widget.h +++ b/examples/widget/widget.h @@ -44,18 +44,16 @@ protected: void timerEvent(QTimerEvent *event) override; void changeEvent(QEvent *event) override; void paintEvent(QPaintEvent *event) override; -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; -#else - bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; -#endif private: + void initOnce(); void setupUi(); void updateStyleSheet(); void updateSystemButtonIcons(); + void resetContentsMargins(); private: + bool m_inited = false; QWidget *m_titleBarWidget = nullptr; QLabel *m_windowTitleLabel = nullptr; QPushButton *m_minimizeButton = nullptr;