2015-04-02 5 views
1

Предположим, у меня есть 3 монитора. Как получить дескриптор второго только по его индексу? EnumDisplayMonitors() не будет работать, потому что он также перечисляет псевдоустройства, а EnumDisplayDevices() не дает мне дескриптора.получить ручку (реального) монитора по его индексу

+0

Как насчет 'MonitorFromRect',' MonitorFromPoint' или 'MonitorFromWindow'? Будет ли кто-нибудь из них работать на вас? Все они возвращают «ГМОНИТОР». –

+0

К сожалению нет, мне нужен индекс – Grisu47

ответ

2

Для доступа к дескриптору HMONITOR для каждого монитора необходимо использовать EnumDisplayMonitors() вместо EnumDisplayDevices().

Однако мониторы не идентифицируются по индексу. GetMonitorInfo() может сказать вам, какой монитор «первичный», но это все. Нет никакого способа узнать, какой монитор «второй», «третий» и т. Д. И вы не можете использовать местоположения монитора, чтобы определить это, так как «второй» монитор можно было бы расположить в любом месте по отношению к «первичному», монитор, а затем «третий» монитор можно расположить в любом месте по отношению к «первому» или «второму» монитору.

Таким образом, вы должны надеяться, что EnumDisplayMonitors() перечисляется в порядке, что мониторы установлены, то вы можете сделать что-то вроде этого:

struct sEnumInfo 
{ 
    int iIndex; 
    HMONITOR hMonitor; 
}; 

BOOL CALLBACK GetMonitorByIndex(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) 
{ 
    sEnumInfo *info = (sEnumInfo*) dwData; 
    if (--info->iIndex < 0) 
    { 
     info->hMonitor = hMonitor; 
     return FALSE; 
    } 
    return TRUE; 
} 

sEnumInfo info; 
info.index = 1; 
info.hMonitor = NULL; 

EnumDisplayMonitors(NULL, NULL, GetMonitorByIndex, (LPARAM)&info); 
if (info->hMonitor != NULL) 
{ 
    //... 
} 
0

Вы можете перечислить устройства с EnumDisplayMonitors() и проверьте, является ли он псевдомонитором с EnumDisplayDevices()

Во время повторного просмотра через мониторы с использованием GetMonitorInfo() вы можете получить MONITORINFOEX с именем устройства монитора.

Затем с помощью EnumDisplayDevices() вы можете получить DISPLAY_DEVICE, который содержит StateFlags с информацией, если текущий монитор является псевдо-монитор (или, как в случае, если пыльник крепится к рабочему столу)

BOOL DispayEnumeratorProc(_In_ HMONITOR hMonitor, _In_ HDC hdcMonitor, _In_ LPRECT lprcMonitor, _In_ LPARAM dwData) 
{ 
    TClass* self = (TClass*)dwData; 
    if (self == nullptr) 
     return FALSE; 

    MONITORINFOEX monitorInfo; 
    ::ZeroMemory(&monitorInfo, sizeof(monitorInfo)); 
    monitorInfo.cbSize = sizeof(monitorInfo); 

    BOOL res = ::GetMonitorInfo(hMonitor, &monitorInfo); 
    if (res == FALSE) 
     return TRUE; 

    DISPLAY_DEVICE displayDevice; 
    ::ZeroMemory(&displayDevice, sizeof(displayDevice)); 
    displayDevice.cb = sizeof(displayDevice); 

    res = ::EnumDisplayDevices(monitorInfo.szDevice, 0, &displayDevice, 0); 
    if (res == FALSE) 
     return TRUE; 

    if (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) 
     self->RegisterDisplay(monitorInfo); 

    return TRUE; 
} 

void TClass::EnumerateDisplayMonitors() 
{ 
    BOOL res = ::EnumDisplayMonitors(NULL, NULL, &DispayEnumeratorProc, (LPARAM)this); 
    if (res == FALSE) 
     Print("Failed"); 
} 

Также вы можете сортировать мониторы перебирая EnumDisplayDevices()

Если вы передадите NULL в качестве первого параметра в EnumDisplayDevices(), он вернет информацию об адаптере на основе второго параметра. В этом случае ваши устройства будут определять порядок.

Вы можете сравнить DeviceName из DISPLAY_DEVICE с szDevice из MONITORINFOEX, хранящихся до того, чтобы отсортировать HMONITORs

void TClass::SortDisplayMonitors() 
{ 
    DISPLAY_DEVICE displayDevice; 
    ::ZeroMemory(&displayDevice, sizeof(displayDevice)); 
    displayDevice.cb = sizeof(displayDevice); 

    std::map<std::string, DWORD> devices; 
    for (DWORD iDevNum = 0; ::EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0) != FALSE; ++iDevNum) 
     devices.insert({displayDevice.DeviceName, iDevNum}); 

    auto compare = [&devices](MONITORINFOEX& l, MONITORINFOEX& r) 
     { 
      DWORD il = -1; 
      DWORD ir = -1; 

      auto foundL = devices.lower_bound(l.szDevice); 
      if (foundL != devices.end()) 
       il = foundL->second; 

      auto foundR = devices.lower_bound(r.szDevice); 
      if (foundR != devices.end()) 
       ir = foundR->second; 

      return (il < ir); 
     }; 

    std::sort(m_monitors.begin(), m_monitors.end(), compare); 
} 

PS: Вы можете написать
DWORD иль = СТАНД.MODBUS :: numeric_limits < DWORD> :: макс ();
insted of
DWORD il = -1;
, но не забудьте указать NOMINMAX, прежде чем включать Windows.h

+1

Я думаю, вы должны добавить объяснение, почему вы сделали то, что сделали. –

Смежные вопросы