• 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

  • 相关阅读:
    python中matplotlib所绘制的图包含了很多的对象
    pd.concat()命令
    Java设计模式——外观模式
    Java设计模式——桥接模式
    Java基础面试
    java web解决表单重复提交
    Servlet 工作原理解析
    Mysql日期函数
    解决多个下拉框动态级联初始化问题
    window.parent与window.opener、window.showModalDialog的区别 opener和showModalDialog刷新父页面的方法
  • 原文地址:https://www.cnblogs.com/findumars/p/8627626.html
Copyright © 2020-2023  润新知