it-swarm.com.de

Färben Sie verschiedene Teile einer RichTextBox-Zeichenfolge

Ich versuche, Teile einer Zeichenfolge einzufärben, um sie an eine RichTextBox anzuhängen. Ich habe eine Saite, die aus verschiedenen Saiten aufgebaut ist.

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

So würde die Nachricht aussehen, wenn sie einmal aufgebaut ist.

[21:23] Benutzer: meine Nachricht hier.

Ich möchte, dass alles in und einschließlich der Klammern [9:23] eine Farbe ist, „user“ eine andere Farbe und die Nachricht eine andere Farbe. Dann möchte ich den String an meine RichTextBox anhängen.

Wie kann ich das erreichen?

96
Fatal510

Hier ist eine Erweiterungsmethode, die die AppendText-Methode mit einem Farbparameter überlädt:

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

Und so würden Sie es verwenden:

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

Beachten Sie, dass Sie möglicherweise ein Flackern bemerken, wenn Sie viele Nachrichten ausgeben. In diesem C # Corner - Artikel finden Sie Vorschläge, wie Sie das RichTextBox-Flimmern reduzieren können.

217
Nathan Baulch

Ich habe die Methode mit font als Parameter erweitert:

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;
}
11
Renan F.

Dies ist die modifizierte Version, die ich in meinen Code eingebe (ich verwende .Net 4.5), aber ich denke, es sollte auch mit 4.0 funktionieren.

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

Unterschiede zum Original:

  • möglichkeit, Text in eine neue Zeile einzufügen oder einfach anzufügen
  • es ist nicht nötig, die Auswahl zu ändern, es funktioniert gleich
  • eingefügtes ScrollToCaret, um das automatische Scrollen zu erzwingen
  • suspend/Resume-Layoutaufrufe hinzugefügt
7
tedebus

Ich denke, ein "ausgewählter Text" in einer RichTextBox zu ändern, ist nicht der richtige Weg, um farbigen Text hinzuzufügen.

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

Von MSDN :

Die Blocks-Eigenschaft ist die content-Eigenschaft von RichTextBox. Es ist ein Sammlung von Absatzelementen. Inhalt in jedem Absatzelement kann folgende Elemente enthalten: 

  • In der Reihe

  • InlineUIContainer

  • Lauf

  • Span

  • Fett gedruckt

  • Hyperlink

  • Kursiv

  • Unterstreichen

  • Zeilenumbruch

Ich denke, Sie müssen Ihre Zeichenfolge in Abhängigkeit von der Teilefarbe aufteilen und so viele Run-Objekte erstellen, wie Sie benötigen.

3
Elo

Es ist Arbeit für mich! Ich hoffe es wird dir nützlich sein!

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

Bei Verwendung von Selection in WPF und Aggregieren aus mehreren anderen Antworten ist kein anderer Code erforderlich (außer Severity-Enum und GetSeverityColor-Funktion)

 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
Honza Nav
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
KhaledDev

Wenn Sie den Text wie von jemandem ausgewählt auswählen, kann die Auswahl kurz erscheinen. In Windows Forms applications gibt es keine anderen Lösungen für das Problem, aber heute habe ich eine schlechte, funktionierende Lösung gefunden: Sie können eine PictureBox in eine Überlappung mit der RichtextBox setzen. mit dem Screenshot von if, während der Auswahl und dem Ändern der Farbe oder Schriftart, so dass alle wieder angezeigt werden, wenn der Vorgang abgeschlossen ist.

Code ist hier ...

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

Besser ist es, WPF zu verwenden. Diese Lösung ist nicht perfekt, aber für Winform funktioniert es.

0
user6730329