MeasureString() накладывает текст слева и справа
Я использую GDI + в С++. (Эта проблема может существовать и на С#).
Я замечаю, что всякий раз, когда я вызываю Graphics:: MeasureString() или Graphics:: DrawString(), строка заполняется пробелом слева и справа.
Например, если я использую шрифт Courier (не курсив!), и я измеряю "P", я получаю 90, но "PP" дает мне 150. Я ожидаю, что моноширинный шрифт даст ровно вдвое большую ширину для "PP".
Мой вопрос: это намеренное или задокументированное поведение и как его отключить?
RectF Rect(0,0,32767,32767);
RectF Bounds1, Bounds2;
graphics->MeasureString(L"PP", 1, font, Rect, &Bounds1);
graphics->MeasureString(L"PP", 2, font, Rect, &Bounds2);
margin = Bounds1.Width * 2 - Bounds2.Width;
Ответы
Ответ 1
Это по дизайну, этот метод не использует фактические глифы для измерения ширины и поэтому добавляет немного отступов в случае выступов.
MSDN предлагает использовать другой метод, если вам нужна более высокая точность:
Чтобы получить метрики, подходящие для смежных строк в макете (например, при форматировании текста), используйте метод MeasureCharacterRanges или один методов MeasureString, который принимает StringFormat и передать GenericTypographic. Кроме того, TextRenderingHint для Graphics AntiAlias .
Ответ 2
Это правда, что по дизайну, однако ссылка на принятый ответ на самом деле не идеальна. Проблема заключается в использовании float во всех этих методах, когда вы действительно хотите использовать пиксели (ints).
класс TextRenderer предназначен для этой цели и работает с истинными размерами. См. Ссылку из msdn для прочтения этого использования.
Ответ 3
Append StringFormat.GenericTypographic
исправит вашу проблему:
graphics->MeasureString(L"PP", 1, font, width, StringFormat.GenericTypographic);
Применить тот же атрибут к DrawString
.
Ответ 4
Похоже, он также может подключаться к намекая, на основе этой т.п.н. статье Почему появляется текст отличается при рисовании с GDIPlus против GDI
Ответ 5
TextRenderer отлично подходит для получения размера шрифта. Но в цикле рисования использование TextRenderer.DrawText было мучительно медленным по сравнению с graphics.DrawString().
Поскольку ширина строки является проблемой, гораздо лучше использовать комбинацию TextRenderer.MeasureText и graphics.DrawString..