Qt 简单截图工具(一) 高仿QQ截屏 滑动截屏

2023-10-30


本系列目录

Qt 简单截图工具(一) 高仿QQ截屏 滑动截屏
Qt 简单截图工具(二) 添加菜单栏,添加取色器、切图功能


# 截屏工具分析
  • 闲来无聊,在学习qt几个月后突然想制作一个截屏工具来给自己使用。简单分析了一下,认为截屏方式共可以分为三种:
  1. 获取当前窗口或控件的界面保存为图片
  2. 滑动鼠标截取当前桌面显示内容
  3. 识别鼠标指向窗口。控件或图标保存为图片

本章主要实现滑动鼠标截取当前桌面显示内容这种方式,侧重讲解大体实现,具体功能见代码

功能考虑

  • 改功能的实现主要分为三大部分:滑动鼠标截取桌面图片截图辅助功能截取部分二次处理

滑动鼠标截取当前桌面显示内容

滑动鼠标截取桌面图片

  1. 获取当前桌面显示内容为图片,此后的所有操作都是围绕这个图片进行。
QPixmap show_top_pixmap_ ;
show_top_pixmap_ = QPixmap::grabWindow(QApplication::desktop()->winId);          //当前桌面显示内容
  1. 使用画笔将桌面图片绘制到widget上,全屏显示,并绘制阴影,截取操作实际上是在该widget对象上进行,但此时效果看起来就像在原桌面上操作。
//窗口设置
this->setWindowModality(Qt::WindowModal);                                    //设置窗口模态类型:半模态,窗口级模态对话框,阻塞父窗口、父窗口的父窗口及兄弟窗口。
this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);                 //一次上下文帮助按钮
this->setWindowState(Qt::WindowActive | Qt::WindowFullScreen);               //全屏显示

//阴影色效果绘制
Qpainter *_painter;
QColor shadow_color = QColor(0, 0, 0, 100);                                  //阴影色
_painter->setPen(QPen(Qt::white, 1, Qt::SolidLine, Qt::FlatCap));            //设置画笔
_painter->drawPixmap(0, 0, show_top_pixmap_ );                               //将桌面图片绘制到窗体上
_painter->fillRect(show_top_pixmap_ .rect(), shadow_color );                 //绘制阴影色效果
  1. 鼠标按下为起始位置p1,鼠标释放为结束位置p2,以p1,p2两点绘制矩形,矩形所在区域则为截屏区域。考虑到美化可以将矩形边框去掉,在矩形八个位置绘制圆形,以便之后的截屏区域二次调整。

在这里插入图片描述
实现上述功能需要重写的函数:

virtual void mousePressEvent(QMouseEvent *event);             //鼠标按下
virtual void mouseReleaseEvent(QMouseEvent *event);           //鼠标移动
virtual void mouseMoveEvent(QMouseEvent *event);              //鼠标释放
virtual void paintEvent(QPaintEvent *event);                  //画笔绘制
  • 裁剪矩形绘制
//通过上述函数获取鼠标起始位置
Qpoint mouse_slid_begin_point_, mouse_slid_end_point_;            //截取图片:滑动鼠标起始位置
Qpixmap pixmap_;                //截屏结果图片
QRect selected_rect = GetRect(mouse_slid_begin_point, mouse_slid_end_point_);               //根据两点计算矩形大小
_painter->drawPixmap(selected_rect .topLeft(), pixmap_);              //绘制矩形区域内裁剪图片

pixmap_对象中存放的内容就是需要保存的图片,这样基本的截图功能就已经实现。

截图辅助功能

  • 截图工具的辅助功能暂时先不考虑对图片本身进行二次操作(例如:自定义画笔,箭头,马赛克等),优先考虑将这个图片的参数信息显示,具备一些基本操作等。暂时考虑添加的信息显示:裁剪区域大小,十字形辅助线,锚点(图片局部放大显示)像素点颜色,当前鼠标位置,提示信息。
    在这里插入图片描述
    在这里插入图片描述
  1. 裁剪区域大小,十字形辅助线,当前鼠标位置,提示信息 这类信息就是计算好要显示的位置,然后将信息绘制到上面即可,具体实现这里不加赘述。
  2. 锚点功能。这里取17X11的图片,然后放大十倍进行显示。获取鼠标当前位置p3,以p3为中心截取17X11区域内图片,将图片放大后绘制在大小为170X110的矩形内。十字形锚点,简单来说为两个大小为170X10,10X110的蓝色透明矩形垂直交叉绘制,交叉部分绘制一个大小为10X10填充色为当前鼠标指向色的矩形。
//*******************信息框--图片区****************
	//矩形:图片框
	QRect rect_infomation_pixmap_rect(information_x, information_y, 170, 110);
	//放大图片处理
	QRect rect_information_pixmap(mouse_now_point_.x() - 8, mouse_now_point_.y() - 5, 17, 11);
	QPixmap information_pixmap_ = show_top_pixmap_.copy(rect_information_pixmap).scaled(170, 110, Qt::KeepAspectRatioByExpanding);
	_painter->drawPixmap(rect_infomation_pixmap_rect.topLeft(), information_pixmap_);
	//中央辅助线绘制
	QColor information_pixmap_color = QColor(0, 0, 255, 150);
	QRect information_pixmap_x(information_x, information_y + 50, 170, 10);
	QRect information_pixmap_y(information_x + 80, information_y, 10, 110);
	_painter->fillRect(information_pixmap_x, information_pixmap_color);
	_painter->fillRect(information_pixmap_y, information_pixmap_color);
	QRect information_pixmap_f(information_x + 80, information_y + 50, 10, 10);
	_painter->setBrush(QColor(rgb_color));
	_painter->drawRect(information_pixmap_f);
	_painter->setBrush(Qt::NoBrush);
	_painter->drawRect(rect_infomation_pixmap_rect);
  1. 像素点颜色。当前屏幕图片为全屏显示,所以鼠标的相对位置(event->pos())就是当前指向像素点的位置,由此获取像素点颜色。
//获取图片固定位置颜色
QRgb GetPixmapColor(QPixmap _pixmap, QPoint _position);

QRgb CustomSlidScreenCapture::GetPixmapColor(QPixmap _pixmap, QPoint _position)
{
	QImage image_ = _pixmap.toImage();
    //获取一行像素点颜色
	QRgb *line_rgb = (QRgb *)image_.scanLine(_position.y());
    //取对应像素点颜色
	return line_rgb[_position.x()];
}
  • 像素点颜色转化为文本信息
QRgb rgb_color = GetPixmapColor(show_top_pixmap_, mouse_now_point_);
QString text_information_color = "(" + QString::number(qRed(rgb_color)) + "  ," + QString::number(qGreen(rgb_color)) + "  ," + QString::number(qBlue(rgb_color)) + ")";

截取部分二次处理

在获取截取区域矩形后,需要对当前矩形进行微调,调整分为八个方向:上、下、左、右、左上、左下、右上、右下,在判断当前鼠标所处矩形位置后,记录鼠标按下与释放的位置p4、p5,根据这两点计算出鼠标移动的距离,然后对绘制的矩形区域进行调整。除却调整矩形大小之外,矩形还应该可以拖动,实现方式与上面大同小异。对于截取部分的二次处理,主要是对数据的处理,没有太大的难度,这里不在多加赘述。

  • 设置鼠标的不同样式
this->setCursor(Qt::ArrowCursor);
  • 鼠标样式枚举枚举
枚举值 含义
Qt::ArrowCursor 数表常态
Qt::SizeVerCursor 垂直上下箭头
Qt::SizeAllCursor 全方向箭头
Qt::SizeHorCursor 水平左右箭头
Qt::SizeBDiagCursor 斜左下右上箭头
Qt::SizeFDiagCursor 斜左上右下箭头

代码实现

至此,滑动鼠标截取当前桌面显示内容功能已大致完成,代码具体实现如下:

  • custom_slid_screen_capture.h
#pragma once
#include <QDialog>
#include <QObject>
#include <QWidget>
#include <QPixmap>
#include <QImage>
#include <QPoint>
#include <QPainter>
#include <QApplication>
#include <QDesktopWidget>
#include <QStandardPaths>
#include <QKeyEvent>
#include <QMenu>
#include <QClipboard>
#include <QtGui//QWindow>
#include <QDebug>
#include <QtGui/QScreen>
#include <QFileDialog>
#include <Windows.h>
#include <vector>

enum ArrowType
{
	Arrow_Cursor,
	Size_Ver_Cursor_Top,
	Size_Ver_Cursor_Bottom,
	Size_Hor_Cursor_Left,
	Size_Hor_Cursor_Right,
	Size_All_Cursor,
	Size_Bdiag_Cursor_Top,
	Size_Bdiag_Cursor_Bottom,
	Size_Fdiag_Cursor_Top,
	Size_Fdiag_Cursor_Bottom
};

class CustomSlidScreenCapture
	:public QDialog
{
	Q_OBJECT
public:
	CustomSlidScreenCapture();
	~CustomSlidScreenCapture();


public:

	void ScreenCapture();

private:

	QPixmap show_top_pixmap_;										//当前桌面显示内容
	QPixmap pixmap_;												//当前图片
	QString pixel_color_;											//当前像素颜色
	QPoint mouse_slid_begin_point_, mouse_slid_end_point_;			//截取图片:滑动鼠标起始位置
	QPoint mouse_now_point_;										//鼠标当前位置
	bool mouse_slid_press_flag_;									//截取图片:鼠标是否按下
	bool mouse_slid_finish_;										//截取图片:截屏区域是否选择完毕
	QPoint mouse_rect_begin_point_, mouse_rect_end_point_;			//调整截屏区域:滑动鼠标起始位置
	bool mouse_rect_press_flag_;									//调整截屏区域:鼠标是否按下
	QPoint mouse_result_begin_point_, mouse_result_end_point_;		//调整结果:图片起始位置

private:
	/*******************画笔绘制相关********************/
	//绘制整体背景图片
	void DrawBackgroundPixmap(QPainter *_painter);
	//绘制滑动矩形框
	void DrawSlidRect(QPainter *_painter);
	//绘制辅助线
	void DrawBoostLine(QPainter *_painter);
	//绘制信息框
	void DrawInformationRect(QPainter *_painter);
	//绘制结果矩形框--大小重绘
	void DrawFruitRect(QPainter *_painter);
	//绘制结果矩形框--样式
	void DrawFruitRectStyle(QPainter *_painter, QPoint& _begion_point, QPoint& _end_point);
	//绘制结果矩形框相关判断显示
	void DrawFruitRectIsShow(QPainter *_painter);

	//获取要绘制的矩形
	QRect GetRect(const QPoint& _begin_Point, const QPoint& _end_Point);
	//获取图片固定位置颜色
	QRgb GetPixmapColor(QPixmap _pixmap, QPoint _position);
	//获取起始点的偏移
	QPoint GetOffsetPoint(const QPoint& _begin_Point, const QPoint& _end_Point);
	//判断点是否在该矩形内
	ArrowType PointInRect(QPoint& _point, QRect _rect);
	//保存图片
	void Save();
	//返回当前截图对象
	QPixmap GetScreenPixmap();

protected:
	virtual void mousePressEvent(QMouseEvent *event);


	virtual void mouseReleaseEvent(QMouseEvent *event);


	virtual void mouseMoveEvent(QMouseEvent *event);


	virtual void paintEvent(QPaintEvent *event);


	virtual void keyReleaseEvent(QKeyEvent *event);

};
  • custom_slid_screen_capture.cpp
#include "custom_slid_screen_capture.h"

std::vector<QRect> allWindowRect;
std::vector<HWND> allWindowHwnd;
std::vector<MyRect> myRectRestlt;

bool CALLBACK MyEnumWindowsProc(HWND _hwnd, LPARAM _lparam);

CustomSlidScreenCapture::CustomSlidScreenCapture()
	: mouse_slid_press_flag_(false)
	, mouse_slid_finish_(false)
	, mouse_rect_press_flag_(false)
	, pixel_color_("(0,0,0)")
{
	this->setWindowModality(Qt::WindowModal);
	this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
	this->setWindowState(Qt::WindowActive | Qt::WindowFullScreen);
	//默认鼠标移动进入鼠标移动响应函数
	this->setMouseTracking(true);
	::EnumWindows((WNDENUMPROC)MyEnumWindowsProc, 0);
}

CustomSlidScreenCapture::~CustomSlidScreenCapture()
{
}

void CustomSlidScreenCapture::ScreenCapture()
{
	show_top_pixmap_ = QPixmap::grabWindow(QApplication::desktop()->winId());
}


QRect CustomSlidScreenCapture::GetRect(const QPoint& _begin_Point, const QPoint& _end_Point)
{
	int x, y, width, height;
	width = qAbs(_begin_Point.x() - _end_Point.x());
	height = qAbs(_begin_Point.y() - _end_Point.y());
	x = _begin_Point.x() < _end_Point.x() ? _begin_Point.x() : _end_Point.x();
	y = _begin_Point.y() < _end_Point.y() ? _begin_Point.y() : _end_Point.y();
	QRect selected_rect = QRect(x, y, width, height);									//QRect类代表一个矩形区域
	if (selected_rect.width() == 0)
	{
		selected_rect.setWidth(1);
	}
	if (selected_rect.height() == 0)
	{
		selected_rect.setHeight(1);
	}
	return selected_rect;
}

QRgb CustomSlidScreenCapture::GetPixmapColor(QPixmap _pixmap, QPoint _position)
{
	QImage image_ = _pixmap.toImage();
	QRgb *line_rgb = (QRgb *)image_.scanLine(_position.y());
	return line_rgb[_position.x()];
}

QPoint CustomSlidScreenCapture::GetOffsetPoint(const QPoint& _begin_Point, const QPoint& _end_Point)
{
	return QPoint(_end_Point.x() - _begin_Point.x(), _end_Point.y() - _begin_Point.y());
}

ArrowType CustomSlidScreenCapture::PointInRect(QPoint& _point, QRect _rect)
{
	int x1 = _rect.topLeft().x();
	int y1 = _rect.topLeft().y();
	int x2 = _rect.bottomRight().x();
	int y2 = _rect.bottomRight().y();
	int range_size = (_rect.width() ? _rect.height() : _rect.width()>_rect.height())/3;

	//全
	if (_point.x() >= x1 + range_size && _point.x() <= x2 - range_size && _point.y() >= y1 + range_size && _point.y() <= y2 - range_size)
		return Size_All_Cursor;
	//水平-左
	if (_point.x() >= x1 - 100 && _point.x() <= x1 + range_size && _point.y() >= y1 + range_size && _point.y() <= y2 - range_size)
		return Size_Hor_Cursor_Left;
	//水平-右
	if (_point.x() >= x2 - range_size && _point.x() <= x2 + 100 && _point.y() >= y1 + range_size && _point.y() <= y2 - range_size)
		return Size_Hor_Cursor_Right;
	//垂直-上
	if (_point.x() >= x1 + range_size && _point.x() <= x2 - range_size && _point.y() >= y1 - 100 && _point.y() <= y1 + range_size)
		return Size_Ver_Cursor_Top;
	//垂直-下
	if (_point.x() >= x1 + range_size && _point.x() <= x2 - range_size && _point.y() >= y2 - range_size && _point.y() <= y2 + 100)
		return Size_Ver_Cursor_Bottom;
	//斜下-上
	if (_point.x() >= x1 - 100 && _point.x() <= x1 + range_size && _point.y() >= y1 - 100 && _point.y() <= y1 + range_size)
		return Size_Fdiag_Cursor_Top;
	//斜下-下
	if (_point.x() >= x2 - range_size && _point.x() <= x2 + 100 && _point.y() >= y2 - range_size && _point.y() <= y2 + 100)
		return Size_Fdiag_Cursor_Bottom;
	//斜上-上
	if (_point.x() >= x2 - range_size && _point.x() <= x2 + 100 && _point.y() >= y1 - 100 && _point.y() <= y1 + range_size)
		return Size_Bdiag_Cursor_Top;
	//斜上-下
	if (_point.x() >= x1 - 100 && _point.x() <= x1 + range_size && _point.y() >= y2 - range_size && _point.y() <= y2 + 100)
		return Size_Bdiag_Cursor_Bottom;
	return Arrow_Cursor;
}

void CustomSlidScreenCapture::CalculataRectDistance(QRect rect)
{
	int dis = rect.width() + rect.height();
	MyRect temp_myrect;
	temp_myrect.myRect_ = rect;
	temp_myrect.distance_ = dis;
	myRectRestlt.push_back(temp_myrect);
}

void CustomSlidScreenCapture::Save()
{
	QString file_name = QFileDialog::getSaveFileName(this, QStringLiteral("截图文件保存"), "picture1.jpg", tr("Images(*.png,*.bmp,*.jpg)"));
	pixmap_.save(file_name);
}

