QT实现的截屏工具与录像功能

前言

目前实现了高仿微信的截屏工具,alt+x截屏,用户选取区域进行截屏确认,截屏完成后复制到了粘贴板,用全局按键监听按键,程序在最小化时也可以对按键进行监听,有截屏预览与保存按键。
大致流程:main->widget->按下截屏按键->takeScreenshot()合并主屏幕和副屏的截图->创建FullScreenWindow类->用户选择区域->确认->发送确认信号->QGraphicsScene预览。
注释写的还算较为全,最近在找工作没有太多的时间写博客,这里单纯记录一下,后续准备通过ffmpeg库来实现录像功能,有问题欢迎留言。
部分功能预览图:
在这里插入图片描述

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMouseEvent>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QShortcut>
#include <QHotkey>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    //void paintEvent(QPaintEvent *event) override;
//    void mousePressEvent(QMouseEvent *event) override;
//    void mouseMoveEvent(QMouseEvent *event) override;
//    void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
    void on_screenshotButton_clicked();

    void on_saveButton_clicked();

private:
    Ui::Widget *ui;
    QPoint startPos;
    QPoint endPos;
    QGraphicsScene *scene;
    QShortcut *shortcut;
    QHotkey* hotkey;
    QPixmap scaledScreenshot;
    bool screenshotCompleted; // 标志位,表示截图是否已完成
    void handleScreenshotSelected(const QPixmap& selectedScreenshot);
    void handleScreenshotCancelled();
    void takeScreenshot();
};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include "fullscreenwindow.h"
#include <QClipboard>
#include <QPainter>
#include <QScreen>
#include <QDesktopWidget>
#include <QWidget>
#include <QFileDialog>
#include <QMessageBox>
#include <QTime>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget),screenshotCompleted(true)
{
    ui->setupUi(this);
    //移除最大化按钮并限制更改大小
    setWindowFlags(windowFlags()&~Qt::WindowMaximizeButtonHint); setFixedSize(this->width(), this->height());
    // 创建场景和图像项
    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);
//    // 按键
//    shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_X), this);
//    connect(shortcut, &QShortcut::activated, this, &Widget::takeScreenshot);
    // 创建全局快捷键监听
    hotkey = new QHotkey(QKeySequence(Qt::ALT + Qt::Key_X), true, this);
    connect(hotkey, &QHotkey::activated, this, &Widget::takeScreenshot);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::takeScreenshot()
{
    // 获取主屏幕和副屏的截图
    QScreen *primaryScreen = QGuiApplication::primaryScreen();
    QScreen *secondaryScreen = nullptr; 

    QList<QScreen*> screens = QGuiApplication::screens();
    if (screens.size() > 1) {
        secondaryScreen = screens.at(1); // 假设第二个屏幕是副屏
    }

    QPixmap primaryScreenshot = primaryScreen->grabWindow(0);
    QPixmap secondaryScreenshot = secondaryScreen ? secondaryScreen->grabWindow(0) : QPixmap(); // 如果没有副屏,使用空的 QPixmap

    // 合并主屏幕和副屏的截图
    QPixmap combinedScreenshot(primaryScreenshot.width() + secondaryScreenshot.width(), std::max(primaryScreenshot.height(), secondaryScreenshot.height()));
    QPainter painter(&combinedScreenshot);
    painter.drawPixmap(0, 0, primaryScreenshot);
    painter.drawPixmap(primaryScreenshot.width(), 0, secondaryScreenshot);

    // 创建全屏窗口并传递合并后的截图
    FullScreenWindow *fullscreenWindow = new FullScreenWindow(combinedScreenshot);
    connect(fullscreenWindow, &FullScreenWindow::screenshotSelected, this, &Widget::handleScreenshotSelected);
    connect(fullscreenWindow, &FullScreenWindow::screenshotCancelled, this, &Widget::handleScreenshotCancelled);


}


void Widget::on_screenshotButton_clicked()
{
    if (screenshotCompleted) {
        screenshotCompleted = false; // 设置标志位为false,表示截图进行中
        hide(); // 隐藏主界面
        // 添加一个等待操作以确保主界面完全隐藏
        QTime dieTime = QTime::currentTime().addMSecs(100); // 100毫秒的等待时间
        while (QTime::currentTime() < dieTime)
        {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
        }
        takeScreenshot();
    }
}

