QT 无标题栏窗口的拖动和拉伸

如下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);
}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值