QPixmap CustomSlidScreenCapture::GetScreenPixmap()
{
	return pixmap_;
}

void CustomSlidScreenCapture::mousePressEvent(QMouseEvent *event)
{
	//滑动获取截屏区域
	if (event->button() == Qt::LeftButton&&!mouse_slid_finish_)
	{
		mouse_slid_press_flag_ = true;
		mouse_slid_begin_point_ = event->pos();
	}
	//拖动截屏区域
	if (event->button() == Qt::LeftButton&&!mouse_rect_press_flag_&&mouse_slid_finish_&&PointInRect(mouse_now_point_, GetRect(mouse_slid_begin_point_, mouse_slid_end_point_))!=Arrow_Cursor)
	{
		mouse_rect_press_flag_ = true;
		mouse_rect_begin_point_ = event->pos();
		mouse_rect_end_point_ = event->pos();
		mouse_result_begin_point_ = mouse_slid_begin_point_;
		mouse_result_end_point_ = mouse_slid_end_point_;
	}
#if 0
	//点击截取屏幕
	if (event->button() == Qt::LeftButton&&!mouse_rect_press_flag_&&mouse_slid_finish_&&PointInRect(mouse_now_point_, GetRect(mouse_slid_begin_point_, mouse_slid_end_point_)) != Arrow_Cursor)
	{
		mouse_rect_end_point_ = event->pos();
		mouse_rect_press_flag_ = false;
		mouse_slid_begin_point_ = mouse_result_begin_point_;
		mouse_slid_end_point_ = mouse_result_end_point_;
	}
#endif
	update();
	return QWidget::mousePressEvent(event);
}

void CustomSlidScreenCapture::mouseReleaseEvent(QMouseEvent *event)
{
	//滑动获取截屏区域
	if (mouse_slid_press_flag_)
	{
		mouse_slid_end_point_ = event->pos();
		mouse_slid_press_flag_ = false;
		mouse_slid_finish_ = true;
		mouse_result_begin_point_ = mouse_slid_begin_point_;
		mouse_result_end_point_ = mouse_slid_end_point_;
	}
	//拖动截屏区域
	if (mouse_rect_press_flag_)
	{
		mouse_rect_end_point_ = event->pos();
		mouse_rect_press_flag_ = false;
		/*QRect rect_f = GetRect(mouse_result_begin_point_, mouse_result_end_point_);
		mouse_slid_begin_point_ = rect_f.topLeft();
		mouse_slid_end_point_ = rect_f.bottomRight();*/
		mouse_slid_begin_point_ = mouse_result_begin_point_;
		mouse_slid_end_point_ = mouse_result_end_point_;
	}
	update();
	return QWidget::mouseReleaseEvent(event);
}

void CustomSlidScreenCapture::mouseMoveEvent(QMouseEvent *event)
{
	mouse_now_point_ = event->pos();
	//滑动获取截屏区域
	if (mouse_slid_press_flag_)
	{
		mouse_slid_end_point_ = event->pos();																
	}
	//拖动截屏区域
	if (mouse_rect_press_flag_)
	{
		mouse_rect_end_point_ = event->pos();
	}

	//调用该函数时会调用paintEvent函数
	update();	
	return QWidget::mouseMoveEvent(event);
}

void CustomSlidScreenCapture::keyReleaseEvent(QKeyEvent *event)
{
	//退出
	if (event->key() == Qt::Key_Escape)
	{
		close();
	}
	//保存颜色
	if (event->key() == Qt::Key_C)
	{
		QApplication::clipboard()->setText(pixel_color_);
	}
	//复制内容到剪切板
	if (event->matches(QKeySequence::Copy))
	{
		QApplication::clipboard()->setPixmap(pixmap_);
	}
	//重置
	if (event->key() == Qt::Key_Enter)
	{
		mouse_slid_press_flag_ = false;
		mouse_slid_finish_ = false;
	}
    //保存图片
	if (event->matches(QKeySequence::Save))
	{
		Save();
		mouse_slid_press_flag_ = false;
		mouse_slid_finish_ = false;
	}
	update();
}

void CustomSlidScreenCapture::DrawBackgroundPixmap(QPainter *_painter)
{
	QColor shadowColor = QColor(0, 0, 0, 100);											//阴影色
	_painter->setPen(QPen(Qt::white, 1, Qt::SolidLine, Qt::FlatCap));					//设置画笔
	_painter->drawPixmap(0, 0, show_top_pixmap_);										//将获取的图片画到窗体上
	_painter->fillRect(show_top_pixmap_.rect(), shadowColor);							//画影罩效果
}

void CustomSlidScreenCapture::DrawSlidRect(QPainter *_painter)
{
	//绘制截取区域
	QRect selected_rect = GetRect(mouse_slid_begin_point_, mouse_slid_end_point_);
	pixmap_ = show_top_pixmap_.copy(selected_rect);
	_painter->drawPixmap(selected_rect.topLeft(), pixmap_);
	DrawFruitRectStyle(_painter, mouse_slid_begin_point_, mouse_slid_end_point_);

	//截取区域大小信息
	QString pixmap_size = QString::number(selected_rect.width()) + " X " + QString::number(selected_rect.height());
	QColor information_color = QColor(0, 0, 0, 150);
	QFontMetrics fm(_painter->font());
	QRect fm_rect = fm.boundingRect(pixmap_size);
	QRect pixmap_size_rect(selected_rect.topLeft().x(), selected_rect.topLeft().y() -20, fm_rect.width() + 5, 20);
	_painter->fillRect(pixmap_size_rect, information_color);
	_painter->drawText(pixmap_size_rect,Qt::AlignCenter, pixmap_size);
}

void CustomSlidScreenCapture::DrawBoostLine(QPainter *_painter)
{
	//绘制辅助线
	QLine line_boost_x(QPoint(0, mouse_slid_end_point_.y()), QPoint(show_top_pixmap_.width(), mouse_slid_end_point_.y()));
	QLine line_boost_y(QPoint(mouse_slid_end_point_.x(), 0), QPoint(mouse_slid_end_point_.x(), show_top_pixmap_.height()));
	_painter->drawLine(line_boost_x);
	_painter->drawLine(line_boost_y);
}

void CustomSlidScreenCapture::DrawInformationRect(QPainter *_painter)
{
	//绘制辅助信息框位置
	int information_x = mouse_now_point_.x() +50;
	int information_y = mouse_now_point_.y() +50;

	//*******************信息框--整体****************
	QRect rect_infomation(information_x, information_y, 170, 170);
	//整体颜色基调
	QColor information_color = QColor(0, 0, 0, 150);
	_painter->fillRect(rect_infomation, information_color);
	//*******************信息框--文本内容****************
	//文本:位置信息
	QRect rect_infomation_position(information_x, information_y + 110, 170, 20);
	QString text_information_position = "(" + QString::number(mouse_now_point_.x()) + "," + QString::number(mouse_now_point_.y()) + ")";
	_painter->drawText(rect_infomation_position, Qt::AlignCenter, text_information_position);

	//文本:颜色信息
	QRect rect_infomation_color(information_x, information_y + 130, 170, 20);
	//颜色显示小框
	QRect rect_infomation_color_f(information_x + 5, information_y + 135, 10, 10);
	QRgb rgb_color = GetPixmapColor(show_top_pixmap_, mouse_now_point_);
	QString text_information_color = "(" + QString::number(qRed(rgb_color)) + "  ," + QString::number(qGreen(rgb_color)) + "  ," + QString::number(qBlue(rgb_color)) + ")";
	pixel_color_ = text_information_color;
	_painter->drawText(rect_infomation_color, Qt::AlignCenter, text_information_color);
	_painter->setBrush(QColor(rgb_color));
	_painter->drawRect(rect_infomation_color_f);
	_painter->setBrush(Qt::NoBrush);

	//文本:提示信息
	QRect rect_infomation_text(information_x, information_y + 150, 170, 20);
	QString text_information_text = QStringLiteral("按C复制颜色值");
	_painter->drawText(rect_infomation_text, Qt::AlignCenter, text_information_text);

	//*******************信息框--图片区****************
	//图片框
	QRect rect_infomation_pixmap_rect(information_x, information_y, 170, 110);
	//放大图片
	QRect rect_information_pixmap(mouse_now_point_.x() - 8, mouse_now_point_.y() - 5, 17, 11);
	QPixmap information_pixmap_ = show_top_pixmap_.copy(rect_information_pixmap).scaled(170, 110, Qt::KeepAspectRatioByExpanding);
	_painter->drawPixmap(rect_infomation_pixmap_rect.topLeft(), information_pixmap_);
	//中央辅助线
	QColor information_pixmap_color = QColor(0, 0, 255, 150);
	QRect information_pixmap_x(information_x, information_y + 50, 170, 10);
	QRect information_pixmap_y(information_x + 80, information_y, 10, 110);
	_painter->fillRect(information_pixmap_x, information_pixmap_color);
	_painter->fillRect(information_pixmap_y, information_pixmap_color);
	QRect information_pixmap_f(information_x + 80, information_y + 50, 10, 10);
	_painter->setBrush(QColor(rgb_color));
	_painter->drawRect(information_pixmap_f);
	_painter->setBrush(Qt::NoBrush);
	_painter->drawRect(rect_infomation_pixmap_rect);
}

void CustomSlidScreenCapture::DrawFruitRect(QPainter *_painter)
{
	//绘制结果矩形框
	//计算偏移
	if (mouse_rect_press_flag_)
	{
		QRect rect_f = GetRect(mouse_slid_begin_point_, mouse_slid_begin_point_);
		QPoint rect_f_begin = rect_f.topLeft();
		QPoint rect_f_end = rect_f.bottomRight();
		ArrowType flag = PointInRect(mouse_now_point_, GetRect(mouse_result_begin_point_, mouse_result_end_point_));
		int offset_x = GetOffsetPoint(mouse_rect_begin_point_, mouse_rect_end_point_).x();
		int offset_y = GetOffsetPoint(mouse_rect_begin_point_, mouse_rect_end_point_).y();
		switch (flag)
		{
		case Arrow_Cursor:
			break;
		case Size_Ver_Cursor_Top:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x(), mouse_slid_begin_point_.y() + offset_y);
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x(), mouse_slid_end_point_.y());
			break;
		case Size_Ver_Cursor_Bottom:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x(), mouse_slid_begin_point_.y());
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x(), mouse_slid_end_point_.y() + offset_y);
			break;
		case Size_Hor_Cursor_Left:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x() + offset_x, mouse_slid_begin_point_.y());
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x(), mouse_slid_end_point_.y() + offset_y);
			break;
		case Size_Hor_Cursor_Right:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x(), mouse_slid_begin_point_.y());
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x() + offset_x, mouse_slid_end_point_.y());
			break;
		case Size_All_Cursor:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x() + offset_x, mouse_slid_begin_point_.y() + offset_y);
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x() + offset_x, mouse_slid_end_point_.y() + offset_y);
			break;
		case Size_Bdiag_Cursor_Top:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x(), mouse_slid_begin_point_.y() + offset_y);
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x() + offset_x, mouse_slid_end_point_.y());
			break;
		case Size_Bdiag_Cursor_Bottom:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x() + offset_x, mouse_slid_begin_point_.y());
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x(), mouse_slid_end_point_.y() + offset_y);
			break;
		case Size_Fdiag_Cursor_Top:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x() + offset_x, mouse_slid_begin_point_.y() + offset_y);
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x(), mouse_slid_end_point_.y());
			break;
		case Size_Fdiag_Cursor_Bottom:
			mouse_result_begin_point_ = QPoint(mouse_slid_begin_point_.x(), mouse_slid_begin_point_.y());
			mouse_result_end_point_ = QPoint(mouse_slid_end_point_.x() + offset_x, mouse_slid_end_point_.y() + offset_y);
			break;
		default:
			break;
		}
		
	}

	//绘制截取区域
	QRect selected_rect = GetRect(mouse_result_begin_point_, mouse_result_end_point_);
	pixmap_ = show_top_pixmap_.copy(selected_rect);
	_painter->drawPixmap(selected_rect.topLeft(), pixmap_);
	DrawFruitRectStyle(_painter, mouse_result_begin_point_, mouse_result_end_point_);

	//截取区域大小信息
	QString pixmap_size = QString::number(selected_rect.width()) + " X " + QString::number(selected_rect.height());
	QColor information_color = QColor(0, 0, 0, 150);
	QFontMetrics fm(_painter->font());
	QRect fm_rect = fm.boundingRect(pixmap_size);
	QRect pixmap_size_rect(selected_rect.topLeft().x(), selected_rect.topLeft().y() -20, fm_rect.width() + 5, 20);
	_painter->fillRect(pixmap_size_rect, information_color);
	_painter->drawText(pixmap_size_rect, Qt::AlignCenter, pixmap_size);

}

