最近在学Qt。学东西怎么能不动手。

就写了些小程序。看QQ截图能够动态吸附直线的功能挺有意思,所以就模仿了一个。

先上效果图

界面很简单。。呵呵

移动鼠标,会把鼠标所在最小矩形选中。把没有选中的地方给模糊化,以示我们选中的区域很清楚。

还可以选中窗口中控件的区域。

小菜单

截图效果

编程思路:

1.动态找到鼠标所在区域的矩形,肯定是要获得桌面上每个窗口以及其子控件的大小位置属性。

想获得这些属性Qt貌似没有提供相关的API,只能用windows的API  EnumWindows 和 EnumChildWindows枚举出所有的窗口的位置坐标和大小属性保存在 一个vector中。

2.有了位置和大小(保存在一个Rect中就行了)就好办了。重写Qt的鼠标移动事件,自己定义了一个结构体

  1. struct MyRect
  2. {
  3. QRect myRect_;  //矩形
  4. int distance;   //鼠标当前点到 所有边的距离之和,用于比较
  5. };

每当鼠标移动就把每个包含鼠标当前点的矩形保存到myRect_中并且计算他的大小distance。

然后找到最小的distance对应的矩形。这个就是上图我们要显示的矩形了。

3.该怎么处理??Qt你们都晓得把。

我是通过QPixmap类的grabWindow 获得整个屏幕,然后 组合绘图 变色整个屏幕。

当鼠标移动到某个区域时 把这个区域 清晰显示。即上图效果。

4.保存图片QPixmap的save即可。

说了这么多了上代码把。

