QT桌面挂件动画

参考

图片资源

功能

  • 桌面挂件动画置顶
  • 切换挂件动画
  • 图片选择更换桌面壁纸
  • 显示时改变桌面壁纸,隐藏/退出时还原桌面壁纸
  • 系统托盘菜单,可选择开/关悬浮挂件功能按键
  • 悬浮挂件功能按键随鼠标区域显示/隐藏

实现

05DesktopPattern.pro

链接 user32 Advapi32

# 对于 Windows 平台,GetDesktopWindow 函数位于 user32.lib 库
LIBS += -luser32 -lAdvapi32

main.cpp

#include "desktoppattern.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    
    
    QApplication a(argc, argv);
    DesktopPattern w;
    w.show();
    return a.exec();
}

desktoppattern.h

#ifndef DESKTOPPATTERN_H
#define DESKTOPPATTERN_H

#include <QWidget>
#include <QTimer>
#include <QLabel>
#include <QDebug>
#include <QPushButton>
#include <QGraphicsDropShadowEffect>
#include <QEvent>
#include <QMouseEvent>
#include <QFileDialog>
#include <QApplication>
#include <QSystemTrayIcon>  // 将窗口嵌入到系统托盘
#include <QMenu>
#include "wallpaper.h"

class DesktopPattern : public QWidget

{
    
    
    Q_OBJECT

public:
    DesktopPattern(QWidget *parent = nullptr);
    ~DesktopPattern();
    bool eventFilter(QObject *watched,QEvent *ev) override;
    void setVisible(bool visible)override;
    void initButton();
    void showButton();
    void hideButton();
    void initWindowToSystemTray();// 初始化系统托盘
public slots:
    void updateRoleAnimation();// 更新角色动画
private:
    QLabel* roleLabel;
    qint8 curFrame;	//当前帧
    qint8 curPath;	//当前路径
    QList<QString> pathList;
    bool timerRunning = false;// 在类中添加一个标志变量
    bool hoverChoose = true; // 悬浮选择按钮开关

    QPushButton* closeBtn;
    QPushButton* cutBtn;
    QPushButton* openBtn;
    QSystemTrayIcon *trayIcon;  // 系统托盘

    Wallpaper *mWallpaper;
    QString wallpaperPath; // 替换为你的壁纸文件路径
};

#endif // DESKTOPPATTERN_H

desktoppattern.cpp

#include "desktoppattern.h"


DesktopPattern::DesktopPattern(QWidget *parent)
    : QWidget(parent)
{
    
    
    //setWindowFlags(Qt::FramelessWindowHint);// 无窗口的边框,
    //窗口将始终显示在其他窗口之上
    setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);

    setAttribute(Qt::WA_TranslucentBackground);// 背景透明 属性
    setWindowIcon(QIcon(":/resource/icon.ico"));
    curFrame=0;
    curPath = 0;	//当前路径
    pathList.append("background-image:url(:/resource/desktopRole/summerGril/%1.png);");
    pathList.append("background-image:url(:/resource/desktopRole/littleBoy/%1.png);");
    pathList.append("background-image:url(:/resource/desktopRole/blackGril/action1-happy/%1.png);");
    pathList.append("background-image:url(:/resource/desktopRole/blackGril/action2-sad/%1.png);");
    pathList.append("background-image:url(:/resource/desktopRole/blackGril/action3-naughty/%1.png);");
    pathList.append("background-image:url(:/resource/desktopRole/blackGril/action4-shy/%1.png);");

    // 定时器更新角色动画
    QTimer *updateTimer = new QTimer(this);
    updateTimer->callOnTimeout(this,&DesktopPattern::updateRoleAnimation);
    updateTimer->start(500);

    roleLabel = new QLabel(this);
    roleLabel->resize(500, 500);


    //给窗口设置阴影
    QGraphicsDropShadowEffect * effect=new QGraphicsDropShadowEffect(this);
    effect->setColor(QColor(230,231,232,220));
    effect->setBlurRadius(5);// 设置模糊半径
    this->setGraphicsEffect(effect);

    this->installEventFilter(this);// 安装事件过滤器

    initButton();
    initWindowToSystemTray();

    mWallpaper = new Wallpaper();
}

DesktopPattern::~DesktopPattern()
{
    
    
    if(mWallpaper)
        delete mWallpaper;
}

