Anton Semenov
Anton Semenov

Reputation: 6347

How can I draw string in rich format on winform?

I need to write a line of text in rich format on windows form. How can I achive this?

Upvotes: 2

Views: 6301

Answers (4)

Anton Semenov
Anton Semenov

Reputation: 6347

As it turned out there is no any standard way to draw RTF string on Graphics context. So I have two ways to act:

  1. Parse rtf string manually. Devide it into chunks and draw onto graphical context as shown in TcKs's answer
  2. The second way is some kind of workaround, but its completly ready to use. Look atthis link or this

Thank you everybody for help!

Upvotes: 0

Ganapathy Subramaniam
Ganapathy Subramaniam

Reputation: 21

In addition to TcKs Code, following segment will solve word wrap functionality:

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
    {
        var arial_8 = new Font("Arial", 8);
        var webdings_10 = new Font("Webdings", 10);

        var richTexts = new RichText[] {
        new RichText("Default text and this is the lengthy string to check the display. One more line to verify again")
        , new RichText("Default green text. this is the lengthy string to check the display. One more line to verify again", Color.Green)
        , new RichText("Regular arial 8.", arial_8)
        , new RichText("Bold arial 8.", new Font(arial_8, FontStyle.Bold))
        };

        var g = e.Graphics;

        Point textPosition = new Point(0, 0);
        int maxWidth = this.pictureBox2.ClientSize.Width;
        foreach (var richText in richTexts)
        {
            var text = richText.Text;
            if (string.IsNullOrEmpty(text)) { continue; }

            var font = richText.Font ?? Control.DefaultFont;
            var textColor = richText.TextColor ?? Control.DefaultForeColor;

            using (var brush = new SolidBrush(textColor))
            {
                string[] strs = text.Split(new string[] { " " }, StringSplitOptions.None);
                int fontheight = (int)g.MeasureString("\r\n", font).Height;
                foreach (string val in strs)
                {
                    var measure = g.MeasureString(val, font);
                    if (measure.Width + textPosition.X > maxWidth)
                    {
                        var newPosition = textPosition;
                        newPosition.X = 0;
                        newPosition.Y = textPosition.Y + fontheight;
                        textPosition = newPosition;
                    }

                    g.DrawString(val, font, brush, textPosition);

                    var nextposition = textPosition;
                    nextposition.X = textPosition.X + (int)measure.Width;
                    textPosition = nextposition;

                }
            }
        }
    }

Upvotes: 2

TcKs
TcKs

Reputation: 26632

You must split the string to the "chunks" with same formatting and draw every single "chunk".

Use Graphics.MeasureString for computation of positions and Graphics.DrawString to final draw.

Simple sample code (does not solve word-wraping, images, etc...):

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();

        this.Paint += new PaintEventHandler(Form1_Paint);
        this.SizeChanged += new EventHandler(Form1_SizeChanged);
    }

    void Form1_SizeChanged(object sender, EventArgs e) {
        this.Invalidate();
    }

    public class RichText {
        public Font Font { get; set; }
        public Color? TextColor { get; set; }
        public string Text { get; set; }

        public RichText() { }
        public RichText(string text) {
            this.Text = text;
        }
        public RichText(string text, Font font) : this(text) {
            this.Font = font;
        }
        public RichText(string text, Color textColor) : this(text) {
            this.TextColor = textColor;
        }
        public RichText(string text, Color textColor, Font font) : this(text, textColor) {
            this.Font = font;
        }
    }
    void Form1_Paint(object sender, PaintEventArgs e) {
        var arial_8 = new Font("Arial", 8);
        var webdings_10 = new Font("Webdings", 10);

        var richTexts = new RichText[]{
            new RichText("Default text.")
            , new RichText("Default green text.", Color.Green)
            , new RichText("Regular arial 8.", arial_8)
            , new RichText("Bold arial 8.", new Font(arial_8, FontStyle.Bold))
            , new RichText("Regular webdings 10.", webdings_10)
            , new RichText("Regular blue webdings 10.", Color.Blue, webdings_10)
        };

        var g = e.Graphics;

        Point textPosition = new Point(0, 0);
        int maxWidth = this.ClientSize.Width;
        foreach (var richText in richTexts) {
            var text = richText.Text;
            if (string.IsNullOrEmpty(text)) { continue; }

            var font = richText.Font ?? Control.DefaultFont;
            var textColor = richText.TextColor ?? Control.DefaultForeColor;

            using (var brush = new SolidBrush(textColor)) {
                var rslt_Measure = g.MeasureString(text, font);
                if (rslt_Measure.Width + textPosition.X > maxWidth) {
                    // this code does not solve word-wraping
                    var rslt_Line = g.MeasureString("\r\n", font);
                    Point tmpTextPosition = new Point(0, textPosition.Y + (int)rslt_Line.Height);

                    g.DrawString(text, font, brush, tmpTextPosition);
                    var newPosition = tmpTextPosition;
                    newPosition.X += (int)rslt_Measure.Width;
                    textPosition = newPosition;
                }
                else {
                    g.DrawString(text, font, brush, textPosition);
                    var newPosition = textPosition;
                    newPosition.X += (int)rslt_Measure.Width;
                    textPosition = newPosition;
                }
            }
        }
    }
}

EDIT:

If you want process RTF maybe this links will be usefull:

Upvotes: 3

Robert Levy
Robert Levy

Reputation: 29073

Will a RichTextBox control set to readonly do what you need?

Upvotes: 1

Related Questions