Что вы, вероятно, ищете 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);
}
К сожалению, это вызывает мерцание, теряет позицию прокрутки бара и может занять некоторое время при обработке больших блоков текста. Лучше всего использовать некоторый пользовательский контроль, например. Scintilla:
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.
Если скобки могут быть вложенными, это не является тривиальной проблемой, и вам необходимо проанализировать весь текст в RTB. В не вложенном случае быстрое решение ждет, пока пользователь не войдет в символ '}', а затем найдет соответствующий символ '{', выберите диапазон текста на основе этих символьных индексов и измените выбранные текстовые атрибуты (например, цвет - https://msdn.microsoft. com/en-us/library/system.windows.forms.richtextbox.selectioncolor (v = vs.110) .aspx) – csharpfolk
Нет, скобки не могут быть вложенными. Чтобы проверить последний введенный символ, это хороший подход. Но если пользователь удаляет случайную скобку? Возможно, я должен разобрать весь текст на каждое нажатие клавиши, чтобы повторно применить форматирование. – ion