带有 OpenGL 的 Qt MDI 应用程序:如何获取有效的屏幕截图?

发布于 2024-08-03 06:21:21 字数 1567 浏览 9 评论 0 原文

我有一个用 Qt 编写的 MDI 应用程序。一些子窗口包括 QGLWidget,即 OpenGL 上下文。其中最突出的是使用 OpenGL 顶点和片段着色器来可视化其数据。

我需要以编程方式捕获应用程序主窗口的屏幕截图,当然包括所有恰好可见的子窗口。乍一听起来很简单(“肯定被问过很多次了,所以让我们用谷歌搜索一下!”),但仔细一看,似乎变得有点棘手......

现在这是我迄今为止尝试过的:

  1. QPixmap::grabWidget 不适用于以下子窗口使用着色器程序,显然是因为重定向上下文似乎不支持必要的 OpenGL 扩展。 (渲染代码检查关联的上下文是否支持所需的扩展,如果不支持则拒绝继续。)
  2. QPixmap::grabWindow 默默地将所有 OpenGL 上下文留空——即使是那些仅使用基本基元的上下文。
  3. QGLWidget::grabFrameBuffer 有效,但仅捕获特定子窗口的 OpenGL 上下文,而我想获取整个应用程序(本质上是 Alt+PrtScr 在 Windows 中所做的事情)。

我还尝试先执行#2,然后对所有子窗口迭代#3,只需将#3 的结果复制到#2 图像的正确位置。这种方法效果很好,直到我让一些子窗口重叠——在这种情况下,#3 中的图像会覆盖子窗口框架等。因此,这种方法可能需要更多的代码才能处理所有令人讨厌的极端情况...

一些附加背景:一旦获得屏幕截图,我将把其中的几个放在一个序列中以创建视频 - 可能使用 我之前的问题;只是该应用程序已从单上下文独立 OpenGL 程序发展为使用 Qt 进行整体窗口和 UI 小部件内容,并将图形嵌入子窗口中的程序。

虽然我当然更喜欢一个漂亮的、类似 Qt 的跨平台解决方案,但我也愿意考虑诉诸 Windows 特定的 hack。 (这应该是可能的,因为我可以看到 Alt+PrtScr 做了非常正确的事情。)

那么,有什么建议吗?

I have an MDI app written in Qt. Some of the subwindows include QGLWidgets, i.e., OpenGL contexts. The most salient of these use OpenGL vertex and fragment shaders to visualize their data.

I need to programmatically capture a screenshot of the application's main window, including of course all the subwindows that happen to be visible. Sounds easy at first ("definitely been asked many times, so let's just google it!"), but after a closer look it seems to be getting a bit tricky...

Now here's what I've tried so far:

  1. QPixmap::grabWidget doesn't work for the subwindows that use shader programs, apparently because the redirection context does not seem to support the necessary OpenGL extensions. (The rendering code checks that the associated context supports the required extensions, and refuses to continue if not.)
  2. QPixmap::grabWindow silently leaves all OpenGL contexts empty -- even those that use basic primitives only.
  3. QGLWidget::grabFrameBuffer works, but captures only the OpenGL context of the specific subwindow, whereas I'd like to grab the whole application (essentially what Alt+PrtScr does in Windows).

I also tried doing first #2 and then iterating #3 for all subwindows, just copying the result of #3 into the right location of the image from #2. This worked very well, until I made some subwindows overlap -- in which case the images from #3 overwrite the subwindow frames, etc. So this approach would probably require much more code in order to handle all the nasty corner cases...

Some additional background: Once I get the screenshot, I'm going to put several of them in a seqence in order to create a video -- probably using ffmpeg. That makes this question a kind of continuation to (the first part of) my previous question; it's just that the app has evolved from a single-context standalone OpenGL program to something that uses Qt for the overall windowing and UI widget stuff, and embeds the graphics in subwindows.

While I would of course prefer a nice, Qt-ish cross-platform solution, I'm willing to consider resorting to a Windows-specific hack, too. (Which ought to be possible, as I can see Alt+PrtScr doing very much the right thing.)

So, any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

还给你自由 2024-08-10 06:21:21

非常黑客,但确实捕获桌面(不隐藏窗口),就像本教程 并裁剪除窗口工作之外的所有内容?

更一般地说,我什至不确定 OpenGL 规范是否要求输出必须放置在前缓冲区中:实现可以仅使用视频覆盖(或 Voodoo2 式 VGA 直通恶作剧)进行输出。

Very hackish, but does capturing the desktop (without hiding your window) like in this tutorial and cropping everything but your window work?

More generally, I'm not even sure that the OpenGL spec demands that output has to be placed in the front buffer: an implementation could just use video overlays (or Voodoo2-esque VGA pass-through shenanigans) for output.

も星光 2024-08-10 06:21:21

我唯一能想到的就是执行以下伪代码:

 for each window
     grab the window into its own pixmap
     grab the GL portions and paste into the windows
 order the window pixmaps by depth of the window (deepest first)
 initialize a common pixmap
 for each window pixmap
     paint the window pixmap into the common pixmap at the appropriate location.

The only thing I can think of off-hand is to do the following psuedocode:

 for each window
     grab the window into its own pixmap
     grab the GL portions and paste into the windows
 order the window pixmaps by depth of the window (deepest first)
 initialize a common pixmap
 for each window pixmap
     paint the window pixmap into the common pixmap at the appropriate location.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文