TextRenderer.DrawText по-разному отображает Arial в XP и Vista

У меня есть приложение aC#, которое выполняет рендеринг текста, что-то наравне с простым текстовым редактором wysiwyg.

Я использую TextRenderer.DrawText для визуализации текста на экране и GetTextExtentPoint32 для измерения текста, чтобы я мог расположить разные стили / размеры шрифта на одной строке.

В Vista это все работает нормально. В XP, однако, Arial отображает по-разному, некоторые символы, такие как 'o' и 'b', занимают больше ширины, чем в Vista. GetTextExtentPoint32, кажется, измеряет строку, как это было бы в Vista, хотя и с меньшей шириной. Конечным результатом является то, что время от времени текст будет перекрывать текст, предшествующий ему, потому что предыдущий текст измеряется как меньше, чем на самом деле на экране.

Кроме того, мой код рендеринга текста имитирует, т. Е. Рендеринг текста точно (только для простого форматирования и только на английском языке) и т. Е. Рендеринг текста кажется согласованным между vista и xp - вот как я заметил изменение размера различных символов.

У кого-нибудь есть идеи о том, что происходит?

Короче говоря, TextRenderer.DrawText и GetTextExtentPoint32 не совпадают в xp для Arial. DrawText, кажется, рисует определенные символы больше и / или меньше, чем в Vista, но GetTextExtentPoint32, кажется, измеряет текст так же, как в Vista (что, похоже, соответствует отображению текста, например, на xp и vista). Надеюсь, что это имеет смысл.

Примечание. К сожалению, TextRenderer.MeasureString недостаточно быстр и точен для удовлетворения моих требований. Я попытался использовать это и должен был вырвать это.

3 ответа

Спасибо, что нашли время ответить Адриан.

Насколько я понимаю, TextRenderer.DrawText фактически оборачивает вызов GDI, полностью обойдя отрисовку текста GDI+. Вот почему меня смутило, что GetTextExtentPoint32 не работает с выводом.

Я думаю, что нашел проблему, хотя. Оказывается, если вы установите для Graphics.TextRenderingHint значение System.Drawing.Text.TextRenderingHint.ClearTypeGridFit или, возможно, другие значения, это приведет к увеличению или уменьшению размера некоторых символов в некоторых шрифтах. Это похоже на правду больше в XP, чем в Vista. Я не видел, чтобы это произошло вообще в Vista. В любом случае, похоже, что GetTextExtentPoint32 либо не способен распознать разницу, либо я не устанавливаю какой-либо флаг при выполнении вызова.

Мое решение состоит в том, чтобы просто использовать системные настройки textrenderinghint.

На самом деле и DrawText TextRenderer, и MeasureString основаны на DrawTextEx (а это User32, а не функция Gdi). Таким образом, вы можете рассмотреть возможность использования собственных маршализованных вызовов этой функции вместо MeauseString, потому что она выполняет некоторые дополнительные вычисления (особенно если вы используете переопределение функций без HDC).

Также, возможно, этот пост будет вам полезен.

Я не C# парень, но я считаю, что.NET рендеринг построен на основе GDI+. Я также почти уверен, что GDI + делает свой собственный рендеринг шрифтов, который использует негласное масштабирование.

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

Вы должны последовательно использовать ту или иную модель, чтобы получить идеальные по пикселям результаты.

В игре могут быть и другие факторы, которые могут сделать это более очевидным в XP, чем в Vista, но фундаментальная проблема существует в обоих случаях. Эти другие факторы могут включать настройки DPI, масштабирование DPI, настройки ClearType или сглаживания, связывание шрифтов (если вы смешиваете скрипты из других алфавитов), замену шрифтов (особенно при печати) и, возможно, даже разные версии Arial. Я даже не уверен, что GDI + использует тот же режим отображения по умолчанию, что и GDI.

Также смотрите мой ответ на предварительный просмотр.

Другие вопросы по тегам