主要实现2 个功能点:
1 截图
2 窗口镂空
实现截图主要使用QGuiApplication::primaryScreen() 获取到QScreen ,然后调用QGuiApplication::grabWindow函数进行截图,代码示例:
QScreen* screen = QGuiApplication::primaryScreen();
if(const QWindow* window = windowHandle())
{
screen = window->screen();
}
if(!screen)
return;
originalPixmap = screen->grabWindow(0,rc.left(),rc.top(),rc.right() - rc.left(),rc.bottom() - rc.top());
此时originalPixmap 就是 截取的图片,类型为QPixmap,可直接展示。
实现窗口局部透明,即窗口局部镂空。首先将窗口 搞成全透明,然后在未截图情况下,
绘制窗口背景为半透明;(为什么要先 将窗口弄成全透明那?
因为 不将窗口搞成全透明的话,后面绘制的半透明,
其实 还存在一个窗口背景。做不到真正意义上的全透明)
在截图的情况下将 截图区域不绘制,即全透明,然后绘制非截图区域为半透明。代码如下:
if(type == QEvent::Paint)
{
qDebug() << "start paint";
QRect rc = ComputeRect(ptStart,ptEnd);
QPainter painter(screenshot_dlg_);
if(bCapStart)
{
//设置mask 使当前区域全透明
QPolygon polygon1;
QRect screenRc = ScreenRect();
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.setPen(QPen(Qt::NoPen));
polygon1 << QPoint(screenRc.left(),screenRc.top())
<< QPoint(screenRc.right(),screenRc.top())
<< QPoint(rc.right(),rc.top())
<< QPoint(rc.left(),rc.top());
painter.drawPolygon(polygon1);
QPolygon polygon2;
polygon2 << QPoint(screenRc.left(),screenRc.top())
<< QPoint(screenRc.left(),screenRc.bottom())
<< QPoint(rc.left(),rc.bottom())
<< QPoint(rc.left(),rc.top());
painter.drawPolygon(polygon2);
QPolygon polygon3;
polygon3 << QPoint(screenRc.left(),screenRc.bottom())
<< QPoint(screenRc.right(),screenRc.bottom())
<< QPoint(rc.right(),rc.bottom())
<< QPoint(rc.left(),rc.bottom());
painter.drawPolygon(polygon3);
QPolygon polygon4;
polygon4 << QPoint(screenRc.right(),screenRc.top())
<< QPoint(screenRc.right(),screenRc.bottom())
<< QPoint(rc.right(),rc.bottom())
<< QPoint(rc.right(),rc.top());
painter.drawPolygon(polygon4);
}
else
{
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.drawRect(ScreenRect());
}
}
以上4个区域polygon1、polygon2、polygon3、polygon4 即为非截图区域,
我们把它搞成半透明,未绘制的就是全透明了(因为窗口就是全透的)。
完整代码如下:
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QDialog>
#include <QRect>
#include <QSizeGrip>
class SceenShot:public QWidget
{
public:
SceenShot(QWidget* parent = Q_NULLPTR);
void updateShowScreenshot();
bool eventFilter(QObject *watched, QEvent *event) override;
protected:
void resizeEvent(QResizeEvent *event) override;
QRect ScreenRect();
public slots:
void StartShotScreen();
void ShootScreen(QRect& rc);
private:
QRect ComputeRect(QPoint& pt1,QPoint& pt2);
QDialog* screenshot_dlg_;
QPushButton* shot_screen_;
QVBoxLayout* vbox_;
QLabel* show_label_;
QPixmap originalPixmap;
//绘制截图窗口用的
QPixmap* m_Cache;
QSizeGrip m_SizeGrip;
};
#endif // WINDOW_H
window.cpp
#include "window.h"
#include <QGuiApplication>
#include <QWindow>
#include <QScreen>
#include <QMouseEvent>
#include <QPainter>
#include <QPen>
#include <QDebug>
#include <QImage>
#include <QBitmap>
SceenShot::SceenShot(QWidget* parent)
:QWidget(parent),m_SizeGrip(nullptr)
{
m_Cache = nullptr;
vbox_ = new QVBoxLayout(this);
shot_screen_ = new QPushButton(tr("shootScreen"),this);
shot_screen_->setShortcut(tr("ctrl+a"));
show_label_ = new QLabel(this);
show_label_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
show_label_->setAlignment(Qt::AlignCenter);
show_label_->setMinimumSize(300,300);
show_label_->setPixmap(originalPixmap);
connect(shot_screen_,&QPushButton::clicked,this,&SceenShot::StartShotScreen);
vbox_->addWidget(shot_screen_);
vbox_->addWidget(show_label_);
screenshot_dlg_ = new QDialog(this,Qt::FramelessWindowHint);
screenshot_dlg_->setAttribute(Qt::WA_TranslucentBackground);
screenshot_dlg_->hide();
//给Dialog 安装事件过滤器
screenshot_dlg_->installEventFilter(this);
//this->setLayout(vbox_);
}
void SceenShot::ShootScreen(QRect& rc)
{
shot_screen_->setEnabled(false);
QScreen* screen = QGuiApplication::primaryScreen();
if(const QWindow* window = windowHandle())
{
screen = window->screen();
}
if(!screen)
return;
originalPixmap = screen->grabWindow(0,rc.left(),rc.top(),rc.right() - rc.left(),rc.bottom() - rc.top());
updateShowScreenshot();
shot_screen_->setEnabled(true);
}
void SceenShot::updateShowScreenshot()
{
show_label_->setPixmap(originalPixmap.scaled(show_label_->size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
}
void SceenShot::resizeEvent(QResizeEvent *event)
{
QSize scaledSize = originalPixmap.size();
scaledSize.scale(show_label_->size(), Qt::KeepAspectRatio);
if (!show_label_->pixmap() || scaledSize != show_label_->pixmap()->size())
updateShowScreenshot();
}
void SceenShot::StartShotScreen()
{
//获取屏幕大小信息
QScreen* primaryScreen = QGuiApplication::primaryScreen();
QRect rect = primaryScreen->geometry();
screenshot_dlg_->setGeometry(rect);
screenshot_dlg_->show();
}
bool SceenShot::eventFilter(QObject *watched, QEvent *event)
{
static QPoint ptStart ={0,0};
static QPoint ptEnd ={0,0};
static bool bCapStart = false;
QEvent::Type type = event->type();
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
if(mouse_event && mouse_event->button() == Qt::LeftButton && type == QEvent::MouseButtonPress)
{
//鼠标左键按下,记录按下位置
bCapStart = true;
ptStart = mouse_event->pos();
}
else if(mouse_event && mouse_event->button() == Qt::LeftButton && type == QEvent::MouseButtonRelease)
{
//qDebug() << "MouseButtonRelease";
bCapStart = false;
QRect rc = ComputeRect(ptStart,ptEnd);
qDebug() << "x:" << rc.left() << " y:" << rc.top() << " right:" << rc.right() << " bottom:" << rc.bottom();
ShootScreen(rc);
ptStart.setX(0);
ptStart.setY(0);
ptEnd.setX(0);
ptEnd.setY(0);
}
else if(bCapStart && type == QEvent::MouseMove)
{
ptEnd = mouse_event->pos();
screenshot_dlg_->update();
}
// //重写Dialog得绘制事件和改变大小事件
// if(type == QEvent::Paint)
// {
// if(m_Cache != NULL)
// {
// QPainter painter(screenshot_dlg_);
// painter.drawPixmap(0, 0, *m_Cache);
// #if QT_VERSION >= 0x040500
// if(!testAttribute(Qt::WA_TranslucentBackground)) screenshot_dlg_->setMask(m_Cache->mask());
// #else
// screenshot_dlg_->setMask(m_Cache->mask());
// #endif
// }
// }
// else if(type == QEvent::Resize)
// {
// delete m_Cache;
// m_Cache = new QPixmap(screenshot_dlg_->size());
// m_Cache->fill(Qt::transparent);
// QPainter painter(m_Cache);
// QColor darkBlue ( 23, 23, 34);
// QColor lightBlue(177, 177, 203);
// /********** Window's background **********/
// QPolygon background;
// background << QPoint( 0, 16)
// << QPoint( 16, 0)
// << QPoint(width() - 1, 0)
// << QPoint(width() - 1, height() - 33)
// << QPoint(width() - 17, height() - 17)
// << QPoint( 272, height() - 17)
// << QPoint( 256, height() - 1)
// << QPoint( 16, height() - 1)
// << QPoint( 16, 272)
// << QPoint( 0, 256);
// painter.setPen (QPen (darkBlue));
// painter.setBrush(QBrush(darkBlue));
// painter.drawPolygon(background);
// /*****************************************/
// /********** Window's frame **********/
// QPolygon frame;
// frame << QPoint( 4, 20)
// << QPoint( 20, 4)
// << QPoint(width() - 4, 4)
// << QPoint(width() - 4, height() - 37)
// << QPoint(width() - 20, height() - 21)
// << QPoint( 268, height() - 21)
// << QPoint( 252, height() - 5)
// << QPoint( 20, height() - 5)
// << QPoint( 20, 268)
// << QPoint( 4, 252);
// painter.setPen (QPen(lightBlue));
// painter.setBrush(Qt::NoBrush );
// painter.drawPolygon(frame);
// /*****************************************/
// //m_SizeGrip.move (width() - 32, height() - 49);
// //m_SizeGrip.resize( 32, 32);
// }
if(type == QEvent::Paint)
{
qDebug() << "start paint";
QRect rc = ComputeRect(ptStart,ptEnd);
QPainter painter(screenshot_dlg_);
if(bCapStart)
{
//设置mask 使当前区域全透明
QPolygon polygon1;
QRect screenRc = ScreenRect();
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.setPen(QPen(Qt::NoPen));
polygon1 << QPoint(screenRc.left(),screenRc.top())
<< QPoint(screenRc.right(),screenRc.top())
<< QPoint(rc.right(),rc.top())
<< QPoint(rc.left(),rc.top());
painter.drawPolygon(polygon1);
QPolygon polygon2;
polygon2 << QPoint(screenRc.left(),screenRc.top())
<< QPoint(screenRc.left(),screenRc.bottom())
<< QPoint(rc.left(),rc.bottom())
<< QPoint(rc.left(),rc.top());
painter.drawPolygon(polygon2);
QPolygon polygon3;
polygon3 << QPoint(screenRc.left(),screenRc.bottom())
<< QPoint(screenRc.right(),screenRc.bottom())
<< QPoint(rc.right(),rc.bottom())
<< QPoint(rc.left(),rc.bottom());
painter.drawPolygon(polygon3);
QPolygon polygon4;
polygon4 << QPoint(screenRc.right(),screenRc.top())
<< QPoint(screenRc.right(),screenRc.bottom())
<< QPoint(rc.right(),rc.bottom())
<< QPoint(rc.right(),rc.top());
painter.drawPolygon(polygon4);
}
else
{
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.drawRect(ScreenRect());
}
}
return false;
}
QRect SceenShot::ComputeRect(QPoint& pt1,QPoint& pt2)
{
QRect rc;
if(pt1.x() > pt2.x())
{
if(pt1.y() > pt2.y())
{
//pt1 为右下点
rc.setTopLeft(pt2);
rc.setBottomRight(pt1);
}
else
{
rc.setBottomLeft(pt2);
rc.setTopRight(pt1);
}
}
else
{
if(pt1.y() > pt2.y())
{
//pt1 为左下点
rc.setBottomLeft(pt1);
rc.setTopRight(pt2);
}
else
{
rc.setTopLeft(pt1);
rc.setBottomRight(pt2);
}
}
return rc;
}
QRect SceenShot::ScreenRect()
{
QScreen* screen = QGuiApplication::primaryScreen();
return screen->geometry();
}
main.cpp
#include <QApplication>
#include "window.h"
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
SceenShot sc;
sc.show();
sc.resize(300,300);
return app.exec();
}
以上就是简单的截图功能。使用鼠标拖拽截图。