使用 QT6 实现一个截图软件

使用 QT6 实现一个截图软件

完整代码见 Hardews/ScreenCutTool: 用 QT6 实现的一个简易截图软件

功能实现简介

启动时最小化到托盘,点击托盘中的软件图标时启动截图

使用 QT 提供的 QSystemTrayIcon ,并拦截 closeEvent 事件,使程序关闭时是隐藏而不是退出。

1
2
3
4
5
6
7
8
// 托盘
tray = new QSystemTrayIcon(this);// 初始化托盘对象 tray
tray->setIcon(QIcon("://logo/logo.svg")); // 托盘图标
tray->setToolTip("截图工具 学习版\n截图快捷键: Ctrl+Alt+F"); // 提示文字
QString title="截图工具";
QString text="截图工具已启动";
tray->show();
tray->showMessage(title, text, QSystemTrayIcon::Information, 3000);
1
2
3
4
5
6
7
8
void main_window::closeEvent(QCloseEvent *event)
{
if(tray->isVisible())
{
hide(); // 隐藏窗口
event->ignore(); // 忽略事件
}
}

快捷键截图

这里用的是外部库 QHotKey,就可以在程序隐藏到托盘时监听快捷键。

1
2
3
4
5
6
QHotkey *hotkey = new QHotkey(QKeySequence("Ctrl+Alt+F"), true);
// 连接热键被按下的信号与槽
QObject::connect(hotkey,&QHotkey::activated,[=](){
// 热键被按下的处理代码段
ScreenWidget::Instance()->showFullScreen();
});

将截图复制到剪贴板

通过 QT 提供的获取剪贴板内容的对象,然后 setPixmap 即可。

当点击确认按钮或者需要复制到剪切板时,执行函数。

1
2
3
4
5
void ScreenWidget::saveScreenToClip(QPixmap screen)
{
QClipboard *clip = QApplication::clipboard();
clip->setPixmap(screen);
}

截图区域绘制完毕后的操作菜单

先添加布局,然后平时隐藏。当鼠标点击释放时(这时候肯定是结束移动,或者截图完毕了),通过最新的坐标,调整菜单的位置并展示。

然后鼠标点击以及鼠标移动时,将菜单隐藏即可。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void ScreenWidget::paintOperatorMenu()
{
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;

// 绘制菜单项
int buttonX = x; // 与截图区域左对齐
int buttonY = y + h + 5;

// 如果按钮栏会超出窗口底部,进行适当的调整
if (buttonY + buttonContainer->height() > this->height()) {
buttonY = this->height() - buttonContainer->height() - 5; // 防止超出窗口底部
}
buttonContainer->move(buttonX, buttonY);
buttonContainer->resize(w, buttonContainer->height());
buttonContainer->show();
}

打包成安装文件

参考 《Qt5+安装包制作(Qt Installer Framework)》

遇到的问题

connect 链接菜单按钮,点击菜单按钮无反应

原因为旧语法不适用,无法绑定,改为新语法即可。

实例被复用导致设置的自动复制自动打开另存为无效

因为原始的初始化会先判断实例是否为空,为空才创建,不为空则复用。

改为如下:

1
2
3
4
5
6
ScreenWidget *ScreenWidget::Instance(bool need_auto_copy, bool need_auto_save_as)
{
// 确保每次初始化都是最新的
self.reset(new ScreenWidget(nullptr, need_auto_copy, need_auto_save_as));
return self.data();
}

尚未解决

打包后的 exe 需要在目录下运行才能用,脱离了该目录就会报错找不到 QT core 什么的。