使用dpiawareness = 1时,辅助监视器的坐标很奇怪

时间:2017-03-24 15:10:12

标签: windows winapi hdpi

我有两台显示器:

DISPLAY2: 3840x2160 (primary (no idea why it's called DISPLAY2 though)
DISPLAY1: 1920x1080 (located right of primary)

我写了一个小程序来打印它们的几何图形,然后输出:

\\.\DISPLAY2; x=0, y=0; 3840x2160
\\.\DISPLAY1; x=3840, y=278; 1920x1080

哪个看起来正确。但是,如果我拨打SetProcessDpiAwareness((PROCESS_DPI_AWARENESS) 1);,则会打印:

\\.\DISPLAY2; x=0, y=0; 7680x4320
\\.\DISPLAY1; x=7680, y=556; 3840x2160

为什么尺寸只增加了一倍?

请注意,我没有在我的显示器上使用任何缩放系数,以便能够弄清楚首先发生了什么。但是,如果我在主显示器上设置了2倍的缩放比例,那么这就是它打印的内容:

\\.\DISPLAY2; x=0, y=0; 3840x2160
\\.\DISPLAY1; x=7680, y=556; 3840x2160

为什么辅助监视器从x = 7680开始?

这是我用来打印值的代码:

#include <Windows.h>
#include <iostream>
#include <ShellScalingAPI.h>

#pragma comment(lib, "Shcore.lib")
#pragma comment(lib, "User32.lib")

BOOL monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
{
    MONITORINFOEX info;
    memset(&info, 0, sizeof(MONITORINFOEX));
    info.cbSize = sizeof(MONITORINFOEX);
    if (!GetMonitorInfo(hMonitor, &info))
        return false;

    std::cout << info.szDevice << "; x="<< info.rcMonitor.left << ", y=" << info.rcMonitor.top << "; "
              << (info.rcMonitor.right - info.rcMonitor.left) << "x" << (info.rcMonitor.bottom - info.rcMonitor.top)
              << "\n";

    return true;
}

int main()
{
    int result = SetProcessDpiAwareness((PROCESS_DPI_AWARENESS) 1);
    if (result) {
        std::cout << "Failed to call SetProcessDpiAwareness\n";
        return 1;
    }

    EnumDisplayMonitors(0, 0, monitorEnumCallback, reinterpret_cast<LPARAM>(&result));
    return 0;
}

1 个答案:

答案 0 :(得分:3)

(1)为每种情况打印系统DPI,以及(2)也尝试SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)可能是有益的。两台显示器的DPI可能不同(或至少Windows认为它们是。)

您告诉Windows,您了解单个系统范围的DPI。为确保应用程序在这种情况下做正确的事情,Windows已经编制了一个虚拟屏幕坐标系统,该系统允许基于主监视器DPI的所有布局的应用程序在两个监视器上获得良好的结果。如果它已使用主监视器的DPI,则在辅助监视器上绘制时,程序可能无法选择最佳图标大小和坐标。同样,如果它使用了辅助监视器的DPI,则应用程序将无法在主要监视器上执行像素完美定位。如果您查看与GDI绘图(ClearType),Direct2D,鼠标和指针消息等的所有交互,则使用双倍较高的DPI然后降尺度可能是一个合理的折衷方案。

如果你的应用程序是每个监视器的DPI意识,我怀疑你会全面获得真正的价值。