Отключить разрыв слов при переносе строк в .NET DrawString

Я использую .NET для рисования строки в ограниченном пространстве. Я хочу, чтобы струна была как можно больше. У меня нет проблем с тем, что строка разбивается на несколько строк (если она остается внутри прямоугольника). Теперь проблема: я не хочу, чтобы .NET разбивал строку на разные строки в середине слова. Например, строка «Тест» печатается в одну строку крупным шрифтом. Строка «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));
    }

person HH321    schedule 23.03.2010    source источник


Ответы (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");
    }
}
person ejohnson    schedule 10.10.2017

Вы можете изменить размер элемента управления в зависимости от длины / размера строки. Это позволит убедиться, что строка умещается в одну строку.

person Aseem Gautam    schedule 23.03.2010
comment
Но у меня есть фиксированное пространство, размер которого я не хочу изменять. Я хочу уменьшить масштаб / обернуть текст так, чтобы он соответствовал - person HH321; 23.03.2010

Кажется, что у вас есть правильный ответ. Я не думаю, что существует единственный вызов метода фреймворка, который мог бы сделать все это за вас. Другой вариант, если вы отображаете кнопку и текст в winform, вы должны посмотреть на классы ButtonRenderer и TextRenderer. При вызове DrawText или MeasureString вы также можете указать TextFormatFlags, который позволит вам указать WorkBreak, SingleLine или использование усечения Ellipse.

person Fadrian Sudaman    schedule 30.07.2010