動態(tài)壁紙軟件開發(fā)
項目源代碼在下面鏈接獲取:
-----------------------------
開發(fā)者:CodeSharkSJ
希望此項目能加強(qiáng)你對Qt的應(yīng)用
文章目錄
- 項目圖與開發(fā)環(huán)境
- 核心技術(shù)原理
- 自定義窗口程序
- UI布局
- 背景繪制
- 樣式表
- 基本實現(xiàn)
- QWebEngine
- QMedia使用
- 系統(tǒng)托盤隱藏
- 記憶功能
- 應(yīng)用程序打包
項目圖與開發(fā)環(huán)境
開發(fā)環(huán)境: visual studio 2022 + Qt 5.14.1
項目圖解:
?核心技術(shù)原理
桌面圖標(biāo)后面有一個背景窗體,這個窗體沒有名字,但是類型屬于workerW??
它的父類是Program Maneger,
遍歷所有workerW類型的窗體,逐一比較它的父窗體是不是Program Manager就可以找到背景窗體。 但如果沒有找到可以發(fā)送消息生成一個生成一個WorkerW窗體,設(shè)置為Program Manager的兒子,再在此上面播放視頻。
自定義窗口程序
打開VS2022創(chuàng)建 [? Qt Widgets Application? ?]
這里Base Class(基類)你必須選擇Qwidget?
?立即編譯運(yùn)行 ,能正常運(yùn)行就開始下面步驟?。
鼠標(biāo)無法拖動窗口
您需要添加額外的代碼
1.在頭文件添加兩個繼承的方法和一個私有的數(shù)據(jù)成員? ??
#include <qevent.h>
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
private:
QPoint _Point;
2.實現(xiàn)
? ?mousePressEvent? // 鼠標(biāo)按下事件
? ?
void Wallpaper::mousePressEvent(QMouseEvent* event)
{
_Point = event->globalPos() - this->pos();
}
? mouseMoveEvent?? // 鼠標(biāo)移動事件
??
void Wallpaper::mouseMoveEvent(QMouseEvent* event)
{
move(event->globalPos() - _Point);
}
UI布局
?打開
右上角皮膚,設(shè)置,最小化 ,關(guān)閉
圖標(biāo)文件自行準(zhǔn)備,在屬性欄添加。
我會把項目發(fā)給你們????
刷新率選擇
60HZ設(shè)置固定(因為暫時沒有120的方案)
調(diào)節(jié)音量
?
設(shè)置步長1,旁邊是標(biāo)簽? 設(shè)置為0
? ? ? ?
?------------------------
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WallpaperClass</class>
<widget class="QWidget" name="WallpaperClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1370</width>
<height>827</height>
</rect>
</property>
<property name="windowTitle">
<string>Wallpaper</string>
</property>
<property name="windowIcon">
<iconset resource="Wallpaper.qrc">
<normaloff>:/Wallpaper/ico/Wall.png</normaloff>:/Wallpaper/ico/Wall.png</iconset>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="Line" name="line">
<property name="geometry">
<rect>
<x>0</x>
<y>40</y>
<width>1381</width>
<height>16</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>131</width>
<height>21</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<family>微軟雅黑</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Wallpaper</string>
</property>
</widget>
<widget class="QPushButton" name="closeBtn">
<property name="geometry">
<rect>
<x>1325</x>
<y>13</y>
<width>33</width>
<height>29</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#closeBtn:hover{
background-color: rgb(219, 0, 0);
color: rgb(255, 255, 255);
border-radius: 1px;
}</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Wallpaper.qrc">
<normaloff>:/Wallpaper/MS/CLOSE.png</normaloff>:/Wallpaper/MS/CLOSE.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="SkinBtn">
<property name="geometry">
<rect>
<x>1200</x>
<y>11</y>
<width>37</width>
<height>33</height>
</rect>
</property>
<property name="toolTip">
<string>更換主題</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#SkinBtn:hover{
background-color: rgb(90, 90,90);
color: rgb(255, 255, 255);
border-radius: 1px;
}</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Wallpaper.qrc">
<normaloff>:/Wallpaper/MS/theme.png</normaloff>:/Wallpaper/MS/theme.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="setBtn">
<property name="geometry">
<rect>
<x>1243</x>
<y>11</y>
<width>37</width>
<height>33</height>
</rect>
</property>
<property name="toolTip">
<string>更多選項</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#setBtn:hover{
background-color: rgb(90, 90,90);
color: rgb(255, 255, 255);
border-radius: 1px;
}</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
...
背景繪制
默認(rèn)為黑色,點(diǎn)換膚按鈕更換
QString tempBg = ConfigFile->value("ckbg").toString(); // 啟動程序看配置文件里的背景文件名
if (tempBg != "") // 有就設(shè)置
{
startBg(tempBg);
}
else
{
QPalette pal;
pal.setColor(QPalette::Background, QColor(46, 46, 46));
this->setPalette(pal);
}
void Wallpaper::startBg(QString file)
{
QPalette pal = this->palette();
pal.setBrush(QPalette::Background, QBrush(QPixmap(file)));
setPalette(pal);
}
void Wallpaper::onSkinBtn()
{
QString tempFile = QFileDialog::getOpenFileName(this, "選擇圖片", "", "src(*.jpg *.png *.jpeg)"); // 選擇背景圖
ConfigFile->setValue("ckbg", tempFile); // 寫到tempFile下次啟動就加載 ini
startBg(tempFile); // 設(shè)置背景的函數(shù)
}
?樣式表
qss(樣式表)參考了css 但是并不能像css那樣炫酷。
為按鈕添加樣式表:
關(guān)閉:
QPushButton#closeBtn:hover{ #鼠標(biāo)浮在上面的效果
background-color: rgb (219, 0, 0);
color: rgb(255, 255, 255);
border-radius: 1px;
}
最小化:
QPushButton#minBtn:hover{
background-color: rgb(90, 90,90);
color: rgb(255, 255, 255);
border-radius: 1px;
}
設(shè)置:
QPushButton#setBtn:hover{
background-color: rgb(90, 90,90);
color: rgb(255, 255, 255);
border-radius: 1px;
}
改一下顏色
color: rgb(149, 149, 149)
拉動條? ? :
?
QSlider::groove:horizontal {
border: 0px solid #bbb;
}
QSlider::sub-page:horizontal {
background: rgb(90,49,255);
border-radius: 2px;
margin-top:8px;
margin-bottom:8px;
}
QSlider::add-page:horizontal {
background: rgb(255,255, 255);
border: 0px solid #777;
border-radius: 2px;
margin-top:9px;
margin-bottom:9px;
}
QSlider::handle:horizontal {
background: rgb(193,204,208)
width: 5px;
border: 1px solid rgb(193,204,208);
border-radius: 2px;
margin-top:6px;
margin-bottom:6px;
}
QSlider::handle:horizontal:hover {
background: rgb(193,204,208);
width: 10px;
border: 1px solid rgb(193,204,208);
border-radius: 5px;
margin-top:4px;
margin-bottom:4px;
}
基本實現(xiàn)
??右上角按鈕實現(xiàn)
頭文件添加槽,在構(gòu)造函數(shù)內(nèi)進(jìn)行信號連接。
private slots:
void onCloseBtn();
void onMinBtn();
void onSetBtn();
void onSkinBtn();
? ? ?構(gòu)造函數(shù)內(nèi)添加
connect(ui.closeBtn,SIGNAL(clicked()),this,SLOT(onCloseBtn()));
connect(ui.minBtn, SIGNAL(clicked()), this, SLOT(onMinBtn()));
connect(ui.setBtn, SIGNAL(clicked()), this, SLOT(onSetBtn()));
connect(ui.SkinBtn, SIGNAL(clicked()), this, SLOT(onSkinBtn()));
? ? ? ? ?
???closeBtn:
? ? ?
void Wallpaper::onCloseBtn()
{
hide(); // 隱藏用于托盤顯示
//close();
}
? ? ??onMinBtn{ showMinimized();? ? }? ??
? ? ??onSetBtn { /* 暫不實現(xiàn)? */?}
? ? ??onSkinBtn? // 換膚
QString tempFile = QFileDialog::getOpenFileName(this, "選擇圖片", "", "src(*.jpg *.png *.jpeg)"); // user選擇背景圖
ConfigFile->setValue("ckbg", tempFile); // 寫 到tempFile下次啟動就加載
startBg(tempFile); // 設(shè)置背景的函數(shù)
??隱藏到托盤
? ?使用#include <qsystemtrayicon.h> 實現(xiàn)
? ?定義數(shù)據(jù)成員 在頭文件?QSystemTrayIcon* systemtrayicon;?
? ?由于有大量的彈出菜單,我們把彈出菜單的需要的東西封在initSpecific()
? ??
void Wallpaper::initSpecific()
{
systemtrayicon = new QSystemTrayIcon(QIcon(":/Wallpaper/ico/Wall.png"));
systemtrayicon->setToolTip(("動態(tài)壁紙:運(yùn)行中"));
systemtrayicon->show();
QMenu* tray_Menu = new QMenu(this);
/*托盤彈出的菜單*/
QAction* action1 = new QAction("顯示主界面");
QAction* action2 = new QAction("退出壁紙");
tray_Menu->setStyleSheet("background-color: rgb(92,92,92);");
tray_Menu->addAction(action1);
tray_Menu->addSeparator();
tray_Menu->addAction(action2);
systemtrayicon->setContextMenu(tray_Menu); // 放入
connect(action1, SIGNAL(triggered(bool)), this, SLOT(onAction1())); // 注意信號
connect(action2, SIGNAL(triggered(bool)), this, SLOT(onAction2()));
}
??主界面切換
三個按鈕
?三按鈕槽函數(shù)
private slots:
void onInstalledBtn();
void onDiscovBtn();
void onMoberBtn();
void Wallpaper::onInstalledBtn()
{
ui.stackedWidget->setCurrentIndex(0);
}
void Wallpaper::onDiscovBtn()
{
ui.stackedWidget->setCurrentIndex(1);
}
void Wallpaper::onMoberBtn()
{
ui.stackedWidget->setCurrentIndex(2);
}
// 默認(rèn)在你設(shè)計后停留的頁面
??拉動條
void Wallpaper::onSliderSetNum(int num)
{
ui.valuseShow->setText(QString::number(num)); //拉動了就設(shè)置旁邊的標(biāo)簽
mediaPlayer->setVolume(num); // 根據(jù)標(biāo)簽設(shè)置音量 這個mediaPlayer后面會寫
}
connect(ui.vloueQSlider, SIGNAL(valueChanged(int)), SLOT(onSliderSetNum(int))); // 當(dāng)進(jìn)度條拉動 valueChanged發(fā)射信號
????????
QWebEngine使用
顯示網(wǎng)頁
#include <QWebEngineView>
// 網(wǎng)址
ui.webEngineView->load(QUrl("https://www.pgyer.com/0uTR"));
把這個放在界面上
QMedia使用
#include <QMediaPlayer>
#include <QMediaPlaylist> // 播放列表 用于循環(huán)播放
#include <QVideoWidget> // 播放視頻的窗口
QVideoWidget* videoWidget;
QMediaPlayer* mediaPlayer;
QMediaPlaylist* Videolist;
Videolist = new QMediaPlaylist;
mediaPlayer = new QMediaPlayer;
videoWidget = new QVideoWidget;
談一談這個按鈕,按下后選擇視頻,并在桌面顯示出來??
?先來個查找的工具,用于殺死視頻窗口,不然釋放
QVideoWidget還是會播放。
工具:
#include <Windows.h>
//獲取背景窗體句柄
HWND GetBackground() {
//背景窗體沒有窗體名,但是知道它的類名是workerW,且有父窗體Program Maneger,所以只要
//遍歷所有workerW類型的窗體,逐一比較它的父窗體是不是Program Manager就可以找到背景窗體
HWND hwnd = FindWindowA("progman", "Program Manager");
HWND worker = NULL;
do {
worker = FindWindowExA(NULL, worker, "workerW", NULL); // 根據(jù)類名獲取窗體句柄
if (worker != NULL) {
char buff[200] = { 0 };
int ret = GetClassNameA(worker, (PCHAR)buff, sizeof(buff) * 2);
if (ret == 0) {
return NULL;
}
}
if (GetParent(worker) == hwnd) {
return worker;//返回結(jié)果
}
} while (worker != NULL);
//沒有找到
//發(fā)送消息生成一個WorkerW窗體
SendMessage(hwnd, 0x052C, 0, 0);
//重復(fù)上面步驟
do {
worker = FindWindowExA(NULL, worker, "workerW", NULL);
if (worker != NULL) {
char buff[200] = { 0 };
int ret = GetClassNameA(worker, (PCHAR)buff, sizeof(buff) * 2);
if (ret == 0) {
return NULL;
}
}
if (GetParent(worker) == hwnd) {
return worker;//返回結(jié)果
}
} while (worker != NULL);
return NULL;
}
void SetBackground(HWND child) {
SetParent(child, GetBackground()); // 把視頻窗口設(shè)置為Program Manager的兒子
}
??按鈕的實現(xiàn)
void onGetVideo(); // 槽
connect(ui.getVideo, SIGNAL(clicked()), this, SLOT(onGetVideo()));
void Wallpaper::onGetVideo()
{
if (isPlay == false) // 判斷是否有過視頻窗口
{
QString file;
file = QFileDialog::getOpenFileName(this, "選擇圖片或視頻", "", "src(*.mp4)");
ConfigFile->setValue("videos", file); // 寫入配置文件
isPlay = true; // 現(xiàn)在有了
showVoide(file); // 放視頻具體操作
}
else
{
// 不創(chuàng)建窗口模式 直接設(shè)置播放列表里面的視頻
mediaPlayer->stop();
QString file;
file = QFileDialog::getOpenFileName(this, "選擇圖片或視頻", "", "src(*.mp4)");
ConfigFile->setValue("videos", file);
NextVideo(file); // 啟動下一個視頻
}
return;
}
showVoide
void Wallpaper::showVoide(QString Name)
{
HWND hwnd = (HWND)videoWidget->winId(); //獲取播放視頻的窗口id
SetBackground(hwnd);
videoWidget->setWindowFlags(Qt::FramelessWindowHint); // // 隱藏標(biāo)題欄
videoWidget->showFullScreen(); // 最大化顯示
/*
this->windowClose = tempWork; //獲取子窗口id后面用來關(guān)閉
2023年1月29日21:30:01 發(fā)現(xiàn)bug 這段代碼是直接關(guān)了系統(tǒng)背景資源管理器會崩潰
*/
this->windowClose = hwnd; // 到時候直接殺播放視頻的窗口就行了 但會留下壁紙
// mediaPlayer為播放控制器 用于啟動播放 Videolist是播放列表
Videolist->addMedia(QMediaContent(QUrl::fromLocalFile(Name)));// 設(shè)置要播放的文件路徑
Videolist->setCurrentIndex(0);
Videolist->setPlaybackMode(QMediaPlaylist::Loop); // 循環(huán)
mediaPlayer->setVideoOutput(videoWidget); // 設(shè)置視頻輸出窗口
mediaPlayer->setPlaylist(Videolist);
mediaPlayer->play();
}
NextVideo
void Wallpaper::NextVideo(QString Name)
{
Videolist->clear();
Videolist->addMedia(QMediaContent(QUrl::fromLocalFile(Name)));
mediaPlayer->play();
}
記憶功能
程序啟動時檢查配置文件,進(jìn)行響應(yīng)的調(diào)度?。
QSettings可以提供方便的ini配置操作
#include <QSettings>
QString GetAPPDATAFolder()
{
wchar_t path[255] = { 0 };
SHGetSpecialFolderPath(
NULL,
path,
CSIDL_APPDATA,
FALSE
);
QString rlt = QString::fromWCharArray(path);
return rlt;
}
QString folder = GetDesktopFolder(); //獲取用戶數(shù)據(jù)文件夾 一般配置文件放里面
folder.append("\\Wallpaper_user.ini");
ConfigFile = new QSettings(folder, QSettings::IniFormat);
ConfigFile->beginGroup("USERRCONFIG"); // 節(jié)點(diǎn)名
QString tempBg = ConfigFile->value("ckbg").toString(); // 讀這個ckbg下的數(shù)據(jù)
// ConfigFile->setValue("ckbg", tempFile); // 寫
// 加載上次設(shè)置的視頻
QString tempVid = ConfigFile->value("videos").toString();
if (tempVid != "")
{
if (isPlay == false)
{
isPlay = true;
showVoide(tempVid);
}
}
應(yīng)用程序打包
如何在讓程序在別的計算機(jī)執(zhí)行
一、使用這個工具????????
?找不到用Everything?搜。
選Release 和 x64 編譯
?打開終端程序,進(jìn)入程序所在目錄
?輸入??
windeployqt D:\local\Wallpaper.exe
會自動加載所需。
二、Enigma Virtual Box
虛擬目錄
使一些dll和其他文件隱藏,只有exe程序。
---------------------------------------------------------
由于沒有使用MD編輯文章,觀感可能不舒服,請見諒。
有問題私信
------------------------------------------------------------
源代碼:文章來源:http://www.zghlxwxcb.cn/news/detail-451235.html
鏈接:https://pan.baidu.com/s/1-HUPkdniFPPHUJ2B8AC0wQ?pwd=sjfd?
提取碼:sjfd文章來源地址http://www.zghlxwxcb.cn/news/detail-451235.html
到了這里,關(guān)于QT開發(fā)實戰(zhàn)-動態(tài)壁紙軟件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!