代码编辑器控件ICSharpCode.TextEditor的关键字高亮以及代码折叠功能

SharpDevelop (#develop)有很多“副产品”,其中最出名的应算SharpZipLib (#ziplib),纯C#的ZIP类库,

而在SharpDevelop (#develop)中,“隐藏”了很多优秀的类库,其中ICSharpCode.TextEditor是其中之一。

github源代码地址

https://github.com/icsharpcode

ICSharpCode.TextEditor是基于System.Windows.Forms的类库项目

类ICSharpCode.TextEditor.TextEditorControl 依次继承于抽象类 TextEditorControlBase,而类TextEditorControlBase又继承于System.Windows.Forms.UserControl,

可以当作Winforms控件来使用。该控件可以实现富文本编辑类似于【RichTextBox】,关键字的高亮(变色)显示,以及花括号{}等的自动折叠功能。

新建Winforms应用程序TextEditorDemo。添加对类库ICSharpCode.TextEditor.dll的引用。

添加一个ICSharpCode.TextEditor.TextEditorControl 控件textEditorControl1。

为了实现代码折叠功能,我们新建一个实现IFoldingStrategy(折叠策略接口)的类FoldingStrategyForCSharp。

FoldingStrategyForCSharp.cs的源程序如下:

using ICSharpCode.TextEditor.Document;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TextEditorDemo
{
    /// <summary>
    /// C#代码折叠策略,实现接口IFoldingStrategy
    /// </summary>
    public class FoldingStrategyForCSharp : IFoldingStrategy
    {
        /// <summary>
        /// 生成代码折叠,对花括号{},#region等的处理
        /// </summary>
        /// <param name="document">当前文档</param>
        /// <param name="fileName">文档名</param>
        /// <param name="parseInformation">Extra parse information, not used in this sample.</param>
        /// <returns>A list of FoldMarkers.</returns>
        public List<FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInformation)
        {
            List<FoldMarker> list = new List<FoldMarker>();
            Stack<int> startLines = new Stack<int>();
            // Create foldmarkers for the whole document, enumerate through every line.
            for (int i = 0; i < document.TotalNumberOfLines; i++)
            {
                // Get the text of current line.
                string text = document.GetText(document.GetLineSegment(i));
                if (text.Trim().StartsWith("#region")) // Look for method starts
                {
                    startLines.Push(i);
                }
                if (text.Trim().StartsWith("#endregion")) // Look for method endings
                {
                    int start = startLines.Pop();
                    // Add a new FoldMarker to the list.
                    // document = the current document
                    // start = the start line for the FoldMarker
                    // document.GetLineSegment(start).Length = the ending of the current line = the start column of our foldmarker.
                    // i = The current line = end line of the FoldMarker.
                    // 7 = The end column
                    list.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length, i, 57, FoldType.Region, "..."));
                }
                //支持嵌套 {}
                if (text.Trim().StartsWith("{")) // Look for method starts
                {
                    startLines.Push(i);
                }
                if (text.Trim().StartsWith("}")) // Look for method endings
                {
                    if (startLines.Count > 0)
                    {
                        int start = startLines.Pop();
                        list.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length, i, 57, FoldType.TypeBody, "...}"));
                    }
                }

                // /// <summary>
                if (text.Trim().StartsWith("/// <summary>")) // Look for method starts
                {
                    startLines.Push(i);
                }
                if (text.Trim().StartsWith("/// <returns>")) // Look for method endings
                {
                    int start = startLines.Pop();
                    //获取注释文本(包括空格)
                    string display = document.GetText(document.GetLineSegment(start + 1).Offset, document.GetLineSegment(start + 1).Length);
                    //remove ///
                    display = display.Trim().TrimStart('/');
                    list.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length, i, 57, FoldType.TypeBody, display));
                }
            }
            return list;
        }
    }
}

为了触发代码折叠功能,需处理文本更新事件TextChanged,调用文本更新折叠功能。

textEditorControl1.Document.FoldingManager.UpdateFoldings(null, null);

默认的窗体Form1的主要代码如下:

