最近在学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. asp.net Code学习二(使用vs 2015 update 3)

    1.在vs 2015上搭建asp.net core:  安装 .Net core sdk.vs2015 tool 即可使用vs 2015开发asp.net core. 2.Net core中国学习小组 ...

  2. 找不到或无法载入主类 org.jivesoftware.openfire.starter.ServerStarter

    刚接触openfire的配置就出现了这个错误.解决方法非常easy,忘记了将openfire的源文件加入到user entries中了

  3. shell实例浅谈之三产生随机数七种方法

    一.问题 Shell下有时须要使用随机数,在此总结产生随机数的方法.计算机产生的的仅仅是"伪随机数".不会产生绝对的随机数(是一种理想随机数).伪随机数在大量重现时也并不一定保持唯 ...

  4. Nginx分发服务

    nginx配置分发tomcat服务 http://blog.csdn.net/yan_chou/article/details/53265775 http://www.cnblogs.com/deng ...

  5. Zookeeper源码用ant进行编译为eclipse工程--转载

    原文地址:http://www.it165.net/os/html/201411/10142.html Zookeeper GitHub的下载地址是:https://github.com/apache ...

  6. jqgrid 实现行编辑,表单编辑的列联动

    这个问题的场景相信大家都遇到过,比方有A,B,C三列,B,C列均为下拉框.可是C列的值是由B列的值来决定的.即C列中的值是动态变化的,变化的根据就是B列中你选择的值. 本文给出的是一个有用,简易快捷的 ...

  7. 利用VS安装项目打包软件的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 昨天摸索了一下,发现使用VS安装项目来打包软件还是挺方便的. 1. 创建一个安装项目工程,如下图: 2. 设置工程属性 ...

  8. ZOJ 1796 Euchre Results 数学水题

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1796 题意: 四个人玩游戏,已知三个人的输赢情况,求第四个人的输赢情况. ...

  9. 机器学习算法笔记1_2:分类和逻辑回归(Classification and Logistic regression)

    形式: 採用sigmoid函数: g(z)=11+e−z 其导数为g′(z)=(1−g(z))g(z) 如果: 即: 若有m个样本,则似然函数形式是: 对数形式: 採用梯度上升法求其最大值 求导: 更 ...

  10. 调试 之gdb thread命令 与 ltrace/strace

    我们可以通过  1)  gdb prog_name -> r               用在逐步调试自己的程序时 2)  gdb -> attach process_id       正 ...