Introduction
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).
Background
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
Seperators
property.
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
.
A HighlightDescriptor
is an instance of a class describing a highlighting rule, which can be divided into token identification info and design info.
Highlighting Rules
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>.
The HighlightDescriptor
is as follows:
public class HighlightDescriptor
{
public HighlightDescriptor(string token,
string closeToken, Color color, Font font,
DescriptorType descriptorType, DescriptorRecognition dr,
bool useForAutoComplete)
{
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
and 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);
return res;
}
private unsafe void SetScrollPos(Win32.POINT point)
{
IntPtr ptr = new IntPtr(&point);
Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);
}
#endregion
- 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.
History
- 05/29/2005: First release.
- 04/06/2005: Fixed a few bugs when using the
ToCloseToken
DescriptorType.
- 07/13/2005: Fixed a few bugs, added Undo/Redo functionality.