前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[整理]如何做一个语法着色控件

[整理]如何做一个语法着色控件

作者头像
跟着阿笨一起玩NET
发布2018-09-18 14:53:28
6780
发布2018-09-18 14:53:28
举报
文章被收录于专栏:跟着阿笨一起玩NET

前言

很多IDE或者开发工具中都有语法着色的功能,这是如何实现的呢?笔者试着用C#做了一个Sample,基本上实现此功能。

本文一半是原创,一半是参考国外的论坛

思路

语法着色器,实际上只做了两件事情:“接受用户输入”以及“改变关键字字体属性”。

1)首先看第一个:接受用户输入。

C#自带的控件中能够满足需求的首推“RichTextBox”,笔者在网上经常看到很多同行都以此为基础,制作出类似MS-Word的种种效果。既然,复杂的Word效果都能够实现,那么语法着色自然也就不在话下。

2)其次,最重要的“改变关键字字体属性”。

这一点还可分成三个更小的工作:关键字列表、判断关键字、定义字体属性。

  • 关键字列表很简单,一个List即可满足需求。 这里以基本SQL语句为例。 private IList<String> _KeyWords = new List<String>() { "SELECT", "UPDATE", "DELETE", "INSERT", "DROP", "FROM", "WHERE", "ALERT", "CREATE", "TABLE", "VALUES", "NULL", "AND", "OR", "NOT", "IN", "INTO", "UNION", "AS", "IS", "COUNT", "MAX", "MIN", "AVG", "WAIT", "NOWAIT", "WITHOUT", "LOCK", "GROUP", "ORDER", "BY", "JOIN", "LEFT", "RIGHT", "CASE", "WHEN", "ELSE", "END", "COMMIT", "ROLLBACK" };
  • 判断关键字 为了在用户输入时能够立即对所输入的内容有所反映,我们需要override一下RichTextBox的OnTextChanged()方法。 其他属性及方法介绍请参考MSDN 笔者的算法很简单,遍历业已定义好的关键字列表,用其与用户输入的内容进行比较,如果发现相同,则按照字符的index值计算编辑区域。
代码语言:javascript
复制
定义字体属性
 在C#中有一个叫做FONT的类能够满足需求。 其他属性及方法介绍请参考MSDN
 注意事项
 笔者在尝试的过程中发现屏幕中显示的内容会随着用户的输入,出现闪烁。究其原因可能是因为Windows一直在重新绘制窗口造成的,为了回避这个问题,我们可以使用SuspendLayout()和ResumeLayout()暂停和恢复画面重新绘制的过程。

 做完这几步,我们的语法着色控件也就大功告成了。下面是全部源代码。在VS2008 Express版本上调试通过。
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Drawing; using System.ComponentModel;  namespace Base {     public partial class SQLEditor : RichTextBox     {                  /// <summary>         /// 关键字列表         /// </summary>         private IList<String> _KeyWords = new List<String>()         {             "SELECT", "UPDATE", "DELETE", "INSERT", "DROP", "FROM", "WHERE", "ALERT", "CREATE", "TABLE",             "VALUES", "NULL",             "AND", "OR", "NOT", "IN", "INTO", "UNION", "AS", "IS",             "COUNT", "MAX", "MIN", "AVG",             "WAIT", "NOWAIT", "WITHOUT", "LOCK", "GROUP", "ORDER", "BY",             "JOIN", "LEFT", "RIGHT", "CASE", "WHEN", "ELSE", "END",             "COMMIT", "ROLLBACK"         };         [CategoryAttribute("KeyWords"), Description("关键字列表")]         public IList<String> KeyWords         {             get             {                 return this._KeyWords;             }             set             {                 this._KeyWords = value;             }         }          /// <summary>         /// 关键字颜色(默认为蓝色)         /// </summary>         private Color _KeyWordsColor = Color.Blue;         [CategoryAttribute("KeyWordsColor"), Description("关键字颜色")]         public Color KeyWordsColor         {             get             {                 return this._KeyWordsColor;             }             set             {                 this._KeyWordsColor = value;             }         }          // TODO 数字,字符串属性          /// <summary>         /// 分隔符         /// </summary>         Regex tokens = new Regex(@"[\s\r\n\t\(\)\;]");          /// <summary>         /// 接受输入时语法着色         /// </summary>         /// <param name="e"></param>         protected override void OnTextChanged(EventArgs e)         {             base.OnTextChanged(e);              // TODO DEBUG             Console.WriteLine("POINT:" + this.SelectionStart + "|" + "SIZE:" + this.Text.Length);              // 暂停屏幕刷新,防止闪烁             SuspendLayout();              // 缓存输入焦点位置             int inputPoint = this.SelectionStart;              String[] wrk_words = tokens.Split(this.Text.ToUpper());              // 判断是否有必要进行着色             if (this.Text.Length == 0) return;              // 克隆关键字列表             IList<String> C_KeyWords = new List<String>(this._KeyWords);             // 关键字开始坐标             int iStart = 0;              // 初始化             this.SelectionStart = 0;             this.SelectionLength = this.Text.Length;             this.SelectionColor = Color.Black;             this.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);              // 逐字匹配             foreach (String word in wrk_words)             {                 foreach (String keyw in C_KeyWords)                 {                     // 判断当前值是否为关键字                     if (word.Equals(keyw))                     {                         // 查找坐标                         iStart = this.Text.ToUpper().IndexOf(keyw);                          // 判断是否存在处理对象                         while (iStart >= 0)                         {                             this.SelectionStart = iStart;                             this.SelectionLength = keyw.Length;                              this.SelectionColor = Color.Blue;                             this.SelectionFont = new Font("Courier New", 10, FontStyle.Bold);                              // 获取下一次处理开始坐标                             iStart = this.Text.ToUpper().IndexOf(keyw, this.SelectionStart + 1);                              this.SelectionStart = this.Text.Length;                             this.SelectionLength = 0;                         }                     }                     // break;                  }              }              // 计算输入点的位置,如果不在末尾,则说明用户在修改前面的内容,否则将焦点移到末尾             this.SelectionStart = (inputPoint < this.Text.Length) ? inputPoint : this.Text.Length;             this.SelectionLength = 0;              ResumeLayout();         }     } }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-01-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 思路
    • 1)首先看第一个:接受用户输入。
      • 2)其次,最重要的“改变关键字字体属性”。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档