/** * @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 #include #include 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 originPainting = nullptr); /** * @brief : 测量控件 (大小感知器) * @date : 2017年04月27日 */ void initMeasureWidget(void); /** * @brief : 初始化截屏背景 * @return: QPixmap 经过暗色处理的屏幕图 * @date : 2017年04月15日 */ std::shared_ptr 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 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 getGlobalScreen(void); private: /// 截屏窗口是否已经展示 bool isLeftPressed_; /// 用于检测误操作 QPoint startPoint_; /// 当前桌面屏幕的矩形数据 QRect desktopRect_; /// 屏幕暗色背景图 std::shared_ptr backgroundScreen_; /// 屏幕原画 std::shared_ptr originPainting_; /// 截图屏幕 std::shared_ptr screenTool_; /// 截图器大小感知器 std::shared_ptr rectTool_; /// 放大取色器 std::shared_ptr 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 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 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 originPainting_; /// 当前窗口几何数据 用于绘制截图区域 QRect currentRect_; /// 右键菜单对象 QMenu *menu_; }; #endif /// OESCREENSHOT_H