【问题标题】:Highlight bracketed parts of RichTextBox in C#在 C# 中突出显示 RichTextBox 的括号部分
【发布时间】:2016-03-19 06:22:50
【问题描述】:

我需要一种方法来动态(在 TextChanged 事件上)突出显示 RichTextBox 的括号部分,但我被卡住了。 例如,如果文本是:

“这是一个{非常美好}和{和平}的早晨”

“{very nice}”和“{peacefull}”部分(包括括号)应该使用不同的文本颜色。

【问题讨论】:

  • 如果括号可能嵌套,那么这不是一个小问题,您需要在 RTB 中解析整个文本。在非嵌套情况下,快速解决方案是等到用户输入} 字符,然后找到匹配的{ 字符,根据这些字符索引选择文本范围并更改选定的文本属性(例如颜色 - msdn.microsoft.com/en-us/library/…
  • 不,括号不能嵌套。检查输入的最后一个字符是一个不错的方法。但是如果用户删除了一个随机括号呢?也许我应该在每次击键时解析整个文本以重新应用格式。

标签: c# richtextbox highlighting


【解决方案1】:

您可能正在寻找带有语法高亮的 RichTextBox(您尝试高亮的内容类似于代码编辑器中的字符串高亮)。 stackoverflow 上有很多问题已经有了很好的答案,例如 A textbox/richtextbox that has syntax highlighting? [C#]。如果您必须使用 RichTextBox,您可以使用以下代码开始

private void rtb_TextChanged(object sender, EventArgs e) {
        var cursorPosition = rtb.SelectionStart;

        rtb.SelectAll();
        rtb.SelectionColor = Color.Black;

        var partsToHighlight = Regex.Matches(rtb.Text, "{[^}{]*}")
            .Cast<Match>()
            .ToList();

        foreach (var part in partsToHighlight) {
            rtb.Select(part.Index, part.Length);
            rtb.SelectionColor = Color.Red;
        }

        rtb.Select(cursorPosition, 0);
    }

不幸的是,它会导致闪烁、滚动条位置丢失,并且在处理大量文本时可能需要一些时间。更好的方法是使用一些自定义控件,例如闪烁:

public partial class Form1 : Form {
    private readonly CustomLexer _lexer = new CustomLexer();

    public Form1() {
        InitializeComponent();

        var editor = new ScintillaNET.Scintilla {
            Dock = DockStyle.Fill,

        };
        this.Controls.Add(editor);

        editor.StyleResetDefault();
        editor.Styles[Style.Default].Font = "Consolas";
        editor.Styles[Style.Default].Size = 10;
        editor.StyleClearAll();

        editor.Styles[CustomLexer.StyleText].ForeColor = Color.Black;
        editor.Styles[CustomLexer.StyleParens].ForeColor = Color.Red;


        editor.Lexer = Lexer.Container;
        editor.StyleNeeded += scintilla_StyleNeeded;
    }

    private void scintilla_StyleNeeded(object sender, StyleNeededEventArgs e) {
        var scintilla = (ScintillaNET.Scintilla)sender;

        var startPos = scintilla.GetEndStyled();
        var endPos = e.Position;

        _lexer.Style(scintilla, startPos, endPos);
    }
}

public class CustomLexer {
    public const int StyleText = 0;
    public const int StyleParens = 1;

    private const int STATE_TEXT = 0;
    private const int STATE_INSIDE_PARENS = 1;

    public void Style(Scintilla scintilla, int startPosition, int endPosition) {
        // Back up to the line start

        var startLine = scintilla.LineFromPosition(startPosition);
        var endLine = scintilla.LineFromPosition(endPosition);

        var fixedStartPosition = scintilla.Lines[startLine].Position;
        var fixedStopPosition = scintilla.Lines[endLine].Position + scintilla.Lines[endLine].Length;

        scintilla.StartStyling(fixedStartPosition);

        bool insideBrackets = false;
        for (var i = fixedStartPosition; i < fixedStopPosition; i++) {
            var c = (char)scintilla.GetCharAt(i);

            if (c == '{') insideBrackets = true;

            if (insideBrackets) {
                scintilla.SetStyling(1, StyleParens);
            }
            else {
                scintilla.SetStyling(1, StyleText);
            }

            if (c == '}') insideBrackets = false;
        }
    }
}

这是基于一个很棒的教程here

【讨论】:

    猜你喜欢
    • 2016-10-07
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 2013-11-13
    • 2011-08-06
    • 1970-01-01
    • 2020-12-24
    • 2016-05-06
    相关资源
    最近更新 更多