Graphics.MeasureString возвращает значения, отличные от Win32 GetTextExtent - PullRequest
3 голосов
/ 15 октября 2008

Я пытался найти метод в C # для измерения размера строки. Стандартный метод для измерения строки в Win32 - это использование GetTextExtent. Настоящая цель - найти среднюю ширину и высоту шрифта. Стандартный метод определения средней ширины символа начинается с получения ширины всех буквенных символов и делится на 52:

size = dc.GetTextExtent(
       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52);
averageWidth = size / 52;

У Microsoft есть страница, на которой перечислены средние значения ширины символов для некоторых размеров шрифта при определенных настройках DPI, и я подтвердил их своими собственными вызовами GetTextExtent.

  • Tahoma 8pt, 96dpi: 13x6 px
  • Tahoma 9pt, 96dpi: 14x7 px
  • Segoe UI 9pt, 96dpi : 15x7 px

Теперь я хочу выполнить те же вычисления в .NET WinForms. Используя Graphics.MeasureString (), я придумаю код:

public static SizeF GetAvgCharSizeF(Graphics g, Font font)
{
   String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

   SizeF textSize = g.MeasureString(s, font);

   float baseUnitX = (textSize.Width / s.Length);
   float baseUnitY = textSize.Height;

   return new SizeF(baseUnitX, baseUnitY);
}

К сожалению, значения не соответствуют известным, принятым, истинным значениям:

  • Tahoma 8pt, 96dpi: 14x6 px (14.21x6.09 px)
  • Tahoma 9pt, 96dpi: 16x7 px (15,98x6,85 px)
  • Пользовательский интерфейс Segoe 9pt, 96dpi: 17x7 px (17,46x6,91 px)

Средняя ширина символов в порядке, но высота символов слишком велика примерно на 13%. Я предполагаю, что дополнительная высота обусловлена ​​различием в классификации высоты, которое было изменено, чтобы включать в себя восходящие и спусковые устройства. Если измерительная строка была слишком высокой, я попытался изменить ее на:

String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

до

String s = "acemnorsuvwxyz";

думая, что теперь строка не такая высокая, и поэтому измеренная высота должна быть короче. Нет, он возвращает точную такую ​​же высоту, что и версия строки, которая включает в себя восходящие и нисходящие (хотя средняя ширина немного больше).

Что может быть причиной этого, и может получить среднюю высоту символа, которую можно сделать для средней высоты текста, чтобы она соответствовала принятым значениям, возвращаемым GetTextExtent?

Примечание. Несмотря на то, что стандартной практикой для получения средней высоты символа является использование GetTextMetrics, высота, возвращаемая GetTextExtents, возвращает то же значение.

1 Ответ

3 голосов
/ 15 октября 2008

Я подозреваю, что это потому, что движок рендеринга текста отличается от .NET. Возможно, вы захотите посмотреть на различия между GDI и GDI +. Ситуация также может измениться для вас снова, если вы вызовете метод Application.SetCompatibleTextRenderingDefault(<bool>) с параметром true или false (я считаю, что по умолчанию установлено значение true).

Как правило, если вы рисуете с помощью Windows API, измеряйте с помощью Windows API, а если вы рисуете с .NET, измеряйте с помощью .NET.

...