Click here to Skip to main content
15,879,535 members
Articles / Programming Languages / C#

(Improved) Fast syntax highlighting control!

Rate me:
Please Sign up or sign in to vote.
3.92/5 (5 votes)
1 Feb 2013CPOL3 min read 23K   21   12
Syntax highlighting has never been so easy!

Testing the syntax highlighting!

Introduction 

Hello CodeProject! I am back once again. This time I have removed my other article, it was my first article so besides it being a really complicated and long one, I now have finally improved the code. No more bugs as far as I can see, the speed of the control has now increased roughly by 35-45%. If you have never seen my previous article, well, basically this is my very own Syntax Highlighting control. It's derived from RichTextBox, and I suppose you all have seen the results of many people who made these ones. Well, no worries, I have made sure this one actually fulfills any needs or desires (isn't it the same? :P).

The code

This code that I will give you has been completely made by me. The idea's however have been inspired by many Notepad's (Notepad++, Visual Studio's IDE). This is a basic piece of code, and anyone who has the ability to understand this simple code should be able to do as he/she wants easily. If you use this control, make sure to make something good out off it, I don't need any (Credits?), as this has purely been made for learning purposes by me.

How do you use the code?

  1. Create a new Project or use an existing one.
  2. Add a new class by going to your Solution Explorer, Add, New Item, Class.
  3. Replace the class code with the following.
  4. Build or debug the application. 
  5. (Drag)(Create) (in) the TextBox (or make one) (in) via (code) (the ToolBox).
  6. Profit!

The code

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Threading;

namespace Classik
{
    public class AdvancedRichTextBox : RichTextBox
    {

        #region API Stuff
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetScrollPos(IntPtr hWnd, int nBar);

        [DllImport("user32.dll")]
        public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

        [DllImport("user32.dll")]
        public static extern bool LockWindowUpdate(IntPtr hWnd);

        private const int SB_HORZ = 0x0;
        private const int SB_VERT = 0x1;
        #endregion
        public int HorizontalPosition
        {
            get { return GetScrollPos((IntPtr)this.Handle, SB_HORZ); }
            set { SetScrollPos((IntPtr)this.Handle, SB_HORZ, value, true); }
        }
        public int VerticalPosition
        {
            get { return GetScrollPos((IntPtr)this.Handle, SB_VERT); }
            set { SetScrollPos((IntPtr)this.Handle, SB_VERT, value, true); }
        }

        public AdvancedRichTextBox()
        {
            this.ForeColor = Color.Black;
        }

        int PreviousLength = 0;
        protected override void OnTextChanged(EventArgs e)
        {
            if (PreviousLength == this.Text.Length - 1 || PreviousLength == this.Text.Length + 1)
                SyntaxView(new Regex("( for | while )"));
            else
                SyntaxAll(new Regex("( for | while )"));

            PreviousLength = this.Text.Length;

            base.OnTextChanged(e);
        }

        public void SyntaxView(Regex Syntax)
        {
            int SelectionStart = this.SelectionStart;
            int SelectionLength = this.SelectionLength;

            int FirstCharacter = this.GetCharIndexFromPosition(new Point(0, 0));
            int FirstLine = this.GetLineFromCharIndex(FirstCharacter);

             int LastLine = this.GetLineFromCharIndex(this.GetCharIndexFromPosition(
                 new Point(this.ClientSize.Width, this.ClientSize.Height))) ;

            Color SelectionColor = this.ForeColor;
            Font SelectionFont = this.Font;

            for (int i = FirstLine; i <= LastLine; i++)
            {
                MatchCollection Matches = Syntax.Matches(this.Lines[i]);

                if (Matches.Count > 0)
                {
                    LockWindowUpdate(this.Handle);

                    foreach (Match m in Matches)
                    {
                        int Start = this.GetFirstCharIndexFromLine(i);
                        this.Select(Start + m.Index, m.Length);
                        this.SelectionColor = Color.Red;
                    }
                }
            }

            this.SelectionStart = SelectionStart;
            this.SelectionLength = SelectionLength;
            this.SelectionColor = SelectionColor;
            this.SelectionFont = SelectionFont;

            LockWindowUpdate(IntPtr.Zero);

            this.Invalidate();

        }
        public void SyntaxAll(Regex Syntax)
        {
            int SelectionStart = this.SelectionStart;
            int SelectionLength = this.SelectionLength;

            Color SelectionColor = this.ForeColor;
            Font SelectionFont = this.Font;

            LockWindowUpdate(this.Handle);

            for (int i = 0; i < this.Lines.Length; i++)
            {
                MatchCollection Matches = Syntax.Matches(this.Lines[i]);

                if (Matches.Count > 0)
                {
                    LockWindowUpdate(this.Handle);

                    foreach (Match m in Matches)
                    {
                        int Start = this.GetFirstCharIndexFromLine(i);
                        this.Select(Start + m.Index, m.Length);
                        this.SelectionColor = Color.Red;
                    }
                }
            }

            this.SelectionFont = SelectionFont;
            this.SelectionColor = SelectionColor;
            this.SelectionStart = SelectionStart;
            this.SelectionLength = SelectionLength;

            LockWindowUpdate(IntPtr.Zero);

            this.Invalidate();
        }
    }
}

Using the code

Now, how would we go about using this highlighting tool. Well, I have made some simple steps "The Code" box,  it will explain how to add the code and use it. But! There are some other things mainly, how would you go about adding more highlights! Well, it's easy. We have two voids, SyntaxView and SyntaxAll. They both need to be changed in order to make it work. The only bits you have to concentrate on is:

C#
LockWindowUpdate(this.Handle);

foreach (Match m in Matches)
{
    int Start = this.GetFirstCharIndexFromLine(i);
    this.Select(Start + m.Index, m.Length);
    this.SelectionColor = Color.Red;
}

and:

C#
SyntaxView(new Regex("( for | while )"));
else
    SyntaxAll(new Regex("( for | while )"));

The smallest one will hopefully explain itself. If it does not, basically, every single word you would like to be highlighted needs to be in the new Regex, split by '|'. The above code is in both of the voids. And it can be used to change the color of highlighting. You can also change the font using 'this.SelectionFont'. There is another things that you might wonder: "How would I add more Colors instead of only one", well this is easy. All you have to do is add a little Switch or if statement to both of the foreach loops like so;

C#
Color HighlightColor = Color.Blue;
switch (m.ToString())
{
    case "one":
       HighlightColor = Color.Blue;
       break;

    case "two":
       HighlightColor = Color.Orange;
       break;

    case "three":
       HighlightColor = Color.Purple;
       break;
}
this.SelectionColor = HighlightColor ;

There are of course a lot of other ways of doing it. This is just a simple example. But make sure to change both the view and all.

Points of Interest

I think the most interesting part of this article is that it's simple to use, and easy for everyone to understand.

Additional Notes

There are a few external API voids, some of them should explain themselves, one does not:

  • LockWindowUpdate: This makes the window frozen until unfrozen with 'IntPtr.Zero'. You use handles for that one.

I am sorry if anyone had troubles reading this, English is not my first language so I hope the article has been interesting and especially understandable.

History 

  • Fixed every bug known in older versions. 
  • 1/2/2013: Fixed 'Highlighting for in foreach' bug. Cheers wvd_vegt.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Netherlands Netherlands
Yvar Birx;

I am fifteen years old and studied coding for about three years. I mostly code in C#, but I also have coded in Java and Visual Basic.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Jan Zumwalt11-Apr-16 16:39
Jan Zumwalt11-Apr-16 16:39 
QuestionLooks Good & Next Steps Pin
Dave Kerr28-Nov-13 21:10
mentorDave Kerr28-Nov-13 21:10 
AnswerRe: Looks Good & Next Steps Pin
It's Eddie!6-May-16 4:33
It's Eddie!6-May-16 4:33 
QuestionWhere is the download For project? Pin
Elegiac20-May-13 18:20
Elegiac20-May-13 18:20 
GeneralMy vote of 4 Pin
wvd_vegt1-Feb-13 4:47
professionalwvd_vegt1-Feb-13 4:47 
GeneralRe: My vote of 4 Pin
wvd_vegt1-Feb-13 4:53
professionalwvd_vegt1-Feb-13 4:53 
GeneralRe: My vote of 4 Pin
Yvar Birx1-Feb-13 5:37
Yvar Birx1-Feb-13 5:37 
GeneralRe: My vote of 4 Pin
wvd_vegt1-Feb-13 8:05
professionalwvd_vegt1-Feb-13 8:05 
GeneralRe: My vote of 4 Pin
Yvar Birx2-Feb-13 4:02
Yvar Birx2-Feb-13 4:02 
Dear Wvd_vegt,

I appreciate your feedback! I am not really experienced in Regex so getting to know it via this is very nice. I'll apply your code soon as I am currently doing some projects.

GB

- Riberto.
GeneralBut where's the code? Pin
John Brett31-Jan-13 1:02
John Brett31-Jan-13 1:02 
GeneralRe: But where's the code? Pin
Yvar Birx31-Jan-13 4:41
Yvar Birx31-Jan-13 4:41 
SuggestionRe: But where's the code? Pin
Jan Zumwalt11-Apr-16 5:51
Jan Zumwalt11-Apr-16 5:51 

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.