You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取主显示适配器的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的老环境

关键点解释:

  1. DirectDrawEnumerateEx:相比旧的DirectDrawEnumerate,它支持传入显示器句柄,能更准确地关联适配器和物理显示器,避免多显示器环境下的识别错误
  2. MONITORINFOF_PRIMARY:通过这个标志精准判断当前适配器对应的是否是主显示器,彻底摆脱枚举顺序依赖
  3. 兼容 fallback:针对不支持GetMonitorInfo的老系统,保留了DirectDraw默认的“第一个枚举到的是主设备”逻辑,确保兼容性

用这个函数替换原来的NULL参数后,你的DirectDraw应该就能在多显示器环境下正常启用硬件加速了,那些难以复现的线程性能问题大概率也会跟着缓解。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:34:33