Как Qt перечисляет экраны? - PullRequest
0 голосов
/ 24 января 2019

Сегодня я обнаружил, что порядок, в котором Qt перечисляет экраны (QGuiApplication::screens), отличается от порядка в Windows (EnumDisplayMonitors).

Что такоелогика, лежащая в основе этого различия, чтобы учесть это при смешивании Windows API и Qt?Например, если требуется показать что-то на экране № 2 (с использованием перечисления Windows).

Здесь код, который я использовал для тестирования (также доступен в 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)

1 Ответ

0 голосов
/ 24 января 2019

Насколько я мог видеть в разных системах, EnumDisplayMonitors возвращает мониторы в порядке, определенном в настройках дисплея, в то время как QGuiApplication::screens всегда показывает основной экран в первой позиции (на самом деле, QGuiApplication::primaryScreen просто сделать это: вернуть первый элемент).

Глядя на исходный код, в Windows Qt также использует функцию EnumDisplayMonitors, но в основном перемещает основной экран в первую позицию (он фактически вставляет в первую позицию основной экран, вставляя в конце списка любой другой монитор).

Таким образом, основной экран будет на первой позиции, экраны с индексом ниже, чем у основного экрана, будут смещены на одну позицию, а остальные будут совпадать с индексом.


В качестве примечания, взятого из комментариев кода, если основной экран изменяется во время выполнения приложения, Qt не может сообщить об этом изменении.

Обратите внимание, что побочным эффектом этой политики является то, что невозможно изменить основной экран, о котором сообщает Qt, если только мы не хотим удалить все существующие экраны и добавить их снова при каждом изменении основного экрана.

...