Click here to Skip to main content
15,888,341 members
Articles / Programming Languages / Visual Basic
Article

Real Time SynTax Colorizing

Rate me:
Please Sign up or sign in to vote.
3.22/5 (21 votes)
25 Apr 20042 min read 94.8K   629   39   22
Aaron shows how to use the RichTextbox for Real Time Syntax Coloring painlessly.

Sample Image - syntaxcolorizing.jpg

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:

  1. Find the number of visible lines.
  2. 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:

VB
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' 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.

VB
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here



Comments and Discussions

 
QuestionHelp | if have 2 syntax not highlight Pin
Eki Indradi24-Dec-15 19:09
Eki Indradi24-Dec-15 19:09 
QuestionTHANKS !!! Pin
Eki Indradi22-Dec-15 0:14
Eki Indradi22-Dec-15 0:14 
GeneralMy vote of 2 Pin
Dave Kreskowiak29-Jul-09 3:47
mveDave Kreskowiak29-Jul-09 3:47 
GeneralMake a class! Pin
zauberfee13-Oct-08 4:27
zauberfee13-Oct-08 4:27 
QuestionBackground highlight line if it starts with "fox" Pin
UltraWhack16-Jun-08 4:45
UltraWhack16-Jun-08 4:45 
GeneralWeird problems Pin
The Mighty Atom14-Jan-08 3:10
The Mighty Atom14-Jan-08 3:10 
Hi Aaron!

Awesome code! Im using this in my application which is a front end compiler. This compiler creates a log file, and i want to use your code do colorize error messages in that logfile.

But anyway, something strange is happening, check it out:

http://www.themightyatom.nl/screenshots/screenshot_colored_text.png

As you can see, something is wrong:

The word "hlcsg is colored yellow, which is working fine. But there's another instance of this word (Current hlcsg settings) in the log which is not colored yellow! Why?"

Also note that the word "estimate" is colored purple, but i haven't added this word to the Keywords on the left! What the.

The words "max texture memory" (below the purple estimate) is not colored at all.

The word "zhlt.wad" is colored red, but the word "wadinclude" is partially colored red, only the first character and the last character of that word is left white (which is the default color) and it not even in the Keywords! Below the second zhlt.wad is another instance of zhlt.wad, but this one is left white, while it should be colored red as well.

The words "discarded from clipping hulls" is colored greenyellow, only the last character of the word "hulls" is left white.

This is really weird, and i can't figure it out.

I guess this has something to do with text encoding, since the log text is actually being read from a .log file on my hard drive.
When i empty the RichtTextBox and start to type in words manually, it works fine.

If you know why this is happening and how to fix this, please tell me how, i would really appreciate it and ill give you credits in my app when i release it. Smile | :)

- Atom

http://www.themightyatom.nl

GeneralRe: Weird problems Pin
The Mighty Atom19-Jan-08 8:36
The Mighty Atom19-Jan-08 8:36 
GeneralNice code Pin
IDstrife15-Oct-06 5:07
IDstrife15-Oct-06 5:07 
GeneralFirstVisibleLine() Pin
Silberztein28-Oct-05 1:53
Silberztein28-Oct-05 1:53 
GeneralExtremely Poor Performance Pin
andrew|21-Mar-05 19:30
andrew|21-Mar-05 19:30 
GeneralMake it a module Pin
nanbil24-Sep-04 5:04
nanbil24-Sep-04 5:04 
GeneralRe: Make it a module Pin
Aaron Eldreth6-Oct-04 2:24
Aaron Eldreth6-Oct-04 2:24 
GeneralInteresting... a little bug though Pin
Ryan Binns14-Sep-04 18:13
Ryan Binns14-Sep-04 18:13 
GeneralRe: Interesting... a little bug though Pin
Aaron Eldreth15-Sep-04 10:51
Aaron Eldreth15-Sep-04 10:51 
GeneralRe: Interesting... a little bug though Pin
nanbil24-Sep-04 5:12
nanbil24-Sep-04 5:12 
GeneralSuggestions for a successful colorizer Pin
caractacus29-Apr-04 1:45
caractacus29-Apr-04 1:45 
GeneralRe: Suggestions for a successful colorizer Pin
Aaron Eldreth29-Apr-04 9:39
Aaron Eldreth29-Apr-04 9:39 
GeneralThis sounds interesting; any references? Pin
Rolf Schaeuble5-May-04 0:28
Rolf Schaeuble5-May-04 0:28 
GeneralRe: This sounds interesting; any references? Pin
caractacus5-May-04 3:14
caractacus5-May-04 3:14 
GeneralRe: This sounds interesting; any references? Pin
Rolf Schaeuble5-May-04 10:07
Rolf Schaeuble5-May-04 10:07 
GeneralFiles Problem Pin
Dejan Petrovic27-Apr-04 14:20
Dejan Petrovic27-Apr-04 14:20 
GeneralRe: Files Problem Pin
Aaron Eldreth27-Apr-04 16:07
Aaron Eldreth27-Apr-04 16:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.