Qt写一个截屏工具(窗口透明)
最近发现好多次打开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的代码片
源文件 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的代码片
Qt写一个截屏工具(窗口透明)的更多相关文章
- Java开发的一个简单截屏工具
//源代码 import java.awt.*;import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transfe ...
- Gif截屏工具 - GifCam
如果你需要录制截屏并保存成gif图片格式,那么你一定不能错过GifCam这个神奇的小工具.它虽然只有600K,但功能不可小觑. GifCam (Gif相机) 是一款免费且非常优秀的视频录制/剪辑的GI ...
- 截屏工具 HyperSnap
听说Tencent开发了1款截屏工具,叫"snip".确实字体效果不错,但是丫只有for mac的,不知道脑子里怎么想的,该不是直接买了第三方的然后冠了个名儿吧. 那么Windows有没有类似的工具呢 ...
- Java 截屏工具类
PrintScreenUtils.java package javax.utils; import java.awt.AWTException; import java.awt.Dimension; ...
- 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具
用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具 前言 上周,同事抱怨说 react 怎么不能像 angular 那样,使用命令行工具来生成一个组件.对呀,平时工作时,想要创建 ...
- Linux截屏工具scrot用法详细介绍
Scrot是Linux命令行中使用的截图工具,能够进行全屏.选取等操作,下面小编将针对Scrot截图工具的用法给大家做个详细介绍,通过操作实例来学习Scrot的使用. 在Linux中安装Scrot ...
- Qt编程—去掉标题栏和设置窗口透明用法
学习Qt编程,有时候我们很想做出好看又比较炫的画面,这时就常用到qt上的一些技巧. 这里我以一个小例子来展示qt的这些技巧,此qt编程写的,如图:(去掉标题栏和设置窗口透明后) 代码实现部分: .h文 ...
- Snipaste多截屏工具软件
Snipaste是一个简单的截图小工具,可以支持同时截取多张图片,添加标注等等,操作简单方便,解压即用 百度网盘链接: https://pan.baidu.com/s/1YC75DRoLzdeyli1 ...
- 动手写一个Remoting接口测试工具(附源码下载)
基于.NET开发分布式系统,经常用到Remoting技术.在测试驱动开发流行的今天,如果针对分布式系统中的每个Remoting接口的每个方法都要写详细的测试脚本,无疑非常浪费时间.所以,我想写一个能自 ...
随机推荐
- linux如何关闭selinux?
首先我们可以用命令来查看selinux的状态getenforce 这个命令可以查看到selinux的状态,当前可以看到是关闭状态的.还有一个命令也可以查看出selinux的状态.sestatus -v ...
- Noip2009提高组总结
Noip2009的题目还是有一定难度的,主要是搜索和最短路都是我的弱项,不检查第一遍下来只做了150分,还是这句话,素质和读题的仔细程度决定了分数.仔细想想,我们化学老师说的话没错,或许题目你都会做, ...
- Floodlight之 FloodlightContextStore 数据结构
FloodlightContextStore 代表的是一种缓存模型(利用的是ConcurrentHashMap).里面存储的是上下文相关的对象,可以依据对应的key得到详细的 Object. ...
- sqlite性能简单測试
主要測试sqlite在大数据量下的插入及查询性能: 測试环境:Centos6.4 1G内存 单核 数据量 大小 索引字段检索(耗时) 非索引字段检索(耗时) 总插入时间 10W 19M 0.001 ...
- sass基本语法
sass是一种基于ruby语言开发的CSS预处理器.它可以使用变量,嵌套,混入,继承,运算,函数等编程语言具有的特性进行CSS的开发,使得CSS的开发变得简单粗暴清晰可维护. sass有两种后缀文件格 ...
- ajax 基础
<html><head><script type="text/javascript">function showHint(str){var xm ...
- 关于left join 和 inner join
今天遇到一个逻辑很复杂的SQL,虽然写出来了,但是并没有完全体会,找了找资料,算是摸清楚了left join和inner join 的实际意义. 感谢PCJIM的文章,写的非常明白,原文地址:http ...
- ThinkPHP - 登录模块,核心代码
/** * 登录成功 * @return [type] [description] */ public function checkLogin($data) { $user = M($this-> ...
- JAVA虚拟机内存模型
一.对于Java程序员来说,在虚拟机的自动内存管理机制下,我们不需要为每一个new操作去写匹配的delete/free操作 但是当我们对于内存的管理了解有能够帮助我们理解Java虚拟机的垃圾回收机制. ...
- C++对C语言的非面向对象特性扩充(3)
今天要讲的是C++作用域运算符"::",强制类型转换的扩充,C++中相对于C中malloc和free函数的运算符new和delete,以及C++对C的一个重要扩充:引用(refer ...