Color different parts of a RichTextBox string

186,490

Solution 1

Here is an extension method that overloads the AppendText method with a color parameter:

public static class RichTextBoxExtensions
{
    public static void AppendText(this RichTextBox box, string text, Color color)
    {
        box.SelectionStart = box.TextLength;
        box.SelectionLength = 0;

        box.SelectionColor = color;
        box.AppendText(text);
        box.SelectionColor = box.ForeColor;
    }
}

And this is how you would use it:

var userid = "USER0001";
var message = "Access denied";
var box = new RichTextBox
              {
                  Dock = DockStyle.Fill,
                  Font = new Font("Courier New", 10)
              };

box.AppendText("[" + DateTime.Now.ToShortTimeString() + "]", Color.Red);
box.AppendText(" ");
box.AppendText(userid, Color.Green);
box.AppendText(": ");
box.AppendText(message, Color.Blue);
box.AppendText(Environment.NewLine);

new Form {Controls = {box}}.ShowDialog();

Note that you may notice some flickering if you're outputting a lot of messages. See this C# Corner article for ideas on how to reduce RichTextBox flicker.

Solution 2

I have expanded the method with font as a parameter:

public static void AppendText(this RichTextBox box, string text, Color color, Font font)
{
    box.SelectionStart = box.TextLength;
    box.SelectionLength = 0;

    box.SelectionColor = color;
    box.SelectionFont = font;
    box.AppendText(text);
    box.SelectionColor = box.ForeColor;
}

Solution 3

This is the modified version that I put in my code (I'm using .Net 4.5) but I think it should work on 4.0 too.

public void AppendText(string text, Color color, bool addNewLine = false)
{
    box.SuspendLayout();
    box.SelectionColor = color;
    box.AppendText(addNewLine
        ? $"{text}{Environment.NewLine}"
        : text);
    box.ScrollToCaret();
    box.ResumeLayout();
}

Differences with original one:

  • Possibility to add text to a new line or simply append it
  • No need to change selection, it works the same
  • Inserted ScrollToCaret to force autoscroll
  • Added SuspendLayout/ResumeLayout calls for better performance

Solution 4

EDIT : sorry this is a WPF answer

I think modifying a "selected text" in a RichTextBox isn't the right way to add colored text. So here a method to add a "color block" :

        Run run = new Run("This is my text");
        run.Foreground = new SolidColorBrush(Colors.Red); // My Color
        Paragraph paragraph = new Paragraph(run);
        MyRichTextBlock.Document.Blocks.Add(paragraph);

From MSDN :

The Blocks property is the content property of RichTextBox. It is a collection of Paragraph elements. Content in each Paragraph element can contain the following elements:

  • Inline

  • InlineUIContainer

  • Run

  • Span

  • Bold

  • Hyperlink

  • Italic

  • Underline

  • LineBreak

So I think you have to split your string depending on parts color, and create as many Run objects as needed.

Solution 5

It`s work for me! I hope it will be useful to you!

public static RichTextBox RichTextBoxChangeWordColor(ref RichTextBox rtb, string startWord, string endWord, Color color)
{
    rtb.SuspendLayout();
    Point scroll = rtb.AutoScrollOffset;
    int slct = rtb.SelectionIndent;
    int ss = rtb.SelectionStart;
    List<Point> ls = GetAllWordsIndecesBetween(rtb.Text, startWord, endWord, true);
    foreach (var item in ls)
    {
        rtb.SelectionStart = item.X;
        rtb.SelectionLength = item.Y - item.X;
        rtb.SelectionColor = color;
    }
    rtb.SelectionStart = ss;
    rtb.SelectionIndent = slct;
    rtb.AutoScrollOffset = scroll;
    rtb.ResumeLayout(true);
    return rtb;
}

public static List<Point> GetAllWordsIndecesBetween(string intoText, string fromThis, string toThis,bool withSigns = true)
{
    List<Point> result = new List<Point>();
    Stack<int> stack = new Stack<int>();
    bool start = false;
    for (int i = 0; i < intoText.Length; i++)
    {
        string ssubstr = intoText.Substring(i);
        if (ssubstr.StartsWith(fromThis) && ((fromThis == toThis && !start) || !ssubstr.StartsWith(toThis)))
        {
            if (!withSigns) i += fromThis.Length;
            start = true;
            stack.Push(i);
        }
        else if (ssubstr.StartsWith(toThis) )
        {
            if (withSigns) i += toThis.Length;
            start = false;
            if (stack.Count > 0)
            {
                int startindex = stack.Pop();
                result.Add(new Point(startindex,i));
            }
        }
    }
    return result;
}
Share:
186,490
Essam Ahmed
Author by

Essam Ahmed

Self Learning .Net programmer asp.net-MVC

Updated on December 23, 2021

Comments

  • Essam Ahmed
    Essam Ahmed over 2 years

    I'm trying to color parts of a string to be appended to a RichTextBox. I have a string built from different strings.

    string temp = "[" + DateTime.Now.ToShortTimeString() + "] " +
                  userid + " " + message + Environment.NewLine;
    

    This is what the message would look like once it is constructed.

    [9:23pm] User: my message here.

    I want everything within and including the brackets [9:23] to be one color, 'user' to be another color and the message to be another color. Then I'd like the string appended to my RichTextBox.

    How can I accomplish this?

  • Natrium
    Natrium about 12 years
    I had some trouble with this. I used in another place box.Text += mystring and so all the colors disappeared. When I replaced this with box.AppendText(mystring), it worked like a charme.
  • manu_dilip_shah
    manu_dilip_shah about 12 years
    I have some trouble with the code the color dissapears on adding string in some other color.The only difference is i am assigning var box to a previously made richtextbox....
  • 00jt
    00jt over 10 years
    What am i doing wrong... "SelectionStart" is not a property of a RichTextBox (or i can't access it at least)? I found "Selection" but it is a get-only property...
  • Nathan Baulch
    Nathan Baulch over 10 years
    This is specifically for WinForms. Are you using WPF by any chance?
  • Jeff
    Jeff almost 6 years
    Note--for this to work you must use the AppendText method. Assigning anything to the text property of the box will break it.
  • Kristen Hammack
    Kristen Hammack over 5 years
    I was hoping this was the answer I was really looking for, but it appears to be a WPF answer and not a WinForms answer.
  • vaso123
    vaso123 over 4 years
    I have no overload ikee this, only AppendText(string text) with WinForms
  • Momoro
    Momoro about 4 years
    @vaso123 You have to add it yourself. (e.g. Inside of a class file)
  • Josef Bláha
    Josef Bláha almost 4 years
    This does not solve the given problem, only illustrates how the solution might work.
  • tm1
    tm1 over 3 years
    Note that colors didn't work for me in the case where the form was not yet shown.