Примечание. Просмотрите другие ответы, поскольку они содержат очень ценные приемы. Мой ответ здесь содержит только предостережения и предостережения против предположения, что осведомленность о DPI - это просто.
Я обычно избегаю масштабирования с учетом DPI с помощью TForm.Scaled = True
. Осведомленность о DPI важна для меня только тогда, когда это становится важным для клиентов, которые звонят мне и готовы за это платить. Техническая причина этой точки зрения заключается в том, что осведомленность о DPI или нет, вы открываете окно в мир боли. Многие стандартные и сторонние элементы управления VCL не работают с высоким разрешением. Заметным исключением является то, что части VCL, которые охватывают общие элементы управления Windows, работают замечательно при высоком разрешении. Огромное количество сторонних и встроенных пользовательских элементов управления Delphi VCL не работают должным образом или вообще не работают при высоком разрешении. Если вы планируете включить TForm.Scaled, обязательно протестируйте 96, 125 и 150 DPI для каждой формы в вашем проекте, а также для всех сторонних и встроенных элементов управления, которые вы используете.
Сам Delphi написан на Delphi. В нем включен флаг осведомленности о высоком разрешении для большинства форм, хотя даже совсем недавно, как в Delphi XE2, авторы среды разработки сами решили НЕ включать этот флаг манифеста о высоком разрешении на разрешение. Обратите внимание, что в Delphi XE4 и более поздних версиях флаг поддержки HIGH DPI включен, и среда IDE выглядит хорошо.
Я предлагаю вам не использовать TForm.Scaled = true (который используется по умолчанию в Delphi, поэтому, если вы не изменили его, большинство ваших форм имеют Scaled = true) с флагами High DPI Aware (как показано в ответах Дэвида) с Приложения VCL, созданные с использованием встроенного конструктора форм delphi.
В прошлом я пытался сделать минимальный образец поломки, которую вы можете ожидать увидеть, когда TForm.Scaled имеет значение true и когда масштабирование формы Delphi имеет сбой. Эти сбои не всегда и вызываются только значением DPI, отличным от 96. Мне не удалось определить полный список других вещей, включая изменения размера шрифта Windows XP. Но поскольку большинство этих сбоев появляется только в моих собственных приложениях, в довольно сложных ситуациях я решил показать вам некоторые доказательства, которые вы можете проверить самостоятельно.
Delphi XE выглядит так, когда вы устанавливаете масштабирование DPI на «Fonts @ 200%» в Windows 7, и Delphi XE2 так же не работает в Windows 7 и 8, но эти сбои, похоже, исправлены в Delphi XE4:
В основном это стандартные элементы управления VCL, которые некорректно работают при высоком разрешении. Обратите внимание, что большинство вещей вообще не масштабировалось, поэтому разработчики IDE Delphi решили игнорировать осведомленность о DPI, а также отключить виртуализацию DPI. Такой интересный выбор.
Отключите виртуализацию DPI, только если вам нужен этот новый дополнительный источник боли и трудный выбор. Я предлагаю вам оставить это в покое. Обратите внимание, что общие элементы управления Windows в основном работают нормально. Обратите внимание, что элемент управления обозревателя данных Delphi представляет собой оболочку C # WinForms вокруг стандартного общего элемента управления деревом Windows. Это чистый сбой Microsoft, и для его исправления может потребоваться, чтобы Embarcadero либо переписал чистый родной элемент управления деревом .Net для своего проводника данных, либо написал код DPI-check-and-modify-properties для изменения высоты элементов в элементе управления. Даже Microsoft WinForms не может обрабатывать высокий DPI чисто, автоматически и без специального кода kludge.
Обновление: интересный факт: хотя среда IDE delphi не кажется «виртуализированной», она не использует содержимое манифеста, показанное Дэвидом, для достижения «виртуализации без DPI». Возможно, он использует какую-то функцию API во время выполнения.
Обновление 2: в ответ на то, как я буду поддерживать 100% / 125% DPI, я бы предложил двухэтапный план. Фаза 1 - инвентаризация моего кода для настраиваемых элементов управления, которые необходимо исправить для высокого разрешения, а затем составить план их исправления или постепенного отказа. Фаза 2 заключалась в том, чтобы взять некоторые области моего кода, которые разработаны как формы без управления макетом, и преобразовать их в формы, которые используют какое-то управление макетом, чтобы изменение DPI или высоты шрифта могло работать без отсечения. Я подозреваю, что такая компоновка «между элементами управления» будет намного более сложной для большинства приложений, чем работа «внутри управления».
Обновление: в 2016 году последняя версия Delphi 10.1 Berlin хорошо работает на моей рабочей станции с разрешением 150 dpi.
SetProcessDPIAware
.Ваши настройки в файле .dfm будут правильно увеличены, пока
Scaled
естьTrue
.Если вы устанавливаете размеры в коде, вам нужно масштабировать их,
Screen.PixelsPerInch
разделив наForm.PixelsPerInch
. ИспользуйтеMulDiv
для этого.Это то, что делает фреймворк сохранения формы, когда
Scaled
естьTrue
.Фактически, вы можете привести убедительный аргумент в пользу замены этой функции версией, которая жестко кодирует значение 96 в качестве знаменателя. Это позволяет вам использовать абсолютные значения размеров и не беспокоиться об изменении значения, если вы случайно измените масштаб шрифта на своей машине разработки и повторно сохраните файл .dfm. Причина, по которой это имеет значение, заключается в том, что
PixelsPerInch
свойство, хранящееся в файле .dfm, является значением компьютера, на котором последний раз был сохранен файл .dfm.Итак, продолжая тему, еще одна вещь, которой следует опасаться, заключается в том, что если ваш проект разрабатывается на нескольких машинах с разными значениями DPI, вы обнаружите, что масштабирование, которое Delphi использует при сохранении файлов .dfm, приводит к блужданию элементов управления по серии изменений. . На моем рабочем месте, чтобы избежать этого, мы придерживаемся строгой политики, согласно которой формы всегда редактируются только с разрешением 96 точек на дюйм (100% масштабирование).
Фактически, моя версия
ScaleFromSmallFontsDimension
также допускает возможность отличия шрифта формы во время выполнения от шрифта, установленного во время разработки. На машинах XP мои формы приложения используют 8pt Tahoma. В Vista и выше используется пользовательский интерфейс Segoe с разрешением 9 пунктов. Это дает еще одну степень свободы. При масштабировании необходимо учитывать это, потому что абсолютные значения измерений, используемые в исходном коде, считаются относительными к базовой линии 8pt Tahoma при 96dpi.Если вы используете какие-либо изображения или глифы в своем пользовательском интерфейсе, их тоже нужно масштабировать. Типичным примером могут служить глифы, которые используются на панелях инструментов и в меню. Вы захотите предоставить эти глифы в качестве ресурсов значков, связанных с вашим исполняемым файлом. Каждый значок должен содержать диапазон размеров, а затем во время выполнения вы выбираете наиболее подходящий размер и загружаете его в список изображений. Некоторые подробности по этой теме можно найти здесь: Как мне загружать значки с ресурса, не страдая от алиасинга?
Другой полезный прием - определение размеров в относительных единицах относительно
TextWidth
илиTextHeight
. Итак, если вы хотите, чтобы что-то было размером около 10 вертикальных линий, вы можете использовать10*Canvas.TextHeight('Ag')
. Это очень приблизительная и готовая метрика, потому что она не учитывает межстрочный интервал и так далее. Однако часто все, что вам нужно сделать, это уметь правильно масштабировать графический интерфейсPixelsPerInch
.Вы также должны отметить свое приложение как поддерживающее высокое разрешение . Лучше всего это сделать через манифест приложения. Поскольку инструменты сборки Delphi не позволяют настраивать манифест, который вы используете, это заставляет вас связать собственный ресурс манифеста.
Сценарий ресурса выглядит так:
где
Manifest.txt
содержит фактический manifest. Вам также нужно будет включить раздел comctl32 v6 и установитьrequestedExecutionLevel
значениеasInvoker
. Затем вы связываете этот скомпилированный ресурс со своим приложением и убедитесь, что Delphi не пытается сделать то же самое со своим манифестом. В современном Delphi этого можно добиться, установив для параметра проекта Runtime Themes значение None.Манифест - это верный способ заявить, что ваше приложение поддерживает высокий уровень DPI. Если вы просто хотите быстро опробовать его, не вмешиваясь в манифест, позвоните
SetProcessDPIAware
. Сделайте это в первую очередь при запуске приложения. Желательно в одном из первых разделов инициализации модуля или первым делом в вашем файле .dpr.Если вы не заявляете, что ваше приложение поддерживает высокий уровень разрешения, то Vista и более поздние версии будут отображать его в устаревшем режиме для любого масштабирования шрифта выше 125%. Это выглядит ужасно. Постарайтесь не попасть в эту ловушку.
Обновление Windows 8.1 для каждого монитора
Начиная с Windows 8.1, теперь ОС поддерживает настройки DPI для каждого монитора ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). Это большая проблема для современных устройств, к которым могут быть подключены разные дисплеи с очень разными возможностями. У вас может быть экран ноутбука с очень высоким разрешением и внешний проектор с низким разрешением. Поддержка такого сценария требует еще больше усилий, чем описано выше.
источник
Также важно отметить, что соблюдение DPI пользователя - это лишь часть вашей реальной работы:
На протяжении десятилетий Windows решала эту проблему, создавая макет с использованием диалоговых единиц , а не пикселей. «Диалог единица» определяется так , что шрифт в среднем характера является
Delphi действительно поставляется с (ошибочным) понятием
Scaled
, когда форма пытается автоматически настраиваться на основеЭто не решает проблему, когда пользователь использует шрифт, отличный от того, который вы использовали для формы, например:
6.21px x 13.00px
96 точек на дюйм)пользователь, работающий с Tahoma 8pt (где средний символ -
5.94px x 13.00px
96 точек на дюйм)Как и в случае с любым, кто разрабатывает приложение для Windows 2000 или Windows XP.
или
5.94px x 13.00px
96 точек на дюйм)6.67px x 15px
96 точек на дюйм)Как хороший разработчик, вы будете уважать предпочтения шрифтов вашего пользователя. Это означает, что вам также необходимо масштабировать все элементы управления в вашей форме в соответствии с новым размером шрифта:
Scaled
не справится с этим за вас.Становится хуже, когда:
10.52px x 25px
Теперь вам нужно все масштабировать
Scaled
не справится с этим за вас.Если вы умны, вы можете увидеть, насколько безразлично соблюдение DPI:
Вы не должны смотреть на настройки DPI пользователя, вы должны смотреть на их размер шрифта . Два пользователя работают
используют тот же шрифт . DPI - это только одна вещь, которая влияет на размер шрифта; предпочтения пользователя - другое.
StandardizeFormFont
Кловис заметил, что я ссылаюсь на функцию,
StandardizeFormFont
которая исправляет шрифт в форме и масштабирует его до нового размера шрифта. Это не стандартная функция, а полный набор функций, которые выполняют простую задачу, с которой Borland никогда не справлялся.В Windows 6 разных шрифтов; в Windows нет единой «настройки шрифта».
Но по опыту мы знаем, что наши формы должны соответствовать настройке шрифта заголовка значка.
После того, как мы знаем , размер шрифта , мы будем масштабировать форму к , мы получаем текущую высоту шрифта в формах ( в пикселях ), и масштабах по этому фактору.
Например, если я устанавливаю форму
-16
, и форма в настоящее время находится-11
, то нам нужно масштабировать всю форму следующим образом:Стандартизация происходит в два этапа. Сначала масштабируйте форму по соотношению новых и старых размеров шрифта. Затем фактически измените элементы управления (рекурсивно), чтобы использовать новый шрифт.
Вот работа по фактическому масштабированию формы. Он работает с ошибками в собственном
Form.ScaleBy
методе Borland . Сначала он должен отключить все привязки в форме, затем выполнить масштабирование, а затем снова включить привязки:а затем мы должны рекурсивно использовать новый шрифт:
С рекурсивно отключенными якорями:
И якоря повторно активируются рекурсивно:
С работой по фактическому изменению шрифта элементов управления осталось:
Это намного больше кода, чем вы думали; Я знаю. Печально то, что на земле нет разработчика Delphi, кроме меня, который на самом деле делает свои приложения правильными.
источник
Вот мой подарок. Функция, которая может помочь вам с горизонтальным расположением элементов в макете графического интерфейса. Бесплатно для всех.
источник