原创内容,转载请声明。
今天看到了一些辅助工具的窗口总是会有个毛玻璃效果,我就很好奇如何用c++如何编写那种窗口,就查阅了会儿资料,然后封装了毛玻璃的窗口类,本文主要用于笔记以后方便自己看,如果对你有帮助,可以参考,只能给主窗口使用,控件请自行更改绘图事件处。
废话不多说,上源码:
需要用到的头文件:
#include <QWidget>
#include <QtWin>
/*
QtWin头文件包含不了,可能是没有包含winextras模块,
具体包含方法:pro文件中QT+=...后添加\winextras
*/
#include <qdialog.h>
#include <QGraphicsBlurEffect>
#include <QGraphicsPixmapItem>
#include <QPaintEvent>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QApplication>
#include <QDesktopWidget>
#include <QEvent>
#include <QMouseEvent>
#include <qscreen.h>
#include <QHBoxLayout>//水平
#include <QVBoxLayout>//垂直
#include <qspinbox.h>
aerowidget.h内容:
#ifndef AEROWIDGET_H
#define AEROWIDGET_H
#include <QWidget>
#include <QWidget>
#include <QtWin>
#include <qdialog.h>
#include <QGraphicsBlurEffect>
#include <QGraphicsPixmapItem>
#include <QPaintEvent>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QApplication>
#include <QDesktopWidget>
#include <QEvent>
#include <QMouseEvent>
#include <qscreen.h>
#include <QHBoxLayout>//水平
#include <QVBoxLayout>//垂直
#include <qspinbox.h>
class AeroWidget : public QWidget
{
Q_OBJECT
public:
QWidget* _parent;
explicit AeroWidget(QWidget *parent = nullptr);
public:
void setParent(QWidget* p);//设置父类
void setAlpha(int v);//设置透明度
void paintEvent(QPaintEvent *ev);//绘图时间,在此函数中搞毛玻璃背景
QColor bgColor;
private slots:
void valueChanged_Slot(int v);//更新透明度
};
//重要
enum AccentState
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_INVALID_STATE = 4
};
struct AccentPolicy
{
AccentState AccentState;
int AccentFlags;
int GradientColor;
int AnimationId;
};
enum WindowCompositionAttribute
{
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_LAST = 23
};
struct WindowCompositionAttributeData
{
WindowCompositionAttribute Attribute;
int * Data;
int SizeOfData;
};
typedef int* (*pfun)(HWND hwnd, WindowCompositionAttributeData *data);
//下面的宏其实是为了方便写绘图事件处理窗口内的模糊的代码,
//使用方式为 AERO(主窗口指针(本类中的_parent),bgColor)
#define AERO(t,bgColor) static bool v = false;\
if (v) return;\
QPainter painter(t);\
painter.setRenderHint(QPainter::Antialiasing);\
painter.setPen(Qt::NoPen);\
painter.setBrush(bgColor);\
painter.drawRoundedRect(rect(), 0, 0);\
v = true;
#endif // AEROWIDGET_H
aerowidget.cpp内容:
#include "aerowidget.h"
AeroWidget::AeroWidget(QWidget *parent) : QWidget(parent)
{
_parent = parent;
HWND hWnd = HWND(parent->winId());
HMODULE hUser = GetModuleHandle(L"user32.dll");
if (hUser) {
pfun setWindowCompositionAttribute = (pfun)GetProcAddress(hUser, "SetWindowCompositionAttribute");
if (setWindowCompositionAttribute) {
AccentPolicy accent = { ACCENT_ENABLE_BLURBEHIND,0, 0, 0 };
WindowCompositionAttributeData data;
data.Attribute = WCA_ACCENT_POLICY;
data.Data = reinterpret_cast<int *>(&accent) ;
data.SizeOfData = sizeof(accent);
setWindowCompositionAttribute(hWnd, &data);
/*
setWindowCompositionAttribute
一个官方文档里面没有记录上去的函数,具体上网百度去
该函数在此处用于设置毛玻璃背景
*/
}
}
parent->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明
bgColor = QColor(255, 255, 255, 100);
}
//当毛玻璃的透明程度变化时就可以用下面的一个slot和一个函数来更新
void AeroWidget::valueChanged_Slot(int v)
{
bgColor.setAlpha(v);//设置透明度
this->update();//更新
}
void AeroWidget::setAlpha(int v)
{
bgColor.setAlpha(v);//设置透明度
this->update();//更新
}
void AeroWidget::paintEvent(QPaintEvent *ev)
{
AERO(this->_parent,this->bgColor);//更新透明毛玻璃背景
}
All in all,以上就是封装最简单的一个毛玻璃窗口类
他的使用也十分简单:
//在主窗口的构造函数中使用,老样子和其他控件一样
AeroWidget 毛玻璃窗口对象(this);
/*
记住,因为毛玻璃窗口类需要用到父类指针,请创造对象的时候就指明父类指针到this处
如: AeroWidget 毛玻璃窗口对象(父类窗口对象指针);
不然的话qt大可能会报错(我是这样)!
*/
在widget.cpp中使用如下:
#include "widget.h"
#include "aerowidget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
AeroWidget aw(this);
//然后窗口就成了毛玻璃就不用管了,但是其边框也会透明,不知为何
//自己直接复制和增加一些功能和修改都是可以的
//窗口无边框
//setWindowFlag(Qt::FramelessWindowHint);
//窗口顶置
//setWindowFlags(Qt::WindowStaysOnTopHint);
//窗口半透明
//QtWin::enableBlurBehindWindow(this);
//setAttribute(Qt::WA_TranslucentBackground);
resize(900,600);//改变窗口大小
}
适当可以修改来达到自己想要的效果。
最后附带一张简单窗口的效果图:
原创不易,转载请声明。