前言
主窗体设置无边框无法拖动修改尺寸,可以和自定义标题栏一样重写,搭配自定义标题栏一起使用,这里写的QMainWindow,如果是无边框QDialog,直接把QMainWindow对应的改为QDialog即可。
提示:以下是本篇文章正文内容,下面案例可供参考
1.头文件
代码如下(示例):
#ifndef VARIABLESIZEMAINWINDOW_H
#define VARIABLESIZEMAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QMouseEvent>
#ifdef Q_OS_WIN
#include "Windows.h"
#endif
class VariableSizeMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit VariableSizeMainWindow(QWidget *parent = nullptr);
~VariableSizeMainWindow();
enum Direction { DOWN = 0, LEFT, RIGHT, LEFTBOTTOM, RIGHTBOTTOM, NONE };
public:
void initData();
QRectF boundingRect() const;
QRectF leftBorder() const;
QRectF rightBorder() const;
QRectF topBorder() const;
QRectF bottomBorder() const;
void setMousePressCursorShape(const QPointF& pt);
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#ifdef Q_OS_WIN
bool winEvent(MSG *message, long *result);
#endif
private:
qreal borderSize; //边界尺寸
bool isLeftPressDown; //判断左键是否按下
Direction dir; //窗口大小改变时,记录改变方向
QDateTime dateTimeLastModify;
private:
void mousePressEvent(QMouseEvent *event); //鼠标点击事件
void mouseMoveEvent(QMouseEvent *event); //鼠标移动事件
void mouseReleaseEvent(QMouseEvent *event); //鼠标离开事件
bool eventFilter(QObject *obj, QEvent *event); //事件过滤器
};
#endif // VARIABLESIZEMAINWINDOW_H
2.函数实现
代码如下(示例):
#include "variablesizemainwindow.h"
VariableSizeMainWindow::VariableSizeMainWindow(QWidget *parent) :
QMainWindow(parent)
{
initData();
}
VariableSizeMainWindow::~VariableSizeMainWindow()
{
}
void VariableSizeMainWindow::initData()
{
//设置窗体标题栏隐藏
setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint| Qt::WindowMinimizeButtonHint| Qt::WindowMaximizeButtonHint);
//设置接受拖拽事件
setAcceptDrops(true);
this->setMouseTracking(true);
this->setAttribute(Qt::WA_Hover, true);
this->installEventFilter(this);
borderSize = 10;
isLeftPressDown = false;
this->dir = NONE;
//#if _DEBUG
startTimer(1000);
//#endif
}
//主窗体实现函数
bool VariableSizeMainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (eventType == "windows_generic_MSG") {
#ifdef Q_OS_WIN
MSG *msg = static_cast<MSG *>(message);
//qDebug() << TIMEMS << msg->message;
if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
//系统休眠的时候自动最小化可以规避程序可能出现的问题
this->showMinimized();
qDebug()<<"系统休眠中,最小化窗口!";
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
//休眠唤醒后自动打开
this->showNormal();
qDebug()<<"系统已唤醒,恢复窗口!";
}
#endif
} else if (eventType == "NSEvent") {
#ifdef Q_OS_MACOS
#endif
}
return false;
}
#ifdef Q_OS_WIN
bool VariableSizeMainWindow::winEvent(MSG *message, long *result)
{
return nativeEvent("windows_generic_MSG", message, result);
}
#endif
void VariableSizeMainWindow::mousePressEvent(QMouseEvent *event)
{
isLeftPressDown = true;
setMousePressCursorShape(event->pos());
if (dir != NONE) {
this->mouseGrabber();
}
qDebug() << "dir = " << dir;
}
QRectF VariableSizeMainWindow::boundingRect() const
{
return QRectF(QPointF(0, 0), geometry().size());
}
QRectF VariableSizeMainWindow::leftBorder() const
{
return QRectF(0, 0, 3, boundingRect().height());
}
QRectF VariableSizeMainWindow::rightBorder() const
{
return QRectF(boundingRect().width() - borderSize, 0, borderSize, boundingRect().height());
}
QRectF VariableSizeMainWindow::topBorder() const
{
return QRectF(0, 0, boundingRect().width(), borderSize);
}
QRectF VariableSizeMainWindow::bottomBorder() const
{
return QRectF(0, boundingRect().height() - borderSize, boundingRect().width(), borderSize);
}
void VariableSizeMainWindow::setMousePressCursorShape(const QPointF& pt)
{
QCursor cursor = Qt::ArrowCursor;
if (rightBorder().contains(pt) && bottomBorder().contains(pt)) // 右下角
{
dir = RIGHTBOTTOM;
cursor = Qt::SizeFDiagCursor;
}
else if (leftBorder().contains(pt) && bottomBorder().contains(pt)) // 左下角
{
dir = LEFTBOTTOM;
cursor = Qt::SizeBDiagCursor;
}
else if (rightBorder().contains(pt)) // 右边
{
dir = RIGHT;
cursor = Qt::SizeHorCursor;
}
else if (bottomBorder().contains(pt)) // 底边
{
dir = DOWN;
cursor = Qt::SizeVerCursor;
}
else if (leftBorder().contains(pt)) // 左边
{
dir = LEFT;
cursor = Qt::SizeHorCursor;
}
else
{
dir = NONE;
cursor = Qt::ArrowCursor;
}
setCursor(cursor);
}
void VariableSizeMainWindow::mouseMoveEvent(QMouseEvent *event)
{
QPoint gloPoint = event->globalPos();
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
if (!isLeftPressDown) {
setMousePressCursorShape(gloPoint);
}
else {
if (dir != NONE) {
QRect rMove(tl, rb);
switch (dir) {
case LEFT:
if (rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
break;
case RIGHT:
rMove.setWidth(gloPoint.x() - tl.x());
break;
case DOWN:
if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
rMove.setHeight(gloPoint.y() - tl.y());
break;
case LEFTBOTTOM:
if (rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
rMove.setHeight(gloPoint.y() - tl.y());
break;
case RIGHTBOTTOM:
rMove.setWidth(gloPoint.x() - tl.x());
if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
rMove.setHeight(gloPoint.y() - tl.y());
break;
default:
break;
}
this->setGeometry(rMove);
}
}
QMainWindow::mouseMoveEvent(event);
}
void VariableSizeMainWindow::mouseReleaseEvent(QMouseEvent *event)
{
isLeftPressDown = false;
if (dir != NONE) {
dir = NONE;
this->releaseMouse();
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
bool VariableSizeMainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this)
{
if (event->type() == QMouseEvent::HoverEnter)
{
QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
setMousePressCursorShape(_mouseEvent->pos());
}
if (event->type() == QMouseEvent::HoverMove)
{
QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
if (!isLeftPressDown)
setMousePressCursorShape(_mouseEvent->pos());
}
if (event->type() == QMouseEvent::HoverLeave)
{
unsetCursor();
}
}
return QMainWindow::eventFilter(obj, event);
}
3.使用
.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "variablesizemainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public VariableSizeMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
static MainWindow *getInstance() {
static QMutex mutex;
if (!instance) {
QMutexLocker locker(&mutex);
if (!instance) {
instance = new MainWindow;
}
}
return instance;
}
private:
Ui::MainWindow *ui;
static MainWindow *instance;
};
#endif // MAINWINDOW_H
.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow *MainWindow::instance = Q_NULLPTR;
MainWindow::MainWindow(QWidget *parent) :
VariableSizeMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}