|
@ -1,12 +1,12 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>images/button_minimize_black.svg</file>
|
||||
<file>images/button_minimize_white.svg</file>
|
||||
<file>images/button_maximize_black.svg</file>
|
||||
<file>images/button_maximize_white.svg</file>
|
||||
<file>images/button_restore_black.svg</file>
|
||||
<file>images/button_restore_white.svg</file>
|
||||
<file>images/button_close_black.svg</file>
|
||||
<file>images/button_close_white.svg</file>
|
||||
<file>images/dark/chrome-close.svg</file>
|
||||
<file>images/dark/chrome-maximize.svg</file>
|
||||
<file>images/dark/chrome-minimize.svg</file>
|
||||
<file>images/dark/chrome-restore.svg</file>
|
||||
<file>images/light/chrome-close.svg</file>
|
||||
<file>images/light/chrome-maximize.svg</file>
|
||||
<file>images/light/chrome-minimize.svg</file>
|
||||
<file>images/light/chrome-restore.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -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.
|
|
@ -1,6 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="#000" stroke-width=".17639">
|
||||
<path d="m6.1295 3.6601 3.2632 3.2632z"/>
|
||||
<path d="m9.3927 3.6601-3.2632 3.2632z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 264 B |
|
@ -1,6 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="#fff" stroke-width=".17639">
|
||||
<path d="m6.1295 3.6601 3.2632 3.2632z"/>
|
||||
<path d="m9.3927 3.6601-3.2632 3.2632z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 264 B |
|
@ -1,3 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="6.1736" y="3.7042" width="3.175" height="3.175" fill="none" stroke="#000" stroke-width=".35278"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 225 B |
|
@ -1,3 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="6.1736" y="3.7042" width="3.175" height="3.175" fill="none" stroke="#fff" stroke-width=".35278"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 225 B |
|
@ -1,3 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m6.35 5.4681h3.5278z" fill="none" stroke="#000" stroke-width=".35278"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 199 B |
|
@ -1,3 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m6.35 5.4681h3.5278z" fill="none" stroke="#fff" stroke-width=".35278"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 199 B |
|
@ -1,11 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="#000">
|
||||
<rect x="6.1736" y="4.4097" width="2.4694" height="2.4694" stroke-width=".35278"/>
|
||||
<g stroke-width=".35278">
|
||||
<path d="m6.8792 4.2333v-0.70556z"/>
|
||||
<path d="m7.0556 3.7042h2.4694z"/>
|
||||
<path d="m9.3486 3.8806v2.4694z"/>
|
||||
<path d="m9.1722 6.1736h-0.35278z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 430 B |
|
@ -1,11 +0,0 @@
|
|||
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="#fff">
|
||||
<rect x="6.1736" y="4.4097" width="2.4694" height="2.4694" stroke-width=".35278"/>
|
||||
<g stroke-width=".35278">
|
||||
<path d="m6.8792 4.2333v-0.70556z"/>
|
||||
<path d="m7.0556 3.7042h2.4694z"/>
|
||||
<path d="m9.3486 3.8806v2.4694z"/>
|
||||
<path d="m9.1722 6.1736h-0.35278z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 430 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.11641 7.99992L2.55835 12.558L3.44223 13.4419L8.00029 8.88381L12.5583 13.4419L13.4422 12.558L8.88417 7.99992L13.4422 3.44187L12.5583 2.55798L8.00029 7.11604L3.44223 2.55798L2.55835 3.44187L7.11641 7.99992Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 378 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.00024 3V13H13.0002V3H3.00024ZM12.0002 12H4.00024V4H12.0002V12Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 196 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.0002 7.99994V8.99994H3.00024V7.99994H14.0002Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 180 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.00024 5V14H12.0002V5H3.00024ZM11.0002 13H4.00024V6H11.0002V13Z" fill="#424242"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.00024 5H6.00024V4H13.0002V11H12.0002V12H14.0002V5V3H12.0002H5.00024V5Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 337 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.1161 7.99992L2.55804 12.558L3.44193 13.4419L7.99999 8.88381L12.558 13.4419L13.4419 12.558L8.88387 7.99992L13.4419 3.44187L12.558 2.55798L7.99999 7.11604L3.44193 2.55798L2.55804 3.44187L7.1161 7.99992Z" fill="#C5C5C5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 374 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 3V13H13V3H3ZM12 12H4V4H12V12Z" fill="#C5C5C5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 163 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 7.99994V8.99994H3V7.99994H14Z" fill="#C5C5C5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 164 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 5V14H12V5H3ZM11 13H4V6H11V13Z" fill="#C5C5C5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 5H6V4H13V11H12V12H14V5V3H12H5V5Z" fill="#C5C5C5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 266 B |
|
@ -29,14 +29,14 @@
|
|||
#include <QtWidgets/qlabel.h>
|
||||
#include <QtWidgets/qpushbutton.h>
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utilities.h>
|
||||
|
||||
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<int>(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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|