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

Заполнить текст внутри прямоугольника

Я использую GDI + для рисования строки на объекте Graphics.

Я хочу, чтобы строка помещалась внутри заранее определенного прямоугольника (без нарушения каких-либо строк)

Есть ли способ сделать это, кроме использования TextRenderer.MeasureString() в цикле до тех пор, пока не будет возвращен желаемый размер?

что-то вроде:

DrawScaledString(Graphics g, string myString, Rectangle rect)
4b9b3361

Ответ 1

Вы можете использовать ScaleTransform

string testString = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Suspendisse et nisl adipiscing nisl adipiscing ultricies in ac lacus.
Vivamus malesuada eros at est egestas varius tincidunt libero porttitor.
Pellentesque sollicitudin egestas augue, ac commodo felis ultricies sit amet.";

Bitmap bmp = new Bitmap(300, 300);
using (var graphics = Graphics.FromImage(bmp))
{
    graphics.FillRectangle(Brushes.White, graphics.ClipBounds);
    var stringSize = graphics.MeasureString(testString, this.Font);
    var scale = bmp.Width / stringSize.Width;
    if (scale < 1)
    {
        graphics.ScaleTransform(scale, scale);
    }
    graphics.DrawString(testString, this.Font, Brushes.Black, new PointF());
}
bmp.Save("lorem.png", System.Drawing.Imaging.ImageFormat.Png);

Но вы можете получить некоторые эффекты псевдонимов.

alt text

Изменить:

Но если вы хотите изменить размер шрифта, я думаю, вы можете изменить размер шрифта с помощью scale в коде выше, а не использовать масштабное преобразование. Попробуйте оба и сравните качество результата.

Ответ 2

Здесь другое решение проблемы, оно немного интенсивно, поскольку для этого требуется справедливый бит создания и уничтожения шрифтов, но может работать лучше, в зависимости от ваших обстоятельств и потребностей:

public class RenderInBox
{
    Rectangle box; 
    Form root;
    Font font;
    string text;

    StringFormat format;

    public RenderInBox(Rectangle box, Form root, string text, string fontFamily, int startFontSize = 150)
    {
        this.root = root;
        this.box = box;
        this.text = text;

        Graphics graphics = root.CreateGraphics();

        bool fits = false;
        int size = startFontSize;
        do
        {
            if (font != null)
                font.Dispose();

            font = new Font(fontFamily, size, FontStyle.Regular, GraphicsUnit.Pixel);

            SizeF stringSize = graphics.MeasureString(text, font, box.Width, format);

            fits = (stringSize.Height < box.Height);
            size -= 2;
        } while (!fits);

        graphics.Dispose();

        format = new StringFormat()
        {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Center
        };

    }

    public void Render(Graphics graphics, Brush brush)
    {
        graphics.DrawString(text, font, brush, box, format);
    }
}

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

var titleBox = new RenderInBox(new Rectangle(10, 10, 400, 100), thisForm, "This is my text it may be quite long", "Tahoma", 200);
titleBox.Render(myGraphics, Brushes.White);

Вы должны создать объект RenderInBox заранее из-за его интенсивного создания. Поэтому он не подходит для каждой потребности.