前言
最近换了 windows11 系统,感觉 windows11 的安全做的比 windows10 好了很多,就没再使用其他的安全管理软件,但是我又想只查看内存的使用率,有没有一个好的软件,就尝试着使用 QT 自己写了一个,过程中查阅了很多资料,都没有完整的实现说明,所以写了这篇文章说说我是如何完成自己的内存显示小程序的。
环境介绍
我是用的是 QT-5.14.2
windows11 系统
准备资源
我们需要准备一张图片用作背景,我这里准备了两张图片,一张是全白的正方形图片和一张半透明的正方形图片
一张图片用于退出菜单图标
这里我是希望在调试程序的时候能够看到背景,用于调整数字的位置,但是完成之后我又想要透明的效果,所以我的是两张图片,这里准备的图片最好是中间显示部分为白色,这样比较容易看清。
创建项目
- 我这里创建了一个名为
RAMshow
的应用程序 -
Details
中Base class
选的QWidget
-
Kits
选的MinGW 64bit
其他的选项默认即可
导入资源图片
依次点击 文件 -> 新建文件或项目 -> Qt -> Qt Resource File
名称我填的 res
,下一步,点击完成。
添加路径,点击 Add Prefix
, 修改前缀为 /res
。
添加文件,点击Add Files
将之前的所有图片添加进来
点击build构建项目
需要注意,这里我的图片是放在项目里面的,我在项目中新建了一个
res
的文件夹,将图片放在了这里面,不然程序运行可能无法使用
目录结构如下:
资源文件如下:
显示托盘图标
参考文章 :
https://blog.csdn.net/u012952807/article/details/70670410?spm=1001.2014.3001.5501
我们需要使用以下头文件:
#include // 操作托盘的类
#include
在widget.h
中添加头文件,添加以下代码:
private:
QSystemTrayIcon *icon; // 托盘图像
QPixmap image;
在widget.cpp构造函数中初始化:
// :/res/res/ram_show_no_transparent.png 此路径在资源图片上右键,选择`Copy Path`即可复制
image.load(":/res/res/ram_show_no_transparent.png");
icon = new QSystemTrayIcon(this);
icon->setIcon(image);
icon->show()
此时可以在托盘中看见一个白色的正方形。
获取内存信息并显示在图标上
参考文章
https://blog.csdn.net/u012952807/article/details/70674034?spm=1001.2014.3001.5501
需要使用一下头文件:
#include
#include
#include
在widget.h
中添加头文件,添加以下代码:
private:
QPainter *painter; //画笔,将数字画到图片上
QTimer *timer; // 添加定时器,用于刷新内存信息
QFont font; // 设置数字的显示样式
private slots:
void update(); // 用于刷新icon的数字
在widget.cpp构造函数中初始化:
painter = new QPainter();
font.setPointSize(65); //设置字体大小
font.setBold(true); // 是否加粗
timer = new QTimer(this); // 初始化定时器
添加 update()
函数的定义:
void Widget::update()
{
// 获取内存使用率
MEMORYSTATUSEX statusex;
statusex.dwLength=sizeof(statusex);
GlobalMemoryStatusEx(&statusex);
long s = statusex.dwMemoryLoad;
// 在原有的图片上添加数字
QPixmap base = image;
// 将长整型转为字符类型
QString text = QString::number(s);
painter->begin(&base);
painter->setFont(font);
// 前两个参数是坐标,根据自己的实际情况修改
painter->drawText(2, 75, text);
painter->end();
// 修改托盘图标
icon->setIcon(QIcon(base));
}
运行程序,可以看到右下角的图标上出现了数字。
添加右键菜单
参考文章 :
https://www.cxyzjd.com/article/weixin_42126427/106697190
之前的程序没有设置菜单用于退出,所以我们每次运行都有一个窗口,现在,我们将窗口显示注释掉。
在main.cpp
中将 w.show()
注释掉。
接着我们给程序的托盘图标添加右键菜单
在 widget.cpp
中添加:
#include
在初始化方法中添加代码:
需要写到
icon->setIcon(QIcon(image));
的后面,icon->show();
前面
// 添加右键菜单
QMenu *menu = new QMenu(this);
QAction *quit = new QAction("退出", this);
// 为菜单按钮添加图标
quit->setIcon(QIcon(":/res/res/quit.png"));
menu->addAction(quit);
icon->setContextMenu(menu);
// 绑定退出
connect(quit, &QAction::triggered, qApp, &QApplication::quit);
运行项目,由于注释了main函数中的show()方法,运行是不会像之前一样弹出窗口,右键托盘图标,点击退出,功能正常就表示成功了。
添加开机自启
参考文章
https://www.i4k.xyz/article/thequitesunshine007/119605740
开机启动需要使用到两个类,在widget.h
中添加:
#include
#include
public:
//添加函数
void setAutoRun();
添加自启动需要修改注册表,路径为
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
在widget.cpp
中初始化函数:
// 在`include`后面添加一行
#define AUTO_RUN "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
// 定义函数
void Widget::setAutoRun()
{
// 注册表是以 key-value 形式存储的,一般使用程序名称作为 key
// 64 bit的系统使用 QSettings::Registry64Format, 32bit 使用 QSettings::Registry32Format
QSettings *settings = new QSettings(AUTO_RUN, QSettings::Registry64Format);
QString application_name = QApplication::applicationName();//获取应用名称
QString path = settings->value(application_name).toString();
QString appPath = QApplication::applicationFilePath();//找到应用的目录
QString newPath = QDir::toNativeSeparators(appPath);
if (path != newPath)
{
settings->setValue(application_name, newPath);
}
}
在main函数中调用方法
w.setAutoRun();
// w.show();
运行程序,查看注册表,可以看见一个以程序名称为key的值存在,表示成功。
最后修改icon
为透明效果。
到这里就全部完工了。
源码
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void setAutoRun();
private:
Ui::Widget *ui;
QSystemTrayIcon *icon;
QPixmap image;
QPainter *painter;
QTimer *timer;
QFont font;
private slots:
void update();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include
#include
#include
#define AUTO_RUN "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
painter = new QPainter();
font.setPointSize(65);
font.setBold(true);
timer = new QTimer(this);
image.load(":/res/res/ram_show_no_transparent.png");
icon = new QSystemTrayIcon(this);
icon->setIcon(image);
// 添加右键菜单
QMenu *menu = new QMenu(this);
QAction *quit = new QAction("退出", this);
// 为菜单按钮添加图标
quit->setIcon(QIcon(":/res/res/quit.png"));
menu->addAction(quit);
icon->setContextMenu(menu);
// 绑定退出
connect(quit, &QAction::triggered, qApp, &QApplication::quit);
icon->show();
// 刚启动时进行一次跟新
update();
// 设置定时器,每隔3s跟新一次
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(3000);
}
Widget::~Widget()
{
delete ui;
}
void Widget::setAutoRun()
{
QSettings *settings = new QSettings(AUTO_RUN, QSettings::Registry64Format);
QString application_name = QApplication::applicationName();//获取应用名称
QString path = settings->value(application_name).toString();
QString appPath = QApplication::applicationFilePath();//找到应用的目录
QString newPath = QDir::toNativeSeparators(appPath);
if (path != newPath)
{
settings->setValue(application_name, newPath);
}
}
void Widget::update()
{
// 获取内存使用率
MEMORYSTATUSEX statusex;
statusex.dwLength=sizeof(statusex);
GlobalMemoryStatusEx(&statusex);
long s = statusex.dwMemoryLoad;
// 在原有的图片上添加数字
QPixmap base = image;
// 将长整型转为字符类型
QString text = QString::number(s);
painter->begin(&base);
painter->setFont(font);
// 前两个参数是坐标,更具自己的实际情况修改
painter->drawText(2, 75, text);
painter->end();
// 修改托盘图标
icon->setIcon(QIcon(base));
}
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setAutoRun();
// w.show();
return a.exec();
}