Skip to content

Commit

Permalink
[feature]支持徒手绘制区域截图
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Oct 7, 2022
1 parent e8e61f6 commit 734169e
Show file tree
Hide file tree
Showing 26 changed files with 2,038 additions and 27 deletions.
38 changes: 32 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,49 @@
3. 支持截取**光标**
4. 支持**热键**截图
5. 支持**自由框选截图**
6. 支持**录制GIF**
7. 支持**自动保存**图片
8. 支持**多显示屏**(仅在双显示屏下测试)
9. 支持**最小化****托盘**
10. 支持**跟随系统启动**
11. ......
6. 支持**徒手绘制**区域**截图**
7. 支持**录制GIF**
8. 支持**自动保存**图片
9. 支持**多显示屏**(仅在双显示屏下测试)
10. 支持**最小化****托盘**
11. 支持**跟随系统启动**
12. ......

## 🚧待实现

- **编辑**截图
- **固定区域**截图
- **多区域**截图
- **滚动**长截图(图片**拼接算法**问题待解决)

## 🤩应用截图

#### 首页

![image](image/screenshot/ic_main_window.png)

#### 自由框选截图

![ic_freesnap_dialog](image/screenshot/ic_freesnap_dialog.png)

#### **徒手绘制**区域截图

![ic_freehandsnap_dialog](image/screenshot/ic_freehandsnap_dialog.png)

#### **徒手绘制**区域截图效果

![ic_freehandsnap_result](image/screenshot/ic_freehandsnap_result.png)

#### 录制GIF

![ic_gif_dialog](image/screenshot/ic_gif_dialog.png)

#### 常规设置

![ic_setting_dialog](image/screenshot/ic_setting_dialog.png)

#### 捕捉设置

![ic_setting_dialog_2](image/screenshot/ic_setting_dialog_2.png)

## 🎉特别感谢
Expand Down
8 changes: 8 additions & 0 deletions SmartScreenSnapper/SmartScreenSnapper.pro
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ SOURCES += \
src/aboutdialog.cpp \
src/application.cpp \
src/const.cpp \
src/freehandsnapdialog.cpp \
src/freehandsnap/freehandsnapgraphicsscene.cpp \
src/freesnap/freesnapgraphicsview.cpp \
src/freesnap/freesnaprect.cpp \
src/freesnap/freesnapscene.cpp \
src/freesnapdialog.cpp \
src/gif-h/gif.cpp \
src/gifdialog.cpp \
src/graphicsview.cpp \
src/longsnapdialog.cpp \
src/main.cpp \
src/mainwindow.cpp \
src/mdiwindow.cpp \
Expand All @@ -45,13 +48,16 @@ HEADERS += \
src/aboutdialog.h \
src/application.h \
src/const.h \
src/freehandsnapdialog.h \
src/freehandsnap/freehandsnapgraphicsscene.h \
src/freesnap/freesnapgraphicsview.h \
src/freesnap/freesnaprect.h \
src/freesnap/freesnapscene.h \
src/freesnapdialog.h \
src/gif-h/gif.h \
src/gifdialog.h \
src/graphicsview.h \
src/longsnapdialog.h \
src/mainwindow.h \
src/mdiwindow.h \
src/minifmod.h \
Expand All @@ -64,6 +70,8 @@ HEADERS += \
src/windowsinfo.h

FORMS += \
ui/freehandsnapdialog.ui \
ui/longsnapdialog.ui \
ui/aboutdialog.ui \
ui/freesnapdialog.ui \
ui/gifdialog.ui \
Expand Down
6 changes: 3 additions & 3 deletions SmartScreenSnapper/SmartScreenSnapper.pro.user
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2022-10-06T12:42:40. -->
<!-- Written by QtCreator 4.11.1, 2022-10-06T19:57:25. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
Expand Down Expand Up @@ -67,7 +67,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.14.2 MinGW 32-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.14.2 MinGW 32-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5142.win32_mingw73_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
Expand Down Expand Up @@ -299,7 +299,7 @@
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">E:/C++/SmartScreenSnapper/build-SmartScreenSnapper-Desktop_Qt_5_14_2_MinGW_32_bit-Debug</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">E:/C++/SmartScreenSnapper/build_MinGW_32_bit-Release</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
Expand Down
11 changes: 11 additions & 0 deletions SmartScreenSnapper/res/image/FreeHandSnap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions SmartScreenSnapper/res/res.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
<file>image/GIFRecord.png</file>
<file>image/Setting.svg</file>
<file>image/GitHub.svg</file>
<file>image/FreeHandSnap.svg</file>
</qresource>
</RCC>
105 changes: 105 additions & 0 deletions SmartScreenSnapper/src/freehandsnap/freehandsnapgraphicsscene.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "freehandsnapgraphicsscene.h"

#include <QGraphicsSceneMouseEvent>
#include <QGraphicsPolygonItem>
#include <QRegion>
#include <QDebug>

FreeHandSnapGraphicsScene::FreeHandSnapGraphicsScene(QWidget *parent) :
QGraphicsScene(parent),
mousePressed(false),
unsuredPath(nullptr),
hasNewUnsuredPath(false),
path(),
pathItem(nullptr),
grayItem(nullptr),
grayColor(0, 0, 0, 180)
{
connect(this, &QGraphicsScene::sceneRectChanged, this, [=](){
refreshGrayArea();
});
}

FreeHandSnapGraphicsScene::~FreeHandSnapGraphicsScene()
{
if (unsuredPath) delete unsuredPath;
if (path) delete path;
}

