Example E2993
Visible to All Users

Rich Text Editor for WinForms - Implement ISyntaxHighlightService to Highlight C and VB Code Syntax

The Rich Text Editor supports ISyntaxHighlightService that allows you to implement syntax highlighting for a document displayed in the control. This example demonstrates how to highlight its source code (C# and VB). The project uses the DevExpress CodeParser library to parse the code into tokens according to the syntax elements of the programming language.

Rich Text Editor - Highlight Code Syntax

Implementation Details

  1. Declare a custom class that implements ISyntaxHighlightService. In the class constructor, specify colors for different code element categories (keywords, comments, strings, and so on). This example uses colors of the current application skin.
  2. Implement the ISyntaxHighlightService.Execute method. Within the method, use parsers from the DevExpress CodeParser library to parse C# and VB source code into tokens.
  3. Convert tokens to the SyntaxHighlightToken objects and specify format settings for each token.
  4. Pass the list of SyntaxHighlightToken objects to the SubDocument.ApplySyntaxHighlight method to enable syntax highlighting in the document.
  5. Call the RichEditControl.ReplaceService<T> method to register the custom ISyntaxHighlightService implementation.

Files to Look At

Form1.cs (VB: Form1.vb)

Documentation

Highlight Document Syntax

More Examples

How to: Create Syntax Highlight Tokens to Highlight T-SQL Language Syntax

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

SyntaxHighlightApp/Form1.cs(vb)
C#
using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using DevExpress.CodeParser; using DevExpress.LookAndFeel; using DevExpress.Skins; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.XtraRichEdit.Services; namespace SyntaxHighlightApp { public partial class Form1 : DevExpress.XtraEditors.XtraForm { public Form1() { string path = "Form1.cs"; InitializeComponent(); richEditControl1.RemoveShortcutKey(System.Windows.Forms.Keys.Enter, System.Windows.Forms.Keys.Shift); // Use service substitution to register a custom service that implements syntax highlighting. richEditControl1.ReplaceService<ISyntaxHighlightService>(new MySyntaxHighlightService(richEditControl1)); richEditControl1.LoadDocument(path); } } /// <summary> /// This class implements the Execute method of the ISyntaxHighlightService interface to parse and colorize text. /// </summary> public class MySyntaxHighlightService : ISyntaxHighlightService { readonly RichEditControl syntaxEditor; SyntaxColors syntaxColors; SyntaxHighlightProperties commentProperties; SyntaxHighlightProperties keywordProperties; SyntaxHighlightProperties stringProperties; SyntaxHighlightProperties xmlCommentProperties; SyntaxHighlightProperties textProperties; public MySyntaxHighlightService(RichEditControl syntaxEditor) { this.syntaxEditor = syntaxEditor; syntaxColors = new SyntaxColors(UserLookAndFeel.Default); } void HighlightSyntax(TokenCollection tokens) { commentProperties = new SyntaxHighlightProperties(); commentProperties.ForeColor = syntaxColors.CommentColor; keywordProperties = new SyntaxHighlightProperties(); keywordProperties.ForeColor = syntaxColors.KeywordColor; stringProperties = new SyntaxHighlightProperties(); stringProperties.ForeColor = syntaxColors.StringColor; xmlCommentProperties = new SyntaxHighlightProperties(); xmlCommentProperties.ForeColor = syntaxColors.XmlCommentColor; textProperties = new SyntaxHighlightProperties(); textProperties.ForeColor = syntaxColors.TextColor; Document document = syntaxEditor.Document; List<SyntaxHighlightToken> syntaxTokens = new List<SyntaxHighlightToken>(tokens.Count); foreach (Token token in tokens) { var categorizedToken = token as CategorizedToken; if (categorizedToken != null) HighlightCategorizedToken(categorizedToken, syntaxTokens); } if (syntaxTokens.Count > 0) { document.ApplySyntaxHighlight(syntaxTokens); } } void HighlightCategorizedToken(CategorizedToken token, List<SyntaxHighlightToken> syntaxTokens) { Color backColor = syntaxEditor.ActiveView.BackColor; TokenCategory category = token.Category; switch (category) { case TokenCategory.Comment: syntaxTokens.Add(SetTokenColor(token, commentProperties, backColor)); break; case TokenCategory.Keyword: syntaxTokens.Add(SetTokenColor(token, keywordProperties, backColor)); break; case TokenCategory.String: syntaxTokens.Add(SetTokenColor(token, stringProperties, backColor)); break; case TokenCategory.XmlComment: syntaxTokens.Add(SetTokenColor(token, xmlCommentProperties, backColor)); break; default: syntaxTokens.Add(SetTokenColor(token, textProperties, backColor)); break; } } SyntaxHighlightToken SetTokenColor(Token token, SyntaxHighlightProperties foreColor, Color backColor) { if (syntaxEditor.Document.Paragraphs.Count < token.Range.Start.Line) return null; int paragraphStart = syntaxEditor.Document.Paragraphs[token.Range.Start.Line - 1].Range.Start.ToInt(); int tokenStart = paragraphStart + token.Range.Start.Offset - 1; if (token.Range.End.Line != token.Range.Start.Line) paragraphStart = syntaxEditor.Document.Paragraphs[token.Range.End.Line - 1].Range.Start.ToInt(); int tokenEnd = paragraphStart + token.Range.End.Offset - 1; Debug.Assert(tokenEnd > tokenStart); return new SyntaxHighlightToken(tokenStart, tokenEnd - tokenStart, foreColor); } #region #ISyntaxHighlightServiceMembers public void Execute() { string newText = syntaxEditor.Text; // Determine the language by file extension. string ext = System.IO.Path.GetExtension(syntaxEditor.Options.DocumentSaveOptions.CurrentFileName); ParserLanguageID lang_ID = ParserLanguage.FromFileExtension(ext); // Do not parse HTML or XML. if (lang_ID == ParserLanguageID.Html || lang_ID == ParserLanguageID.Xml || lang_ID == ParserLanguageID.None) return; // Use DevExpress.CodeParser to parse text into tokens. ITokenCategoryHelper tokenHelper = TokenCategoryHelperFactory.CreateHelper(lang_ID); if (tokenHelper != null) { TokenCollection highlightTokens = tokenHelper.GetTokens(newText); if (highlightTokens != null && highlightTokens.Count > 0) { HighlightSyntax(highlightTokens); } } } public void ForceExecute() { Execute(); } #endregion #ISyntaxHighlightServiceMembers } /// <summary> /// This class defines colors to highlight tokens. /// </summary> public class SyntaxColors { static Color DefaultCommentColor { get { return Color.Green; } } static Color DefaultKeywordColor { get { return Color.Blue; } } static Color DefaultStringColor { get { return Color.Brown; } } static Color DefaultXmlCommentColor { get { return Color.Gray; } } static Color DefaultTextColor { get { return Color.Black; } } UserLookAndFeel lookAndFeel; public Color CommentColor { get { return GetCommonColorByName(CommonSkins.SkinInformationColor, DefaultCommentColor); } } public Color KeywordColor { get { return GetCommonColorByName(CommonSkins.SkinQuestionColor, DefaultKeywordColor); } } public Color TextColor { get { return GetCommonColorByName(CommonColors.WindowText, DefaultTextColor); } } public Color XmlCommentColor { get { return GetCommonColorByName(CommonColors.DisabledText, DefaultXmlCommentColor); } } public Color StringColor { get { return GetCommonColorByName(CommonSkins.SkinWarningColor, DefaultStringColor); } } public SyntaxColors(UserLookAndFeel lookAndFeel) { this.lookAndFeel = lookAndFeel; } Color GetCommonColorByName(string colorName, Color defaultColor) { Skin skin = CommonSkins.GetSkin(lookAndFeel); if (skin == null) return defaultColor; return skin.Colors[colorName]; } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.