3

RichTextBox在我的代码中使用 a 来显示语法突出显示的代码。现在,在每次击键时,我都必须重新解析所有标记并重新为它们重新着色。但是为 a 中的单个单词着色的唯一方法是逐个WinForm richtextbox选择这些单词并使用 SelectionFont 为它们着色。

但是,如果用户的输入速度非常快,那么我选择单个单词会导致非常明显的闪烁(所选单词具有 Windows 蓝色背景的东西,这会导致闪烁)。有什么办法可以让我在不选择它们的情况下为单个单词着色(从而导致所选文本周围出现蓝色突出显示)。我尝试SuspendLayout()在着色期间使用禁用渲染,但这没有帮助。提前致谢!

这是我的代码:

代码:

private void editBox_TextChanged(object sender, EventArgs e) {
  syntaxHighlightFromRegex(); 
}

private void syntaxHighlightFromRegex() {      
  this.editBox.SuspendLayout();

  string REG_EX_KEYWORDS = @"\bSELECT\b|\bFROM\b|\bWHERE\b|\bCONTAINS\b|\bIN\b|\bIS\b|\bLIKE\b|\bNONE\b|\bNOT\b|\bNULL\b|\bOR\b"; 
  matchRExpression(this.editBox, REG_EX_KEYWORDS, KeywordsSyntaxHighlightFont, KeywordSyntaxHighlightFontColor);
}

private void matchRExpression(RichTextBox textBox, string regexpression, Font font, Color color) {
  System.Text.RegularExpressions.MatchCollection matches = Regex.Matches(this.editBox.Text, regexpression, RegexOptions.IgnoreCase);
  foreach (Match match in matches) {
     textBox.Select(match.Index, match.Length); 
     textBox.SelectionColor = color;
     textBox.SelectionFont = font;
  }
}

MyRichTextBox 内部(源自 RichTextBox):

public void BeginUpdate() {
  SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
}
public void EndUpdate() {
  SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int WM_SETREDRAW = 0x0b;
4

2 回答 2

1

尽管看起来您合并了 Hans 的语法高亮文本框,但看起来您并没有使用它。

突出显示这些单词时,您需要在突出显示之前记住光标所在的位置和长度,因为在您的代码中,您正在移动光标而不是放回光标。

如果没有错误检查,请尝试将您的代码更改为:

void editBox_TextChanged(object sender, EventArgs e) {
  this.editBox.BeginUpdate();
  int lastIndex = editBox.SelectionStart;
  int lastLength = editBox.SelectionLength;
  syntaxHighlightFromRegex();
  editBox.Select(lastIndex, lastLength);
  this.editBox.SelectionColor = Color.Black;
  this.editBox.EndUpdate();
  this.editBox.Invalidate();
}
于 2012-08-28T17:29:05.457 回答
0

糟糕,原来我错误地使用了汉斯代码。我应该调用 BeginUpdate() 来停止绘制控件并调用 EndUpdate() 来重新开始绘制它。我反其道而行之。

感谢大家(尤其是汉斯)的所有帮助!

于 2012-08-28T17:36:22.533 回答