Tô màu các phần khác nhau của chuỗi RichTextBox


109

Tôi đang cố tô màu các phần của một chuỗi để được nối vào RichTextBox. Tôi có một chuỗi được xây dựng từ các chuỗi khác nhau.

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

Đây là thông điệp sẽ trông như thế nào khi nó được xây dựng.

[9:23 tối] Người dùng: tin nhắn của tôi ở đây.

Tôi muốn mọi thứ bên trong và bao gồm cả dấu ngoặc [9:23] là một màu, 'user' là một màu khác và thông điệp là một màu khác. Sau đó, tôi muốn chuỗi được thêm vào RichTextBox của mình.

Làm thế nào tôi có thể thực hiện điều này?



5
Tôi đã tìm kiếm và tôi không thấy nó hữu ích.
Fatal510

Cảm ơn vì giải pháp đơn giản này, hoạt động tốt cho tôi. Đừng quên sử dụng AppendText (...) mỗi khi bạn muốn nối thêm văn bản và không sử dụng toán tử '+ =' hoặc các màu được áp dụng sẽ bị loại bỏ.
Xhis

Câu trả lời:


238

Đây là một phương thức mở rộng làm quá tải AppendTextphương thức với một tham số màu:

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;
    }
}

Và đây là cách bạn sẽ sử dụng nó:

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();

Lưu ý rằng bạn có thể nhận thấy một số nhấp nháy nếu bạn đang xuất nhiều tin nhắn. Xem bài viết này ở Góc C # để biết ý tưởng về cách giảm nhấp nháy RichTextBox.


3
Tôi đã gặp một số rắc rối với điều này. Tôi đã sử dụng ở một nơi khác box.Text += mystringvà vì vậy tất cả các màu đều biến mất. Khi tôi thay thế điều này bằng box.AppendText(mystring), nó hoạt động giống như một charme.
Natrium

3
Tôi có một số rắc rối với các mã dissapears màu sắc trên thêm chuỗi trong một số khác khác biệt duy nhất color.The là tôi đang gán var hộp một richtextbox thực hiện trước ....
manu_dilip_shah

Tôi đang làm gì sai ... "SelectionStart" không phải là thuộc tính của RichTextBox (hoặc ít nhất tôi không thể truy cập nó)? Tôi đã tìm thấy "Lựa chọn" nhưng nó là thuộc tính chỉ nhận được ...
00jt

2
Điều này dành riêng cho WinForms. Bạn có đang sử dụng WPF không?
Nathan Baulch

Tôi không có quá tải ikee này, chỉ AppendText(string text)với WinForms
vaso123

12

Tôi đã mở rộng phương thức với phông chữ làm tham số:

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;
}

Lưu ý - để làm việc này, bạn phải sử dụng phương thức AppendText. Việc gán bất kỳ thứ gì cho thuộc tính văn bản của hộp sẽ phá vỡ nó.
Jeff

8

Đây là phiên bản sửa đổi mà tôi đã đặt trong mã của mình (tôi đang sử dụng .Net 4.5) nhưng tôi nghĩ nó cũng sẽ hoạt động trên 4.0.

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();
}

Sự khác biệt với bản gốc:

  • khả năng thêm văn bản vào một dòng mới hoặc chỉ cần nối nó
  • không cần thay đổi lựa chọn, nó hoạt động giống nhau
  • đã chèn ScrollToCaret để buộc tự động cuộn
  • đã thêm tạm ngừng / tiếp tục cuộc gọi bố trí

5

Tôi nghĩ rằng sửa đổi "văn bản đã chọn" trong RichTextBox không phải là cách phù hợp để thêm văn bản màu. Vì vậy, đây là một phương pháp để thêm một "khối màu":

        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);

Từ MSDN :

Thuộc tính Blocks là thuộc tính nội dung của RichTextBox. Nó là một tập hợp các phần tử Đoạn văn. Nội dung trong mỗi phần tử Đoạn văn có thể chứa các phần tử sau:

  • Nội tuyến

  • InlineUIContainer

  • Chạy

  • Span

  • Dũng cảm

  • Siêu liên kết

  • In nghiêng

  • Gạch chân

  • Ngắt dòng

Vì vậy, tôi nghĩ rằng bạn phải chia chuỗi của mình tùy thuộc vào màu sắc của các bộ phận và tạo nhiều Runđối tượng nếu cần.


Tôi đã hy vọng đây là câu trả lời mà tôi thực sự đang tìm kiếm, nhưng nó có vẻ là câu trả lời WPF chứ không phải câu trả lời WinForms.
Kristen Hammack

3

Nó làm việc cho tôi! Tôi hy vọng nó sẽ hữu ích cho bạn!

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

Chọn văn bản như đã nói từ ai đó, lựa chọn có thể xuất hiện trong giây lát. Không Windows Forms applicationscó giải pháp nào khác cho vấn đề, nhưng hôm nay tôi đã tìm thấy một cách giải quyết không tốt: bạn có thể đặt PictureBoxchồng chéo lên RichtextBoxvới ảnh chụp màn hình của nếu, trong quá trình lựa chọn và thay đổi màu sắc hoặc phông chữ, làm cho nó sau xuất hiện lại tất cả, khi hoạt động hoàn tất.

Mã ở đây ...

//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();

Tốt hơn là sử dụng WPF; giải pháp này không hoàn hảo, nhưng đối với Winform, nó hoạt động.


0
private void Log(string s , Color? c = null)
        {
            richTextBox.SelectionStart = richTextBox.TextLength;
            richTextBox.SelectionLength = 0;
            richTextBox.SelectionColor = c ?? Color.Black;
            richTextBox.AppendText((richTextBox.Lines.Count() == 0 ? "" : Environment.NewLine) + DateTime.Now + "\t" + s);
            richTextBox.SelectionColor = Color.Black;

        }

0

Sử dụng Lựa chọn trong WPF, tổng hợp từ một số câu trả lời khác, không cần mã nào khác (ngoại trừ enum Mức độ nghiêm trọng và hàm GetSeverityColor)

 public void Log(string msg, Severity severity = Severity.Info)
    {
        string ts = "[" + DateTime.Now.ToString("HH:mm:ss") + "] ";
        string msg2 = ts + msg + "\n";
        richTextBox.AppendText(msg2);

        if (severity > Severity.Info)
        {
            int nlcount = msg2.ToCharArray().Count(a => a == '\n');
            int len = msg2.Length + 3 * (nlcount)+2; //newlines are longer, this formula works fine
            TextPointer myTextPointer1 = richTextBox.Document.ContentEnd.GetPositionAtOffset(-len);
            TextPointer myTextPointer2 = richTextBox.Document.ContentEnd.GetPositionAtOffset(-1);

            richTextBox.Selection.Select(myTextPointer1,myTextPointer2);
            SolidColorBrush scb = new SolidColorBrush(GetSeverityColor(severity));
            richTextBox.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, scb);

        }

        richTextBox.ScrollToEnd();
    }

0

Tôi đã tạo Hàm này sau khi nghiên cứu trên internet vì tôi muốn in một chuỗi XML khi bạn chọn một hàng từ chế độ xem lưới dữ liệu.

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;
}

và đây là cách bạn gọi nó

   HighlightPhrase(richTextBox1, "<", ">","</", Color.Red, Color.Black);

Điều này không giải quyết vấn đề đã cho, chỉ minh họa cách giải pháp có thể hoạt động.
Josef Bláha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.