#ifndef DESKDOCKWIDGET_H
#define DESKDOCKWIDGET_H
#include "qtinclude.h"
class FloatingWidget : public QWidget
{
Q_OBJECT
public:
enum FloatingFeature
{
NoArea = 0x0,
TopArea = 0x1,
BottomArea = 0x2,
LeftArea = 0x4,
RightArea = 0x8,
AllArea = 0xf,
};
public:
explicit FloatingWidget(FloatingFeature D, QWidget * parent = nullptr, Qt::WindowFlags flags = 0);
protected:
virtual void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
virtual void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
virtual void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
virtual void enterEvent(QEvent *) Q_DECL_OVERRIDE;
virtual void leaveEvent (QEvent *) Q_DECL_OVERRIDE;
QSize sizeHint() const{ return QSize(128, 142);}
private slots:
void setDirection(FloatingFeature D);
void HideDockWidget();
void ShowDockWidget();
private:
void MoveWindow(const QPoint & start, const QPoint & end, unsigned int step = 5);
private:
bool m_IsVisible = true;
FloatingFeature m_feature;
QPoint m_dragPosition;
QPoint m_RecoverPosition;
QTimer * m_timer = nullptr;
};
#endif // DESKDOCKWIDGET_H
#include "deskdockwidget.h"
#include <QtCore/QtMath>
#include <QtCore/QPropertyAnimation>
#include <QtWidgets/QDesktopWidget>
#define TEST_BIT(a, b) a & b
#define HIDE_BORDER 1 //隐藏时显示border
#define CHECK_BORDER 2 //边界检测宽度
FloatingWidget::FloatingWidget(FloatingFeature D, QWidget * parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
, m_feature(D)
{
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
setMouseTracking(true);
}
void FloatingWidget::MoveWindow(const QPoint & start, const QPoint & end, unsigned int step)
{
QPoint distance = end - start;
QPoint stepPos, stepOne;
if (end.x() == start.x())
{
stepOne.setY(step * (distance.y() > 0 ? 1 : -1));
}
else
{
stepOne.setX(step * (distance.x() > 0 ? 1 : -1));
}
stepPos = stepOne;
int disLenght = distance.manhattanLength();
while (stepPos.manhattanLength() <= disLenght)
{
move(start + stepPos);
stepPos += stepOne;
}
move(end);
m_RecoverPosition = start;
}
void FloatingWidget::setDirection(FloatingFeature D)
{
m_feature = D;
}
void FloatingWidget::paintEvent(QPaintEvent *e)
{
QPainter p(this);
QPixmap img(":/images/m.png");
p.setBrush(QBrush(img));
p.setPen(QColor("#b5b4c9"));
p.drawRoundedRect(0,0,width() - 1,height() - 1, 8, 8);
}
void FloatingWidget::HideDockWidget()
{
if (m_IsVisible == false)
{
return;
}
m_IsVisible = false;
int curHeight = height();
int curWidth = width();
QDesktopWidget * desktop = qApp->desktop();
QRect rect = desktop->screenGeometry(this);
if (frameGeometry().left() - CHECK_BORDER <= rect.top()
&& TEST_BIT(m_feature, LeftArea))
{
MoveWindow(pos(), pos() - QPoint(curWidth - HIDE_BORDER, 0));
}
else if (frameGeometry().right() + CHECK_BORDER >= rect.right()
&& TEST_BIT(m_feature, RightArea))
{
MoveWindow(pos(), pos() + QPoint(curWidth - HIDE_BORDER, 0));
}
else if (frameGeometry().top() - CHECK_BORDER <= rect.top()
&& TEST_BIT(m_feature, TopArea))
{
MoveWindow(pos(), pos() - QPoint(0, curHeight - HIDE_BORDER));
}
else
{
m_IsVisible = true;
}
if (m_IsVisible == false)
{
if (m_timer && m_timer->isActive())
{
m_timer->stop();
}
}
}
void FloatingWidget::ShowDockWidget()
{
if (m_IsVisible)
{
return;
}
m_IsVisible = true;
int curHeight = height();
int curWidth = width();
QDesktopWidget * desktop = qApp->desktop();
QRect rect = desktop->screenGeometry(this);
QRect frameRect = frameGeometry();
if (frameRect.left() == m_RecoverPosition.x() - (curWidth - HIDE_BORDER)
&& TEST_BIT(m_feature, LeftArea))
{
MoveWindow(pos(), m_RecoverPosition);
}
else if (frameRect.left() == m_RecoverPosition.x() + (curWidth - HIDE_BORDER)
&& TEST_BIT(m_feature, RightArea))
{
MoveWindow(pos(), m_RecoverPosition);
}
else if (frameRect.top() == m_RecoverPosition.y() - (curHeight - HIDE_BORDER)
&& TEST_BIT(m_feature, TopArea))
{
MoveWindow(pos(), m_RecoverPosition);
}
else
{
m_IsVisible = false;
}
}
void FloatingWidget::mousePressEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton)
{
m_dragPosition = e->globalPos() - frameGeometry().topLeft();
e->accept();
}
}
void FloatingWidget::mouseMoveEvent(QMouseEvent * event)
{
if (event->buttons() & Qt::LeftButton)
{
QPoint pos = event->globalPos() - m_dragPosition;
QDesktopWidget * desktop = qApp->desktop();
QRect rect = desktop->screenGeometry(QCursor::pos());
QRect frameRect = frameGeometry();
if (rect.top() >= pos.y())//修正顶端位置
{
pos.setY(rect.top());
}
if (rect.left()>= pos.x())//修正左侧位置
{
int leftScreenNumber = desktop->screenNumber(pos - QPoint(width(), 0));
if (desktop->screenGeometry(leftScreenNumber).contains((pos - QPoint(width(), 0))) == false)
{
pos.setX(rect.left());
}
}
if (rect.right() <= pos.x() + frameRect.width())//修正右侧位置
{
int rightScreenNumber = desktop->screenNumber(pos + QPoint(width(), 0));
if (desktop->screenGeometry(rightScreenNumber).contains((pos + QPoint(width(), 0))) == false)
{
pos.setX(rect.right() - frameRect.width());
}
}
move(pos);
event->accept();
}
}
void FloatingWidget::mouseReleaseEvent(QMouseEvent * event)
{
QWidget::mouseReleaseEvent(event);
}
void FloatingWidget::enterEvent(QEvent * e)
{
if (m_timer && m_timer->isActive())
{
m_timer->stop();
}
ShowDockWidget();
QWidget::enterEvent(e);
}
void FloatingWidget::leaveEvent(QEvent * e)
{
QPoint mousePos = mapFromGlobal(QCursor::pos());
if (rect().contains(mousePos) == false
&& mousePos.x() != rect().width())
{
HideDockWidget();
}
else
{
if (m_timer == nullptr)
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, [this]{
QPoint mousePos = mapFromGlobal(QCursor::pos());
if (this->rect().contains(mousePos) == false
&& mousePos.x() != rect().width())
{
HideDockWidget();
}
});
}
m_timer->start(500);
}
QWidget::leaveEvent(e);
}
#include "deskdockwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FloatingWidget *w = new FloatingWidget(FloatingWidget::AllArea);
w->show();
return a.exec();
}
#ifndef __QT_ALL_INCLUDES__
#define __QT_ALL_INCLUDES__
#include <QtWidgets/QWidget>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDesktopWidget>
#include <QTimer>
#include <QCursor>
#include <QPainter>
#include <QMouseEvent>
#include <QPixmap>
#include <Windows.h>
#endif