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