2015-12-13 5 views
0

Мне нужен способ динамически (при событии TextChanged) выделить выделенные в скобки части RichTextBox, но я застрял. Например, если текст:Выделите заключенные в скобки части RichTextBox в C#

«Это {очень хороший} и {мирное} утро»

части «{очень хороший}» и «{Peacefull}» (включая скобки) должны получить другой цвет текста.

+0

Если скобки могут быть вложенными, это не является тривиальной проблемой, и вам необходимо проанализировать весь текст в RTB. В не вложенном случае быстрое решение ждет, пока пользователь не войдет в символ '}', а затем найдет соответствующий символ '{', выберите диапазон текста на основе этих символьных индексов и измените выбранные текстовые атрибуты (например, цвет - https://msdn.microsoft. com/en-us/library/system.windows.forms.richtextbox.selectioncolor (v = vs.110) .aspx) – csharpfolk

+0

Нет, скобки не могут быть вложенными. Чтобы проверить последний введенный символ, это хороший подход. Но если пользователь удаляет случайную скобку? Возможно, я должен разобрать весь текст на каждое нажатие клавиши, чтобы повторно применить форматирование. – ion

ответ

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); 
    } 

К сожалению, это вызывает мерцание, теряет позицию прокрутки бара и может занять некоторое время при обработке больших блоков текста. Лучше всего использовать некоторый пользовательский контроль, например. 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.

+0

Большое спасибо! – ion