Hey. This code is a class derived from .Net's
RichTextBox. It offers syntax highlighting and auto-completion features (like Intellisense, only a little dumber).
Have you ever written an application that had its own script language? Ever needed to edit SQL/code in you application? Didn't you just want a control that was a little better than a
TextBox with a fixed width font? Now you can have it :-)
This control was written when I needed to edit SQLs in an application I wrote. Then I thought:
"Even if I could find a control that knows to edit SQLs well, it still wouldn't highlight names of tables or stored procedures that I wrote. And I know I'll need a control that can highlight my own script language sometime..."
So I sat down and wrote it. Later I realized that syntax highlighting without an auto-completion is not worth much, so I added support for that too.
Using the code
First of all, I must apologise. I'm not much of a GUI programmer, so all of the manipulation is done using code, as I lack the knowledge to write custom editors for a
PropertyGrid. With that out of the way, we may continue! The control has two inputs for highlighting:
- Separators: Accessed using the
Each separator is a
char, and what is later refferd to as "token" is a not-empty string between separators.
- Highlight Descriptor: You can use the (how surprising)
HighlightDescriptor method to add a
HighlightDescriptor is an instance of a class describing a highlighting rule, which can be divided into token identification info and design info.
A highlighting rule has 6 fields it's constructed with:
- Token: A string that is later compared to the text.
- DescriptorType: Sets the highlighting type. The options are in a single word, to the end of the line, and to the corresponding closing token.
- DescriptorRecognition: Determines how the token is compared to the token from the text. The options are: the text is equal to the token, the text begins with the token, and the text contains the token.
- Color: Sets the color of the token when highlighted.
- Font: Sets the font on the token when highlighted. This field is optional.
- UseForAutoComplete: Determines if the token will be used for auto completion.
Due to laziness, a
HighlightDescriptor's values can only be set in the constructor. <SideNote> I really think that the
readonly keyword is under appreciated.</SideNote>.
HighlightDescriptor is as follows:
public class HighlightDescriptor
public HighlightDescriptor(string token,
string closeToken, Color color, Font font,
DescriptorType descriptorType, DescriptorRecognition dr,
Color = color;
Font = font;
Token = token;
DescriptorType = descriptorType;
CloseToken = closeToken;
DescriptorRecognition = dr;
UseForAutoComplete = useForAutoComplete;
public readonly Color Color;
public readonly Font Font;
public readonly string Token;
public readonly string CloseToken;
public readonly DescriptorType DescriptorType;
public readonly DescriptorRecognition DescriptorRecognition;
public readonly bool UseForAutoComplete;
Points of Interest
There were a few interesting things during the writing:
- Scrollbars: Since every time the text changes, I actually change it again (as far as the base textbox knows), the scrollbars reset themselves to top and left most positions. To resolve this, I used the
EM_GETSCROLLPOS Windows messages:
#region Scrollbar positions functions
private unsafe Win32.POINT GetScrollPos()
Win32.POINT res = new Win32.POINT();
IntPtr ptr = new IntPtr(&res);
Win32.SendMessage(Handle, Win32.EM_GETSCROLLPOS, 0, ptr);
private unsafe void SetScrollPos(Win32.POINT point)
IntPtr ptr = new IntPtr(&point);
Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);
- Keyboard strokes: During my work on the auto complete feature, I found out that even if you override the
OnKeyDown method and not call the base method, keystrokes of keys containing actual characters are still handled (they arrive using the
WM_CHAR message). Due to that I decided to override the
WndProc method and filter unwanted keystrokes at that level.
- RTF: I didn't really learn RTF for this project. I just took a regular
RichTextBox and understood what I have to build for my needs. Hence my resulting RTF is probably not optimal. It probably has language limitations that can be solved fairly easily by manipulating the RTF header.
- 05/29/2005: First release.
- 04/06/2005: Fixed a few bugs when using the
- 07/13/2005: Fixed a few bugs, added Undo/Redo functionality.