Подтвердить что ты не робот

Неравномерность TextRenderer.MeasureText и Graphics.MeasureString

Это не проблема округления. Разница ~ 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 или наоборот.

4b9b3361

Ответ 1

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);
}

Ответ 2

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

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);
        }
    }