void CustomSlidScreenCapture::DrawFruitRectStyle(QPainter *_painter, QPoint& _begion_point, QPoint& _end_point)
{
	int radius_roll = 4;
	int x1 = _begion_point.x();
	int y1 = _begion_point.y();
	int x2 = _end_point.x();
	int y2 = _end_point.y();
	QVector<QPoint> points;
	points.push_back(QPoint(x1, y1));
	points.push_back(QPoint((x1 + x2) / 2, y1));
	points.push_back(QPoint(x2, y1));
	points.push_back(QPoint(x2, (y1 + y2) / 2));
	points.push_back(QPoint(x2, y2));
	points.push_back(QPoint((x1 + x2) / 2, y2));
	points.push_back(QPoint(x1, y2));
	points.push_back(QPoint(x1, (y1 + y2) / 2));
	_painter->setBrush(Qt::blue);
	for (int i = 0; i < 8; i++)
	{
		_painter->drawEllipse(points.at(i),radius_roll,radius_roll);
	}
	
}

void CustomSlidScreenCapture::DrawFruitRectIsShow(QPainter *_painter)
{
	ArrowType flag = PointInRect(mouse_now_point_, GetRect(mouse_result_begin_point_, mouse_result_end_point_));
	switch (flag)
	{
	case Arrow_Cursor:
		this->setCursor(Qt::ArrowCursor);
		break;
	case Size_Ver_Cursor_Top:
		this->setCursor(Qt::SizeVerCursor);
		break;
	case Size_Ver_Cursor_Bottom:
		this->setCursor(Qt::SizeVerCursor);
		break;
	case Size_Hor_Cursor_Left:
		this->setCursor(Qt::SizeHorCursor);
		break;
	case Size_Hor_Cursor_Right:
		this->setCursor(Qt::SizeHorCursor);
		break;
	case Size_All_Cursor:
		this->setCursor(Qt::SizeAllCursor);
		break;
	case Size_Bdiag_Cursor_Top:
		this->setCursor(Qt::SizeBDiagCursor);
		break;
	case Size_Bdiag_Cursor_Bottom:
		this->setCursor(Qt::SizeBDiagCursor);
		break;
	case Size_Fdiag_Cursor_Top:
		this->setCursor(Qt::SizeFDiagCursor);
		break;
	case Size_Fdiag_Cursor_Bottom:
		this->setCursor(Qt::SizeFDiagCursor);
		break;
	default:
		break;
	}
	if (flag&&!mouse_rect_press_flag_)
		DrawInformationRect(_painter);					//绘制信息框
}

void CustomSlidScreenCapture::paintEvent(QPaintEvent *event)
{
	QPainter *painter = new QPainter(this);
	painter->save();
	DrawBackgroundPixmap(painter);							//绘制整体背景图片
	//滑动截取图片
	if (mouse_slid_press_flag_)
	{
		DrawBoostLine(painter);								//绘制辅助线
		DrawSlidRect(painter);								//绘制滑动矩形框
		DrawInformationRect(painter);						//绘制信息框
	}
	//截取图片二次处理
	if (mouse_slid_finish_)
	{
		DrawFruitRect(painter);								//绘制结果矩形框--大小重绘
		DrawFruitRectIsShow(painter);						//绘制结果矩形框相关判断显示
	}
	if (!mouse_slid_finish_)
	{
		DrawFruitRect(painter);								//绘制结果矩形框--大小重绘
		//DrawFruitRectIsShow(painter);						//绘制结果矩形框相关判断显示
	}
	painter->restore();
}

