Bootstrap

Qt 手写一个电脑截图工具

目录

引入信号和槽

截图

捕获信号

渲染截图

 显示截图


创建一个sinpasteApp类,使其继承自object。我们在这个类内进行封装截图功能:

 此时创建完成之后会生成一个sinpasteapp.h和sinpasteapp.cpp文件:

接下来我们需要创建一个系统托盘,我们点击这个托盘的时候上面会弹出一个菜单,上面显示一个截图和退出菜单选项。

在main.cpp内定义我们创建的sinpasteApp类实例,这样就会自动调sinpasteapp.h和cpp文件了:

 main.cpp

在sinpasteapp.h文件建一个托盘对象:

sinpasteapp.h

#include<QSystemTrayIcon>  //系统托盘
class sinpasteApp : public QObject
{
.......
private:
        QSystemTrayIcon sysMeun;  //定义托盘对象
};

sinpasteapp.h内构造时动态分配托盘对象,动态分配的目的是为了让托盘不会一直存在,直到程序结束。

sinpasteapp.cpp


sinpasteApp::sinpasteApp(QObject *parent)
    : QObject{parent},
    sysMeun(new QSystemTrayIcon(this))  //动态分配托盘
{}

在构造时设置一下托盘图标:

sinpasteapp.cpp

    sinpasteApp::sinpasteApp(QObject *parent)
    : QObject{parent},   
 sysMeun(new QSystemTrayIcon(this))
{
    this->sysMeun->setIcon(QIcon(":/images/logo.png"));
    this->sysMeun->show();
}

给托盘设置菜单:

sinpasteapp.h

#include<QMenu>

class sinpasteApp : public QObject
{
.......
private:
    void initSysMenu();
}

定义:

sinpasteapp.cpp

//初始化菜单
void sinpasteApp::initSysMenu()
{
    QMenu* menu=new QMenu;
    menu->addAction("截图");
    menu->addAction("退出");
    this->sysMeun->setContextMenu(menu);
}

调用

sinpasteapp.cpp

sinpasteApp::sinpasteApp(QObject *parent)
    : QObject{parent},
    sysMeun(new QSystemTrayIcon(this))
{

    this->sysMeun->setIcon(QIcon(":/images/logo.png"));
     initSysMenu();
    this->sysMeun->show();
}

引入信号和槽

我们需要点击菜单退出实现退出功能,点击截图实现截图功能。其中退出功能直接调用系统的quit()函数,截图由我们自己封装函数去实现具体截图功能。

 
qApp就是一个应用程序对象,我们调quit()会用到了qapplication,qapplication在main函数被创建,是单例的,我们要想访问它只能通过qApp去访问。

截图

sinpasteapp.h

public slots:
    void  grapsScreen();

sinpasteapp.cpp

//截图
void sinpasteApp::grapsScreen()
{  
    QList<QScreen*>screens=qApp->screens();  //获取显示器数量
    if(screens.empty())
    {
        qDebug("没有获取到显示器");
        return;
    }
    auto curpos=QCursor::pos();  //获取鼠标位置
    
    QPixmap pix;
    for(auto screen:screens)
    {
        QRect rect=screen->geometry();  //获取显示器矩形区域
        if(rect.contains(curpos))  //如果显示器内包含鼠标
        {
            pix=screen->grabWindow();  //把截图保存到pix变量
        }
    }
    if(pix.isNull())
    {
        qDebug()<<"截图为空";
        return;
    }
  
    emit shotFinished(pix);  //把截图发送给显示截图槽函数
}

我们截图的内容在widget窗口显示出来:

捕获信号

sinpasteapp.h

创建一个Widget类型的指针: 

#include"widget.h"

class sinpasteApp : public QObject
{
......
private:
        Widget* view;
}

构造时给view分配内存:

sinpasteApp::sinpasteApp(QObject *parent)
    : QObject{parent},
    view(new Widget()),
    sysMeun(new QSystemTrayIcon(this))
{
.......
     connect(this,&sinpasteApp::shotFinished,this->view,&Widget::showPix);
       //发起信号者             发送的槽函数         接收者        接收槽函数    
}

渲染截图

渲染需要重写虚函数paintEvent()。

Widget.h

#include<QPaintEvent>

class Widget : public QWidget
{
    Q_OBJECT

......
protected:
    void paintEvent(QPaintEvent* event);

}

Widget.cpp

#include<QPainter>


void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    if(!this->windowPix.isNull())
    {
        painter.drawPixmap(this->rect(),this->windowPix);  //第一个参数为要绘制的区域(这里我们传屏幕的矩形区域),第二个参数为要绘制的东西,这里我们传之前保存的截图
    }
}

 显示截图

 void Widget:: showPix(QPixmap pix)
{
      this->windowPix=pix;
      this->show();
}

;