RichTextBox dizesinin farklı kısımlarını renklendirin


109

RichTextBox'a eklenecek bir dizenin parçalarını renklendirmeye çalışıyorum. Farklı dizelerden oluşturulmuş bir dizim var.

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

Bu, oluşturulduktan sonra mesajın nasıl görüneceğidir.

[9:23 pm] Kullanıcı: mesajım burada.

Köşeli parantezler [9:23] dahil olmak üzere her şeyin tek renk, "kullanıcı" nın başka bir renk ve mesajın başka bir renk olmasını istiyorum. Ardından dizenin RichTextBox'ıma eklenmesini istiyorum.

Bunu nasıl başarabilirim?



5
Arama yaptım ve hiçbirini yararlı bulamadım.
Fatal510

Bu basit çözüm için teşekkürler, benim için iyi çalışıyor. Her metin eklemek istediğinizde AppendText (...) 'i kullanmayı unutmayın ve' + = 'operatörünü kullanmayın veya uygulanan renkler atılır.
Xhis

Yanıtlar:


239

AppendTextYöntemi bir renk parametresiyle aşırı yükleyen bir uzantı yöntemi :

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

Ve bunu nasıl kullanacağı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();

Çok fazla mesaj çıktısı alıyorsanız, bir miktar titreme fark edebileceğinizi unutmayın. Bkz bu C # Köşe RichTextBox kaybolmasını azaltmak için nasıl fikirler için yazı.


3
Bununla biraz sorun yaşadım. Başka bir yerde kullandım box.Text += mystringve böylece tüm renkler kayboldu. Bunu ile değiştirdiğimde box.AppendText(mystring), bir charme gibi çalıştı.
Natrium

3
Başka bir renkte dize eklerken rengin kaybolduğu kodla ilgili biraz sorun yaşıyorum. Tek fark var kutusunu önceden yapılmış bir richtextbox'a
atıyorum

Neyi yanlış yapıyorum ... "SelectionStart" RichTextBox'ın bir özelliği değil (veya en azından ona erişemiyorum)? "Seçim" i buldum, ancak yalnızca elde edilebilen bir mülk ...
00jt

2
Bu özellikle WinForms içindir. WPF'yi şans eseri kullanıyor musunuz?
Nathan Baulch

Bunu sadece AppendText(string text)WinForms ile aşırı yüklemem yok
vaso123

12

Yöntemi parametre olarak yazı tipiyle genişlettim:

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

Not - bunun çalışması için AppendText yöntemini kullanmanız gerekir. Kutunun text özelliğine herhangi bir şey atamak onu bozar.
Jeff

9

Bu, koduma koyduğum değiştirilmiş versiyon (.Net 4.5 kullanıyorum) ama bence 4.0'da da çalışması gerekiyor.

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

Orijinal olanla farklılıklar:

  • yeni bir satıra metin ekleme veya basitçe ekleme imkanı
  • seçimi değiştirmeye gerek yok, aynı şekilde çalışıyor
  • otomatik kaydırmayı zorlamak için ScrollToCaret eklendi
  • düzen aramalarını askıya alma / sürdürme eklendi

6

Bir RichTextBox'ta "seçili bir metni" değiştirmenin renkli metin eklemenin doğru yolu olmadığını düşünüyorum. İşte burada bir "renk bloğu" eklemek için bir yöntem:

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

Gönderen MSDN :

Blocks özelliği, RichTextBox öğesinin content özelliğidir. Paragraf öğelerinden oluşan bir koleksiyondur. Her bir Paragraf öğesindeki içerik aşağıdaki öğeleri içerebilir:

  • Çizgide

  • InlineUIContainer

  • Çalıştırmak

  • karış

  • cesur

  • Köprü

  • İtalik

  • Altını çizmek

  • Satır sonu

Bu yüzden ipinizi parça rengine göre ayırmanız ve Rungerektiği kadar nesne oluşturmanız gerektiğini düşünüyorum.


Bunun gerçekten aradığım yanıt olduğunu umuyordum, ancak bir WPF yanıtı gibi görünüyor, bir WinForms yanıtı değil.
Kristen Hammack

3

Benim için çalışıyor! Umarım sizin için yararlı olur!

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

Birinin söylediği gibi metni seçmek, seçim anlık olarak görünebilir. İçinde Windows Forms applicationssorun için başka bir çözüm yok, ancak bugün çözmenin kötü, işe yarayan bir yolunu buldum: eğer, seçim sırasında ve değişen renk veya yazı tipinin ekran görüntüsü ile PictureBoxüst üste bir tane koyabilirsiniz. RichtextBoxişlem tamamlandığında tümünü yeniden görün.

Kod burada ...

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

WPF kullanmak daha iyidir; bu çözüm mükemmel değil, ancak Winform için işe yarıyor.


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

WPF'de Seçim'i kullanarak, diğer birkaç yanıttan bir araya getirerek, başka bir kod gerekmez (Önem sıralaması ve GetSeverityColor işlevi dışında)

 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

Veri ızgarası görünümünden bir satır seçtiğinizde bir XML dizesi yazdırmak istediğim için bu işlevi internette araştırdıktan sonra oluşturdum.

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

ve bu nasıl adlandırılır

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

Bu, verilen sorunu çözmez, yalnızca çözümün nasıl çalışabileceğini gösterir.
Josef Bláha
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.