代码编辑器之关键字染色, 优化了的方案

代码编辑器之 关键字染色
                     
电子科技大学软件学院03级2班 周银辉
  
    在制作代码编辑器,对关键字染色虽然都很容易地想到使用RichTextBox的SelectionColor属性来实现,但将遇到很多细节问题,导致染色的效果很差,比如染色时文本闪烁得很厉害.甚至不能正确地染色,比如将"inty"染成黑色,但用户突然在字母't'后插入换行时却不能将'int'染成关键字的蓝色.这里是我今天用RichTextBox实现的染色方案,效果挺不错的.
  
一,关于染色时的闪烁:
    染色时闪烁得很厉害,原因是调用Select(int,int)函数次数(或是设置SelectionStart属性次数)过多。
    如果你采用如下方式染色:当文本改变时,对改变的文本行进行分析,如果含有关键字,就将这些关键字进行染色。那么你的染色方式将导致严重的闪烁。因为如果文本的当前行含有较多关键字时,每键入一个字符都会对这些关键字依次染色一次,每次染色时都会调用
调用Select(int,int)函数(或是设置SelectionStart属性)。当然这也会导致不真确的染色,因为一个键入可能影响两行文本(比如在一行文本中间插入换行符时)。
    我的方式是:减少染色次数。当在文本筐中键入字符是,取得受本次键入影响的单词,如果该单词是关键字,那么将其染成关键字颜色(蓝色),否则染成普通文本颜色(黑色)。由于一次键入顶多影响两个单词,所以每次键入顶多染色两次(并且没有重复染色);

二,关于受键入影响的单词:
    如果键入的是字母数字或者下划线,那么光标处的单词便是受影响的单词,只需要判断该单词是否为关键字,
如果该单词是关键字,那么将其染成关键字颜色(蓝色),否则染成普通文本颜色(黑色)。 如果键入的是除字母数字或者下划线外的字符,那么受影响的是以该字符为界的两个单词,比如在“intint”中间插入空格是其被分解成以空格为界的两个“int”,那么就对这两个单词进行判断就可以了。
以下代码描述了上述思想(其中GetCurrentWord()用于取得指定位置处的单词,Dye()用于将指定文本染色)
 1  private   void  richTextBox_CodeArea_TextChanged( object  sender, EventArgs e)
 2          {
 3              RichTextBox rbx  =  (RichTextBox)sender;
 4               int  start, length;
 5               int  ins  =   this .richTextBox_CodeArea.SelectionStart;
 6              
 7               char  c  =   '   ' ;
 8               string  word  =   "" ;
 9               if  (ins  >   0 )
10              {
11                  c  =   this .richTextBox_CodeArea.Text[ins  -   1 ];
12              }
13               else
14              {
15                   if  ( this .richTextBox_CodeArea.Text.Length  >   0 )
16                  {
17                      c  =   this .richTextBox_CodeArea.Text[ 0 ];
18                  }
19              }
20 
21               // 取得插入点两边的两个单词,并判断这两个单词是否是关键字.
22               if  ( ! char .IsLetter(c)  &&   ! Char.IsDigit(c)  &&  c  !=   ' _ ' )
23              {
24                   // 将字符c染色
25                   this .Dye(ins  -   1 1 this .textColor,  this .textColor);
26 
27                  word  =   this .GetCurrentWord(ins  -   1 out  start,  out  length);
28 
29                  Color cl  =  IsKey(word)  ?   this .keyColor :  this .textColor;
30                   this .Dye(start, length, cl,  this .textColor);
31 
32                  word  =   this .GetCurrentWord(ins  +   1 out  start,  out  length);
33                  cl  =  IsKey(word)  ?   this .keyColor :  this .textColor;
34                   this .Dye(start, length, cl,  this .textColor);
35 
36              }
37               else // 取得插入点处的单词并判断其是否是关键字
38              {
39                  word  =   this .GetCurrentWord(ins,  out  start,  out  length);
40                  Color cl  =  IsKey(word)  ?   this .keyColor :  this .textColor;
41                   this .Dye(start, length, cl,  this .textColor);
42              }
43 
44          }
45 

三, 关于不正确的染色:
     染色之所以有时会出现错误,是因为算法不能应付一些特殊的情况。比如"intif"被染成黑色后,当在‘i’前面插入换行符时,其被分成两行,此时"int"与"if"都应该被染成蓝色,而往往"int”还会保持黑色。按照“
二,关于受键入影响的单词”中描述的方法进行染色将解决这方面的问题。

---------------------------------
Demo下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值