我正在创建一个小程序,它将包括所有显示器在桌面(扩展模式)或禁用所有辅助显示器(显示器可以连接到gpus和集成图形)。
这个程序是为Windows 7设计的,所以依靠互联网上的信息,我决定使用CCD APIs,但在SetDisplayConfig()函数上遇到了一个问题。例如,这段关闭所有辅助显示器的代码可以完美地工作,因为'i'递增,其中一个显示器会关闭。
UINT32 PathCount = 0; //path count
UINT32 ModeCount = 0; //mode count
HRESULT hr;
hr = GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &PathCount, &ModeCount);
std::vector<DISPLAYCONFIG_PATH_INFO> pathArray(PathCount);
std::vector<DISPLAYCONFIG_MODE_INFO> modeArray(ModeCount);
hr = QueryDisplayConfig(QDC_ALL_PATHS, &PathCount, &pathArray[0], &ModeCount, &modeArray[0], NULL);
for (int i = 1; i < PathCount;i++)
{
if(pathArray[i].flags != 0)
{
pathArray[i].flags = 0;
hr = SetDisplayConfig(PathCount, &pathArray[0], ModeCount, &modeArray[0], SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_ALLOW_CHANGES);
}
}
为了扩展一个显示器,我找到了这段代码。
SetDisplayConfig(0, NULL, 0, NULL, SDC_TOPOLOGY_EXTEND | SDC_APPLY);
这个函数用这个特定的参数工作,但它只针对我的第二个显示器,它连接到gpu作为我的主显示器,而不是第三个显示器,它连接到主板(只有当我把我的第二个显示器从gpu上断开后,这个函数才会对连接到主板的显示器工作)。
我试着用
for (int i = 1; i < PathCount;i++)
{
if(pathArray[i].flags != 1)
{
pathArray[i].flags = 1;
hr = SetDisplayConfig(PathCount, &pathArray[0], ModeCount, &modeArray[0], SDC_TOPOLOGY_EXTEND | SDC_APPLY | SDC_PATH_PERSIST_IF_REQUIRED);
}
}
但收到 ERROR_ADAP_HDW_ERR 错误信息。
所以我想请大家帮我一下,如何用'SDC_TOPOLOGY_EXTEND'标志的SetDisplayConfig()finction来针对特定的显示器(或所有的显示器),或者有其他的方法来解决这个问题?如何使用带有'SDC_TOPOLOGY_EXTEND'标志的SetDisplayConfig()finction来锁定特定的显示器(或一次锁定所有显示器),或者有其他方法来解决这个问题?
所以我做了它,它不能与一些奇特的显示器设置(如多个USB显示器)工作,但它的工作原理,所有的显示器被添加到桌面(或桌面被延伸到所有的显示器
我是如何做到的?微软的迂回帮助了我,通过监控windows 10的系统设置,当我添加显示到桌面时,它只是将最重要的属性设置为默认值。
HRESULT hr = S_OK;
UINT32 NumPathArrayElements = 0;
UINT32 NumModeInfoArrayElements = 0;
//LONG error = GetDisplayConfigBufferSizes((QDC_ALL_PATHS | QDC_VIRTUAL_MODE_AWARE), &NumPathArrayElements, &NumModeInfoArrayElements);
hr = GetDisplayConfigBufferSizes((QDC_ALL_PATHS), &NumPathArrayElements, &NumModeInfoArrayElements);
std::vector<DISPLAYCONFIG_PATH_INFO> PathInfoArray2(NumPathArrayElements);
std::vector<DISPLAYCONFIG_MODE_INFO> ModeInfoArray2(NumModeInfoArrayElements);
//error = QueryDisplayConfig((QDC_ALL_PATHS | QDC_VIRTUAL_MODE_AWARE), &NumPathArrayElements, &PathInfoArray2[0], &NumModeInfoArrayElements, &ModeInfoArray2[0], NULL);
hr = QueryDisplayConfig((QDC_ALL_PATHS), &NumPathArrayElements, &PathInfoArray2[0], &NumModeInfoArrayElements, &ModeInfoArray2[0], NULL);
struct displaySourcePair
{
std::wstring displayName;
UINT32 displayId;
};
std::vector<displaySourcePair> ocupiedDisplays;
if (hr == S_OK)
{
DISPLAYCONFIG_SOURCE_DEVICE_NAME SourceName = {};
SourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
SourceName.header.size = sizeof(SourceName);
DISPLAYCONFIG_TARGET_PREFERRED_MODE PreferedMode = {};
PreferedMode.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
PreferedMode.header.size = sizeof(PreferedMode);
int newId = 0;
for (UINT32 i = 0; i < NumPathArrayElements; i++)
{
bool match = false;
SourceName.header.adapterId = PathInfoArray2[i].sourceInfo.adapterId;
SourceName.header.id = PathInfoArray2[i].sourceInfo.id;
PreferedMode.header.adapterId = PathInfoArray2[i].targetInfo.adapterId;
PreferedMode.header.id = PathInfoArray2[i].targetInfo.id;
hr = HRESULT_FROM_WIN32(DisplayConfigGetDeviceInfo(&SourceName.header));
hr = HRESULT_FROM_WIN32(DisplayConfigGetDeviceInfo(&PreferedMode.header));
if (hr == S_OK)
{
if ((PathInfoArray2[i].flags & DISPLAYCONFIG_PATH_ACTIVE) == true)
{
std::wstring str = std::wstring(SourceName.viewGdiDeviceName);
displaySourcePair tmpStruct;
tmpStruct.displayId = PreferedMode.header.id;
tmpStruct.displayName = str;
ocupiedDisplays.push_back(tmpStruct);
}
for (int k = 0; k < ocupiedDisplays.size(); k++)
{
std::wstring str = std::wstring(SourceName.viewGdiDeviceName);
if (ocupiedDisplays[k].displayName == str || ocupiedDisplays[k].displayId == PreferedMode.header.id)
{
match = true;
}
}
if (match == false && PathInfoArray2[i].targetInfo.targetAvailable == 1)
{
PathInfoArray2[i].flags |= DISPLAYCONFIG_PATH_ACTIVE;
std::wstring str = std::wstring(SourceName.viewGdiDeviceName);
displaySourcePair tmpStruct;
tmpStruct.displayId = PreferedMode.header.id;
tmpStruct.displayName = str;
ocupiedDisplays.push_back(tmpStruct);
}
if (PathInfoArray2[i].targetInfo.targetAvailable == 1)
{
PathInfoArray2[i].sourceInfo.id = newId;
newId++;
}
if (PathInfoArray2[i].targetInfo.id != PreferedMode.header.id)
{
PathInfoArray2[i].targetInfo.id = PreferedMode.header.id;
}
PathInfoArray2[i].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
PathInfoArray2[i].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
}
}
//hr = SetDisplayConfig(NumPathArrayElements, &PathInfoArray2[0], 0, NULL, (SDC_VALIDATE | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES | SDC_VIRTUAL_MODE_AWARE));
//hr = SetDisplayConfig(NumPathArrayElements, &PathInfoArray2[0], 0, NULL, (SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES | SDC_VIRTUAL_MODE_AWARE));
hr = SetDisplayConfig(NumPathArrayElements, &PathInfoArray2[0], 0, NULL, (SDC_VALIDATE | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES));
hr = SetDisplayConfig(NumPathArrayElements, &PathInfoArray2[0], 0, NULL, (SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES));
}