如何获取主显示适配器的GUID以传入DirectDrawCreateEx()函数?
如何获取主显示适配器的GUID以传入DirectDrawCreateEx()函数?
我太懂你这种头疼的处境了——维护古老的Windows C++代码,移到多显示器环境后硬件加速就没了,微软文档只撂下一句要传适配器GUID却连个示例都不给,简直让人抓狂!别担心,我之前帮人解决过一模一样的问题,下面给你一个靠谱的实现方案。
核心思路是利用DirectDraw的枚举功能,遍历所有显示适配器,找到标记为主显示设备的那一个,提取它的GUID。具体实现如下:
#include <ddraw.h> #include <windows.h> // 全局变量用于临时保存主适配器的GUID(仅在枚举回调中使用) static GUID g_PrimaryAdapterGUID = {0}; static BOOL g_FoundPrimaryAdapter = FALSE; // DirectDraw枚举回调函数 static BOOL WINAPI DirectDrawEnumCallbackEx(GUID FAR *lpGUID, LPCSTR lpDriverDescription, LPCSTR lpDriverName, LPVOID lpContext, HMONITOR hm) { // 跳过空GUID的设备,只处理有效适配器 if (lpGUID == NULL || g_FoundPrimaryAdapter) { return TRUE; } // 获取显示器信息,验证是否为主显示器 MONITORINFOEX monitorInfo = {0}; monitorInfo.cbSize = sizeof(MONITORINFOEX); if (GetMonitorInfo(hm, &monitorInfo)) { if (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) { // 找到主适配器,复制GUID g_PrimaryAdapterGUID = *lpGUID; g_FoundPrimaryAdapter = TRUE; // 找到后立即停止枚举,提升效率 return FALSE; } } // 兼容老系统:如果GetMonitorInfo不可用,默认第一个枚举到的适配器是主设备(DirectDraw传统行为) else { g_PrimaryAdapterGUID = *lpGUID; g_FoundPrimaryAdapter = TRUE; return FALSE; } // 继续枚举下一个设备 return TRUE; } // 获取主显示适配器的GUID函数 HRESULT GetPrimaryDisplayAdapterGUID(GUID* pOutGUID) { if (pOutGUID == NULL) return E_INVALIDARG; // 重置全局状态,避免多次调用的干扰 g_FoundPrimaryAdapter = FALSE; ZeroMemory(&g_PrimaryAdapterGUID, sizeof(GUID)); // 枚举所有已连接的DirectDraw设备 HRESULT hr = DirectDrawEnumerateEx(NULL, DirectDrawEnumCallbackEx, NULL, DDENUM_ATTACHEDSECONDARYDEVICES); if (FAILED(hr)) return hr; if (!g_FoundPrimaryAdapter) return E_FAIL; // 输出结果 *pOutGUID = g_PrimaryAdapterGUID; return S_OK; }
使用说明:
- 记得在项目中链接
ddraw.lib(如果用VS的话,在链接器输入设置里添加这个依赖) - 调用
GetPrimaryDisplayAdapterGUID获取主适配器GUID后,直接把它传给DirectDrawCreateEx的第一个参数即可 - 这个函数兼容Windows XP及以上的系统,覆盖了大部分还在跑DirectDraw的老环境
关键点解释:
- DirectDrawEnumerateEx:相比旧的
DirectDrawEnumerate,它支持传入显示器句柄,能更准确地关联适配器和物理显示器,避免多显示器环境下的识别错误 - MONITORINFOF_PRIMARY:通过这个标志精准判断当前适配器对应的是否是主显示器,彻底摆脱枚举顺序依赖
- 兼容 fallback:针对不支持
GetMonitorInfo的老系统,保留了DirectDraw默认的“第一个枚举到的是主设备”逻辑,确保兼容性
用这个函数替换原来的NULL参数后,你的DirectDraw应该就能在多显示器环境下正常启用硬件加速了,那些难以复现的线程性能问题大概率也会跟着缓解。
内容来源于stack exchange
相关产品推荐
相关产品推荐

