最近发现好多次打开QQ仅仅想用它来截屏 ⊙﹏⊙b汗
不如自己来写一个截屏工具,集成到自己的小工具箱里面
动手之前考虑一下要怎么实现,我考虑过的方案大概有下面两种 :
1. 监控全局鼠标事件 (真是“初生牛犊不怕虎“ ~~o(>_<)o ~~ )。
2. 将窗口设置为屏幕大小(去掉标题栏),设置窗口背景透明(这个时候窗口不就是我们的屏幕了么哈哈),然后用mouseEvent来获取鼠标事件(连全局鼠标监控都省了)。
最终栽在了背景透明的实现上。(透明后窗口是黑的)
最后受到第二种方法启发,想到一种简单的方法:先截取全屏,将窗口设置为屏幕大小(去掉标题栏),将窗口背景设置为刚才截取的图片,然后在上面用用mouseEvent来获取鼠标事件,完成截屏。
头文件 SreenShoot.h
1 | #ifndef SCREENSHOOT_H #define SCREENSHOOT_H #include <QWidget> #include <QRubberBand> // 用于创建一个橡皮筋选框 #include <QLabel> // 动态显示截图区域尺寸 #include <QDateTime> // 用当前系统时间动态生成截图的文件名 #include <QScreen> // 用来截取全屏 #include <QDesktopWidget> // 用于获取屏幕尺寸 #include <QApplication> #include <QPalette> // 对话框的调色板,用于将图片设置为窗体背景 #include <QMouseEvent> // 重载用于获取鼠标事件 #include <QString> // 配合上面的<QDateTime> 用于存储文件名 #include <windows.h> // 调用win32API #include <QImage> // 用于储存图片对象 #include <QDir> // 用于获取当前程序目录,得到截图的路径 #include <QDesktopServices> //配合 <QDir> 用系统浏览器打开图片 #include <QFile> // 删除文件 class ScreenShoot : public QWidget { Q_OBJECT public: static ScreenShoot* Instance() { if(!instance) instance = new ScreenShoot(); return instance; } void mouseMoveEvent(QMouseEvent *e); // 处理鼠标移动 void mousePressEvent(QMouseEvent *e); // 处理鼠标按下 void mouseReleaseEvent(QMouseEvent *e); // 处理鼠标释放 void setbackground(int width,int height); // 初始化程序背景 void grabScreen(); // 根据选取截屏,保存并打开图片 void setLabel(); // 动态显示截图区域尺寸 void keyPressEvent(QKeyEvent *e); // 处理esc取消按键 ~ScreenShoot(); void show(); // 重写 show() 每次显示都重新渲染窗体背景 单例需要 private: QRubberBand* g_rubber; QPoint origin; // 记录鼠标按下坐标 QPoint end; // 记录鼠标释放坐标 QLabel* label; // 显示截图区域尺寸 QImage* bg; // 记录全屏图片 int g_width; // 屏幕宽度 int g_height; // 屏幕高度 static ScreenShoot* instance; ScreenShoot(); }; #endif // SCREENSHOOT_H |
来自CODE的代码片
ScreenShoot.h
源文件 SreenShoot.cpp
1 | #include <ScreenShoot.h> ScreenShoot* ScreenShoot::instance = 0; ScreenShoot::ScreenShoot() { // 获取屏幕尺寸 QDesktopWidget* desktopWidget = QApplication::desktop(); QRect deskRect = desktopWidget->screenGeometry(); // 将窗体设置为屏幕尺寸,去掉标题栏 g_width = deskRect.width(); g_height = deskRect.height(); this ->resize(g_width,g_height); // 调用setbackground() 设置背景 setbackground(deskRect.width(),deskRect.height()); //初始化变量 g_rubber = NULL; origin = end = QPoint(0,0); //截图标签 label = new QLabel(""); label->setWindowFlags(Qt::FramelessWindowHint); this ->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); } ScreenShoot::~ScreenShoot() { } void ScreenShoot::mousePressEvent(QMouseEvent *e) { if(!g_rubber) { g_rubber = new QRubberBand(QRubberBand::Rectangle,this); } // 将橡皮框设置可见 g_rubber->show(); // 记录点击位置 origin = e->pos(); // 设置橡皮框选区 g_rubber->setGeometry(origin.x(),origin.y(),0,0); } void ScreenShoot::mouseMoveEvent(QMouseEvent *e) { if(g_rubber) { // 记录终点 end = e->pos(); //调整要显示的区域 int w = abs(end.x() - origin.x()); int h = abs(end.y() - origin.y()); int x = origin.x() < end.x() ? origin.x() : end.x(); int y = origin.y() < end.y() ? origin.y() : end.y(); g_rubber->setGeometry(x,y,w,h); // 动态显示选区大小 setLabel(); } } void ScreenShoot::mouseReleaseEvent(QMouseEvent *e) { if(g_rubber) { // 记录终点 end = e ->pos(); g_rubber->hide(); // 截屏 grabScreen(); // 截屏后关闭程序和标签栏 label->close(); // 如果使用close(),当主窗口隐藏时,主窗口也会close(),如果你需要将他作为一个模块,使用hide而不是close this ->close(); } } void ScreenShoot::grabScreen() { // 调整要截取的区域 int wid = abs(origin.x() - end.x()); int height = abs(origin.y() - end.y()); int x = origin.x() < end.x() ? origin.x() : end.x(); int y = origin.y() < end.y() ? origin.y() : end.y(); //构造文件名 QDateTime time = QDateTime::currentDateTime(); QString str = time.toString("yyyyMMddhhmmss"); QString picName = str + ".bmp"; // 对全屏背景进行截图 QImage pic = bg->copy(x,y,wid,height); pic.save(picName); // 获取程序当前路径,打片截图 QString path; QDir dir; path=dir.currentPath(); QString picPath = "file:///" + path + "/" + picName; QDesktopServices::openUrl(QUrl(picPath)); //删除背景图 QFile::remove("bg.bmp"); } void ScreenShoot::setLabel() { // 调整标签显示位置 int wid = abs(origin.x() - end.x()); int height = abs(origin.y() - end.y()); int x = origin.x() < end.x() ? origin.x() : end.x(); int y = origin.y() < end.y() ? origin.y() : end.y(); // 设置标签显示内容 QString str = QString(" %1 x %2 ").arg(wid).arg(height); label->setText(str); // 设置标签位置 QRect rect(label->contentsRect()); label->move(QPoint(x,y - rect.height())); label->show(); } void ScreenShoot::keyPressEvent(QKeyEvent *e) { // 如果按下ESC键,关闭程序 if(e->key() == Qt::Key_Escape) { label->close(); // 如果使用close(),当主窗口隐藏时,主窗口也会close(),如果你需要将他作为一个模块,使用hide而不是close this ->close(); QFile::remove("bg.bmp"); } } void ScreenShoot::setbackground(int width,int height) { //截取当前屏幕 QScreen *screen = QGuiApplication::primaryScreen(); screen->grabWindow(0).save("bg.bmp","bmp"); //读取背景图,等比例缩放RGB值,使背景变暗,进入截图模式 int red,green,blue; bg = new QImage("bg.bmp"); QImage bg_blend(width,height,QImage::Format_RGB32); for(int x = 0; x < width; x++) { for(int y = 0; y < height; y++) { red = qRed(bg->pixel(x,y)) * 0.6 ; green = qGreen(bg->pixel(x,y)) * 0.6; blue = qBlue(bg->pixel(x,y)) * 0.6; bg_blend.setPixel( x, y, qRgb( red, green, blue ) ); } } // 将图片设置为背景 QPalette palette; palette.setBrush(this->backgroundRole(),QBrush(bg_blend)); this->setPalette(palette); } void ScreenShoot::show() { QWidget::show(); setbackground(g_width,g_height); } |
来自CODE的代码片
ScreenShoot.cpp
main函数