Поддержка высокого DPI в Windows Forms

Начиная с платформы .NET Framework 4.7 в Windows Forms появились усовершенствования для распространенных сценариев с высоким DPI и динамическим DPI. Например:

  • Улучшения масштабирования и макетирования ряда элементов управления Windows Forms, таких как MonthCalendar и CheckedListBox.

  • Масштабирование за один проход. В платформе .NET Framework 4.6 и более ранних версий масштабирование выполнялось с помощью нескольких проходов, что приводило к масштабированию некоторых элементов управления в большей степени, чем это было необходимо.

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

В версиях платформы .NET Framework начиная с 4.7 расширенная поддержка высокого DPI является функцией явного согласия. Чтобы использовать ее преимущества, необходимо настроить ваше приложение.

Настройка приложения Windows Forms для поддержки высокого DPI

Новые функции Windows Forms, поддерживающие осведомленность о высоком DPI, доступны только в приложениях, предназначенных для платформы .NET Framework 4.7 и работающих в операционных системах Windows, начиная с Windows 10 Creators Update.

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

  • Объявите совместимость с Windows 10.

    Для этого добавьте в файл манифеста следующее:

    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
      <application>
        <!-- Windows 10 compatibility -->
        <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      </application>
    </compatibility>
    
  • Включите осведомленность о DPI для каждого монитора в файле app.config.

    В Windows Forms появился новый элемент <System.Windows.Forms.ApplicationConfigurationSection> для поддержки новых функций и настроек, добавленных начиная с платформы .NET Framework 4.7. Чтобы воспользоваться преимуществами новых функций, поддерживающих высокий DPI, добавьте в файл конфигурации приложения следующее.

    <configuration>
      <!-- ... other xml settings ... -->
    
      <System.Windows.Forms.ApplicationConfigurationSection>
        <add key="DpiAwareness" value="PerMonitorV2" />
      </System.Windows.Forms.ApplicationConfigurationSection>
    
    </configuration>
    

    Важно!

    В предыдущих версиях платформы .NET Framework манифест использовался для добавления поддержки высокого DPI. Этот подход больше не рекомендуется, так как он подразумевает переопределение параметров, определенных в файле app.config.

  • Вызовите статический метод EnableVisualStyles.

    Это должен быть первый вызов метода в точке входа вашего приложения. Например:

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form2());
    }
    

Отказ от отдельных функций поддержки высокого DPI

Установка значения DpiAwareness для PerMonitorV2 включает все функции осведомленности о высоком DPI, поддерживаемые в версиях платформы .NET Framework, начиная с 4.7. Как правило, это подходит для большинства приложений Windows Forms. Однако вы можете отказаться от одной или нескольких таких функций. Наиболее важной причиной этого является то, что существующий код приложения уже обрабатывает эту функцию. Например, если приложение обрабатывает автомасштабирование, вы можете захотеть отключить функцию автоматического изменения размера следующим образом:

<configuration>
  <!-- ... other xml settings ... -->

  <System.Windows.Forms.ApplicationConfigurationSection>
    <add key="DpiAwareness" value="PerMonitorV2" />
    <add key="EnableWindowsFormsHighDpiAutoResizing" value="false" />
  </System.Windows.Forms.ApplicationConfigurationSection>

</configuration>

Список отдельных ключей и их значений см. в разделе Элемент конфигурации Add Windows Forms.

Новые события изменения DPI

Начиная с .NET Framework 4.7, три следующих новых события позволяют программно обрабатывать динамические изменения DPI:

  • DpiChangedAfterParent, которое возникает при изменении параметра DPI для элемента управления программным образом после возникновения события изменения DPI для соответствующего родительского элемента управления или формы;
  • DpiChangedBeforeParent, которое возникает при изменении параметра DPI для элемента управления программным образом перед возникновением события изменения DPI для соответствующего родительского элемента управления или формы;
  • DpiChanged, которое возникает при изменении параметра DPI на устройстве, на котором в данный момент отображается форма.

Новые вспомогательные методы и свойства

В .NET Framework 4.7 также добавлен ряд новых вспомогательных методов и свойств, которые предоставляют сведения о масштабировании и позволяют выполнять масштабирование. Например:

  • LogicalToDeviceUnits преобразует значение из логического в пиксели устройства.

  • ScaleBitmapLogicalToDevice масштабирует растровое изображение до логического DPI для устройства.

  • DeviceDpi возвращает DPI для текущего устройства.

Особенности управления версиями

Помимо платформы .NET Framework 4.7 и Windows 10 Creators Update, ваше приложение также может запускаться в среде, в которой оно несовместимо с улучшениями высокого DPI. В этом случае вам потребуется разработать резервную форму для приложения. Вы можете сделать это, чтобы выполнить настраиваемое рисование для обработки масштабирования.

Для этого вам также необходимо определить операционную систему, в которой работает ваше приложение. Это можно сделать с помощью кода, подобного приведенному ниже.

// Create a reference to the OS version of Windows 10 Creators Update.
Version OsMinVersion = new Version(10, 0, 15063, 0);

// Access the platform/version of the current OS.
Console.WriteLine(Environment.OSVersion.Platform.ToString());
Console.WriteLine(Environment.OSVersion.VersionString);

// Compare the current version to the minimum required version.
Console.WriteLine(Environment.OSVersion.Version.CompareTo(OsMinVersion));

Обратите внимание, что приложение не будет успешно обнаруживать ОС Windows 10, если она не была указана в манифесте приложения как поддерживаемая операционная система.

Вы также можете проверить версию платформы .NET Framework, для которой было создано приложение:

Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);

См. также