0

i am trying to develop a win form for chatting purpose. I am developing Chat bubbles using pure inbuilt functions of .Net Framework, No fancy UI, No third party libraries. Now let's have a look on how every thing is being done.

My following function is responsible for generating a Panel dynamically for each chat message received, the Pain event is used to draw rounded rectangle and color is transparent. A picture box is used to show static avatar.

private void SetRemoteMessage(string msg)
        {
            PictureBox pb = new PictureBox();
            pb.Bounds = new Rectangle(0, 0, 72, 72);
            pb.Image = Base64ToImage(avatar_his);

            Panel p = new Panel();
            Label lb = new Label();
            lb.BackColor = Color.Transparent;
            lb.ForeColor = Color.Blue;
            lb.Text = msg;
            lb.Font = new Font("Arial", 14, FontStyle.Bold, GraphicsUnit.Point);

            p.Bounds = new Rectangle(rX, rY, (Width / 2) - 25, pb.Height);
            p.BackColor = Color.Transparent;

            lb.Size = new Size(p.Width - pb.Width, p.Height);
            lb.Paint += _control_Paint;

            lb.Location = new Point(pb.Width + 5, 0);

            p.Controls.Add(pb);
            p.Controls.Add(lb);

            SetPanel(p);

            rY += p.Height + 20;
            mY += p.Height + 20;
        } 

following is the Paint event binded to the parent "Container" Panel so that a simple rounded rectangle is shown for each bubble

private void _control_Paint(object sender, PaintEventArgs e)
        {
            Control c = (Control)sender;

            if(!c.Name.Equals("lb"))
            {
                Graphics v = e.Graphics;
                DrawRoundRect(v, Pens.Blue, e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1, 10);  
            }
            else
            {
                using (Font font1 = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point))
                {
                    e.Graphics.DrawString(c.Text, font1, Brushes.Blue, c.Bounds);
                }
            }

            base.OnPaint(e);
        }

and the following function to actually generate rounded rectangles

private void DrawRoundRect(Graphics g, Pen p, float X, float Y, float width, float height, float radius)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddLine(X + radius, Y, X + width - (radius * 2), Y);
            gp.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90);
            gp.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2));
            gp.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
            gp.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height);
            gp.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
            gp.AddLine(X, Y + height - (radius * 2), X, Y + radius);
            gp.AddArc(X, Y, radius * 2, radius * 2, 180, 90);
            gp.CloseFigure();
            g.DrawPath(p, gp);
        }

The chat message is not wrapped automatically so to wrap it, the Pain method is used as it can be seen in Paint event . .the output is good as expected instead of one thing Screenshot of Problem

The Problem can be seen easily the Panel height is not increasing according when a large message is given to display in bubble.

What i tried already is

  1. Measuring string length with Graphics class, but i was not able to implement it with success
  2. Enabling Scrollbars, Yes this approach worked but i am not interested to use this behavior
  3. Counting string length and increasing height, This works but not efficient, specially when form is resized all calculations of measurement then become invalid.
Zain Ul Abidin
  • 2,467
  • 1
  • 17
  • 29
  • 1
    _What i tried already is Measuring string length with Graphics class, but i was not able to implement it with success_ That's what I would recommend. So, show your code and explani how it didn't work! Note that with the irght overload you measure not so much the Lenght as the Height, ie you feed font, text and maximum width and get a rectangle. – TaW May 24 '20 at 09:39
  • i took Utility code for measuring string from following link https://stackoverflow.com/a/1003503/2355176 then i converted the Height of the returned string SizeF object from float to int, and finally set that height to the Pane's Height . . this approach failed .even worst output . Panel is squeezed . .or shortened . . – Zain Ul Abidin May 24 '20 at 12:35
  • _from following link_ There are four or so answers there. I hope you didn't pick the 1st one?! You need to feed the maximum width into the MeasureString function! – TaW May 24 '20 at 15:11
  • Now trying the first answer . – Zain Ul Abidin May 24 '20 at 15:17
  • Textrenderer is fine as is Measurestring. Just use the right overload. So instead of copying answers using MSDN is what I recommend.. Note that the link also starts with two overloads that are only meant for measuirng a single line!! You need to feed in the maximum width in a size parameter!! – TaW May 24 '20 at 15:29

0 Answers0