Click here to Skip to main content
15,881,852 members
Articles / Programming Languages / C#
Article

CodeTextBox - another RichTextBox control with syntax highlightning and intellisense

Rate me:
Please Sign up or sign in to vote.
4.87/5 (34 votes)
8 Sep 2008CPOL2 min read 145.1K   6.4K   147   37
A RichTextBox control with syntax highlightning and intellisense.

Image 1

Introduction

I needed a script-editor control for one of my projects, with syntax highlighting and intellisense for more comfort. I did a search on CodeProject and Google, but didn't find any - just separate solutions for one of the two functions... The one I found with both syntax highlighting and intellisense just wasn't flexible enough for me, because it could be used only for C#, and only could handle classes (intellisense popped up after pressing the . key). As I wanted to use this mostly for LUA, this simply wasn't enough. I decided to use this control as a sample, and write my own, flexible one... After a few days, I came out with this: I have a flexible syntax-highlighter, with intellisense. :) I can edit everything in design mode, for example, the intellisense hotkey, or the scope-operator's list... Yes, I can handle not just the point, but more like ::, or ->, with C++ language support in mind. :)

Using the code

I designed the CodeTextBox control to be easy to work with: you can edit all the necessary properties in design mode as well, under the CodeTextBox category.

CodeTextBox properties

There're some things that I couldn't do automatically, or put in Design mode...

  • If you put text in the CodeTextBox programmatically, you should update syntax highlighting to get the proper results.
  • You can do it like this: codeTextBox1.UpdateSyntaxHightlight();.

  • I used the built-in TreeView control to store intellisense's data. I know it's a waste of resources, but it was a fast solution for now, and I need to give some instructions on how to use it, because there's a lot of things there...
  • To build up the intellisense-tree, you should add items to the intellisense-tree's nodes. I use the node's Name and Tag attributes for intellisense. Name should contain the name of the intellisense item, Tag should contain one of the following: class, event, interface, namespace, method, or property. Intellisense will assign images before the names based on this Tag property.

Limitations, Ideas

I know that it's not perfect yet, but hey, it's useable... :) Let me tell you some ideas to make this better, and also some of its limitations that I haven't been able to solve until now...

Limitations:

As in most syntax highlighters, I cannot handle C-style comment blocks, and keywords like #region.

Ideas:

  • Implementing an XML serializer for the syntax highlighter and the intellisense to enable ease-of-use, and for a more comfortable language support.
  • Implementing some .NET-Reflection support for the intellisense to let it handle .NET based scripting easier.
  • Replacing the TreeView with a tinier container, but keeping the easy design-time edit function that TreeView has.

References

History

  • 2008.09.08 - Version 1.0.

License

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


Written By
Software Developer (Senior) Moonlight Studios
Hungary Hungary
I'm working as a software developer since 2005 mostly using C# and MS SQL Server for building windows and web applications. I have 3 years experience in developing CRM softwares, but I'm also interested in Game development using C++, DirectX, and C#-XNA.
I'm always open for new technologies, preferring code reusability, stability, and "nice solutions".

Comments and Discussions

 
GeneralRe: Remove pinove call to run under moni, imporve speed Pin
The_Mega_ZZTer23-Jun-09 16:05
The_Mega_ZZTer23-Jun-09 16:05 
GeneralRe: Remove pinove call to run under moni, imporve speed Pin
Christo66719-Apr-10 4:46
Christo66719-Apr-10 4:46 
GeneralCannot open with Visual Studio 2005 express Pin
g.bude17-Sep-08 1:02
g.bude17-Sep-08 1:02 
GeneralOr Visual Studio 2005 Pro Pin
eddiem914-Oct-08 17:10
eddiem914-Oct-08 17:10 
GeneralRe: Or Visual Studio 2005 Pro Pin
Tamas Honfi14-Oct-08 22:52
Tamas Honfi14-Oct-08 22:52 
GeneralFlashing on paste Pin
AndrusM16-Sep-08 6:17
AndrusM16-Sep-08 6:17 
GeneralRe: Flashing on paste Pin
Tamas Honfi17-Sep-08 0:32
Tamas Honfi17-Sep-08 0:32 
GeneralRe: Flashing on paste Pin
AndrusM17-Sep-08 1:04
AndrusM17-Sep-08 1:04 
Thank you for reply.
Mini-csarplab earlier version highlighter which I currently use pastes without flashing. It uses secondary invisible RichTextBox as buffer for this. This does not require pinvokes.
Maybe this method can be used.


I tested it in MONO SVN and found that sometimes MONO crashes
with expeption.

Also I found that colors are incorrect in MONO.
It may be worth to create simple code to reproduce those issues and post them to MONO buglist to they can be fixed.

I'm also interested to highlight SQL syntax. How to add this ? Manoli highlighter uses class below to define this. How to use this class or some other SQL syntax definition?

#region Copyright © 2001-2003 Jean-Claude Manoli [jc@manoli.net]
/*
 * Based on code submitted by Mitsugi Ogawa.
 * 
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the author(s) be held liable for any damages arising from
 * the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 
 *   1. The origin of this software must not be misrepresented; you must not
 *      claim that you wrote the original software. If you use this software
 *      in a product, an acknowledgment in the product documentation would be
 *      appreciated but is not required.
 * 
 *   2. Altered source versions must be plainly marked as such, and must not
 *      be misrepresented as being the original software.
 * 
 *   3. This notice may not be removed or altered from any source distribution.
 */ 
