DXGI监视器枚举未能为Dell P2715Q显示器提供完整的尺寸信息。

3
我创建了DXGI适配器和监视器枚举。连接到我的电脑的第二个显示器是Dell P2715Q,具有3840*2160分辨率:

分辨率

然而,该程序将其报告为第二个可用分辨率2560*1440。最小代码以重现:
int main()
{
IDXGIFactory1* pFactory1;

HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory1));

if (FAILED(hr))
{
    wcout << L"CreateDXGIFactory1 failed. " << endl;
    return 0;
}

for (UINT i = 0;; i++)
{
    IDXGIAdapter1* pAdapter1 = nullptr;

    hr = pFactory1->EnumAdapters1(i, &pAdapter1);

    if (hr == DXGI_ERROR_NOT_FOUND)
    {
        // no more adapters
        break;
    }

    if (FAILED(hr))
    {
        wcout << L"EnumAdapters1 failed. " << endl;
        return 0;
    }

    DXGI_ADAPTER_DESC1 desc;

    hr = pAdapter1->GetDesc1(&desc);

    if (FAILED(hr))
    {
        wcout << L"GetDesc1 failed. " << endl;
        return 0;
    }

    wcout << L"Adapter: " << desc.Description << endl;

    for (UINT j = 0;; j++)
    {
        IDXGIOutput *pOutput = nullptr;

        HRESULT hr = pAdapter1->EnumOutputs(j, &pOutput);

        if (hr == DXGI_ERROR_NOT_FOUND)
        {
            // no more outputs
            break;
        }

        if (FAILED(hr))
        {
            wcout << L"EnumOutputs failed. " << endl;
            return 0;
        }

        DXGI_OUTPUT_DESC desc;

        hr = pOutput->GetDesc(&desc);

        if (FAILED(hr))
        {
            wcout << L"GetDesc1 failed. " << endl;
            return 0;
        }

        wcout << L"  Output: " << desc.DeviceName <<
            L"  (" << desc.DesktopCoordinates.left << L"," << desc.DesktopCoordinates.top << L")-(" <<
            (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left) << L"," << 
            (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top) << L")" << endl;

    }
}

return 0;
}

输出:

适配器:英特尔(R)Iris(TM)Pro Graphics 6200
   输出:\\.\DISPLAY1  (0,0)-(1920,1200)
   输出:\\.\DISPLAY2  (1920,0)-(2560,1440)

这种行为可能的原因:DirectX限制、视频内存、显示适配器、驱动程序、显示器?

环境:

Windows 10 x64
Intel(R) Iris(TM) Pro Graphics 6200
DELL P2715Q

也许不是精确的秒分辨率,而是高DPI缩放。 - Roman R.
@RomanR. 你能再解释一下吗?谢谢。 - Alex F
2个回答

3

您的应用程序被视为不支持DPI缩放。操作系统会为您缩放坐标,以保持与传统应用程序的兼容性。

让系统知道您已经了解高DPI桌面应用程序开发,这样您就可以获得预期的坐标:

#include <ShellScalingAPI.h>

#pragma comment(lib, "shcore.lib")

int main()
{
    SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
    // there goes your code

Adapter: Intel(R) HD Graphics 4600
  Output: \\.\DISPLAY4  (0,0)-(3840,2160)
  Output: \\.\DISPLAY5  (3840,0)-(3840,2160)

没有 SetProcessDpiAwareness

Adapter: Intel(R) HD Graphics 4600
  Output: \\.\DISPLAY4  (0,0)-(2194,1234)
  Output: \\.\DISPLAY5  (2194,0)-(2194,1234)

注意:MSDN对DXGI_OUTPUT_DESC结构的注释如下:

DesktopCoordinates

类型:RECT

包含输出边界在桌面坐标系下的RECT结构。桌面坐标系取决于桌面每英寸的点数(DPI)。有关编写DPI感知Win32应用程序的信息,请参阅高DPI。


测试。同时,SetProcessDpiAwareness返回S_OK,但结果相同。 - Alex F
1
在我的电脑上,SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)解决了问题。但在另一个程序中,这并没有帮助,但在Windows显示设置中将文本大小设置为100%解决了问题。我需要进一步调查这个问题。感谢您指出正确的方向。 - Alex F
PROCESS_PER_MONITOR_DPI_AWARE 明显是最灵活的。我想,使用每个系统 DPI,你首先将主要的显示器 DPI 应用于所有显示器。无论哪种方式,它都是关于高 DPI 缩放,可能会很棘手(MSDN 上的文章相当长,我对 SetProcessDpiAwareness 的参考只是一个粗略的例子,你已经理解了...)。 - Roman R.
虽然不建议这样做,但是可以通过编程方式设置默认的 DPI 意识。一旦在您的进程中创建了一个窗口(HWND),则不再支持更改 DPI 意识模式。如果您正在以编程方式设置进程默认的 DPI 意识模式,则必须在创建任何 HWND 之前调用相应的 API。 - wqw

2
作为罗马答案的替代方案,您可以向项目添加清单(manifest)以使其支持dpi。
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接