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

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

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

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

что-то типа:

DrawScaledString(Graphics g, string myString, Rectangle rect)

2 ответов


Вы можете использовать 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

Edit:

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


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

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 заранее из-за его интенсивной природы создания. Поэтому он не подходит для каждого необходимость.