Qt自定义标题栏-移动窗口
程序员文章站
2022-03-07 16:01:49
...
前情提要
众所周知,一个最简单的窗口也是有标题栏的
Widnows
默认提供的标题栏上有:
图标-窗口标题-Min-Max-Close按钮
但是,这未免太过局限
高*度的自定义是极客(Geek)
精神不可或缺的一部分
如果你想在标题栏上增加/减少控件,或改变布局、颜色、Size
就必须抛弃Windows
提供的嗟来之食
蹴尔而与之,乞人不屑也
じゃあ、どうする
使用无边框窗口即可
setWindowFlags(Qt::FramelessWindowHint);//Qt
这样就可以去除默认的标题栏,取而代之的便是光秃秃的客户区
你问我接下来怎么办?
那自然是自己写一个标题栏,当然这不是重点
只是你很快就会发现:根本没法移动窗口
それは決まってんだろう(那可不废话)
衣来伸手饭来张口,吃久了五斗米都不知道怎么下地了
正题
前摇巨长,现在进入正题,重点讲讲如何移动窗口
有两种方式:
- 监测鼠标动作
- 响应Windows消息,伪造标题栏
手动模拟
第一种最直观,平时移动窗口的方式不就是:
在鼠标在标题栏按下左键并移动 就可以带着窗口一起飞嘛
那只要手动检测鼠标状态 并移动窗口即可
void Widget::mousePressEvent(QMouseEvent* event)//鼠标按下
{
curPos = event->screenPos().toPoint();
}
void Widget::mouseMoveEvent(QMouseEvent* event)//鼠标按着并移动
{
if (!(event->buttons() & Qt::LeftButton)) return;//左键按下
QPoint mousePos = event->screenPos().toPoint();
QPoint newPos = this->pos() + mousePos - curPos;
curPos = mousePos;
move(newPos);
}
每次鼠标移动都会触发Move
消息,只要计算与上次移动的差值并同步移动窗口,即可
这里要注意几个细节:
-
最好用函数自带的参数
event
,因为QCursor::pos()
更新相对滞后 -
最好用鼠标的全局坐标
event->screenPos()
,而不是相对窗口坐标event->pos()
,因为后者在鼠标快速移动的情况下可能越界导致Bomb
爆炸,窗口鬼畜
伪造消息
第二种,欺骗Windows,假装自定义标题栏就是原来的标题栏
响应Windows
消息即可
bool Widget::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
Q_UNUSED(eventType);
MSG* msg = (MSG*)message;
switch (msg->message) {
case WM_NCHITTEST://鼠标移动消息
int xPos = GET_X_LPARAM(msg->lParam) - this->frameGeometry().x();//解析鼠标相对坐标
int yPos = GET_Y_LPARAM(msg->lParam) - this->frameGeometry().y();
if (ui->label_title->geometry().contains(xPos, yPos)) //标题栏(伪)
*result = HTCAPTION;//POINT重点语句,通过result指针返回--------------------------------<-
else //其他部分不做处理,返回false,留给其他事件处理器处理
return false;
return true;
}
return false; //此处返回false,留给其他事件处理器处理
}
通过result
指针,将结果返回给Windows,假装是标题栏(CAPTION)
Peace
上一篇: 非逆向加参数md5加密方法