CPP。

  1. #include "imagewidget.h"
  2. #include <QPainter>
  3. #include <QColor>
  4. #include <QMessageBox>
  5. #include <QByteArray>
  6. #include <QBuffer>
  7. #include <QPainter>
  8. #include <QDesktopWidget>
  9. #include <QPen>
  10. #include <Windows.h>
  11. #include <vector>
  12. std::vector<QRect> allWindowRect;     //用于存储所有的窗口
  13. std::vector<HWND> allWindowHwnd;      //用于存储所有的窗口句柄
  14. std::vector<MyRect> myRectRestlt;     // 找到所有包含 鼠标当前移动点的矩形,并保存其到各边的距离之和。
  15. //声明回调函数
  16. bool CALLBACK MyEnumWindowsProc(HWND hwnd,LPARAM lParam);
  17. ImageWidget::ImageWidget(QWidget *parent)
  18. : QWidget(parent)
  19. {
  20. ui.setupUi(this);
  21. //用于获取窗口大小
  22. QDesktopWidget *dtw = QApplication::desktop();
  23. //获得 整个屏幕
  24. pixmap_ = pixmap_.grabWindow(QApplication::desktop()->winId(),0,0,dtw->width(),dtw->height());
  25. isPressed = false;
  26. isDragging = false;
  27. captureMenu_ = new CaptureMenu();
  28. //打开鼠标 跟踪
  29. setMouseTracking(true);
  30. //关联 用于保存文件名
  31. connect(captureMenu_,SIGNAL(toSaveFile(QString)),this,SLOT(slotGetFileName(QString)));
  32. //遍历窗口 获得各个窗口的大小
  33. ::EnumWindows((WNDENUMPROC)MyEnumWindowsProc,0);
  34. }
  35. ImageWidget::~ImageWidget()
  36. {
  37. }
  38. void ImageWidget::paintEvent(QPaintEvent *event)
  39. {
  40. QPainter painter(this);
  41. pixmap_ = pixmap_.scaled(width(),height(),Qt::KeepAspectRatio);
  42. //pixmap_没有 alpha通道 添加通道
  43. QPixmap temp(pixmap_.size());
  44. temp.fill(Qt::transparent);
  45. QPainter p(&temp);
  46. p.setCompositionMode(QPainter::CompositionMode_Source);
  47. p.drawPixmap(0, 0, pixmap_);
  48. p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
  49. p.fillRect(temp.rect(), QColor(50, 50, 50, 100)); //把图片调 暗 以显示截图全屏
  50. //  pixmap_ = temp;
  51. //水印????
  52. painter.drawPixmap(0,0,temp);
  53. QPen penWather;
  54. penWather.setWidth(10);
  55. penWather.setBrush(QColor(125,125,125,125));
  56. painter.setPen(penWather);
  57. QString tempStr;
  58. tempStr = QString(tr("开始按钮X:%1 Y:%2 移动中的X:%3 Y:%4")).arg(pStart_.x()).arg(pStart_.y()).arg(pMove_.x()).arg(pMove_.y());
  59. painter.drawText(100,100,tempStr);
  60. //显示 截图拖动的区域
  61. QPen pen;
  62. pen.setWidth(5);
  63. pen.setColor(QColor(0,255,255,127));
  64. painter.setPen(pen);
  65. if (isDragging)
  66. {
  67. painter.drawPixmap(pStart_.x(),pStart_.y(),pixmap_,pStart_.x(),pStart_.y(),pMove_.x()-pStart_.x(),pMove_.y()-pStart_.y());
  68. painter.drawRect(pStart_.x()-2,pStart_.y()-2,pMove_.x()-pStart_.x()-2,pMove_.y()-pStart_.y()-2);
  69. }
  70. else
  71. {
  72. painter.drawPixmap(miniRect.myRect_.left(),miniRect.myRect_.top(),pixmap_,miniRect.myRect_.left(),miniRect.myRect_.top(),miniRect.myRect_.width(),miniRect.myRect_.height());
  73. painter.drawRect(miniRect.myRect_.left()-2, miniRect.myRect_.top()-2, miniRect.myRect_.width()-2, miniRect.myRect_.height()-2);
  74. }
  75. }
  76. void ImageWidget::mousePressEvent(QMouseEvent *event)
  77. {
  78. pStart_.setX(event->x());
  79. pStart_.setY(event->y());
  80. isPressed = true;
  81. }
  82. void ImageWidget::mouseMoveEvent(QMouseEvent *event)
  83. {
  84. if (isPressed)      //如果按下 鼠标 开始 区域截图
  85. {
  86. isDragging = true;
  87. pMove_.setX(event->x());
  88. pMove_.setY(event->y());
  89. }
  90. else            //如果没有按下鼠标 开始自动寻找合适窗口  //、应该改为 找到距离最近的 矩形块 。。。!!!!!!
  91. {
  92. //每次移动都清空
  93. myRectRestlt.clear();
  94. for (std::vector<QRect>::iterator it = allWindowRect.begin()+1;it != allWindowRect.end();it++)
  95. {
  96. if (it->contains(event->x(),event->y()))
  97. {
  98. calculateRectDistance(*it);
  99. }
  100. }
  101. MyRect tempMinRect;
  102. for(std::vector<MyRect>::iterator it = myRectRestlt.begin();it != myRectRestlt.end();it++)
  103. {
  104. if (it->distance < tempMinRect.distance)  //找到最小的矩形
  105. {
  106. tempMinRect = *it;      //
  107. }
  108. }
  109. miniRect = tempMinRect;
  110. }
  111. update();
  112. }
  113. void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
  114. {
  115. //记录 结束点
  116. if (isDragging)
  117. {
  118. pEnd_.setX(event->x());
  119. pEnd_.setY(event->y());
  120. }
  121. else
  122. {
  123. pStart_.setX(miniRect.myRect_.left());
  124. pStart_.setY(miniRect.myRect_.top());
  125. pEnd_.setX(miniRect.myRect_.right());
  126. pEnd_.setY(miniRect.myRect_.bottom());
  127. }
  128. isPressed = false;
  129. //isDragging = false;
  130. //新建菜单窗口
  131. captureMenu_->move(event->x()-152,event->y());
  132. captureMenu_->setWindowFlags(Qt::FramelessWindowHint);
  133. captureMenu_->exec();
  134. //退出窗口
  135. close();
  136. //发射 信号给截图软件窗口 可以显示
  137. emit beVisible();
  138. }
  139. //回调函数
  140. bool CALLBACK MyEnumWindowsProc(HWND hwnd,LPARAM lParam)
  141. {
  142. if (::IsWindow(hwnd) && ::IsWindowVisible(hwnd))
  143. {
  144. RECT tempRect;
  145. QRect tempQRect;
  146. ::GetWindowRect(hwnd,&tempRect);
  147. tempQRect.setTopLeft(QPoint(tempRect.left,tempRect.top));
  148. tempQRect.setBottomRight(QPoint(tempRect.right,tempRect.bottom));
  149. allWindowRect.push_back(tempQRect);
  150. allWindowHwnd.push_back(hwnd);
  151. ::EnumChildWindows(hwnd,(WNDENUMPROC)MyEnumWindowsProc,0);
  152. }
  153. return true;
  154. }
  155. void ImageWidget::slotGetFileName(QString filename)
  156. {
  157. pixmapSave_ = pixmap_.copy(pStart_.x(),pStart_.y(),pEnd_.x()-pStart_.x(),pEnd_.y()-pStart_.y());
  158. //保存截图
  159. QByteArray bytes;//用于存放2进制数据
  160. QBuffer buffer(&bytes); //设置缓存
  161. buffer.open(QIODevice::ReadOnly);
  162. pixmapSave_.save(filename,"PNG",1);
  163. }
  164. void ImageWidget::calculateRectDistance(QRect rect)
  165. {
  166. int dis = rect.width() + rect.height();
  167. MyRect tempMyRect;
  168. tempMyRect.myRect_ = rect;
  169. tempMyRect.distance = dis;
  170. //添加进入
  171. myRectRestlt.push_back(tempMyRect);
  172. }

