C# RichTextBox语法突出显示
我和你一起工作。它用于在C# RichTextBox语法突出显示,c#,richtextbox,C#,Richtextbox,我和你一起工作。它用于在RichTextBox中突出显示语法。我特别关注的是函数ProcessLine()和OnTextChanged(),我对其进行了如下修改: protected override void OnTextChanged(EventArgs e) { // Calculate stuff here. m_nContentLength = this.TextLength; int nCurrentSelectionStart = SelectionSta
RichTextBox
中突出显示语法。我特别关注的是函数ProcessLine()
和OnTextChanged()
,我对其进行了如下修改:
protected override void OnTextChanged(EventArgs e)
{
// Calculate stuff here.
m_nContentLength = this.TextLength;
int nCurrentSelectionStart = SelectionStart;
int nCurrentSelectionLength = SelectionLength;
m_bPaint = false;
// Find the start of the current line.
m_nLineStart = nCurrentSelectionStart;
while ((m_nLineStart > 0) && (Text[m_nLineStart - 1] != '\n'))
m_nLineStart--;
// Find the end of the current line.
m_nLineEnd = nCurrentSelectionStart;
while ((m_nLineEnd < Text.Length) && (Text[m_nLineEnd] != '\n'))
m_nLineEnd++;
// Calculate the length of the line.
m_nLineLength = m_nLineEnd - m_nLineStart;
// Get the current line.
m_strLine = Text.Substring(m_nLineStart, m_nLineLength);
// Process this line.
ProcessLine();
m_bPaint = true;
}
// Process a line.
private void ProcessLine()
{
// Save the position and make the whole line black
int nPosition = SelectionStart;
SelectionStart = m_nLineStart;
SelectionLength = m_nLineLength;
SelectionColor = Color.Black;
/*// Process the keywords
ProcessRegex(m_strKeywords, Settings.KeywordColor);
// Process numbers
if(Settings.EnableIntegers)
ProcessRegex("\\b(?:[0-9]*\\.)?[0-9]+\\b", Settings.IntegerColor);
// Process strings
if(Settings.EnableStrings)
ProcessRegex("\"[^\"\\\\\\r\\n]*(?:\\\\.[^\"\\\\\\r\\n]*)*\"", Settings.StringColor);
// Process comments
if(Settings.EnableComments && !string.IsNullOrEmpty(Settings.Comment))
ProcessRegex(Settings.Comment + ".*$", Settings.CommentColor);*/
SelectionStart = nPosition;
SelectionLength = 0;
SelectionColor = Color.Red;
m_nCurSelection = nPosition;
}
protectedoverride void OnTextChanged(事件参数e)
{
//计算这里的东西。
m_nContentLength=this.TextLength;
int nCurrentSelectionStart=SelectionStart;
int nCurrentSelectionLength=SelectionLength;
m_b绘制=假;
//找到当前行的开始。
m_nLineStart=n当前选择开始;
而((m_nLineStart>0)和&(Text[m_nLineStart-1]!='\n'))
m_nLineStart--;
//找到当前行的末尾。
m_nlined=n当前选择开始;
while((m_nlinend
- 我的第一个问题是,当我在
中输入OnTextChanged()
时,我是否总是在ProcessLine()
的末尾有一个换行符?最小值或m_strLine
是否为“\n”,最大值是否为“\n”m_strLine
- 我有这个权利,
是我的插入符号位置,如果SelectionStart
为零,如果SelectionLength
大于零,我的插入符号位于SelectionLength
SelectStart+SelectionLength
- 我正试图修改这段代码,使其为大量不同的语法表达式着色,我计划对每一行一个字符进行检查。当粘贴或加载一个20k+行的文件时,这怎么公平呢
RichTextBox处理大文本的效率极低。即使您得到一些适当的突出显示,性能问题也会很快出现。这将严重影响扩展。如果您的目标仅仅是一个正常运行的应用程序,那么您应该按照DelegateX的建议去做;如果你想学习如何做,首先要想办法减少工作量。为此,这里有一些一般性的提示: 仅突出显示窗口内的文本将是一个巨大的改进,不会产生任何视觉副作用-将文本分成块(按函数、方法、类等)并仅突出显示可见块,甚至是被遮挡的部分,可能也是可行的,避免偏移起始位置影响高光的问题。如果不这样做,您将遇到这样的情况:第一条渲染线部分穿过If或括号块,结果是语法树不平衡
您仍然无法使用RichTextBox控件处理20k行,但数千行应该会更快。面对同样的问题,并且未能找到“5分钟准备就绪”解决方案,我开发了自己的RichTextBox扩展来突出XML 由于时间的压力,我开发得非常快,没有时间修改它,所以请随意修改它 只需复制并粘贴扩展代码以与RichTextBox一起使用,或者复制整个扩展代码 应用程序代码,包括同步和异步使用 扩展方法
//用于异步突出显示
公共委托无效操作OnRichTextBox(RichTextBox-RichTextBox);
//扩展类
公共静态类RichTextBoxExtensions
{
公共静态void HighlightXml(此RichTextBox RichTextBox)
{
新的StandardHighlight().HighlightXml(richTextBox);
}
公共异步静态void HighlightXmlAsync(此RichTextBox RichTextBox)
{
var helper=新的StandardHighlight();
var win=新的主窗口();
等待任务。工厂。开始新建(()=>
{
richTextBox.Dispatcher.BeginInvoke(新的VoidActionOnRichTextBox(helper.HighlightXml),richTextBox);
});
}
}
//您可以使用更多高亮显示方法来扩展它
公共课标准亮点
{
public void HighlightXml(RichTextBox RichTextBox)
{
//收集文本框信息
var textRange=new textRange(richTextBox.Document.ContentStart,richTextBox.Document.ContentEnd).Text;
XDocument XDocument;
尝试
{
xDocument=xDocument.Parse(textRange);
}
抓住
{
返回;
}
var documentLines=xDocument.ToString().Split(new[]{Environment.NewLine},StringSplitOptions.None);
//获取最长的行长度
int?maxVal=null;
对于(int i=0;i// Use for asynchronous highlight
public delegate void VoidActionOnRichTextBox(RichTextBox richTextBox);
// Extension Class
public static class RichTextBoxExtensions
{
public static void HighlightXml(this RichTextBox richTextBox)
{
new StandardHighlight().HighlightXml(richTextBox);
}
public async static void HighlightXmlAsync(this RichTextBox richTextBox)
{
var helper = new StandardHighlight();
var win = new MainWindow();
await Task.Factory.StartNew(() =>
{
richTextBox.Dispatcher.BeginInvoke(new VoidActionOnRichTextBox(helper.HighlightXml), richTextBox);
});
}
}
// You can extent it with more highlight methods
public class StandardHighlight
{
public void HighlightXml(RichTextBox richTextBox)
{
// Collect Text-Box Information
var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd).Text;
XDocument xDocument;
try
{
xDocument = XDocument.Parse(textRange);
}
catch
{
return;
}
var documentLines = xDocument.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);
// Get the Longest Line Length
int? maxVal = null;
for (int i = 0; i < documentLines.Length; i++)
{
int thisNum = documentLines[i].Length;
if (!maxVal.HasValue || thisNum > maxVal.Value) { maxVal = thisNum; }
}
// Set Text-Box Width & Clear the Current Content
if (maxVal != null) richTextBox.Document.PageWidth = (double)maxVal * 5.5;
richTextBox.Document.Blocks.Clear();
#region *** Process Lines ***
foreach (var documentLine in documentLines)
{
// Parse XML Node Components
var indentSpace = Regex.Match(documentLine, @"\s+").Value;
var xmlTags = Regex.Matches(documentLine, @"(<[^/].+?)(?=[\s])|(<[^/].+?>)|(</.+?>)");
if (documentLine.Contains("<!--")) xmlTags = Regex.Matches(documentLine, @"(<[^/].+?>)"); // Parse comments
var nodeAttributes = Regex.Matches(documentLine, @"(?<=\s)(.+?)(?=\s)");
// Process XML Node
var nodeAttributesCollection = new List<Run>();
if (nodeAttributes.Count > 0)
{
for (int i = 0; i < nodeAttributes.Count; i++)
{
if (!(nodeAttributes[i].Value.Length < 2) && !(documentLine.Contains("<!--")))
{
var attributeName = $"{Regex.Match(nodeAttributes[i].Value, @"(.+?=)").Value}";
if (i == 0) attributeName = $" {Regex.Match(nodeAttributes[i].Value, @"(.+?=)").Value}";
var attributeValue = $"{Regex.Match(nodeAttributes[i].Value, @"(?<=(.+?=))"".+?""").Value} ";
if (i == nodeAttributes.Count - 1) attributeValue = attributeValue.Trim();
nodeAttributesCollection.Add(new Run { Foreground = new SolidColorBrush(Colors.Green), Text = $"{attributeName}" });
nodeAttributesCollection.Add(new Run { Foreground = new SolidColorBrush(Colors.Brown), Text = $"{attributeValue}" });
}
}
}
// Initialize IndentSpace
Run run = null;
if (indentSpace.Length > 1) run = new Run { Text = indentSpace };
// Initialize Open Tag
var tagText = xmlTags[0].Value.Substring(1, xmlTags[0].Value.Length - 2);
var tagTextBrush = new SolidColorBrush(Colors.Blue);
var tagBorderBruh = new SolidColorBrush(Colors.Red);
if (tagText.StartsWith("!--"))
{
tagTextBrush = new SolidColorBrush(Colors.DarkSlateGray);
tagBorderBruh = new SolidColorBrush(Colors.DarkSlateGray);
}
var openTag = new Run
{
Foreground = tagTextBrush,
Text = tagText
};
// Initialize Content Tag
var content = new Run
{
Foreground = new SolidColorBrush(Colors.Black),
};
// Initialize Paragraph
var paragraph = new Paragraph();
paragraph.Margin = new Thickness(0);
if (run != null) paragraph.Inlines.Add(run); // Add indent space if exist
// Process Open Tag
paragraph.Inlines.Add(new Run { Foreground = tagBorderBruh, Text = "<" });
paragraph.Inlines.Add(openTag);
// Process Open Tag Attributes
if (nodeAttributesCollection.Count > 0)
{
nodeAttributesCollection.ForEach(attribute => { paragraph.Inlines.Add(attribute); });
nodeAttributesCollection.Clear();
}
paragraph.Inlines.Add(new Run { Foreground = tagBorderBruh, Text = ">" });
// Process Closing Tag
if (xmlTags.Count > 1)
{
Run closingTag = new Run();
content.Text = documentLine.Replace(xmlTags[0].Value, "").Replace(xmlTags[1].Value, "").Trim();
closingTag = new Run
{
Foreground = new SolidColorBrush(Colors.Blue),
Text = xmlTags[1].Value.Substring(1, xmlTags[1].Value.Length - 2)
};
paragraph.Inlines.Add(content);
paragraph.Inlines.Add(new Run { Foreground = new SolidColorBrush(Colors.Red), Text = "<" });
paragraph.Inlines.Add(closingTag);
paragraph.Inlines.Add(new Run { Foreground = new SolidColorBrush(Colors.Red), Text = ">" });
}
richTextBox.Document.Blocks.Add(paragraph);
}
#endregion
}
}
public static void HighlightXml(this RichTextBox richTextBox)
{
// Collect Text-Box Information
var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd).Text;
XmlDocument xmlDocument = new XmlDocument();
try
{
xmlDocument.LoadXml(textRange.Trim());
}
catch
{
return;
}
var documentLines = xmlDocument.OuterXml.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
// Get the Longest Line Length
int? maxVal = null;
for (int i = 0; i < documentLines.Length; i++)
{
int thisNum = documentLines[i].Length;
if (!maxVal.HasValue || thisNum > maxVal.Value) { maxVal = thisNum; }
}
// Set Text-Box Width & Clear the Current Content
if (maxVal != null) richTextBox.Document.PageWidth = (double)maxVal * 10;
richTextBox.Document.Blocks.Clear();
#region *** Process Lines ***
foreach (var documentLine in documentLines)
{
// Parse XML Node Components
var indentSpace = Regex.Match(documentLine, @"\s+").Value;
var xmlTags = Regex.Matches(documentLine, @"(?<=<)[^>\s+]*");
if (documentLine.Contains("<!--")) xmlTags = Regex.Matches(documentLine, @"(<[^/].+?>)");
var nodeAttributes = Regex.Matches(documentLine, @"(?<=\s)[^><:\s]*=*(?=[>,\s])");
// Process XML Node
var nodeAttributesCollection = new List<Run>();
if (nodeAttributes.Count > 0)
{
for (int i = 0; i < nodeAttributes.Count; i++)
{
if (!(nodeAttributes[i].Value.Length < 2) && !(documentLine.Contains("<!--")))
{
var attributeName = $"{Regex.Match(nodeAttributes[i].Value, @"(.+?=)").Value}";
if (i == 0) attributeName = $" {Regex.Match(nodeAttributes[i].Value, @"(.+?=)").Value}";
var attributeValue = $"{Regex.Match(nodeAttributes[i].Value, @"(?<=(.+?=))"".+?""").Value} ";
if (i == nodeAttributes.Count - 1) attributeValue = attributeValue.Trim();
nodeAttributesCollection.Add(new Run { Foreground = new SolidColorBrush(Colors.Green), Text = $"{attributeName}" });
nodeAttributesCollection.Add(new Run { Foreground = new SolidColorBrush(Colors.Brown), Text = $"{attributeValue}" });
}
}
}
// Initialize IndentSpace
Run run = null;
if (indentSpace.Length > 1) run = new Run { Text = indentSpace };
// Initialize Open Tag
var tagText = xmlTags[0].Value;//.Substring(1, xmlTags[0].Value.Length - 2);
var tagTextBrush = new SolidColorBrush(Colors.Blue);
var tagBorderBruh = new SolidColorBrush(Colors.Red);
if (tagText.StartsWith("!--"))
{
tagTextBrush = new SolidColorBrush(Colors.DarkSlateGray);
tagBorderBruh = new SolidColorBrush(Colors.DarkSlateGray);
}
var openTag = new Run
{
Foreground = tagTextBrush,
Text = tagText
};
// Initialize Content Tag
var content = new Run
{
Foreground = new SolidColorBrush(Colors.Black),
};
// Initialize Paragraph
var paragraph = new Paragraph();
paragraph.Margin = new Thickness(0);
if (run != null) paragraph.Inlines.Add(run); // Add indent space if exist
// Process Open Tag
paragraph.Inlines.Add(new Run { Foreground = tagBorderBruh, Text = "<" });
paragraph.Inlines.Add(openTag);
// Process Open Tag Attributes
if (nodeAttributesCollection.Count > 0)
{
nodeAttributesCollection.ForEach(attribute => { paragraph.Inlines.Add(attribute); });
nodeAttributesCollection.Clear();
}
paragraph.Inlines.Add(new Run { Foreground = tagBorderBruh, Text = ">" });
// Process Closing Tag
if (xmlTags.Count > 1)
{
Run closingTag = new Run();
content.Text = documentLine.Replace($"<{xmlTags[0].Value}>", "").Replace($"<{xmlTags[1].Value}>", "").Trim();
closingTag = new Run
{
Foreground = new SolidColorBrush(Colors.Blue),
Text = xmlTags[1].Value.Substring(1, xmlTags[1].Value.Length - 1)
};
paragraph.Inlines.Add(content);
paragraph.Inlines.Add(new Run { Foreground = new SolidColorBrush(Colors.Red), Text = "<" });
paragraph.Inlines.Add(closingTag);
paragraph.Inlines.Add(new Run { Foreground = new SolidColorBrush(Colors.Red), Text = ">" });
}
richTextBox.Document.Blocks.Add(paragraph);
}
#endregion
}