Warnai bagian berbeda dari string RichTextBox

109

Saya mencoba mewarnai bagian string untuk ditambahkan ke RichTextBox. Saya memiliki string yang dibangun dari string yang berbeda.

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

Seperti inilah pesan akan terlihat setelah dibuat.

[21:23] Pengguna: pesan saya di sini.

Saya ingin semua yang ada di dalam dan termasuk tanda kurung [9:23] menjadi satu warna, 'pengguna' menjadi warna lain dan pesan menjadi warna lain. Lalu saya ingin string tersebut ditambahkan ke RichTextBox saya.

Bagaimana saya bisa melakukannya?

Fatal510
sumber
5
Saya melakukan pencarian dan saya tidak menemukan satupun yang berguna.
Fatal510
Terima kasih untuk solusi sederhana ini, berfungsi dengan baik untuk saya. Jangan lupa untuk menggunakan AppendText (...) setiap kali Anda ingin menambahkan teks, dan tidak menggunakan operator '+ =' atau warna yang diterapkan akan dibuang.
Xhis

Jawaban:

239

Berikut adalah metode ekstensi yang membebani AppendTextmetode dengan parameter warna:

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

Dan inilah cara Anda menggunakannya:

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

Perhatikan bahwa Anda mungkin melihat beberapa kedipan jika Anda mengeluarkan banyak pesan. Lihat artikel Sudut C # ini untuk mengetahui cara mengurangi kedipan RichTextBox.

Nathan Baulch
sumber
3
Saya mengalami masalah dengan ini. Saya menggunakan di tempat lain box.Text += mystringsehingga semua warna menghilang. Ketika saya menggantinya dengan box.AppendText(mystring), itu bekerja seperti pesona.
Natrium
3
Saya mengalami masalah dengan kode warna menghilang saat menambahkan string dalam beberapa warna lain. Satu-satunya perbedaan adalah saya menetapkan kotak var ke kotak
teks kaya yang
Apa yang saya lakukan salah ... "SelectionStart" bukan milik RichTextBox (atau setidaknya saya tidak bisa mengaksesnya)? Saya menemukan "Pilihan" tetapi ini adalah properti yang hanya dapat
diperoleh
2
Ini khusus untuk WinForms. Apakah Anda menggunakan WPF secara kebetulan?
Nathan Baulch
Saya tidak memiliki kelebihan seperti ini, hanya AppendText(string text)dengan WinForms
vaso123
12

Saya telah memperluas metode dengan font sebagai 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;
}
Renan F.
sumber
Catatan - agar ini bekerja, Anda harus menggunakan metode AppendText. Menetapkan apa pun ke properti teks kotak akan merusaknya.
Jeff
9

Ini adalah versi modifikasi yang saya masukkan ke dalam kode saya (saya menggunakan .Net 4.5) tetapi saya pikir ini harus berfungsi pada 4.0 juga.

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

Beda dengan yang asli:

  • kemungkinan untuk menambahkan teks ke baris baru atau hanya menambahkannya
  • tidak perlu mengubah pilihan, cara kerjanya sama
  • memasukkan ScrollToCaret untuk memaksa autoscroll
  • menambahkan penangguhan / lanjutkan panggilan tata letak
tedebus
sumber
6

Saya pikir memodifikasi "teks yang dipilih" dalam RichTextBox bukanlah cara yang tepat untuk menambahkan teks berwarna. Jadi di sini metode untuk menambahkan "blok warna":

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

Dari MSDN :

Properti Blok adalah properti konten RichTextBox. Ini adalah kumpulan elemen Paragraph. Konten di setiap elemen Paragraph dapat berisi elemen berikut:

  • Di barisan

  • InlineUIContainer

  • Lari

  • Menjangkau

  • Mencolok

  • Hyperlink

  • Miring

  • Menggarisbawahi

  • LineBreak

Jadi saya pikir Anda harus membagi string Anda tergantung pada warna bagian, dan membuat Runobjek sebanyak yang dibutuhkan.

Elo
sumber
Saya berharap ini adalah jawaban yang benar-benar saya cari, tetapi tampaknya itu jawaban WPF dan bukan jawaban WinForms.
Kristen Hammack
3

Ini berhasil untuk saya! Semoga bermanfaat bagi Anda!

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
sumber
0

Memilih teks seperti yang diucapkan dari seseorang, semoga pemilihan tersebut muncul sesaat. Tidak Windows Forms applicationsada solusi lain untuk masalah ini, tetapi hari ini saya menemukan cara yang buruk, berhasil, untuk memecahkannya: Anda dapat meletakkannya PictureBoxdi tumpang tindih keRichtextBox dengan tangkapan layar jika, selama pemilihan dan perubahan warna atau font, membuatnya setelah muncul kembali semua, setelah operasi selesai.

Kode ada di sini ...

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

Lebih baik menggunakan WPF; solusi ini tidak sempurna, tetapi untuk Winform berhasil.


sumber
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
sumber
0

Menggunakan Pilihan di WPF, menggabungkan dari beberapa jawaban lain, tidak ada kode lain yang diperlukan (kecuali enum Severity dan fungsi 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();
    }
Honza Nav
sumber
0

Saya membuat Fungsi ini setelah meneliti di internet karena saya ingin mencetak string XML saat Anda memilih baris dari tampilan kisi data.

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

dan begitulah Anda menyebutnya

   HighlightPhrase(richTextBox1, "<", ">","</", Color.Red, Color.Black);
N.Tesla
sumber
Ini tidak menyelesaikan masalah yang diberikan, hanya menggambarkan bagaimana solusi tersebut dapat bekerja.
Josef Bláha