qt之实现截图功能(全局热键,程序隐藏也可执行)

一、前言

qt实现截屏功能,基于自己做的自定义面板程序,自定义面板是根据个人需求专属定制,提醒自己用了多久电脑,什么时候该休息一会了,有一些辅助工具,截屏,用到什么控件了也可参考历史的控件,这样就算没联网没有登录qq和微信也可实现截屏功能。

二、环境

qt5.7mingw

windows8

三、正文

首先上一下效果图

正文正式开始,实现这个截图功能看视乎简单,实际还是涉及到挺多问题的

1.首先截屏不可能是在写的程序聚焦情况下执行,必须支持程序在后台,随时按下快捷键即可截屏,这就需要实现全局快捷按键获取了。

2.截屏时得有效果,否者不清楚截屏的位置是在哪里,这样自己看不方便,别人更是看不明白了,所以需要实现全局遮罩,就是截屏时的灰色背景。

3.有了遮罩还得实现截屏区域的显示,否则也不是很明确具体截屏在哪里,这就需要用到mouseevent和paintevent这两个函数组合使用了。

*实现了以上三点,才能达到截屏刚刚够看,否则真的是一塌糊涂,和qq微信自带的ctrl+alt+a  和alt+a比起来,着实差远了,但是我把它放在我的自定义控件面板中,在电脑单机工作时,或者没有上qq微信时也可以实现截屏功能。

正文真正的开始了:

首先是实现全局按键函数,这里我一开始是用一个钩子函数的单独按键获取,但是只能获取到一个键值,所以在GitHub上面查到了一个dalao写的pri库,于是就调用了,发现有一些问题,还不是很完美。

dalao的库我也放在本资源下载链接里了,还有我写的截屏功能代码都在里面, 有需要的可以下载。

添加上如下的pri即可

include(D:/QT57/workspace/My/MyCustomWidget/CustomWidget/QHotkey-master/qhotkey.pri)

头文件包含#include <QHotkey>

mainwindow.cpp包含

    //qhotkey.pri引用于GitHub,实现在widget以外获取全局键盘函数
    QHotkey *hotkey=new QHotkey(QKeySequence("Ctrl+Shift+A"),true);
    //QHotkey *hotkey=new QHotkey(Qt::Key_L,Qt::ControlModifier,true);
    //连接热键被按下的信号与槽
    QObject::connect(hotkey,&QHotkey::activated,[=](){
        //热键被按下的处理代码段
         qDebug()<<"QString::number(key)";
         qApp->beep();//蹦的一声
         basewidget->setGeometry(0, 0,1920,1080);//遮罩窗口位置
    });
我是用的ctrl+shift+a实现截屏,也可自行更改快捷键

他这里有一个bug就是在connect内不能执行QMessageBox或者其他的打开界面函数,这一切异常都是在我的窗口呗隐藏时发送的,窗口不隐藏怎么使用也没有问题,但是那就失去了他在后台可执行的意义,所以我将里面的遮罩背景一直显示出来,不用的时候放在0,0位置,1,1像素,用的是后在满屏显示遮罩。

其次就是遮罩的实现了,这里遮罩实现需要新建一个ui界面,或者也可以新建一个类不建立ui界面都可以。

我的遮罩代码也放在本博的资源内了,可以下载参考,核心代码都在里面。

在mainwindow.h中添加

#include "shadewidget.h"    
Shadewidget *basewidget;    //半透明遮罩

在mainwindow。cpp中

    //初始化半透明遮罩
    basewidget=new Shadewidget;
    basewidget->setParent(this,Qt::FramelessWindowHint|Qt::Window);
    basewidget->setWindowFlags(basewidget->windowFlags() | Qt::WindowStaysOnTopHint);
    basewidget->setGeometry(0, 0, 1,1);    //遮罩窗口位置
    basewidget->show();
    basewidget->raise();
    //获取截屏标志
    //qhotkey.pri引用于GitHub,实现在widget以外获取全局键盘函数
    QHotkey *hotkey=new QHotkey(QKeySequence("Ctrl+Shift+A"),true);
    //QHotkey *hotkey=new QHotkey(Qt::Key_L,Qt::ControlModifier,true);
    //连接热键被按下的信号与槽
    QObject::connect(hotkey,&QHotkey::activated,[=](){
        //热键被按下的处理代码段
         qDebug()<<"QString::number(key)";
         qApp->beep();//蹦的一声
         basewidget->setGeometry(0, 0,1920,1080);//遮罩窗口位置
    });

下面代码有一半是上面那个,让人看懂一下吧

本段代码意思就是初始化遮罩界面和按下快捷键将遮罩界面放大到全屏显示,这里的1920.1080可以改成自动获取屏幕大小,不一定所有的屏幕全是我这个分辨率的。

在然后就是遮罩界面了。这个界面首先头文件需要引用一些包含库,还有定义

#include <QWidget>
#include <QCloseEvent>
#include <QtDebug>
#include <QApplication>
#include <QPixmap>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QClipboard>
#include <QPainter>

private slots:
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void closeEvent(QCloseEvent *event);
    void paintEvent(QPaintEvent */*event*/);
private:
    Ui::Shadewidget *ui;
    QPixmap screen;        //截屏图片
    QPoint start_point;
    QPoint end_point;
    int x,y,w,h;

在此界面第一个重要的关键点是失能界面的强制关闭功能,否则主界面在后台时调用出来遮罩界面,遮罩界面被强制关闭时主程序就会挂掉

Shadewidget::Shadewidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Shadewidget)
{
    ui->setupUi(this);
    QPalette palette=this->palette();
    palette.setBrush(QPalette::Background,QColor(0,0,0));
    this->setPalette(palette);
    this->setWindowOpacity(0.4);//设置窗口透明度
    this->setWindowFlags(Qt::FramelessWindowHint|windowFlags());//去掉标题栏
}

Shadewidget::~Shadewidget()
{
    delete ui;
}
void Shadewidget::closeEvent(QCloseEvent *event)
{
    event->ignore();
}

在之后就是鼠标事件的配置,去获取起始坐标,鼠标移动时的坐标作为结束坐标,这两个坐标不一定谁前谁后谁高谁低,所以定义了xywh去计算出区域的起始点和长宽。

我的逻辑是在按下鼠标时候记录一个起始坐标,然后鼠标move,过程中一直记录结束坐标,然后一直有新的xywh,通过这些纸刷新paint出需要截屏的区域,鼠标抬起后再次点击是否要这个截图,点击必须在绘制出的区域内,才算是我想要这张截图,否则截图被视为无效,(新增)绘制完区域之后点击区域外面,区域被复位清空,这块是写博客时发现一个细节小问题,资源已经上传了,这里详细看帖子的人自己改一下,在鼠标释放事件上面的else里加了两行代码。

继续刚才,点击区域内保存保存该区域截图和退出截屏。

完毕!

附上代码

//实现窗口移动
void Shadewidget::mouseMoveEvent(QMouseEvent *event)
{
    end_point=event->globalPos()-this->pos();//获取点击的坐标
    if(end_point.x()>start_point.x()){
        x=start_point.x();//比较起始坐标
        w=end_point.x()-start_point.x();
    }
    else {
        x=end_point.x();
        w=start_point.x()-end_point.x();
    }
    if(end_point.y()>start_point.y()){
        y=start_point.y();//比较起始坐标
        h=end_point.y()-start_point.y();
    }
    else {
        y=end_point.y();
        h=start_point.y()-end_point.y();
    }
    update();
    //qDebug()<<start_point<<end_point<<event->globalPos()-this->pos();//获取点击的坐标
}
//鼠标点击事件
void Shadewidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::RightButton){//右键退出截屏
        this->setGeometry(0, 0, 1,1);    //遮罩窗口位置
        //关闭之后清空
        x=y=w=h=0;
        update();
    }
    if(event->x()>x&&event->x()<(x+w)&&event->y()>y&&event->y()<(y+h)){//画完范围确定截图
        //截屏
        this->setWindowOpacity(0);//设置窗口透明度
        screen=QPixmap::grabWindow(QApplication::desktop()->winId(),x,y,w,h);
        this->setWindowOpacity(0.4);//设置窗口透明度
       //保存到粘贴板
        QClipboard *pic=QApplication::clipboard();
        pic->setPixmap(screen);
        this->setGeometry(0, 0, 1,1);    //遮罩窗口位置
        //关闭之后清空
        x=y=w=h=0;
        update();
    }
    else{
        x=y=w=h=0;
        update();
        start_point=event->globalPos()-this->pos();//获取点击的坐标
    }
    //qDebug()<<start_point;//获取点击的坐标
}
//鼠标释放事件
void Shadewidget::mouseReleaseEvent(QMouseEvent *event)
{


}
void Shadewidget::paintEvent(QPaintEvent */*event*/)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    painter.save();
    painter.setPen(Qt::green);
    QPointF topLeftPot(x, y);
    QPointF bottomRightPot(x+w, y+h);//右上角
    QRectF barRect = QRectF(topLeftPot, bottomRightPot);
    painter.setBrush(Qt::white);
    painter.drawRect(barRect);
    painter.restore();

}

