我正在与this code合作。它用于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;
}
我的第一个问题是,当我进入ProcessLine()
中的OnTextChanged()
时,我是否会在m_strLine
结束时始终使用换行符?最小值或m_strLine
是“\ n”还是最大的“任何#ofchars + \ n”?
正好如此,如果SelectionStart
为零,SelectionLength
是我的插入位置,如果SelectionLength
大于零,则我的插入符号为{{1} }}
我正在尝试修改此代码以为许多不同的语法表达式着色,并且我计划每行一个字符,每行一行。粘贴或加载20k +行的文件时,这怎么可能?
答案 0 :(得分:5)
我现在可以建议你使用稳定,功能更强大且不易出错的东西,例如Scintilla for .NET和Color Code。这些控件是免费和开源的。试试看:
ScintillaNET {
{3}}
RichTextBox对于处理大型文本效率极低。即使你得到了一些不错的突出显示,性能问题也会很快开始出现。
答案 1 :(得分:1)
这将非常严重。如果你的目标只是一个正常运行的应用程序,你应该做DelegateX建议的事情;如果你是在这里学习如何,首先要找出减少工作量的方法。为此,这里有一些一般指针:
仅突出显示窗口内的文本将是一个没有任何视觉副作用的巨大改进 - 它可能也可以将文本分解为块(通过函数,方法,类等)并且只突出显示块,甚至是被遮挡的部分,以避免偏移起始位置影响高光的问题。如果不这样做,您将遇到第一个渲染线在 if 或括号块的中途,并且结果有一个不平衡的语法树的情况。
你仍然无法使用RichTextBox控件处理20k行,但是数千应该是快速的。
答案 2 :(得分:0)
面对同样的问题,未能找到准备好的5分钟&#34;解决方案,我已经开发了自己的RichTextBox扩展来突出显示XML。
由于时间压力,我开发得非常快,没有时间对其进行修改 - 所以请随意改进它。
只需复制&amp;粘贴扩展代码以与RichTextBox一起使用或复制整个 应用程序代码包括同步和异步使用
扩展方法
// 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
}
}
答案 3 :(得分:0)
修正版 - 将JSON作为内部文本和更好的元素提取处理
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
}