The problem with above approaches is that they do not detect the correct number of monitors in Clone, Internal, External topologies. They get the correct number only in Extended topology. There is a way to get the correct number of monitors in any topology with QueryDisplayConfig function. You have to use QDC_ALL_PATHS in flags and count only unique monitors found.
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);
Use DisplayConfigGetDeviceInfo to get the monitor name from the path target.
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);
You will get the monitor name in:
targetName.monitorDevicePath, targetName.monitorFriendlyDeviceName