Qt 模仿QQ截图 动态吸附直线

Posted 朝闻道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt 模仿QQ截图 动态吸附直线相关的知识,希望对你有一定的参考价值。

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

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

先上效果图

界面很简单。。呵呵

技术分享图片

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

技术分享图片

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

技术分享图片

小菜单

技术分享图片

截图效果

技术分享图片

编程思路:

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

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

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

 

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

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

 

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

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

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

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

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

 

说了这么多了上代码把。

CPP。

 

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


。H

 

 

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


贴了2个最重要的文件。

 

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

 

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

 

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

以上是关于Qt 模仿QQ截图 动态吸附直线的主要内容,如果未能解决你的问题,请参考以下文章

Qt5.10实现QQ截图工具功能代码源码分析

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

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

Qt学习笔记-设计简易的截图工具软件

Qt写的截图软件包含源代码和可执行程序

gif格式的图片怎么截图