最近在学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. [CortexM0--stm32f0308]discovery开发板

        问题描写叙述:stm32提供了很多IC入门级开发板,价格还是蛮廉价的. stm32f0308-discovery就是一款cortex-m0架构的入门级开发板. 例如以下对其进行下简介. IO便 ...

  2. ZZUACM 2015 暑假集训 round 01

    A. Encoding Problem Description Given a string containing only 'A' - 'Z', we could encode it using t ...

  3. 学习笔记(二):javascript之dom操作

    一.document.getElementById()    根据Id获取元素节点 <div id="div1"> <p id="p1"> ...

  4. Python画图参数设置

    https://blog.csdn.net/qiu931110/article/details/68130199

  5. GO语言学习(十三)Go 语言变量作用域

    Go 语言变量作用域 作用域为已声明标识符所表示的常量.类型.变量.函数或包在源代码中的作用范围. Go 语言中变量可以在三个地方声明: 函数内定义的变量称为局部变量 函数外定义的变量称为全局变量 函 ...

  6. c#下halcon配置

    1.在halcon中写入算子,实现函数过程 比如: read_image(Image,'D:/MyFile/halcon/数字识别/1.jpg') decompose3(Image, ImageR, ...

  7. oracle-function 练习

    /* *scm_iss.test_imti_fun2 *带有输入參数的Function */ CREATE OR REPLACE FUNCTION TEST_IMTI_FUN2(P_NO IN NUM ...

  8. FTP 访问的形式

    主要是扼要的列举一下访问的方式,不涉及太具体的内容.大家可以在百度上搜索一下具体的操作方法. 主要有: 1. 网页浏览器中输入 ftp://192.168.0.111的形式. 2. 资源管理器中输入f ...

  9. like小计

    1.有索引的列最好进行 ‘aa%’形式可以使用一些索引. 2.如果非得进行 ‘%aa%’这种类型查询,那这个条件不要进行主要过滤条件. 意思是这个列如果有索引就不能用索引,即使用了,索引页是进行对整个 ...

  10. Mac OS X Kernel Basic User Credentials

    User Credentials In order to understand security in OS X, it is important to understand that there a ...