QPolygonF FreeHandSnapGraphicsScene::getPathPolygonF()
{
auto p = QPainterPath(*path);
QPointF point = pathItem->pos();
p.translate(-point.x(), -point.y());
return p.toFillPolygon();
}

QRectF FreeHandSnapGraphicsScene::getPathRect()
{
return path->boundingRect();
}

void FreeHandSnapGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
mousePressed = true;
hasNewUnsuredPath = false;
if (!path) {
path = new QPainterPath(event->scenePos());
}
}

void FreeHandSnapGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
mousePressed = false;

if (hasNewUnsuredPath) {
path = new QPainterPath(*unsuredPath);
hasNewUnsuredPath = false;
refreshPathItem(*path);
}
}

void FreeHandSnapGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (mousePressed) {
path->lineTo(event->scenePos());
refreshPathItem(*path);
} else if (path) {
unsuredPath = new QPainterPath(*path);
unsuredPath->lineTo(event->scenePos());
hasNewUnsuredPath = true;
refreshPathItem(*unsuredPath);
}
}

// 更新区域和阴影
void FreeHandSnapGraphicsScene::refreshPathItem(QPainterPath path)
{
refreshGrayArea();
if (pathItem) {
removeItem(pathItem);
delete pathItem;
}
pathItem = addPath(path, QPen(QBrush(Qt::yellow), 5));
}


// 绘制灰色阴影
void FreeHandSnapGraphicsScene::refreshGrayArea()
{
if (grayItem) {
removeItem(grayItem);
delete grayItem;
}

if (!path) {
grayItem = addRect(sceneRect(),
QPen(Qt::transparent),
QBrush(grayColor));
return;
}

grayItem = addPolygon(QPolygonF(sceneRect()).subtracted(path->toFillPolygon()),
QPen(Qt::transparent),
QBrush(grayColor));
}
35 changes: 35 additions & 0 deletions SmartScreenSnapper/src/freehandsnap/freehandsnapgraphicsscene.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef FREEHANDSNAPGRAPHICSVIEW_H
#define FREEHANDSNAPGRAPHICSVIEW_H

#include <QGraphicsView>

class FreeHandSnapGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
FreeHandSnapGraphicsScene(QWidget *parent = nullptr);

~FreeHandSnapGraphicsScene();

QPolygonF getPathPolygonF();

QRectF getPathRect();

protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void refreshPathItem(QPainterPath path);
void refreshGrayArea();
private:
bool mousePressed;

QPainterPath* unsuredPath;
bool hasNewUnsuredPath;
QPainterPath* path;
QGraphicsItem* pathItem;
QGraphicsItem* grayItem;
QColor grayColor;
};

#endif // FREEHANDSNAPGRAPHICSVIEW_H
60 changes: 60 additions & 0 deletions SmartScreenSnapper/src/freehandsnapdialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "freehandsnapdialog.h"
#include "ui_freehandsnapdialog.h"
#include "windows.h"
#include "screenshothelper.h"
#include "freehandsnap/freehandsnapgraphicsscene.h"

#include <QMouseEvent>
#include <QPainter>
#include <QDebug>

FreeHandSnapDialog::FreeHandSnapDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::FreeHandSnapDialog)
{
ui->setupUi(this);

setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setWindowState(Qt::WindowActive);
//多显示器支持
move(GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN));
resize(GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)); //信息Widget不接收鼠标事件

// 可在不点击鼠标的情况下捕获移动事件
setMouseTracking(true);
ui->graphicsView->setMouseTracking(true);

fullScreenPixmap = ScreenShotHelper::getFullScreen();
scene = new FreeHandSnapGraphicsScene(this);
scene->setSceneRect(QRectF(0, 0, width(), height()));
scene->setBackgroundBrush(QBrush(fullScreenPixmap));
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
ui->graphicsView->setScene(scene);
ui->graphicsView->setGeometry(0, 0, width(), height());
}

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

void FreeHandSnapDialog::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape) {
close();
return;
} else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
QRectF r = scene->getPathRect();
// 先用QImage设置透明度,直接用QPixmap是黑色背景,设置透明无效
QImage image(r.width(), r.height(), QImage::Format_ARGB32_Premultiplied);
QPainter painter(&image);
image.fill(Qt::transparent);
painter.setBrush(QBrush(fullScreenPixmap));
painter.setPen(QPen(Qt::transparent));
painter.translate(-r.x(), -r.y());
painter.drawConvexPolygon(scene->getPathPolygonF());
emit captured(QPixmap::fromImage(image));
close();
return;
}
}
35 changes: 35 additions & 0 deletions SmartScreenSnapper/src/freehandsnapdialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef FREEHANDSNAPDIALOG_H
#define FREEHANDSNAPDIALOG_H

#include <QDialog>
#include <QGraphicsScene>

#include <src/freehandsnap/freehandsnapgraphicsscene.h>

namespace Ui {
class FreeHandSnapDialog;
}

class FreeHandSnapDialog : public QDialog
{
Q_OBJECT

signals:
void captured(QPixmap);

public:
explicit FreeHandSnapDialog(QWidget *parent = nullptr);
~FreeHandSnapDialog();

private:
Ui::FreeHandSnapDialog *ui;

FreeHandSnapGraphicsScene *scene;

QPixmap fullScreenPixmap;

protected:
void keyPressEvent(QKeyEvent *event);
};

#endif // FREEHANDSNAPDIALOG_H
Loading

0 comments on commit 734169e

Please sign in to comment.