Отключить перенос слов при переносе строк в.NET DrawString
Я использую.NET, чтобы нарисовать строку в ограниченном пространстве. Я хочу, чтобы строка была как можно больше. У меня нет проблем в разбивке строки на несколько строк (если она остается внутри прямоугольника). Теперь проблема: я не хочу, чтобы.NET разрывал строку в разные строки в середине слова. Например, строка "Test" печатает на одной строке крупным шрифтом. Строка "Testing" должна печататься на одной строке мелким шрифтом (а не "Testi" на одной строке и "ng" на другой), а строка "Test Test" должна печататься на двух строках довольно крупным шрифтом.
У кого-нибудь есть идеи, как ограничить.NET, чтобы не нарушать мои слова?
В настоящее время я использую такой код:
internal static void PaintString(string s, int x, int y, int height, int maxwidth, Graphics g, bool underline)
{
FontStyle fs = FontStyle.Bold;
if (underline)
fs |= FontStyle.Underline;
Font fnt = new System.Drawing.Font("Arial", 18, fs);
SizeF size = g.MeasureString(s, fnt, maxwidth);
while (size.Height > height)
{
fnt = new System.Drawing.Font("Arial", fnt.Size - 1, fs);
size = g.MeasureString(s, fnt, maxwidth);
}
y = (int)(y + height / 2 - size.Height / 2);
g.DrawString(s, fnt, new SolidBrush(Color.Black), new Rectangle(x, y, maxwidth, height));
}
3 ответа
Найдите самое длинное слово в вашей строке и используйте MeasureString
чтобы он поместился на одной строке:
internal static void PaintString(string s, int x, int y, int maxHeight, int maxWidth, Graphics graphics, bool underline)
{
FontStyle fontStyle = FontStyle.Bold;
if (underline)
{
fontStyle |= FontStyle.Underline;
}
var longestWord = Regex.Split(s, @"\s+").OrderByDescending(w => w.Length).First();
using (var arial = new FontFamily("Arial"))
using (var format = new StringFormat(StringFormatFlags.LineLimit)) // count only lines that fit fully
{
int fontSize = 18;
while (fontSize > 0)
{
var boundingBox = new RectangleF(x, y, maxWidth, maxHeight);
using (var font = new Font(arial, fontSize, fontStyle))
{
int charactersFittedAll, linesFilledAll, charactersFittedLongestWord, linesFilledLongestWord;
graphics.MeasureString(s, font, boundingBox.Size, format, out charactersFittedAll, out linesFilledAll);
graphics.MeasureString(longestWord, font, boundingBox.Size, format, out charactersFittedLongestWord, out linesFilledLongestWord);
// all the characters must fit in the bounding box, and the longest word must fit on a single line
if (charactersFittedAll == s.Length && linesFilledLongestWord == 1)
{
Console.WriteLine(fontSize);
graphics.DrawString(s, font, new SolidBrush(Color.Black), boundingBox, format);
return;
}
}
fontSize--;
}
throw new InvalidOperationException("Use fewer and/or shorter words");
}
}
То, что у вас есть, кажется правильным ответом. Я не думаю, что есть один вызов метода Framework, который может сделать все это за вас. Другой вариант, если вы отрисовываете кнопку и текст в winform, вам следует взглянуть на классы ButtonRenderer и TextRenderer. При вызове DrawText или MeasureString вы также можете указать TextFormatFlags, который позволит вам указать WorkBreak, SingleLine или использовать усечение Ellipse.
Вы можете изменить размер элемента управления в зависимости от длины / размера строки. Это позволит убедиться, что строка помещается в одну строку.