Как настроить приложение для правильной работы на компьютере с высокой настройкой DPI (например, 150%)?

Я создал простое приложение Winforms в C#. Когда я запускаю приложение на машине с высокими настройками DPI (например, 150%), приложение масштабируется. Все идет нормально! Но вместо рендеринга шрифтов с более высоким размером шрифта, все тексты также просто масштабируются. Это, конечно, приводит к очень размытому тексту (на всех элементах управления, таких как кнопки и т. Д.).

Разве окна не должны заботиться о правильном отображении текстов? Например, строка заголовка моего приложения отображается четко и ясно.

7 ответов

Решение

После того, как вы пройдете 100% (или 125% с установленным флажком "Масштабирование DPI в стиле XP"), Windows по умолчанию берет на себя масштабирование вашего пользовательского интерфейса. Это достигается за счет того, что ваше приложение выводит свой вывод в растровое изображение и выводит это растровое изображение на экран. Изменение масштаба этого растрового изображения делает текст неизбежно нечетким. Эта функция называется "виртуализация DPI". Она позволяет использовать старые программы на мониторах с высоким разрешением.

Вы должны явно сообщить ему, что вы можете обрабатывать более высокие настройки DPI, добавив <dpiAware> элемент к вашему манифесту. Страница MSDN находится здесь, но она не завершена, поскольку в ней не указаны настройки UAC. Project + Add New Item, выберите "Файл манифеста приложения". Отредактируйте текст манифеста или скопируйте / вставьте это:

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
    <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

Вы также можете вызвать функцию SetProcessDPIAware() в своем методе Main(), что необходимо, например, если вы развертываете с ClickOnce:

    [STAThread]
    static void Main() {
        if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());             // Edit as needed
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool SetProcessDPIAware();

ОБНОВЛЕНИЕ, эта общая потребность, наконец, немного легче, если вы используете VS2015 Update 1 или выше. Добавленный манифест уже имеет соответствующую директиву, просто удалите комментарии.


Ключевое слово для поиска, поэтому я могу найти этот пост назад: dpiAware

Приложения могут разрабатываться в двух разных режимах.

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

Второй вариант - объявить приложение как поддерживающее DPI. В этом случае ОС не будет выполнять масштабирование и позволит вашему приложению отображаться в соответствии с исходным разрешением экрана. В случае среды на монитор-DPI ваше приложение будет отображаться с самым высоким DPI из всех экранов, тогда это растровое изображение будет уменьшено до подходящего размера для каждого монитора. Уменьшение масштаба приводит к лучшему впечатлению от просмотра, чем масштабирование, но вы все равно можете заметить некоторую нечеткость.

Если вы хотите избежать этого, вы должны объявить ваше приложение как per-monitor-DPI-осведомленное. Затем вы должны определить, когда ваше приложение перетаскивается на разные мониторы, и выполнить рендеринг в соответствии с DPI текущего.

Объявление осведомленности о DPI выполняется в файле манифеста.

обратитесь к следующей ссылке

Используя.NET Framework 4.7 и Windows 10 Creators Update или более новую версию, вы должны выполнить следующие действия, чтобы настроить поддержку высокого разрешения для приложения Windows Form:

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

Чтобы сделать это, добавьте следующее к вашему manifest файл:

<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, добавьте следующее в файл конфигурации приложения.

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

Важный

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

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

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

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

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

Источник: поддержка высокого разрешения в Windows Forms.

Ни одно из этих предложений не сработало для меня, но что-то случилось после того, как я удалил Form.Font = new... от Form.Design.cs, форма начала правильно масштабироваться, она работает, если Шрифт определен в конструкторе или нет вообще. Зачем? кто-то другой может объяснить, я просто могу рассказать об изменениях, которые я сделал, и мне потребовалось несколько минут, чтобы понять, что это было основной причиной формы, над которой я работал. Надеюсь, поможет.

По крайней мере, начиная с Visual Studio 2017, вам просто нужно добавить файл манифеста и раскомментировать этот раздел:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
</application>

Это не ответ. Это моя работа вокруг. Ни один из приведенных выше ответов или комментариев не помог мне. Я также искал и пробовал другие методы.

Я использую Visual Studio.NET с C# и Windows.Forms с момента его первоначального выпуска. До VS 2022 и Windows 11 в этом году настройка режима масштабирования работала нормально. По какой-то причине некоторые из моих значений Form.Height уменьшаются во время выполнения. Пока проблем с изменением Form.Width не возникло. Для меня эта проблема началась 1 апреля 2022 года, поэтому я сначала подумал, что это первоапрельская шутка!

В любом случае, я пока отказался от попыток решения и решил, что для меня более практично просто установить Form.Size в коде конструктора.

Я наблюдаю, что пользовательский интерфейс дизайнера использует размер , который он преобразует в ClientSizeв его сгенерированном коде следующим образом:

        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
  this.ClientSize = new System.Drawing.Size(744, 109);
  this.ControlBox = false;
  this.DoubleBuffered = true;
  this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
  this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;

Мой обходной путь в конструкторе моей формы выглядит так:

      /// <summary>
/// Constructor
/// </summary>
public MyForm()
{
  // In the designer, MyForm.Size was entered and displayed as 760, 148
  InitializeComponent();

  // At runtime, MyForm.Size is changed to 760, 111
  // I will Reset this form's Size here so I can get full height again.
  this.Size = new Size(760, 148);
}

Платформа:

  • Windows 11 Профессиональная
  • Microsoft Visual Studio Professional 2022
  • Версия 17.1.6
  • VisualStudio.17.Выпуск/17.1.6+32421.90
  • Microsoft .NET Framework версии 4.8.04161
  • Инструменты С# 4.1.0-5.22165.10+e555772db77ca828b02b4bd547c318387f11d01f
  • Видео HDMI 1920x1080 (100% или без масштабирования)

Я боролся с этим уже много лет. Иногда я вношу изменения, которые работают, иногда нет. Теперь я наконец нашел настройку, которая работала для всех мониторов:

В файле app.config добавьте следующий раздел. Обратите внимание, что значение говорит «SystemDPIAware».

ваш экран будет выглядеть одинаково на всех мониторах

          <System.Windows.Forms.ApplicationConfigurationSection>
    <add key="DpiAwareness" value="SystemDPIAware"/>
  </System.Windows.Forms.ApplicationConfigurationSection>
Другие вопросы по тегам