Introduction
This article shows how to perform interactive syntax highlighting within the RichTextBox control. The source code is written in C#.
This text builds upon the previous article Syntax Highlighting within the RichTextBox Control - Part 1 that described how to highlight text as it is loaded into the RichTextBox.
Description
To perform interactive syntax highlighting within the RichTextBox, the events generated by the control need to be monitored. In this example I monitor the event TextChanged which is triggered each time text is modified within the control. Further to make life easy apply formatting to the entire line that the user is editing. Note, this implementation has some drawbacks in terms of screen flicker. More about that later.
We begin by attaching an event handler to the RichTextBox property TextChanged like so.
- RichTextBox m_rtb = null;
- m_rtb = new RichTextBox();
- ...
- m_rtb.TextChanged += new EventHandler(this.TextChangedEvent)
Note, I have removed the highlighting code for comments to make the example more readable. See the attached file for a more complete example.
- 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 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;
- }
- }
Conclusion
This article described a rudimentary example of how to perform syntax highlighting interactively within the RichTextBox control. A more thorough implementation is left to the reader.
Rahul RautPosted Sep 3, 2012, 8:04 AM
Great Solution! I implemented it. Just one query if I want to use it for shell variable how to do that ${VARIABLE_NAME} The background color should be changed
Guest UserPosted Mar 30, 2011, 4:12 AM
very thanks it's good, waiting for next articles. The world is a rose smell it and pass it to your friends. good work.
chithra rPosted Aug 25, 2010, 12:30 PM
Thanks for your tutorial. It was very helpful. I have a question though , the csysntax highlighting doesn't work when i do a cut copy paste into my richtextbox . What needs to be changed to implement this ? Many Thnaks
pierre charrierPosted Jun 2, 2010, 4:56 PM
Sorry for my English, I'm French... But I found an error : when I write something, it works, but if I delete the line, when there is'nt any character "String line = rtbTexte.Text.Substring(start, end - start);" startIndex is < 0 and there ise an error. We have to manage ArgumentOutOfRangeException, and I don't know how to do it :/
DarineditedPosted Feb 8, 2009, 11:24 PMEdited Feb 8, 2009, 11:55 PM
using System; using System.Windows.Forms; class RichTextBoxExtended : RichTextBox { private const int WM_SETREDRAW = 0xB; [System.Runtime.InteropServices.DllImport("user32.dll")] private extern static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); protected override void OnTextChanged(EventArgs e) { SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero); base.OnTextChanged(e); SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); this.Invalidate(true); } }
DarineditedPosted Feb 8, 2009, 4:27 PMEdited Feb 8, 2009, 11:47 PM
Adding the code below, then placing the FreezeDraw() at the beginning of TextChangedEvent, and UnfreezeDraw() at the end of TextChangedEvent, seems to work wonderfully at eliminating the flicker. #region "Avoid flickering" private const int WM_SETREDRAW = 0xB; [System.Runtime.InteropServices.DllImport("User32")] private static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, int lParam); private void FreezeDraw() { //Disable drawing SendMessage(m_rtb.Handle, WM_SETREDRAW, 0, 0); } private void UnfreezeDraw() { //Enable drawing and do a redraw. SendMessage(m_rtb.Handle, WM_SETREDRAW, 1, 0); m_rtb.Invalidate(true); } #endregion
randyPosted Jan 21, 2008, 6:42 PM
I found that using this method would cause unsightly flicker in the RichTextBox control. This was caused by excessive manipulation of the SelectionStart and SelectionLength properties of the control. I was able to get around this by writing the richtext format to a StringBuilder object and replacing the control's Rtf property with this only once per update. It may prove slower (I didn't perform any benchmark testing), but for the relatively small controls I am using it for it updates without any visible hesitation. Of course, richtext format has some special characters so implementing this must involve handling this. Just my two cents!
Ahmed ElmahdawyPosted Jan 8, 2008, 8:03 AM
???! ?'?? ???? ????? ???? ???????? ???, ????????? ?????? ?# 2005 ??????? ???????. ??? ??????? ??????? ?? ???? ????: ??????? ???? ????????(??? ???????????, ????? ????) ???????();