Нумерация мониторов на компьютере

Я нашел 7 различных способов перечислить мониторы, подключенные к компьютеру. Но все решения дают разные результаты (количество мониторов и информация на каждом мониторе).

Вот эти решения:

  1. Используя знаменитый EnumDisplayDevices

  2. Использование EnumDisplayMonitors

  3. Использование инструментария управления Windows (WMI):
    С помощью следующего запроса: SELECT * FROM WmiMonitorID в пространстве имен root\\WMI.

  4. Снова используя WMI < / em>:
    С новым запросом: SELECT * FROM Win32_DesktopMonitor в пространстве имен root\\CIMV2.

  5. Использование Setup API < / em>:
    Первым вызовом _ 7_, чтобы затем получить набор информации об устройстве, итеративно с _ 8_

  6. Использование графической инфраструктуры DirectX (DXGI)
    С первым _ 9_, затем _ 10_

  7. Использование Подключение и настройка API дисплеев (CCD):
    _ 11_ (QDC_ALL_PATHS, &numPathArrayElements, pathInfoArray, &numModeInfoArrayElements, modeInfoArray, nullptr);

Я тщетно пытался понять разницу между всеми этими методами со ссылкой на MSDN.

Наблюдения

Из того, что я заметил:

  • Запросы WmiMonitorID и Setup API возвращают список подключенных (не обязательно активных) дисплеев.
  • Запрос Win32_DesktopMonitor WMI возвращает неправильный (по крайней мере, неожиданный) результат (перечисляется только 1 монитор, даже когда он неактивен, а рабочий стол - на другом мониторе).
  • EnumDisplayDevices возвращает список активных устройств (кроме случаев, когда активен только 1 монитор с другим подключенным монитором)
  • Запросы EnumDisplayMonitors и DXGI возвращают список активных мониторов.
  • CCD кажется наиболее надежным методом (дает все возможные пути между целями и источниками).

Вопросы

Какого результата следует ожидать при использовании каждого из этих методов (список подключенных дисплеев, список установленных дисплеев, список активных дисплеев)? Что делать, если я использую зеркальные дисплеи или расширенные дисплеи? Что делать, если в компьютере есть несколько видеокарт без нескольких выходов?

Бонус: некоторые методы (DXGI, EnumDisplayDevices, CCD) используют своего рода иерархию с Adapter - Монитор. Но не дает одинаковых связей между адаптерами и мониторами. Итак, каково определение адаптера для DXGI? для CCD? для EnumDisplayDevices?


person Cédric Bignon    schedule 02.08.2013    source источник
comment
Я полагаю, уловка здесь будет заключаться в том, чтобы узнать, вызывают ли все они один и тот же API самого низкого уровня и используют ли он   -  person paulm    schedule 12.08.2013
comment
Я думаю, что правильнее всего задать более точный вопрос, например, «Как перечислить X при выполнении Y?», Где X - это монитор, физическое устройство, логическое устройство и т. Д., А Y - ваша цель. Наличие вашей цели, безусловно, позволит вам отфильтровать некоторые возможности. Как показывает ваше (глубокое и очень точное) исследование, все не так просто, как вы думали заранее, и невозможно ответить, используя такие слова, как монитор и компьютер.   -  person    schedule 12.08.2013
comment
@Cedric Bignon Я не использую Windows, но почему бы вам не написать тестовый код, который использует все, что использует каждый из этих методов, возможно, в отдельных файлах, а затем дизассемблировать двоичные файлы, чтобы увидеть, делают ли они одни и те же системные вызовы ?   -  person Charles Addis    schedule 13.08.2013
comment
Я второй @tibo. Ваш вопрос слишком открытый. Добавьте к этому, что есть также различия от одной версии Windows к другой (некоторые DXGI только для Windows 8 и т. Д.). Одно наблюдение, которое может быть полезным: платформа .NET (которую можно рассматривать как слой абстракции над Windows) определяет класс Screen (System.Windows.Forms.Screen), который полностью основан на EnumDisplayMonitors / GetMonitorInfo (он сообщает устройству название).   -  person Simon Mourier    schedule 13.08.2013
comment
есть еще один: GetSystemMetrics(SM_CMONITORS) считает только видимые мониторы. Это отличается от EnumDisplayMonitors, который перечисляет как видимые дисплеи, так и невидимые псевдо-мониторы, связанные с драйверами зеркалирования. Невидимый псевдо-монитор связан с псевдоустройством, используемым для зеркального отображения рисунка приложения для удаленного взаимодействия или других целей.   -  person mikew    schedule 10.03.2021


Ответы (2)


Я не знаю всех этих API, но я помню некоторые из них (плохие воспоминания), так что вот что я могу вспомнить и найти, копаясь в MSDN и играя с wbemtest, который, к моему удивлению, я даже помню. Я понимаю, что это, вероятно, не ВСЕ, на которое вы надеялись.

Для иллюстраций ниже (и все эти иллюстрации находятся на моем ноутбуке Dell Latitude, на котором я печатаю это вам, и, по логике, у меня есть два монитора, подключенных к нему через док-станцию). Но ноутбук закрыт, поэтому экран ноутбука не виден.

Если я захожу в свойства дисплея, я вижу только один экран.

введите описание изображения здесь

Подключен к CIMv2

select * from Win32_DesktopMonitor;

возвращает два экземпляра.

введите описание изображения здесь

DesktopMonitor1 - это внешний дисплей (GenericPNPDisplay), а DesktopMonitor1 - это монитор (экран) по умолчанию.

Подключен к root \ WMI

select * from WMIMonitorID;

дает мне только один экземпляр, и этот экземпляр является внешним монитором (я знаю это, потому что имя производителя - HP). (HWP26CE - это идентификатор для HP w2408, см.

Кроме того, есть разница между видеоадаптерами и мониторами. EnumDisplayDevices показывает адаптеры, а EnumDisplayMonitors показывает мониторы. Первый предназначен в первую очередь для того, чтобы просто перечислить адаптеры, но второй позволяет вам предоставить прямоугольник отсечения и определить, на каких мониторах этот прямоугольник отсечения попадает. Это становится полезным, когда у вас есть несколько активных мониторов, и кто-то решает сделать что-то, что вызывает ничью, которая будет охватывать несколько мониторов. Вы можете указать обратный вызов для EnumDisplayMonitors, и этот обратный вызов будет вызываться с некоторыми параметрами (если память мне не изменяет, один из параметров был подмножеством указанного прямоугольника отсечения, который попадает на указанный монитор).

Я смутно помню SetupDiEnumDeviceInfo, и я думаю, что он дает вам HDEVINFO для каждого интерфейса и поэтому (я полагаю) предоставит вам только одну запись в моей конфигурации, потому что у меня только один адаптер. Тогда тебе придется что-то делать, чтобы получить SP_DEVINFO_DATA.

Я никогда не использовал DirectX и другие API, так что молчу об этих двух. Надеюсь, кто-нибудь еще расскажет об этих двоих, и вы получите исчерпывающий ответ!

person amrith    schedule 15.08.2013

Если это актуально в вашем случае, при использовании Qt 5.x вы можете использовать метод QGuiApplication::screens() (http://qt-project.org/doc/qt-5.1/qtgui/qguiapplication.html#screen), чтобы перечислить все дисплеи.

Или, если это не актуально, вы всегда можете посмотреть их исходный код, как они перечисляют дисплеи и получают все соответствующие свойства (в том числе в отношении зеркалирования, расширенных рабочих столов и т. Д.).

person Kurt Pattyn    schedule 14.08.2013