Färben Sie verschiedene Teile einer RichTextBox-Zeichenfolge

108

Ich versuche, Teile einer Zeichenfolge einzufärben, die an eine RichTextBox angehängt werden sollen. Ich habe eine Saite aus verschiedenen Saiten aufgebaut.

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

So würde die Nachricht aussehen, wenn sie einmal erstellt wurde.

[9:23 pm] Benutzer: meine Nachricht hier.

Ich möchte, dass alles in und einschließlich der Klammern [9:23] eine Farbe hat, "Benutzer" eine andere Farbe und die Nachricht eine andere Farbe. Dann möchte ich, dass die Zeichenfolge an meine RichTextBox angehängt wird.

Wie kann ich das erreichen?

Fatal510
quelle
5
Ich habe gesucht und nichts davon nützlich gefunden.
Fatal510
Vielen Dank für diese einfache Lösung, funktioniert gut für mich. Vergessen Sie nicht, den AppendText (...) jedes Mal zu verwenden, wenn Sie Text anhängen möchten, und nicht den Operator '+ =', da sonst angewendete Farben verworfen werden.
Xhis

Antworten:

237

Hier ist eine Erweiterungsmethode, die die AppendTextMethode 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 Ideen zum Reduzieren des RichTextBox-Flimmerns.

Nathan Baulch
quelle
3
Ich hatte einige Probleme damit. Ich habe an einem anderen Ort verwendet box.Text += mystringund so verschwanden alle Farben. Als ich dies durch ersetzte box.AppendText(mystring), funktionierte es wie ein Charme.
Natrium
3
Ich habe einige Probleme mit dem Code, den die Farbe beim Hinzufügen eines Strings in einer anderen Farbe verschwindet. Der einzige Unterschied besteht darin, dass ich einer zuvor erstellten Richtextbox eine Var-Box zuordne ....
manu_dilip_shah
Was mache ich falsch ... "SelectionStart" ist keine Eigenschaft einer RichTextBox (oder ich kann zumindest nicht darauf zugreifen)? Ich habe "Selection" gefunden, aber es ist eine Get-Only-Eigenschaft ...
00jt
2
Dies ist speziell für WinForms. Verwenden Sie WPF zufällig?
Nathan Baulch
Ich habe keine Überlastung ikee dies, nur AppendText(string text)mit WinForms
vaso123
12

Ich habe die Methode mit der Schriftart 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;
}
Renan F.
quelle
Hinweis - Damit dies funktioniert, müssen Sie die AppendText-Methode verwenden. Wenn Sie der Texteigenschaft des Felds etwas zuweisen, wird es beschädigt.
Jeff
8

Dies ist die modifizierte Version, die ich in meinen Code eingefügt habe (ich verwende .Net 4.5), aber ich denke, sie sollte auch unter 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, einer neuen Zeile Text hinzuzufügen oder ihn einfach anzuhängen
  • Die Auswahl muss nicht geändert werden, sie funktioniert genauso
  • ScrollToCaret eingefügt, um das automatische Scrollen zu erzwingen
  • Layoutaufrufe zum Anhalten / Fortsetzen hinzugefügt
Tedebus
quelle
5

Ich denke, das Ändern eines "ausgewählten Textes" in einer RichTextBox ist nicht der richtige Weg, um farbigen Text hinzuzufügen. Also hier eine Methode, um einen "Farbblock" 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 eine Sammlung von Absatzelementen. Der Inhalt in jedem Absatzelement kann die folgenden Elemente enthalten:

  • In der Reihe

  • InlineUIContainer

  • Lauf

  • Spanne

  • Fett gedruckt

  • Hyperlink

  • Kursiv

  • Unterstreichen

  • Zeilenumbruch

Ich denke, Sie müssen Ihre Zeichenfolge abhängig von der Farbe der Teile teilen und so viele RunObjekte wie nötig erstellen .

Elo
quelle
Ich hatte gehofft, dass dies die Antwort war, nach der ich wirklich gesucht habe, aber es scheint eine WPF-Antwort und keine WinForms-Antwort zu sein.
Kristen Hammack
3

Es funktioniert 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;
}
Mohammad Fathi MiMFa
quelle
0

Wenn Sie Text wie von jemandem ausgewählt auswählen, wird die Auswahl möglicherweise vorübergehend angezeigt. Es Windows Forms applicationsgibt keine anderen Lösungen für das Problem, aber heute habe ich einen schlechten, funktionierenden Weg gefunden, um es zu lösen: Sie können eine PictureBoxÜberlappung mit dem setzenRichtextBox mit dem Screenshot von if, während der Auswahl und der Änderung der Farbe oder Schriftart, um es danach zu machen erscheinen alle wieder, wenn der Vorgang abgeschlossen ist.

Code ist da ...

//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 sie.


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

        }
KhaledDev
quelle
0

Bei Verwendung von Selection in WPF, aggregiert 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();
    }
Honza Nav
quelle
0

Ich habe diese Funktion nach Recherchen im Internet erstellt, da ich eine XML-Zeichenfolge drucken wollte, wenn Sie eine Zeile aus einer Datenrasteransicht auswählen.

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

und so nennst du es

   HighlightPhrase(richTextBox1, "<", ">","</", Color.Red, Color.Black);
N. Tesla
quelle
Dies löst das gegebene Problem nicht, sondern zeigt nur, wie die Lösung funktionieren könnte.
Josef Bláha