Подтвердить что ты не робот

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

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

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

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

Screenshot

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

4b9b3361

Ответ 1

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

У этого довольно неприятный ответ. Используя Alin Constantin WinCheat и проверяя окно верхнего уровня калькулятора, я вижу размер окна 320x576 и размер клиента, который также составляет 320x576.

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

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

Ответ 2

Обновление для 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.

Ответ 3

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

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

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

Ответ 4

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

Настройка системы: два монитора, один - 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.

Вздох.