Notepad2实现单词高亮


Notepad2是一个基于文本编辑器控件Scintilla的编辑器,Notepad++也属同类.所以添加这个功能实际上是修改Scintilla的某个组件.

Scintilla的核心部分是Paint,即将文本绘制到窗口中,执行这个任务是是Editor::Paint函数.

Paint函数的主要逻辑是循环遍历需要绘制的行,然后使用DrawLine函数来实际的执行绘图操作,因为我们要检查每一行,所以循环开始前就要确定需要高亮的文本的内容.代码如下

    // 获取需要高亮的文本
    bool lastHighLighted false;
        if highLightStr ) { lastHighLighted true delete highLightStr;}
    highLightStr 0;
    if selType == selRectangle || selType == noSel) {
        highLightStr 0;
        }
    else {
        int start SelectionStart();
        int end SelectionEnd();
        if (start != end) {

            highLightStr new char[end start 8];
            pdoc->GetCharRange(highLightStr,start,end start);
            highLightStr[end start] = '\0';
            }
        }

    if highLightStr || (lastHighLighted && !highLightStr) )
        if (AbandonPaint())
            return;

highLightStr 是Editor对象的一个成员,每次Paint,检查是否有选中文本,如果有,将选中的文本提取出来,highLightStr 指向这个文本.另一部分代码在DrawLine函数中.

DrawLine会输出一行文本到屏幕上,分为两个阶段,第一个阶段绘制背景,第二个阶段绘制文字.需要在第一个阶段中添加一部分代码.

                    if (vsDraw.highLightOn && !inSelection) {

                        char ll->chars[i+1];
                        ll->chars[i+1] = '\0';
                        std::string str(&ll->chars[startseg]);
                        
                        size_type index = -1;

                        for ( ;  highLightStr && (index str.find(highLightStr,index 1) ) != std::string::npos ; )
                        {

                            rcHighLight.left ll->positions[index startseg] + xStart subLineStart;
                            rcHighLight.right ll->positions[index startseg strlen(highLightStr)] + xStart subLineStart;
                            surface->FillRectangle(rcHighLight,vsDraw.HighLightBack.allocated);
                        }
    
                        ll->chars[i+1] = c;
                        }

说明,highLightOn表示是否开启单词高亮,inSelection表示文本是否在选区范围内,对选区中的文本一律不作高亮.str是当前要绘制的行中的某个段,一个段是一段样式相同的文本,例如一段注释是一段,一个关键字也是一个段.接下来的for循环在str中搜索highLightStr的每次出现,如果找到,则计算这段文本所占据的矩形区域,最后用FillRectangle给这矩形区域填充一个颜色,这里采用IDA中的色彩:黄色.

效果图