学qt有一阵子,今天正好有闲心写篇博客。
项目介绍
写个展示动漫小姐姐的软件(图片资源网上找的)
效果如下
实现原理并不难。简单讲述一下思路。工具是用vs2022 cmake构建
一个主窗口 去除边框 窗口透明 然后支持拖。剩下的就是对界面进行美化用qss美化 (说实话美化比mfc方便多了,界面友好)。
最后附上软代码有兴趣的可以自己编译运行。当前项目使用的环境是QT5。 编译时更改一下qt路径即可。
代码展示
主程序代码
#include "MyDesktopSoft.h"
#include "eventfilterobject.h"
#include <QResizeEvent>
#include <QTimer>
#include <QFile>
MyDesktopSoft::MyDesktopSoft(QWidget *parent):QWidget(parent)
{
this->init_ui();
}
void MyDesktopSoft::updateRoleModelAnimation()
{
m_frames = m_roleModels[m_currentRole].size();
m_roleModelLabel->setPixmap(m_roleModels[m_currentRole][m_index]);
m_index = (m_index + 1) % m_frames;
}
void MyDesktopSoft::init_ui()
{
setFixedSize(350, 640);
setWindowFlag(Qt::FramelessWindowHint); //取消窗口边框
setWindowFlag(Qt::WindowStaysOnTopHint);//窗口置顶
setAttribute(Qt::WA_TranslucentBackground);//窗口背景透明
installEventFilter(new eventFilterObject(this)); // 捕获窗口拖拽
//添加人物资源
RoleModel roleModel;
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/blackGril/action1-happy/%1.png").arg(i));
}
m_roleModels.insert("blackGril/happy", roleModel);
roleModel.clear();
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/blackGril/action2-sad/%1.png").arg(i));
}
m_roleModels.insert("blackGril/sad", roleModel);
roleModel.clear();
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/blackGril/action3-naughty/%1.png").arg(i));
}
m_roleModels.insert("blackGril/naughty", roleModel);
roleModel.clear();
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/blackGril/action4-shy/%1.png").arg(i));
}
m_roleModels.insert("blackGril/shy", roleModel);
roleModel.clear();
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/littleBoy/%1.png").arg(i));
}
m_roleModels.insert("littleBoy", roleModel);
roleModel.clear();
for (int i = 0; i < 6; i++) {
roleModel.addFrame(QString(":/assets/desktopRole/summerGril/%1.png").arg(i));
}
m_roleModels.insert("summerGril", roleModel);
m_roleModelLabel = new QLabel(this);
m_wallpaper = new Wallpaper;
QTimer* timer = new QTimer(this);
timer->callOnTimeout(this,&MyDesktopSoft::updateRoleModelAnimation);
timer->start(600);
m_currentRole = "summerGril"; //默认情况下是 summerGril
updateRoleModelAnimation();
m_closeBtn = new QPushButton(this);
m_settingBtn = new QPushButton(this);
m_closeBtn->move(240, 300);
m_settingBtn->move(240, 340);
m_closeBtn->setObjectName("closeBtn");
m_settingBtn->setObjectName("settingBtn");
QFile file(":/assets/style.css");
if (file.open(QIODevice::ReadOnly)) {
this->setStyleSheet(file.readAll());
}
m_setting = new Setting;
connect(m_closeBtn, &QPushButton::released, this, &MyDesktopSoft::close);
connect(m_settingBtn, &QPushButton::released, m_setting, &QWidget::show);
//当主界面关闭时通知附界面关闭
connect(m_closeBtn, &QPushButton::released, m_setting, &QWidget::close);
//附属界面给主界面发送消息 模型更换了
connect(m_setting, &Setting::roleModelChanged, this, [=](const QString& role) {
m_currentRole = role;
});
connect(m_setting, &Setting::wallpaperChanged, m_wallpaper, &Wallpaper::setWallpaper);
}
MyDesktopSoft::~MyDesktopSoft()
{
//申请的指针都要去释放 最后
if (m_setting) {
delete m_setting;
}
if (m_closeBtn) {
delete m_closeBtn;
}
if (m_settingBtn) {
delete m_settingBtn;
}
if (m_roleModelLabel) {
delete m_roleModelLabel;
}
if (m_wallpaper) {
delete m_wallpaper;
}
}
void MyDesktopSoft::resizeEvent(QResizeEvent* ev)
{
m_roleModelLabel->resize(ev->size());
}
void MyDesktopSoft::mousePressEvent(QMouseEvent* ev)
{
if (ev->button() == Qt::MouseButton::RightButton) {
m_closeBtn->setVisible(!m_closeBtn->isVisible());
m_settingBtn->setVisible(!m_settingBtn->isVisible());
}
}
响应鼠标拖拽 代码片段
#include "eventfilterobject.h"
#include<QMouseEvent>
#include<QWidget>
eventFilterObject::eventFilterObject(QObject *parent) : QObject(parent)
{
}
bool eventFilterObject::eventFilter(QObject *watched, QEvent *ev)
{
auto* mouseEv = static_cast<QMouseEvent*>(ev);
static QPoint dis;
if(ev->type() == QEvent::MouseButtonPress)
{
dis = mouseEv->pos();
}
else if(ev->type() == QEvent::MouseMove && mouseEv->buttons()&Qt::LeftButton
&& !dis.isNull())
{
auto *pthis = static_cast<QWidget*>(watched);
//if(pthis->parent()==nullptr)
pthis->move(mouseEv->globalPos() - dis);
//pthis->move(pthis->mapToParent(mouseEv->pos()) - dis);
}
else if(ev->type() == QEvent::MouseButtonRelease)
{
dis = QPoint();
}
return false;
}
查找顶层窗口类
头文件
#ifndef FINDDEKTOPHWND_H
#define FINDDEKTOPHWND_H
#include<qt_windows.h>
class QWidget;
class FindDektopHwnd
{
public:
FindDektopHwnd();
static BOOL CALLBACK EnumWindowsProc(_In_ HWND tophandle, _In_ LPARAM topparamhandle);
/*
* @return 返回桌面句柄
*/
static HWND GetDesktopHandle();
/**
* @param child 是需要设置为子窗口的控件.
* @param parent 是空则把child设置为桌面的孩子,否则设置为parent的孩子
*/
static void SetParent(QWidget*child,HWND parent);
inline static HWND _workerw = NULL;
};
#endif // FINDDEKTOPHWND_H
cpp文件
#include "finddektophwnd.h"
#include<QWidget>
FindDektopHwnd::FindDektopHwnd()
{
}
BOOL CALLBACK FindDektopHwnd::EnumWindowsProc(_In_ HWND tophandle, _In_ LPARAM topparamhandle)
{
HWND defview = FindWindowExW(tophandle, 0, L"SHELLDLL_DefView", NULL);
if (defview != NULL)
{
_workerw = FindWindowExW(0, tophandle, L"WorkerW", 0);
}
return true;
}//遍历句柄的回调函数
HWND FindDektopHwnd::GetDesktopHandle()
{
ULONG_PTR result;
HWND windowHandle = FindWindowW(L"Progman", NULL);
SendMessageTimeout(windowHandle, 0x052c, 0, 0, SMTO_NORMAL, 0x3e8, (PDWORD_PTR)&result);
EnumWindows(EnumWindowsProc, (LPARAM)NULL);
ShowWindow(_workerw, SW_HIDE);
return windowHandle;
}
void FindDektopHwnd::SetParent(QWidget *child, HWND parent)
{
HWND dekstopHwnd = parent;
if(parent == nullptr)
{
//获取桌面的窗口句柄
dekstopHwnd = FindDektopHwnd::GetDesktopHandle();
}
//把dekstopHwnd设置为父对象
::SetParent((HWND)child->winId(),(HWND)dekstopHwnd);
}
身下的就是一些细碎处理事件
唉,剩下的代码就不一一展示了,都在附件中有需要的可以自提