。H

  1. #ifndef IMAGEWIDGET_H
  2. #define IMAGEWIDGET_H
  3. #include <QWidget>
  4. #include "ui_imagewidget.h"
  5. #include <QPixmap>
  6. #include <QPoint>
  7. #include <QMouseEvent>
  8. #include <capturemenu.h>
  9. #include <QRect>
  10. struct MyRect
  11. {
  12. QRect myRect_;  //矩形
  13. int distance;   //鼠标当前点到 所有边的距离之和,用于比较
  14. };
  15. class ImageWidget : public QWidget
  16. {
  17. Q_OBJECT
  18. public:
  19. ImageWidget(QWidget *parent = 0);
  20. ~ImageWidget();
  21. void paintEvent(QPaintEvent *event);
  22. //重写 鼠标按下 事件,记录截图起始点
  23. void mousePressEvent(QMouseEvent *event);
  24. //重写 鼠标松下 事件,记录截图结束点
  25. void mouseReleaseEvent(QMouseEvent *event);
  26. //重写 鼠标移动 事件,当拉动截图区域时 改变截图区域为正常图片(非蒙尘)
  27. void mouseMoveEvent(QMouseEvent *event);
  28. //用于计算 鼠标当前点到各个边的距离之和
  29. void calculateRectDistance(QRect rect);
  30. private:
  31. Ui::ImageWidget ui;
  32. QPixmap pixmap_;    //用于显示 截的整个屏幕
  33. QPixmap pixmapSave_; //用于 保存截图
  34. QPoint pStart_; //记录开始截图位置
  35. QPoint pEnd_;   //记录结束截图位置
  36. QPoint pMove_;  //记录移动中的坐标
  37. bool isPressed; //是否按下按钮
  38. bool isDragging;    //是否用户拖选
  39. MyRect miniRect;    //最小矩形
  40. CaptureMenu *captureMenu_;  //截图结束时的菜单
  41. QString fullPath;   //保存文件名以及 路径
  42. public slots:
  43. void slotGetFileName(QString filename);
  44. signals:
  45. void beVisible();  //给 截图软件发射可见 信号
  46. };
  47. #endif // IMAGEWIDGET_H

贴了2个最重要的文件。

应届生刚入职在实习,公司让学Qt,学了半个月,代码写的不好的地方或者大家有更好的做法希望大家多多指教,注释很详细。

下载:http://download.csdn.net/detail/kfbyj/6713861

https://blog.csdn.net/kfbyj/article/details/8811010

