Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

(Improved) Fast syntax highlighting control!

0.00/5 (No votes)
1 Feb 2013 3  
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

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:

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:

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;

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 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