环境:Desktop Qt 5.4.1 MSVC2013 32bit

需要的库:dwmapi.lib 、user32.lib

需要头文件:<dwmapi.h> 、<windowsx.h>

在要处理的QWidget 构造函数中,添加以下两行:

1
2
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
SetWidgetBorderless(this);

SetWidgetBorderless的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 类,内容如下:

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
95
96
97
98
99
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 方法:

1
2
3
4
5
6
7
8
9
10
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、窗口阴影等特性的更多相关文章

  1. winform 窗体设置成无边框、可拖拽、四周圆角

    最近做一个及时通讯系统的登录界面,现在将界面用到的无边框.可拖拽.四周圆角的方法分享如下: 1.无边框的窗体: 把FormBorderStyle的属性设置为none 2.可拖拽:private Poi ...

  2. Qt无边框窗体-最大化时支持拖拽还原

    目录 一.概述 二.效果展示 三.demo制作 1.设计窗体 2.双击放大 四.拖拽 五.相关文章 原文链接:Markdown模板 一.概述 用Qt进行开发界面时,既想要实现友好的用户交互又想界面漂亮 ...

  3. Qt——透明无边框Widget的bug

    Experience 最近在封装一些类的时候,打算做一个窗口框架,能实现拖动.缩放.最大最小化.基本样式等功能,可不慎遇见一件无比蛋疼的事情,QWidget最小化后再恢复正常界面,最小化按钮居然仍处于 ...

  4. jQuery插件之路(三)——文件上传(支持拖拽上传)

    好了,这次咱一改往日的作风,就不多说废话了,哈哈.先贴上源代码地址,点击获取.然后直接进入主题啦,当然,如果你觉得我有哪里写的不对或者欠妥的地方,欢迎留言指出.在附上一些代码之前,我们还是先来了解下, ...

  5. GMF Q&A(1): 如何让palette支持拖拽(DnD)等10则

    1,如何让palette支持拖拽(DnD) 在*PaletteFactory类中,把私有类NodeToolEntry 和LinkToolEntry的基类修改为PaletteToolEntry.并在构造 ...

  6. .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽

    这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...

  7. 一个可以自由定制外观、支持拖拽消除的MaterialDesign风格Android BadgeView

    为了尊重作者,先放上链接:https://github.com/qstumn/BadgeView BadgeView 一个可以自由定制外观.支持拖拽消除的MaterialDesign风格Android ...

  8. 关于安装了VMware tools后仍然不支持拖拽文件的问题

    我在学校机房里面的redhat4上面安装了VMware tools之后能正常支持拖拽,但是我自己电脑上的却不支持,折腾了好久,网上找了很久也还是没有解决,不过发现了一些问题,总结如下:(当然我总结的这 ...

  9. 让一个view 或者控件不支持拖拽

    让一个view 或者控件不支持拖拽: dragView.userInteractionEnabled = NO;

随机推荐

  1. 大牛之路II

    时间限制:500MS  内存限制:1000K 提交次数:138 通过次数:31 题型: 编程题   语言: C++;C Description 要成为ACM大牛,要掌握很多必需的知识点.某些知识点可以 ...

  2. 使用 Java 开发并生成 .jar 文件

    1. 编写文件 D:\test\Hello.java: package test; public class Hello { public static void main(String argv[] ...

  3. Windows Phone 硬件检测

    private static bool IsWvga{ get { return App.Current.Host.Content.ScaleFactor == 100; }} private sta ...

  4. Repeater控件中的三目运算

    <asp:Repeater ID="rptimg" runat="server">        <ItemTemplate>      ...

  5. RN组件之ViewPagerAndroid

    一.ViewPagerAndroid 1.一个允许在子视图之间左右翻页的容器.每一个ViewPagerAndroid的子容器会被视作一个单独的页,并且会被拉伸填满 ViewPagerAndroid.注 ...

  6. Eclipse @override报错解决

    第一种解决方案: @Override是JDK5 就已经有了,但有个小小的Bug,就是不支持对接口的实现,认为这不是Override 而JDK6 修正了这个Bug,无论是对父类的方法覆盖还是对接口的实现 ...

  7. LeetCode-Sudoku Solver (递归解法)

    题目地址: https://leetcode.com/problems/sudoku-solver/ // 将字符串的数独题转换成 int[9][9] ][], char ** b, int boar ...

  8. CSS浏览器兼容的那些事儿

    1.文字本身的大小不兼容.同样是font-size:14px的宋体文字,在不同浏览器下占的空间是不一样的,ie下实际占高16px,下留白3px,ff下实际占高17px,上留白1px,下留白3px,op ...

  9. Add SSH Key to GitLab on Windows

    Download Git for windows Open Git Bash Type in "ssh-keygen -t rsa", and then press Enter b ...

  10. hdu Pie

    这道题是一道二分搜索的题,首先计算出最大的平均体积:mx=V总/f:然后去left=0,right=mx,mid=(left+right)/2进行二分搜索,当所有pi分割出的mid的个数是大于等于f时 ...