Real Time SynTax Colorizing






3.22/5 (21 votes)
Apr 26, 2004
2 min read

95891

630
Aaron shows how to use the RichTextbox for Real Time Syntax Coloring painlessly.
Introduction
There seems to be three ways to do real time syntax coloring. Good, fast, and flicker-free. Pick any two. Matthew Hazlett did an article that covers "good and flicker-free", so I thought some people might find it useful to have simply "good and fast".
Background
Back in January, I worked on HTML syntax coloring. I was amazed by the lack of information on the subject in VB.NET. There was some in VB, but naturally, it didn't upgrade too well (nothing is ever easy). So, I had to make my own. Isn't that how things typically are? I've learned a lot from CodeProject, and would like to give back.
Using the code
The code is pretty much self-explanatory, but the idea behind it works something like this:
- Find the number of visible lines.
- For each visible line, color it.
Simple enough, eh?
Now, on to the actual code, the first subroutine that finds the number of visible lines is called ColorVisibleLines
and it looks something like this:
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Sub: ColorVisibleLines()
' It does what?: Colors the visible lines in the RichTextbox
' Notes: N/A
Public Sub ColorVisibleLines(ByVal rtb As RichTextBox)
Dim FirstLine As Integer = FirstVisibleLine()
Dim LastLine As Integer = LastVisibleLine()
Dim FirstVisibleChar As Integer
Dim i As Integer = FirstLine
If (FirstLine = 0) And (LastLine = 0) Then
' If there is no text in the control, it will run an error
' So, if there isn't any text, just exit
Exit Sub
Else
While i < LastLine
FirstVisibleChar = GetCharFromLineIndex(FirstLine)
ColorLineNumber(rtb, FirstLine, FirstVisibleChar)
FirstLine += 1
i += 1
End While
End If
End Sub
As you will notice, this sub calls another sub to do all the actual coloring for us.
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Sub: ColorLineNumber()
' It does what?: Colors a single line in the control
' Notes: This should be fairly simple, it looks to see
' if there are any comments, colors them. Then, it loops
' through the keywords defined, and colors them
Public Sub ColorLineNumber(ByVal rtb As RichTextBox, _
ByVal LineIndex As Integer, ByVal lStart As Integer)
Dim Line As String = rtb.Lines(LineIndex).ToLower
Dim i As Integer = 0
Dim Instance As Integer
Dim SelectionAt As Integer = rtb.SelectionStart
' Lock the update
LockWindowUpdate(rtb.Handle.ToInt32)
' Color the line black to remove any previous coloring
rtb.SelectionStart = lStart
rtb.SelectionLength = Line.Length
rtb.SelectionColor = Color.Black
' Find any comments
Instance = InStr(Line, "'")
' If there are comments, color them
If Instance <> 0 Then
rtb.SelectionStart = (lStart + Instance - 1)
rtb.SelectionLength = (Line.Length - Instance + 1)
rtb.SelectionColor = Color.Green
End If
' There was a comment, so to aviod coloring over the comment
' we exit. Unfortunately, this can present a problem 'cuz
' what if the user comments at the end of a line with code on it.
If Instance = 1 Then
' Unlock the update, restore the start and exit
rtb.SelectionStart = SelectionAt
rtb.SelectionLength = 0
LockWindowUpdate(0)
Exit Sub
End If
' Loop through all the Keywords
While i < Words.Length
' See if the word is in the Line
Instance = InStr(Line, Words(i).Word)
' If the lines contains the word, color it
If Instance <> 0 Then
rtb.SelectionStart = (lStart + Instance - 1)
rtb.SelectionLength = Words(i).Word.Length
rtb.SelectionColor = Words(i).Color
End If
i += 1
End While
' Restore the selectionstart
rtb.SelectionStart = SelectionAt
rtb.SelectionLength = 0
' Unlock the update
LockWindowUpdate(0)
End Sub
The keywords to be colored are stored in a structure called KeyWords
which holds the string to color, and the color to color the string.
Closing
All in all, it's not the most efficient way to color things. For example, you may have noticed that the Instr
function is used to locate the keywords. Regular Expressions (or RegEx) could be used in lieu of the method currently implemented.
Another downside to this method is flicker. This is a very difficult issue to overcome. Even with the LockWindowUpdate
API function, it still flickers (go figure). I am currently attempting to make a non-inherited RichTextBox
that will be a clone of Visual Studio's editor. However, it's still a long distance from completion. The control will be free and I'll post it on CodeProject, and it will contain a lot of features such as line numbering, breakpoints, brace-matching, expanding-collapsing regions, and best of all good, fast, and flicker-free real time syntax coloring.