#include "ScreenShot.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
/**
* @brief 截图矩形框边框尺寸
*/
#define SELECT_RECT_BORDER 1
/**
* @brief 定位拉伸点位边长
*/
#define STRETCH_RECT_SIDE 7
/**
* @brief 定位拉伸点位状态枚举
*/
enum StretchPointState
{
NoSelect, //未选中
TopLeft, //左上
TopCenter, //中上
TopRight, //右上
LeftCenter, //左中
RightCenter, //右中
BottomLeft, //左下
BottomCenter, //中下
BottomRight //右下
};
//截图状态枚举
enum CaptureState
{
Begin, //初始状态
BeginCaptureImage, //开始截图
FinishCaptureImage, //结束截图
BeginMoveCaptureArea, //开始移动截图区域
FinishMoveCaptureArea, //结束移动截图区域
BeginMoveStretchPoint, //开始移动定位拉伸点
FinishMoveStretchPoint, //结束移动定位拉伸点
Finish //结束状态
};
/**
* @brief 截图私有数据类
*/
class ScreenShotPrivate
{
Q_DECLARE_PUBLIC(ScreenShot)
public:
ScreenShotPrivate(ScreenShot *p);
/**
* @brief 初始化定位拉伸点
*/
void initStretchRect();
private:
ScreenShot * const q_ptr;
/**
* @brief 当前选中区域
*/
QRect m_SelectRect;
/**
* @brief 选中截图
*/
QPixmap m_CapturePixmap;
/**
* @brief 背景图,屏幕内容
*/
QPixmap m_BackGroundPixmap;
/**
* @brief 绘图操作对象
*/
QPainter m_Painter;
/**
* @brief 截图状态
*/
CaptureState m_CaptureState;
/**
* @brief 定位拉伸点位状态
*/
StretchPointState m_StretchPointState;
/**
* @brief 定位拉伸点
*/
QRect m_TopLeftRect; //左上
QRect m_TopCenterRect; //中上
QRect m_TopRightRect; //右上
QRect m_LeftCenterRect; //左中
QRect m_RightCenterRect; //右中
QRect m_BottomLeftRect; //左下
QRect m_BottomCenterRect; //中下
QRect m_BottomRightRect; //右下
/**
* @brief 截图开始点
*/
QPoint m_StartPoint;
/**
* @brief 截图结束点
*/
QPoint m_EndPoint;
/**
* @brief 移动开始点
*/
QPoint m_StartMovePoint;
/**
* @brief 移动结束点
*/
QPoint m_EndMovePoint;
};
ScreenShotPrivate::ScreenShotPrivate(ScreenShot *p) :
q_ptr(p)
{
m_CaptureState = CaptureState::Begin;
m_SelectRect = QRect(0, 0, 1, 1);
initStretchRect();
}
void ScreenShotPrivate::initStretchRect()
{
m_StretchPointState = StretchPointState::NoSelect;
m_TopLeftRect = QRect(0, 0, 0, 0);
m_TopCenterRect = QRect(0, 0, 0, 0);
m_TopRightRect = QRect(0, 0, 0, 0);
m_LeftCenterRect = QRect(0, 0, 0, 0);
m_RightCenterRect = QRect(0, 0, 0, 0);
m_BottomLeftRect = QRect(0, 0, 0, 0);
m_BottomCenterRect = QRect(0, 0, 0, 0);
m_BottomRightRect = QRect(0, 0, 0, 0);
}
ScreenShot::ScreenShot(QWidget *parent) :
QWidget(parent),
d_ptr(new ScreenShotPrivate(this))
{
init();
}
/**
* @brief 初始化
*/
void ScreenShot::init()
{
initUI();
}
/**
* @brief UI初始化
*/
void ScreenShot::initUI()
{
//设置鼠标跟踪属性
setMouseTracking(true);
//设置置顶
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
//设置全屏
setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
//加载背景图片
loadBackGroundPixmap();
}
/**
* @brief 加载背景图
*/
void ScreenShot::loadBackGroundPixmap()
{
//暂时定位获取主屏区域,多屏情况待优化
QDesktopWidget *desk = QApplication::desktop();
QScreen *screen = QApplication::primaryScreen();
d_ptr->m_BackGroundPixmap = screen->grabWindow(0, 0, 0, desk->width(), desk->height());
}
/**
* @brief 点是否处于选中区域内
* @param point
* @return
*/
bool ScreenShot::isInSelectRect(QPoint point)
{
return d_ptr->m_SelectRect.contains(point);
}
/**
* @brief 根据两个点位获取矩形区域
* @param beginPoint
* @param endPoint
* @return
*/
QRect ScreenShot::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();
// 避免宽或高为零时拷贝截图有误;
// 参考QQ截图,当选取截图宽或高为零时默认为2;
if(width == 0)
{
width = 2;
}
if(height == 0)
{
height = 2;
}
return QRect(x, y, width, height);
}
/**
* @brief 获取移动后的选中区域
* @return
*/
QRect ScreenShot::getMoveRect()
{
//移动偏移量
QPoint movePoint = d_ptr->m_EndMovePoint - d_ptr->m_StartMovePoint;
//开始移动时的选择区域
QRect selectRect = getRect(d_ptr->m_StartPoint, d_ptr->m_EndPoint);
//检查是否超出背景区域,并纠正
//超出左边界
if(selectRect.topLeft().x() + movePoint.x() < 0)
{
movePoint.setX(0 - selectRect.topLeft().x());
}
//超出右边界
if(selectRect.bottomRight().x() + movePoint.x() > d_ptr->m_BackGroundPixmap.width())
{
movePoint.setX(d_ptr->m_BackGroundPixmap.width() - selectRect.bottomRight().x());
}
//超出上边界
if(selectRect.topLeft().y() + movePoint.y() < 0)
{
movePoint.setY(0 - selectRect.topLeft().y());
}
//超出下边界
if(selectRect.bottomRight().y() + movePoint.y() > d_ptr->m_BackGroundPixmap.height())
{
movePoint.setY(d_ptr->m_BackGroundPixmap.height() - selectRect.bottomRight().y());
}
QPoint startPoint = d_ptr->m_StartPoint + movePoint;
QPoint endPoint = d_ptr->m_EndPoint + movePoint;
//结束移动选区时更新当前d_ptr->m_StartPoint , d_ptr->m_EndPoint,防止下一次操作时截取的图片有问题;
if (d_ptr->m_CaptureState == CaptureState::FinishMoveCaptureArea)
{
d_ptr->m_StartPoint = startPoint;
d_ptr->m_EndPoint = endPoint;
d_ptr->m_StartMovePoint = QPoint(0, 0);
d_ptr->m_EndMovePoint = QPoint(0, 0);
}
return getRect(startPoint, endPoint);
}
/**
* @brief 获取拉伸后的选中区域
* @return
*/
QRect ScreenShot::getStretchRect()
{
QRect stretchRect;
//开始移动时的选择区域
QRect selectRect = getRect(d_ptr->m_StartPoint, d_ptr->m_EndPoint);
switch(d_ptr->m_StretchPointState)
{
case StretchPointState::NoSelect:
stretchRect = selectRect;
break;
case StretchPointState::TopLeft:
{
stretchRect = getRect(selectRect.bottomRight(), d_ptr->m_EndMovePoint);
}
break;
case StretchPointState::TopRight:
{
stretchRect = getRect(selectRect.bottomLeft(), d_ptr->m_EndMovePoint);
}
break;
case StretchPointState::BottomLeft:
{
stretchRect = getRect(selectRect.topRight(), d_ptr->m_EndMovePoint);
}
break;
case StretchPointState::BottomRight:
{
stretchRect = getRect(selectRect.topLeft(), d_ptr->m_EndMovePoint);
}
break;
case StretchPointState::LeftCenter:
{
stretchRect = getRect(QPoint(d_ptr->m_EndMovePoint.x(), selectRect.topLeft().y()), selectRect.bottomRight());
}
break;
case StretchPointState::TopCen