Как масштабировать строку заголовка в приложении Win с поддержкой DPI?

Я делаю свое приложение с поддержкой dpi для каждого монитора, установив <dpiAware>True/PM</dpiAware> в файле манифеста. Я могу проверить с помощью Process Explorer, что это действительно работает, или вызвав GetProcessDpiAwareness.

Это все работает нормально, и я могу масштабировать все в области клиента в моем коде. Однако моя единственная проблема заключается в том, что, если я перетаскиваю свое приложение с монитора с системным dpi на монитор не системного dpi, строка заголовка и любое системное меню будут либо слишком большими, либо слишком маленькими. Это не относится к большинству встроенных приложений (например, Calc, пограничный браузер и т. Д.), Поэтому необходимо правильно масштабировать его. Кто-нибудь, как разработчики в MS сделали это?

Скриншот ниже должен объяснить мою проблему лучше. Также обратите внимание, что отступы между кнопками закрытия, минимума и максимума отличаются, когда они масштабируются (96 точек на дюйм).

Скриншот

Пример приложения Я прилагаю очень простое приложение, которое учитывает dpi для каждого монитора.

18

Решение

Кто-нибудь, как разработчики в MS сделали это?

Это довольно неутешительный ответ. С помощью Алин КонстантинВ WinCheat и осмотрев окно верхнего уровня Калькулятора, я вижу размер окна 320×576 и размер клиента, который также составляет 320×576.

Другими словами, Microsoft полностью избегает этой проблемы, подавляя не-клиентскую область окна, вместо этого помещая все в клиентскую область. Чтобы сделать эту работу полезной для вас, может потребоваться отрисовка строки заголовка.

Стоит отметить, что калькулятор и, например, Проводник Windows не использует тот же цвет для заголовков. Калькулятор, выполняющий нестандартное рисование строки заголовка, объяснил бы это отлично.

7

Другие решения

В Windows 10 Anniversary Update (v1607) добавлен новый API, который необходимо вызвать, чтобы включить масштабирование DPI для не клиентских областей: EnableNonClientDpiScaling. Эта функция должна вызываться, когда WM_NCCREATE получено. Сообщение отправляется обратному вызову процедуры окна при создании окна.

Пример:

case WM_NCCREATE:
{
if (!EnableNonClientDpiScaling(hWnd))
{
// Error handling
return FALSE;
}

return DefWindowProcW(...);
}

Если контекст приложения осведомлен о DPI DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2потом звоню EnableNonClientDpiScaling должен быть опущен, так как это не будет иметь никакого эффекта, хотя функция все равно вернется успешно.

От документация:

Масштабирование не для клиентов для окон верхнего уровня по умолчанию не включено. Вы должны вызвать этот API, чтобы активировать его для каждого отдельного окна верхнего уровня, для которого вы хотите автоматически масштабировать не-клиентскую область. Как только вы это сделаете, вы не сможете отключить его. Включение не-клиентского масштабирования означает, что все области, нарисованные системой для окна, будут автоматически масштабироваться в ответ на изменения DPI в окне. Это включает в себя такие области, как строка заголовка, полосы прокрутки и строка меню. Вы хотите позвонить EnableNonClientDpiScaling когда вы хотите, чтобы операционная система отвечала за автоматическое отображение этих областей в правильном размере на основе API монитора.

Увидеть этот блог для получения дополнительной информации об изменениях масштабирования DPI в Windows 10 AU.

10

документация говорит:

Обратите внимание, что не-клиентская область приложения, поддерживающего каждый монитор-DPI, не масштабируется Windows и будет отображаться пропорционально меньше на дисплее с высоким DPI.

Приложения Microsoft, на которые вы ссылаетесь, удаляют не клиентскую область и заставляют клиентскую область покрывать все окно.

0

ОБНОВИТЬ:

Достаточно добавить новый <dpiAwarness> декларация, чтобы манифест, чтобы решить все это безобразие. Пример Вот.

Остатки прежних расследований (устарели):

Больше исследований на эту тему.

Настройка системы: два монитора, один с разрешением 96 т / д, другой с разрешением 267 т / д (Microsoft Surface 4).

Окно тестирования перемещено на дополнительный монитор с разрешением 96 точек на дюйм:

Здесь рендеринг (неправильно, IMO) с <dpiAware>true/pm</dpiAware> в декларации:

введите описание изображения здесь

Обратите внимание на огромный размер строки заголовка и неправильные размеры значков окна.

И вот правильный рендеринг с использованием <dpiAware>true</dpiAware>

введите описание изображения здесь

И я подозреваю, что документация MSDN вводит в заблуждение относительно значений PROCESS_DPI_AWARENESS. Я не вижу различий в сообщениях и стилях между <dpiAware>true</dpiAware> а также <dpiAware>true/pm</dpiAware>, Последний только увеличивает заголовок. В обоих случаях приложение получает сообщение WM_DPICHANGED при перемещении между мониторами с различным DPI.

Вздох.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector