Skip to content

Commit feeeb75

Browse files
committed
使用简易的无边框窗口,能改变大小和拖动即可。比较麻烦的细节问题不在这里处理了。
1 parent 0599d5b commit feeeb75

File tree

11 files changed

+343
-589
lines changed

11 files changed

+343
-589
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#include "Frameless/TaoFrameLessView.h"
2+
#include <QGuiApplication>
3+
#include <QQuickItem>
4+
#include <QScreen>
5+
#include <QWindow>
6+
7+
struct TaoFrameLessViewPrivate
8+
{
9+
uint32_t mPressedEdge;
10+
QRect mPressedGeometry;
11+
};
12+
TaoFrameLessView::TaoFrameLessView(QWindow* parent)
13+
: Super(parent)
14+
, d(std::make_unique<TaoFrameLessViewPrivate>())
15+
{
16+
setFlags(flags() | Qt::FramelessWindowHint | Qt::Window);
17+
setResizeMode(SizeRootObjectToView);
18+
}
19+
TaoFrameLessView::~TaoFrameLessView() { }
20+
QRect TaoFrameLessView::calcCenterGeo(const QRect& screenGeo, const QSize& normalSize)
21+
{
22+
int w = normalSize.width();
23+
int h = normalSize.height();
24+
int x = screenGeo.x() + (screenGeo.width() - w) / 2;
25+
int y = screenGeo.y() + (screenGeo.height() - h) / 2;
26+
if (screenGeo.width() < w)
27+
{
28+
x = screenGeo.x();
29+
w = screenGeo.width();
30+
}
31+
if (screenGeo.height() < h)
32+
{
33+
y = screenGeo.y();
34+
h = screenGeo.height();
35+
}
36+
37+
return { x, y, w, h };
38+
}
39+
void TaoFrameLessView::moveToScreenCenter()
40+
{
41+
auto geo = calcCenterGeo(screen()->availableGeometry(), size());
42+
if (minimumWidth() > geo.width() || minimumHeight() > geo.height())
43+
{
44+
setMinimumSize(geo.size());
45+
}
46+
setGeometry(geo);
47+
update();
48+
}
49+
50+
void TaoFrameLessView::move(int x, int y)
51+
{
52+
setPosition(x, y);
53+
}
54+
55+
QPoint TaoFrameLessView::mousePosition() const
56+
{
57+
return QCursor::pos();
58+
}
59+
60+
QPoint TaoFrameLessView::globalPosToWindowPos(const QPoint& pos) const
61+
{
62+
return mapFromGlobal(pos);
63+
}
64+
65+
void TaoFrameLessView::mousePressEvent(QMouseEvent* event)
66+
{
67+
auto mousePos = event->pos();
68+
emit mousePressed(mousePos.x(), mousePos.y(), event->button());
69+
d->mPressedEdge = getPosEdges(mousePos);
70+
if (d->mPressedEdge)
71+
{
72+
d->mPressedGeometry = geometry();
73+
}
74+
Super::mousePressEvent(event);
75+
}
76+
77+
void TaoFrameLessView::mouseReleaseEvent(QMouseEvent* event)
78+
{
79+
d->mPressedEdge = 0;
80+
d->mPressedGeometry = {};
81+
Super::mouseReleaseEvent(event);
82+
}
83+
84+
void TaoFrameLessView::mouseMoveEvent(QMouseEvent* event)
85+
{
86+
{
87+
// 实时计算光标
88+
auto edges = getPosEdges(event->pos());
89+
auto shape = getCursorShapeByEdge(edges);
90+
setCursor(shape);
91+
}
92+
{
93+
// 根据按下时位置执行move
94+
if (d->mPressedEdge)
95+
{
96+
doMoveTo(event->pos());
97+
}
98+
}
99+
Super::mouseMoveEvent(event);
100+
}
101+
Qt::CursorShape TaoFrameLessView::getCursorShapeByEdge(const Qt::Edges& edges)
102+
{
103+
switch (edges)
104+
{
105+
case Qt::Edge::TopEdge:
106+
case Qt::Edge::BottomEdge: {
107+
return Qt::CursorShape::SizeVerCursor;
108+
break;
109+
}
110+
case Qt::Edge::LeftEdge:
111+
case Qt::Edge::RightEdge: {
112+
return Qt::CursorShape::SizeHorCursor;
113+
break;
114+
}
115+
case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge):
116+
case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): {
117+
return Qt::CursorShape::SizeFDiagCursor;
118+
break;
119+
}
120+
case (Qt::Edge::TopEdge | Qt::Edge::RightEdge):
121+
case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): {
122+
return Qt::CursorShape::SizeBDiagCursor;
123+
break;
124+
}
125+
default:
126+
break;
127+
}
128+
return Qt::CursorShape::ArrowCursor;
129+
}
130+
131+
void TaoFrameLessView::doMoveTo(const QPoint& nowPos)
132+
{
133+
switch (d->mPressedEdge)
134+
{
135+
case Qt::Edge::TopEdge: {
136+
auto gPos = mapToGlobal(nowPos);
137+
auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), 0, 0);
138+
// setGeometry(newGeo);
139+
setY(newGeo.y());
140+
setHeight(newGeo.height());
141+
break;
142+
}
143+
case Qt::Edge::BottomEdge: {
144+
auto gPos = mapToGlobal(nowPos);
145+
auto newGeo = d->mPressedGeometry.adjusted(0, 0, 0, gPos.y() - d->mPressedGeometry.bottom());
146+
setGeometry(newGeo);
147+
break;
148+
}
149+
case Qt::Edge::LeftEdge: {
150+
auto gPos = mapToGlobal(nowPos);
151+
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, 0);
152+
setGeometry(newGeo);
153+
break;
154+
}
155+
case Qt::Edge::RightEdge: {
156+
auto gPos = mapToGlobal(nowPos);
157+
auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), 0);
158+
setGeometry(newGeo);
159+
break;
160+
}
161+
case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge): {
162+
auto gPos = mapToGlobal(nowPos);
163+
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), gPos.y() - d->mPressedGeometry.top(), 0, 0);
164+
setGeometry(newGeo);
165+
break;
166+
}
167+
case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): {
168+
auto gPos = mapToGlobal(nowPos);
169+
auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), gPos.y() - d->mPressedGeometry.bottom());
170+
setGeometry(newGeo);
171+
break;
172+
}
173+
case (Qt::Edge::TopEdge | Qt::Edge::RightEdge): {
174+
auto gPos = mapToGlobal(nowPos);
175+
auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), gPos.x() - d->mPressedGeometry.right(), 0);
176+
setGeometry(newGeo);
177+
break;
178+
}
179+
case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): {
180+
auto gPos = mapToGlobal(nowPos);
181+
auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, gPos.y() - d->mPressedGeometry.bottom());
182+
setGeometry(newGeo);
183+
break;
184+
}
185+
default:
186+
break;
187+
}
188+
}
189+
Qt::Edges TaoFrameLessView::getPosEdges(const QPoint& pos) const
190+
{
191+
uint32_t edges = 0;
192+
if (pos.x() < 0 || pos.x() > width())
193+
{
194+
return (Qt::Edges)edges;
195+
}
196+
if (pos.y() < 0 || pos.y() > height())
197+
{
198+
return (Qt::Edges)edges;
199+
}
200+
if (pos.x() <= borderWidth())
201+
{
202+
edges |= Qt::Edge::LeftEdge;
203+
}
204+
else if (width() - borderWidth() <= pos.x())
205+
{
206+
edges |= Qt::Edge::RightEdge;
207+
}
208+
if (pos.y() <= borderWidth())
209+
{
210+
edges |= Qt::Edge::TopEdge;
211+
}
212+
else if (height() - borderWidth() <= pos.y())
213+
{
214+
edges |= Qt::Edge::BottomEdge;
215+
}
216+
return (Qt::Edges)edges;
217+
}
Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,43 @@
11
#pragma once
2+
#include "Common/PropertyHelper.h"
23
#include "TaoCommonGlobal.h"
34
#include <QMouseEvent>
45
#include <QQuickView>
56
#include <QRegion>
67

7-
// 无边框窗口,主要用来实现自定义标题栏。
8-
// Windows平台支持拖动和改变大小,支持Aero效果
9-
// 非Windows平台,去掉边框,不做其它处理。由Qml模拟resize和拖动。
10-
class TaoFrameLessViewPrivate;
8+
// 简易的无边框窗口,主要用来实现自定义标题栏。
9+
// 支持标题栏拖动和边缘改变大小,不做深度处理
10+
struct TaoFrameLessViewPrivate;
1111
class TAO_API TaoFrameLessView : public QQuickView
1212
{
1313
Q_OBJECT
1414
using Super = QQuickView;
15-
Q_PROPERTY(bool isMax READ isMax NOTIFY isMaxChanged)
16-
Q_PROPERTY(bool isFull READ isFull NOTIFY isFullChanged)
15+
AUTO_PROPERTY(int, borderWidth, 4)
1716
public:
1817
explicit TaoFrameLessView(QWindow* parent = nullptr);
1918
~TaoFrameLessView();
20-
void moveToScreenCenter();
21-
bool isMax() const;
22-
bool isFull() const;
23-
QQuickItem* titleItem() const;
2419

2520
static QRect calcCenterGeo(const QRect& screenGeo, const QSize& normalSize);
2621
public slots:
27-
void setIsMax(bool isMax);
28-
void setIsFull(bool isFull);
29-
void setTitleItem(QQuickItem* item);
22+
void moveToScreenCenter();
23+
void move(int x, int y);
24+
25+
QPoint mousePosition() const;
3026

27+
QPoint globalPosToWindowPos(const QPoint& pos) const;
3128
signals:
32-
void isMaxChanged(bool isMax);
33-
void isFullChanged(bool isFull);
3429
void mousePressed(int xPos, int yPos, int button);
3530

3631
protected:
37-
void showEvent(QShowEvent* e) override;
38-
void resizeEvent(QResizeEvent* e) override;
39-
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
40-
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
41-
#else
42-
bool nativeEvent(const QByteArray& eventType, void* message, long* result) override;
43-
#endif
44-
void mousePressEvent(QMouseEvent* event) override
45-
{
46-
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
47-
emit mousePressed(event->position().x(), event->position().y(), event->button());
48-
#else
49-
emit mousePressed(event->x(), event->y(), event->button());
50-
#endif
51-
Super::mousePressEvent(event);
52-
}
32+
void mousePressEvent(QMouseEvent* event) override;
33+
void mouseReleaseEvent(QMouseEvent* event) override;
34+
void mouseMoveEvent(QMouseEvent* event) override;
35+
36+
Qt::Edges getPosEdges(const QPoint& pos) const;
37+
Qt::CursorShape getCursorShapeByEdge(const Qt::Edges& edges);
38+
39+
void doMoveTo(const QPoint& nowPos);
5340

5441
private:
55-
TaoFrameLessViewPrivate* d;
42+
std::unique_ptr<TaoFrameLessViewPrivate> d;
5643
};

0 commit comments

Comments
 (0)