Qt如何枚举屏幕?

How does Qt enumerate screens?

今天发现Qt枚举屏幕的顺序(QGuiApplication::screens) differs from the order in Windows (EnumDisplayMonitors)。

这种差异背后的逻辑是什么,以便在混合 Windows API 和 Qt 时将其考虑在内?例如,如果需要在屏幕 #2 中显示某些内容(使用 Windows 枚举)。

这里是我用来测试的代码(也可用in GitHub):

#include <qapplication.h>
#include <qdebug.h>
#include <qscreen.h>
#include <Windows.h>
#include <iostream>

std::ostream& operator<<(std::ostream& of, const RECT& rect)
{
  return of << "RECT(" << rect.left << ", " << rect.top << " " << (rect.right - rect.left) << "x" << (rect.bottom - rect.top) << ")";
}

BOOL CALLBACK printMonitorInfoByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
  auto index = (int*)dwData;
  std::cout << ++*index << " " << *lprcMonitor << std::endl;
  return TRUE;
}

int main(int argc, char* argv[])
{
  QApplication a(argc, argv);

  qDebug() << "*** Qt screens ***";
  const auto screens = qApp->screens();
  for (int ii = 0; ii < screens.count(); ++ii) {
    qDebug() << ii + 1 << screens[ii]->geometry();
  }

  qDebug() << "*** Windows monitors ***";
  int index = 0;
  EnumDisplayMonitors(NULL, NULL, printMonitorInfoByHandle, (LPARAM)&index);

  return 0;
}

我的显示器配置是,从左到右,2 (1280x1024),3 (1920x1080),1 (1920x1080),作为我的主屏幕 3.

结果:

*** Qt screens ***
1 QRect(0,0 1920x1080)
2 QRect(1920,233 1920x1080)
3 QRect(-1280,47 1280x1024)
*** Windows monitors ***
1 RECT(1920, 233 1920x1080)
2 RECT(-1280, 47 1280x1024)
3 RECT(0, 0 1920x1080)

据我在不同系统中所见,EnumDisplayMonitors returns 显示器按照显示设置中定义的顺序显示,而 QGuiApplication::screens 始终显示主屏幕在第一个位置(实际上,QGuiApplication::primaryScreen 只需这样做:return 第一个元素)。

查看源代码,在 Windows Qt 中也使用了 EnumDisplayMonitors 函数,但基本上将主屏幕移动到第一个位置(它实际上将主屏幕插入到第一个位置,而在列表末尾插入任何其他监视器)。

因此,主屏幕将在第一个位置,索引低于主屏幕的屏幕将移动一个位置,而其余屏幕将与索引匹配。


作为旁注,从代码的注释中获取,如果主屏幕在应用程序执行期间发生更改,Qt 无法报告更改。

Note that the side effect of this policy is that there is no way to change primary screen reported by Qt, unless we want to delete all existing screens and add them again whenever primary screen changes.