2022-08-25 18:43:03 +08:00
|
|
|
#include "basewin.h"
|
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QIcon>
|
|
|
|
#include <QMouseEvent>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QPainterPath>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QScreen>
|
|
|
|
|
|
|
|
BaseWinBase::BaseWinBase(QWidget *that) : that(that) {
|
|
|
|
that->setWindowFlag(Qt::FramelessWindowHint);
|
|
|
|
that->setAttribute(Qt::WA_TranslucentBackground);
|
|
|
|
that->setMouseTracking(true);
|
|
|
|
auto layout = new QBoxLayout(QBoxLayout::TopToBottom, that);
|
|
|
|
layout->setContentsMargins(8,8,8,8);
|
|
|
|
layout->setSpacing(0);
|
|
|
|
layout->addWidget(center = new QWidget());
|
|
|
|
center->installEventFilter(that);
|
|
|
|
}
|
|
|
|
|
2022-09-08 23:22:59 +08:00
|
|
|
QBoxLayout *BaseWinBase::addBtns(QBoxLayout *hBox) {
|
2022-08-25 18:43:03 +08:00
|
|
|
if(hBox->count()==0) hBox->addStretch();
|
2023-08-24 16:55:38 +08:00
|
|
|
//最小化按钮
|
|
|
|
auto btn = new QPushButton;
|
2022-12-16 15:08:53 +08:00
|
|
|
btn->setIcon(QIcon(":/imgs/macos-minimize.png"));
|
|
|
|
btn->setIconSize(QSize(20,20));
|
2023-08-24 16:55:38 +08:00
|
|
|
btn->setStyleSheet("QPushButton{padding: 1; border:none; background-color:#222;} QPushButton:hover{background-color:#515151;}QPushButton:pressed{background-color:#515151;}");
|
2022-08-25 18:43:03 +08:00
|
|
|
that->connect(btn, &QPushButton::clicked, that, &BaseWin::showMinimized);
|
|
|
|
hBox->addWidget(btn);
|
2023-08-24 16:55:38 +08:00
|
|
|
//最大化按钮
|
|
|
|
btn = new QPushButton;
|
|
|
|
btn->setIcon(QIcon(":/imgs/macos-max.png"));
|
|
|
|
btn->setIconSize(QSize(20,20));
|
|
|
|
btn->setStyleSheet("QPushButton{padding: 1; border:none; background-color:#222;} QPushButton:hover{background-color:#515151;} QPushButton:pressed{background-color:#515151;}");
|
|
|
|
that->connect(btn, &QPushButton::clicked, that, [=] {
|
|
|
|
if(that->windowState() == Qt::WindowMaximized) {
|
|
|
|
that->setWindowState(Qt::WindowNoState); // 恢复正常状态
|
|
|
|
btn->setIcon(QIcon(":/imgs/macos-max.png"));
|
|
|
|
} else {
|
|
|
|
that->setWindowState(Qt::WindowMaximized); // 最大化
|
|
|
|
btn->setIcon(QIcon(":/imgs/macos-max1.png"));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
hBox->addWidget(btn);
|
|
|
|
//关闭按钮
|
|
|
|
btn = new QPushButton;
|
2022-12-16 15:08:53 +08:00
|
|
|
btn->setIcon(QIcon(":/imgs/close.png"));
|
|
|
|
btn->setIconSize(QSize(20,20));
|
2023-08-24 16:55:38 +08:00
|
|
|
btn->setStyleSheet("QPushButton{padding: 1; border:none; background-color:#222;} QPushButton:hover{background-color:#515151;} QPushButton:pressed{background-color:#515151;}");
|
2022-08-25 18:43:03 +08:00
|
|
|
that->connect(btn, &QPushButton::clicked, that, &BaseWin::close);
|
|
|
|
hBox->addWidget(btn);
|
|
|
|
return hBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseWinBase::paintEvent() {
|
|
|
|
QPainter painter(that);
|
|
|
|
painter.setRenderHints(QPainter::Antialiasing);
|
|
|
|
auto pal = that->palette();
|
|
|
|
auto back = pal.window();
|
|
|
|
bool isMax = that->isMaximized();
|
|
|
|
if(isMax) painter.fillRect(that->rect(), back);
|
|
|
|
else {
|
|
|
|
QPainterPath borderPath = QPainterPath();
|
|
|
|
borderPath.addRoundedRect(0.5, 0.5, that->width()-1, that->height()-1, borderRadius, borderRadius);
|
|
|
|
painter.fillPath(borderPath, back);
|
|
|
|
painter.strokePath(borderPath, isActive ? borderPenAct : borderPenUnact);
|
|
|
|
}
|
|
|
|
QString title = that->windowTitle();
|
|
|
|
if(! title.isEmpty()) {
|
2023-07-28 14:48:41 +08:00
|
|
|
painter.setPen(isActive ? pal.windowText().color() : Qt::gray);
|
2022-08-25 18:43:03 +08:00
|
|
|
isMax ? painter.drawText(titlePos.x()-8, titlePos.y()-8, title) : painter.drawText(titlePos, title);
|
|
|
|
}
|
|
|
|
auto icon = that->windowIcon();
|
|
|
|
if(! icon.isNull()) isMax ? icon.paint(&painter, iconRect.translated(-8, -8)) : icon.paint(&painter, iconRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void transPos(QPoint &pos, QScreen *src, QScreen *dst) {
|
|
|
|
auto ratio = src->devicePixelRatio();
|
|
|
|
if(ratio != 1) {
|
|
|
|
auto geo = src->geometry();
|
|
|
|
pos.setX((pos.x() - geo.x()) * ratio + geo.x());
|
|
|
|
pos.setY((pos.y() - geo.y()) * ratio + geo.y());
|
|
|
|
}
|
|
|
|
ratio = dst->devicePixelRatio();
|
|
|
|
if(ratio != 1) {
|
|
|
|
auto geo = dst->geometry();
|
|
|
|
pos.setX((pos.x() - geo.x()) / ratio + geo.x());
|
|
|
|
pos.setY((pos.y() - geo.y()) / ratio + geo.y());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void BaseWinBase::mousePressEvent(QMouseEvent *e) {
|
|
|
|
if(e->button() != Qt::LeftButton) return;
|
|
|
|
setFrmSec(e->pos());
|
|
|
|
if(mFrmSec==Qt::TitleBarArea) {mPressRel = that->pos() - e->globalPos(); mSize = that->size();}
|
|
|
|
else if(mFrmSec==Qt::TopSection || mFrmSec==Qt::LeftSection || mFrmSec==Qt::TopLeftSection) mPressRel = that->pos() - e->globalPos();
|
|
|
|
else if(mFrmSec==Qt::BottomRightSection) mPressRel = QPoint(that->width() - e->globalX(), that->height() - e->globalY());
|
|
|
|
else if(mFrmSec==Qt::RightSection ) mPressRel = QPoint(that->width() - e->globalX(), that->height() );
|
|
|
|
else if(mFrmSec==Qt::BottomSection ) mPressRel = QPoint(that->width() , that->height() - e->globalY());
|
|
|
|
else if(mFrmSec==Qt::TopRightSection ) mPressRel = that->geometry().topRight() - e->globalPos();
|
|
|
|
else if(mFrmSec==Qt::BottomLeftSection ) mPressRel = that->geometry().bottomLeft() - e->globalPos();
|
|
|
|
else if(mFrmSec==Qt::NoSection) mPressRel.setX(INT_MIN);
|
|
|
|
}
|
|
|
|
void BaseWinBase::mouseReleaseEvent(QMouseEvent *e) {
|
|
|
|
if(e->button() != Qt::LeftButton) return;
|
|
|
|
mPressRel.setX(INT_MIN);
|
|
|
|
}
|
|
|
|
void BaseWinBase::mouseMoveEvent(QMouseEvent *e) {
|
|
|
|
if(e->buttons() & Qt::LeftButton) {
|
|
|
|
if(mFrmSec==Qt::NoSection || mPressRel.x()==INT_MIN) return;
|
|
|
|
if(that->isMaximized()) return;
|
|
|
|
if(mFrmSec==Qt::TitleBarArea) {
|
|
|
|
auto pos = e->globalPos();
|
|
|
|
auto screenMouse = QGuiApplication::screenAt(pos);
|
|
|
|
if(screenMouse==0) return;
|
|
|
|
auto screen = that->screen();
|
|
|
|
if(screenMouse!=screen) transPos(pos, screenMouse, screen);
|
|
|
|
that->setGeometry(QRect(pos + mPressRel, mSize));
|
|
|
|
} else if(mFrmSec==Qt::BottomRightSection) that->resize(mPressRel.rx() + e->globalX(), mPressRel.ry() + e->globalY());
|
|
|
|
else if(mFrmSec==Qt::RightSection ) that->resize(mPressRel.rx() + e->globalX(), mPressRel.ry() );
|
|
|
|
else if(mFrmSec==Qt::BottomSection ) that->resize(mPressRel.rx() , mPressRel.ry() + e->globalY());
|
|
|
|
else {
|
|
|
|
auto geo = that->geometry();
|
|
|
|
if(mFrmSec==Qt::LeftSection) geo.setLeft(e->globalX() + mPressRel.rx());
|
|
|
|
else if(mFrmSec==Qt::TopSection) geo.setTop(e->globalY() + mPressRel.ry());
|
|
|
|
else if(mFrmSec==Qt::TopLeftSection) geo.setTopLeft(e->globalPos() + mPressRel);
|
|
|
|
else if(mFrmSec==Qt::TopRightSection) geo.setTopRight(e->globalPos() + mPressRel);
|
|
|
|
else if(mFrmSec==Qt::BottomLeftSection) geo.setBottomLeft(e->globalPos() + mPressRel);
|
|
|
|
that->setGeometry(geo);
|
|
|
|
}
|
|
|
|
} else setFrmSec(e->pos());
|
|
|
|
}
|
|
|
|
void BaseWinBase::setFrmSec(const QPoint &pos) {
|
|
|
|
if(that->isMaximized()) return;
|
|
|
|
if(pos.y()<8) {
|
|
|
|
if(pos.x()<16) setFrmSecIfNeed(Qt::TopLeftSection, Qt::SizeFDiagCursor);
|
|
|
|
else if(pos.x()<that->width()-16) setFrmSecIfNeed(Qt::TopSection, Qt::SizeVerCursor);
|
|
|
|
else setFrmSecIfNeed(Qt::TopRightSection, Qt::SizeBDiagCursor);
|
|
|
|
} else if(pos.y()>=that->height()-8) {
|
|
|
|
if(pos.x()<16) setFrmSecIfNeed(Qt::BottomLeftSection, Qt::SizeBDiagCursor);
|
|
|
|
else if(pos.x()<that->width()-16) setFrmSecIfNeed(Qt::BottomSection, Qt::SizeVerCursor);
|
|
|
|
else setFrmSecIfNeed(Qt::BottomRightSection, Qt::SizeFDiagCursor);
|
|
|
|
} else if(pos.x()<8) {
|
|
|
|
if(pos.y()<16) setFrmSecIfNeed(Qt::TopLeftSection, Qt::SizeFDiagCursor);
|
|
|
|
else if(pos.y()<that->height()-16) setFrmSecIfNeed(Qt::LeftSection, Qt::SizeHorCursor);
|
|
|
|
else setFrmSecIfNeed(Qt::BottomLeftSection, Qt::SizeBDiagCursor);
|
|
|
|
} else if(pos.x()>=that->width()-8) {
|
|
|
|
if(pos.y()<16) setFrmSecIfNeed(Qt::TopRightSection, Qt::SizeBDiagCursor);
|
|
|
|
else if(pos.y()<that->height()-16) setFrmSecIfNeed(Qt::RightSection, Qt::SizeHorCursor);
|
|
|
|
else setFrmSecIfNeed(Qt::BottomRightSection, Qt::SizeFDiagCursor);
|
|
|
|
} else setFrmSecIfNeed(Qt::TitleBarArea, Qt::ArrowCursor);
|
|
|
|
}
|
|
|
|
void BaseWinBase::setFrmSecIfNeed(Qt::WindowFrameSection frmSec, Qt::CursorShape cursor) {
|
|
|
|
if(mFrmSec==frmSec) return;
|
|
|
|
mFrmSec = frmSec;
|
|
|
|
if(cursor==Qt::ArrowCursor) that->unsetCursor();
|
|
|
|
else that->setCursor(cursor);
|
|
|
|
}
|
|
|
|
void BaseWinBase::leaveEvent() {
|
|
|
|
setFrmSecIfNeed(Qt::NoSection, Qt::ArrowCursor);
|
|
|
|
mPressRel.setX(INT_MIN);
|
|
|
|
}
|
|
|
|
void BaseWinBase::mouseDoubleClickEvent(QMouseEvent *e) {
|
|
|
|
if(e->y() > 32) return;
|
|
|
|
mPressRel.setX(INT_MIN);
|
|
|
|
mFrmSec = Qt::NoSection;
|
|
|
|
if(that->isMaximized()) that->setWindowState(that->windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen));
|
|
|
|
else that->setWindowState((that->windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized);
|
|
|
|
}
|
|
|
|
bool BaseWinBase::eventFilter(QObject *watched, QEvent *e) {
|
|
|
|
if(e->type()==QEvent::Enter && watched==center) {
|
|
|
|
setFrmSecIfNeed(Qt::NoSection, Qt::ArrowCursor);
|
|
|
|
mPressRel.setX(INT_MIN);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void BaseWinBase::changeEvent(QEvent *e) {
|
|
|
|
if(e->type()==QEvent::WindowStateChange) that->isMaximized() ? that->layout()->setContentsMargins(0,0,0,0) : that->layout()->setContentsMargins(8,8,8,8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _MSC_VER //MSVC编译器
|
|
|
|
#include <windows.h>
|
|
|
|
bool BaseWinBase::nativeEvent(const QByteArray &eventType, void *message) {
|
|
|
|
if(eventType=="windows_generic_MSG") {
|
|
|
|
MSG *msg = (MSG*)message;
|
|
|
|
if(msg->message==WM_NCACTIVATE) {
|
|
|
|
isActive = msg->wParam;
|
|
|
|
that->repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|