TextRenderer.MeasureText и Graphics.MeasureString не соответствуют размеру - PullRequest
26 голосов
/ 15 июля 2011

Это не проблема округления.Разница ~ 5+ пикселей.

Строка теста: "" MACD (26,12,9) -0.000016 "

e.Graphics.MeasureString("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)
TextRenderer.MeasureText("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)

Результат всегда:

139.3942
134

Почему так много различий в размере? Мне просто нужен круг ширины строки вне метода рисования. Но он должен соответствовать MeasureString или наоборот.

Ответы [ 2 ]

58 голосов
/ 15 июля 2011

TextRenderer использует GDI для визуализации текста, тогда как Graphics использует GDI +. Оба используют немного другой метод для разметки текста, поэтому размеры отличаются.

Какой из них использовать, зависит от того, что в итоге будет использовано для рисования текста. Если вы рисуете его с GDI + Graphics.DrawString, измерьте с помощью Graphics.MeasureString. Если вы рисуете с использованием GDI TextRenderer.DrawText, измерьте с помощью TextRenderer.MeasureText.

Если текст будет отображаться в элементе управления Windows Forms, он использует TextRenderer, если для UseCompatibleTextRendering установлено значение false (по умолчанию).

Читая между строк вашего вопроса, вы, кажется, используете TextRenderer, потому что у вас нет экземпляра Graphics вне события Paint. Если это так, вы можете создать его самостоятельно для измерения:

using( Graphics g = someControl.CreateGraphics() )
{
    SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

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

using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
     SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
1 голос
/ 15 июля 2011

Я создал следующий класс для использования MeasureString вне события рисования, и он работает довольно хорошо.

public interface ITextMeasurer
    {
        SizeF MeasureString(string text, Font font, StringFormat format);
    }

    public class TextMeasurer : ITextMeasurer
    {
        private readonly Image _fakeImage;
        private readonly Graphics _graphics;

        public TextMeasurer()
        {
            _fakeImage = new Bitmap(1, 1);
            _graphics = Graphics.FromImage(_fakeImage);
        }

        public SizeF MeasureString(string text, Font font, StringFormat format)
        {
            return _graphics.MeasureString(text, font, int.MaxValue, format);
        }
    }
...