如何扩展 RichTextbox 着色函数来为字符串的部分着色?

How to extend a RichTextbox coloring function to color parts of strings?

private void ColorRichTextbox(RichTextBox box, string text, Color color)
{
    int length = MyRichTextBox.TextLength;
    if (!string.IsNullOrWhiteSpace(MyRichTextBox.Text))
    {
        MyRichTextBox.AppendText("\r\n" + text);
    }
    else
    {
        MyRichTextBox.AppendText(text);
    }
    MyRichTextBox.SelectionStart = length;
    MyRichTextBox.SelectionLength = text.Length;
    MyRichTextBox.SelectionColor = color;
}

用法:

ColorRichTextbox(MyRichTextBox,
                    "This is example : " + DateTime.Now, Color.Red);

结果是红色一行,由“This is example :”和 DateTime.Now 部分组成。有没有办法让“This is example :”部分变成白色,DateTime.Now 变成红色?

如果您修改您的方法以不总是将文本强制排在自己的行上,您可以调用它两次 - 首先是白色文本,然后是红色文本:

private void ColorRichTextbox(RichTextBox box, string text, Color color, bool appendNewLine = true)
{
    int length = box.TextLength;
    if (!string.IsNullOrWhiteSpace(box.Text) && appendNewLine)
    {
        box.AppendText("\r\n" + text);
    }
    else
    {
        box.AppendText(text);
    }
    box.SelectionStart = length;
    box.SelectionLength = text.Length;
    box.SelectionColor = color;
}

通过将 appendNewLine 设置为 false,输入的文本将不会放在单独的行中,因此从上一个调用停止的地方继续:

ColorRichTextbox(MyRichTextBox, "This is example : ", Color.White);
ColorRichTextbox(MyRichTextBox, DateTime.Now.ToString(), Color.Red, false); // false = Don't write this text on a separate line

旁注:您似乎没有使用方法的 box 参数。如果你想将它用于多个 RichTextBox,你应该在你的方法中将 MyRichTextBox 替换为 box(这已在我上面的代码中完成)。

结果:

您也可以使用自定义内插字符串处理程序来执行此操作。

richTextBox1.AppendColoredLine($"This is an example : {DateTime.Now:red}");
richTextBox1.AppendColoredLine($"This is an example : {DateTime.Now:green}");
richTextBox1.AppendColoredLine($"This is an example : {DateTime.Now:blue}");
richTextBox1.AppendColoredLine($"This is an example : {DateTime.Now:yellow}");

richTextBox1.AppendColoredLine($"Some other colored things: {"hi":orange}, {10:purple}, {this.Name:gray}");

这是使其工作的代码(需要 .Net 6):

using System;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace YourNamespace;

public static class RichTextBoxExtensions
{
    [InterpolatedStringHandler]
    [StructLayout(LayoutKind.Auto)]
    public ref struct ColoredStringHandler
    {
        private readonly RichTextBox textBox;
        private readonly IFormatProvider? formatProvider;

        public ColoredStringHandler(int literalLength, int formattedCount, RichTextBox textBox, IFormatProvider? formatProvider = null)
        {
            this.textBox = textBox;
            this.formatProvider = formatProvider;

            textBox.DeselectAll();
        }

        public void AppendLiteral(string s) => textBox.AppendText(s);
        public void AppendFormatted<T>(T item) where T : notnull => AppendLiteral(item.ToString() ?? "");
        public void AppendFormatted<T>(T item, string format) where T : notnull
        {
            var color = Color.FromName(format);
            string? s = 
                item is IFormattable
                ? ((IFormattable)(object)item).ToString(null, formatProvider)
                : item.ToString();

            s ??= "";

            Color previousColor = textBox.SelectionColor;
            try
            {
                textBox.SelectionColor = color;
                textBox.AppendText(s);
            }
            finally
            {
                textBox.SelectionColor = previousColor;
            }
        }
    }

    public static void AppendColored(this RichTextBox textBox, IFormatProvider? formatProvider,
        [InterpolatedStringHandlerArgument("textBox", "formatProvider")] ref ColoredStringHandler handler)
    {

    }

    public static void AppendColored(this RichTextBox textBox,
        [InterpolatedStringHandlerArgument("textBox")] ref ColoredStringHandler handler)
    {

    }

    public static void AppendColoredLine(this RichTextBox textBox, IFormatProvider? formatProvider,
        [InterpolatedStringHandlerArgument("textBox", "formatProvider")] ref ColoredStringHandler handler)
    {
        textBox.AppendText(Environment.NewLine);
    }

    public static void AppendColoredLine(this RichTextBox textBox,
        [InterpolatedStringHandlerArgument("textBox")] ref ColoredStringHandler handler)
    {
        textBox.AppendText(Environment.NewLine);
    }
}