winforms 使用模式突出显示RichTextBox中的文本/为文本着色

myss37ts  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(156)

我正在尝试基于模式创建一个彩色RichTextBox。
正文是:

Hey, This{Red} IS A {Cyan}sample. The {Green}color is green color

每个{ }包含一种颜色,它是下一个单词的样式:
嘿,这是一个颜色是绿色的颜色
Hey, This默认颜色。
IS A应为红色。
sample. The应为青色。
color is green color应为绿色。
下面是我的代码:

// Hey, This{Red} IS A {Cyan}sample. The {Green}color is green color
// shown text should be:
// Hey, This IS A sample. The color is green

const string OriginalText = "Hey, This{Red} IS A {Cyan}sample. The {Green}color is green color";
const string ShownText = "Hey, This IS A sample. The color is green color";
const string Pattern = "(?<=\\{)(.*?)(?=\\})";

rtbMain.Text = ShownText;

rtbMain.SelectAll();
rtbMain.SelectionColor = Color.Black;
rtbMain.SelectionBackColor = Color.White;
Regex regex = new(Pattern, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(OriginalText);

if (matches.Count > 0)
{
    var rtbText = rtbMain.Text;
    var length = ShownText.Length;
    var allMatches = new List<Match>();

    for (int i = 0; i < matches.Count; i++)
    {
        var m = matches[i];
        allMatches.Add(m);
        Match nextMatch = null;
        if (matches.Count > i + 1)
        {
            nextMatch = matches[i + 1];
        }
        var sum = GetSum();
        var start = m.Index;
        var currentLength = m.Length;
        if (nextMatch != null)
        {
            var end = nextMatch.Index - start- sum;
            rtbMain.Select(start- 1, end);
        }
        else
        {
            var currentIndex = OriginalText.IndexOf(m.Value);
            rtbMain.Select(length - currentIndex, (length - currentIndex) - sum);
        }
        rtbMain.SelectionColor = GetColor(m.Value);
    }
    int GetSum()
    {
        return allMatches!.Select(m => m.Value.Length - 1).Sum();
    }
    Color GetColor(string color)
    {
        return Color.FromName(color);
    }
}
else
{
    Debug.WriteLine("No matches found");
}

由于RichTextBox没有颜色标记,我不知道如何计算索引/长度的正确位置。
屏幕截图:

gg58donl

gg58donl1#

您也可以比对要剖析之字串的结束位置,然后在循环Matches集合时,您只需要计算字串内的目前位置,并考虑每个相符项目的长度。
使用稍微修改的正则表达式,每个Match的IndexLength引用匹配的标签(例如{green}),并且Group 1中的每个值是Color的名称。
大概是这样的:
(note这里只使用了SelectionColor,因为我在每次迭代时都会向Control追加一个新字符串。添加的新字符串实际上已经是一个Selection,所以不需要显式设置选择的长度)

string originalText = 
    "Hey, This{Red} IS A {Cyan}sample. The {Green}color is green color\n" +
    "plus other text {blue} and some more {orange}colors";

string pattern = @"\{(.*?)\}|$";
var matches = Regex.Matches(originalText, pattern, RegexOptions.IgnoreCase);
int currentPos = 0;

foreach (Match m in matches) {
    someRichTextBox.AppendText(originalText.Substring(currentPos, m.Index - currentPos));

    currentPos = m.Index + m.Length;
    someRichTextBox.SelectionColor = Color.FromName(m.Groups[1].Value);
};
someRichTextBox.SelectionColor = someRichTextBox.ForeColor;

导致:

相关问题