要求:鼠标移到界面边角时,鼠标样式相应地发生改变。
实现方法一:
重写mouseMoveEvent,如果鼠标没有按下,则根据鼠标在界面上的位置设置鼠标样式,如果鼠标按下,则根据位置判断该怎样调整界面大小,或者是拖动界面。思路如上,实现起来很简单。但是存在一个问题,如果界面中放了一些其它控件,比如listWidget,此时鼠标在界面边缘移动速度稍微快一些,mouseMoveEvent就会被子控件截获了,鼠标样式不会改变,对于该方法的这个问题,我还没想到好的解决办法。
实现方法二:
在Qt中处理windows事件,具体实现如下,参考网上一些内容,我顺便修改优化了一下,源代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#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
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#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中项目属性-链接器中进行相关配置即可。