最近在學Qt。學東西怎么能不動手。
就寫了些小程序。看QQ截圖能夠動態吸附直線的功能挺有意思,所以就模仿了一個。
先上效果圖
界面很簡單。。呵呵
移動鼠標,會把鼠標所在最小矩形選中。把沒有選中的地方給模糊化,以示我們選中的區域很清楚。
還可以選中窗口中控件的區域。
小菜單
截圖效果
編程思路:
1.動態找到鼠標所在區域的矩形,肯定是要獲得桌面上每個窗口以及其子控件的大小位置屬性。
想獲得這些屬性Qt貌似沒有提供相關的API,只能用windows的API EnumWindows 和 EnumChildWindows枚舉出所有的窗口的位置坐標和大小屬性保存在 一個vector中。
2.有了位置和大小(保存在一個Rect中就行了)就好辦了。重寫Qt的鼠標移動事件,自己定義了一個結構體
- struct MyRect
- {
- QRect myRect_; //矩形
- int distance; //鼠標當前點到 所有邊的距離之和,用於比較
- };
每當鼠標移動就把每個包含鼠標當前點的矩形保存到myRect_中並且計算他的大小distance。
然后找到最小的distance對應的矩形。這個就是上圖我們要顯示的矩形了。
3.該怎么處理??Qt你們都曉得把。
我是通過QPixmap類的grabWindow 獲得整個屏幕,然后 組合繪圖 變色整個屏幕。
當鼠標移動到某個區域時 把這個區域 清晰顯示。即上圖效果。
4.保存圖片QPixmap的save即可。
說了這么多了上代碼把。
CPP。
- #include "imagewidget.h"
- #include <QPainter>
- #include <QColor>
- #include <QMessageBox>
- #include <QByteArray>
- #include <QBuffer>
- #include <QPainter>
- #include <QDesktopWidget>
- #include <QPen>
- #include <Windows.h>
- #include <vector>
- std::vector<QRect> allWindowRect; //用於存儲所有的窗口
- std::vector<HWND> allWindowHwnd; //用於存儲所有的窗口句柄
- std::vector<MyRect> myRectRestlt; // 找到所有包含 鼠標當前移動點的矩形,並保存其到各邊的距離之和。
- //聲明回調函數
- bool CALLBACK MyEnumWindowsProc(HWND hwnd,LPARAM lParam);
- ImageWidget::ImageWidget(QWidget *parent)
- : QWidget(parent)
- {
- ui.setupUi(this);
- //用於獲取窗口大小
- QDesktopWidget *dtw = QApplication::desktop();
- //獲得 整個屏幕
- pixmap_ = pixmap_.grabWindow(QApplication::desktop()->winId(),0,0,dtw->width(),dtw->height());
- isPressed = false;
- isDragging = false;
- captureMenu_ = new CaptureMenu();
- //打開鼠標 跟蹤
- setMouseTracking(true);
- //關聯 用於保存文件名
- connect(captureMenu_,SIGNAL(toSaveFile(QString)),this,SLOT(slotGetFileName(QString)));
- //遍歷窗口 獲得各個窗口的大小
- ::EnumWindows((WNDENUMPROC)MyEnumWindowsProc,0);
- }
- ImageWidget::~ImageWidget()
- {
- }
- void ImageWidget::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- pixmap_ = pixmap_.scaled(width(),height(),Qt::KeepAspectRatio);
- //pixmap_沒有 alpha通道 添加通道
- QPixmap temp(pixmap_.size());
- temp.fill(Qt::transparent);
- QPainter p(&temp);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.drawPixmap(0, 0, pixmap_);
- p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
- p.fillRect(temp.rect(), QColor(50, 50, 50, 100)); //把圖片調 暗 以顯示截圖全屏
- // pixmap_ = temp;
- //水印????
- painter.drawPixmap(0,0,temp);
- QPen penWather;
- penWather.setWidth(10);
- penWather.setBrush(QColor(125,125,125,125));
- painter.setPen(penWather);
- QString tempStr;
- tempStr = QString(tr("開始按鈕X:%1 Y:%2 移動中的X:%3 Y:%4")).arg(pStart_.x()).arg(pStart_.y()).arg(pMove_.x()).arg(pMove_.y());
- painter.drawText(100,100,tempStr);
- //顯示 截圖拖動的區域
- QPen pen;
- pen.setWidth(5);
- pen.setColor(QColor(0,255,255,127));
- painter.setPen(pen);
- if (isDragging)
- {
- painter.drawPixmap(pStart_.x(),pStart_.y(),pixmap_,pStart_.x(),pStart_.y(),pMove_.x()-pStart_.x(),pMove_.y()-pStart_.y());
- painter.drawRect(pStart_.x()-2,pStart_.y()-2,pMove_.x()-pStart_.x()-2,pMove_.y()-pStart_.y()-2);
- }
- else
- {
- painter.drawPixmap(miniRect.myRect_.left(),miniRect.myRect_.top(),pixmap_,miniRect.myRect_.left(),miniRect.myRect_.top(),miniRect.myRect_.width(),miniRect.myRect_.height());
- painter.drawRect(miniRect.myRect_.left()-2, miniRect.myRect_.top()-2, miniRect.myRect_.width()-2, miniRect.myRect_.height()-2);
- }
- }
- void ImageWidget::mousePressEvent(QMouseEvent *event)
- {
- pStart_.setX(event->x());
- pStart_.setY(event->y());
- isPressed = true;
- }
- void ImageWidget::mouseMoveEvent(QMouseEvent *event)
- {
- if (isPressed) //如果按下 鼠標 開始 區域截圖
- {
- isDragging = true;
- pMove_.setX(event->x());
- pMove_.setY(event->y());
- }
- else //如果沒有按下鼠標 開始自動尋找合適窗口 //、應該改為 找到距離最近的 矩形塊 。。。!!!!!!
- {
- //每次移動都清空
- myRectRestlt.clear();
- for (std::vector<QRect>::iterator it = allWindowRect.begin()+1;it != allWindowRect.end();it++)
- {
- if (it->contains(event->x(),event->y()))
- {
- calculateRectDistance(*it);
- }
- }
- MyRect tempMinRect;
- for(std::vector<MyRect>::iterator it = myRectRestlt.begin();it != myRectRestlt.end();it++)
- {
- if (it->distance < tempMinRect.distance) //找到最小的矩形
- {
- tempMinRect = *it; //
- }
- }
- miniRect = tempMinRect;
- }
- update();
- }
- void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
- {
- //記錄 結束點
- if (isDragging)
- {
- pEnd_.setX(event->x());
- pEnd_.setY(event->y());
- }
- else
- {
- pStart_.setX(miniRect.myRect_.left());
- pStart_.setY(miniRect.myRect_.top());
- pEnd_.setX(miniRect.myRect_.right());
- pEnd_.setY(miniRect.myRect_.bottom());
- }
- isPressed = false;
- //isDragging = false;
- //新建菜單窗口
- captureMenu_->move(event->x()-152,event->y());
- captureMenu_->setWindowFlags(Qt::FramelessWindowHint);
- captureMenu_->exec();
- //退出窗口
- close();
- //發射 信號給截圖軟件窗口 可以顯示
- emit beVisible();
- }
- //回調函數
- bool CALLBACK MyEnumWindowsProc(HWND hwnd,LPARAM lParam)
- {
- if (::IsWindow(hwnd) && ::IsWindowVisible(hwnd))
- {
- RECT tempRect;
- QRect tempQRect;
- ::GetWindowRect(hwnd,&tempRect);
- tempQRect.setTopLeft(QPoint(tempRect.left,tempRect.top));
- tempQRect.setBottomRight(QPoint(tempRect.right,tempRect.bottom));
- allWindowRect.push_back(tempQRect);
- allWindowHwnd.push_back(hwnd);
- ::EnumChildWindows(hwnd,(WNDENUMPROC)MyEnumWindowsProc,0);
- }
- return true;
- }
- void ImageWidget::slotGetFileName(QString filename)
- {
- pixmapSave_ = pixmap_.copy(pStart_.x(),pStart_.y(),pEnd_.x()-pStart_.x(),pEnd_.y()-pStart_.y());
- //保存截圖
- QByteArray bytes;//用於存放2進制數據
- QBuffer buffer(&bytes); //設置緩存
- buffer.open(QIODevice::ReadOnly);
- pixmapSave_.save(filename,"PNG",1);
- }
- void ImageWidget::calculateRectDistance(QRect rect)
- {
- int dis = rect.width() + rect.height();
- MyRect tempMyRect;
- tempMyRect.myRect_ = rect;
- tempMyRect.distance = dis;
- //添加進入
- myRectRestlt.push_back(tempMyRect);
- }
。H
- #ifndef IMAGEWIDGET_H
- #define IMAGEWIDGET_H
- #include <QWidget>
- #include "ui_imagewidget.h"
- #include <QPixmap>
- #include <QPoint>
- #include <QMouseEvent>
- #include <capturemenu.h>
- #include <QRect>
- struct MyRect
- {
- QRect myRect_; //矩形
- int distance; //鼠標當前點到 所有邊的距離之和,用於比較
- };
- class ImageWidget : public QWidget
- {
- Q_OBJECT
- public:
- ImageWidget(QWidget *parent = 0);
- ~ImageWidget();
- void paintEvent(QPaintEvent *event);
- //重寫 鼠標按下 事件,記錄截圖起始點
- void mousePressEvent(QMouseEvent *event);
- //重寫 鼠標松下 事件,記錄截圖結束點
- void mouseReleaseEvent(QMouseEvent *event);
- //重寫 鼠標移動 事件,當拉動截圖區域時 改變截圖區域為正常圖片(非蒙塵)
- void mouseMoveEvent(QMouseEvent *event);
- //用於計算 鼠標當前點到各個邊的距離之和
- void calculateRectDistance(QRect rect);
- private:
- Ui::ImageWidget ui;
- QPixmap pixmap_; //用於顯示 截的整個屏幕
- QPixmap pixmapSave_; //用於 保存截圖
- QPoint pStart_; //記錄開始截圖位置
- QPoint pEnd_; //記錄結束截圖位置
- QPoint pMove_; //記錄移動中的坐標
- bool isPressed; //是否按下按鈕
- bool isDragging; //是否用戶拖選
- MyRect miniRect; //最小矩形
- CaptureMenu *captureMenu_; //截圖結束時的菜單
- QString fullPath; //保存文件名以及 路徑
- public slots:
- void slotGetFileName(QString filename);
- signals:
- void beVisible(); //給 截圖軟件發射可見 信號
- };
- #endif // IMAGEWIDGET_H
貼了2個最重要的文件。
應屆生剛入職在實習,公司讓學Qt,學了半個月,代碼寫的不好的地方或者大家有更好的做法希望大家多多指教,注釋很詳細。
下載:http://download.csdn.net/detail/kfbyj/6713861
https://blog.csdn.net/kfbyj/article/details/8811010