QT自定义Widget实现鼠标拖动窗口移动位置及鼠标拖拽窗口边缘窗口大小改变
通过setWindowFlags(Qt::FramelessWindowHint);可以隐藏掉Qt自带的窗口标题,这句话写的简单,可是窗口引起的改变可不少:
- 最直观的,标题栏没了
- 间接的,没了标题栏,也没有办法拖拽标题栏移动窗口位置了
- 隐含的,鼠标移动到窗口边缘时,鼠标形态不再改变,无法实现鼠标拖拽窗口边缘改变窗口大小
So,想使用自定义的窗体也是需要付出代价的。如果我既想自定义窗体,也想要让自定义的窗体,兼具鼠标拖动窗口移动位置及鼠标拖拽窗口边缘窗口大小改变的特性呢,那就继续往下看吧。
最新get到一个比较有趣的实现方式,想借着实现以上两个功能点来秀一哈。
下面直接上代码:
实现鼠标拖拽移动窗体的代码:
/*MoveWgt.h*/
#ifndef MOVEWGT_H
#define MOVEWGT_H
#include <QObject>
#include <QWidget>
#include <QMouseEvent>
#define Move_Wgt \
private: \
void mousePressEvent(QMouseEvent *event) \
{ \
m_isPressed = true; \
m_startMovePos = event->globalPos()-this->frameGeometry().topLeft(); \
} \
void mouseMoveEvent(QMouseEvent *event) \
{ \
if(m_isPressed) \
{ \
move(this->mapToGlobal(event->pos() - m_startMovePos)); \
} \
} \
void mouseReleaseEvent(QMouseEvent *) \
{ \
m_isPressed = false; \
} \
private: \
bool m_isPressed = false; \
QPoint m_startMovePos;
#endif // MOVEWGT_H
实现拖拽改变窗体大小的代码:
/*DragWgt.h*/
#ifndef DRAGWGT1_H
#define DRAGWGT1_H
#include <QObject>
#include <QWidget>
#include <QMouseEvent>
#include "Windows.h"
#define Drag_Wgt \
bool nativeEvent(const QByteArray &eventType, void *message, long *result) \
{ \
MSG* pMsg = (MSG*)message; \
switch (pMsg->message) \
{ \
case WM_NCHITTEST: \
{ \
QPoint pos = mapFromGlobal(QPoint(LOWORD(pMsg->lParam), HIWORD(pMsg->lParam))); \
bool bHorLeft = pos.x() < g_nBorder; \
bool bHorRight = pos.x() > width() - g_nBorder; \
bool bVertTop = pos.y() < g_nBorder; \
bool bVertBottom = pos.y() > height() - g_nBorder; \
if (bHorLeft && bVertTop) \
{ \
*result = HTTOPLEFT; \
} \
else if (bHorLeft && bVertBottom) \
{ \
*result = HTBOTTOMLEFT; \
} \
else if (bHorRight && bVertTop) \
{ \
*result = HTTOPRIGHT; \
} \
else if (bHorRight && bVertBottom) \
{ \
*result = HTBOTTOMRIGHT; \
} \
else if (bHorLeft) \
{ \
*result = HTLEFT; \
} \
else if (bHorRight) \
{ \
*result = HTRIGHT; \
} \
else if (bVertTop) \
{ \
*result = HTTOP; \
} \
else if (bVertBottom) \
{ \
*result = HTBOTTOM; \
} \
else \
{ \
return false; \
} \
return true; \
} \
break; \
default: \
break; \
} \
return QWidget::nativeEvent(eventType, message, result); \
} \
private: \
int g_nBorder = 4;
#endif // DRAGWGT_H
咋用到程序里面呢?直接上代码:
#ifndef TESTWGT_H
#define TESTWGT_H
#include <QWidget>
#include "movewgt.h"
#include "dragwgt.h"
namespace Ui {
class TestWgt;
}
class TestWgt : public QWidget
{
Q_OBJECT
//对的,就是这两行代码,其他的请略过
Move_Wgt//-------------实现窗体鼠标按住拖拽可移动
Drag_Wgt//-------------实现鼠标拖拽边缘窗体大小改变
public:
explicit TestWgt(QWidget *parent = nullptr);
~TestWgt();
private:
Ui::TestWgt *ui;
};
#endif // TESTWGT_H
注意奥,因为在MoveWgt.h中已经定义过 mousePressEvent、 mouseMoveEvent、 mouseReleaseEvent三个函数,所以在TestWgt中不能再重写该函数,否则编译会出现函数重定义的问题,DragWgt.h文件中相同。如果在自己的类中有需要重写以上函数的需要,可以不采用宏导入的这种方式,功能的实现方式不变,具体的就不在此赘述了。