Как настроить приложение для правильной работы на компьютере с высокой настройкой 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.
Ни одно из этих предложений не сработало для меня, но что-то случилось после того, как я удалил 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>