Qt 5中双监视器的截图捕获

时间:2016-04-21 15:55:06

标签: c++ qt

在Qt应用程序的上下文中,我使用以下代码片段截取完整桌面的屏幕截图:

QDesktopWidget* dw = QApplication::desktop();
QPixmap pixmap = QPixmap::grabWindow(dw->winId(), 0, 0,
                                     dw->width(), dw->height());
pixmap.save(name, "JPG", screenshot_quality);

这种方法在Linux和Windows中非常有效,并且具有双显示器,与屏幕分辨率无关;也就是说,如果两个显示器使用不同的分辨率,它仍然有效。但是,使用Qt 5,我得到以下运行时警告:

static QPixmap QPixmap::grabWindow(WId, int, int, int, int) is deprecated, use QScreen::grabWindow() instead. Defaulting to primary screen.

所以我回顾了Qt 5 doc并写了这篇文章:

QScreen * screen = QGuiApplication::primaryScreen();
QPixmap pixmap = screen->grabWindow(0);
pixmap.save(name, "JPG", screenshot_quality);

但这种方法无法捕获第二个屏幕。

所以我搜索了一下,根据这个帖子Taking Screenshot of Full Desktop with Qt5,我设计了截图截图如下:

QScreen * screen = QGuiApplication::primaryScreen();
QRect g = screen->geometry();
QPixmap pixmap = screen->grabWindow(0, g.x(), g.y(), g.width(), g.height());
pixmap.save(name, "JPG", screenshot_quality);

不幸的是,这也行不通。

引起我注意的是Qt 4的方法效果很好。因为我认为必须有一些方法可以在Qt 5中实现它。

所以,我的问题是如何用Qt 5完成?

编辑:这是我解决的方式:

QPixmap grabScreens()
{
  QList<QScreen*> screens = QGuiApplication::screens();
  QList<QPixmap> scrs;
  int w = 0, h = 0, p = 0;

  foreach (auto scr, screens)
    {
      QRect g = scr->geometry();
      QPixmap pix = scr->grabWindow(0, g.x(), g.y(), g.width(), g.height());
      w += pix.width();
      h = max(h, pix.height());
      scrs.append(pix);
    }

  QPixmap final(w, h);
  QPainter painter(&final);
  final.fill(Qt::black);
  foreach (auto scr, scrs)
    {
      painter.drawPixmap(QPoint(p, 0), scr);
      p += scr.width();
    }

  return final;
}

感谢@ddriver!

2 个答案:

答案 0 :(得分:4)

当然,QGuiApplication::primaryScreen()会为您提供一个屏幕。

您可以使用QList<QScreen *> QGuiApplication::screens()获取与应用程序关联的所有屏幕,为所有屏幕截取屏幕截图,然后创建另一个空白图像,根据您想要组成屏幕的方式调整大小,然后手动构建使用QPainter的最终图片。

QPixmap grabScreens() {
  auto screens = QGuiApplication::screens();
  QList<QPixmap> scrs;
  int w = 0, h = 0, p = 0;
  foreach (auto scr, screens) {
    QPixmap pix = scr->grabWindow(0);
    w += pix.width();
    if (h < pix.height()) h = pix.height();
    scrs << pix;
  }
  QPixmap final(w, h);
  QPainter painter(&final);
  final.fill(Qt::black);
  foreach (auto scr, scrs) {
    painter.drawPixmap(QPoint(p, 0), scr);
    p += scr.width();
  }
  return final;
}

答案 1 :(得分:1)

或者您可以使用虚拟几何(QScreen :: virtualGeometry())并用一行(或两行)代码捕获所有屏幕):

    public async Task<ActionResult> GetPopularContent(int Records, int? WorkareaRef, string Jurisdiction)
    {
        var model = new PopularContentModel();
        int? languageId = null;

        var login = new Login(HttpContext);
        var branding = new DynamicBranding(login);

        if (branding.BrandingDefaultLanguage != Cam.Service.ContentService.defaultLanguageId)
        {
            languageId = branding.BrandingDefaultLanguage;
        }

        languageId = languageId ?? ContentService.defaultLanguageId;
        var jurisdictionRef = string.IsNullOrEmpty(Jurisdiction) ? (int?)null : metaDataService.GetJurisdictionRefViaName(Jurisdiction);

        var reads24 = (await mostPopularContentService.MostPopularLast24HoursAsync(languageId.Value, WorkareaRef, jurisdictionRef, Records + 30)).ToDictionary(x=>x.Article, x=>x.Total);
        var reads7 = (await mostPopularContentService.MostPopularThisWeekAsync(languageId.Value, Records + 30)).ToDictionary(x => x.Article, x => x.Total);
        var readsShared = (await mostPopularContentService.MostSharedThisWeekAsync(languageId.Value, Records + 30)).ToDictionary(x => x.Article, x => x.Total);

        model.Read7DayDataSource = articleService.GetArticlesFromGuidList(reads7.Select(x=>x.Key), wcagOnly: branding.StrictlyWCAG2Accessible, useCache: true)
            .Select(x => new PopularArticle() { Article = x, ArticleGuid = x.ArticleGUID })
            .Where(x=> contentAdminTestingDataFilterService.AllowFirmAccess(x.Article.FirmRef, lexUser) && x.Article.RemoveDate == null)
            .OrderByDescending(x=> reads7[x.ArticleGuid])
            .Take(Records)
            .ToArray();
        model.Read24DataSource = articleService.GetArticlesFromGuidList(reads24.Select(x => x.Key), wcagOnly: branding.StrictlyWCAG2Accessible, useCache: true)
            .Select(x => new PopularArticle() { Article = x, ArticleGuid = x.ArticleGUID })
            .Where(x => contentAdminTestingDataFilterService.AllowFirmAccess(x.Article.FirmRef, lexUser) && x.Article.RemoveDate == null)
            .OrderByDescending(x => reads24[x.ArticleGuid])
            .Take(Records)
            .ToArray();
        model.SharedDataSource = articleService.GetArticlesFromGuidList(readsShared.Select(x => x.Key), wcagOnly: branding.StrictlyWCAG2Accessible, useCache: true)
            .Select(x => new PopularArticle() { Article = x, ArticleGuid = x.ArticleGUID })
            .Where(x => contentAdminTestingDataFilterService.AllowFirmAccess(x.Article.FirmRef, lexUser) && x.Article.RemoveDate == null)
            .OrderByDescending(x => readsShared[x.ArticleGuid])
            .Take(Records)
            .ToArray();

        model.LastUpdated = DateTime.Now.AddDays(-1).Date;

        DecorateFirmName(model);

        model.ShowSocialButtons = branding.ShowSocialButtons;

        return PartialView("PopularContentPartial", model);
    }