c++&QT笔记,windows毛玻璃窗口实现封装

原创内容,转载请声明。


        今天看到了一些辅助工具的窗口总是会有个毛玻璃效果,我就很好奇如何用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);//改变窗口大小
}

适当可以修改来达到自己想要的效果。

最后附带一张简单窗口的效果图:


原创不易,转载请声明。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值