bool DesktopPattern::eventFilter(QObject *watched, QEvent *ev)
{
    
    
    if (/*watched == this && */ev->type() == QEvent::Enter) {
    
    
        // 鼠标进入窗口时执行的操作
        showButton();
    } else if (/*watched == this &&*/ ev->type() == QEvent::Leave) {
    
    
        // 鼠标离开窗口时执行的操作
        if (!timerRunning) {
    
    
            timerRunning = true;
            QTimer::singleShot(3000,this,&DesktopPattern::hideButton);
        }
    }

    QMouseEvent *mouseEv=static_cast<QMouseEvent*>(ev);
    static QPoint beginPos;
    if(ev->type()==QEvent::MouseButtonPress)    // 事件为 鼠标按下
    {
    
    
        beginPos = mouseEv->globalPos()-this->pos();
    }
    else if(ev->type()==QEvent::MouseMove && mouseEv->buttons()&Qt::MouseButton::LeftButton)
    {
    
    // 事件为 鼠标移动 && 鼠标是左键
        this->move(mouseEv->globalPos()-beginPos);
    }

    return QObject::eventFilter(watched, ev);
}

void DesktopPattern::setVisible(bool visible)
{
    
    
    if(visible){
    
    
        if(mWallpaper)
            mWallpaper->setPixmap(wallpaperPath);
        qDebug() << " ";
    }
    else {
    
    
        if(mWallpaper)
            mWallpaper->hide();
    }
    QWidget::setVisible(visible);
}

void DesktopPattern::initButton()
{
    
    
    closeBtn = new QPushButton(this);
    cutBtn= new QPushButton(this);
    openBtn= new QPushButton(this);
    closeBtn->setGeometry(320, 200, 36, 36);
    cutBtn->setGeometry(320, 240, 36, 36);
    openBtn->setGeometry(320, 280, 36, 36);
    closeBtn->setObjectName("closeBtn");
    cutBtn->setObjectName("cutBtn");

    closeBtn->setStyleSheet("background-image:url(:/resource/button/quit.png);background-repeat:no-repeat;");
    cutBtn->setStyleSheet("background-image:url(:/resource/button/cut.png);background-repeat:no-repeat;");
    openBtn->setStyleSheet("background-image:url(:/resource/button/open.png);background-repeat:no-repeat;");

    this->setStyleSheet("QPushButton{border:none;border-radius:5px;background-color:rgb(64,173,250)}\
                        QPushButton#closeBtn:hover{background-color:rgb(233,31,48);}\
                        QPushButton#cutBtn:hover{background-color:rgb(200,150,100);}");
    hideButton();

    connect(closeBtn,&QPushButton::pressed,this,&DesktopPattern::hide);
    connect(cutBtn,&QPushButton::pressed,this,[=](){
    
    
        curPath=(curPath+1)%pathList.count();
    });
    connect(openBtn,&QPushButton::pressed,this,[=](){
    
    
        QString filename = QFileDialog::getOpenFileName(nullptr,"选择壁纸","./","Image(*jpg *png)");
        if(filename.isEmpty())
            return;
        mWallpaper->setPixmap(filename);
        wallpaperPath= filename;
    });

    closeBtn->installEventFilter(this);
    cutBtn->installEventFilter(this);
    openBtn->installEventFilter(this);
    closeBtn->setToolTip("关闭");
    cutBtn->setToolTip("切换");
    openBtn->setToolTip("壁纸");
}

void DesktopPattern::showButton()
{
    
    
    if(!hoverChoose)
        return;
    closeBtn->show();
    cutBtn->show();
    openBtn->show();
}

void DesktopPattern::hideButton()
{
    
    
    closeBtn->hide();
    cutBtn->hide();
    openBtn->hide();
    timerRunning = false;
}