#endregion

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace Manoli.Utils.CSharpFormat
{
	/// <summary>
	/// Generates color-coded T-SQL source code.
	/// </summary>
	class TsqlFormat : CodeFormat
	{
		/// <summary>
		/// Regular expression string to match single line 
		/// comments (--). 
		/// </summary>
		protected override string CommentRegEx
		{
			get
			{
				return @"(?:--\s).*?(?=\r|\n)";
			}
		}

		/// <summary>
		/// Regular expression string to match string literals. 
		/// </summary>
		protected override string StringRegEx
		{
			get
			{
				return @"''|'.*?'";
			}
		}

		/// <summary>
		/// Returns <b>false</b>, since T-SQL is not case sensitive.
		/// </summary>
		public override bool CaseSensitive
		{
			get { return false; }
		}


		/// <summary>
		/// The list of T-SQL keywords.
		/// </summary>
		protected override string Keywords
		{
			get
			{
				return "absolute action ada add admin after aggregate "
					+ "alias all allocate alter and any are array as asc "
					+ "assertion at authorization avg backup before begin "
					+ "between binary bit bit_length blob boolean both breadth "
					+ "break browse bulk by call cascade cascaded case cast "
					+ "catalog char char_length character character_length "
					+ "check checkpoint class clob close clustered coalesce "
					+ "collate collation column commit completion compute "
					+ "connect connection constraint constraints constructor "
					+ "contains containstable continue convert corresponding "
					+ "count create cross cube current current_date current_path "
					+ "current_role current_time current_timestamp current_user "
					+ "cursor cycle data database date day dbcc deallocate dec "
					+ "decimal declare default deferrable deferred delete deny "
					+ "depth deref desc describe descriptor destroy destructor "
					+ "deterministic diagnostics dictionary disconnect disk "
					+ "distinct distributed domain double drop dummy dump "
					+ "dynamic each else end end-exec equals errlvl escape "
					+ "every except exception exec execute exists exit external "
					+ "extract false fetch file fillfactor first float for "
					+ "foreign fortran found free freetext freetexttable from "
					+ "full function general get global go goto grant group "
					+ "grouping having holdlock host hour identity identity_insert "
					+ "identitycol if ignore immediate in include index indicator "
					+ "initialize initially inner inout input insensitive insert "
					+ "int integer intersect interval into is isolation iterate "
					+ "join key kill language large last lateral leading left "
					+ "less level like limit lineno load local localtime localtimestamp "
					+ "locator lower map match max min minute modifies modify "
					+ "module month names national natural nchar nclob new next "
					+ "no nocheck nonclustered none not null nullif numeric object "
					+ "octet_length of off offsets old on only open opendatasource "
					+ "openquery openrowset openxml operation option or order "
					+ "ordinality out outer output over overlaps pad parameter "
					+ "parameters partial pascal path percent plan position "
					+ "postfix precision prefix preorder prepare preserve "
					+ "primary print prior privileges proc procedure "
					+ "public raiserror read reads readtext real reconfigure "
					+ "recursive ref references referencing relative replication "
					+ "restore restrict result return returns revoke right role "
					+ "rollback rollup routine row rowcount rowguidcol rows rule "
					+ "save savepoint schema scope scroll search second section "
					+ "select sequence session session_user set sets setuser "
					+ "shutdown size smallint some space specific specifictype "
					+ "sql sqlca sqlcode sqlerror sqlexception sqlstate sqlwarning "
					+ "start state statement static statistics structure substring "
					+ "sum system_user table temporary terminate textsize than then "
					+ "time timestamp timezone_hour timezone_minute to top trailing "
					+ "tran transaction translate translation treat trigger trim "
					+ "true truncate tsequal under union unique unknown unnest "
					+ "update updatetext upper usage use user using value values "
					+ "varchar variable varying view waitfor when whenever where "
					+ "while with without work write writetext year zone";
			}
		}

		/// <summary>
		/// Use the pre-processor color to mark keywords that start with @@.
		/// </summary>
		protected override string Preprocessors
		{
			get 
			{ 
				return @"@@CONNECTIONS @@CPU_BUSY @@CURSOR_ROWS @@DATEFIRST "
					+ "@@DBTS @@ERROR @@FETCH_STATUS @@IDENTITY @@IDLE "
					+ "@@IO_BUSY @@LANGID @@LANGUAGE @@LOCK_TIMEOUT "
					+ "@@MAX_CONNECTIONS @@MAX_PRECISION @@NESTLEVEL @@OPTIONS "
					+ "@@PACK_RECEIVED @@PACK_SENT @@PACKET_ERRORS @@PROCID "
					+ "@@REMSERVER @@ROWCOUNT @@SERVERNAME @@SERVICENAME @@SPID "
					+ "@@TEXTSIZE @@TIMETICKS @@TOTAL_ERRORS @@TOTAL_READ "
					+ "@@TOTAL_WRITE @@TRANCOUNT @@VERSION";
			}
		}
	}
}


Andrus

GeneralRe: Flashing on paste Pin
Tamas Honfi17-Sep-08 1:20
Tamas Honfi17-Sep-08 1:20 
GeneralOther solutions Pin
RednaxelaFX8-Sep-08 1:23
RednaxelaFX8-Sep-08 1:23 
GeneralRe: Other solutions Pin
dave.dolan8-Sep-08 9:14
dave.dolan8-Sep-08 9:14 
GeneralRe: Other solutions Pin
AndrusM15-Sep-08 10:39
AndrusM15-Sep-08 10:39 
GeneralRe: Other solutions Pin
Angelo DeFusco20-Oct-10 16:19
Angelo DeFusco20-Oct-10 16:19 

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.