(忽略设计器自动生成的代码)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TextEditorDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            //在文本内容更改时自动触发代码折叠事件
            this.textEditorControl1.TextChanged += new System.EventHandler(this.textEditorControl1_TextChanged);
            //https://github.com/icsharpcode
            //SharpDevelop (#develop)有很多“副产品”,其中最出名的应算SharpZipLib (#ziplib),纯C#的ZIP类库,
            //而在SharpDevelop (#develop)中,“隐藏”了很多优秀的类库,其中ICSharpCode.TextEditor是其中之一。
            //SharpZipLib   ---> 压缩类库
            //ILSpy         ---> 反编译.net托管类库项目
            //CodeConverter ---> C#与VB代码之间的转换
            //AvalonEdit    ---> 基于WPF的文本编辑器组件(The WPF-based text editor component used in SharpDevelop)
            /*
             * TextEditor(和SharpDevelop一样)经常使用策略模式,所以你会在很多地方看到Strategy。
             * 在策略模式中,一个接口的定义是根据功能需要,但并不实现这些功能。
             * 如果你需要不同的功能实现,你可以写一个实现了IDocument接口的新策略。
             * 由于某些原因,MarkerStrategy是一个sealed接口类,没有实现相应的接口,因此它不能被替换掉。
             * 
             * 自动缩进由继承了IFormattingStrategy接口的类来提供支持,当用户有输入时,自动缩进会自动格式化编辑器中的文本。
             * DefaultFormattingStrategy实现了当Enter键被按下时根据上一行来自动缩进的简单功能。
             * 在 SharpDevelop的源代码中你可以找到更多的缩进策略。
             * 
             * IFormattingStrategy接口中定义了包括向后搜索或者向前搜索匹配条件文本的方法以使结果能够高亮显示,
             * 实现该接口的类有:TextUtilities,BracketHighlightingSheme,BracketHighlight和TextArea。
             * TextArea中通过硬编码来实现 ()、[]和{}等括号的自动缩进。
             * 
             * 语法高亮通常是由一个DefaultHighlightingStrategy类的实例来提供支持,它使用以”xshd”为扩展名的 XML文件来高亮显示各种文本。
             * 有超过十个这样的XML文件作为资源嵌入在文本编辑器DLL中,当加载一个文件时,TextEditorControl类会根据文件的扩展名来自动选择一个高亮规则文件。
             * 修改编辑器中的文本文件的名称并不会改变之前选择的高亮规则,所以本文Demo中的大部分都是手动设置语法高亮规则的。
            */
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //注意:将ICSharpCode.TextEditor类库的源代码的Resources文件夹里面的所有文件 的 属性--->生成操作 都为 嵌入的资源 即可
            //
            this.textEditorControl1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.textEditorControl1.EnableFolding = true;
            this.textEditorControl1.IsReadOnly = false;
            this.textEditorControl1.Language = ICSharpCode.TextEditor.TextEditorControl.Languages.CSharp;
            this.textEditorControl1.Location = new System.Drawing.Point(0, 0);
            this.textEditorControl1.Name = "textEditorControl1";
            this.textEditorControl1.Size = new System.Drawing.Size(561, 339);
            this.textEditorControl1.TabIndex = 0;
            //代码折叠策略,对花括号{},#region 等标记的处理
            this.textEditorControl1.Document.FoldingManager.FoldingStrategy = new FoldingStrategyForCSharp();

            this.textEditorControl1.Text = @"            Console.WriteLine(""将随机一个1~99之间的数字:请猜猜看"");
            int destNumber = new Random().Next(1, 100);
            int count = 0;
            #region 猜数字循环流程
            while (true)
            {
                Console.WriteLine(""请猜一个数字。。。"");
                count++;
                int currentNumber = int.Parse(Console.ReadLine());
                if (currentNumber == destNumber)
                {
                    Console.WriteLine($""猜数字成功.目标数字【{destNumber}】,共猜了【{count}】次"");
                    break;
                }
                else if (currentNumber > destNumber)
                {
                    Console.WriteLine($""当前数字【{currentNumber}】比猜的数字【大】,请重新试试,当前猜了【{count}】次"");
                }
                else
                {
                    Console.WriteLine($""当前数字【{currentNumber}】比猜的数字【小】,请重新试试,当前猜了【{count}】次"");
                }
            }
            #endregion
";
        }

        private void textEditorControl1_TextChanged(object sender, EventArgs e)
        {
            textEditorControl1.Document.FoldingManager.UpdateFoldings(null, null);
        }
    }
}

程序运行如图:

扫描二维码关注公众号,回复: 13486129 查看本文章

猜你喜欢

转载自blog.csdn.net/ylq1045/article/details/113621222