Scintilla开源库使用指南(一)-程序员宅基地

技术标签: java  操作系统  c/c++  

Scintilla是一个免费、跨平台、支持语法高亮的编辑控件。它完整支持源代码的编辑和调试,包括语法高亮、错误指示、代码完成(code completion)和调用提示(call tips)。能包含标记(marker)的页边(margin)可用于标记断点、折叠和高亮当前行。

Scintilla是一个免费、跨平台、支持语法高亮的编辑控件。它完整支持源代码的编辑和调试,包括语法高亮、错误指示、代码完成 (code completion)和调用提示(call tips)。能包含标记(marker)的页边(margin)可用于标记断点、折叠和高亮当前行。

可以从这里下载Scintilla库:http://scintilla.sourceforge.net/ScintillaDownload.html

这里有Scinilla相关的库下载,比如wxScintilla就是Scintilla的wxWidgets移植版。http://www.scintilla.org/ScintillaRelated.html

另外,Scintilla的作者为了演示这个东东的功能,编写了一个叫SciTE的演示程序。不过这个程序的功能已经强大到足以作为我 们的常用代码编辑器,很值得下载下来学习学习。

老规矩,还是从编译说起

偶只在Windows下编译过,所以只好说说Windows环境下的编译方法。对于Linux,没试过(丢人-_-)

下载、解压略过不提

首先进入scintilla的win32目录:

cd scintilla\win32
  • 对于mingw,输入:
    mingw32-make
  • 对于VC6以上版本,输入:
    nmake -f scintilla.mak
  • 对于VC6(没试过,从Readme里看来的),输入:
    nmake -f scintilla_vc6.mak
  • 对于C++Builder,输入:
    make -fscintilla.mak

编译完成后,在bin目录里会得到Scintilla.dll和SciLexer.dll文件,SciLexer.dll是包含了语法解析器 (Lexer)的Scintilla控件,一般来说我们只要用它就可以了。

需要说明的是,不管是用什么编译器生成的DLL文件,都可以供给其它编译器使用(就象系统DLL一样,任何编译器都能使用),所以不用为各种编译器都编译 一份。

如果觉得生成的SciLexer.dll太大的话,可以考虑去除自带的部分语法解析器。比如你打算只用它来高亮C++代码的话,可以:

  1. 进到src目录里,移除除LexCPP.cxx以外的所有Lex*.cxx文件
  2. 执行LexGen.py重建make文件和KeyWords.cxx文件(需要安装Python)。
  3. 重新按前面的方法编译,这样生成的SciLexer.dll就只带有C++语法解析器了,体积也大小减小了(我VC编译的结果是从1.4M减小到 206K)。

启用Scintilla作为编辑控件

要启用Scintilla,首先当然是要加载之前编译的DLL文件啦~~

::LoadLibrary(_T("SciLexer.dll"));

SciLexer.dll加载后会自动以"Scintilla"作为类名注册一个窗体类,我们只要直接用这个类名建立窗体就可以了:

::CreateWindow(_T("Scintilla"),...);
演示(在C++Builder下编写)

由于Scintilla主要是窗体操作,为了减少不必要的窗体代码(主要是偷懒外加推广一下C++Builder,呵呵),这里使用C++Builder 来写演示程序。对于一些C++Builder的VCL库特有的东东,后面会有解释的。

首先新建一个窗体应用程序,

然后在WinMain里载入SciLexer.dll:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    LoadLibrary(_T("SciLexer.dll"));
    ...

最后,在TForm1的构造里建立Scintilla窗体:

#define SCINT_ID 1010
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ::CreateWindow(_T("Scintilla"), NULL, WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_VISIBLE, 0,0,ClientWidth,ClientHeight, Handle, (HMENU)SCINT_ID, HInstance, NULL); }

很简单,是吧?对于Scintilla来说,没什么好解释的了。

这里主要给不了解C++Builder的童鞋介绍一下VCL的东东,以便于接下来的讲解和代码阅读(以及移植到其它编译器中)。

  • TForm1是一个C++Builder自动生成的窗体类,它继承自TForm,可以把它看成是WS_OVERLAPPEDWINDOW风格的HWND的 封装。
  • ClientWidth和ClientHeight是TForm的属性,看名字就知道它是客户区(ClientRect)的宽和高
  • Handle也是TForm的属性,就是该窗体的HWND
  • HInstance不用解释了吧,这是VCL的一个全局变量。

现在,我们的成果是这样的:

2011040719422488.png

现在,看上去还比较土,接下来我们开始配置它,为使它成为可与VS媲美的代码编程器而战!

配置Scintilla的两种方法

配置Scintilla控件是通过向该控件发送配置命令实现的,各种配置命令可以在doc目录下找到(或者是这里http://scintilla.sourceforge.net/ScintillaDoc.html),后面的大部分事情都是在介绍这些配置命令。

有两种方法来发送配置命令,一种是直接使用SendMessage API。另一种是取得直接控制函数,通过函数来执行配置命令。

在Windows下,第二种方法要比第一种快得多。

直接控制函数的定义为:

typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam);

