Qt 无标题无边框程序的拖动和改变大小
最近做项目遇到的问题,总结下。
有时候我们觉得系统的标题栏和按钮太丑太呆板,想做自己的标题栏以及最大化、最小化、关闭,菜单按钮,我们就需要
- setWindowFlags(Qt::FramelessWindowHint);
但是这样过后,我们就不能拖动窗口改变位置,以及拖动边缘改变窗口大小了。
有两种方案处理这种情况:
1.自己对mouseMoveEvent,mousePressEvent,mouseReleaseEvent 等事件进行处理。
2.Qt可以处理windows的消息。大家重新实现bool winEvent(MSG *message, long *result);(在此又一次感觉Qt的NB)
我刚开始使用第一种方法去实现的。移动窗口很容易做,大家可以去看看这个大大写的,比网上其他版本问题少些。
http://blog.csdn.net/aqtata/article/details/8902889
在窗口边缘按下鼠标拖动改变窗口大小就比较麻烦了。
我是这样做的:
在mousePressEvent 按下设置m_bPressed为真。
在mouseMoveEvent中m_bPressed为真且event->x() 在窗口边缘 及处理算出鼠标移动的增量 然后不断resize窗口。
至于如何为边缘的断定,就自己设定一个 差值 假如 在窗口边缘 ±4个px 就算在在该边缘就处理该resize。
这样做缺点很多,1.拖快了不行,很容易超过该差值 , 2.窗口抖动的厉害,一直在resize,3.要处理太多情况
鉴于上诉缺点于是乎就到处问人百度google。有了第二种方法:
第二种方法很好用,效果和有标题边框程序一样~~~
Qt居然可以处理windows消息。。
这里我们要重新实现winEvent ( MSG * message, long * result )
该虚函数在QWidget和QWizard以及QSizeGrip以及他们的子类中都可以实现。
如果你想停止Qt处理消息就返回true,并且设置result到你想要保存的值返回给window处理。否者的话返回false。
这里我们主要想处理WM_NCHITTEST消息。
The WM_NCHITTEST message is sent to a window in order to determine what part of the window corresponds to a particular screen coordinate. This can happen, for example, when the cursor moves, when a mouse button is pressed or released, or in response to a call to a function such as WindowFromPoint. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.
A window receives this message through its WindowProc function.
WM_NCHITTEST的消息响应函数会根据鼠标当前的坐标来判断鼠标命中了窗口的哪个部位,消息响应函数的返回值指出了部位,例如它可能会返回HTCAPTION,或者HTCLIENT等。(其返回值有很多,请查阅MSDN)。
知道这个就好了,我们还是要判断下鼠标的位置,然后通过该位置保存到result给window处理。
其实就是我们的程序没有边框不能发送这些消息,我们把它告诉windows,然后windows帮我们处理拖动,改变大小等效果。所以效果和有边框有标题程序效果一样的。
头文件申明:
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- MainWindow(QWidget *parent = 0);
- ~MainWindow();
- protected:
- bool winEvent(MSG *message, long *result);
- };
CPP实现
- bool MainWindow::winEvent(MSG *message, long *result)
- {
- switch(message->message)
- {
- case WM_NCHITTEST:
- int xPos = GET_X_LPARAM(message->lParam) - this->frameGeometry().x();
- int yPos = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y();
- if(this->childAt(xPos,yPos) == 0)
- {
- *result = HTCAPTION;
- }else{
- return false;
- }
- if(xPos > 18 && xPos < 22)
- *result = HTLEFT;
- if(xPos > (this->width() - 22) && xPos < (this->width() - 18))
- *result = HTRIGHT;
- if(yPos > 18 && yPos < 22)
- *result = HTTOP;
- if(yPos > (this->height() - 22) && yPos < (this->height() - 18))
- *result = HTBOTTOM;
- if(xPos > 18 && xPos < 22 && yPos > 18 && yPos < 22)
- *result = HTTOPLEFT;
- if(xPos > (this->width() - 22) && xPos < (this->width() - 18) && yPos > 18 && yPos < 22)
- *result = HTTOPRIGHT;
- if(xPos > 18 && xPos < 22 && yPos > (this->height() - 22) && yPos < (this->height() - 18))
- *result = HTBOTTOMLEFT;
- if(xPos > (this->width() - 22) && xPos < (this->width() - 18) && yPos > (this->height() - 22) && yPos < (this->height() - 18))
- *result = HTBOTTOMRIGHT;
- return true;
- }
- return false;
- }
把各种边界情况保存到result给windows处理,我们就省去很多事情,我想windows肯定比我们自己实现的效果要好多了。
以上的18 以及 22 是我对程序的边缘进行判断的范围。
因为
我做了边框阴影。阴影边框设定为20px所以在
- xPos > 18 && xPos < 22 其实就是我们假定的边框了。
地址:http://download.csdn.net/detail/kfbyj/5810151
https://blog.csdn.net/kfbyj/article/details/9284923
Qt 无标题无边框程序的拖动和改变大小的更多相关文章
- Qt:无标题栏无边框程序的拖动和改变大小
From: http://blog.csdn.net/kfbyj/article/details/9284923 最近做项目遇到的问题,总结下. 有时候我们觉得系统的标题栏和按钮太丑太呆板,想做自己的 ...
- Qt无边框MainWindow如何拖动四周改变大小
原来还有winEvent(), x11Event() and macEvent() 这些东西...不过貌似还需要找更好的办法,否则就无法跨平台了. 你需要重新处理部分窗体事件,以下代码适用于Windo ...
- 【转】C# 控件的自定义拖动、改变大小方法
在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Wind ...
- Delphi实现无标题有边框的窗体
1.在delphi中新建窗体程序,然后设置窗口的 BorderStyle属性为bsNone 2.在窗体的public区写下这一句: Procedure CreateParams(var Params ...
- 如何实现一个无边框Form的移动和改变大小(二)
接着上文:这里写链接内容 我们来说说一个比较复杂的实现, 效果如图: 注意为了能够凸显没有NC(NotClient)区域,我们额外用了3个panel分别放在窗体的左右和下部.用来模拟客户自己的控件. ...
- 如何实现一个无边框Form的移动和改变大小(一)
很多时候我们不希望使用Windows提供的窗体. 我们希望使用一个无边框的窗体,什么border,caption透明就行了. 下面我们来说下一些实现方法. 这个方法要求窗体自定义的border siz ...
- WINFROM 无边框窗体的移动和改变大小
因为去掉了边框 移动和调整大小都用不了了,可以调用WIN32的API来实现 1.定义必须常量 ; ; ; ; ; ; const int Guying_HTBOTTOMLEFT = 0x10; ; ...
- C# 控件的自定义拖动、改变大小方法
在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Wind ...
- Qt 无边框窗体改变大小 完美实现(全部自己实现)
近期,做项目用到无边框窗体,令人蛋疼的是无边框窗体大小的改变要像右边框那样,上下左右四周,而且要流畅. 网上也找了些代码,发现居然还要连接到windows事件,这显然不合常理,后来自己新建了demo, ...
随机推荐
- 51 nod 1189 阶乘分数
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1189 题目思路: 1/n! = 1/x +1/y ==> ...
- hdu4605Magic Ball Game 树状数组
//给一棵树.树的每个节点的子节点个数是0或2 //对于每个节点都有一个权值w[i] //一个权值为x的球在每个节点的情况有 //x=w[i] 这个球在该点不向下掉 //x<w[i] 这个球往左 ...
- 让ie6 7 8 9支持原生html5 websocket
让ie6 7 8 9支持原生html5 websocket 从github上的 web-socket-js(socket.io好像也是用这个做的他们的flash替代传输方式)改过来的.不过值得 ...
- JQuery的index()函数
1.index(),这里的索引从0开始计数. jQueryObject.index( [ object ] ):1.1 如果没有指定参数object,则返回当前元素在其所有同辈元素中的索引位置.1.2 ...
- Impala基础认知与安装
一.Impala简介 Cloudera Impala对你存储在Apache Hadoop在HDFS,HBase的数据提供直接查询互动的SQL.除了像Hive使用相同的统一存储平台,Impala也使用相 ...
- win10系统64位安装git后右键运行git bash here生成一个mintty.exe.stackdump文件后闪退解决方案
在其他win10电脑上复制了一个null.sys文件,替换C:\Windows\System32\drivers\null.sys,搞定.
- C#集合类:动态数组、队列、栈、哈希表、字典
1.动态数组:ArrayList 主要方法:Add.AddRange.RemoveAt.Remove 2.队列:Queue 主要方法:Enqueue入队列.Dequeue出队列.Peek返回Queue ...
- 【河南省多校脸萌第六场 A】分班级
[链接]点击打开链接 [题意] 在这里写题意 [题解] 最大的给了最小的,实际上就对应了,最大值减1,最小值加1. 那么二分最后班级人数最小的最大可能是几->temp1; 二分最后班级人数最大的 ...
- Day2:数据运算
一.算数运算 如: #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wan print(10%2) #求模(取模) # 0 ...
- 原生js大总结二
011.if语句的优化 1.把次数多的条件和执行结果放到最前面 2.减少第一次无用的判断,可以用嵌套判断 3.判断语句禁止出现三次嵌套 012.谈谈你对switch的理解 1. ...