后续功能添加在完善后会陆续上传,新人第一次发博客,如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。
原创文章,转载请标明本文出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 简单截图工具(一) 高仿QQ截屏 滑动截屏 的相关文章

  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • 如何使用 Qt DOM 通过此语法获取 xml 属性

    我正在使用 Qt DOM XML 解析器 并且遇到了如下属性定义的问题
  • 在 Qt 服务器上验证用户身份

    我正在尝试使用 C QtTcpSocket 为个人项目 多人国际象棋游戏 实现身份验证系统 我的朋友建议了一种验证用户的方法 但我想问是否有更简单或更好的方法 来自 Python 背景 做这个项目主要是为了加深对 C 的理解 我将发布我朋友
  • 第一次信号发射后自动断开

    我正在从文件加载网页 然后替换其中的一些 html self template web page QtWebKit QWebPage self template web page mainFrame load QtCore QUrl tem
  • 如何让小部件在上下文菜单出现时接收鼠标释放事件

    在Ubuntu20 04上 当上下文菜单出现时 我无法让小部件接收鼠标释放事件 而Windows可以接收 我的pyqt版本是5 15 2 我考虑过手动发送鼠标释放事件 但我不知道当上下文菜单出现时哪些系统会收到鼠标释放事件 这样做可能会导致
  • Retina 显示屏中具有 QOpenGLWIdget 的 Qt MainWindow 显示错误大小

    我有一个 Qt 应用程序MainWindow 我嵌入一个QOpenGLWidget在里面 一切正常 直到我开始使用 Apple Retina 显示屏并在高 DPI 模式下运行我的应用程序 我的QOpenGLWidget只是它应该具有的大小的
  • 完全彻底卸载QT Creator

    问题 如何从 Linux 机器上卸载 QT Creator 我的 Debian Jessie 机器上的安装已损坏 我尝试过重新安装 修复等 但没有成功 建议我完全卸载 获取最新版本并重新安装 问题是我不确定如何执行此操作 每次我尝试时 QT
  • QMainWindow 上的 Qt 布局

    我设计了一个QMainWindow with QtCreator s设计师 它由默认的中央小部件 aQWidget 其中包含一个QVBoxLayout以及其中的所有其他小部件 现在我想要的一切就是QVBoxLayout自动占据整个中央小部件
  • 如何在Qt 5中的paintEvent上使用mouseMoveEvent?

    我是 Qt 和 c 的新手 所以我遇到了一些困难 我正在尝试创建一个小部件 它可以获取 mouseMoveEvent 位置并在鼠标位置的像素图上绘制椭圆 下面你可以看到代码 include myimage h include
  • QML 中可重用的字体属性[重复]

    这个问题在这里已经有答案了 在 QML 中 我希望能够定义一组字体属性以进行简单的语义重用 例如 代替 Text text This is a header font family Encode Sans weight Font Black
  • Qt:不完整类型和前向声明的使用无效

    我有一些误解 A h ifndef A H define A H include B h class A public B Q OBJECT public A endif A cpp include A h A A B ui gt blan
  • 是否有 Qt 小部件可以浏览应用程序中小部件的层次结构(类似于 Spy++)?

    我们有一个具有复杂的小部件层次结构的应用程序 我希望能够以与 Spy 类似的方式浏览此层次结构 查看和编辑属性 例如大小 如果有一个小部件可以显示此信息 则它不需要在外部应用程序中运行 那么问题来了 这样的神兽存在吗 您可以使用Gammar
  • 如何将自定义 Qt 类型与 QML 信号一起使用?

    我在 Qt 5 2 qml 应用程序中创建了一个自定义类型 class Setting public QObject Q OBJECT Q PROPERTY QString key READ key WRITE setKey Q PROPE
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • QML 列表视图拖放

    我想创建两个 qml 列表视图 可以执行两个功能 拖放一个列表中的项目以更改项目的顺序 跨列表拖放项目 项目将从一个列表中删除并添加到另一个列表中 根据 Qt 文档中的拖放示例 我决定创建两个访问同一列表模型的列表视图 列表模型中的每个项目
  • QObject 通用信号处理程序

    信号处理程序 是指插槽 而不是 POSIX 信号的处理程序 我需要 连接 可能不会 using QObject connect直接地 所有信号从 QObject 的 未知 子类的实例到一个单槽另一个 QObject 的 我需要这个才能通过网
  • QFileDialog::getOpenFileName 调试时崩溃,显然是由项目名称引起的?

    我遇到了一个让我非常困惑的问题 我在 Windows 7 上使用 Qt Creator 3 1 2 和 Qt 5 3 使用 MSVC 10 0 编译器和 Windows 8 1 调试工具中的 CDB 不确定我是否应该寻找特定于 Window
  • 使用 QNetworkAccessManager 的 Qt 控制台应用程序

    我正在尝试写一个Qt调用网络服务的应用程序 这是一个控制台应用程序 url 将作为命令行参数传入 我搜索了例如http程序在Qt并找到这个链接 http qt project org doc qt 5 qnetworkaccessmanag
  • 为什么动态 qml 对象的创建如此缓慢,有哪些合理的替代方案?

    我想要实现的目标类似于棋盘游戏 有一个100 100的网格 放在一个Item它驻留在一个Flickable 游戏板 的各个矩形都是 svg 图像 目前大约有 20 种 可能会增加到数百种 作为基准测试 我只是尝试用元素填充 世界 Compo
  • 如何为 Windows 安装开源 Qt 库 5 二进制版本

    这个问题具体是关于Qt libraries 5 0 0 for Windows VS 2010 406 MB at http qt project org downloads http qt project org downloads 但我