// 初始化系统托盘
void DesktopPattern::initWindowToSystemTray()
{
    
    
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/resource/icon.ico"));
    trayIcon->setToolTip("桌面挂件动画");

    QMenu *trayMenu = new QMenu(this);
    QAction *hoverChooseAction = new QAction("HoverChoose", this);
    QAction *showAction = new QAction("Show", this);
    QAction *hideAction = new QAction("Hide", this);
    QAction *quitAction = new QAction("Quit", this);
    hoverChooseAction->setIcon(QIcon(":/resource/button/radio_btn_checked.png"));
    showAction->setIcon(QIcon(":/resource/button/sub.png"));
    hideAction->setIcon(QIcon(":/resource/button/quit.png"));
    quitAction->setIcon(QIcon(":/resource/button/shut.png"));

    trayMenu->addAction(hoverChooseAction);
    trayMenu->addAction(showAction);
    trayMenu->addAction(hideAction);
    trayMenu->addAction(quitAction);
    QString styleSheet = "QMenu{background-color: black;}\
                        QMenu::item {color: white;}\
                        QMenu::item:selected {color: yellow;}";
    trayMenu->setStyleSheet(styleSheet);//设置菜单背景色为黑色、字体颜色为白色、选中项字体颜色为黄色

    trayIcon->setContextMenu(trayMenu);

    connect(hoverChooseAction, &QAction::triggered, this, [=](){
    
    
        hoverChoose=!hoverChoose;
        if(hoverChoose)
            hoverChooseAction->setIcon(QIcon(":/resource/button/radio_btn_checked.png"));
        else
            hoverChooseAction->setIcon(QIcon(":/resource/button/radio_btn_normal.png"));
    });

    connect(showAction, &QAction::triggered, this, &DesktopPattern::show);
    connect(hideAction, &QAction::triggered, this, &DesktopPattern::hide);
    //connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
    connect(quitAction, &QAction::triggered, qApp, [=](){
    
    
        // 在应用程序关闭前执行
        setVisible(false);
        QApplication::quit();
    });

    // 显示系统托盘图标
    trayIcon->show();
}

void DesktopPattern::updateRoleAnimation()
{
    
    
    QString qss("background-repeat:no-repeat;");// 关闭重复平铺
    roleLabel->setStyleSheet(qss+pathList.at(curPath).arg(curFrame));
    curFrame= (curFrame+1)%6;
}

wallpaper.h

#ifndef WALLPAPER_H
#define WALLPAPER_H

#include <QWidget>
#include <QLabel>
#include <QFile>
#include <QPixmap>
#include <QHBoxLayout>
#include<qt_windows.h>
#include <Windows.h>
#include<QDebug>
class Wallpaper : public QWidget
{
    
    
    Q_OBJECT
public:
    explicit Wallpaper(QWidget *parent = nullptr);
    ~Wallpaper();
    void setAllWallpaper();
    void restoreAllWallpaper(); // 还原壁纸
    QString getOriginalWallpaperPath();// 获取原壁纸
    void setPixmap(const QString& fileName);
    void setVisible(bool visible)override;
private:
    QLabel* bkLabel;	//放壁纸
    QPixmap bkPixmap;
    QString originalWallpaperPath; // 替换为你保存原始壁纸路径的变量
    QString wallpaperPath; // 替换为你的壁纸文件路径
signals:

};

#endif // WALLPAPER_H

wallpaper.cpp


#include "wallpaper.h"

Wallpaper::Wallpaper(QWidget *parent)
    : QWidget{
    
    parent}
{
    
    
    setWindowFlags(Qt::FramelessWindowHint);// 无窗口的边框
    setAttribute(Qt::WA_TranslucentBackground);// 属性为透明

    bkLabel = new QLabel(this);

    QHBoxLayout *horizon=new QHBoxLayout(this);
    horizon->setMargin(0);// 边界
    horizon->addWidget(bkLabel);

    originalWallpaperPath=getOriginalWallpaperPath();

//    setPixmap(":/resource/wallpaper/1.jpg");
//    setAllWallpaper();
}

Wallpaper::~Wallpaper()
{
    
    

}

void Wallpaper::setAllWallpaper()
{
    
    
#if 0
    //找到桌面的句柄(标识)
//    TCHAR className[MAX_PATH];
//    GetClassName(GetDesktopWindow(), className, MAX_PATH);
//    HWND desktopHwnd = FindWindow(className, nullptr);
     HWND desktopHwnd = GetDesktopWindow();
    if (!desktopHwnd)
    {
    
    
        qDebug() << "查找失败"<< desktopHwnd;
            return;
    }
    //把this设置给找到的窗口
    SetParent((HWND)this->winId(),desktopHwnd);
#endif

}

 // 还原壁纸
