2015-04-02 102 views
1

獲取(實時)顯示器的句柄假設我有3個顯示器。我如何才能通過索引獲得第二個句柄? EnumDisplayMonitors()將無法工作,因爲它枚舉僞設備以及EnumDisplayDevices()不給我處理。通過索引

+0

怎麼樣'MonitorFromRect','MonitorFromPoint'或'MonitorFromWindow'?他們中的任何一個會爲你工作嗎?他們都返回一個'HMONITOR'。 – 2015-04-02 12:59:57

+0

不幸的是,我需要的索引 – Grisu47 2015-04-02 14:59:52

回答

2

您需要使用EnumDisplayMonitors()而不是EnumDisplayDevices()來訪問每個監視器的HMONITOR句柄。

但是,監視器不是按索引標識的。 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()

當您使用012迭代顯示監視器你可以得到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(),它將根據第二個參數返回適配器的信息。在這種情況下,您的設備將確定訂單。

您可以從DISPLAY_DEVICEszDeviceMONITORINFOEX你之前存儲的比較DeviceName排序您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 IL =的std :: numeric_limits < DWORD> :: MAX( );
insted
DWORD il = -1;
但不要忘記在包含Windows.h之前定義NOMINMAX

+1

我認爲你應該添加一個解釋,爲什麼你做了你所做的。 – 2017-10-23 19:51:07