Все ContainerControls должны быть одинаковыми AutoScaleMode = Font
. (Шрифт будет обрабатывать как изменения DPI, так и изменения настройки размера шрифта системы; DPI будет обрабатывать только изменения DPI, а не изменения настройки размера шрифта системы.)
Все Контейнерные AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
Контроллеры также должны быть установлены с одинаковым значением , принимая 96dpi (см. Следующий пункт) и шрифт по умолчанию MS Sans Serif (см. Раздел 2 ниже). Это автоматически добавляется дизайнером на основе DPI, в котором вы открываете дизайнер, но отсутствует во многих наших старых файлах дизайнеров. Возможно, Visual Studio .NET (версия до VS 2005) не добавляла это должным образом.
Все ваши дизайнерские работы в 96dpi (мы могли бы переключиться на 120dpi; но мудрость в Интернете говорит, что придерживаться 96dpi; экспериментирование здесь в порядке; дизайн не должен иметь значения, поскольку он просто меняет AutoScaleDimensions
линию, которая дизайнерские вставки). Чтобы настроить Visual Studio для работы с виртуальным разрешением 96 точек на дюйм на дисплее высокого разрешения, найдите его файл .exe, щелкните правой кнопкой мыши, чтобы изменить свойства, и в разделе «Совместимость» выберите «Переопределить поведение масштабирования с высоким DPI. Масштабирование выполняется: Система».
Убедитесь, что вы никогда не устанавливаете шрифт на уровне контейнера ... только на листовых элементах управления ИЛИ в конструкторе вашей самой базовой формы, если вы хотите использовать шрифт по умолчанию для всего приложения, кроме MS Sans Serif. (Установка шрифта на контейнере, по-видимому, отключает автоматическое масштабирование этого контейнера, потому что оно происходит в алфавитном порядке после настройки параметров AutoScaleMode и AutoScaleDimensions.) ПРИМЕЧАНИЕ: если вы действительно измените шрифт в конструкторе самой базовой формы, это приведет к ваши AutoScaleDimensions для вычисления не так, как 6x13; в частности, если вы переключитесь на пользовательский интерфейс Segoe (шрифт Win 10 по умолчанию), то он будет 7x15 ... вам нужно будет дотронуться до каждой формы в Designer, чтобы она могла пересчитать все измерения в этом файле .designer, включая AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
.
НЕ используйте Anchor Right
или Bottom
привязанный к UserControl ... его расположение не будет автоматически масштабироваться; вместо этого поместите Panel или другой контейнер в свой UserControl и привяжите другие элементы управления к этой Panel; есть использование панели Dock Right
, Bottom
или Fill
в вашем UserControl.
Только элементы управления в списках элементов управления при вызове ResumeLayout
в конце InitializeComponent
будут автоматически масштабироваться ... если вы динамически добавляете элементы управления, то вам нужно SuspendLayout();
AutoScaleDimensions = new SizeF(6F, 13F);
AutoScaleMode = AutoScaleMode.Font;
ResumeLayout();
включить этот элемент управления перед его добавлением. И ваше позиционирование также необходимо будет отрегулировать если вы не используете режимы док-станции или менеджер раскладок, например FlowLayoutPanel
или TableLayoutPanel
.
Базовые классы, полученные из, ContainerControl
должны оставаться AutoScaleMode
установленными Inherit
(значение по умолчанию, установленное в классе ContainerControl
; но НЕ по умолчанию, установленное дизайнером). Если вы установите его на что-то другое, а затем ваш производный класс попытается установить его на Font (как и должно быть), то сам акт установки этого параметра Font
очистит настройки дизайнера AutoScaleDimensions
, что приведет к отключению автоматического масштабирования! (Это руководство в сочетании с предыдущим означает, что вы никогда не можете создавать экземпляры базовых классов в конструкторе ... все классы должны быть разработаны как базовые классы или как листовые классы!)
Избегайте использования Form.MaxSize
статически / в конструкторе. MinSize
и MaxSize
на форме не масштабировать столько, сколько все остальное. Таким образом, если вы выполняете всю свою работу с разрешением 96 точек на дюйм, то при более высоком значении DPI MinSize
это не вызовет проблем, но может быть не таким ограничительным, как вы ожидали, но вы MaxSize
можете ограничить масштабирование размера, что может вызвать проблемы. Если вы хотите MinSize == Size == MaxSize
, не делайте этого в Designer ... делайте это в конструкторе или OnLoad
переопределении ... установите оба параметра MinSize
и MaxSize
ваш правильно масштабированный размер.
Все элементы управления для конкретного Panel
или Container
должны использовать привязку или стыковку. Если вы смешаете их, то автоматическое масштабирование, которое выполняется этим, Panel
часто будет вести себя нечетко странным образом.
Когда он выполняет автоматическое масштабирование, он будет пытаться масштабировать всю форму ... однако, если в этом процессе он достигает верхнего предела размера экрана, это жесткое ограничение, которое затем может испортить (обрезать) масштабирование Поэтому следует убедиться, что все формы в Designer с разрешением 100% / 96 точек на дюйм имеют размер не более 1024x720 (что соответствует 150% на экране 1080p или 300%, что является рекомендуемым значением Windows на экране 4K). Но вам нужно вычесть для гигантской строки заголовка / заголовка Win10 ... так что больше похоже на максимальный размер 1000x680 ... которое в конструкторе будет похоже на 994x642 ClientSize. (Таким образом, вы можете найти FindAll References на ClientSize, чтобы найти нарушителей.)
NumericUpDown
тоже неMargin
правильно масштабирует . Кажется, маржа масштабируется дважды. Если я уменьшу его один раз, это выглядит хорошо.AutoScaleMode = Font
плохо работает для пользователей, которые используют очень большой шрифт и в Ubuntu. Мы предпочитаемAutoScaleMode = DPI
Мой опыт довольно сильно отличается от нынешнего наиболее популярного ответа. Проходя через код платформы .NET и просматривая исходный код ссылки, я пришел к выводу, что все готово для автоматического масштабирования, и где-то была только небольшая проблема, которая его испортила. Это оказалось правдой.
Если вы создаете правильно перекомпоновываемый макет с автоматическим изменением размера, то почти все работает точно так же, как и автоматически, с настройками по умолчанию, используемыми Visual Studio (а именно, AutoSizeMode = Font в родительской форме и Inherit во всем остальном).
Единственное, что нужно, это если вы установили свойство Font на форму в конструкторе. Сгенерированный код отсортирует назначения в алфавитном порядке, что означает, что
AutoScaleDimensions
они будут назначены ранееFont
. К сожалению, это полностью нарушает логику автоматического масштабирования WinForms.Исправление просто, хотя. Либо вообще не устанавливайте
Font
свойство в конструкторе (задайте его в конструкторе формы), либо вручную переупорядочивайте эти назначения (но тогда вам придется продолжать делать это каждый раз, когда вы редактируете форму в конструкторе). Вуаля, почти идеальное и полностью автоматическое масштабирование с минимальными хлопотами. Даже размеры форм правильно масштабируются.Я перечислю известные проблемы здесь, поскольку я сталкиваюсь с ними:
TableLayoutPanel
неправильно вычисляет контрольные поля . Нет известного обходного пути, за исключением полного исключения полей и отступов или обхода вложенных панелей макета таблицы.источник
Font
в конструкторе: на ум приходит мысль: продолжайте и установите шрифт в конструкторе, чтобы вы могли создавать желаемый шрифт. ТОГДА в конструкторе, после разметки, прочитал это свойство шрифта и снова установил то же значение? Или, может быть, просто попросить сделать макет еще раз? [Предостережение: у меня не было причин тестировать этот подход.] Или, согласно ответу Ноулека , в конструкторе укажите пиксели (чтобы дизайнер Visual Studio не изменял масштаб на мониторе с высоким DPI), а в коде прочитайте это значение, конвертируйте из пикселей в баллы (чтобы получить правильное масштабирование).AutoScaleDimensions
не было установлено в соответствииnew SizeF(6F, 13F)
с рекомендациями в верхнем ответе. Оказалось, что в каждом случае было установлено свойство Font формы (не по умолчанию). Похоже, что когдаAutoScaleMode = Font
, тоAutoScaleDimensions
рассчитывается на основе свойства шрифта формы. Кроме того, настройка масштабирования в панели управления Windows, похоже, влияет наAutoScaleDimensions
.Настройте свое приложение для .Net Framework 4.7 и запустите его под Windows 10 v1703 (Creators Update Build 15063). В .Net 4.7 под Windows 10 (v1703) MS сделала много улучшений DPI .
Для его поддержки добавьте манифест приложения в свое приложение и сообщите, что ваше приложение поддерживает Windows 10:
Затем добавьте
app.config
и объявите приложение Per Monitor Aware. Это сейчас сделано в app.config, а НЕ в манифесте, как раньше!Это PerMonitorV2 является новым с момента обновления Windows 10 Creators:
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
Теперь вы можете подписаться на 3 новых события, чтобы получать уведомления об изменениях DPI:
У вас также есть 3 вспомогательных метода для обработки / масштабирования DPI:
Control.LogicalToDeviceUnits , который преобразует значение из логических пикселей в пиксели устройства.
Control.ScaleBitmapLogicalToDevice , который масштабирует растровое изображение до логического DPI для устройства.
Control.DeviceDpi , который возвращает DPI для текущего устройства.
Если вы по-прежнему видите проблемы, вы можете отказаться от улучшений DPI с помощью записей app.config .
Если у вас нет доступа к исходному коду, вы можете перейти к свойствам приложения в проводнике Windows, перейти к совместимости и выбрать
System (Enhanced)
который активирует масштабирование GDI, чтобы также улучшить обработку DPI:
Выполните все эти шаги, и вы должны получить лучший опыт DPI для приложений WinForms. Но помните, что вам нужно ориентировать свое приложение на .net 4.7 и по крайней мере Windows 10 Build 15063 (Creators Update). В следующем обновлении Windows 10 1709 мы можем получить больше улучшений.
источник
Руководство, которое я написал на работе:
источник
Мне было очень сложно заставить WinForms хорошо играть с высоким DPI. Итак, я написал метод VB.NET для переопределения поведения формы:
источник
Недавно я столкнулся с этой проблемой, особенно в сочетании с масштабированием Visual Studio при открытии редактора в системе с высоким разрешением. Я нашел , что лучше держать
AutoScaleMode = Font
, но чтобы установить формы шрифта для шрифта по умолчанию, но указав размер в пикселях , а не точку, то есть:Font = MS Sans; 11px
. В коде я затем сбрасываю шрифт к значению по умолчанию:Font = SystemFonts.DefaultFont
и все в порядке.Просто мои два цента. Я думал, что поделюсь, потому что «держать AutoScaleMode = Font» и «Установить размер шрифта в пикселях для дизайнера» было то, что я не нашел в Интернете.
У меня есть некоторые подробности в моем блоге: http://www.sgrottel.de/?p=1581&lang=en
источник
В дополнение к тому, что якоря работают не очень хорошо: я бы пошел дальше и сказал, что точное позиционирование (то есть использование свойства Location) не очень хорошо работает с масштабированием шрифта. Мне пришлось решать эту проблему в двух разных проектах. В обоих случаях нам пришлось преобразовать расположение всех элементов управления WinForms в использование TableLayoutPanel и FlowLayoutPanel. Использование свойства Dock (обычно устанавливается в Fill) внутри TableLayoutPanel работает очень хорошо и хорошо масштабируется с помощью системного шрифта DPI.
источник