0

I'm coding a clone messaging app. I have a user control called "Bubble" that I use as a message bubble. And its user control layout is like this:

User Control

It contains only lblMessage, lblTime and pictureBox. lblMessage's AutoSize property off and Anchor is top-left-right. My goal is to size or wrap this according to the content. I am able to resize vertically using this code.

void SetHeight()
{
    //SizeF maxSize = new Size(500, int.MaxValue);

    Graphics g = CreateGraphics();
    SizeF size = g.MeasureString(lblMessage.Text, lblMessage.Font, lblMessage.Width);

    lblMessage.Height = int.Parse(Math.Round(size.Height + 2, 0).ToString());

    lblTime.Top= lblMessage.Bottom +10;
    this.Height = lblTime.Bottom + 10;
}

My result is like this:

Text Rendering

I can resize vertically, but not horizontally at the same time. The way I resize it vertically is to use width property of lblMessage as the limit size. I want to resize user control according to size of short text. I thought about creating a maxSize for MeasureString but I can't get it to work. I'm trying to find a function that continues from a bottom line when it reaches a certain width value. I look forward to your help.

I searched all stackowerflow questions in depth but none of them worked in my case.

**Edit after Jimi comments

I tried to apply his solution to my project. I don't think I did everything right, but with a little bit of comment, something came up that worked for me at least.

 private void Bubble_Paint(object sender, PaintEventArgs e)
    {

        float minimumWidth = lblTime.Width + pictureBox1.Width + 35;
        float maximumWidth = 500;

        string measureString = lblMessage.Text;
        Font stringFont = new Font("Helvetica", 12.0F);
        CharacterRange[] characterRanges = { new CharacterRange(0, measureString.Length) };


        float layautWidth = maximumWidth - minimumWidth;
        RectangleF layoutRect = new RectangleF(10, 6, layautWidth, this.Height);

        StringFormat stringFormat = new StringFormat();
        stringFormat.SetMeasurableCharacterRanges(characterRanges);
        Color myColor = Color.FromArgb(211, 212, 212);
        SolidBrush myBrush = new SolidBrush(myColor);

        Region[] stringRegions = e.Graphics.MeasureCharacterRanges(measureString, stringFont, layoutRect, stringFormat);
        RectangleF measureRect1 = stringRegions[0].GetBounds(e.Graphics);

        //When I gave Rectangle to the DrawString, some last letter was truncated, so I used plain text printing until I got to the bottom line. 
        if (measureRect1.Height < 30)
            e.Graphics.DrawString(measureString, stringFont, myBrush, 10, 6, stringFormat);
        else e.Graphics.DrawString(measureString, stringFont, myBrush, measureRect1, stringFormat);

        e.Graphics.DrawRectangle(new Pen(Color.Transparent, 0), Rectangle.Round(measureRect1));


        this.Width = Convert.ToInt32(measureRect1.Width + minimumWidth);
        lblTime.Top = Convert.ToInt32(measureRect1.Height) + 10;
        this.Height = lblTime.Bottom + 10;

    }

Result in container preview:

user control that goes down one line from the specified limit

https://i.stack.imgur.com/iSI76.jpg

and for one line

https://i.stack.imgur.com/zWFGR.jpg

dynamically result inside the application

enter image description here

quahvaen
  • 31
  • 1
  • 3
  • 1
    Side note: `Graphics g = CreateGraphics();` You need to dispose that since you created it. Or put it in a `using {}` block. – LarsTech Aug 20 '21 at 22:48
  • It's probably easier if you use [Graphics.MeasureCharacterRanges](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.measurecharacterranges) to determine the exact position of each character in your string. Define a Minimum width (right-most Label + Image + padding) and a Maximum Width (the container's Width minus the distance from the container's border that you have determine based on layout you prefer). When the last char's Rectangle in the text reaches the minimum size (it reaches the left of the Control that shows the hour), add a new line (or half-line) [...] – Jimi Aug 20 '21 at 22:59
  • 1
    [...] under the text (i.e, add the height of half a line to the UserControl). The Label + Image are anchored to the Bottom, so will follow. -- You should probably draw the text instead of using a Label. If you want to use a Label, remove its background, so it's completely transparent (it can overlap other Controls without hiding them). Or keep the Label + Image always below the text (to make it simpler). – Jimi Aug 20 '21 at 23:00
  • I checked the link and thought about what you said. This is really a better way. I will try right away. Thank you! – quahvaen Aug 21 '21 at 02:21
  • Hey Jimi really thank you so much. I tried to implement what you said and it seems like I got a result that works for me. But I have a small problem. I always lose one or two character unless the message content goes down to a bottom line. I edited my question, any chance to have a look? Could it be because of float values? – quahvaen Aug 21 '21 at 09:40
  • oh no need, i got it done. It was fixed by giving x, y and StringFormat instead of giving Rectangle to DrawString method. Thanks again. – quahvaen Aug 21 '21 at 12:06

0 Answers0