Wladimir J. van der Laan
14 years ago
4 changed files with 283 additions and 3 deletions
@ -0,0 +1,222 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** |
||||||
|
** Use, modification and distribution is allowed without limitation, |
||||||
|
** warranty, liability or support of any kind. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#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 *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind); |
||||||
|
typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); |
||||||
|
|
||||||
|
static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; |
||||||
|
static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; |
||||||
|
static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; |
||||||
|
static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal helper class that notifies windows if the |
||||||
|
* DWM compositing state changes and updates the widget |
||||||
|
* flags correspondingly. |
||||||
|
*/ |
||||||
|
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"); |
||||||
|
pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); |
||||||
|
pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); |
||||||
|
} |
||||||
|
return pDwmIsCompositionEnabled != 0; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Chekcs and returns true if Windows DWM composition |
||||||
|
* is currently enabled on the system. |
||||||
|
* |
||||||
|
* To get live notification on the availability of |
||||||
|
* this feature, you will currently have to |
||||||
|
* reimplement winEvent() on your widget and listen |
||||||
|
* for the WM_DWMCOMPOSITIONCHANGED event to occur. |
||||||
|
* |
||||||
|
*/ |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enables Blur behind on a Widget. |
||||||
|
* |
||||||
|
* \a enable tells if the blur should be enabled or not |
||||||
|
*/ |
||||||
|
bool QtWin::enableBlurBehindWindow(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 = pDwmEnableBlurBehindWindow(widget->winId(), &bb); |
||||||
|
if (SUCCEEDED(hr)) { |
||||||
|
result = true; |
||||||
|
windowNotifier()->addWidget(widget); |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* ExtendFrameIntoClientArea. |
||||||
|
* |
||||||
|
* This controls the rendering of the frame inside the window. |
||||||
|
* Note that passing margins of -1 (the default value) will completely |
||||||
|
* remove the frame from the window. |
||||||
|
* |
||||||
|
* \note you should not call enableBlurBehindWindow before calling |
||||||
|
* this functions |
||||||
|
* |
||||||
|
* \a enable tells if the blur should be enabled or not |
||||||
|
*/ |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the current colorizationColor for the window. |
||||||
|
* |
||||||
|
* \a enable tells if the blur should be enabled or not |
||||||
|
*/ |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Notify all enabled windows that the DWM state changed */ |
||||||
|
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 |
@ -0,0 +1,37 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
||||||
|
** |
||||||
|
** Use, modification and distribution is allowed without limitation, |
||||||
|
** warranty, liability or support of any kind. |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#ifndef QTWIN_H |
||||||
|
#define QTWIN_H |
||||||
|
|
||||||
|
#include <QColor> |
||||||
|
#include <QWidget> |
||||||
|
/**
|
||||||
|
* This is a helper class for using the Desktop Window Manager |
||||||
|
* functionality on Windows 7 and Windows Vista. On other platforms |
||||||
|
* these functions will simply not do anything. |
||||||
|
*/ |
||||||
|
|
||||||
|
class WindowNotifier; |
||||||
|
|
||||||
|
class QtWin |
||||||
|
{ |
||||||
|
public: |
||||||
|
static bool enableBlurBehindWindow(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
|
Loading…
Reference in new issue