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

104

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

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

Борис
источник

Ответы:

132

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

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

<?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

Ганс Пассан
источник
Спасибо, ваше решение работает нормально. Единственная проблема заключается в том, что все изображения теперь в исходном размере. Думаю, мне придется найти способ добавить дополнительные значки "сетчатки" в мой графический интерфейс ...
Борис
@HansPassant У меня такая же проблема с размытыми шрифтами, и после применения этого решения мои элементы управления не масштабируются и не подходят. Как заставить работать оба?
gajo357
2
Для тех, кто исследует это безумие Win8, SetProcessDPIAwareон устарел, и он также не работает должным образом (по крайней мере, не в Win8.1), вызывая непредсказуемое масштабирование для различных элементов управления. Вместо этого я настоятельно рекомендую использовать манифестный подход.
Джейсон Уильямс
5
Хмя, Windows 8.1 обзавелась dpi для каждого монитора. Я не знал, что мне это нужно.
Ханс Пассан
1
Если вы собираетесь использовать ClickOnce для развертывания, вы не можете использовать параметр dpiAware в манифесте, вместо этого используйте SetProcessDPIAware ().
Матиас
17

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

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

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

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

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

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

shanthi_karthika
источник
что, если у пользователей есть окно восстановленного размера и они перемещают его так, чтобы его части находились на разных мониторах? нам нужно отрендерить все дважды и использовать границы монитора как ограничивающие рамки? сколько из этого покрыто библиотеками winforms?
Cee McSharpface
4

Используя .NET Framework 4.7 и Windows 10 Creators Update (1703) или новее, вы должны выполнить следующие действия, чтобы настроить поддержку высокого разрешения для вашего приложения 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>

Включите в app.configфайле распознавание DPI для каждого монитора .

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

<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 Form1());   
}

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

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

Wollmich
источник
3

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

Васко Бонилья
источник
2

По крайней мере, начиная с 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>
Аранхо
источник