最近一个Qt(C++)的项目需要用到截屏的功能,就花时间研究了一下如何实现。
Qt 确实是好用,截屏只需要下面三行代码就够了。
1 QDesktopWidget *desk = QApplication::desktop();2 QScreen * screen = QGuiApplication::primaryScreen();3 QPixmap p = screen->grabWindow(desk->winId());
这三行代码第一行是获取桌面的窗体对象。
第二行是获得一个 QScreen 对象。
第三行是截取屏幕上窗体对象所在区域的图像。
截取的结果是个QPixmap ,如果需要进一步处理的话,可以转化为 QIamge,一行代码就可以了。
QImage image = p.toImage();
原理就这么简单,但是我将这个代码封装了一下,将截屏功能封装成了一个 Camera。一次截屏操作就相当于相机拍一张照片。这样的好处是我这里有大量的相机图像处理的代码模块。将截屏封装成相机之后,就可以非常便捷的连接我的既有代码了。这种方法在设计模式中成为“适配器模式”。
下面是代码:
class ScreenCamera;/*** @brief The ScreenCameraInfo class 查询屏幕相机的信息的类* 用这个类可以查到当前计算机接了几个显示器,给出每个显示器的名称(deviceName)*/class ScreenCameraInfo{friend class ScreenCamera;public:explicit ScreenCameraInfo(QScreen * screen = nullptr);ScreenCameraInfo(const ScreenCameraInfo &info);/*** @brief description 没有实现,返回空字符串* @return 返回空字符串。*/QString description() const;/*** @brief deviceName 给出屏幕的名称,比如 "\\.\DISPLAY1", "VGA1" 一类的名称。* @return*/QString deviceName() const;bool isNull() const;bool operator!=(const ScreenCameraInfo &other) const;ScreenCameraInfo &operator=(const ScreenCameraInfo &other);bool operator==(const ScreenCameraInfo &other) const;static QListavailableCameras(); static ScreenCameraInfo defaultCamera();private:QScreen* m_screen;};/*** @brief The ScreenCamera class 将截屏功能封装成一个相机,可以像相机一样的操作。*/class ScreenCamera : public QThread{Q_OBJECTpublic:explicit ScreenCamera(QObject *parent = 0);explicit ScreenCamera(ScreenCameraInfo &info, QObject *parent = 0);/*** @brief openDevice 打开一个特定的截屏相机,当计算机连接了多个显示器时通过这个 info 指定截取某一个屏幕的图像* @param info* @return*/bool openDevice(const ScreenCameraInfo &info);/*** @brief setFrameRate 设置定时截屏的帧率。这里模仿相机的帧率设置。* @param fps frame per second 每秒的截屏数量。 [0.001 - 50]*/void setFrameRate(double fps);/*** @brief setRoi 设置感兴趣的区域,利用这个函数我们可以只截取屏幕的一部分区域* @param x 截屏区域的起始X坐标* @param y 截屏区域的起始Y坐标* @param width 截屏区域的宽度,-1 表示完整的屏幕宽度* @param height 截屏区域的高度,-1 表示完整的屏幕高度*/void setRoi(int x, int y, int width, int height);void run() override;/*** @brief capture 获取截屏图像* @return*/QImage capture();signals:/*** @brief imageChanged 定时截取图像时没截取一帧图像就激发一次这个信号* @param image*/void imageChanged(const QImage& image);public slots:/*** @brief start 开始图像采集*/void start();/*** @brief stop 停止图像采集*/void stop();private:int m_sleepInterval;QScreen* m_screen;int m_x;int m_y;int m_width;int m_height;};
ScreenCameraInfo::ScreenCameraInfo(const ScreenCameraInfo &info):m_screen(nullptr){m_screen = info.m_screen;}ScreenCameraInfo::ScreenCameraInfo(QScreen * screen):m_screen(nullptr){m_screen = screen;}bool ScreenCameraInfo::isNull() const{return (m_screen == nullptr);}QString ScreenCameraInfo::description() const{return "";}QString ScreenCameraInfo::deviceName() const{if(m_screen == nullptr) return "";return m_screen->name();}ScreenCameraInfo ScreenCameraInfo::defaultCamera(){QScreen * w = QGuiApplication::primaryScreen();return ScreenCameraInfo(w);}QListScreenCameraInfo::availableCameras() {QListlist = QGuiApplication::screens(); QListinfo; foreach (QScreen * s, list){ScreenCameraInfo i(s);info.append(i);}return info;}bool ScreenCameraInfo::operator!=(const ScreenCameraInfo &other) const{return (m_screen != other.m_screen);}ScreenCameraInfo & ScreenCameraInfo::operator=(const ScreenCameraInfo &other){m_screen = other.m_screen;return *this;}bool ScreenCameraInfo::operator==(const ScreenCameraInfo &other) const{return m_screen == other.m_screen;}ScreenCamera::ScreenCamera(ScreenCameraInfo &info, QObject *parent) : QThread(parent){m_screen = info.m_screen;m_sleepInterval = 500;m_x = 0;m_y = 0;m_width = -1;m_height = -1;}ScreenCamera::ScreenCamera(QObject *parent) : QThread(parent){m_screen = nullptr;m_sleepInterval = 500;m_x = 0;m_y = 0;m_width = -1;m_height = -1;}bool ScreenCamera::openDevice(const ScreenCameraInfo &info){m_screen = info.m_screen;return (m_screen);}void ScreenCamera::setFrameRate(double fps){fps = qBound(0.001, fps, 50.0);m_sleepInterval = 1000 / fps;}void ScreenCamera::setRoi(int x, int y, int width, int height){if(m_screen){QRect rect = m_screen->geometry();m_x = qBound(0, x, rect.width());m_y = qBound(0, y, rect.height());m_width = qBound(-1, width, rect.width());m_height = qBound(-1, height, rect.height());}}void ScreenCamera::run(){while(1){if(m_screen){QDesktopWidget *desk = QApplication::desktop();//qDebug() << "m_width = " << m_width;//qDebug() << "m_height = " << m_height;QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);QImage image = p.toImage();emit imageChanged(image);}msleep(m_sleepInterval);}}QImage ScreenCamera::capture(){if(m_screen){QDesktopWidget *desk = QApplication::desktop();QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);QImage image = p.toImage();return image;}return QImage();}void ScreenCamera::stop(){terminate();}void ScreenCamera::start(){QThread::start(QThread::InheritPriority);}
用法很简答,下面给个代码片段:
ScreenCameraInfo info = ScreenCameraInfo::defaultCamera();qDebug() << info.deviceName();m_screenCamera = new ScreenCamera(info);connect(m_screenCamera, SIGNAL(imageChanged(QImage)), m_cameraImage, SLOT(setImage(QImage)));m_screenCamera->setRoi(0, 0, 500, 500);m_screenCamera->start();

推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……




还没有评论,来说两句吧...