source: tspsg-svn/trunk/src/qtwin.cpp @ 94

Last change on this file since 94 was 92, checked in by laleppa, 15 years ago

+ Some Windows Vista and Windows 7 eyecandy with translucent windows thanks to http://labs.trolltech.com/blogs/2009/09/15/using-blur-behind-on-windows/ :-)

  • Property svn:keywords set to Id URL
File size: 6.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4**
5** Use, modification and distribution is allowed without limitation,
6** warranty, liability or support of any kind.
7**
8****************************************************************************/
9
10#include "qtwin.h"
11#include <QLibrary>
12#include <QApplication>
13#include <QWidget>
14#include <QList>
15#include <QPointer>
16
17#ifdef Q_WS_WIN
18
19#include <qt_windows.h>
20
21// Blur behind data structures
22#define DWM_BB_ENABLE                 0x00000001  // fEnable has been specified
23#define DWM_BB_BLURREGION             0x00000002  // hRgnBlur has been specified
24#define DWM_BB_TRANSITIONONMAXIMIZED  0x00000004  // fTransitionOnMaximized has been specified
25#define WM_DWMCOMPOSITIONCHANGED        0x031E    // Composition changed window message
26
27typedef struct _DWM_BLURBEHIND
28{
29    DWORD dwFlags;
30    BOOL fEnable;
31    HRGN hRgnBlur;
32    BOOL fTransitionOnMaximized;
33} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
34
35typedef struct _MARGINS
36{
37    int cxLeftWidth;
38    int cxRightWidth;
39    int cyTopHeight;
40    int cyBottomHeight;
41} MARGINS, *PMARGINS;
42
43typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
44typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
45typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
46typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
47
48static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
49static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
50static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
51static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
52
53
54/*
55 * Internal helper class that notifies windows if the
56 * DWM compositing state changes and updates the widget
57 * flags correspondingly.
58 */
59class WindowNotifier : public QWidget
60{
61public:
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
67private:
68    QWidgetList widgets;
69};
70
71static bool resolveLibs()
72{
73    if (!pDwmIsCompositionEnabled) {
74        QLibrary dwmLib(QString::fromAscii("dwmapi"));
75        pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
76        pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
77        pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
78        pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
79    }
80    return pDwmIsCompositionEnabled != 0;
81}
82
83#endif
84
85/*!
86  * Chekcs and returns true if Windows DWM composition
87  * is currently enabled on the system.
88  *
89  * To get live notification on the availability of
90  * this feature, you will currently have to
91  * reimplement winEvent() on your widget and listen
92  * for the WM_DWMCOMPOSITIONCHANGED event to occur.
93  *
94  */
95bool QtWin::isCompositionEnabled()
96{
97#ifdef Q_WS_WIN
98    if (resolveLibs()) {
99        HRESULT hr = S_OK;
100        BOOL isEnabled = false;
101        hr = pDwmIsCompositionEnabled(&isEnabled);
102        if (SUCCEEDED(hr))
103            return isEnabled;
104    }
105#endif
106    return false;
107}
108
109/*!
110  * Enables Blur behind on a Widget.
111  *
112  * \a enable tells if the blur should be enabled or not
113  */
114bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable)
115{
116    Q_ASSERT(widget);
117    bool result = false;
118#ifdef Q_WS_WIN
119    if (resolveLibs()) {
120        DWM_BLURBEHIND bb = {0};
121        HRESULT hr = S_OK;
122        bb.fEnable = enable;
123        bb.dwFlags = DWM_BB_ENABLE;
124        bb.hRgnBlur = NULL;
125        widget->setAttribute(Qt::WA_TranslucentBackground, enable);
126        widget->setAttribute(Qt::WA_NoSystemBackground, enable);
127        hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
128        if (SUCCEEDED(hr)) {
129            result = true;
130            windowNotifier()->addWidget(widget);
131        }
132    }
133#endif
134    return result;
135}
136
137/*!
138  * ExtendFrameIntoClientArea.
139  *
140  * This controls the rendering of the frame inside the window.
141  * Note that passing margins of -1 (the default value) will completely
142  * remove the frame from the window.
143  *
144  * \note you should not call enableBlurBehindWindow before calling
145  *       this functions
146  *
147  * \a enable tells if the blur should be enabled or not
148  */
149bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
150{
151
152    Q_ASSERT(widget);
153    Q_UNUSED(left);
154    Q_UNUSED(top);
155    Q_UNUSED(right);
156    Q_UNUSED(bottom);
157
158    bool result = false;
159#ifdef Q_WS_WIN
160    if (resolveLibs()) {
161        QLibrary dwmLib(QString::fromAscii("dwmapi"));
162        HRESULT hr = S_OK;
163        MARGINS m = {left, top, right, bottom};
164        hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
165        if (SUCCEEDED(hr)) {
166            result = true;
167            windowNotifier()->addWidget(widget);
168        }
169        widget->setAttribute(Qt::WA_TranslucentBackground, result);
170    }
171#endif
172    return result;
173}
174
175/*!
176  * Returns the current colorizationColor for the window.
177  *
178  * \a enable tells if the blur should be enabled or not
179  */
180QColor QtWin::colorizatinColor()
181{
182    QColor resultColor = QApplication::palette().window().color();
183
184#ifdef Q_WS_WIN
185    if (resolveLibs()) {
186        DWORD color = 0;
187        BOOL opaque = FALSE;
188        QLibrary dwmLib(QString::fromAscii("dwmapi"));
189        HRESULT hr = S_OK;
190        hr = pDwmGetColorizationColor(&color, &opaque);
191        if (SUCCEEDED(hr))
192            resultColor = QColor(color);
193    }
194#endif
195    return resultColor;
196}
197
198#ifdef Q_WS_WIN
199WindowNotifier *QtWin::windowNotifier()
200{
201    static WindowNotifier *windowNotifierInstance = 0;
202    if (!windowNotifierInstance)
203        windowNotifierInstance = new WindowNotifier;
204    return windowNotifierInstance;
205}
206
207
208/* Notify all enabled windows that the DWM state changed */
209bool WindowNotifier::winEvent(MSG *message, long *result)
210{
211    if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
212        bool compositionEnabled = QtWin::isCompositionEnabled();
213        foreach(QWidget * widget, widgets) {
214            if (widget) {
215                widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
216            }
217            widget->update();
218        }
219    }
220    return QWidget::winEvent(message, result);
221}
222#endif
Note: See TracBrowser for help on using the repository browser.