Захват рабочего стола с нескольких экранов с использованием Qt4 - PullRequest
6 голосов
/ 19 октября 2010

Я пишу приложение для захвата экрана в Qt4 с помощью C ++.У меня проблема при настройке на двух экранах.Я не могу получить изображение со второго экрана.Я попробовал приложение ac #, и оно будет захватывать все рабочие столы в одном изображении, и я мог извлечь из него каждое изображение рабочего стола экрана.Вот код 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 или функцией, используя тот же дескриптор окна, он повторяет только первый рабочий стол, хотя фактически рабочий стол ретранслируется из двух экранов.Одна идея состоит в том, чтобы использовать собственные вызовы Windows и сохранить изображение во временном файле и загрузить оттуда QPixmap, но это не так просто - сохранить HBITMAP в файле на C ++ без MFC.Вывод: что вы думаете об ошибке в Qt?Любая идея, как обойти это (без MFC)

Ответы [ 4 ]

4 голосов
/ 19 октября 2010

вы можете считать экраны с помощью QDesktopWidget::screenCount() (Qt 4.6), а затем перемещаться по всем экранам и делать QPixmap::grabWindow(...)

О «рабочем столе, составленном из 2 экранов». Все зависит от того, виртуальный ли экран 2 (все экраны обрабатываются как один экран) или нет.

@ Frerich Raabe: он работает в Windows 7, так как я использую похожий код для захвата экрана.

3 голосов
/ 19 октября 2010

Я недавно заметил ту же проблему.

В конце концов я решил отказаться от Qt для снятия скриншотов.Другая ситуация, в которой Qt ломается, - это использование темы Aero в Windows Vista или Windows 7. Эта тема, по-видимому, отображает все данные в фоновый буфер, поэтому все снимки экрана, сделанные Qt, являются черными.

Вместо использования QtЯ могу рекомендовать использовать класс ScreenShooter, как описано в http://www.apriorit.com/our-experience/articles/9-sd-articles/193-multi-monitor-screenshot

2 голосов
/ 16 мая 2012

При использовании виртуального рабочего стола метод QPixmap::grabWindow, похоже, возвращает скриншот с размером основного экрана.Передача размеров полного виртуального рабочего стола возвращает скриншот обоих мониторов;

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

Еще предстоит проверить это поведение на Unix / Mac, но он работает под Windows 7.

0 голосов
/ 26 октября 2012

При установке нескольких мониторов в Windows мониторы обычно объединяются в виртуальный рабочий стол.Я говорю «обычно», потому что я не совсем уверен, что происходит во всех версиях Windows от XP SP0 (25 октября 2001 г.) до Win8 SP0 (26 октября 2012 г.).Но для виртуального рабочего стола это означает, что 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.

...