如何获取Windows中的显示数量?

时间:2011-10-14 11:37:20

标签: c++ windows winapi

我想计算活动显示的数量。对于Mac,我可以使用以下内容:

CGDisplayCount nDisplays;
CGGetActiveDisplayList(0,0, &nDisplays);
log.printf("Displays connected: %d",(int)nDisplays);

如何在Windows中实现相同功能?我找到EnumDisplayMonitors但我无法弄清楚如何使用它。

3 个答案:

答案 0 :(得分:19)

正如您所发现的那样,EnumDisplayMonitors()将完成这项工作,但打电话有点棘手。文档说明:

  

EnumDisplayMonitors函数枚举显示监视器(包括与镜像驱动程序关联的不可见伪监视器),这些监视器与指定剪切矩形和设备上下文的可见区域的交集形成的区域相交。 EnumDisplayMonitors为枚举的每个监视器调用一次应用程序定义的MonitorEnumProc回调函数。请注意,GetSystemMetrics(SM_CMONITORS)仅计算显示监视器。

这使我们找到了一个更简单的解决方案:GetSystemMetrics(SM_CMONITORS)。事实上,如果你有假的监视器,这可能比EnumDisplayMonitors()更好。


如同调用EnumDisplayMonitors()的说明一样:

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
    int *Count = (int*)dwData;
    (*Count)++;
    return TRUE;
}

int MonitorCount()
{
    int Count = 0;
    if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count))
        return Count;
    return -1;//signals an error
}

答案 1 :(得分:2)

未经测试,但基本上您只需要为枚举函数提供回调:

int numMonitors = 0;

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  {
  //lprcMonitor holds the rectangle that describes the monitor position and resolution)

  numMonitors++;
  return true;
  }

int main()
  {
  EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, NULL);
  }

答案 2 :(得分:0)

上述方法的问题在于,它们无法在“克隆”,“内部”,“外部”拓扑中检测到正确数量的监视器。它们仅在扩展拓扑中获得正确的号码。使用QueryDisplayConfig函数可以在任何拓扑中获取正确数量的监视器。您必须在标志中使用QDC_ALL_PATHS并仅计算找到的唯一监视器。

    DISPLAYCONFIG_TOPOLOGY_ID currTopologyId = 0;
    UINT32 numPathArrayElements = 0;
    UINT32 numModeInfoArrayElements = 0;
    LONG retCode = ::GetDisplayConfigBufferSizes(flags, &numPathArrayElements, &numModeInfoArrayElements);
    auto pathArray = std::make_unique<DISPLAYCONFIG_PATH_INFO[]>(numPathArrayElements);
    auto modeInfoArray = std::make_unique<DISPLAYCONFIG_MODE_INFO[]>(numModeInfoArrayElements);
    retCode = ::QueryDisplayConfig(flags, &numPathArrayElements, pathArray.get(), &numModeInfoArrayElements, modeInfoArray.get(), &currTopologyId);

使用DisplayConfigGetDeviceInfo从路径目标获取监视器名称。

    DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
    targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
    targetName.header.size = sizeof(targetName);
    targetName.header.adapterId = pathInfo.targetInfo.adapterId;
    targetName.header.id = pathInfo.targetInfo.id;

    LONG retCode = ::DisplayConfigGetDeviceInfo(&targetName.header);

您将在以下位置获得监视器名称:

targetName.monitorDevicePath, targetName.monitorFriendlyDeviceName