要求:鼠標移到界面邊角時,鼠標樣式相應地發生改變。
實現方法一:
重寫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中項目屬性-鏈接器中進行相關配置即可。