diff --git a/README.md b/README.md index 391acfa..65660c2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ | 28 | ntpclient | NTP服务器时间同步 | | 29 | lunarcalendarwidget | 农历控件 | | 30 | videowidget | 通用视频控件 | +| 31 | screenwidget | 屏幕截图控件 | ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/lightbutton.gif) ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/movewidget.gif) @@ -61,4 +62,5 @@ ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/emailtool.gif) ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/ntpclient.gif) ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/lunarcalendarwidget.gif) -![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/videowidget.gif) \ No newline at end of file +![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/videowidget.gif) +![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/snap/screenwidget.gif) \ No newline at end of file diff --git a/screenwidget/main.cpp b/screenwidget/main.cpp new file mode 100644 index 0000000..b8325f8 --- /dev/null +++ b/screenwidget/main.cpp @@ -0,0 +1,30 @@ +#pragma execution_character_set("utf-8") + +#include "screenwidget.h" +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setFont(QFont("Microsoft Yahei", 9)); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) +#if _MSC_VER + QTextCodec *codec = QTextCodec::codecForName("gbk"); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); +#endif + QTextCodec::setCodecForLocale(codec); + QTextCodec::setCodecForCStrings(codec); + QTextCodec::setCodecForTr(codec); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); + QTextCodec::setCodecForLocale(codec); +#endif + + ScreenWidget::Instance()->showFullScreen(); + + return a.exec(); +} diff --git a/screenwidget/screenwidget.cpp b/screenwidget/screenwidget.cpp new file mode 100644 index 0000000..994662f --- /dev/null +++ b/screenwidget/screenwidget.cpp @@ -0,0 +1,327 @@ +#pragma execution_character_set("utf-8") + +#include "screenwidget.h" +#include "qmutex.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qdesktopwidget.h" +#include "qfiledialog.h" +#include "qevent.h" +#include "qdatetime.h" +#include "qstringlist.h" + +#if (QT_VERSION > QT_VERSION_CHECK(5,0,0)) +#include "qscreen.h" +#endif + +#define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")) + +Screen::Screen(QSize size) +{ + maxWidth = size.width(); + maxHeight = size.height(); + + startPos = QPoint(-1, -1); + endPos = startPos; + leftUpPos = startPos; + rightDownPos = startPos; + status = SELECT; +} + +int Screen::width() +{ + return maxWidth; +} + +int Screen::height() +{ + return maxHeight; +} + +Screen::STATUS Screen::getStatus() +{ + return status; +} + +void Screen::setStatus(STATUS status) +{ + this->status = status; +} + +void Screen::setEnd(QPoint pos) +{ + endPos = pos; + leftUpPos = startPos; + rightDownPos = endPos; + cmpPoint(leftUpPos, rightDownPos); +} + +void Screen::setStart(QPoint pos) +{ + startPos = pos; +} + +QPoint Screen::getEnd() +{ + return endPos; +} + +QPoint Screen::getStart() +{ + return startPos; +} + +QPoint Screen::getLeftUp() +{ + return leftUpPos; +} + +QPoint Screen::getRightDown() +{ + return rightDownPos; +} + +bool Screen::isInArea(QPoint pos) +{ + if (pos.x() > leftUpPos.x() && pos.x() < rightDownPos.x() && pos.y() > leftUpPos.y() && pos.y() < rightDownPos.y()) { + return true; + } + + return false; +} + +void Screen::move(QPoint p) +{ + int lx = leftUpPos.x() + p.x(); + int ly = leftUpPos.y() + p.y(); + int rx = rightDownPos.x() + p.x(); + int ry = rightDownPos.y() + p.y(); + + if (lx < 0) { + lx = 0; + rx -= p.x(); + } + + if (ly < 0) { + ly = 0; + ry -= p.y(); + } + + if (rx > maxWidth) { + rx = maxWidth; + lx -= p.x(); + } + + if (ry > maxHeight) { + ry = maxHeight; + ly -= p.y(); + } + + leftUpPos = QPoint(lx, ly); + rightDownPos = QPoint(rx, ry); + startPos = leftUpPos; + endPos = rightDownPos; +} + +void Screen::cmpPoint(QPoint &leftTop, QPoint &rightDown) +{ + QPoint l = leftTop; + QPoint r = rightDown; + + if (l.x() <= r.x()) { + if (l.y() <= r.y()) { + ; + } else { + leftTop.setY(r.y()); + rightDown.setY(l.y()); + } + } else { + if (l.y() < r.y()) { + leftTop.setX(r.x()); + rightDown.setX(l.x()); + } else { + QPoint tmp; + tmp = leftTop; + leftTop = rightDown; + rightDown = tmp; + } + } +} + +QScopedPointer ScreenWidget::self; +ScreenWidget *ScreenWidget::Instance() +{ + if (self.isNull()) { + static QMutex mutex; + QMutexLocker locker(&mutex); + if (self.isNull()) { + self.reset(new ScreenWidget); + } + } + + return self.data(); +} + +ScreenWidget::ScreenWidget(QWidget *parent) : QWidget(parent) +{ + //this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); + + menu = new QMenu(this); + menu->addAction("保存当前截图", this, SLOT(saveScreen())); + menu->addAction("保存全屏截图", this, SLOT(saveFullScreen())); + menu->addAction("截图另存为", this, SLOT(saveScreenOther())); + menu->addAction("全屏另存为", this, SLOT(saveFullOther())); + menu->addAction("退出截图", this, SLOT(hide())); + + //取得屏幕大小 + screen = new Screen(QApplication::desktop()->size()); + //保存全屏图像 + fullScreen = new QPixmap(); +} + +void ScreenWidget::paintEvent(QPaintEvent *) +{ + int x = screen->getLeftUp().x(); + int y = screen->getLeftUp().y(); + int w = screen->getRightDown().x() - x; + int h = screen->getRightDown().y() - y; + + QPainter painter(this); + + QPen pen; + pen.setColor(Qt::green); + pen.setWidth(2); + pen.setStyle(Qt::DotLine); + painter.setPen(pen); + painter.drawPixmap(0, 0, *bgScreen); + + if (w != 0 && h != 0) { + painter.drawPixmap(x, y, fullScreen->copy(x, y, w, h)); + } + + painter.drawRect(x, y, w, h); + + pen.setColor(Qt::yellow); + painter.setPen(pen); + painter.drawText(x + 2, y - 8, tr("截图范围:( %1 x %2 ) - ( %3 x %4 ) 图片大小:( %5 x %6 )") + .arg(x).arg(y).arg(x + w).arg(y + h).arg(w).arg(h)); +} + +void ScreenWidget::showEvent(QShowEvent *) +{ + QPoint point(-1, -1); + screen->setStart(point); + screen->setEnd(point); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) + *fullScreen = fullScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height()); +#else + QScreen *pscreen = QApplication::primaryScreen(); + *fullScreen = pscreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height()); +#endif + + //设置透明度实现模糊背景 + QPixmap pix(screen->width(), screen->height()); + pix.fill((QColor(160, 160, 160, 200))); + bgScreen = new QPixmap(*fullScreen); + QPainter p(bgScreen); + p.drawPixmap(0, 0, pix); +} + +void ScreenWidget::saveScreen() +{ + int x = screen->getLeftUp().x(); + int y = screen->getLeftUp().y(); + int w = screen->getRightDown().x() - x; + int h = screen->getRightDown().y() - y; + + QString fileName = QString("%1/screen_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME); + fullScreen->copy(x, y, w, h).save(fileName, "png"); + close(); +} + +void ScreenWidget::saveFullScreen() +{ + QString fileName = QString("%1/full_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME); + fullScreen->save(fileName, "png"); + close(); +} + +void ScreenWidget::saveScreenOther() +{ + QString name = QString("%1.png").arg(STRDATETIME); + QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)"); + if (!fileName.endsWith(".png")) { + fileName += ".png"; + } + + if (fileName.length() > 0) { + int x = screen->getLeftUp().x(); + int y = screen->getLeftUp().y(); + int w = screen->getRightDown().x() - x; + int h = screen->getRightDown().y() - y; + fullScreen->copy(x, y, w, h).save(fileName, "png"); + close(); + } +} + +void ScreenWidget::saveFullOther() +{ + QString name = QString("%1.png").arg(STRDATETIME); + QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)"); + if (!fileName.endsWith(".png")) { + fileName += ".png"; + } + + if (fileName.length() > 0) { + fullScreen->save(fileName, "png"); + close(); + } +} + +void ScreenWidget::mouseMoveEvent(QMouseEvent *e) +{ + if (screen->getStatus() == Screen::SELECT) { + screen->setEnd(e->pos()); + } else if (screen->getStatus() == Screen::MOV) { + QPoint p(e->x() - movPos.x(), e->y() - movPos.y()); + screen->move(p); + movPos = e->pos(); + } + + this->update(); +} + +void ScreenWidget::mousePressEvent(QMouseEvent *e) +{ + int status = screen->getStatus(); + + if (status == Screen::SELECT) { + screen->setStart(e->pos()); + } else if (status == Screen::MOV) { + if (screen->isInArea(e->pos()) == false) { + screen->setStart(e->pos()); + screen->setStatus(Screen::SELECT); + } else { + movPos = e->pos(); + this->setCursor(Qt::SizeAllCursor); + } + } + + this->update(); +} + +void ScreenWidget::mouseReleaseEvent(QMouseEvent *) +{ + if (screen->getStatus() == Screen::SELECT) { + screen->setStatus(Screen::MOV); + } else if (screen->getStatus() == Screen::MOV) { + this->setCursor(Qt::ArrowCursor); + } +} + +void ScreenWidget::contextMenuEvent(QContextMenuEvent *) +{ + this->setCursor(Qt::ArrowCursor); + menu->exec(cursor().pos()); +} diff --git a/screenwidget/screenwidget.h b/screenwidget/screenwidget.h new file mode 100644 index 0000000..2f2744e --- /dev/null +++ b/screenwidget/screenwidget.h @@ -0,0 +1,90 @@ +#ifndef SCREENWIDGET_H +#define SCREENWIDGET_H + +/** + * 全局截屏控件 作者:feiyangqingyun(QQ:517216493) 2016-11-11 + * 1:支持鼠标右键选择菜单 + * 2:支持全局截屏和局部截屏 + * 3:支持图片另存为 + */ + +#include +#include +#include +#include + +class Screen +{ +public: + enum STATUS {SELECT, MOV, SET_W_H}; + Screen() {} + Screen(QSize size); + + void setStart(QPoint pos); + void setEnd(QPoint pos); + QPoint getStart(); + QPoint getEnd(); + + QPoint getLeftUp(); + QPoint getRightDown(); + + STATUS getStatus(); + void setStatus(STATUS status); + + int width(); + int height(); + bool isInArea(QPoint pos); // 检测pos是否在截图区域内 + void move(QPoint p); // 按 p 移动截图区域 + +private: + QPoint leftUpPos, rightDownPos; //记录 截图区域 左上角、右下角 + QPoint startPos, endPos; //记录 鼠标开始位置、结束位置 + int maxWidth, maxHeight; //记录屏幕大小 + STATUS status; //三个状态: 选择区域、移动区域、设置width height + + void cmpPoint(QPoint &s, QPoint &e);//比较两位置,判断左上角、右下角 +}; + +#ifdef quc +#if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) +#include +#else +#include +#endif + +class QDESIGNER_WIDGET_EXPORT ScreenWidget : public QWidget +#else +class ScreenWidget : public QWidget +#endif + +{ + Q_OBJECT +public: + static ScreenWidget *Instance(); + explicit ScreenWidget(QWidget *parent = 0); + +private: + static QScopedPointer self; + QMenu *menu; //右键菜单对象 + Screen *screen; //截屏对象 + QPixmap *fullScreen; //保存全屏图像 + QPixmap *bgScreen; //模糊背景图 + QPoint movPos; //坐标 + +protected: + void contextMenuEvent(QContextMenuEvent *); + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void paintEvent(QPaintEvent *); + void showEvent(QShowEvent *); + +private slots: + void saveScreen(); + void saveFullScreen(); + void saveScreenOther(); + void saveFullOther(); +}; + +#endif // SCREENWIDGET_H + diff --git a/screenwidget/screenwidget.pro b/screenwidget/screenwidget.pro new file mode 100644 index 0000000..10ebe50 --- /dev/null +++ b/screenwidget/screenwidget.pro @@ -0,0 +1,18 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-01-05T22:11:54 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = screenwidget +TEMPLATE = app +DESTDIR = $$PWD/../bin +CONFIG += warn_off + +SOURCES += main.cpp +SOURCES += screenwidget.cpp +HEADERS += screenwidget.h diff --git a/snap/screenwidget.gif b/snap/screenwidget.gif new file mode 100644 index 0000000..b45871a Binary files /dev/null and b/snap/screenwidget.gif differ