void Widget::handleScreenshotSelected(const QPixmap& selectedScreenshot)
{
    QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem();
    // 处理截图完成后的操作
    screenshotCompleted = true; // 设置标志位为true,表示截图已完成
    //将屏幕截图复制到剪贴板
    QClipboard *clipboard = QGuiApplication::clipboard();
    clipboard->setPixmap(selectedScreenshot);
    // 缩放截图适应窗体大小
    scaledScreenshot = selectedScreenshot.scaled(ui->graphicsView->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    pixmapItem->setPixmap(scaledScreenshot);
    scene->clear();
    scene->addItem(pixmapItem);
    show(); // 显示主界面

}

void Widget::handleScreenshotCancelled()
{
    screenshotCompleted = true; // 设置标志位为true,表示截图已完成
    show(); // 显示主界面
}


void Widget::on_saveButton_clicked()
{
    if (screenshotCompleted) {
           screenshotCompleted = false; // 设置标志位为false,表示保存截图进行中

           if (!scaledScreenshot.isNull()) {
               // 打开文件对话框以获取保存路径和文件名
               QString filePath = QFileDialog::getSaveFileName(this, "保存截图", QDir::homePath(), "Images (*.png *.jpg *.bmp)");

               if (!filePath.isEmpty()) {
                   // 保存截图到指定路径
                   scaledScreenshot.save(filePath);
                   screenshotCompleted = true; // 设置标志位为true,表示保存截图已完成
                   QMessageBox::information(this, "保存成功", "截图已成功保存");
               }
           } else {
               // 如果截图为空,弹出警告
               screenshotCompleted = true; // 设置标志位为true,表示保存截图已完成
               QMessageBox::warning(this, "警告", "当前没有截图可保存");
           }
       }
}


fullscreenwindow.h文件

#ifndef FULLSCREENWINDOW_H
#define FULLSCREENWINDOW_H

#include <QWidget>
#include <QPixmap>
#include <QRect>
#include <QPushButton>

class FullScreenWindow : public QWidget
{
    Q_OBJECT
public:
    FullScreenWindow(QPixmap screenshot);

protected:
    // 函数声明
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void keyPressEvent(QKeyEvent *event) override;


private:
    QPushButton *confirmButton;
    QPushButton *cancelButton;
    QPixmap screenshot;
    QRect selectionRect;
    QPoint startPos;
    QPoint endPos;
    QRect selectedRegion;
    QPixmap fullScreenScreenshot;
    void closeWindow();
    void confirmSelection();
    void cancelSelection();


signals:
    void screenshotSelected(const QPixmap& screenshot);
    void screenshotCancelled();
};

#endif // FULLSCREENWINDOW_H

fullscreenwindow.cpp文件

#include "fullscreenwindow.h"
#include <QPainter>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>
#include <QVBoxLayout>
#include <QScreen>


FullScreenWindow::FullScreenWindow(QPixmap screenshot) : screenshot(screenshot)
{
    setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
    setCursor(QCursor(Qt::CrossCursor));
    // 设置窗口位置和大小以适应图像大小
    setGeometry(0, 0, screenshot.width(), screenshot.height());

    // 在构造函数中创建按钮并设置属性
    confirmButton = new QPushButton("确定", this);
    confirmButton->setMinimumSize(80, 30);
    confirmButton->setMaximumSize(80, 30);
    confirmButton->hide();
    cancelButton = new QPushButton("取消", this);
    cancelButton->setMinimumSize(80, 30);
    cancelButton->setMaximumSize(80, 30);
    cancelButton->hide();
    connect(confirmButton, &QPushButton::clicked, this, &FullScreenWindow::confirmSelection);
    connect(cancelButton, &QPushButton::clicked, this, &FullScreenWindow::cancelSelection);
    show();
}

void FullScreenWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(0, 0, screenshot);
    painter.setPen(QPen(Qt::red, 1, Qt::DashLine));

    QRect selectionRect(startPos, endPos);
    painter.drawRect(selectionRect);
}



void FullScreenWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        startPos = event->pos();
        //selectingScreenshot = true;
    }
}

void FullScreenWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        endPos = event->pos();
        update();
    }
}

void FullScreenWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        selectedRegion = QRect(startPos, endPos);
        // 处理用户选择的区域
        // 在用户选择区域的正下方放置按钮
        int buttonX = selectedRegion.center().x() - confirmButton->width() / 2;
        int buttonY = selectedRegion.bottom() + 10; // 10 是按钮与选择区域的间距

        // 设置按钮的位置
        confirmButton->move(buttonX, buttonY);
        cancelButton->move(buttonX + confirmButton->width() + 10, buttonY);
        // 显示按钮
        confirmButton->show();
        cancelButton->show();
//        // 创建布局管理器,并将按钮放置在适当的位置
//        QVBoxLayout *layout = new QVBoxLayout(this);
//        layout->addWidget(confirmButton);
//        layout->addWidget(cancelButton);
//        // 设置布局的边框和背景颜色

//        // 设置布局的位置
//        int layoutTop = selectionRect.bottom() + 10;  // 10 是布局距离矩形框底部的垂直偏移量
//        //layout->setGeometry(QRect(10, layoutTop, layout->sizeHint().width(), layout->sizeHint().height()));
        //setLayout(layout);
    }
}

void FullScreenWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Escape) {
            // 如果用户按下 ESC 键,关闭窗口
            close();
            emit screenshotCancelled();
        }
}
void FullScreenWindow::confirmSelection()
{
    if (!selectedRegion.isEmpty())
    {
        // 裁剪整个屏幕截图为所选区域
        QPixmap croppedScreenshot = screenshot.copy(selectedRegion);
        // 发送裁剪后的截图给主页面
        emit screenshotSelected(croppedScreenshot);

        // 关闭窗口
        close();
    }
}

void FullScreenWindow::cancelSelection()
{
    emit screenshotCancelled();
    // 关闭窗口
    close();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值