Qt——鼠标拖动调整窗口大小
要求:鼠标移到界面边角时,鼠标样式相应地发生改变。
实现方法一:
重写mouseMoveEvent,如果鼠标没有按下,则根据鼠标在界面上的位置设置鼠标样式,如果鼠标按下,则根据位置判断该怎样调整界面大小,或者是拖动界面。思路如上,实现起来很简单。但是存在一个问题,如果界面中放了一些其它控件,比如listWidget,此时鼠标在界面边缘移动速度稍微快一些,mouseMoveEvent就会被子控件截获了,鼠标样式不会改变,对于该方法的这个问题,我还没想到好的解决办法。
实现方法二:
在Qt中处理windows事件,具体实现如下,参考网上一些内容,我顺便修改优化了一下,源代码如下:
#ifndef MBASEWIDGET_H #define MBASEWIDGET_H #include <QtWidgets/QWidget> #include "windows.h" class MBaseWidget : public QWidget { Q_OBJECT public: MBaseWidget(QWidget *parent); ~MBaseWidget(); void setMarginWidth(const int &); //设置鼠标可以在界面边缘多大范围内拖动改变界面大小 void serResizable(bool); //设置是否可以拖动改变大小 protected: bool nativeEvent(const QByteArray & eventType, void * message, long * result); bool winEvent(MSG *message, long *result); private: int m_iMarginWidth; bool m_bCanResize; }; #endif // MBASEWIDGET_H
#include "MBaseWidget.h" #include "windowsx.h" MBaseWidget::MBaseWidget(QWidget *parent) : QWidget(parent) { m_iMarginWidth = 3; m_bCanResize = true; setWindowFlags(Qt::FramelessWindowHint); } MBaseWidget::~MBaseWidget() { } void MBaseWidget::setMarginWidth(const int &iWidth) { m_iMarginWidth = iWidth; } void MBaseWidget::serResizable(bool bCanResize) { m_bCanResize = bCanResize; } //处理windows事件,在QT5中,被函数nativeEvent取代 bool MBaseWidget::winEvent(MSG *message, long *result) { switch (message->message) { case WM_NCHITTEST: int iPosX = GET_X_LPARAM(message->lParam) - this->frameGeometry().x();//鼠标位置x int iPosY = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y();//鼠标位置y *result = HTCAPTION; if (!m_bCanResize) { return true;//返回为真,此时仍可拖动,但无法改变大小 } if (iPosX >= 0 && iPosX <= m_iMarginWidth) { *result = HTLEFT;//左 int iHeight = this->height(); if (iPosY >= 0 && iPosY <= m_iMarginWidth) { *result = HTTOPLEFT;//左上 } if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight) { *result = HTBOTTOMLEFT;//左下 } return true; } int iWidth = this->width(); int iHeight = this->height(); if (iPosX >= iWidth - m_iMarginWidth && iPosX <= iWidth) { *result = HTRIGHT;//右 if (iPosY >= 0 && iPosY <= m_iMarginWidth) { *result = HTTOPRIGHT;//右上 return true; } if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight) { *result = HTBOTTOMRIGHT;//右下 return true; } return true; } if (iPosY >= 0 && iPosY <= m_iMarginWidth) { *result = HTTOP;//上 return true; } if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight) { *result = HTBOTTOM;//下 return true; } return true; } return false; } bool MBaseWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) { return winEvent((MSG*)message, result); }
这种方法是借助windows来实现的,所以受系统的限制,比如,拖动放大到与屏幕一样大时,就不能继续放大了,而且其它类直接继承这个类可能会出现问题。
实现方法三:
既然通过mouseMoveEvent不能解决鼠标的样式问题,那么可以考虑通过其它事件来实现,下面是我实现的一个类,包括头文件、dll和lib文件。
在VS中项目属性-链接器中进行相关配置即可。