Qt制作Aero特效窗口

时间:2022-08-05 17:19:50

转载请注明链接与作者huihui1988

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

以下是头文件和实现文件:
  1. //qtwin.h
  2. #ifndef QTWIN_H
  3. #define QTWIN_H
  4. #include <QColor>
  5. #include <QWidget>
  6. class WindowNotifier;
  7. class QtWin
  8. {
  9. public:
  10. static bool enableAeroWindow(QWidget *widget, bool enable = true);
  11. static bool extendFrameIntoClientArea(QWidget *widget,
  12. int left = -1, int top = -1,
  13. int right = -1, int bottom = -1);
  14. static bool isCompositionEnabled();
  15. static QColor colorizatinColor();
  16. private:
  17. static WindowNotifier *windowNotifier();
  18. };
  19. #endif // QTWIN_H
  20. //qtwin.cpp
  21. #include "qtwin.h"
  22. #include <QLibrary>
  23. #include <QApplication>
  24. #include <QWidget>
  25. #include <QList>
  26. #include <QPointer>
  27. #ifdef Q_WS_WIN
  28. #include <qt_windows.h>
  29. // Blur behind data structures
  30. #define DWM_BB_ENABLE                 0x00000001  // fEnable has been specified
  31. #define DWM_BB_BLURREGION             0x00000002  // hRgnBlur has been specified
  32. #define DWM_BB_TRANSITIONONMAXIMIZED  0x00000004  // fTransitionOnMaximized has been specified
  33. #define WM_DWMCOMPOSITIONCHANGED        0x031E    // Composition changed window message
  34. typedef struct _DWM_BLURBEHIND
  35. {
  36. DWORD dwFlags;
  37. BOOL fEnable;
  38. HRGN hRgnBlur;
  39. BOOL fTransitionOnMaximized;
  40. } DWM_BLURBEHIND, *PDWM_BLURBEHIND;
  41. typedef struct _MARGINS
  42. {
  43. int cxLeftWidth;
  44. int cxRightWidth;
  45. int cyTopHeight;
  46. int cyBottomHeight;
  47. } MARGINS, *PMARGINS;
  48. typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
  49. typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
  50. typedef HRESULT (WINAPI *PtrDwmenableAeroWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
  51. typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
  52. static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
  53. static PtrDwmenableAeroWindow pDwmenableAeroWindow = 0;
  54. static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
  55. static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
  56. /*
  57. *同步响应DWM状态消息
  58. */
  59. class WindowNotifier : public QWidget
  60. {
  61. public:
  62. WindowNotifier() { winId(); }
  63. void addWidget(QWidget *widget) { widgets.append(widget); }
  64. void removeWidget(QWidget *widget) { widgets.removeAll(widget); }
  65. bool winEvent(MSG *message, long *result);
  66. private:
  67. QWidgetList widgets;
  68. };
  69. static bool resolveLibs()
  70. {
  71. if (!pDwmIsCompositionEnabled) {
  72. QLibrary dwmLib(QString::fromAscii("dwmapi"));
  73. pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
  74. pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
  75. pDwmenableAeroWindow = (PtrDwmenableAeroWindow)dwmLib.resolve("DwmenableAeroWindow");
  76. pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
  77. }
  78. return pDwmIsCompositionEnabled != 0;
  79. }
  80. #endif
  81. /*!
  82. * 检查 DWM 是否开启
  83. *
  84. */
  85. bool QtWin::isCompositionEnabled()
  86. {
  87. #ifdef Q_WS_WIN
  88. if (resolveLibs()) {
  89. HRESULT hr = S_OK;
  90. BOOL isEnabled = false;
  91. hr = pDwmIsCompositionEnabled(&isEnabled);
  92. if (SUCCEEDED(hr))
  93. return isEnabled;
  94. }
  95. #endif
  96. return false;
  97. }
  98. /*!
  99. * 对一个widget实现Aero效果.
  100. *
  101. */
  102. bool QtWin::enableAeroWindow(QWidget *widget, bool enable)
  103. {
  104. Q_ASSERT(widget);
  105. bool result = false;
  106. #ifdef Q_WS_WIN
  107. if (resolveLibs()) {
  108. DWM_BLURBEHIND bb = {0};
  109. HRESULT hr = S_OK;
  110. bb.fEnable = enable;
  111. bb.dwFlags = DWM_BB_ENABLE;
  112. bb.hRgnBlur = NULL;
  113. widget->setAttribute(Qt::WA_TranslucentBackground, enable);
  114. widget->setAttribute(Qt::WA_NoSystemBackground, enable);
  115. hr = pDwmenableAeroWindow(widget->winId(), &bb);
  116. if (SUCCEEDED(hr)) {
  117. result = true;
  118. windowNotifier()->addWidget(widget);
  119. }
  120. }
  121. #endif
  122. return result;
  123. }
  124. /*!
  125. * 设置Aero绘图区
  126. */
  127. bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
  128. {
  129. Q_ASSERT(widget);
  130. Q_UNUSED(left);
  131. Q_UNUSED(top);
  132. Q_UNUSED(right);
  133. Q_UNUSED(bottom);
  134. bool result = false;
  135. #ifdef Q_WS_WIN
  136. if (resolveLibs()) {
  137. QLibrary dwmLib(QString::fromAscii("dwmapi"));
  138. HRESULT hr = S_OK;
  139. MARGINS m = {left, top, right, bottom};
  140. hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
  141. if (SUCCEEDED(hr)) {
  142. result = true;
  143. windowNotifier()->addWidget(widget);
  144. }
  145. widget->setAttribute(Qt::WA_TranslucentBackground, result);
  146. }
  147. #endif
  148. return result;
  149. }
  150. /*!
  151. * 返回当前窗口颜色.
  152. */
  153. QColor QtWin::colorizatinColor()
  154. {
  155. QColor resultColor = QApplication::palette().window().color();
  156. #ifdef Q_WS_WIN
  157. if (resolveLibs()) {
  158. DWORD color = 0;
  159. BOOL opaque = FALSE;
  160. QLibrary dwmLib(QString::fromAscii("dwmapi"));
  161. HRESULT hr = S_OK;
  162. hr = pDwmGetColorizationColor(&color, &opaque);
  163. if (SUCCEEDED(hr))
  164. resultColor = QColor(color);
  165. }
  166. #endif
  167. return resultColor;
  168. }
  169. #ifdef Q_WS_WIN
  170. WindowNotifier *QtWin::windowNotifier()
  171. {
  172. static WindowNotifier *windowNotifierInstance = 0;
  173. if (!windowNotifierInstance)
  174. windowNotifierInstance = new WindowNotifier;
  175. return windowNotifierInstance;
  176. }
  177. /* 所有窗口响应 DWM 状态变换消息 */
  178. bool WindowNotifier::winEvent(MSG *message, long *result)
  179. {
  180. if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
  181. bool compositionEnabled = QtWin::isCompositionEnabled();
  182. foreach(QWidget * widget, widgets) {
  183. if (widget) {
  184. widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
  185. }
  186. widget->update();
  187. }
  188. }
  189. return QWidget::winEvent(message, result);
  190. }
  191. #endif
  192. 使用的时候只需要在生成窗口的main.cpp中#include "qtwin.h",并使用相关函数,以下是main.cpp文件:
  193. #include <QtGui/QApplication>
  194. #include "widget.h"
  195. #include "qtwin.h"
  196. int main(int argc, char *argv[])
  197. {
  198. QApplication a(argc, argv);
  199. Widget window;
  200. window.setGeometry(1040,0,240,120);
  201. window.setWindowFlags(Qt::CustomizeWindowHint);
  202. #ifdef Q_WS_X11
  203. window.setAttribute(Qt::WA_TranslucentBackground);
  204. window.setAttribute(Qt::WA_NoSystemBackground, false);
  205. QPalette pal = window.palette();
  206. QColor bg = pal.window().color();
  207. bg.setAlpha(180);
  208. pal.setColor(QPalette::Window, bg);
  209. window.setPalette(pal);
  210. window.ensurePolished(); // workaround Oxygen filling the background
  211. window.setAttribute(Qt::WA_StyledBackground, false);
  212. #endif
  213. if (QtWin::isCompositionEnabled()) {
  214. QtWin::extendFrameIntoClientArea(&window);
  215. window.setContentsMargins(0, 0, 0, 0);
  216. }
  217. window.show();
  218. return a.exec();
  219. }

http://blog.csdn.net/huihui1988/article/details/5601497