假设我有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.iIndex = 1;
info.hMonitor = NULL;
EnumDisplayMonitors(NULL, NULL, GetMonitorByIndex, (LPARAM)&info);
if (info.hMonitor != NULL)
{
//...
}
你可以排除主监视器,这里是示例代码(样式可能会有所不同):
如果DEVMODE dmPosition x == 0且y == 0,则它是主监视器。
仅对于显示设备,POINTL结构,其指示显示设备相对于桌面区域的位置坐标。主显示设备始终位于坐标(0,0)处。
检查x,y以定义第二个或第三个。
LONG second_x=0;
LONG second_y=0;
DWORD deviceNum = 0;
DISPLAY_DEVICE displayDevice;
DEVMODE devMode;
memset(&displayDevice, 0, sizeof(displayDevice));
displayDevice.cb = sizeof(DISPLAY_DEVICE);
while(EnumDisplayDevices(NULL, deviceNum, &displayDevice, 0))
{
EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
if (devMode.dmPosition.x == 0 && devMode.dmPosition.y == 0)
{
// primary monitor
}
else
{
// second or third monitor
second_x = devMode.dmPosition.x;
second_y = devMode.dmPosition.y;
}
++deviceNum;
}
m_pMainWnd->SetWindowPos(NULL,(int)second_x,(int)second_y,0,0,SWP_SHOWWINDOW | SWP_NOSIZE);
您可以使用EnumDisplayMonitors()
枚举设备并使用EnumDisplayDevices()
检查它是否为伪监视器
当您使用GetMonitorInfo()
迭代显示监视器时,您可以获得带有监视器设备名称的MONITORINFOEX
。
然后使用EnumDisplayDevices()
你可以获得包含DISPLAY_DEVICE
的StateFlags
,如果当前的监视器是一个伪监视器(或者如果bellow附加到桌面)
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()
,它将根据第二个参数返回适配器的信息。在这种情况下,您的设备将确定订单。
你可以将qazxsw poi中的qazxsw poi与你之前存储的qazxsw poi中的qazxsw poi进行比较来排序你的DeviceName
DISPLAY_DEVICE
PS:你可以写 DWORD il = std :: numeric_limits <DWORD> :: max(); 绝对的 DWORD il = -1; 但在包含Windows.h之前不要忘记定义NOMINMAX