Microsoft Most Valuable Professional

Chris Pietschmann

An MVP From Wisconsin



VB.NET: RegEx Syntax Highlighting RichTextBox

RegEx Syntax HighlighterHere is a version of my code for syntax highlighting in a RichTextBox that incorporates regular expressions.

 

Download RegEx Syntax Highlighting RichTextBox Source Code

Source Code Listed:

Public Class SyntaxRTB

Inherits System.Windows.Forms.RichTextBox

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _

(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _

ByVal lParam As Integer) As Integer

Private Declare Function LockWindowUpdate Lib "user32" _

(ByVal hWnd As Integer) As Integer

Private _SyntaxHighlight_CaseSensitive As Boolean = False

Friend Words As New DataTable

'Contains Windows Messages for the SendMessage API call

Private Enum EditMessages

LineIndex = 187

LineFromChar = 201

GetFirstVisibleLine = 206

CharFromPos = 215

PosFromChar = 1062

End Enum

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)

MyBase.OnTextChanged(e)

ColorVisibleLines()

End Sub

Public Sub New()

Me.AcceptsTab = True

AddSQLSyntax()

End Sub

Function AddSQLSyntax()

ClearSyntaxWords()

AddSyntaxWord("\b(select|text|ntext|date|datetime|order by|" & _

"group by|smalldatetime|cursor|on|as|for|filename|" & _

"database|drop|function|delete|insert|update|int|" & _

"varchar|nvarchar|bit|binary|table|inner|where|from|" & _

"out|procedure|view|trigger|set)\b", Color.Blue)

AddSyntaxWord("\b@@identity\b", Color.Pink)

AddSyntaxWord("\b(in|join|outer|and|or)\b", Color.Gray)

AddSyntaxWord("\bsp_refreshview\b", Color.Red)

Return True

End Function

Public Function ClearSyntaxWords()

Words = New DataTable

''Load all the keywords and the colors to make them

Words.Columns.Add("Word")

Words.PrimaryKey = New DataColumn() {Words.Columns(0)}

Words.Columns.Add("Color")

Return True

End Function

Public Function AddSyntaxWord(ByVal strWord As String, ByVal clrColor As Color)

Dim MyRow As DataRow

MyRow = Words.NewRow()

MyRow("Word") = strWord

MyRow("Color") = clrColor.Name

Words.Rows.Add(MyRow)

Return True

End Function

Public Sub ColorRtb()

Dim FirstVisibleChar As Integer

Dim i As Integer = 0

While i < Me.Lines.Length

FirstVisibleChar = GetCharFromLineIndex(i)

ColorLineNumber(i, FirstVisibleChar)

i += 1

End While

End Sub

Public Sub ColorVisibleLines()

Dim FirstLine As Integer = FirstVisibleLine()

Dim LastLine As Integer = LastVisibleLine()

Dim FirstVisibleChar As Integer

If (FirstLine = 0) And (LastLine = 0) Then

'If there is no text it will error, so exit the sub

Exit Sub

Else

While FirstLine < LastLine

FirstVisibleChar = GetCharFromLineIndex(FirstLine)

ColorLineNumber(FirstLine, FirstVisibleChar)

FirstLine += 1

End While

End If

End Sub

Public Sub ColorLineNumber(ByVal LineIndex As Integer, ByVal lStart As Integer)

Dim i As Integer = 0

Dim SelectionAt As Integer = Me.SelectionStart

Dim MyRow As DataRow

Dim MyI As Integer

' Lock the update

LockWindowUpdate(Me.Handle.ToInt32)

MyI = lStart

''Turn the whole link black before applying RegEx Syntax matching.

Me.SelectionStart = MyI

Me.SelectionLength = Lines(LineIndex).Length

Me.SelectionColor = Color.Black

''Check for matches in a particular line number

Dim rm As System.Text.RegularExpressions.MatchCollection

Dim m As System.Text.RegularExpressions.Match

For Each MyRow In Words.Rows

'"( |^)1.*2( |$)"

rm = System.Text.RegularExpressions.Regex.Matches(Me.Text, MyRow("Word"))

For Each m In rm

