-
Notifications
You must be signed in to change notification settings - Fork 366
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
使用简易的无边框窗口,能改变大小和拖动即可。比较麻烦的细节问题不在这里处理了。
- Loading branch information
Showing
11 changed files
with
343 additions
and
589 deletions.
There are no files selected for viewing
217 changes: 217 additions & 0 deletions
217
3rdparty/TaoCommon/src/TaoCommon/Frameless/TaoFrameLessView.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#include "Frameless/TaoFrameLessView.h" | ||
#include <QGuiApplication> | ||
#include <QQuickItem> | ||
#include <QScreen> | ||
#include <QWindow> | ||
|
||
struct TaoFrameLessViewPrivate | ||
{ | ||
uint32_t mPressedEdge; | ||
QRect mPressedGeometry; | ||
}; | ||
TaoFrameLessView::TaoFrameLessView(QWindow* parent) | ||
: Super(parent) | ||
, d(std::make_unique<TaoFrameLessViewPrivate>()) | ||
{ | ||
setFlags(flags() | Qt::FramelessWindowHint | Qt::Window); | ||
setResizeMode(SizeRootObjectToView); | ||
} | ||
TaoFrameLessView::~TaoFrameLessView() { } | ||
QRect TaoFrameLessView::calcCenterGeo(const QRect& screenGeo, const QSize& normalSize) | ||
{ | ||
int w = normalSize.width(); | ||
int h = normalSize.height(); | ||
int x = screenGeo.x() + (screenGeo.width() - w) / 2; | ||
int y = screenGeo.y() + (screenGeo.height() - h) / 2; | ||
if (screenGeo.width() < w) | ||
{ | ||
x = screenGeo.x(); | ||
w = screenGeo.width(); | ||
} | ||
if (screenGeo.height() < h) | ||
{ | ||
y = screenGeo.y(); | ||
h = screenGeo.height(); | ||
} | ||
|
||
return { x, y, w, h }; | ||
} | ||
void TaoFrameLessView::moveToScreenCenter() | ||
{ | ||
auto geo = calcCenterGeo(screen()->availableGeometry(), size()); | ||
if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) | ||
{ | ||
setMinimumSize(geo.size()); | ||
} | ||
setGeometry(geo); | ||
update(); | ||
} | ||
|
||
void TaoFrameLessView::move(int x, int y) | ||
{ | ||
setPosition(x, y); | ||
} | ||
|
||
QPoint TaoFrameLessView::mousePosition() const | ||
{ | ||
return QCursor::pos(); | ||
} | ||
|
||
QPoint TaoFrameLessView::globalPosToWindowPos(const QPoint& pos) const | ||
{ | ||
return mapFromGlobal(pos); | ||
} | ||
|
||
void TaoFrameLessView::mousePressEvent(QMouseEvent* event) | ||
{ | ||
auto mousePos = event->pos(); | ||
emit mousePressed(mousePos.x(), mousePos.y(), event->button()); | ||
d->mPressedEdge = getPosEdges(mousePos); | ||
if (d->mPressedEdge) | ||
{ | ||
d->mPressedGeometry = geometry(); | ||
} | ||
Super::mousePressEvent(event); | ||
} | ||
|
||
void TaoFrameLessView::mouseReleaseEvent(QMouseEvent* event) | ||
{ | ||
d->mPressedEdge = 0; | ||
d->mPressedGeometry = {}; | ||
Super::mouseReleaseEvent(event); | ||
} | ||
|
||
void TaoFrameLessView::mouseMoveEvent(QMouseEvent* event) | ||
{ | ||
{ | ||
// 实时计算光标 | ||
auto edges = getPosEdges(event->pos()); | ||
auto shape = getCursorShapeByEdge(edges); | ||
setCursor(shape); | ||
} | ||
{ | ||
// 根据按下时位置执行move | ||
if (d->mPressedEdge) | ||
{ | ||
doMoveTo(event->pos()); | ||
} | ||
} | ||
Super::mouseMoveEvent(event); | ||
} | ||
Qt::CursorShape TaoFrameLessView::getCursorShapeByEdge(const Qt::Edges& edges) | ||
{ | ||
switch (edges) | ||
{ | ||
case Qt::Edge::TopEdge: | ||
case Qt::Edge::BottomEdge: { | ||
return Qt::CursorShape::SizeVerCursor; | ||
break; | ||
} | ||
case Qt::Edge::LeftEdge: | ||
case Qt::Edge::RightEdge: { | ||
return Qt::CursorShape::SizeHorCursor; | ||
break; | ||
} | ||
case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge): | ||
case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): { | ||
return Qt::CursorShape::SizeFDiagCursor; | ||
break; | ||
} | ||
case (Qt::Edge::TopEdge | Qt::Edge::RightEdge): | ||
case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): { | ||
return Qt::CursorShape::SizeBDiagCursor; | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
return Qt::CursorShape::ArrowCursor; | ||
} | ||
|
||
void TaoFrameLessView::doMoveTo(const QPoint& nowPos) | ||
{ | ||
switch (d->mPressedEdge) | ||
{ | ||
case Qt::Edge::TopEdge: { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), 0, 0); | ||
// setGeometry(newGeo); | ||
setY(newGeo.y()); | ||
setHeight(newGeo.height()); | ||
break; | ||
} | ||
case Qt::Edge::BottomEdge: { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(0, 0, 0, gPos.y() - d->mPressedGeometry.bottom()); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case Qt::Edge::LeftEdge: { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, 0); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case Qt::Edge::RightEdge: { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), 0); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge): { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), gPos.y() - d->mPressedGeometry.top(), 0, 0); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), gPos.y() - d->mPressedGeometry.bottom()); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case (Qt::Edge::TopEdge | Qt::Edge::RightEdge): { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), gPos.x() - d->mPressedGeometry.right(), 0); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): { | ||
auto gPos = mapToGlobal(nowPos); | ||
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, gPos.y() - d->mPressedGeometry.bottom()); | ||
setGeometry(newGeo); | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
} | ||
Qt::Edges TaoFrameLessView::getPosEdges(const QPoint& pos) const | ||
{ | ||
uint32_t edges = 0; | ||
if (pos.x() < 0 || pos.x() > width()) | ||
{ | ||
return (Qt::Edges)edges; | ||
} | ||
if (pos.y() < 0 || pos.y() > height()) | ||
{ | ||
return (Qt::Edges)edges; | ||
} | ||
if (pos.x() <= borderWidth()) | ||
{ | ||
edges |= Qt::Edge::LeftEdge; | ||
} | ||
else if (width() - borderWidth() <= pos.x()) | ||
{ | ||
edges |= Qt::Edge::RightEdge; | ||
} | ||
if (pos.y() <= borderWidth()) | ||
{ | ||
edges |= Qt::Edge::TopEdge; | ||
} | ||
else if (height() - borderWidth() <= pos.y()) | ||
{ | ||
edges |= Qt::Edge::BottomEdge; | ||
} | ||
return (Qt::Edges)edges; | ||
} |
51 changes: 19 additions & 32 deletions
51
3rdparty/TaoCommon/src/TaoCommon/Frameless/TaoFrameLessView.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,43 @@ | ||
#pragma once | ||
#include "Common/PropertyHelper.h" | ||
#include "TaoCommonGlobal.h" | ||
#include <QMouseEvent> | ||
#include <QQuickView> | ||
#include <QRegion> | ||
|
||
// 无边框窗口,主要用来实现自定义标题栏。 | ||
// Windows平台支持拖动和改变大小,支持Aero效果 | ||
// 非Windows平台,去掉边框,不做其它处理。由Qml模拟resize和拖动。 | ||
class TaoFrameLessViewPrivate; | ||
// 简易的无边框窗口,主要用来实现自定义标题栏。 | ||
// 支持标题栏拖动和边缘改变大小,不做深度处理 | ||
struct TaoFrameLessViewPrivate; | ||
class TAO_API TaoFrameLessView : public QQuickView | ||
{ | ||
Q_OBJECT | ||
using Super = QQuickView; | ||
Q_PROPERTY(bool isMax READ isMax NOTIFY isMaxChanged) | ||
Q_PROPERTY(bool isFull READ isFull NOTIFY isFullChanged) | ||
AUTO_PROPERTY(int, borderWidth, 4) | ||
public: | ||
explicit TaoFrameLessView(QWindow* parent = nullptr); | ||
~TaoFrameLessView(); | ||
void moveToScreenCenter(); | ||
bool isMax() const; | ||
bool isFull() const; | ||
QQuickItem* titleItem() const; | ||
|
||
static QRect calcCenterGeo(const QRect& screenGeo, const QSize& normalSize); | ||
public slots: | ||
void setIsMax(bool isMax); | ||
void setIsFull(bool isFull); | ||
void setTitleItem(QQuickItem* item); | ||
void moveToScreenCenter(); | ||
void move(int x, int y); | ||
|
||
QPoint mousePosition() const; | ||
|
||
QPoint globalPosToWindowPos(const QPoint& pos) const; | ||
signals: | ||
void isMaxChanged(bool isMax); | ||
void isFullChanged(bool isFull); | ||
void mousePressed(int xPos, int yPos, int button); | ||
|
||
protected: | ||
void showEvent(QShowEvent* e) override; | ||
void resizeEvent(QResizeEvent* e) 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 | ||
void mousePressEvent(QMouseEvent* event) override | ||
{ | ||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) | ||
emit mousePressed(event->position().x(), event->position().y(), event->button()); | ||
#else | ||
emit mousePressed(event->x(), event->y(), event->button()); | ||
#endif | ||
Super::mousePressEvent(event); | ||
} | ||
void mousePressEvent(QMouseEvent* event) override; | ||
void mouseReleaseEvent(QMouseEvent* event) override; | ||
void mouseMoveEvent(QMouseEvent* event) override; | ||
|
||
Qt::Edges getPosEdges(const QPoint& pos) const; | ||
Qt::CursorShape getCursorShapeByEdge(const Qt::Edges& edges); | ||
|
||
void doMoveTo(const QPoint& nowPos); | ||
|
||
private: | ||
TaoFrameLessViewPrivate* d; | ||
std::unique_ptr<TaoFrameLessViewPrivate> d; | ||
}; |
Oops, something went wrong.