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;