Я пытался найти метод в C# для измерения размера строки. стандартный метод для измерения строки в Win32 заключается в использовании GetTextExtent. Настоящая цель - найти ширину и высоту в среднем символа шрифта. Стандартный метод определения средней ширины символа начинается с получения ширины всех буквенных символов и деления на 52:
size = dc.GetTextExtent(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52);
averageWidth = size / 52;
У Microsoft есть страница, на которой перечислены средняя ширина символа для некоторых размеров шрифтов при определенных настройках DPI, и я подтвердил их своими собственными вызовами GetTextExtent.
Теперь я хочу выполнить те же вычисления в .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);
}
К сожалению, значения не соответствуют известным, принятым и истинным значениям:
Средняя ширина символов в порядке, но высота символов слишком велика примерно на 13%. Я предполагаю, что дополнительная высота связана с разницей в классификации высоты, которая была изменена для включения восходящих и нисходящих элементов. Если измерительная струна была слишком высокой, я попытался изменить ее с:
String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
к
String s = "acemnorsuvwxyz";
думая, что теперь веревка не такая высокая, и поэтому измеренная высота должна быть короче. Нет, он возвращает точный ту же высоту, что и версия строки, которая включала восходящие и нисходящие элементы (хотя средняя ширина немного больше).
Что может быть причиной этого и можно ли получить среднюю высоту символа, что можно сделать со средней высотой текста, чтобы она соответствовала принятым значениям, возвращаемым GetTextExtent?
Примечание. Несмотря на то, что стандартной практикой получения средней высоты символа является использование GetTextMetrics, высота, возвращаемая GetTextExtents, возвращает то же значение.





Я подозреваю, что это связано с тем, что механизм визуализации текста в .NET отличается. Возможно, вы захотите найти различия между GDI и GDI +. Все может снова измениться для вас, если вы вызовете метод Application.SetCompatibleTextRenderingDefault(<bool>) с параметром true или false (я считаю, что значение по умолчанию истинно).
В общем, если вы рисуете с помощью Windows API, измеряйте с помощью Windows API, а если вы рисуете с помощью .NET, измеряйте с помощью .NET.
Стандартные положения и размеры элементов управления выражаются в терминах «средний размер символа с высотой». Если средняя ширина и высота меняются в зависимости от того, кто измеряет, вы теряете стандарт.
Я понял, что действительно существует разница между текстом Graphics.MeasureString и GDI. Проблема была настолько серьезной, что, начиная с .NET Framwork 2.0, Microsoft переключила все в .NET на использование GDI для рендеринга текста. Вот что такое класс TextRenderer. Он содержит два метода (MeasureString и DrawString), которые просто вызывают GDI. А поскольку GDI продолжает улучшаться (скорость, лигатуры и т. д.), TextRenderer является предпочтительным способом визуализации текста в .NET. Graphics.DrawString мертв и существует только для совместимости.
Вы пробовали TextRenderer.MeasureText?