void Wallpaper::restoreAllWallpaper()
{
    
    
    // 在应用程序关闭之前将 originalWallpaperPath 设置为原始壁纸的路径
    // 应用程序关闭时恢复原始壁纸
    if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)originalWallpaperPath.utf16(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE))
    {
    
    
            qDebug() << "还原壁纸失败";
            return;
    }
    qDebug() << "还原壁纸成功"<<originalWallpaperPath;
}
// 获取原壁纸
QString Wallpaper::getOriginalWallpaperPath()
{
    
    
    wchar_t wallpaperPath[MAX_PATH];
    if (SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, wallpaperPath, 0))
    {
    
    
            return QString::fromWCharArray(wallpaperPath);
    }
    return QString();
}

void Wallpaper::setPixmap(const QString &fileName)
{
    
    
#if 0
    if(QPixmap(fileName).isNull())
        return;
    bkPixmap.load(fileName);
    bkLabel->setPixmap(bkPixmap);
    this->hide();
    this->showFullScreen();// 全屏显示
#endif
    if(!QFile(fileName).exists())
            return;
    wallpaperPath = fileName;
    if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)wallpaperPath.utf16(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE))
    {
    
    
            qDebug() << "更改壁纸失败";
            return;
    }
    qDebug() << "更改壁纸成功"<<wallpaperPath;
}

void Wallpaper::setVisible(bool visible)
{
    
    
    if(visible)
    {
    
    
        qDebug() << "壁纸显示";
    }
    else
        restoreAllWallpaper();
    QWidget::setVisible(visible);
}

效果

在这里插入图片描述

模糊知识点

  1. 系统托盘应用
#include <QSystemTrayIcon>
#include <QMenu>

trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(QIcon("xxx"));
trayIcon->setToolTip("xxx");

QMenu *trayMenu = new QMenu(this);
QAction *hoverChooseAction = new QAction("HoverChoose", this);
trayMenu->addAction(hoverChooseAction);

trayIcon->setContextMenu(trayMenu);
trayIcon->show();
  1. 当应用程序接收到 quitAction 的触发信号后,会调用 QApplication::quit() 来退出应用程序。因此,在退出之前,可能没有足够的时间来执行 setVisible(bool visible) 方法。
    如果你希望在应用程序退出之前执行一些操作,可以绑定使用 aboutToQuit 信号,该信号在应用程序即将退出时发出
connect(qApp, &QApplication::aboutToQuit, this, [=](void){
    
      });
  1. SystemParametersInfoW Windows API 的函数
SystemParametersInfoW(
    _In_ UINT uiAction,
    _In_ UINT uiParam,
    _Pre_maybenull_ _Post_valid_ PVOID pvParam,
    _In_ UINT fWinIni);
`uiAction`:表示要执行的操作,可以是以下之一:
	SPI_SETDESKWALLPAPER :设置桌面壁纸。
	其他例如 SPI_SETICONMETRICS、SPI_SETKEYBOARDDELAY 等用于设置其他系统参数的标识符。
	
`uiParam`:取决于 uiAction 的值,通常用于传递额外的参数信息。比如,如果 uiAction 是 SPI_SETDESKWALLPAPER,那么 uiParam 可以是 0 或者其他与壁纸设置相关的参数。

`pvParam`:是一个指向参数数据的指针。具体取决于 uiAction 的值以及所需参数类型。例如,如果 uiAction 是 SPI_SETDESKWALLPAPER,那么 pvParam 应该是指向壁纸文件路径的指针。

`fWinIni`:是一个标志,指示是否应更新用户配置文件中的设置并通知系统更改。可以使用以下标志之一或它们的组合:
	SPIF_UPDATEINIFILE:将更改写入用户配置文件(如 INI 文件)。		
	SPIF_SENDCHANGE:在更改后立即向其它组件发送系统更改通知。
// 设置桌面壁纸
QString wallpaperPath="xxx";
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)wallpaperPath.utf16(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)


// 获取桌面壁纸路径
wchar_t wallpaperPath[MAX_PATH];
if (SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, wallpaperPath, 0))
{
    
    
        return QString::fromWCharArray(wallpaperPath);
}

猜你喜欢

转载自blog.csdn.net/qq_47355554/article/details/131435969