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);
}

效果

image.png

CSDN

模糊知识点

  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);
}
相关文章
|
Linux
QT桌面(实现界面的滑动切换)
QT桌面(实现界面的滑动切换)
254 0
|
JSON 自然语言处理 图形学
|
图形学
unity3d UGUI常用游戏进度条实现方式
测试.png 直接将脚本挂载到进度条image对象上即可,这种方式可以解决当进度条使用图片的时候,防止图片拉伸变形 using UnityEngine; using UnityEngine.
3022 0
|
6月前
|
开发工具 图形学
【推荐100个unity插件之11】Shader实现UGUI的特效——UIEffect为 Unity UI 提供视觉效果组件
【推荐100个unity插件之11】Shader实现UGUI的特效——UIEffect为 Unity UI 提供视觉效果组件
416 0
QT圆形进度条(QT桌面项目光照强度检测)
QT圆形进度条(QT桌面项目光照强度检测)
129 0
|
API iOS开发 Perl
iOS UIButton图文混排快捷显示
iOS UIButton图文混排快捷显示
iOS UIButton图文混排快捷显示
|
iOS开发
iOS开发- 分屏动画
iOS开发- 分屏动画
142 0
iOS开发- 分屏动画
|
JSON Android开发 数据格式
原生app开发技巧——底部导航栏动画效果按钮制作方法之采用photoshop制作gif动画-过渡动画关键帧
原生app开发技巧——底部导航栏动画效果按钮制作方法之采用photoshop制作gif动画-过渡动画关键帧
原生app开发技巧——底部导航栏动画效果按钮制作方法之采用photoshop制作gif动画-过渡动画关键帧
|
C++
Qt界面优化:鼠标双击特效
Qt界面优化:鼠标双击特效
246 1
Qt界面优化:鼠标双击特效