65.9K
CodeProject 正在变化。 阅读更多。
Home

用 C# 编写的语法高亮文本框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (77投票s)

2005年5月30日

3分钟阅读

viewsIcon

1003601

downloadIcon

12453

本文介绍了 RichTextBox 的代码,该代码知道如何高亮文本部分并提供自动完成功能。

Sample Image

引言

嘿。 这段代码是一个派生自 .Net 的 RichTextBox 的类。 它提供语法高亮和自动完成功能(就像 Intellisense,只是稍微笨一点)。

背景

你是否曾经编写过具有自己脚本语言的应用程序? 是否需要在您的应用程序中编辑 SQL/代码? 您是否只是想要一个比具有固定宽度字体的 TextBox 更好的控件? 现在你可以拥有它了:-)

当我需要在自己编写的应用程序中编辑 SQL 时,编写了这个控件。 然后我想

“即使我能找到一个可以很好地编辑 SQL 的控件,它仍然不会高亮我编写的表名或存储过程名。而且我知道我需要一个可以高亮我自己脚本语言的控件……”

所以我坐下来写了它。 后来我意识到没有自动完成的语法高亮意义不大,所以我添加了对自动完成的支持。

使用代码

首先,我必须道歉。 我不太擅长 GUI 编程,所以我所有的操作都是使用代码完成的,因为我缺乏为 PropertyGrid 编写自定义编辑器的知识。 解决了这个问题,我们可以继续! 该控件有两个用于高亮的输入

  1. 分隔符: 使用 Seperators 属性访问。

    每个分隔符都是一个 char,并且后面被称为“token”的是分隔符之间的非空字符串。

  2. 高亮描述符: 你可以使用(多么令人惊讶)HighlightDescriptor 方法添加一个 HighlightDescriptor

    HighlightDescriptor 是一个描述高亮规则的类的实例,它可以分为 token 识别信息和设计信息。

高亮规则

高亮规则有 6 个字段,使用它们构建

  • Token: 稍后与文本进行比较的字符串。
  • DescriptorType: 设置高亮类型。选项有:到单词的末尾、到行的末尾,以及到相应的结束 token。
  • DescriptorRecognition: 确定 token 如何与文本中的 token 进行比较。选项有:文本等于 token,文本以 token 开头,文本包含 token。
  • Color: 设置高亮时 token 的颜色。
  • Font: 设置高亮时 token 的字体。 这个字段是可选的。
  • UseForAutoComplete: 确定 token 是否将用于自动完成。

由于懒惰,HighlightDescriptor 的值只能在构造函数中设置。 <SideNote> 我真的认为 readonly 关键字被低估了。</SideNote>。

HighlightDescriptor 如下

        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; 
        }

关注点

写作过程中发生了一些有趣的事情

  1. 滚动条:由于每次文本更改时,我实际上都会再次更改它(就基础文本框而言),因此滚动条会将自身重置为最顶部和最左边的位置。 为了解决这个问题,我使用了 EM_GETSCROLLPOSEM_GETSCROLLPOS Windows 消息
            #region Scrollbar positions functions
            /// <summary>
            /// Sends a win32 message to get the scrollbars' position.
            /// </summary>
            /// <returns>a POINT structre containing horizontal
            ///       and vertical scrollbar position.</returns>
            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;
    
            }
    
            /// <summary>
            /// Sends a win32 message to set scrollbars position.
            /// </summary>
            /// <param name="point">a POINT
            ///        conatining H/Vscrollbar scrollpos.</param>
            private unsafe void SetScrollPos(Win32.POINT point)
            {
                IntPtr ptr = new IntPtr(&point);
                Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);
    
            }
            #endregion
  2. 键盘笔画:在自动完成功能的工作期间,我发现即使您覆盖了 OnKeyDown 方法并且不调用基本方法,仍然会处理包含实际字符的键的按键(它们使用 WM_CHAR 消息到达)。 因此,我决定覆盖 WndProc 方法并在该级别过滤掉不需要的按键。
  3. RTF:我并没有真正为这个项目学习 RTF。 我只是采用了一个常规的 RichTextBox,并了解了我需要构建什么来满足我的需求。 因此,我生成的 RTF 可能不是最佳的。 它可能具有可以通过操作 RTF 标头轻松解决的语言限制。

历史

  • 2005/05/29:首次发布。
  • 2005/06/04:修复了一些使用 ToCloseToken DescriptorType 时的错误。
  • 2005/07/13:修复了一些错误,添加了撤消/重做功能。
© . All rights reserved.