Qt制作Aero特效窗口

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

//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

使用的时候只需要在生成窗口的main.cpp中#include "qtwin.h",并使用相关函数,以下是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();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值