Color different parts of a RichTextBox string

前端 未结 9 652
暖寄归人
暖寄归人 2020-11-22 08:10

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.ToSh         


        
相关标签:
9条回答
  • 2020-11-22 08:29

    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.

    0 讨论(0)
  • 2020-11-22 08:33

    Selecting text as said from somebody, may the selection appear momentarily. In Windows Forms applications there is no other solutions for the problem, but today I found a bad, working, way to solve: you can put a PictureBox in overlapping to the RichtextBox with the screenshot of if, during the selection and the changing color or font, making it after reappear all, when the operation is complete.

    Code is here...

    //The PictureBox has to be invisible before this, at creation
    //tb variable is your RichTextBox
    //inputPreview variable is your PictureBox
    using (Graphics g = inputPreview.CreateGraphics())
    {
        Point loc = tb.PointToScreen(new Point(0, 0));
        g.CopyFromScreen(loc, loc, tb.Size);
        Point pt = tb.GetPositionFromCharIndex(tb.TextLength);
        g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(pt.X, 0, 100, tb.Height));
    }
    inputPreview.Invalidate();
    inputPreview.Show();
    //Your code here (example: tb.Select(...); tb.SelectionColor = ...;)
    inputPreview.Hide();
    

    Better is to use WPF; this solution isn't perfect, but for Winform it works.

    0 讨论(0)
  • 2020-11-22 08:35

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 08:36

    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.

    0 讨论(0)
  • 2020-11-22 08:39

    I created this Function after researching on the internet since I wanted to print an XML string when you select a row from a data grid view.

    static void HighlightPhrase(RichTextBox box, string StartTag, string EndTag, string ControlTag, Color color1, Color color2)
    {
        int pos = box.SelectionStart;
        string s = box.Text;
        for (int ix = 0; ; )
        {
            int jx = s.IndexOf(StartTag, ix, StringComparison.CurrentCultureIgnoreCase);
            if (jx < 0) break;
            int ex = s.IndexOf(EndTag, ix, StringComparison.CurrentCultureIgnoreCase);
            box.SelectionStart = jx;
            box.SelectionLength = ex - jx + 1;
            box.SelectionColor = color1;
            
            int bx = s.IndexOf(ControlTag, ix, StringComparison.CurrentCultureIgnoreCase);
            int bxtest = s.IndexOf(StartTag, (ex + 1), StringComparison.CurrentCultureIgnoreCase);
            if (bx == bxtest)
            {
                box.SelectionStart = ex + 1;
                box.SelectionLength = bx - ex + 1;
                box.SelectionColor = color2;
            }
            
            ix = ex + 1;
        }
        box.SelectionStart = pos;
        box.SelectionLength = 0;
    }
    

    and this is how you call it

       HighlightPhrase(richTextBox1, "<", ">","</", Color.Red, Color.Black);
    
    0 讨论(0)
  • 2020-11-22 08:40

    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;
    }
    
    0 讨论(0)
提交回复
热议问题