4

私はこのコードで作業しています。での構文強調表示用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()私の最初の質問は、 inに入るとき、OnTextChanged()常に末尾に改行文字があるのm_strLineですか? 最小値m_strLineは「\n」で最大値は「any#ofchars+\n」ですか?

  • そして、私はこの権利を持っています.がゼロのSelectionStart場合、私のキャレットの位置はありますか?SelectionLengthSelectionLengthSelectStart+SelectionLength

  • このコードを変更して、さまざまな構文式に色を付けようとしています。行ごとに、一度に 1 文字ずつ実行する予定です。20,000 行以上のファイルを貼り付けまたはロードする場合、これはどのように公平になるでしょうか?

4

4 に答える 4

7

私が今あなたに提案できるのは、Scintilla for .NET や Color Code など、安定した、より強力で、エラーが発生しにくいものを使用することだけです。これらのコントロールは無料でオープン ソースです。それらを試してみてください:

ScintillaNET
ColorCode - .NET の構文の強調表示/色付け

RichTextBox は、大きなテキストを扱うには非常に非効率的です。まともな強調表示が得られたとしても、パフォーマンスの問題はすぐに現れ始めます.

于 2012-08-13T19:50:02.470 に答える
1

これは本当にひどくスケーリングするでしょう。目標が単に機能するアプリケーションである場合は、DelegateXが提案することを実行する必要があります。方法を学ぶためにこれに参加している場合は、実行される作業の量を減らす方法を見つけることから始めます。そのために、ここにいくつかの一般的な指針があります:

ウィンドウ内のテキストを強調表示するだけで、視覚的な副作用のない大幅な改善が得られます。おそらく、テキストをブロックに分割し(関数、メソッド、クラスなど)、表示されているブロックのみを強調表示することもできます。オフセット開始位置がハイライトに影響を与える問題を回避するために、オクルージョンされた部分。これを行わないと、最初にレンダリングされた行がifブロックまたは括弧ブロックの途中にあり、その結果、構文ツリーのバランスが崩れる状況に遭遇します。

それでもRichTextBoxコントロールで20k行を処理することはできませんが、数千行は高速であるはずです。

于 2012-08-13T19:59:54.427 に答える
0

同じ問題に直面し、「5 分で準備完了」の解決策が見つからなかったため、XML を強調表示する独自の RichTextBox 拡張機能を開発しました。

時間のプレッシャーのために非常に迅速に開発し、修正する時間がありませんでした - 自由に改良してください。

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
    }
}
于 2016-11-15T17:23:41.483 に答える