Fill text inside rectangle

▼魔方 西西 提交于 2019-11-29 01:22:10

问题


I'm using GDI+ to draw a string on a Graphics object.

I want the string to fit inside a pre-defined rectangle (without breaking any lines)

Is there's anyway of doing this besides using TextRenderer.MeasureString() in a loop until the desirable size is returned?

something like:

DrawScaledString(Graphics g, string myString, Rectangle rect)

回答1:


You can use the 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);

But you might get some alias effects.

Edit:

But if you want to change the font size instead I guess you can change the font size with scale in the code above instead of using the scale transform. Try both and compare the quality of the result.




回答2:


Here's another solution to the problem, it's a little intensive as it requires a fair bit of font creation and destruction, but may work better, depending on your circumstances and needs:

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);
    }
}

To use it simply create a new class and call Render(). Note this is specifically written for rendering to a form.

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);

You should create the RenderInBox object upfront due to it's intensive creation nature. Therefore it's not suitable for every need.



来源:https://stackoverflow.com/questions/4152342/fill-text-inside-rectangle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!