后三个参数和SendMessage的后三个参数一样。
SciFnDirect的第一个参数用于指定具体的Scintilla窗体,它类似于窗体的HWND又不完全相同,姑且也称之为句柄吧。它是用一个配置命 令取得的,下面马上就要讲到。

取得直接控制函数和句柄的方法是:

SciFnDirect fnDirect = (SciFnDirect)SendMessage(hwndEditor,SCI_GETDIRECTFUNCTION,0,0);
sptr_t ptrDirect = (sptr_t)SendMessage(hwndEditor,SCI_GETDIRECTPOINTER,0,0);

取得这两样东西以后,就可以直接执行配置命令了,如:

m_fnDirect(fnDirect, SCI_CLEARALL, 0, 0);

演示代码:编写成员函数SendEditor,用于配置之前建立的Scintilla控件。

#include <Scintilla.h> 
#include <SciLexer.h> 
  
class TForm1 : public TForm 
{ 
__published:    // IDE-managed Components 
private:    // User declarations 
    SciFnDirect m_fnDirect; 
    sptr_t m_ptrDirect; 
public:        // User declarations 
    __fastcall TForm1(TComponent* Owner); 
    sptr_t SendEditor(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0) 
    { 
        return m_fnDirect(m_ptrDirect, iMessage, wParam, lParam); 
    } 
}; 
  
#define SCINT_ID 1010 
__fastcall TForm1::TForm1(TComponent* Owner) 
    : TForm(Owner) 
{ 
    HWND hwndEditor = ::CreateWindow(_T("Scintilla"), 
        NULL, WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_VISIBLE, 
        0,0,ClientWidth,ClientHeight, 
        Handle, 
        (HMENU)SCINT_ID, HInstance, NULL); 
    m_fnDirect = (SciFnDirect)SendMessage(hwndEditor,SCI_GETDIRECTFUNCTION,0,0); 
    m_ptrDirect = (sptr_t)SendMessage(hwndEditor,SCI_GETDIRECTPOINTER,0,0); 
} 
 

让Scintilla支持语法高亮

有了前面的SendEditor控制函数,我们就可以配置语法高亮了,下面这段代码可以使我们的Scintilla控件显示C++语法高亮代码:

const char* g_szKeywords=
    "asm auto bool break case catch char class const "
    "const_cast continue default delete do double "
    "dynamic_cast else enum explicit extern false finally "
    "float for friend goto if inline int long mutable "
    "namespace new operator private protected public "
    "register reinterpret_cast register return short signed "
    "sizeof static static_cast struct switch template "
    "this throw true try typedef typeid typename "
    "union unsigned using virtual void volatile "
    "wchar_t while";
...
SendEditor(SCI_SETLEXER, SCLEX_CPP); //C++语法解析SendEditor(SCI_SETKEYWORDS, 0, (sptr_t)g_szKeywords);//设置关键字// 下面设置各种语法元素前景色SendEditor(SCI_STYLESETFORE, SCE_C_WORD, 0x00FF0000);   //关键字SendEditor(SCI_STYLESETFORE, SCE_C_STRING, 0x001515A3); //字符串SendEditor(SCI_STYLESETFORE, SCE_C_CHARACTER, 0x001515A3); //字符SendEditor(SCI_STYLESETFORE, SCE_C_PREPROCESSOR, 0x00808080);//预编译开关SendEditor(SCI_STYLESETFORE, SCE_C_COMMENT, 0x00008000);//块注释SendEditor(SCI_STYLESETFORE, SCE_C_COMMENTLINE, 0x00008000);//行注释SendEditor(SCI_STYLESETFORE, SCE_C_COMMENTDOC, 0x00008000);//文档注释(/**开头)
 
要支持语法高亮,要做三件事:
一、选定语法解析器

语法解析器用于把一大段代码分解成一个个的单词(token),另外还用于代码折叠的控制(后面会说到)。

选定语法解析器的命令是SCI_SETLEXER,如:

SendEditor(SCI_SETLEXER, SCLEX_CPP);
 

除了SCLEX_CPP以外,还有SCLEX_HTML、SCLEX_PERL、SCLEX_SQL、SCLEX_VB等一大堆,定 义在SciLexer.h里。现代的IDE应该可以定位SCLEX_CPP定义,它周围的SCLEX_XXX就是其它的语法解析器。

另外,也可以用SCI_SETLEXERLANGUAGE命令,如:

SendEditor(SCI_SETLEXERLANGUAGE, 0, (sptr_t)"cpp");

SCI_SETLEXERLANGUAGE接受的是一个字符串参数,这个字符串定义于代码解析器源代码(src\lex*.cxx) 最后面LexerModule开头的那行代码,那里的第三个参数就是。

二、设置关键字

语法解析只负责把代码拆分开,至于哪些是关键字,还得我们来指定。