20240513升级功能

增加截图右键弹出菜单选项,增加截图取消快捷键ESC

 初始化代码如下:

    ///截图
    //获取截屏标志
    basewidget=new Shadewidget;
    basewidget->setParent(this,Qt::FramelessWindowHint|Qt::Window);
    basewidget->setWindowFlags(basewidget->windowFlags() | Qt::WindowStaysOnTopHint);
    basewidget->setGeometry(0, 0, 1,1);    //遮罩窗口位置
    basewidget->hide();
    basewidget->raise();
    //qhotkey.pri引用于GitHub,实现在widget以外获取全局键盘函数
    QHotkey *hotkey=new QHotkey(QKeySequence("Ctrl+Shift+A"),true);
    //QHotkey *hotkey=new QHotkey(Qt::Key_L,Qt::ControlModifier,true);
    //连接热键被按下的信号与槽
    QObject::connect(hotkey,&QHotkey::activated,[=](){
        //热键被按下的处理代码段
        ui->btn_menu_1->click();//执行截图功能
    });
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

调用代码

​
this->hide();
qApp->beep();//蹦的一声
basewidget->show();//调用前显示,使用完毕之后在隐藏,否则按alt+tab能看到截图任务
basewidget->setGeometry(0, 0,QApplication::desktop()->width(),QApplication::desktop()->height());//遮罩窗口位置

​

核心代码,都在这里了,不用找下载链接了

#include "shadewidget.h"
#include "ui_shadewidget.h"
Shadewidget::Shadewidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Shadewidget)
{
    ui->setupUi(this);
    QPalette palette=this->palette();
    palette.setBrush(QPalette::Background,QColor(0,0,0));
    this->setPalette(palette);
    this->setWindowOpacity(0.4);//设置窗口透明度
    this->setWindowFlags(Qt::FramelessWindowHint|windowFlags());//去掉标题栏
    this->setWindowTitle("screen");

    menu = new QMenu(this);//创建右键菜单
    menu->addAction("复制选中到粘贴板", this, [=](){copy(true);});
    menu->addAction("选中图像另存为", this, [=](){save();});
    menu->addAction("复制全屏到粘贴板", this, [=](){
        x=0;y=0;w=QApplication::desktop()->width();h=QApplication::desktop()->height();
        copy(true);
    });
    menu->addAction("全屏图像另存为", this, [=](){
        x=0;y=0;w=QApplication::desktop()->width();h=QApplication::desktop()->height();
        save();
    });
    menu->addAction("退出截图", this, [=](){
        this->setGeometry(0, 0, 1,1);    //遮罩窗口位置
        x=y=w=h=0;//关闭之后清空
        update();
        this->hide();
    });
    menu->setStyleSheet("background-color: rgb(30, 30, 30, 100);color: rgb(255, 255, 255);"
                        "border-right:2px solid #aaaaaa; "
                        "border-bottom:2px solid #aaaaaa;"
                        "border-left:2px solid #aaaaaa;"
                        "border-top:2px solid #aaaaaa; "
                        "border-radius:5px;"
                        "font: 16pt ""黑体"";"
                        "selection-background-color: rgb(100, 40, 40);");

}
Shadewidget::~Shadewidget()
{

    delete menu;
    delete ui;
}
void Shadewidget::closeEvent(QCloseEvent *event)
{
    event->ignore();
}
//实现窗口移动
void Shadewidget::mouseMoveEvent(QMouseEvent *event)
{
    end_point=event->globalPos()-this->pos();//获取点击的坐标
    if(end_point.x()>start_point.x()){
        x=start_point.x();//比较起始坐标
        w=end_point.x()-start_point.x();
    }
    else {
        x=end_point.x();
        w=start_point.x()-end_point.x();
    }
    if(end_point.y()>start_point.y()){
        y=start_point.y();//比较起始坐标
        h=end_point.y()-start_point.y();
    }
    else {
        y=end_point.y();
        h=start_point.y()-end_point.y();
    }
    update();
//    qDebug()<<start_point<<end_point<<event->globalPos()-this->pos();//获取点击的坐标
}
//鼠标点击事件
void Shadewidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::RightButton){//右键弹出菜单
        menu->exec(cursor().pos());//菜单显示的位置跟随鼠标
    }
    if(event->x()>x&&event->x()<(x+w)&&event->y()>y&&event->y()<(y+h)){//鼠标点击在 画完范围内 确定截图
        copy(true);//将截图复制到粘贴板
    }
    else{
        x=y=w=h=0;
        update();
        start_point=event->globalPos()-this->pos();//获取点击的坐标
    }
