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

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

 

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

 

 

 

/*附属定义

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值