随机推荐

  • 心电图心跳信号多分类预测(一)

    目录 1 赛题理解 1 1赛题概况 1 2数据概况 1 3代码示例 1 3 1数据读取 1 3 2分类指标计算示例 2 baseline 2 1 导入第三方包 2 2 读取数据 2 3 数据预处理 2 4 训练数据 测试数据准备 2 5 模
  • gitLab配置ssh实现私钥访问

    1 配置ssh文件 1 cd C Users 用户名 ssh 找到文件夹 删除 ssh 里面所有其他文件方面我们配置要最新的 2 win r cmd 呼出命令行 ssh keygen t rsa C 必须对应gitLab用户名 3 生成文件
  • 如何理解委托

    以前一直没弄懂委托到底有什么用 为什么要用 今天小小总结了一下 如下 总结 delegate 1 委托的定义 1 就是一个类 他定义了方法的类型 2 public delegate void 自定义类型 类型 变量 当然还有匿名委托dele
  • 再谈select, iocp, epoll,kqueue及各种I/O复用机制

    上篇文章太过幼稚 一派胡言 希望没有误导大家 我也是菜鸟 学习本身就是一个不断追求真理的过程 希望能谅解 首先感谢kasicass GG指出错误 已经指导我很多次了 非常感谢 然后我又查阅了一些资料 再次整理 more seriously
  • 老油条表示真干不过,部门新来的00后网络安全工程师已把我卷崩溃,想要润了...

    在程序员职场上 什么样的人最让人反感呢 是技术不好的人吗 并不是 技术不好的同事 我们可以帮他 是技术太强的人吗 也不是 技术很强的同事 可遇不可求 向他学习还来不及呢 真正让人反感的 是技术平平 却急于表现自己的人 每天加班到12点 在老
  • 解决java中html转word文档,转成功后的word文档在断网情况下无法显示图片问题

    前一段时间遇到一个问题 就是将html转成word文档 里面有图片 表格 和各种形式的文字 刚开始的做法是将html代码取出来 然后以留的形式进行保存 后缀名为 doc 当我转成之后发现一切完美 但是图片出现了问题 1 图片大小 像素有问题
  • 用elasticsearch-certutil生成证书

    1 生成CA证书 生成的elastic stack ca zip包含了证书和私钥 证书有效期是10年 elasticsearch certutil ca days 3650 keysize 4096 out cert elastic sta
  • 【Python爬虫】requests+BeautifulSoup4+MongoDB 爬取51job招聘信息(最新)

    新手训练 51job 网站完整的Python爬虫程序 文章目录 前言 一 网站解析 1 分析网站加载形式 2 分析网站的url 二 代码实现 1 引入库 2 解析城市编码 3 获取数据 3 1 解析数据 3 2 数据的清洗和存储 4 完整代
  • react更新props后this.props === nextProps

    1 this props always equals to nextProps 结构 父组件 ComparisonChart 子组件 UniversalChart 问题 父组件中state gt data传到子组件作为props gt da
  • 点击跳转到高德地图,百度地图,腾讯地图进行导航

    现在随着APP定制化的需求 很多APP都需要导航功能 然而自己APP集成一个导航 除了会增加APP大几十兆之外 还没有专业导航软件功能强大 然而现在大部分手机自带导航软件 所以只需要打开调用即可 包括腾讯的微信 都没有直接导航 而是调用了手
  • Ubuntu18.04及以上开机自启动脚本设置方法

    一 问题 ubuntu 18 04及以上系统取消了rc local自启动功能 因此不能像ubuntu16一样通过编辑rc local来设置开机启动脚本 通过下列简单设置后 可以使rc local重新发挥作用 二 方法 1 建立rc loca
  • Django连接MySql

    首先我们需要在Pycharm新建一个Django的项目 新建后的文件目录如下 a init py 标识当前所在目录时一个Python包 通过import导入的包或者方法会被自动识别 b asgi py 一个ASGI兼容的Web服务器的入口
  • Python中os.listdir和os.walk(获取路径方法)的区别

    在Python中 os listdir 和 os walk 是两种不同的方法来获取文件系统中的路径列表 os listdir 这个函数用来获取指定目录下的所有文件和文件夹的名称列表 它接受一个路径参数 返回该路径下的所有项目的名称 包括文件
  • Vue的条件判断

    1 Vue的条件判断 1 vue的条件判断 v if v else if v else 这三个指令与JS的条件语句if else else if类似 Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件 2 指令v if 可以用
  • 计算机专业毕业设计题目大全 (各类型系统设计大全)

    计算机专业毕业设计题目大全 毕设 论文 答辩通关法则 看这一篇 源码都在下面了 写在前面 尽管论文方法和毕设源码都有 但还是要看课 自己敲完完善好 做好充分准备面对答辩 1 网络留言薄 2 客户管理系统 3 多媒体积件管理库的开发与应用 4
  • QMap的使用(插入、取值、删除、遍历)

    1 创建 里面的数据类型随意都行 QMap
  • Java对象创建过程

    1 用户new一个对象 2 JVM检查常量池 看是否可定位到一个类 所对应的符号引用 并检查该类是否已经加载 解析和初始化 若没有 则执行类加载过程 3 类加载检查通过 JVM为新对象分配内存 由于类已经加载完成 所以内存大小是可以确定的
  • 【C/C++】C++ 浮点数

    C 浮点数 计算机将 2 5 3 64564 这样的值分成两部分存储 一部分表示值 另一部分 缩放因子 用于对值进行放大或缩小 浮点数的两种表示方法 1 使用常用的标准小数点表示法 如3 1415926 2 E表示法 如2 52e 8 25
  • 公众号开发配置,服务号对接第三方服务器配置方法

    很多公司企业在注册服务号后 通常需要对接第三方的开发平台 进行一些功能的完善补充 市面上第三方平台非常之多 但是因微信官方限制 所需要的配置总结下来就这么几点 下面给大家讲解下配置的要点 一 授权域名及IP白名单 1 登录微信公众平台后 点
  • Qt 简单截图工具(一) 高仿QQ截屏 滑动截屏

    目录 本系列目录 功能考虑 滑动鼠标截取当前桌面显示内容 滑动鼠标截取桌面图片 截图辅助功能 截取部分二次处理 代码实现 本系列目录 Qt 简单截图工具 一 高仿QQ截屏 滑动截屏 Qt 简单截图工具 二 添加菜单栏 添加取色器 切图功能