Как преобразовать DLU в пиксели?

Microsoft использует единицы длины диалогового окна (DLU) в своих рекомендациях для пользовательского интерфейса. Как преобразовать их в пиксели?

Насколько я знаю, DLU зависит от размера системного шрифта. Можете посоветовать какой-нибудь простой способ такой конвертации в Delphi для Win32?


person Andrew    schedule 29.07.2011    source источник


Ответы (3)


Вам следует использовать функцию MapDialogRect() .

Передайте RECT в единицах диалогового окна, и будет возвращен эквивалент RECT в единицах пикселей. Обратите внимание, что вам нужен дескриптор диалога, чтобы дать MapDialogRect() достаточный контекст. Функция должна знать шрифт, чтобы выполнить преобразование.


Если у вас возникнет соблазн использовать _5 _, помните, что сказал Рэймонд Чен: GetDialogBaseUnits - это посуда .

Как вы можете догадаться из названия этой записи, GetDialogBaseUnits - это черепаха. Поскольку для GetDialogBaseUnits нет параметра HWND, он не знает, какие DLU диалогового окна вы хотите получить. Так что догадки.

И он всегда ошибается.

GetDialogBaseUnits возвращает базовые единицы диалогового окна для диалоговых окон, в которых используется системный шрифт по умолчанию. Но системный шрифт по умолчанию больше никто не использует. Он кричит «старый и тупой». Но он остается по умолчанию из соображений совместимости. (И, следовательно, GetDialogBaseUnits тоже.)

Если вам нужно рассчитать размеры в пикселях из DLU и у вас нет дескриптора диалогового окна, вы должны использовать метод, описанный здесь: Как рассчитать базовые единицы диалогового окна с несистемным шрифтом


Однако в комментариях вы дали понять, что для решения вашей проблемы вам на самом деле не нужно преобразовывать DLU в пиксели. Вы можете использовать встроенное в Delphi масштабирование форм, чтобы гарантировать, что ваши формы имеют размер, соответствующий преобладающему масштабированию шрифтов.

person David Heffernan    schedule 29.07.2011
comment
Для этой функции требуется HWND диалогового окна, но что, если мое окно не является диалоговым? Могу ли я получить HWND стандартного диалога где-нибудь в системе? - person Andrew; 29.07.2011
comment
блоки диалога бессмысленны без контекста. У вас должен быть диалог. - person David Heffernan; 29.07.2011
comment
Простой пример: я хочу установить размер моих командных кнопок на стандартную высоту. Стандартная высота = 14 DLU. В моем приложении нет диалогового окна. :( - person Andrew; 29.07.2011
comment
DLU имеют значение только относительно некоторого шрифта. Установите для кнопок высоту 23 пикселя в dfm 96 точек на дюйм, а масштабирование формы delphi сделает все остальное. - person David Heffernan; 29.07.2011

Сначала мы начнем с того, что представляет собой диалоговое окно.

Для этого я процитирую один из моих собственных вопросов без ответа :

Что такое блок диалога?

Диалог - это единица измерения, основанная на предпочитаемом пользователем размере шрифта. Блок диалога определяется таким образом, что средний символ имеет ширину 4 блока диалога и высоту 8 блоков диалога:

введите описание изображения здесь

Это означает, что диалоговые блоки:

  • изменить выбранным шрифтом
  • изменено с выбранной настройкой DPI
  • не квадратные

я также процитирую еще один из моих собственных вопросов без ответа < / а>:

Вы можете ознакомиться с рекомендациями по пользовательскому интерфейсу Windows, чтобы узнать, откуда берутся эти измерения. Краткая версия:

  • dlu = блок диалога
  • dlu зависит от размера шрифта (элементы меняются в зависимости от размера шрифта пользователя)
  • горизонтальный dlu отличается от вертикального dlu (dlu не квадратные)

Это происходит из определения блока диалога: средний символ составляет 8dlus в высоту на 4dlus в ширину.

Грузия 14 пунктов:

введите описание изображения здесь

Если вы используете более мелкий шрифт (например, 8pt Tahoma стих 14pt Georgia), dlus станет меньше:

Segoe UI 9pt:

введите описание изображения здесь

Примечание. Вы заметите, что разрешение (т. е. dpi) не влияет на обсуждение.

Итак, вам нужен средний размер символа. У Microsoft есть официальная методика для расчета среднего размера символа.

  • Средняя высота:

    GetTextMetrics(dc, {var}textMetrics);
    averageHeight := textMetrics.tmHeight;
    
  • средняя ширина:

    Измерьте строку ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz, используя person Ian Boyd    schedule 21.05.2012


Для базового значения (и, естественно, системного шрифта) вызовите GetDialogBaseUnits < / а>. См. Также абзац remarks там, где описан альтернативный метод перевода единиц диалога ‹-> пикселей с GetTextMetrics и / или GetTextExtentPoint32 без HWND диалогового окна.

person Premature Optimization    schedule 30.07.2011
comment
Системный шрифт используется только в том случае, если в шаблоне диалогового окна не удается указать шрифт. Большинство шаблонов диалоговых окон задают шрифт; в результате эта функция бесполезна для большинства диалоговых окон. Для диалогового окна, в котором не используется системный шрифт, базовыми единицами измерения являются средняя ширина и высота в пикселях символов шрифта диалогового окна. Вы можете использовать функции GetTextMetrics и GetTextExtentPoint32, чтобы вычислить эти значения для выбранного шрифта. Однако, используя функцию MapDialogRect, вы можете избежать ошибок, которые могут возникнуть, если ваши вычисления будут отличаться от вычислений, выполняемых системой. - person David Heffernan; 30.07.2011
comment
@ Дэвид Хеффернан, ваше первоначальное предложение просто не будет работать с VCL. Прочтите замечания, они жизненно необходимы для понимания концепции. - person Premature Optimization; 30.07.2011
comment
VCL не использует DLU. Формы VCL также не подходят для GetDialogBaseUnits. Вы читали текст msdn, в котором говорится не использовать GetDialogBaseUnits? - person David Heffernan; 30.07.2011
comment
@ Дэвид Хеффернан, да, я знал. Я также не остановился на этих словах и прочитал другой текст, который показывает, как решить проблему, сделав ваше решение неработающим. - person Premature Optimization; 30.07.2011
comment
так вы утверждаете, что MapDialogRect () сейчас не работает? Вам нужно прекратить поверхностную вендетту. - person David Heffernan; 30.07.2011
comment
@David Heffernan, это никогда не было подходящим решением, однако вы забыли удалить комментарий, в котором вы признали этот факт :) - person Premature Optimization; 30.07.2011