避免扫描整个Richtextbox突出显示

时间:2013-07-11 08:49:13

标签: c# winforms syntax-highlighting

我正在编写代码编辑器,我想出了这组代码:

public class Test2 : Form {

  RichTextBox m_rtb = null;

  public static void Main() {
    Application.Run(new Test2());
  }

  public Test2() {
    Text = "Test2";
    ClientSize = new Size(400, 400);
    m_rtb = new RichTextBox();
    m_rtb.Multiline = true;
    m_rtb.WordWrap = false;
    m_rtb.AcceptsTab = true;
        m_rtb.ScrollBars = RichTextBoxScrollBars.ForcedBoth;
    m_rtb.Dock = DockStyle.Fill;
    m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
    m_rtb.SelectionColor = Color.Black;
    Controls.Add(m_rtb);
    Parse();
    m_rtb.TextChanged += new EventHandler(this.TextChangedEvent);
  }

  void Parse() {
    String inputLanguage = 
      "// Comment.\n" +
      "using System;\n" + "\n" +
      "public class Stuff : Form { \n" +
      "  public static void Main(String args) {\n" +
      "  }\n" +   
      "}\n" ; 

    // Foreach line in input,
    // identify key words and format them when adding to the rich text box.
    Regex r = new Regex("\\n");
    String [] lines = r.Split(inputLanguage);
    foreach (string l in lines) {
      ParseLine(l);
    }    
  }

  void ParseLine(string line) {
    Regex r = new Regex("([ \\t{}();])");
    String [] tokens = r.Split(line);

    foreach (string token in tokens) {
      // Set the token's default color and font.
      m_rtb.SelectionColor = Color.Black;
      m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);

      // Check for a comment.
      if (token == "//" || token.StartsWith("//")) {
        // Find the start of the comment and then extract the whole comment.
        int index = line.IndexOf("//");
        string comment = line.Substring(index, line.Length - index);
        m_rtb.SelectionColor = Color.LightGreen;
        m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
        m_rtb.SelectedText = comment;
        break;
      }

      // Check whether the token is a keyword. 
      String [] keywords = { "public", "void", "using", "static", "class" }; 
      for (int i = 0; i < keywords.Length; i++) {
        if (keywords[i] == token) {
          // Apply alternative color and font to highlight keyword.
          m_rtb.SelectionColor = Color.Blue;
          m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Bold);
          break;
        }
      }
      m_rtb.SelectedText = token;
    }    
    m_rtb.SelectedText = "\n";
  } 

  private void TextChangedEvent(object sender, EventArgs e) {
    // Calculate the starting position of the current line.
    int start = 0, end = 0;
    for (start = m_rtb.SelectionStart - 1; start > 0; start--) {
      if (m_rtb.Text[start] == '\n')  { start++; break; }
    }

    // Calculate the end position of the current line.
    for (end = m_rtb.SelectionStart; end < m_rtb.Text.Length; end++) {
      if (m_rtb.Text[end] == '\n') break;
    }

    // Extract the current line that is being edited.
    String line = m_rtb.Text.Substring(start, end - start);

    // Backup the users current selection point.
    int selectionStart = m_rtb.SelectionStart;
    int selectionLength = m_rtb.SelectionLength;

    // Split the line into tokens.
    Regex r = new Regex("([ \\t{}();])");
    string [] tokens = r.Split(line);
    int index = start;
    foreach (string token in tokens) {

      // Set the token's default color and font.
      m_rtb.SelectionStart = index;
      m_rtb.SelectionLength = token.Length;
      m_rtb.SelectionColor = Color.Black;
      m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);

      // Check for a comment.
      if (token == "//" || token.StartsWith("//")) {
        // Find the start of the comment and then extract the whole comment.
        int length = line.Length - (index - start);
        string commentText = m_rtb.Text.Substring(index, length);
        m_rtb.SelectionStart = index;
        m_rtb.SelectionLength = length;
        m_rtb.SelectionColor = Color.LightGreen;
        m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
        break;
      }

      // Check whether the token is a keyword. 
      String [] keywords = { "public", "void", "using", "static", "class" }; 
      for (int i = 0; i < keywords.Length; i++) {
        if (keywords[i] == token) {
          // Apply alternative color and font to highlight keyword.        
          m_rtb.SelectionColor = Color.Blue;
          m_rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Bold);
          break;
        }
      }
      index += token.Length;
    }
    // Restore the users current selection point.    
    m_rtb.SelectionStart = selectionStart;
    m_rtb.SelectionLength = selectionLength;  
  } 
}

问题是每次按空格键或键入整个代码编辑器继续扫描,如搜索要突出显示的内容,我发现它有点烦人...

所以我只是想问一下这个问题的可能解决方案......避免突出显示整个richtextbox,比如扫描下一个要突出显示的内容。

非常感谢您的帮助!更多力量!

1 个答案:

答案 0 :(得分:0)

我在你最近的一个问题中回答了这个问题,但是如果其他人正在阅读这个并且找不到它,我会在这里发布(因为这是关于性能的):

您可以使用一些方法来提高性能:

1)您可以通过从当前选择中获取文本范围来获取用户正在编辑的行。我建议使用WPF的richtextbox,因为它包含更多功能,并且具有有用的TextPointer类,您可以使用它来获取当前行。看起来你正在使用WinForms,所以这可以用这几行代码完成(添加一些简单的代码):

int start_index = RTB.GetFirstCharIndexOfCurrentLine();
int line = RTB.GetLineFromCharIndex(index);
int last_index = RTB.GetFirstCharIndexFromLine(line+1);
RTB.Select(start_index, last_index);

然后,您可以使用当前选择。

2)如果您不希望频繁更新,可以创建一个计时器来测量自上次编辑以来的延迟,如果在计时器结束之前进行了另一次编辑,则重置计时器。