问题
I am using a RichTextBox
in my code where I show syntax-highlighted code. 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.
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). 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. 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):
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;
回答1:
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();
}
回答2:
Oops turns out I was using Hans code incorrectly. I was supposed to call BeginUpdate() to stop drawing control and EndUpdate() to start drawing it again. I was doing it the other way around.
Thanks for all the help, everyone (especially Hans)!
来源:https://stackoverflow.com/questions/12150634/c-changing-font-style-of-winform-richtextbox-without-selecting-the-text