Это (в некотором смысле) классика.
Существует несоответствие между довольно точным измерением, выполненным MeasureCharacterRanges , и фактическим отображением строки, выполненным Graphics.DrawString
.
RectagleF
, возвращаемое Region.GetBounds()
, учитывает меру текста как есть.
Graphics.DrawString
, с другой стороны, выполняет своего рода сетку при вычислении расположения текста внутри заданногограницы.
Я не буду здесь это объяснять, это довольно обширный вопрос, но я уже написал кое-что об этом:
Рисование длинной строки в результатах растрового изображенияв выпусках чертежей .
Если вам интересно, вы можете найти некоторые подробности о поведении объекта Graphics
в этом контексте.
В сумме это, текстизмерено правильно, но корректировки, выполняемые Graphics.DrawString
, приводят к тому, что текст не полностью помещается в измеренные границы: нарисованный текст слегка переполняется .
Вы можете исправить это проблема с помощьюпара StringFormat
флагов:
Добавить [StringFormat].Trimming = StringTrimming.None
С этим параметром вы можете сразу увидеть, в чем проблема: последний символ (или несколько символов)) переносятся на новую строку, портя чертеж.
Чтобы исправить это, добавьте StringFormatFlags.NoWrap
к StringFormatFlags.NoClip
Это, по-видимому, решитпроблема.Очевидно, потому что теперь вся строка рисуется в одной строке.
Я предлагаю вам другой метод, использующий TextRenderer.DrawText для визуализации строк.
Обратите внимание, что TextRenderer
на самом деле это класс, используемый WinForms
элементами управления (ну, не всеми из них) для визуализации текста на экране.
Это результат использования следующего метода:
Пример кода с использованием исходного кода с некоторыми изменениями:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Control control = sender as Control;
const string txt = "C# Helper! Draw some text with each word in a random color.";
TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter |
TextFormatFlags.NoPadding | TextFormatFlags.NoClipping;
using (StringFormat format = new StringFormat())
{
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
MatchCollection mc = Regex.Matches(txt, @"[^\s]+");
CharacterRange[] ranges = mc.Cast<Match>().Select(m => new CharacterRange(m.Index, m.Length)).ToArray();
format.SetMeasurableCharacterRanges(ranges);
using (Font font = new Font("Times New Roman", 40, FontStyle.Regular, GraphicsUnit.Point))
{
Region[] regions = e.Graphics.MeasureCharacterRanges(txt, font, control.ClientRectangle, format);
for (int i = 0; i < ranges.Length; i++)
{
Rectangle WordBounds = Rectangle.Round(regions[i].GetBounds(e.Graphics));
string word = txt.Substring(ranges[i].First, ranges[i].Length);
TextRenderer.DrawText(e.Graphics, word, font, WordBounds, RandomColor(), flags);
}
}
}
}
private Random rand = new Random();
private Color[] colors =
{
Color.Red,
Color.Green,
Color.Blue,
Color.Lime,
Color.Orange,
Color.Fuchsia,
};
private Color RandomColor()
{
return colors[rand.Next(0, colors.Length)];
}