【问题标题】:QPixmap doesn't grab web browser windowQPixmap 不抓取网络浏览器窗口
【发布时间】:2017-07-09 16:15:31
【问题描述】:

当我在网络浏览器窗口中使用QPixmap::GrabWindow(WId) 时,它只返回黑屏。

我正在使用以下代码:

QScreen *screen = QGuiApplication::primaryScreen();
m_pixmap = screen->grabWindow(hW);
m_image = m_pixmap.toImage();
m_image.save("p.png");

当我打开“p.png”时,它只是黑色的图片。对于其他窗口,这很好用。

如何才能正常浏览浏览器画面?

【问题讨论】:

  • 什么是hW? :P
  • @eyllanesc 这是窗口的WId

标签: c++ qt qimage qpixmap screen-grab


【解决方案1】:

事实上,QScreen::grabWindow 使用Windows GDI 来捕获图像。这是一个相当古老的 API,由没有硬件加速(由处理器绘制)的程序使用。还有chrome——这个软件并不古老,早就用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”——微软编译器特性:必要的库会在编译时自行拉起(查看framecapturer.h)

【讨论】:

    猜你喜欢
    • 2016-11-29
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2016-09-11
    • 2012-10-30
    相关资源
    最近更新 更多