0
点赞
收藏
分享

微信扫一扫

c++builder RichEdit的源码显示之亮显(附代码)


因为要在richEdit中显示pb源码,故写了亮显代码。因为只做显示,无需编辑,所以不想借用控件,那样升级维护比较麻烦。

 

图先:基本和pb中看到的效果一直,而且处理了数字(整数和小数),枚举常量。注释,字符串优先处理。

 

 

c++builder RichEdit的源码显示之亮显(附代码)_character

 

/*附属定义
const int KEYWORD_QTY = 140;
 const int KEYWORD_MAXLEN = 15  ,KEYWORD_MINLEN = 2;
 short KeyWordOffset[KEYWORD_MAXLEN];       //用于指示某个长度的关键字的开始处,免得从第一个关键字循环找,效率低 
struct strc_KEYWORD{
     int iLen;
     int tcolor;
     int iFont;
     char szKEYWORD[20];
 }; 
strc_KEYWORD KEYWORD_LIST[KEYWORD_QTY + 1]={     //关键字只贴若干个..
             4,clPurple,1,"blob",      7,clPurple,1,"boolean",       4,clPurple,1,"char",     9,clPurple,1,"character",
             4,clPurple,1,"date",      8,clPurple,1,"datetime",      7,clPurple,1,"decimal",  3,clPurple,1,"dec",
             6,clPurple,1,"double",    7,clPurple,1,"integer",       3,clPurple,1,"int",      4,clPurple,1,"long",
             8,clPurple,1,"longlong",  4,clPurple,1,"real",          6,clPurple,1,"string",   4,clPurple,1,"time",
             15,clPurple,1,"unsignedinteger",   4,clPurple,1,"uint",  11,clPurple,1,"unsignedint",              11,clPurple,1,"unsignedlong",
             5,clPurple,1,"ulong",     3,clPurple,1,"any"}  
 
 
在create事件中把KEYWORD_LIST冒泡排序,按长度从小到大。
KeyWordOffset[]用来指示某个长度的关键字的开始offset,比如KeyWordOffset[6] = 50
                                                                                  代表长度为6的关键字排在第50位开始的地方
 
*/
//注意如下的代码中,单引号内的字符的右斜要变为左斜,我粘贴上来,这个控件自动变为右斜线了。注意! 
void __fastcall TForm1::HighLightTxtEx(TObject *Sender)
 {
     //高亮显示文本,提示关键字;
     //显示模式分关键字,数据类型两大模式。    
     int iLenOfText;
     int ibegin = 0,iend = 0;
   
     TFontStyles StyleProcess;   
     StyleProcess = TFontStyles()<<fsBold;    bool bISdecimal; 
    //注意:文件最开头和 0x20,0x0D,0x0A,0x09作为词语分隔符。
     
     iLenOfText = RichEditSource ->Text.Length();    if (iLenOfText < 20) return;
      
     iLenOfText -=2;    //最后2字符总是0D0A,所以为了防止越界。可以减少2个。
     char *pText = new char[iLenOfText];    memcpy(pText,RichEditSource ->Text.c_str(),iLenOfText);    //转成指针可能比较快
    LockWindowUpdate(Handle);                //不要这一句。
    for(int i = 0;i < iLenOfText;i ++){
        Application->ProcessMessages();      //******注意这里,如果代码很长比如超过5页,不释放消息的话会很卡。
                                                          //增加这一句后,看起来感觉上是刷的一下就着色好了,但只是个错觉,
                                                          //因为我们眼睛看到的是第一页,而且鼠标最开始操作的也是第一页。如果
                                                          //你迅速拉到最后一页,可以发现程序着色还是进行。但是释放消息能够提高
                                                          //响应,我们也不会一下子看到最尾的地方。基本可用。
                                                          //当然如果是代码是可编辑状态,那只需要处理从当前光标处到后面的亮显即可。
                                                          //就比如我们在编程时输入/*,后面就会全部变成蓝色。但是我们眼睛其实在3s时间
                                                          //左右,只能看到当前位置的一页左右,所以释放消息都应该可以的。
        //优先是注释
         //判断到一个注释,要用内循环增加指针,直到结束。这样不要靠外循环去判断。很麻烦。
         //2种注释:2F 2F + 0D 0A (优先,因为 //*   */           也是//优先。谁先出现谁优先。跟字符串一起是一个道理,抢先式。
         //2F 2A + 2A 2F
         
         if(*(pText + i) == '/x2F' &&  *(pText + i + 1) == '/x2F'){
              ibegin = i;
              //循环直到行末
              i +=2;
              while( !(*(pText + i)== '/x0D' && *(pText + i + 1) == '/x0A')){
                   i ++;
              }             iend = i - ibegin;
             //高亮显示;
              RichEditSource ->SelStart = ibegin;
              RichEditSource ->SelLength = iend ;             RichEditSource ->SelAttributes->Color = clSilver;
              RichEditSource ->SelAttributes->Style = StyleProcess;
              
              continue;       //不要往下检查,而应该for到下一个i值
         }        if(*(pText + i) == '/x2F' &&  *(pText + i + 1) == '/x2A'){
              ibegin = i;
              //循环直到行末
              i +=2;
              while(  !(*(pText + i)== '/x2A' && *(pText + i + 1) == '/x2F')){
                   i ++;
              }             iend = i - ibegin;
             //高亮显示;
              RichEditSource ->SelStart = ibegin;
              RichEditSource ->SelLength = iend ;             RichEditSource ->SelAttributes->Color = clSilver;
              RichEditSource ->SelAttributes->Style = StyleProcess;
              
              continue;       //不要往下检查,而应该for到下一个i值
         }
         
         //其次是字符串
         if(*(pText + i) == '/"'){
              ibegin = i;
              
              //循环直到行末
              i ++;             while(true){  //如果有转义符,不算退出,还是在字符串内
                   if(*(pText + i)== '~'){
                     i +=2;
                   }
                   if(*(pText + i)== '/"'){
                     break;
                   }
                   i++;
              }             iend = i - ibegin +1;
             //高亮显示;
              RichEditSource ->SelStart = ibegin;
              RichEditSource ->SelLength = iend ;             RichEditSource ->SelAttributes->Color = clMaroon;
              RichEditSource ->SelAttributes->Style = StyleProcess;
              
              continue;       //不要往下检查,而应该for到下一个i值
         }         //捕获数字 (整数和小数,指数)
         if(*(pText + i) > '/x2F' &&  *(pText + i) < '/x3A'){
              ibegin = i;
              //循环直到行末
              i ++;
              bISdecimal = false;
              while(true){
                 if(*(pText + i) == '/x2E' || *(pText + i) == '/x45'){
                     bISdecimal = true;
                     i ++;
                 }else if(*(pText + i) > '/x2F' &&  *(pText + i) < '/x3A'){
                     i ++;
                 }else{
                     break;
                 }
              }             iend = i - ibegin;
             //高亮显示;
              RichEditSource ->SelStart = ibegin;
              RichEditSource ->SelLength = iend;
              if(bISdecimal){
                 RichEditSource ->SelAttributes->Color = clGray;
              }else{
                 RichEditSource ->SelAttributes->Color = clNavy;
              }             RichEditSource ->SelAttributes->Style = StyleProcess;
              continue;       //不要往下检查,而应该for到下一个i值
         }
                 
         //再次是一般语句        
         //逐个取词语,包括起始位置和长度,便于与关键字比较。
         //关键字是以"_"和字母开头的。
         //如何定义是一个字以内呢?1.必须是字母,而且小写(程序生成的关键字都是小写,可以保证,无需转换),只要遇到不是字母的,退出        //1.如果不是在词内,进入词状态,并直到词的结束(非小写字母,比如空格,括号,逗号,句号,回车,点符号等)
         if (('/x60' < *(pText + i) &&
                 '/x7B' > *(pText + i)) ||
                 '/x5F' == *(pText + i)){            ibegin = i;
            //非字母数字结束
             while(('/x40' < *(pText + i) &&
                     '/x5B' > *(pText + i)) ||
                             ('/x2F' < *(pText + i) &&
                             '/x3A' > *(pText + i)) ||
                                 ('/x60' < *(pText + i) &&
                                 '/x7B' > *(pText + i)) ||
                                     '/x5F' == *(pText + i)){
                i ++;
             }            //如果是枚举,以感叹号结束
             if(*(pText + i)== '/x21'){
                   //设置为枚举的颜色
                   //高亮显示;
                   iend = i +1 - ibegin;
                   RichEditSource ->SelStart = ibegin;
                   RichEditSource ->SelLength = iend;                  RichEditSource ->SelAttributes->Color = clNavy;
                   RichEditSource ->SelAttributes->Style = StyleProcess;
                   
                   continue;
             }            iend = i - ibegin;
              
             //对比关键字 ,KEYWORD_LIST已排序数组
             if(iend > KEYWORD_MAXLEN || iend < KEYWORD_MINLEN) continue;      //上下限长度
             
             for(int kkk=KeyWordOffset[iend -1];kkk< KEYWORD_QTY;kkk++){ 
                 if (KEYWORD_LIST[kkk].iLen > iend) break;                      //在排序数组内已经无法找到该长度了。                if (KEYWORD_LIST[kkk].iLen == iend){
                     if (memcmp(pText + ibegin,KEYWORD_LIST[kkk].szKEYWORD,iend)==0){                        //高亮显示;
                         RichEditSource ->SelStart = ibegin;
                         RichEditSource ->SelLength = iend;                        RichEditSource ->SelAttributes->Color = (TColor)KEYWORD_LIST[kkk].tcolor;
                         RichEditSource ->SelAttributes->Style = StyleProcess;                        //找到后要退出循环比较。
                         break;
                     }
                 }
             }
         }
     }    //取消选择
     RichEditSource ->SelStart = 0;
     RichEditSource ->SelLength = 0;    LockWindowUpdate(0);                       //不要这一句
    delete [] pText;
     pText = NULL;
 }

举报

相关推荐

0 条评论