是的,这是可能的,并且比“常规”方法快两倍左右。
在3M文本中更改30k个单词需要28秒,而之前则需要60秒。
以下是我建议的步骤,假设您的单词可以在richTextBox.Rtf
中被识别(*):
顺便提一下,这里有一个RTF参考。
我使用RichTextBox RTB
中的RegEx
进行替换,如下所示:
string search "find me!";
RTB.SelectionStart = 0;
RTB.SelectionLength = 1;
RTB.SelectionColor = Color.HotPink;
Regex RX = new Regex(search);
MatchCollection matches = RX.Matches(RTB.Rtf);
RTB.Rtf = RX.Replace(RTB.Rtf, "\\cf1 " + search + "\\cf0 ");
RTB.SelectionStart = 0;
RTB.SelectionLength = 1;
RTB.SelectionColor = RTB.ForeColor;
(
*) 注意,像这样修改
Rtf
属性假定您的搜索文本在
Rtf
中是可识别的。您可以通过比较搜索
Rtf
和
Text
的匹配计数以检查此内容!当它们不一致时,您可能需要使用“常规”方法。
请注意,此仅处理
Colors
。对于字体大小等,您需要以类似的方式添加
\fn
(它们索引到样式表)命令。
更新:我已将上面的代码包装在扩展函数中,并更好地处理了多种颜色、单词边界和一些检查..:
int colorWords(RichTextBox RTB, String searchWord, Color color)
{
string wordChar = @"\w*";
Regex RX = new Regex(wordChar + searchWord + wordChar);
RTB.SelectionStart = 0;
RTB.SelectionLength = 0;
RTB.SelectedText = "~";
RTB.SelectionStart = 0;
RTB.SelectionLength = 1;
RTB.SelectionColor = color;
MatchCollection matches = null;
matches = RX.Matches(RTB.Text);
int textCount = matches.Count;
matches = RX.Matches(RTB.Rtf);
if (textCount < matches.Count) return -1;
if (matches.Count <= 0) return 0;
List<Color> colors = getRtfColorTable(RTB);
int cIndex = 1;
Color cRGB = Color.FromArgb(255, color);
if (colors.Contains(cRGB) )
cIndex = colors.FindIndex(x => x == cRGB) + 1;
RTB.Rtf = RX.Replace(RTB.Rtf, "\\cf" + cIndex + " " + searchWord + "\\cf0 ");
RTB.SelectionStart = 0;
RTB.SelectionLength = 1;
RTB.Cut();
return matches.Count;
}
这里有一个函数,可以从Rtf颜色表中提取当前的颜色。(希望完整规范不是非常小,用两个简单的
IndexOf
来解决可能有些过于乐观了... ;-)
List<Color> getRtfColorTable(RichTextBox RTB)
{
List<Color> colors = new List<Color>();
string tabString = @"\colortbl ;";
int ct0 = RTB.Rtf.IndexOf(tabString);
if (ct0 >= 0)
{
ct0 += tabString.Length;
int ct1 = RTB.Rtf.IndexOf(@"}", ct0);
var table = RTB.Rtf.Substring(ct0, ct1 - ct0).Split(';');
foreach(string t in table)
{
var ch = t.Split('\\');
if (ch.Length == 4)
{
int r = Convert.ToInt16(ch[1].Replace("red", ""));
int g = Convert.ToInt16(ch[2].Replace("green", ""));
int b = Convert.ToInt16(ch[3].Replace("blue", ""));
colors.Add(Color.FromArgb(255, r, g, b));
}
}
}
return colors;
}
这个例子被称为:
colorWords(RTB, "<DIR>", Color.SaddleBrown);
colorWords(RTB, "Verzeichnis", Color.BlueViolet);
colorWords(RTB, "2012", Color.OrangeRed);