Me.SelectionStart = m.Index

Me.SelectionLength = m.Length

Me.SelectionColor = Color.FromName(MyRow("color"))

Next

Next

' Restore the selectionstart

Me.SelectionStart = SelectionAt

Me.SelectionLength = 0

Me.SelectionColor = Color.Black

' Unlock the update

LockWindowUpdate(0)

End Sub

Public Function GetCharFromLineIndex(ByVal LineIndex As Integer) As Integer

Return SendMessage(Me.Handle, EditMessages.LineIndex, LineIndex, 0)

End Function

Public Function FirstVisibleLine() As Integer

Return SendMessage(Me.Handle, EditMessages.GetFirstVisibleLine, 0, 0)

End Function

Public Function LastVisibleLine() As Integer

Dim LastLine As Integer = FirstVisibleLine() + (Me.Height / Me.Font.Height)

If LastLine > Me.Lines.Length Or LastLine = 0 Then

LastLine = Me.Lines.Length

End If

Return LastLine

End Function

Public Property CaseSensitive() As Boolean

Get

Return _SyntaxHighlight_CaseSensitive

End Get

Set(ByVal Value As Boolean)

_SyntaxHighlight_CaseSensitive = Value

End Set

End Property

End Class

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Monday, July 03, 2006 5:08 PM
Permalink | Comments (8) | Post RSSRSS comment feed

Related posts

Comments

Matanel Sindilevich

Sunday, July 23, 2006 4:13 PM

Matanel Sindilevich

Hi! I would like to know why you add '\b' to the start and end of every Syntax Word, used then as a pattern for Regular Expression Matches? I don't know how it goes in VB.NET, but C# won't work well with "\\b@@identity\\b" (C# equialence of VB.NET "\b@@identity\b") Syntax Word. Means, C# won't find any match unless you specify just "@@identity", without '\\b'. If so. why do you need to add '\b' at all? Thank you in advance for your reply.

Chris Pietschmann

Wednesday, July 26, 2006 2:07 AM

Chris Pietschmann

I am by no means an expert with RegEx. At the moment I don’t remember my reasoning for doing what I did, but do know for a simple example it just works. If you have a better suggestion, feel free to post it.

TC Conway

Sunday, August 20, 2006 1:08 PM

TC Conway

This looks like great code, but have a sec to help a Noob out? Ok. So you just paste this into Form1.vb, after the "Public Class Form1" class? Any guidance on adding this to an existing project would be extremely helpful!

nilam

Monday, September 25, 2006 10:23 AM

nilam

code is nice but not flicker free
how to make it flicker free

tom

Friday, December 08, 2006 3:25 AM

tom

Nice one, but in c# vs2005 something goes wrong with calculating public int FirstVisibleLine()
{
return SendMessageA(this.Handle, (int) RichTextMessages.GetFirstVisibleLine, 0, 0);
}

public int LastVisibleLine()
{
int LastVisibleLine = FirstVisibleLine() + (this.Height / this.Font.Height);
if (LastVisibleLine > this.Lines.Length || LastVisibleLine == 0)
LastVisibleLine = FirstVisibleLine();
return LastVisibleLine;
}

after inserting one, very long line

Larry

Friday, December 08, 2006 10:06 PM

Larry

The \b tell the regular expression engine that the entire word must be found in order to match.

example: With expression \bWordToFind\b

this would match
here is a WordToFind in a string

this would not match
here is aWordToFind in a string

Boirss

Monday, February 12, 2007 9:47 PM

Boirss

Very nice code. Especially like the API call.
However, the performance of the text box becomes extremely slow as the line numbers and line lenghts grow.

Randy

Friday, April 13, 2007 1:48 PM

Randy

Thank you so much, works great for my application.

Comments are closed

About the author

I'm Chris Pietschmann, go to the About Me page to learn more about me.

Search

Sponsors

Web.Maps.VE - ASP.NET AJAX Virtual Earth Mapping Server Control

Recent comments

Disclaimer


This work is licensed under a Creative Commons Attribution 3.0 United States License, unless explicitly stated otherwise within the posted content.
© Copyright 2004 - 2008 Chris Pietschmann