让Qt的无边框窗口支持拖拽、Aero Snap、窗口阴影等特性
环境:Desktop Qt 5.4.1 MSVC2013 32bit
需要的库:dwmapi.lib
、user32.lib
需要头文件:<dwmapi.h>
、<windowsx.h>
在要处理的QWidget
构造函数中,添加以下两行:
12 |
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);SetWidgetBorderless(this); |
SetWidgetBorderless
的实现如下:
1234567891011121314 |
void SetWidgetBorderless(const QWidget *widget){#ifdef Q_OS_WIN HWND hwnd = reinterpret_cast<HWND>(widget->winId()); const LONG style = ( WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN ); SetWindowLongPtr(hwnd, GWL_STYLE, style); const MARGINS shadow = {1, 1, 1, 1}; DwmExtendFrameIntoClientArea(hwnd, &shadow); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);#endif} |
这个函数的作用是给无边框窗口加上阴影、Aero Snap以及其他动画特效。
这时窗口还无法手动更改大小,需要更改的话,需要自己实现一个QAbstractNativeEventFilter
类,内容如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
class NativeEventFilter : public QAbstractNativeEventFilter{public: bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE {#ifdef Q_OS_WIN if (eventType != "windows_generic_MSG") return false; MSG* msg = static_cast<MSG*>(message); QWidget* widget = QWidget::find(reinterpret_cast<WId>(msg->hwnd)); if (!widget) return false; switch (msg->message) { case WM_NCCALCSIZE: { *result = 0; return true; } case WM_NCHITTEST: { const LONG borderWidth = 9; RECT winrect; GetWindowRect(msg->hwnd, &winrect); long x = GET_X_LPARAM(msg->lParam); long y = GET_Y_LPARAM(msg->lParam); // bottom left if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMLEFT; return true; } // bottom right if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMRIGHT; return true; } // top left if (x >= winrect.left && x < winrect.left + borderWidth && y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPLEFT; return true; } // top right if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPRIGHT; return true; } // left if (x >= winrect.left && x < winrect.left + borderWidth) { *result = HTLEFT; return true; } // right if (x < winrect.right && x >= winrect.right - borderWidth) { *result = HTRIGHT; return true; } // bottom if (y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOM; return true; } // top if (y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOP; return true; } return false; } default: break; } return false;#else return false;#endif }}; |
然后在窗口创建之前,使用QApplication::installNativeEventFilter
方法把监听器注册给主程序。
要手动移动窗口位置的话,还要重截QWidget::mousePressEvent
方法:
12345678910 |
void MyWidget::mousePressEvent(QMouseEvent *ev){ QWidget::mousePressEvent(ev); if (!ev->isAccepted()) {#ifdef Q_OS_WIN ReleaseCapture(); SendMessage(reinterpret_cast<HWND>(winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); }#endif} |
在实际操作时,有时还需要添加最大化和关闭按扭,这时正常调用QWidget::showMaximized()
和QWidget::close()
等Qt自带方法即可。
最终实现效果大概是这样:
缩放动画、阴影什么的和Windows本地窗口一样。
参考链接:https://github.com/deimos1877/BorderlessWindow
https://blog.yeatse.com/2015/03/01/qt-frameless-window/
让Qt的无边框窗口支持拖拽、Aero Snap、窗口阴影等特性的更多相关文章
- Qt——透明无边框Widget的bug
Experience 最近在封装一些类的时候,打算做一个窗口框架,能实现拖动.缩放.最大最小化.基本样式等功能,可不慎遇见一件无比蛋疼的事情,QWidget最小化后再恢复正常界面,最小化按钮居然仍处于 ...
- GMF Q&;A(1): 如何让palette支持拖拽(DnD)等10则
1,如何让palette支持拖拽(DnD) 在*PaletteFactory类中,把私有类NodeToolEntry 和LinkToolEntry的基类修改为PaletteToolEntry.并在构造 ...
- .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽
这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...
- 一个可以自由定制外观、支持拖拽消除的MaterialDesign风格Android BadgeView
为了尊重作者,先放上链接:https://github.com/qstumn/BadgeView BadgeView 一个可以自由定制外观.支持拖拽消除的MaterialDesign风格Android ...
- 关于安装了VMware tools后仍然不支持拖拽文件的问题
我在学校机房里面的redhat4上面安装了VMware tools之后能正常支持拖拽,但是我自己电脑上的却不支持,折腾了好久,网上找了很久也还是没有解决,不过发现了一些问题,总结如下:(当然我总结的这 ...
- WPF.UIShell UIFramework之自定义窗口的深度技术 - 模态闪动(Blink)、窗口四边拖拽支持(WmNCHitTest)、自定义最大化位置和大小(WmGetMinMaxInfo)
无论是在工作和学习中使用WPF时,我们通常都会接触到CustomControl,今天我们就CustomWindow之后的一些边角技术进行探讨和剖析. 窗口(对话框)模态闪动(Blink) 自定义窗口的 ...
- WinForm支持拖拽效果
有一个MSDN客户提问在WinForm中如何实现拖拽效果——比如在WinForm中有一个Button,我要实现的效果是拖拽这个Button到目标位置后生成一个该控件的副本. 其实这个操作主要分成三步走 ...
- C# 图片盖章功能实现,支持拖拽-旋转-放缩-保存
实现图片盖章功能,在图片上点击,增加“图章”小图片,可以拖拽“图章”到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩. 操作方法:1.点击增加“图章”2.选中移动图标3.点中右下角放缩旋 ...
- 原生JS实现弹出窗口的拖拽
上一篇说了一下弹出窗口功能的实现思路,一般情况下紧接着就会需要做到弹窗的移动,当然现在有很插件.库比如hammer可以使用,效率也非常好.但我觉得还是有必要了解一下原生JS的实现思路及方式,如下: 思 ...
随机推荐
- struts2国际化
struts2国际化 1:什么是国际化? 国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式.它要求从产品中抽离所有的与语言,国家/地区和文化相关的元素 ...
- Webpack学习笔记一:What is webpack
#,Loaders干嘛的,webpack can only process JavaScript natively, but loaders are used to transform other ...
- C#窗体无法接受Keydown事件
问题一描述:当新建一个窗体时,添加KeyDown事件后,会正常处理,但是当添加有控件时,比如Button,TextBox,不会触发窗体的KeyDown事件,也没有调用KeyDown事件的处理程序. 原 ...
- 前端开发教程:使用 CSS3 Transforms 构建圆形导航
在本教程中我将告诉你如何使用 CSS 变换来创建圆形导航.教程逐一讲解实现这个样式将要涉及一些基本的数学知识并配合 CSS 变换来创建这些样式.不过不用担心,这里用到的数学知识真的是很简单的.教程使用 ...
- jdk源码分析之ArrayList
ArrayList关键属性分析 ArrayList采用Object数组来存储数据 /** * The array buffer into which the elements of the Array ...
- java连接mysql :No Suitable Driver Found For Jdbc 解决方法
今天出现编码出现了No suitable driver found for jdbc,又是找遍了网上的资料,基本上都说是以下个问题: 一是:连接URL格式出现了问题(Connection con ...
- hive数据库的一些应用
1.创建表格create table usr_info(mob string,reason string,tag string) row format delimited fields termina ...
- [leetcode]_Merge Two Sorted Lists
题目:合并两个有序单链表 思路:一开始想复杂了,以为必须在原链表上修改(绕来绕去还AC了,但是思路相当绕),其实没有,按照正常地合并两个数组同样的方法也对. 代码: public ListNode m ...
- 10.10 dos实验
一. 实验目的 (1)认识DOS: (2)掌握命令解释程序的原理: (3)掌握简单的DOS调用方法: (4)掌握C语言编程初步. 二. 实验内容和要求 编写类似于DOS,UNIX的命令行解释程序 (1 ...
- bzoj 3781 小B的询问(莫队算法)
[题意] 若干个询问sigma{ cnt[i]^2 } cnt[i]表示i在[l,r]内的出现次数. [思路] 莫队算法,裸题. 一个cnt数组即可维护插入与删除. [代码] #include< ...