【问题标题】:Capture multiple screens desktop image using Qt4使用 Qt4 捕获多屏幕桌面图像
【发布时间】:2011-04-27 08:33:16
【问题描述】:

我正在使用 C++ 在 Qt4 中编写屏幕捕获应用程序。我在调整双屏时遇到问题。我无法使用第二个屏幕获取图像。我尝试了一个 c# 应用程序,它将在一个图像中抓取所有桌面,我可以从那里提取每个屏幕桌面图像。 这是c#代码

    using System;
using System.Drawing;
using System.Runtime.InteropServices;

public class TestGrab
{
  [STAThread]
  static void Main(string[] args)
  {
    IntPtr hDC = WindowsNative.GetDC(WindowsNative.GetDesktopWindow());
    IntPtr hBitmap = WindowsNative.GetCurrentObject(hDC,
    WindowsNative.OBJ_BITMAP);
    System.Drawing.Bitmap imageDesktop = System.Drawing.Image.FromHbitmap(
    hBitmap);
    imageDesktop.Save(@"c:\zzzzdesktop.png");
  }
}

public class WindowsNative
{
  [DllImport("user32.dll")]
  public static extern IntPtr GetDesktopWindow();

  [DllImport("user32.dll")]
  public static extern IntPtr GetDC(IntPtr ptr);

  public const int OBJ_BITMAP = 7;
  [DllImport("gdi32.dll")]
  public static extern IntPtr GetCurrentObject(IntPtr hdc, uint
  uiObjectType);
}

Qt 代码更小,我还测试了桌面的本机窗口句柄是否与 Qt desktop0>winId() 不同,但它们是相等的

QPixmap CaptureWinDesktop()
{
    WId desktop=GetDesktopWindow();
    WId desktop2=QApplication::desktop()->winId();
    if(desktop!=desktop2)
    {
        qDebug("sunt fdiferite WId");
    }
     QPixmap entireDesktop= QPixmap::grabWindow(desktop);
     return entireDesktop;
}

我不确定这是 Qt 中的错误还是功能,使用相同的窗口句柄它只重试第一个桌面,而实际上它是由 2 个屏幕组成的桌面。一个想法是使用本地 Windows 调用并将图像保存在临时文件中并从那里加载 QPixmap,但是在没有 MFC 的 c++ 文件中保存 HBITMAP 并不简单。 结论:您认为 Qt 中的错误是什么?知道如何解决它(没有 MFC)

【问题讨论】:

标签: qt screen-capture multiple-monitors


【解决方案1】:

您可以使用 QDesktopWidget::screenCount() (Qt 4.6) 计算屏幕数,然后遍历所有屏幕并执行 QPixmap::grabWindow(...)

关于“由 2 个屏幕组成的桌面”。这完全取决于 2 个屏幕是否是虚拟的(所有屏幕都视为一个屏幕)。

@Frerich Raabe:它适用于 Windows 7,因为我正在使用类似的代码来执行屏幕抓取。

【讨论】:

  • :grabWindow(...) 将为我返回第一个屏幕,即使我使用第二个屏幕。你确定它可以在双显示器上工作吗?
  • 我最近正在实现抓取屏幕功能,是的,它运行良好。您使用的是什么版本的 Qt?
  • 我在 Windows XP sp3 上使用 4.6.3,我设置了双显示器,我总是只看到第一个屏幕,我尝试了所有可能性,我不喜欢使用 win APIDS
  • 我安装了 atest SDK,我也遇到了同样的问题。
  • 哦,我还没有在 Windows XP 上测试它,因为我们不确定我们是否会支持它。我写道它适用于 Windows 7(也适用于 vista)。如果我有可能,我会在 Windows XP 上测试它
【解决方案2】:

我最近注意到了同样的问题。

我最终决定放弃 Qt 来截取屏幕截图。 Qt 中断的另一种情况是在使用 Windows Vista 或 Windows 7 的 Aero 主题时。这个主题显然将所有数据渲染到背景缓冲区中,因此 Qt 截取的所有屏幕截图都是黑色的。

我可以推荐使用 ScreenShooter 类,而不是使用 Qt,如 http://www.apriorit.com/our-experience/articles/9-sd-articles/193-multi-monitor-screenshot 中所述

【讨论】:

  • 谢谢,这可以省去我处理所有 HDC、RECT HBITMAP 和其他复杂结构的麻烦
  • 如果您的应用程序是开源的,我想查看代码,在我看来,您链接的屏幕截图应用程序使用了 MFC atlimage.h
【解决方案3】:

对于虚拟桌面,QPixmap::grabWindow 方法似乎返回了主屏幕大小的屏幕截图。传入完整虚拟桌面的尺寸会返回两个显示器的屏幕截图;

  QDesktopWidget *desktop = QApplication::desktop();
  QPixmap screenshot = QPixmap::grabWindow(desktop->winId(), 0, 0, desktop->width(), desktop->height());

尚未在 Unix / Mac 机器上测试此行为,但它可以在 Windows 7 下运行。

【讨论】:

  • 在我的 Ubuntu 10.10 上像魅力一样工作!非常感谢你给我指路。
【解决方案4】:

在 Windows 上的多显示器设置中,显示器通常连接到虚拟桌面。我说“通常”是因为我不完全确定从 XP SP0(2001 年 10 月 25 日)到 Win8 SP0(2012 年 10 月 26 日)的所有 Windows 版本会发生什么。但是,作为虚拟桌面,这意味着screen(x) 将始终返回相同的小部件;据我所见,这是唯一的 QDesktopWidget 本身。但是,screenGeometry(x) 将为每个枚举监视器返回不同的值。

您可以通过使用screenGeometry(x) 的结果作为QPixmap::grabWindow 的参数来抓取第二个屏幕;即:

QDesktopWidget* desktop = QApplication::desktop();
WId wid = desktop->winId();
QRect geo = desktop->screenGeometry(indexOfTheMonitorYouWant);
QPixmap cap = QPixmap::grabWindow(wid, geo.left(), geo.top(), geo.width(), geo.height());

这对我来说很有效,我即将把构建交给我的 QA 团队。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 2013-08-03
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多