使用Qt4捕获多个屏幕桌面图像

时间:2010-10-19 08:19:44

标签: qt screen-capture multiple-monitors

我正在使用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的情况下将HBITMAP保存在c ++文件中并不简单。 结论:您认为Qt中的错误是什么?任何想法如何解决它(没有MFC)

4 个答案:

答案 0 :(得分:4)

您可以使用QDesktopWidget::screenCount()(Qt 4.6)统计屏幕,然后浏览所有屏幕并执行QPixmap::grabWindow(...)

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

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

答案 1 :(得分:3)

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

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

我可以建议使用http://www.apriorit.com/our-experience/articles/9-sd-articles/193-multi-monitor-screenshot

中描述的ScreenShooter类,而不是使用Qt。

答案 2 :(得分:2)

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

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

然而,要在Unix / Mac盒子上测试这种行为,但它可以在Windows 7下运行。

答案 3 :(得分:0)

在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团队。