这种方式带来了些许的灵活性,比如我们要高亮一种自定义的语言,这种语言的风格与C++类似(如Java、C#、php等),我们也 可以选定SCLEX_CPP作为语法解析器,然后定义自己的关键字。(所以不需要把各种解析器都编译进DLL文件里)

设置关键字的命令是SCI_SETKEYWORDS。它的wParam用于指定关键字种类,可以是0~8即9种类型,这样我们可以做 更细致的区分,如把关键字for if和int bool区分显示。lParam指定关键字,以空格分隔。    

三、设置文本元素对应的字体风格

即字体、前景色、背景色、斜体粗体等

设置字体风格的命令以SCI_STYLE作为前缀,这组命令比较多,为了不浪费篇幅,偶这里只列举几个,其它的可以参考这里 (http://scintilla.sourceforge.net/ScintillaDoc.html#StyleDefinition)。

SCI_STYLESETBACK(int styleNumber, int colour) //设置背景色SCI_STYLESETFORE(int styleNumber, int colour) //设置前景色SCI_STYLESETFONT(int styleNumber, char *fontName) //设置字体SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)//设置字号SCI_STYLESETBOLD(int styleNumber, bool bold) //设置粗体
这里的styleNumber是指文本元素,如关键字、行号、控制字串等。前面代码中的SCE_C_XXXX是C++解析器分解出的 语法相关的元素。另外还有STYLE_DEFAULT(默认)、STYLE_LINENUMBER(行号)、STYLE_BRACELIGHT(括号匹 配)、STYLE_BRACEBAD(括号失配)、STYLE_CONTROLCHAR(控制字符)、STYLE_INDENTGUIDE(缩进线)、 STYLE_CALLTIP(调用提示)。
SCI_STYLECLEARALL //把所有文本元素设置成与STYLE_DEFAULT相同的风格

Scintilla文档建议的顺序是先向STYLE_DEFAULT设置一些通用风格,然后再用SCI_STYLECLEARALL 把所有元素风格重置成与STYLE_DEFAULT一致,最后单独设置其它元素。

演示,我们的编辑器支持C++高亮啦!
#include <Scintilla.h> 
#include <SciLexer.h> 
... 
void TForm1::setCppStyle() 
{ 
    const char* szKeywords1= 
        "asm auto break case catch class const " 
        "const_cast continue default delete do double " 
        "dynamic_cast else enum explicit extern false " 
        "for friend goto if inline mutable " 
        "namespace new operator private protected public " 
        "register reinterpret_cast return signed " 
        "sizeof static static_cast struct switch template " 
        "this throw true try typedef typeid typename " 
        "union unsigned using virtual volatile while"; 
    const char* szKeywords2= 
        "bool char float int long short void wchar_t"; 
    // 设置全局风格 
    SendEditor(SCI_STYLESETFONT, STYLE_DEFAULT,(sptr_t)"Courier New"); 
    SendEditor(SCI_STYLESETSIZE, STYLE_DEFAULT,10); 
    SendEditor(SCI_STYLECLEARALL); 
    //C++语法解析 
    SendEditor(SCI_SETLEXER, SCLEX_CPP); 
    SendEditor(SCI_SETKEYWORDS, 0, (sptr_t)szKeywords1);//设置关键字 
    SendEditor(SCI_SETKEYWORDS, 1, (sptr_t)szKeywords2);//设置关键字 
    // 下面设置各种语法元素风格 
    SendEditor(SCI_STYLESETFORE, SCE_C_WORD, 0x00FF0000);   //关键字 
    SendEditor(SCI_STYLESETFORE, SCE_C_WORD2, 0x00800080);   //关键字 
    SendEditor(SCI_STYLESETBOLD, SCE_C_WORD2, TRUE);   //关键字 
    SendEditor(SCI_STYLESETFORE, SCE_C_STRING, 0x001515A3); //字符串 
    SendEditor(SCI_STYLESETFORE, SCE_C_CHARACTER, 0x001515A3); //字符 
    SendEditor(SCI_STYLESETFORE, SCE_C_PREPROCESSOR, 0x00808080);//预编译开关 
    SendEditor(SCI_STYLESETFORE, SCE_C_COMMENT, 0x00008000);//块注释 
    SendEditor(SCI_STYLESETFORE, SCE_C_COMMENTLINE, 0x00008000);//行注释 
    SendEditor(SCI_STYLESETFORE, SCE_C_COMMENTDOC, 0x00008000);//文档注释(/**开头) 
  
    SendEditor(SCI_SETCARETLINEVISIBLE, TRUE); 
    SendEditor(SCI_SETCARETLINEBACK, 0xb0ffff); 
} 
  
__fastcall TForm1::TForm1(TComponent* Owner) 
    : TForm(Owner) 
{ 
    ... 
    setCppStyle(); 
}

看上去不错,如果你愿意,还可以加上当前行高亮功能:

SendEditor(SCI_SETCARETLINEVISIBLE, TRUE);
SendEditor(SCI_SETCARETLINEBACK, 0xb0ffff);
最后,建议把TAB宽度由默认的8改为4(依个人习惯~~) 
SendEditor(SCI_SETTABWIDTH, 4);
现在,我们的成果是这样的:
2011040719491640.png

转载于:https://www.cnblogs.com/superanyi/archive/2011/04/07/2008632.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30323631/article/details/97534840

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签