RichEditControl自定义高亮语法

RichEditControl作为强大的富文本编辑器,支持自定义高亮语法,这就可以实现编辑语言、SQL语言和其他标记文本的显示。很香,下面是自定义XML高亮显示的效果。

RichEditControl自定义高亮语法

需要实现ISyntaxHighlightService接口的方法即可,自定义类如下:

using System.Collections.Generic;
using System.Drawing;
using DevExpress.XtraRichEdit.API.Native;
using DevExpress.XtraRichEdit.Services;

namespace Dev.Tool.Xml
{
    /// <summary>
    /// 自定义语法高亮服务
    /// </summary>
    public class CustomSyntaxHighlightService : ISyntaxHighlightService
    {
        #region 私有变量

        //文档
        private readonly Document _document;
        //默认语法高亮颜色
        private readonly SyntaxHighlightProperties _defaultSettings = new SyntaxHighlightProperties() { ForeColor = Color.Brown };
        //关键字语法高亮颜色
        private readonly SyntaxHighlightProperties _keywordSettings = new SyntaxHighlightProperties() { ForeColor = Color.Blue };
        //字符串语法高亮颜色
        private readonly SyntaxHighlightProperties _stringSettings = new SyntaxHighlightProperties() { ForeColor = Color.Black };

        readonly string[] _keywords = {"version", "encoding", "application", "name", "isnull", "iskey", "value", "property", "=", "</", "/>", "<", ">"};

        #endregion

        #region 构造函数

        public CustomSyntaxHighlightService(Document document)
        {
            this._document = document;
        }

        #endregion

        #region 接口成员
        public void ForceExecute()
        {
            Execute();
        }

        public void Execute()
        {
            _document.ApplySyntaxHighlight(ParseTokens());
        }

        #endregion

        #region 私有函数

        /// <summary>
        /// 解析标记
        /// </summary>
        /// <returns>语法高亮标记列表</returns>
        private List<SyntaxHighlightToken> ParseTokens()
        {
            List<SyntaxHighlightToken> tokens = new List<SyntaxHighlightToken>();
            // 搜索标记
            DocumentRange[] ranges = _document.FindAll("\"", SearchOptions.None);
            for (int i = 0; i < ranges.Length / 2; i++)
            {
                tokens.Add(new SyntaxHighlightToken(ranges[i * 2].Start.ToInt(),
                    ranges[i * 2 + 1].Start.ToInt() - ranges[i * 2].Start.ToInt() + 1, _stringSettings));
            }
            // 搜索关键词
            foreach (var t in _keywords)
            {
                ranges = _document.FindAll(t, SearchOptions.None);
                foreach (var t1 in ranges)
                {
                    if (!IsRangeInTokens(t1, tokens))
                        tokens.Add(new SyntaxHighlightToken(t1.Start.ToInt(), t1.Length, _keywordSettings));
                }
            }
            // 排序
            tokens.Sort(new SyntaxHighlightTokenComparer());
            // 添加
            AddPlainTextTokens(tokens);
            return tokens;
        }

        /// <summary>
        /// 添加明文标记
        /// </summary>
        /// <param name="tokens">标记列表</param>
        private void AddPlainTextTokens(List<SyntaxHighlightToken> tokens)
        {
            int count = tokens.Count;
            if (count == 0)
            {
                tokens.Add(new SyntaxHighlightToken(0, _document.Range.End.ToInt(), _defaultSettings));
                return;
            }
            tokens.Insert(0, new SyntaxHighlightToken(0, tokens[0].Start, _defaultSettings));
            for (int i = 1; i < count; i++)
            {
                tokens.Insert(i * 2, new SyntaxHighlightToken(tokens[i * 2 - 1].End, tokens[i * 2].Start - tokens[i * 2 - 1].End, _defaultSettings));
            }
            tokens.Add(new SyntaxHighlightToken(tokens[count * 2 - 1].End, _document.Range.End.ToInt() - tokens[count * 2 - 1].End, _defaultSettings));
        }

        /// <summary>
        /// 是否在DocumentRange范围内
        /// </summary>
        /// <param name="range">DocumentRange范围</param>
        /// <param name="tokens">标记</param>
        /// <returns></returns>
        private bool IsRangeInTokens(DocumentRange range, List<SyntaxHighlightToken> tokens)
        {
            foreach (var t in tokens)
            {
                if (range.Start.ToInt() >= t.Start && range.End.ToInt() <= t.End)
                    return true;
            }

            return false;
        }

        #endregion
    }

    #region 比较器
    public class SyntaxHighlightTokenComparer : IComparer<SyntaxHighlightToken>
    {
        public int Compare(SyntaxHighlightToken x, SyntaxHighlightToken y)
        {
            if (x == null || y == null)
                return 0;
            return x.Start - y.Start;
        }
    }
    #endregion
}

调用方式:

richEditControl1.ReplaceService<ISyntaxHighlightService>(new CustomSyntaxHighlightService(richEditControl1.Document));
richEditControl1.LoadDocument(fileName, DevExpress.XtraRichEdit.DocumentFormat.PlainText);
上一篇:【栈和队列】leetcode150——逆波兰表达式求值


下一篇:Vue中mustache的探秘