509 lines
12 KiB
C++
509 lines
12 KiB
C++
/**
|
||
* @author : 陈鲁勇
|
||
* @date : 2017年04月
|
||
* @version: 1.0
|
||
* @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权;
|
||
* 除非遵守本许可,否则您不能使用这个文件。
|
||
* @remarks: 您可以获得该许可的副本:
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
* 除非适用法律需要或者书面同意,按本许可分发的软件
|
||
* 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。
|
||
* 参见按照本许可控制许可权限及限制的特定语言的许可证。
|
||
*
|
||
* 你可以获得该代码的最新版本:
|
||
*
|
||
* https://git.oschina.net/Mr_ChenLuYong/screenshot
|
||
*
|
||
* 开源社区的所有人都期待与你的共同维护。
|
||
*
|
||
*
|
||
* 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习:
|
||
*
|
||
* 博客地址:http://blog.csdn.net/csnd_ayo
|
||
*
|
||
* 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915
|
||
*
|
||
* 期待你提交Bug,欢迎Issues。
|
||
*
|
||
*/
|
||
|
||
|
||
#ifndef OESCREENSHOT_H
|
||
#define OESCREENSHOT_H
|
||
|
||
#include <memory>
|
||
#include <QRect>
|
||
#include <QWidget>
|
||
|
||
class OEScreen;
|
||
class OERect;
|
||
class OEAmplifier;
|
||
class QTimer;
|
||
class QMenu;
|
||
|
||
|
||
/**
|
||
* @class : OEScreenshot
|
||
* @brief : 截屏功能的主要入口,
|
||
* 管理全局热键,资源的回收与释放.
|
||
* @remark: 调用示例( OEScreenshot::Instance(); )
|
||
*/
|
||
class OEScreenshot : public QWidget {
|
||
Q_OBJECT
|
||
|
||
signals:
|
||
|
||
/**
|
||
* @brief : 鼠标移动(信号)
|
||
* @param : int x轴的坐标
|
||
* @param : int y轴的坐标
|
||
* @date : 2017年04月18日
|
||
*/
|
||
void cursorPosChange(int, int);
|
||
|
||
/**
|
||
* @brief : 双击(信号)
|
||
* @date : 2017年04月18日
|
||
*/
|
||
void doubleClick(void);
|
||
|
||
/**
|
||
* @brief : 鼠标当前位置最小的子窗口(信号)
|
||
* @param : QRect 当前窗口的矩形数据
|
||
* @date : 2017年04月18日
|
||
*/
|
||
void findChildWind(QRect);
|
||
|
||
public:
|
||
/**
|
||
* @brief : 构造函数
|
||
* @note : 当前依附的父窗口(一般不给父窗口)
|
||
* @date : 2017年04月16日
|
||
*/
|
||
explicit OEScreenshot(QWidget *parent = 0);
|
||
~OEScreenshot(void);
|
||
|
||
/**
|
||
* @brief : 窗口实例
|
||
* @note : 通过这个函数获得截图器的整个实例
|
||
* @return: 返回 OEScreenshot 实例指针
|
||
* @date : 2017年04月15日
|
||
*/
|
||
static OEScreenshot *Instance(void);
|
||
|
||
/**
|
||
* @brief : 摧毁截图窗口
|
||
* @note : 通过这个函数可以摧毁整个截图窗口
|
||
* @date : 2017年04月30日
|
||
*/
|
||
static void destroy(void);
|
||
|
||
protected:
|
||
|
||
/**
|
||
* @brief : 隐藏窗口事件
|
||
*/
|
||
virtual void hideEvent(QHideEvent *);
|
||
/**
|
||
* @brief : 关闭窗口事件
|
||
*/
|
||
virtual void closeEvent(QCloseEvent *);
|
||
/**
|
||
* @brief : 双击事件
|
||
*/
|
||
virtual void mouseDoubleClickEvent(QMouseEvent*);
|
||
/**
|
||
* @brief : 鼠标按下事件
|
||
*/
|
||
virtual void mousePressEvent(QMouseEvent *);
|
||
/**
|
||
* @brief : 鼠标释放事件
|
||
*/
|
||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||
/**
|
||
* @brief : 鼠标移动事件
|
||
*/
|
||
virtual void mouseMoveEvent(QMouseEvent *e);
|
||
|
||
/**
|
||
* @brief : 按键按下事件
|
||
*/
|
||
virtual void keyPressEvent(QKeyEvent *e);
|
||
/**
|
||
* @brief : 自绘事件
|
||
*/
|
||
virtual void paintEvent(QPaintEvent *);
|
||
|
||
/**
|
||
* @brief : 更新当前鼠标选区的窗口
|
||
*/
|
||
void updateMouse(void);
|
||
|
||
private:
|
||
|
||
|
||
/**
|
||
* @brief : 初始化放大镜 (色彩采集器)
|
||
* @note : 他需要屏幕的原画作为放大器的放大元素
|
||
* @param : originPainting 放大器必要的元素,若为空,则默认用originPainting_原画
|
||
* @date : 2017年04月15日
|
||
* @remark: 需先行调用getGlobalScreen。
|
||
*/
|
||
void initAmplifier(std::shared_ptr<QPixmap> originPainting = nullptr);
|
||
|
||
/**
|
||
* @brief : 测量控件 (大小感知器)
|
||
* @date : 2017年04月27日
|
||
*/
|
||
void initMeasureWidget(void);
|
||
|
||
/**
|
||
* @brief : 初始化截屏背景
|
||
* @return: QPixmap 经过暗色处理的屏幕图
|
||
* @date : 2017年04月15日
|
||
*/
|
||
std::shared_ptr<QPixmap> initGlobalScreen(void);
|
||
|
||
|
||
/**
|
||
* @brief : 初始化鼠标
|
||
* @note : 为鼠标设置默认状态下的图标样式
|
||
* @param : ico 鼠标图片的资源文件路径
|
||
* @date : 2017年04月15日
|
||
* @remark: 若参数未填写,在使用本程序默认的鼠标Logo
|
||
*/
|
||
void initCursor(const QString& ico = "");
|
||
|
||
/**
|
||
* @brief : 创建截图器
|
||
* @note : 若截图器已存在,则返回截图器示例,不会重复创建。
|
||
* @param : pos 截图器的起始位置 (给当前鼠标位置即可)
|
||
* @date : 2017年04月16日
|
||
* @remark: 创建截图器前,需要创建相关的组件,(例:大小感知器,放大取色器)
|
||
*/
|
||
std::shared_ptr<OEScreen> createScreen(const QPoint &pos);
|
||
|
||
/**
|
||
* @brief : 摧毁截图器
|
||
* @note : 若截图器已存在,则摧毁示例,并清理示例创建的连带资源
|
||
* @date : 2017年04月16日
|
||
*/
|
||
void destroyScreen(void);
|
||
|
||
|
||
/**
|
||
* @brief : 获得当前屏幕的大小
|
||
* @note : 这个函数是支持多屏幕的,示例:双屏幕 QRect(-1920, 0, 3840, 1080)
|
||
* @return: 返回 QRect 引用
|
||
* @date : 2017年04月15日
|
||
*/
|
||
const QRect& getScreenRect(void);
|
||
|
||
/**
|
||
* @brief : 获得屏幕的原画
|
||
* @note : 他不会重复获得屏幕原画,如果有,则返回原有的原画
|
||
* @return: QPixmap* 指针
|
||
* @date : 2017年04月15日
|
||
* @remark: 若想重新获得屏幕原画,需要清理原有资源
|
||
*/
|
||
std::shared_ptr<QPixmap> getGlobalScreen(void);
|
||
|
||
|
||
private:
|
||
|
||
/// 截屏窗口是否已经展示
|
||
bool isLeftPressed_;
|
||
/// 用于检测误操作
|
||
QPoint startPoint_;
|
||
/// 当前桌面屏幕的矩形数据
|
||
QRect desktopRect_;
|
||
/// 屏幕暗色背景图
|
||
std::shared_ptr<QPixmap> backgroundScreen_;
|
||
/// 屏幕原画
|
||
std::shared_ptr<QPixmap> originPainting_;
|
||
/// 截图屏幕
|
||
std::shared_ptr<OEScreen> screenTool_;
|
||
/// 截图器大小感知器
|
||
std::shared_ptr<OERect> rectTool_;
|
||
/// 放大取色器
|
||
std::shared_ptr<OEAmplifier> amplifierTool_;
|
||
/// 当前鼠标选区最小的矩形窗口
|
||
QRect windowRect_;
|
||
/// 截屏实例对象
|
||
static OEScreenshot *self_;
|
||
/// 置顶定时器
|
||
QTimer* egoisticTimer_;
|
||
/// 活动窗口
|
||
static bool isActivity_;
|
||
private slots:
|
||
|
||
/**
|
||
* @brief : Window下霸道置顶(唯我独尊)
|
||
* @date : 2017年04月28日
|
||
* @remark: 使用该函数时,会终止右键菜单的行为,慎重使用,避免BUG
|
||
*/
|
||
void onEgoistic(void);
|
||
};
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @class : OERect
|
||
* @brief : 大小感知器
|
||
* @note : 主要关乎截图器左上方的大小感知控件
|
||
*/
|
||
class OERect : public QWidget {
|
||
Q_OBJECT
|
||
|
||
signals:
|
||
|
||
|
||
public:
|
||
|
||
explicit OERect(QWidget *parent = 0);
|
||
|
||
protected:
|
||
|
||
/**
|
||
* @brief : 自绘函数
|
||
*/
|
||
void paintEvent(QPaintEvent *);
|
||
|
||
public slots:
|
||
|
||
/**
|
||
* @brief : 外部组件位置修改(槽)
|
||
* @note : 感知器修改自身位置
|
||
* @param : x 横向位置
|
||
* @param : y 纵向位置
|
||
* @date : 2017年04月15日
|
||
*/
|
||
void onPostionChange(int x, int y);
|
||
|
||
/**
|
||
* @brief : 外部组件大小修改 (槽)
|
||
* @note : 感知器修改显示的大小数据
|
||
* @param : w 宽度
|
||
* @param : h 高度
|
||
* @date : 2017年04月15日
|
||
*/
|
||
void onSizeChange(int w, int h);
|
||
|
||
private:
|
||
/// 背景色
|
||
std::shared_ptr<QPixmap> backgroundPixmap_;
|
||
/// 显示的文字信息
|
||
QString info_;
|
||
};
|
||
|
||
|
||
/**
|
||
* @class : OEScreen
|
||
* @brief : 截图器
|
||
* @note : 主要关乎图片的编辑与保存
|
||
*/
|
||
class OEScreen : public QWidget {
|
||
|
||
Q_OBJECT
|
||
|
||
signals:
|
||
|
||
|
||
/**
|
||
* @brief : 截图器大小修改(信号)
|
||
* @param : int 宽度
|
||
* @param : int 高度
|
||
* @date : 2017年04月17日
|
||
*/
|
||
void sizeChange(int,int);
|
||
|
||
/**
|
||
* @brief : 截图器窗口的位置(信号)
|
||
* @param : int 窗口的横向位置
|
||
* @param : int 窗口的纵向位置
|
||
* @date : 2017年04月17日
|
||
*/
|
||
void postionChange(int,int);
|
||
|
||
/**
|
||
* @brief : 双击 (信号)
|
||
* @date : 2017年04月17日
|
||
*/
|
||
void doubleClick(void);
|
||
|
||
protected:
|
||
|
||
/// 内边距,决定拖拽的触发。
|
||
const int PADDING_ = 6;
|
||
|
||
/// 方位枚举
|
||
enum DIRECTION {
|
||
UPPER=0,
|
||
LOWER=1,
|
||
LEFT,
|
||
RIGHT,
|
||
LEFTUPPER,
|
||
LEFTLOWER,
|
||
RIGHTLOWER,
|
||
RIGHTUPPER,
|
||
NONE
|
||
};
|
||
|
||
public:
|
||
|
||
explicit OEScreen(std::shared_ptr<QPixmap> originPainting, QPoint pos, QWidget *parent = 0);
|
||
|
||
~OEScreen() { isInit_ = false; }
|
||
|
||
/**
|
||
* @brief : 获得当前截图器是否存在
|
||
* @return: true : 存在
|
||
* @date : 2017年04月17日
|
||
*/
|
||
static bool state(void) { return isInit_; }
|
||
|
||
protected:
|
||
|
||
/**
|
||
* @brief : 获得当前坐标点的边界方位
|
||
* @param : cursor 当前鼠标的位置
|
||
* @return: DIRECTION 鼠标的方位枚举
|
||
* @date : 2017年04月17日
|
||
*/
|
||
DIRECTION getRegion(const QPoint &cursor);
|
||
|
||
|
||
/**
|
||
* @brief : 呼出菜单事件
|
||
*/
|
||
virtual void contextMenuEvent(QContextMenuEvent *);
|
||
|
||
/**
|
||
* @brief : 双击事件
|
||
*/
|
||
virtual void mouseDoubleClickEvent(QMouseEvent *e);
|
||
|
||
/**
|
||
* @brief : 鼠标按下事件
|
||
*/
|
||
virtual void mousePressEvent(QMouseEvent *e);
|
||
|
||
/**
|
||
* @brief : 鼠标释放事件
|
||
*/
|
||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||
/**
|
||
* @brief : 鼠标移动事件
|
||
*/
|
||
virtual void mouseMoveEvent(QMouseEvent *e);
|
||
|
||
/**
|
||
* @brief : 窗口移动事件
|
||
*/
|
||
virtual void moveEvent(QMoveEvent *);
|
||
|
||
/**
|
||
* @brief : 窗口大小修改事件
|
||
*/
|
||
virtual void resizeEvent(QResizeEvent *);
|
||
|
||
|
||
/**
|
||
* @brief : 窗口显示事件
|
||
*/
|
||
virtual void showEvent(QShowEvent *);
|
||
|
||
/**
|
||
* @brief : 窗口隐藏事件
|
||
*/
|
||
virtual void hideEvent(QHideEvent *);
|
||
|
||
/**
|
||
* @brief : 鼠标进入窗口事件
|
||
*/
|
||
virtual void enterEvent(QEvent *e);
|
||
|
||
/**
|
||
* @brief : 鼠标离开窗口事件
|
||
*/
|
||
virtual void leaveEvent(QEvent *e);
|
||
|
||
/**
|
||
* @brief : 窗口关闭事件
|
||
*/
|
||
virtual void closeEvent(QCloseEvent *);
|
||
|
||
/**
|
||
* @brief : 界面自绘事件
|
||
*/
|
||
virtual void paintEvent(QPaintEvent *);
|
||
|
||
private:
|
||
|
||
/**
|
||
* @brief : 获得一个以时间格式命名的文件名
|
||
* @return: QString 文件名
|
||
* @date : 2017年04月16日
|
||
*/
|
||
virtual const QString getFileName(void);
|
||
|
||
public slots:
|
||
|
||
|
||
/**
|
||
* @brief : 根据鼠标位置修改窗口大小
|
||
* @param : x 鼠标的横向位置
|
||
* @param : y 鼠标的纵向位置
|
||
* @date : 2017年04月16日
|
||
*/
|
||
void onMouseChange(int x,int y);
|
||
|
||
/**
|
||
* @brief : 保存屏幕到剪切板中
|
||
* @date : 2017年04月16日
|
||
*/
|
||
void onSaveScreen(void);
|
||
|
||
protected slots:
|
||
|
||
/**
|
||
* @brief : 保存编辑屏幕到其他路径下
|
||
* @note : 会呼出路径选择的窗口
|
||
* @date : 2017年04月16日
|
||
*/
|
||
void onSaveScreenOther(void);
|
||
|
||
/**
|
||
* @brief : 退出当前截图窗口
|
||
* @date : 2017年04月16日
|
||
*/
|
||
void quitScreenshot(void);
|
||
|
||
private:
|
||
|
||
/// 是否已经设置初始大小
|
||
static bool isInit_;
|
||
/// 窗口大小改变时,记录改变方向
|
||
DIRECTION direction_;
|
||
/// 起点
|
||
QPoint originPoint_;
|
||
/// 鼠标是否按下
|
||
bool isPressed_;
|
||
/// 拖动的距离
|
||
QPoint movePos_;
|
||
/// 标记锚点
|
||
QPolygon listMarker_;
|
||
/// 屏幕原画
|
||
std::shared_ptr<QPixmap> originPainting_;
|
||
/// 当前窗口几何数据 用于绘制截图区域
|
||
QRect currentRect_;
|
||
/// 右键菜单对象
|
||
QMenu *menu_;
|
||
|
||
};
|
||
|
||
|
||
|
||
#endif /// OESCREENSHOT_H
|