координаты вторичного монитора странные при использовании dpiawareness=1

У меня два монитора:

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;
}

person Sergio Martins    schedule 24.03.2017    source источник


Ответы (1)


Может быть полезно (1) распечатать системный DPI для каждого случая и (2) также попробовать SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE). DPI для ваших двух мониторов, вероятно, разные (или, по крайней мере, Windows так считает).

Вы сообщили Windows, что знаете о едином общесистемном DPI. Чтобы убедиться, что в этом случае приложения работают правильно, Windows разработала систему координат виртуального экрана, которая позволяет приложениям, которые основывают всю свою компоновку на DPI основного монитора, получать хорошие результаты на обоих мониторах. Если бы он использовал DPI основного монитора, ваша программа могла бы не выбирать наилучшие размеры значков и координаты при рисовании на дополнительном мониторе. Точно так же, если бы он использовал DPI дополнительного монитора, приложения не смогли бы выполнять позиционирование с точностью до пикселя на основном мониторе. Использование вдвое большего DPI, а затем уменьшение масштаба, вероятно, является разумным компромиссом, если вы посмотрите на все взаимодействия с рисованием GDI (ClearType), Direct2D, сообщениями мыши и указателя и т. д.

Если бы ваше приложение было осведомлено о DPI для каждого монитора, я подозреваю, что вы получили бы истинные значения по всем направлениям.

person Adrian McCarthy    schedule 24.03.2017