通过索引
获取(实时)显示器的句柄假设我有3个显示器。我如何才能通过索引获得第二个句柄? EnumDisplayMonitors()将无法工作,因为它枚举伪设备以及EnumDisplayDevices()不给我处理。通过索引
您需要使用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)
{
//...
}
您可以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_DEVICE
与szDevice
从MONITORINFOEX
你之前存储的比较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
我认为你应该添加一个解释,为什么你做了你所做的。 – 2017-10-23 19:51:07
怎么样'MonitorFromRect','MonitorFromPoint'或'MonitorFromWindow'?他们中的任何一个会为你工作吗?他们都返回一个'HMONITOR'。 – 2015-04-02 12:59:57
不幸的是,我需要的索引 – Grisu47 2015-04-02 14:59:52