为RichTextBox字符串的不同部分上色


109

我正在尝试为要附加到RichTextBox的字符串部分上色。我有一个由不同的字符串构建的字符串。

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

这是消息一旦构造后的样子。

[9:23 pm]用户:我的留言在这里。

我希望方括号[9:23]中的所有内容(包括括号在内)都是一种颜色,“用户”是另一种颜色,消息是另一种颜色。然后,我想将字符串附加到我的RichTextBox中。

我该怎么做?



5
我进行了搜索,但发现没有任何用处。
Fatal510

感谢这种简单的解决方案,对我来说效果很好。不要忘了每次要附加文本时都使用AppendText(...),并且不要使用'+ ='运算符,否则应用的颜色将被丢弃。
Xhis

Answers:


237

这是一个扩展方法,该AppendText方法使用color参数重载该方法:

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

这就是您将如何使用它:

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

请注意,如果输出大量消息,您可能会注意到一些闪烁。有关如何减少RichTextBox闪烁的想法,请参见C#Corner文章。


3
我对此有些麻烦。我在另一个地方用过,box.Text += mystring所以所有的颜色都消失了。当我将其替换box.AppendText(mystring)为时,它就像一个烟囱。
纳里奇

3
我在代码上遇到了麻烦,颜色在以其他颜色添加字符串时消失了。唯一的区别是我将var box分配给先前制作的
richtextbox

我在做什么错...“ SelectionStart”不是RichTextBox的属性(或者我至少无法访问它)?我找到了“选择”,但它是一个只能获取的属性...
00jt 2014年

2
这是专门针对WinForms的。您是否有机会使用WPF?
内森·鲍尔奇

我没有重载ikee,只有AppendText(string text)WinForms
vaso123

12

我已经用字体作为参数扩展了该方法:

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

注意-为此,您必须使用AppendText方法。将任何内容分配给框的text属性都会破坏它。
杰夫

8

这是我放入代码中的修改版本(我使用的是.Net 4.5),但我认为它也应该在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();
}

与原始版本的差异:

  • 可以将文本添加到新行或简单地附加它
  • 无需更改选择,它的工作原理相同
  • 插入ScrollToCaret以强制自动滚动
  • 添加了挂起/恢复布局调用

5

我认为在RichTextBox中修改“选定的文本”不是添加彩色文本的正确方法。所以这里是一种添加“色块”的方法:

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

MSDN

Blocks属性是RichTextBox的content属性。它是段落元素的集合。每个段落元素中的内容可以包含以下元素:

  • 排队

  • InlineUIContainer

  • 跨度

  • 胆大

  • 超连结

  • 斜体

  • 强调

  • 越线

因此,我认为您必须根据零件颜色拆分字符串,并Run根据需要创建尽可能多的对象。


我希望这是我真正想要的答案,但这似乎是WPF答案,而不是WinForms答案。
克里斯汀·哈马克

3

对我有用!希望对您有用!

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

如从某人那里选择文本,选择可能会立即出现。在Windows Forms applications存在该问题没有其他解决办法,但今天我发现了一个错误,工作,方法来解决:你可以把PictureBox重叠的RichtextBox用,如果截图,在选择过程和不断变化的颜色或字体,使其后操作完成后,全部重新出现。

代码在这里...

//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。这个解决方案并不完美,但是对于Winform来说,它可以工作。


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中使用选择,从其他几个答案中汇总,不需要其他代码(严重性枚举和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

我在互联网上研究后创建了此函数,因为当您从数据网格视图中选择一行时,我想打印XML字符串。

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

这就是你的称呼

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

这不能解决给定的问题,仅说明解决方案的工作方式。
JosefBláha
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.