因为要在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;
}