0

I want to print multiple different Strings on a rectangle in C#.

My Problem is that the Strings are always overlapping when I print them.
I can not print the whole string because every line has another font.

RectangleF[] rectangles = { 
    new RectangleF(650.8188976377953F, 57.48031496062993F, 275.59055118110234F, 334.6456692913386F) 
};

StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;        

e.Graphics.DrawRectangles(blackPen, rectangles);
e.Graphics.DrawString("test1", headLine, black,rectangles[0],stringFormat);
e.Graphics.DrawString("test2", subLines, black, rectangles[0], stringFormat);

How can I draw them, so that they are not overlapping and place them everywhere I want without using coordinates?

2 Answers 2

3

Your strings overlap because you have one drawing area (rectangles[0]) and all strings are drawn in this area, without any further indication in relation to their position.
Since StringFormat.LineAlignment is set to StringAlignment.Center, all Text is drawn in the center of the area defined by rectangles[0].

To center a series of strings inside a drawing area, you can imagine your sequence of strings, plus the space that divides them, as a Rectangle.
To center this Rectangle (Drawing Area) inside a Container object, you can define the relation between this parts as:

Drawing Area Height = (Text Height * Number of Strings) + (Interline * (Number of Strings - 1))

Blank Area Height = (Container Height - Drawing Area Height)

The centered position of the imaginary Drawing Area inside its Container is then:

Container Top + (Blank Area Height / 2)

Now we know where to start to draw our Text lines. All other string positions are relative to the already calculated Drawing Area (since they are all part of this measure).
This way, you don't need to manually position the strings inside a Container.


To define the different strings and their related properties (Text, Font, Font Style, Text Height, Text Color) I have used a class object, DrawingString.

The Text lines are separated by an interline.
You can modify this value and specify a different line spacing:

float interline = 12.0f;

The Text position inside the Container rectangle (rectangles[0]) is calculated automatically.
Thus, you can add more strings to the list and they'll be positioned accordingly.

DrawingString class:

internal class DrawingString
{
    public DrawingString() { }
    public DrawingString(string text, string fontName, FontStyle style, float fontSize, Brush brush)
    {
        Text = text;
        FontName = fontName;
        FontStyle = style;
        FontSize = fontSize;
        Brush = brush;
    }
    public string Text { get; set; }
    public string FontName { get; set; }
    public FontStyle FontStyle { get; set; }
    public float FontSize { get; set; }
    public Brush Brush { get; set; }
}

List<DrawingString> drawingStrings = new List<DrawingString>() {
    new DrawingString("A Graphics", "Arial", FontStyle.Regular, 20f, Brushes.LightGreen),
    new DrawingString("String Drawing", "Segoe UI", FontStyle.Regular, 17f, Brushes.Orange),
    new DrawingString("Example", "Calibri", FontStyle.Regular, 22f, Brushes.SteelBlue),
    new DrawingString("One more Line", "Microsoft Sans Serif", FontStyle.Regular, 17f, Brushes.MediumPurple)
};

List<RectangleF> rectangles = new List<RectangleF>() {
    new RectangleF(5.8188976377953F, 5.48031496062993F, 170.59055118110234F, 170.6456692913386F)
};

You can now choose a canvas to draw these strings to. It could be the surface of a Control or an Image.
If it's a Control, use the Graphics object provided by the Paint event handler to draw the strings, otherwise, derive a Graphics object from the Bitmap, using the Graphics.FromImage() method.

If the same StringFormat is used to draw all strings and/or if it needs to be redefined by the User or the application, declare a StringFormat object as a Field and modify it as required (it could also be part of the DrawingString class):

StringFormat format = new StringFormat() {
    Alignment = StringAlignment.Center,
    LineAlignment = StringAlignment.Center,
    FormatFlags = StringFormatFlags.NoClip,
    Trimming = StringTrimming.EllipsisWord
};

Assuming these string are drawn on the surface of, e.g., a PictureBox Control, hence using the PaintEventArgs of its Paint event handler:

private void somePictureBox_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

    float interline = 12.0f;
    float textHeigh = drawingStrings.Select(ds => ds.FontSize + interline).Sum() - interline;
    float textPosition = (rectangles[0].Height - textHeigh + interline) / 2;

    foreach (var item in drawingStrings) {
        rectangles.Add(new RectangleF(
            new PointF(rectangles[0].X, textPosition), 
            new SizeF(rectangles[0].Width, item.FontSize)));
        textPosition += item.FontSize + interline;
    }

    // Uncomment to draw the bounding Rectangles border        
    // e.Graphics.DrawRectangles(Pens.White, rectangles.ToArray());

    int rectArea = 0;
    foreach (var item in drawingStrings) {
        rectArea += 1;
        using (Font font = new Font(item.FontName, item.FontSize, item.FontStyle, GraphicsUnit.Pixel)) {
            e.Graphics.DrawString(item.Text, font, item.Brush, rectangles[rectArea], format);
        }
    }
}

This is the result with the List<DrawingString> you see in the code and what happens if you add another line of Text:

Draw strings Draw more strings

If you uncomment this line: e.Graphics.DrawRectangles(Pens.White, rectangles.ToArray());,
you can see how the rectangles are sized with different interline values:

Drawn strings bounding rectangles Drawn strings bounding rectangles

     Interline 12.0F          Interline 16.0F
Sign up to request clarification or add additional context in comments.

Comments

0

You can get drawed string sizes with;

Graphics.MeasureString("test1", StringFont)

then you can extend your rectangle destinations from returned size points.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.