Contents

【转】原创作品,允许转载。转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。
http://blog.csdn.net/huihui1988/article/details/5601497

初学QT,边看书边自己做点小东西。最近突然心血来潮,想自己做个小巧点的,界面美观一点的备忘当桌面上。想了半天,发现VISTA/WIN7的Aero效果就不错,况且自己现在就在用WIN7。于是上网找了下QT制作Aero效果的方法。Google之后终于找到了函数和用法。于是做了一个简单的Aero特效窗口。

以下是头文件和实现文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//qtwin.h
#ifndef QTWIN_H
#define QTWIN_H
#include <QColor>
#include <QWidget>
class WindowNotifier;
class QtWin
{
public:
static bool enableAeroWindow(QWidget *widget, bool enable = true);
static bool extendFrameIntoClientArea(QWidget *widget,
int left = -1, int top = -1,
int right = -1, int bottom = -1);
static bool isCompositionEnabled();
static QColor colorizatinColor();
private:
static WindowNotifier *windowNotifier();
};
#endif // QTWIN_H
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//qtwin.cpp
#include "qtwin.h"
#include <QLibrary>
#include <QApplication>
#include <QWidget>
#include <QList>
#include <QPointer>
#ifdef Q_WS_WIN
#include <qt_windows.h>
// Blur behind data structures
#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified
#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified
#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message
typedef struct _DWM_BLURBEHIND
{
DWORD dwFlags;
BOOL fEnable;
HRGN hRgnBlur;
BOOL fTransitionOnMaximized;
} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
typedef struct _MARGINS
{
int cxLeftWidth;
int cxRightWidth;
int cyTopHeight;
int cyBottomHeight;
} MARGINS, *PMARGINS;
typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
typedef HRESULT (WINAPI *PtrDwmenableAeroWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
static PtrDwmenableAeroWindow pDwmenableAeroWindow = 0;
static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
/*
*同步响应DWM状态消息
*/
class WindowNotifier : public QWidget
{
public:
WindowNotifier() { winId(); }
void addWidget(QWidget *widget) { widgets.append(widget); }
void removeWidget(QWidget *widget) { widgets.removeAll(widget); }
bool winEvent(MSG *message, long *result);
private:
QWidgetList widgets;
};
static bool resolveLibs()
{
if (!pDwmIsCompositionEnabled) {
QLibrary dwmLib(QString::fromAscii("dwmapi"));
pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
pDwmenableAeroWindow = (PtrDwmenableAeroWindow)dwmLib.resolve("DwmenableAeroWindow");
pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
}
return pDwmIsCompositionEnabled != 0;
}
#endif
/*!
* 检查 DWM 是否开启
*
*/
bool QtWin::isCompositionEnabled()
{
#ifdef Q_WS_WIN
if (resolveLibs()) {
HRESULT hr = S_OK;
BOOL isEnabled = false;
hr = pDwmIsCompositionEnabled(&isEnabled);
if (SUCCEEDED(hr))
return isEnabled;
}
#endif
return false;
}
/*!
* 对一个widget实现Aero效果.
*
*/
bool QtWin::enableAeroWindow(QWidget *widget, bool enable)
{
Q_ASSERT(widget);
bool result = false;
#ifdef Q_WS_WIN
if (resolveLibs()) {
DWM_BLURBEHIND bb = {0};
HRESULT hr = S_OK;
bb.fEnable = enable;
bb.dwFlags = DWM_BB_ENABLE;
bb.hRgnBlur = NULL;
widget->setAttribute(Qt::WA_TranslucentBackground, enable);
widget->setAttribute(Qt::WA_NoSystemBackground, enable);
hr = pDwmenableAeroWindow(widget->winId(), &bb);
if (SUCCEEDED(hr)) {
result = true;
windowNotifier()->addWidget(widget);
}
}
#endif
return result;
}
/*!
* 设置Aero绘图区
*/
bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
{
Q_ASSERT(widget);
Q_UNUSED(left);
Q_UNUSED(top);
Q_UNUSED(right);
Q_UNUSED(bottom);
bool result = false;
#ifdef Q_WS_WIN
if (resolveLibs()) {
QLibrary dwmLib(QString::fromAscii("dwmapi"));
HRESULT hr = S_OK;
MARGINS m = {left, top, right, bottom};
hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
if (SUCCEEDED(hr)) {
result = true;
windowNotifier()->addWidget(widget);
}
widget->setAttribute(Qt::WA_TranslucentBackground, result);
}
#endif
return result;
}
/*!
* 返回当前窗口颜色.
*/
QColor QtWin::colorizatinColor()
{
QColor resultColor = QApplication::palette().window().color();
#ifdef Q_WS_WIN
if (resolveLibs()) {
DWORD color = 0;
BOOL opaque = FALSE;
QLibrary dwmLib(QString::fromAscii("dwmapi"));
HRESULT hr = S_OK;
hr = pDwmGetColorizationColor(&color, &opaque);
if (SUCCEEDED(hr))
resultColor = QColor(color);
}
#endif
return resultColor;
}
#ifdef Q_WS_WIN
WindowNotifier *QtWin::windowNotifier()
{
static WindowNotifier *windowNotifierInstance = 0;
if (!windowNotifierInstance)
windowNotifierInstance = new WindowNotifier;
return windowNotifierInstance;
}
/* 所有窗口响应 DWM 状态变换消息 */
bool WindowNotifier::winEvent(MSG *message, long *result)
{
if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
bool compositionEnabled = QtWin::isCompositionEnabled();
foreach(QWidget * widget, widgets) {
if (widget) {
widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
}
widget->update();
}
}
return QWidget::winEvent(message, result);
}
#endif
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
//main.cpp
#include <QtGui/QApplication>
#include "widget.h"
#include "qtwin.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
window.setGeometry(1040,0,240,120);
window.setWindowFlags(Qt::CustomizeWindowHint);
#ifdef Q_WS_X11
window.setAttribute(Qt::WA_TranslucentBackground);
window.setAttribute(Qt::WA_NoSystemBackground, false);
QPalette pal = window.palette();
QColor bg = pal.window().color();
bg.setAlpha(180);
pal.setColor(QPalette::Window, bg);
window.setPalette(pal);
window.ensurePolished(); // workaround Oxygen filling the background
window.setAttribute(Qt::WA_StyledBackground, false);
#endif
if (QtWin::isCompositionEnabled()) {
QtWin::extendFrameIntoClientArea(&window);
window.setContentsMargins(0, 0, 0, 0);
}
window.show();
return a.exec();
}
Contents