当我在网页浏览器窗口中使用QPixmap::GrabWindow(WId)
时,它只返回黑屏。
我正在使用以下代码:
QScreen *screen = QGuiApplication::primaryScreen();
m_pixmap = screen->grabWindow(hW);
m_image = m_pixmap.toImage();
m_image.save("p.png");
当我打开“p.png”时,它只是黑色图片。与其他窗户一起使用效果很好。
如何使用正常的浏览器屏幕?
事实是QScreen :: grabWindow使用Windows GDI来捕获图像。这是一个相当古老的API,程序在没有硬件加速的情况下使用(由处理器绘制)。而铬 - 这个软件并不古老,并且长期以来都是通过Windows DXGI绘制的。
我已经编写了使用这种技术的软件。发布了示例代码here。它将由Qt 5.10库上的MSVC编译器编译,看起来没有差别,2015年或2017年。我的机器是64位,也许这也很重要。
里面有两个类:FrameBroadcast和FrameCapturer。 FrameBroadcast从FrameCapturer请求具有特定时间间隔的屏幕截图,并通过信号void frameCaptured (QSharedPointer <Frame> frame);
发送订户QSharedPointer一旦超出所有插槽处理程序的范围,就会自动删除为屏幕内容分配的内存。
#include <QApplication>
#include <QObject>
#include <QPixmap>
#include <QImage>
#include <QDialog>
#include <QLabel>
#include "framebroadcast.h"
/*static Frame* CopyFrame(const Frame *incomingFrame)
{
Frame *frame = new Frame();
frame->width=incomingFrame->width;
frame->height=incomingFrame->height;
frame->lenght=incomingFrame->lenght;
frame->buffer=new unsigned char[frame->lenght];
std::memcpy(frame->buffer,incomingFrame->buffer,frame->lenght);
return frame;
}
static Frame* CopyFrame(const QSharedPointer<Frame> &incomingFrame)
{
return CopyFrame(incomingFrame.data());
}*/
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDialog *dialog = new QDialog();
QLabel *label = new QLabel(dialog);
FrameBroadcast *cast = new FrameBroadcast();
QObject::connect(cast, &FrameBroadcast::frameCaptured, [=](const QSharedPointer<Frame> &frame) {
int w = static_cast<int>(frame.data()->width);
int h = static_cast<int>(frame.data()->height);
QImage img(frame.data()->buffer,w,h,QImage::Format_RGBA8888);
label->setPixmap(QPixmap::fromImage(img));
label->resize(w,h);
qDebug() << "Update";
});
cast->startCapture();
dialog->show();
return app.exec();
}
在main.cpp中,创建一个简单的对话框,显示捕获的结果。为了以防万一,如果无法将所有操作放在一个插槽中,我会附加一个代码来解开QSharedPointer中屏幕内容的代码。它是在夹杂物之后立即评论出来的。
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"D3D11.lib")
#pragma comment(lib,"Shcore.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"windowscodecs.lib")
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "dxguid.lib")
仔细解析代码是没有意义的。它太大了,但根据您的需求进行重组并不困难。值得注意的是,使用了“Auto-linking” - Microsoft编译器功能:必要的库将在编译时自行启动(在framecapturer.h中查看)