//    qDebug()<<start_point;//获取点击的坐标
}
//鼠标释放事件
void Shadewidget::mouseReleaseEvent(QMouseEvent *event)
{

}
// 键盘按下事件
void Shadewidget::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Escape){ // 是否按下Esc键
        this->setGeometry(0, 0, 1,1);    //遮罩窗口位置
        x=y=w=h=0;//关闭之后清空
        update();
        this->hide();
    }
    else QWidget::keyPressEvent(event);
}
//绘制
void Shadewidget::paintEvent(QPaintEvent */*event*/)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.save();
    painter.setPen(Qt::green);
    QPointF topLeftPot(x, y);
    QPointF bottomRightPot(x+w, y+h);//右上角
    QRectF barRect = QRectF(topLeftPot, bottomRightPot);
    painter.setBrush(Qt::white);
    painter.drawRect(barRect);
    painter.restore();
}
//将截图复制到粘贴板
void Shadewidget::copy(bool hideflag)
{
   //截屏
   this->setWindowOpacity(0);//设置窗口透明度
   screen=QPixmap::grabWindow(QApplication::desktop()->winId(),x,y,w,h);
   this->setWindowOpacity(0.4);//设置窗口透明度
  //保存到粘贴板
   QClipboard *pic=QApplication::clipboard();
   pic->setPixmap(screen);
   this->setGeometry(0, 0, 1,1);    //遮罩窗口位置
   //关闭之后清空
   x=y=w=h=0;
   update();
   if(hideflag)
       this->hide();
}
//截图另存为
void Shadewidget::save()
{
    copy(false);//将截图复制到粘贴板
    QString savename=QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)+"/截图.png";//默认路径:桌面  //默认格式:png
    QString fileName = QFileDialog::getSaveFileName(this,"截图另存为",savename,"PNG (*.png);;BMP (*.bmp);;JPEG (*.jpg *.jpeg)");
    if (!fileName.isEmpty()){
        screen.save(fileName);
    }
    screen.save(fileName);
    this->hide();
}


#ifndef SHADEWIDGET_H
#define SHADEWIDGET_H

#include <QWidget>
#include <QCloseEvent>
#include <QtDebug>
#include <QApplication>
#include <QPixmap>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QClipboard>
#include <QMainWindow>
#include <QMenu>//右键菜单
#include <QMouseEvent>
#include <QPainter>//画笔
#include <QDebug>
#include <QFileDialog>
#include <QShowEvent>
#include <QMessageBox>
namespace Ui {
class Shadewidget;
}

class Shadewidget : public QWidget
{
    Q_OBJECT

public:
    explicit Shadewidget(QWidget *parent = 0);
    ~Shadewidget();
private slots:
    void closeEvent(QCloseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent */*event*/);
    void copy(bool hideflag);//将截图复制到粘贴板
    void save();//截图另存为

private:
    Ui::Shadewidget *ui;
    QPixmap screen;        //截屏图片
    QPoint start_point;
    QPoint end_point;
    int x,y,w,h;

    QMenu *menu;
};

