最近做项目遇到的问题,总结下。

有时候我们觉得系统的标题栏和按钮太丑太呆板,想做自己的标题栏以及最大化、最小化、关闭,菜单按钮,我们就需要

  1. 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帮我们处理拖动,改变大小等效果。所以效果和有边框有标题程序效果一样的。

头文件申明:

  1. class MainWindow : public QMainWindow
  2. {
  3. Q_OBJECT
  4. public:
  5. MainWindow(QWidget *parent = 0);
  6. ~MainWindow();
  7. protected:
  8. bool winEvent(MSG *message, long *result);
  9. };

CPP实现

  1. bool MainWindow::winEvent(MSG *message, long *result)
  2. {
  3. switch(message->message)
  4. {
  5. case WM_NCHITTEST:
  6. int xPos = GET_X_LPARAM(message->lParam) - this->frameGeometry().x();
  7. int yPos = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y();
  8. if(this->childAt(xPos,yPos) == 0)
  9. {
  10. *result = HTCAPTION;
  11. }else{
  12. return false;
  13. }
  14. if(xPos > 18 && xPos < 22)
  15. *result = HTLEFT;
  16. if(xPos > (this->width() - 22) && xPos < (this->width() - 18))
  17. *result = HTRIGHT;
  18. if(yPos > 18 && yPos < 22)
  19. *result = HTTOP;
  20. if(yPos > (this->height() - 22) && yPos < (this->height() - 18))
  21. *result = HTBOTTOM;
  22. if(xPos > 18 && xPos < 22 && yPos > 18 && yPos < 22)
  23. *result = HTTOPLEFT;
  24. if(xPos > (this->width() - 22) && xPos < (this->width() - 18) && yPos > 18 && yPos < 22)
  25. *result = HTTOPRIGHT;
  26. if(xPos > 18 && xPos < 22 && yPos > (this->height() - 22) && yPos < (this->height() - 18))
  27. *result = HTBOTTOMLEFT;
  28. if(xPos > (this->width() - 22) && xPos < (this->width() - 18) && yPos > (this->height() - 22) && yPos < (this->height() - 18))
  29. *result = HTBOTTOMRIGHT;
  30. return true;
  31. }
  32. return false;
  33. }

把各种边界情况保存到result给windows处理,我们就省去很多事情,我想windows肯定比我们自己实现的效果要好多了。

以上的18 以及 22 是我对程序的边缘进行判断的范围。

因为

我做了边框阴影。阴影边框设定为20px所以在

  1. xPos > 18 && xPos < 22 其实就是我们假定的边框了。

地址:http://download.csdn.net/detail/kfbyj/5810151

https://blog.csdn.net/kfbyj/article/details/9284923

Qt 无标题无边框程序的拖动和改变大小的更多相关文章

  1. Qt:无标题栏无边框程序的拖动和改变大小

    From: http://blog.csdn.net/kfbyj/article/details/9284923 最近做项目遇到的问题,总结下. 有时候我们觉得系统的标题栏和按钮太丑太呆板,想做自己的 ...

  2. Qt无边框MainWindow如何拖动四周改变大小

    原来还有winEvent(), x11Event() and macEvent() 这些东西...不过貌似还需要找更好的办法,否则就无法跨平台了. 你需要重新处理部分窗体事件,以下代码适用于Windo ...

  3. 【转】C# 控件的自定义拖动、改变大小方法

    在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Wind ...

  4. Delphi实现无标题有边框的窗体

    1.在delphi中新建窗体程序,然后设置窗口的 BorderStyle属性为bsNone 2.在窗体的public区写下这一句: Procedure CreateParams(var Params ...

  5. 如何实现一个无边框Form的移动和改变大小(二)

    接着上文:这里写链接内容 我们来说说一个比较复杂的实现, 效果如图: 注意为了能够凸显没有NC(NotClient)区域,我们额外用了3个panel分别放在窗体的左右和下部.用来模拟客户自己的控件. ...

  6. 如何实现一个无边框Form的移动和改变大小(一)

    很多时候我们不希望使用Windows提供的窗体. 我们希望使用一个无边框的窗体,什么border,caption透明就行了. 下面我们来说下一些实现方法. 这个方法要求窗体自定义的border siz ...

  7. WINFROM 无边框窗体的移动和改变大小

    因为去掉了边框  移动和调整大小都用不了了,可以调用WIN32的API来实现 1.定义必须常量 ; ; ; ; ; ; const int Guying_HTBOTTOMLEFT = 0x10; ; ...

  8. C# 控件的自定义拖动、改变大小方法

    在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Wind ...

  9. Qt 无边框窗体改变大小 完美实现(全部自己实现)

    近期,做项目用到无边框窗体,令人蛋疼的是无边框窗体大小的改变要像右边框那样,上下左右四周,而且要流畅. 网上也找了些代码,发现居然还要连接到windows事件,这显然不合常理,后来自己新建了demo, ...

随机推荐

  1. 目标跟踪系列十一:Exploiting the Circulant Structure of Tracking-by-detection with Kernels代码思路

    Tracking学习系列原创,转载标明出处: http://blog.csdn.net/ikerpeng/article/details/40144497 这篇文章非常赞啊!非常有必要将其好好的学习, ...

  2. 24. Spring Boot 事务的使用

    转自:https://blog.csdn.net/catoop/article/details/50595702

  3. java解压多目录Zip文件(解决中文乱码问题)--转载

    原文地址:http://zhangyongbo.iteye.com/blog/1749439 import java.io.BufferedOutputStream; import java.io.F ...

  4. swiper轮播控件配置项

    var mySwiper = new Swiper ('.swiper-container', {    direction: 'horizontal',    loop: true,    auto ...

  5. vuepress折腾记

    由于格式比较乱,所以直接拿图片粘贴过来了,详情请看原文链接https://lewiscutey.github.io/blog/blog/vuepress-theme-toos.html

  6. 关于Clipboard和GlobalAlloc函数的关系

    一句话:为了满足进程间通信,使用了clipboard的方法,clipboard是系统提供的一段任何进程都可以访问的公共内存块,malloc 和new分配的动态内存块是在进程的私有地址空间分配的,所以必 ...

  7. Loadrunner--关联详解

    当录制脚本时,VuGen会拦截client端(浏览器)与server端(网站服务器)之间的对话,并且通通记录下来,产生脚本.在VuGen的Recording Log中,您可以找到浏览器与服务器之间所有 ...

  8. eclipse启动tomcat报错

    错误信息:   严重: A child container failed during start java.util.concurrent.ExecutionException: org.apach ...

  9. cocos 关于文件名称的各种坑 各种斜杠坑

    cocos 全部文件路径 的斜杠 必须 用 /  而不能够用 \ 不然编译到安卓各种坑 相对路径 第一个字符不可 带 / /*比如 res/test.png 这样的应该是标准的 /res/test.p ...

  10. html中radio、checkbox选中状态研究(静下心来看,静下心来总结)

    html中radio.checkbox选中状态研究(静下心来看,静下心来总结) 一.总结 1.单选框的如果有多个checked 会以最后一个为准 2.js动态添加checked属性:不行:通过 $(& ...