效果
- 生成一个透明无边框全屏的窗口,然后按ctrl+b键就可以选择区域进行截图保存
步骤
- 新建一个项目
- 新建一个ctrlb类继承QMainWindow
- 新建一个CaptureScreen类继承QWidget
- 在main中启动ctrlb类
代码
ctrlb类.cpp
#include "ctrlb.h"
#include "capturescreen.h"
#include <QKeyEvent>
#include <QPixmap>
#include <QFileDialog>
#include <QProcess>
#include <QDebug>
#include <QFile>
#include <QTextStream>
ctrlb::ctrlb(QWidget *parent)
: QMainWindow(parent) {}
// 按键事件
void ctrlb::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_B && event->modifiers() == Qt::ControlModifier) {
triggerScreenshot();
}
}
// 截图操作
void ctrlb::triggerScreenshot() {
// 定义截图对象
CaptureScreen *capture = new CaptureScreen();
// 调用 close() 函数或用户点击关闭按钮时,窗口对象会被自动销毁
capture->setAttribute(Qt::WA_DeleteOnClose);
// 当完成截图操作后,会发送信号触发保存图片
connect(capture, &CaptureScreen::signalCompleteCature, this, &ctrlb::handleScreenshot);
// 显示截图窗口
capture->show();
}
// 保存图片,参数是屏幕的截图
void ctrlb::handleScreenshot(const QPixmap &screenshot) {
// 判断参数是否为空
if (!screenshot.isNull()) {
QString savePath = "check.jpg";
if (!savePath.isEmpty()) {
// 保存为用户指定的文件
screenshot.save(savePath, "JPG");
}
}
}
ctrlb类.h
#ifndef CTRLB_H
#define CTRLB_H
#include <QMainWindow>
class ctrlb : public QMainWindow
{
Q_OBJECT
public:
explicit ctrlb(QWidget *parent = nullptr);
protected:
void keyPressEvent(QKeyEvent *event) override;
private:
void triggerScreenshot();
private slots:
// 保存图片槽函数
void handleScreenshot(const QPixmap &screenshot);
};
#endif // CTRLB_H
CaptureScreen类.cpp
#include "capturescreen.h"
#include <QApplication>
#include <QMouseEvent>
#include <QPixmap>
#include <QScreen>
CaptureScreen::CaptureScreen(QWidget *parent)
: QWidget(parent)
, m_isMousePress(false)
{
// 初始化窗口
initWindow();
// 读取图像后作为背景。但不显示
loadBackgroundPixmap();
// 水平容器Widget
buttonContainer = new QWidget(this);
// 容器的大小
buttonContainer->setGeometry(0, 0, 180, 30);
// 创建水平布局并绑定容器widget
layout = new QHBoxLayout(buttonContainer);
// 创建确认和取消按钮
m_confirmButton = new QPushButton("确认", this);
m_cancelButton = new QPushButton("取消", this);
// 设置按钮隐藏
m_confirmButton->hide();
m_cancelButton->hide();
// 设置按钮的大小
m_confirmButton->setFixedSize(80, 30);
m_cancelButton->setFixedSize(80, 30);
// 加入布局
layout->addWidget(m_confirmButton);
layout->addWidget(m_cancelButton);
// 设置间隔为10
layout->setSpacing(10);
// 取消确认按钮函数
connect(m_confirmButton, &QPushButton::clicked, this, &CaptureScreen::confirmCapture);
connect(m_cancelButton, &QPushButton::clicked, this, &CaptureScreen::cancelCapture);
}
CaptureScreen::~CaptureScreen()
{
}
void CaptureScreen::initWindow()
{
// 启用鼠标跟踪,移动的时候也会触发事件
this->setMouseTracking(true);
// 设置窗口为无边框模式
this->setWindowFlags(Qt::FramelessWindowHint);
// 设置窗口全屏显示
setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
}
// 抓取当前桌面内容作为背景快照
void CaptureScreen::loadBackgroundPixmap()
{
// 获取当前主屏幕的 QScreen 对象
QScreen *screen = QGuiApplication::primaryScreen();
if (screen) {
// 获取现在的整个屏幕
m_loadPixmap = screen->grabWindow(0);
}
// 获取屏幕宽高
m_screenwidth = m_loadPixmap.width();
m_screenheight = m_loadPixmap.height();
}
// 处理鼠标左键按下,记录起点位置
void CaptureScreen::mousePressEvent(QMouseEvent *event)
{
// 判断是不是左键
if (event->button() == Qt::LeftButton)
{
// 画图标志
m_isMousePress = true;
// 记录起始位置
m_beginPoint = event->pos();
// 取消确认按钮隐藏
m_confirmButton->hide();
m_cancelButton->hide();
}
return QWidget::mousePressEvent(event);
}
// 处理鼠标移动,记录终点位置
void CaptureScreen::mouseMoveEvent(QMouseEvent* event)
{
// 判断是否画图
if (m_isMousePress)
{
// 记录移动位置
m_endPoint = event->pos();
// 画矩形
update();
}
return QWidget::mouseMoveEvent(event);
}
// 处理鼠标松开,记录终点位置
void CaptureScreen::mouseReleaseEvent(QMouseEvent *event)
{
// 记录结束位置
m_endPoint = event->pos();
// 结束画矩形
m_isMousePress = false;
// 计算按钮显示位置
int buttonX = selectedRect.right() - m_confirmButton->width() - m_confirmButton->width() - 10;
int buttonY = selectedRect.bottom() + 5;
if (buttonY + 30 > this->height())
{
buttonY = selectedRect.bottom() - m_confirmButton->height() - 5;
buttonX = selectedRect.right() - m_confirmButton->width() - m_confirmButton->width() - 30;
}
if (buttonX < 0)
{
buttonX = 0;
}
// 设置按钮容器的位置
buttonContainer->move(buttonX, buttonY);
// 显示按钮
m_confirmButton->show();
m_cancelButton->show();
return QWidget::mouseReleaseEvent(event);
}
// 绘制事件
void CaptureScreen::paintEvent(QPaintEvent *event)
{
// 初始化 QPainter 对象 m_painter
m_painter.begin(this);
// 半透明的黑色阴影,用于覆盖整个屏幕
QColor shadowColor = QColor(0, 0, 0, 100);
// 设置画笔
m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap));
// 将获取到的屏幕放到窗口上
m_painter.drawPixmap(0, 0, m_loadPixmap);
// 绘制一个半透明的黑色矩形
m_painter.fillRect(m_loadPixmap.rect(), shadowColor);
// 如果鼠标正在移动,会绘制选中的矩形区域
if (m_isMousePress)
{
// 计算选区矩形
QRect selectedRect = getRect(m_beginPoint, m_endPoint);
// 保存选区内容
m_capturePixmap = m_loadPixmap.copy(selectedRect);
// 将选区内容绘制到窗口
m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);
// 绘制选区边框
m_painter.drawRect(selectedRect);
}
// 释放对象
m_painter.end(); //重绘结束;
}
// 键盘事件
void CaptureScreen::keyPressEvent(QKeyEvent *event)
{
// Esc 键退出截图;
if (event->key() == Qt::Key_Escape)
{
close();
}
// Enter键完成截图;
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
{
// 保存截图为 JPG 格式
QString savePath = "screenshot.jpg";
if (!m_capturePixmap.isNull()) {
// 保存为 JPG 格式
m_capturePixmap.save(savePath, "JPG");
}
// 发送截图完成信号
emit signalCompleteCature(m_capturePixmap);
close();
}
}
// 计算一个矩形区域并返回
QRect CaptureScreen::getRect(const QPoint &beginPoint, const QPoint &endPoint)
{
// 矩形的左上角坐标、宽度和高度
int x, y, width, height;
width = qAbs(beginPoint.x() - endPoint.x());
height = qAbs(beginPoint.y() - endPoint.y());
x = beginPoint.x() < endPoint.x() ? beginPoint.x() : endPoint.x();
y = beginPoint.y() < endPoint.y() ? beginPoint.y() : endPoint.y();
// 创建矩形对象
QRect selectedRect = QRect(x, y, width, height);
// 避免宽或高为零时拷贝截图有误,设置最小为1
if (selectedRect.width() == 0)
{
selectedRect.setWidth(1);
}
if (selectedRect.height() == 0)
{
selectedRect.setHeight(1);
}
// 返回矩形对象
return selectedRect;
}
// 确认截图
void CaptureScreen::confirmCapture()
{
// 保存路径
QString savePath = initBmpSavePath;
if (!m_capturePixmap.isNull()) {
// 保存为 BMP 格式
m_capturePixmap.save(savePath, "BMP");
}
// 发送截图完成信号
emit signalCompleteCature(m_capturePixmap);
hide();
emit capture_close();
}
// 取消截图
void CaptureScreen::cancelCapture()
{
// 隐藏按钮
m_confirmButton->hide();
m_cancelButton->hide();
// 隐藏截图窗口
hide();
emit capture_close();
}
CaptureScreen类.h
#ifndef CAPTURESCREEN_H
#define CAPTURESCREEN_H
#include <QWidget>
#include <QPainter>
class CaptureScreen : public QWidget
{
Q_OBJECT
public:
CaptureScreen(QWidget *parent = 0);
~CaptureScreen();
Q_SIGNALS:
void signalCompleteCature(QPixmap catureImage);
private:
void initWindow();
void loadBackgroundPixmap();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void paintEvent(QPaintEvent *event);
QRect getRect(const QPoint &beginPoint, const QPoint &endPoint);
private:
QWidget* buttonContainer;// 容器
QHBoxLayout* layout;// 水平布局
QPushButton *m_confirmButton;// 确认按钮
QPushButton *m_cancelButton;// 取消按钮
bool m_isMousePress;// 判断鼠标是否移动和是否画矩形
QPixmap m_loadPixmap;// 整个屏幕的图像
QPixmap m_capturePixmap;// 框选的屏幕图像
int m_screenwidth;// 屏幕的宽
int m_screenheight;// 屏幕的高
QPoint m_beginPoint, m_endPoint;// 起点和结束点坐标
QPainter m_painter;// 画图对象
};
#endif // CAPTURESCREEN_H
main
#include "mainwindow.h"
#include <QApplication>
#include "ctrlb.h"
#include <QDebug>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<<"init";
ctrlb w;
// 设置无边框窗口
w.setWindowFlags(Qt::FramelessWindowHint);
// 全屏
w.showFullScreen();
// 背景透明
w.setAttribute(Qt::WA_TranslucentBackground);
// 设置透明度
w.setWindowOpacity(1);
w.show();
return a.exec();
}