#endif // SHADEWIDGET_H

 最终效果图

四、结语

完毕,开心!

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Qt截图工具代码git是指基于Qt框架的截图工具代码存储在Git版本控制系统中。Git是一种开源的分布式版本控制工具,它可以跟踪项目代码的变化,并记录每次修改的细节,使多人协作开发更加便捷。 Qt是一种跨平台的应用程序开发框架,通过使用Qt的相关类库,开发者可以方便地实现图形界面应用程序以及各种功能Qt截图工具通过调用Qt的相关API和函数,实现了屏幕截图功能,用户可以选择截取整个屏幕或者指定区域,并进行保存或者复制到剪贴板。 将Qt截图工具代码存储在Git中,可以使开发者方便地进行代码的版本管理和协作开发。Git使用分支和合并的方式来处理代码的修改,可以在不同的分支上进行独立的开发,最后再将不同分支的修改合并到主分支上。通过Git,开发者可以追踪代码的历史变化,查看每次提交的详细信息,并且可以方便地回滚到之前的版本,以及解决多人同时修改同一文件的冲突问题。 使用Git存储Qt截图工具代码可以实现代码的版本控制和备份,方便开发者进行项目管理和团队协作。通过合理的分支管理和代码提交规范,可以使代码变更的过程变得可控和可追溯,同时也提高了代码的可维护性和可扩展性。 总而言之,Qt截图工具代码Git是指将基于Qt框架开发截图工具代码存储在Git版本控制系统中,通过Git可以实现代码的版本管理、团队协作以及代码变更的可控性和可追溯性。 ### 回答2: qt截图工具代码在git上可以找到很多开源项目。Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的图形界面和工具集,开发者可以利用这些工具来构建自己的应用程序截图工具是Qt应用程序中常见的一个功能,用于将当前屏幕内容保存为图片。 在git上搜索Qt截图工具代码,可以找到一些开源项目。这些项目提供了一些基本的截图功能,例如选择截图区域、截取当前窗口或全屏等。其中有些项目还加入了一些额外的功能,例如插入标记、编辑图片等。 通过查看这些项目的源代码,我们可以学习到Qt的应用程序开发技巧,例如如何使用Qt提供的图形界面组件、如何处理用户输入等。同时,通过参考这些代码,我们也可以在自己的项目中加入截图功能,提升用户体验。 在使用这些开源项目时,需要注意遵循开源协议。通常,这些项目会选择一种开源协议,例如GNU通用公共许可证(GPL)或MIT许可证。我们可以根据自己的需求选择合适的开源项目,并遵守相应的协议要求。 总之,通过在git上寻找Qt截图工具代码,我们可以找到一些开源项目,学习Qt应用程序开发的技巧,并在自己的项目中加入截图功能,提升用户体验。同时,需要遵守开源协议的要求,尊重代码的原作者和社区的贡献。 ### 回答3: Qt截图工具是一个基于Qt框架开发的应用程序,它可以用于对屏幕或窗口进行截图操作。我们可以使用git这个版本控制工具来管理和协作开发这个项目的代码。 首先,我们可以使用git init命令在一个空目录中初始化一个新的git版本库。然后,我们可以将这个空目录设置为Qt截图工具的代码目录。接下来,我们可以使用git add命令将代码文件添加到版本库中。 当我们对代码做出修改时,我们可以使用git commit命令来提交这些修改。这会创建一个新的提交对象,将修改的代码添加到版本库的历史记录中。 除了在本地进行开发外,我们还可以使用git的分支功能来进行团队协作开发。通过创建不同的分支,不同的开发人员可以在自己的分支上进行开发,而不会干扰到其他人的工作。当一个人完成了自己的开发任务并经过测试后,可以使用git merge命令将自己的分支合并到主分支中。 另外,为了确保代码的安全和跟踪性,我们可以将代码仓库上传到远程的代码托管平台,如GitHub或GitLab。这样,团队中的其他成员就可以从远程仓库中获取代码,并进行协作开发。 总之,通过使用git作为版本控制工具,我们可以更加高效地管理和协作开发Qt截图工具的代码。通过记录代码的修改历史、分支管理和远程仓库的使用,我们可以确保代码的安全性和可追踪性,同时提高团队协作的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大桶矿泉水

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值