如下2种方案,2种方案都不完美(拉伸窗口都会抖动),但是如果一定要使用,强烈推荐第1种方案(可减小拉伸时窗口抖动)
方案1:
//this->installEventFilter(this);
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this){
static bool mousePressed = false;
static QPoint last_globalPos;
static QPoint last_pos;
static bool isLeft = false, isTop = false, isRight = false, isBottom = false;
static bool isInDragResizeArea = true;
const int EDGE_SIZE = 10;
const int TITLE_HEIGHT = 40;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->type() == QEvent::MouseButtonPress) {
if (mouseEvent->button() == Qt::LeftButton) {
mousePressed = true;
last_pos = pos();
last_globalPos = mouseEvent->globalPos();
if (mouseEvent->pos().x() < 5)
isLeft = true;
else isLeft = false;
if (mouseEvent->pos().x() <= this->width() && (mouseEvent->pos().x() + EDGE_SIZE) >= this->width() )
isRight = true;
else isRight = false;
if (mouseEvent->pos().y() < 5)
isTop = true;
else isTop = false;
if (mouseEvent->pos().y() <= this->height() && (mouseEvent->pos().y() + EDGE_SIZE) >= this->height())
isBottom = true;
else isBottom = false;
}
} else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
mousePressed = false;
} else if (mouseEvent->type() == QEvent::MouseMove) {
if (!mousePressed){
if (mouseEvent->pos().x() < 5)
isLeft = true;
else isLeft = false;
if (mouseEvent->pos().x() <= this->width() && (mouseEvent->pos().x() + EDGE_SIZE) >= this->width() )
isRight = true;
else isRight = false;
if (mouseEvent->pos().y() < 5)
isTop = true;
else isTop = false;
if (mouseEvent->pos().y() <= this->height() && (mouseEvent->pos().y() + EDGE_SIZE) >= this->height())
isBottom = true;
else isBottom = false;
}
QPoint point_offset = mouseEvent->globalPos() - last_globalPos;
//先判断是否在拖拽区
isInDragResizeArea = true;
if (isLeft){
if (isTop) setCursor(Qt::SizeFDiagCursor);
else if (isBottom) setCursor(Qt::SizeBDiagCursor);
else setCursor(Qt::SizeHorCursor);
}
else if (isRight){
if (isTop) setCursor(Qt::SizeBDiagCursor);
else if (isBottom) setCursor(Qt::SizeFDiagCursor);
else setCursor(Qt::SizeHorCursor);
}
else if (isTop || isBottom){
setCursor(Qt::SizeVerCursor);
}
else {
isInDragResizeArea = false;
setCursor(Qt::ArrowCursor);
}
if (mousePressed) {
if (isInDragResizeArea){
QRect rect = geometry();
if (isLeft && isTop)
rect.setTopLeft(rect.topLeft() + point_offset);
else if (isTop)
rect.setTop(rect.top() + point_offset.y());
else if (isTop && isRight)
rect.setTopRight(rect.topRight() + point_offset);
else if (isRight)
rect.setRight(rect.right() + point_offset.x());
else if (isRight && isBottom)
rect.setBottomRight(rect.bottomRight() + point_offset);
else if (isBottom)
rect.setBottom(rect.bottom() + point_offset.y());
else if (isBottom && isLeft)
rect.setBottomLeft(rect.bottomLeft() + point_offset);
else if (isLeft)
rect.setLeft(rect.left() + point_offset.x());
this->setGeometry(rect);
last_globalPos = mouseEvent->globalPos();
}
else{
if (mouseEvent->pos().y() <= TITLE_HEIGHT) {
this->move(point_offset + last_pos);
}
}
return true;
}
}
else if (mouseEvent->type() == QEvent::MouseButtonDblClick){
if (mouseEvent->pos().y() <= TITLE_HEIGHT){
if (this->windowState() & Qt::WindowMaximized) {
this->showNormal();
}
else {
this->showMaximized();
}
}
}
}
return QMainWindow::eventFilter(watched, event);
}
方案2:
#ifdef Q_OS_WIN
#include "windowsx.h"
#pragma comment (lib,"user32.lib")
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_NCHITTEST) {
*result = 0;
const int EDGE_SIZE = 8;
const int TITLE_HEIGHT = 40;
RECT winrect;
GetWindowRect(reinterpret_cast<HWND>(winId()), &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
// 判断鼠标位置是否在拉伸区域内
if (y < winrect.top + EDGE_SIZE) {
*result = HTTOP;
}
if (y > winrect.bottom - EDGE_SIZE) {
*result = HTBOTTOM;
}
if (x < winrect.left + EDGE_SIZE) {
*result = HTLEFT;
}
if (x > winrect.right - EDGE_SIZE) {
*result = HTRIGHT;
}
if (y < winrect.top + EDGE_SIZE && x < winrect.left + EDGE_SIZE) {
*result = HTTOPLEFT;
}
if (y < winrect.top + EDGE_SIZE && x > winrect.right - EDGE_SIZE) {
*result = HTTOPRIGHT;
}
if (y > winrect.bottom - EDGE_SIZE && x < winrect.left + EDGE_SIZE) {
*result = HTBOTTOMLEFT;
}
if (y > winrect.bottom - EDGE_SIZE && x > winrect.right - EDGE_SIZE) {
*result = HTBOTTOMRIGHT;
}
if (*result != 0) {
return true;
}
}
return QWidget::nativeEvent(eventType, message, result);
}