Qt 模仿QQ截图 动态吸附直线的更多相关文章

  1. 模仿QQ截图片

    原文:模仿QQ截图片 两个picturebox,一个放图片 完整代码如下 using System; using System.Collections.Generic; using System.Co ...

  2. Qt 之 模仿 QQ登陆界面——样式篇

    一.简述 今天晚上花了半天时间从QQ登录界面抠了些图,顺便加了点样式基本上实现了QQ的登陆界面全部效果.虽不说100%相似,那也有99.99%相似了哈O(∩_∩)O. QQ好像从去年开始,登录界面有了 ...

  3. Android:仿手机QQ朋友动态ListView

    1.介绍: 使用此博客XListView模仿Android版本QQ朋友动态ListView效果.效果如下面的截图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZ ...

  4. Android:仿手机QQ好友动态的ListView

    1.介绍: 本博客使用XListView模仿Android版QQ好友动态的ListView效果.效果截图例如以下: 效果图1 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  5. Android 模仿QQ空间风格的 UI(转)

    本文内容 环境 演示模仿QQ空间风格的UI 虽然这个 UI 跟现在的QQ空间有点差别,但是也能学到很多东西. 下载 Demo 环境 Windows 7 64 位 Eclipse ADT V22.6.2 ...

  6. Android 模仿QQ空间风格的 UI

    本文内容 环境 演示模仿QQ空间风格的UI 虽然这个 UI 跟现在的QQ空间有点差别,但是也能学到很多东西. 下载 Demo 环境 Windows 7 64 位 Eclipse ADT V22.6.2 ...

  7. iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)

    代码地址如下:http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该怎 ...

  8. QQ空间动态爬虫

    作者:虚静 链接:https://zhuanlan.zhihu.com/p/24656161 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 先说明几件事: 题目的意 ...

  9. [Surface] 在win8.1上使用QQ截图放大问题(解决办法)

    在使用每次截图的时候整个都被放大了,很让人郁闷,截不到完整的图,本着遇到问题解决问题的想法,这事早解决早好.   开工: 1. 度娘上搜索"win8 qq截图 放大",找到很多资料 ...

随机推荐

  1. RFID的工作流程

    工作流程 1.阅读器通过发射天线发送一定频率的射频信号, 2.当射频卡进入发射天线工作区域时产生感应电流,射频卡获得能量被激活: 3.射频卡将自身编码等信息通过卡内置发送天线发送出去 4.系统接收天线 ...

  2. 洛谷——P1056 排座椅

    https://www.luogu.org/problem/show?pid=1056#sub 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主 ...

  3. 洛谷 P1893 山峰暸望

    P1893 山峰暸望 题目描述 一天,Bessie在眺望美丽的威斯康星的群山的时候,她突然产生了疑问:那座山是最宽的? 她决定在地平线上,利用她的新式大量程山峰高度测量仪依次做N (1 <= N ...

  4. 洛谷 P1109 学生分组

    P1109 学生分组 题目描述 有N组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界R和下界L(L<=R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使 ...

  5. [Ramda] Simple log function for debugging Compose function / Using R.tap for logging

    const log = function(x){ console.log(x); return x; } const get = R.curry(function(prop, obj){ return ...

  6. Eclipse中开发环境也想把Tomcat 的默认BIO模式改为NIO模式

    1.1 问题 有时候,开发环境我们也想把Tomcat 的默认BIO模式改为NIO模式,该如何改呢? 1.2 方案 通过eclipse里面的server.xml进行修改. 1.3 步骤 首先我们来一起看 ...

  7. MySql开发之函数

    1,在mySql常见的文本函数中常见的文本函数例如以下表所看到的: 2,数字函数例如以下: 3,日期和时间函数: 4,格式化日期和时间 使用的函数例如以下DATE_FORMAT()和TIME_FORM ...

  8. chmod用数字来表示权限的方法

    前提:  mode权限设定字串.格式:[ugoa...][[+-=][rwxX]...][,...] 当中u表示拥有者(user).g表示与拥有者属于同一个群体(group),o表示其它以外的人(ot ...

  9. C#利用反射机制,获取实例的属性和属性值

    C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值 对应某个类的实例化的对象tc, 遍历获取所有属性(子成员)的方法(采用反射): Type t = tc.GetType();// ...

  10. iOS_01_什么是ios

    * ios是一款由苹果公司开发的操作系统(os是Operating Systen的简称),就像平时在电脑上用的Window XP.Window 7.都是操作系统. * 那什么是操作系统呢?操作系统其实 ...