Масштабирование неклиентской области для поддержки высокого разрешения на каждый монитор в приложении, поддерживающем Windows 8.1

Я разрабатываю приложение, которое работает в Windows 10 и 8.1, и столкнулось с проблемой масштабирования неклиентской области (строка меню, строка заголовка) при перемещении между мониторами с разным DPI. Клиентская область обрабатывается, но неклиентская область выходит за рамки. Осведомленность о DPI установлена ​​на PerMonitorAware (v1, так как v2 недоступна в Windows 8.1).

Функция EnableNonClientDpiScaling делает именно то, что мне нужно (это общепринятый ответ на все подобные вопросы) — увы, это только часть API, начиная с Windows 10.

Есть ли способ вручную справиться с этим без ранее упомянутой функции, чтобы сохранить поддержку Windows 8.1? Или поддержка Windows 8.1 означает, что невозможно изменить размер неклиентской области при перемещении между экранами с разным DPI?


person Dan    schedule 09.01.2019    source источник
comment
Стоит ли поддерживать 8.1? Конечно, большинство людей воспользовались бы бесплатным обновлением до 10.   -  person Jonathan Potter    schedule 09.01.2019
comment
@JonathanPotter Вы имеете в виду понижение рейтинга? На маленьком планшете 8.1 лучше 10.   -  person Anders    schedule 09.01.2019
comment
Масштабирование неклиентской области на каждый монитор, представленное в юбилейном обновлении Windows 10 10-creators-update/" rel="nofollow noreferrer">Улучшения масштабирования с высоким разрешением.   -  person Daniel Sęk    schedule 11.01.2019
comment
Масштабирование неклиентской области. До юбилейного обновления не было возможности масштабировать DPI неклиентской области Windows (строка заголовка, системные меню, полосы прокрутки верхнего уровня, строки меню и т. д.). Это означало, что если вы создали приложение для каждого монитора, у вас останется неправильный размер (слишком большой или слишком маленький) неклиентской области после изменения DPI без какого-либо обращения, кроме рисования всего этого самостоятельно. В Anniversary Update мы добавили API, который можно вызвать для включения неклиентского масштабирования, EnableNonClientDpiScaling, но теперь с PMv2 вы получаете это автоматически   -  person Daniel Sęk    schedule 11.01.2019


Ответы (2)


Поддержка DPI — это движущаяся цель, вам просто нужно решить, какая у вас минимальная поддерживаемая платформа, и признать, что масштабирование с несколькими мониторами не будет идеальным на этих старых платформах.

Вызовите EnableNonClientDpiScaling в тех версиях, где он доступен (GetProcAddress или эквивалент на любом языке, который вы используете).

То, как новый элемент манифеста осведомленности работает в Windows 10, означает, что вы можете использовать Per-Monitor v2 там, где он поддерживается (1703 и более поздние версии), и PMv1, System или Unaware в более старых сборках. PMv2 обеспечивает автоматическое масштабирование диалогов на основе DialogBox.

person Anders    schedule 09.01.2019

Благодаря Андерсу, GetProcAddress был именно тем, что я искал. Хоть он и не решает изменение размера неклиентской области на Win 8.1 (кажется, кроме как рисовать все самому, действительно нет никакого способа), но дает возможность установить последнюю DPI_AWARENESS_CONTEXT на Win 10:

// the following sets PROCESS_PER_MONITOR_AWARE_V2 on Win10 and
// reverts to PROCESS_PER_MONITOR_AWARE on Win 8.1

typedef BOOL(__stdcall *SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
SetProcessDpiAwarenessContext dpi_call = nullptr;
dpi_call = reinterpret_cast<SetProcessDpiAwarenessContext>(GetProcAddress(
    GetModuleHandle(TEXT("User32.dll")),
    "SetProcessDpiAwarenessContext"));
if (dpi_call != nullptr) {
    if (!(*dpi_call)((DPI_AWARENESS_CONTEXT) - 4))
        throw std::runtime_error("Unable to set DPI aware app.");
} else {
    if (SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) != S_OK)
        throw std::runtime_error("Unable to set DPI aware app.");
}
person Dan    schedule 09.01.2019
comment
Вам не нужен этот код, его можно установить с помощью манифеста. True/PM для элемента Vista и Per Monitor v2 для элемента Windows 10. - person Anders; 09.01.2019