简体   繁体   English

C#:在不选择文本的情况下更改WinForm RichTextBox的字体样式

[英]C#: Changing font style of WinForm RichTextBox without selecting the text

I am using a RichTextBox in my code where I show syntax-highlighted code. 我在我的代码中使用RichTextBox ,其中显示了语法突出显示的代码。 Now, on every keystroke, I have to re-parse all the tokens and re-color them all over again. 现在,在每次按键时,我必须重新解析所有令牌并重新对它们进行重新着色。 But the only way to color individual words in a WinForm richtextbox is to select those words one by one and color them using SelectionFont. 但是,在WinForm richtextbox为单个单词着色的唯一方法是逐个选择这些单词并使用SelectionFont对它们进行着色。

But if the user is typing really fast, there is a very noticeable flickering caused by my selecting individual words (selected words have that Windows blue-background thing and that is causing the flickering). 但是如果用户输入速度非常快,那么我选择单个单词会导致非常明显的闪烁(所选单词具有Windows蓝色背景并导致闪烁)。 Is there any way around that where I can color individual words without selecting them (and hence causing that blue highlight around the selected text). 有什么方法我可以在不选择它们的情况下为单个单词着色(从而在所选文本周围产生蓝色高光)。 I tried using SuspendLayout() to disable rendering during my coloring but that didn't help. 我尝试使用SuspendLayout()在着色期间禁用渲染,但这没有帮助。 Thanks in advance! 提前致谢!

Here is my code: 这是我的代码:

Code: 码:

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

Inside the MyRichTextBox (dervied from RichTextBox): 在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;

Even though it looks like you incorporated Hans' syntax highlighting text box, it doesn't look like you are using it. 即使你看起来像汉斯的语法高亮文本框,它看起来并不像你正在使用它。

When highlighting those words, you need to remember the position and length of where your cursor is before you do the highlighting, because in your code, you are moving the cursor around and not putting it back. 在突出显示这些单词时,您需要记住光标在进行突出显示之前的位置和长度,因为在代码中,您正在移动光标而不是将其放回原位。

Without error checking, try changing your code to this: 如果没有错误检查,请尝试将代码更改为:

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

Oops turns out I was using Hans code incorrectly. 哎呀结果我错误地使用了Hans代码。 I was supposed to call BeginUpdate() to stop drawing control and EndUpdate() to start drawing it again. 我应该调用BeginUpdate()来停止绘制控件,并调用EndUpdate()来再次开始绘制它。 I was doing it the other way around. 我反过来这样做。

Thanks for all the help, everyone (especially Hans)! 感谢所有的帮助,每个人(特别是汉斯)!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM