项目中要使用代码编辑器,搜索之后,发现了强大的编辑器控件Scintilla。

1.简介

Scintilla是一款开源的语法高亮编辑器控件,官方网站:http://www.scintilla.org/。Scintilla是最优秀的编辑控件之一,实现了语法高亮,代码折叠,书签,自动完成等等诸多功能,速度快,源代码也比较好理解,易于扩展,易于增加对新语言的支持。 比较著名的scite,Notepad++,Notepad2都是基于Scintilla开发的。Scintilla提供了Win32版本和Linux版本,在Windows下,它是一个窗体控件,对它的控制都通过发送消息来完成:

LRESULT SendMessage(HWND hWndScintilla,UINT Msg,WPARAM wParam,LPARAM lParam);

Scintilla提供了大量的消息API,每个消息可以带有0个、1个或2个参数。SendMessage函数中的消息,通常带有2个参数:wParam和lParam,没有使用的参数,则设置为0。对于大多数SCI_SETxxxxx设置类消息,都会有一个对应的SCI_GETxxxxx查询消息。

下面的图片是一个数控NC程序编辑器Demo:

2.在MFC中的简单使用

2.1载入Scintilla链接库

首先,将SciLexer.dll复制到项目中。

a.在CwinApp下添加成员:

HMODULE m_hDll;

并初始化为NULL。

b.在InitInstance中载入DLL:

C++代码

m_hDll = LoadLibrary(_T("SciLexer.dll"));

if(m_hDll==NULL)

{

AfxMessageBox("LoadLibrary SciLexer.dll failure...");

}

c.在ExitInstance中卸载DLL:

C++代码

if (m_hDll != NULL)

{

FreeLibrary(m_hDll);

}

2.2 创建一个封装Scintilla的类 — CScintillaWnd

C++代码

//-------------------------------------------------------

// ScintillaWnd.h

#pragma once

//注意:这俩文件来自Scintilla的include目录

#include "Scintilla.h"

#include "SciLexer.h"

// CScintillaWnd

classCScintillaWnd :publicCWnd

{

DECLARE_DYNAMIC(CScintillaWnd)

public:

CScintillaWnd();

virtual~CScintillaWnd();

protected:

DECLARE_MESSAGE_MAP()

public:

virtualBOOLCreate(

DWORDdwExStyle,DWORDdwStyle,constRECT& rect,

CWnd* pParentWnd,UINTnID);

};

//-------------------------------------------------------

// ScintillaWnd.cpp : 实现文件

#include "stdafx.h"

#include "ColorTextBox.h"

#include "ScintillaWnd.h"

// CScintillaWnd

IMPLEMENT_DYNAMIC(CScintillaWnd, CWnd)

CScintillaWnd::CScintillaWnd()

{

}

CScintillaWnd::~CScintillaWnd(){}

BEGIN_MESSAGE_MAP(CScintillaWnd, CWnd)

END_MESSAGE_MAP()

// CScintillaWnd 消息处理程序

BOOLCScintillaWnd::Create(DWORDdwExStyle,DWORDdwStyle,constRECT& rect, CWnd* pParentWnd,UINTnID)

{

// TODO: 在此添加专用代码和/或调用基类

returnCWnd::CreateEx(dwExStyle,"Scintilla","",dwStyle,rect,pParentWnd,nID);

}

2.3 CScintillaWnd类的使用举例

将CScintillaWnd类的对象作为目标窗体类的一个成员,比如某个对话框CColorTextBoxDlg 。

C++代码

class CColorTextBoxDlg : public CDialog

{

// 构造

public:

CColorTextBoxDlg(CWnd* pParent = NULL);// 标准构造函数

// 对话框数据

enum{ IDD = IDD_COLORTEXTBOX_DIALOG };

protected:

virtualvoidDoDataExchange(CDataExchange* pDX);

//..

public:

CScintillaWnd m_ScintillaWnd;

afx_msgintOnCreate(LPCreateSTRUCT lpCreateStruct);

afx_msgvoidOnSize(UINTnType,intcx,intcy);

};

a.在CcolorTextBoxDlg的OnCreate中创建Scintilla窗口:

C++代码

m_ScintillaWnd.Create(

WS_EX_CLIENTEDGE,

WS_CHILD | WS_VISIBLE,

CRect(0,0,lpCreateStruct->cx,lpCreateStruct->cy),

this,10000);

b.在CcolorTextBoxDlg的OnSize中调整Scintilla窗口的大小:

C++代码

m_ScintillaWnd.MoveWindow(0,0,cx,cy);

2.4 接收来自Scintilla控件的通知

当Scintilla控件发生事件时,会用WM_NOTITY消息通知父窗体。

2.4.1在MFC中

C++代码

CxxxxWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)

{

// TODO: 在此添加专用代码和/或调用基类

LPNMHDR pnmh = (LPNMHDR)lParam;

structSCNotification* scn = (structSCNotification*)lParam;

switch(pnmh->code)

{

caseSCN_CHARADDED:

/* Hey, Scintilla just told me that a new */

/* character was added to the Edit Control.*/

/* Now i do something cool with that char. */

break;

//case ...

}

}

2.4.2在SDK中

C++代码

NMHDR *lpnmhdr;

//[...]

caseWM_NOTIFY:

lpnmhdr = (LPNMHDR) lParam;

if(lpnmhdr->hwndFrom==hwndScintilla)

{

switch(lpnmhdr->code)

{

caseSCN_CHARADDED:

/* Hey, Scintilla just told me that a new */

/* character was added to the Edit Control.*/

/* Now i do something cool with that char. */

break;

}

}

break;

2.5 例:行号的显示(MFC)

要显示行号,首先需要在m_ScintillaWnd创建后立即调用以下函数,并在Scintilla通知主窗口SCN_MODIFIED,SCN_ZOOM时调用:

C++代码

void UpdateLineNumberWidth(void)

{

chartchLines[32];

intiLineMarginWidthNow;

intiLineMarginWidthFit;

wsprintf(tchLines," %i ",

m_ScintillaWnd.SendMessage(SCI_GETLINECOUNT,0,0));

iLineMarginWidthNow = m_ScintillaWnd.SendMessage(

SCI_GETMARGINWIDTHN,0,0);

iLineMarginWidthFit = m_ScintillaWnd.SendMessage(

SCI_TEXTWIDTH,STYLE_LINENUMBER,(LPARAM)tchLines);

if(iLineMarginWidthNow != iLineMarginWidthFit)

{

m_ScintillaWnd.SendMessage(SCI_SETMARGINWIDTHN,0,

iLineMarginWidthFit);

}

}

BOOLOnNotify(

WPARAMwParam,LPARAMlParam,LRESULT* pResult)

{

LPNMHDR pnmh = (LPNMHDR)lParam;

structSCNotification* scn = (structSCNotification*)lParam;

switch(pnmh->code)

{

caseSCN_MODIFIED:

//This notification is sent when the text or

//styling of the document changes or is about

//to change

caseSCN_ZOOM:

//This notification is generated when the user

//zooms the display using the keyboard or the

//SCI_SETZOOM method is called.

UpdateLineNumberWidth();

break;

}

returnCDialog::OnNotify(wParam, lParam, pResult);

}

2.6 例:设置文本,打开已有文件(MFC)

C++代码

void OnMenuFileOpen()

{

CFileDialog fDlg(TRUE);

if(fDlg.DoModal()==IDOK)

{

char*pBuffer;

CString strFilePath=fDlg.GetPathName();

CStdioFile stdFile(strFilePath,CFile::modeRead);

UINTnFileLength=stdFile.GetLength();

pBuffer=newchar[nFileLength+1];

nFileLength=stdFile.Read(pBuffer,nFileLength);

stdFile.Close();

if(nFileLength>0)

{

if(m_ScintillaWnd.SendMessage(SCI_GETREADONLY,0,0))

{

m_ScintillaWnd.SendMessage(SCI_SETREADONLY,FALSE,0);

}

m_ScintillaWnd.SendMessage(SCI_CANCEL,0,0);

m_ScintillaWnd.SendMessage(SCI_SETUNDOCOLLECTION,0,0);

m_ScintillaWnd.SendMessage(SCI_EMPTYUNDOBUFFER,0,0);

//如果文本没有只读属性,则清除所有文字。

m_ScintillaWnd.SendMessage(SCI_CLEARALL,0,0);

//从所有行中删除标记,若markerNumber=-1,则删除所有标记。

m_ScintillaWnd.SendMessage(SCI_MARKERDeleteALL,

(WPARAM)-1,0);

m_ScintillaWnd.SendMessage(SCI_ADDTEXT,

nFileLength,(LPARAM)pBuffer);

m_ScintillaWnd.SendMessage(SCI_SETUNDOCOLLECTION,1,0);

m_ScintillaWnd.SendMessage(EM_EMPTYUNDOBUFFER,0,0);

m_ScintillaWnd.SendMessage(SCI_SETSAVEPOINT,0,0);

m_ScintillaWnd.SendMessage(SCI_GOTOPOS,0,0);

m_ScintillaWnd.SendMessage(SCI_CHOOSECARETX,0,0);

UpdateLineNumberWidth();

}

delete[] pBuffer;

}

}

2.7 例:设置默认字体以及字体大小(MFC)

C++代码

void SetDefaultFont(int nSize,const char* face)

{

m_ScintillaWnd.SendMessage(SCI_STYLESETFORE,

STYLE_DEFAULT, RGB(0x00,0x00,0x00));

m_ScintillaWnd.SendMessage(SCI_STYLESETBACK,

STYLE_DEFAULT, RGB(0xff,0xff,0xff));

m_ScintillaWnd.SendMessage(SCI_STYLESETSIZE,

STYLE_DEFAULT, nSize);

m_ScintillaWnd.SendMessage(SCI_STYLESETFONT,

STYLE_DEFAULT,reinterpret_cast(face));

}

2.8 Lexer的编写

要实现一个新的语言(比如M语言)的语法高亮,需要在源代码级别对Scintilla做一点修改,并重新编译Scintilla:

2.8.1加入一个源代码文件:

LexM.cxx

2.8.2实现如下函数:

C++代码

static void ColouriseMDoc (

unsigned int startPos,

int length,

int initStyle,

WordList *keywordlists[],

Accessor &styler);

styler参数是一个Accessor对象,Lexer必须用这个对象来访问将要颜色化的文本。

Lexer用styler.SafeGetCharAt(i)来取得位置在i的字符;

startPos和length参数表示需要颜色化的文本的范围;Lexer为所有在startPos到startPos+length范围内的字符决定恰当的颜色。

initStyle参数表示最初的状态,也就是startPos之前一个字符的状态。状态也是表示指定范围内的文本的颜色。

注意:  startPos位置的字符被事先假定为一行的开始,如果新的一行终止了inisStyle状态Lexer应该进入默认状态(或者说任何状态应该在initStyle之后).

keywordlists参数指定Lexer应该识别的关键词,WordList对象包含识别关键词的方法,Present Lexers用一个classifyWordLLL函数来识别关键词.这些函数展示怎么用keywordlists参数去识别关键词.

2.8.3通过如下方式调用该函数:

C++代码

LexerModule lmM(SCLEX_M, ColouriseMDoc, "m", 0, asmWordListDesc);

2.8.4在KeyWords.cxx文件中调用LINK_LEXER(lmM)宏。

3.备注

mfc c语言 编辑器,语法高亮编辑控件Scintilla在MFC中的简单使用相关推荐

  1. MFC界面控件BCGControlBar v33.3 - 编辑控件功能升级

    BCGControlBar库拥有500多个经过全面设计.测试和充分记录的MFC扩展类. 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间. BCGControlBar专业版和B ...

  2. BCGControlBar Pro for MFC v13.3现已发布:着重改进图表、属性/编辑控件等,打造全面、易上手的MFC库

    亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC v31.3正式发布啦! BCGControlBar Pro for MFC v31.3 ...

  3. 手把手带你实现Markdown编辑器语法高亮

    如果喜欢不如给个star鼓励一下:ZYMarkdownEditor 什么是正则表达式? iOS开发如何使用正则表达式? 使用正则表达式匹配Markdown 性能劣势? 配合YYTextView实现语法 ...

  4. vs中c语言图形显示出来,VS2010+Opencv+MFC读取图像和视频显示在Picture控件

    VS2010+Opencv+MFC读取图像和视频显示在Picture控件,供大家参考,具体内容如下 1.新建MFC对话框应用程序. 其余选项默认,单击完成,创建出对话框应用程序.删掉原来自带的一些控件 ...

  5. VS2019/MFC编程入门教程:组合框控件Combo Box

    上一节讲了列表框控件ListBox的使用,本节主要讲解组合框控件Combo Box.组合框同样相当常见,例如,在Windows系统的控制面板上设置语言或位置时,有很多选项,用来进行选择的控件就是组合框 ...

  6. VS2010/MFC编程入门之三十(常用控件:树形控件Tree Control 上)

    前面两节为大家讲了列表视图控件List Control,这一节开始介绍一种特殊的列表--树形控件Tree Control. 树形控件简介 树形控件在Windows系统中是很常见的,例如资源管理器左侧的 ...

  7. TeeChart替代品,MFC下好用的高速绘图控件-(Hight-Speed Charting)

    相关链接: C++ GUI 绘图控件目录 MFC VS2010 使用TeeChart绘图控件 - 之一 - 控件和类的导入 VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图, ...

  8. 如何用 Swift 语言构建一个自定控件

    本文译自:How To Make a Custom Control in Swift 用户界面控件是所有应用程序重要的组成部分之一.它们以图形组件的方式呈现给用户,用户可以通过它们与应用程序进行交互. ...

  9. VCL组件之编辑控件

    VCL组件之编辑控件 Note 以后将用两种方式提及组件,以组件的名称或定义组件的VCL类的名称.可以说"Label组件用于--"或说"TLabel用于--", ...

最新文章

  1. python使用符号 表示单行注释-【转】Pyhton 单行、多行注释符号使用方法及规范...
  2. libevent之Reactor模式详解
  3. Binary Tree Level Order Traversal
  4. 【收集】几款浏览器兼容性测试工具
  5. [vue] 组件和插件有什么区别?
  6. MVC.Net:将Reponse Redirect从Get变为Post
  7. python下绘制叠加区域图和叠加柱状图
  8. 快安排!QQ更新被吐槽低龄化 但这个功能让微信用户们“羡慕”哭了
  9. (转)非常完善的Log4net详细说明
  10. 图像复原技术及其MATLAB实现
  11. http协议及基于http协议的文件下载
  12. WordPiece是如何基于词表对文本进行切分的
  13. 输入身份证判断性别python最后一位是英文怎么写_身份证号码最后一位,是表示性别用的吗?...
  14. K210入门必看(MAIX DOCK)(一)
  15. php 判断华为手机,一招教你如何看穿华为手机的内存类型
  16. 华尔街见闻-2016年2月
  17. CSP-J2019普及组复赛T4:加工零件
  18. 设置css手机屏幕 media all,手机屏幕自适应之css写法@media
  19. 台式计算机不休眠,台式机不休眠的解决方法
  20. Monthly Expense

热门文章

  1. 使用Poco实现插件方式加载动态库
  2. 人人都是产品经理 2
  3. JAVA WEB开发环境与搭建
  4. Spring Boot 之发送邮件
  5. 公平锁与非公平锁源码对比
  6. oracle中将number类型毫秒值转为时间类型
  7. 65条最常用正则表达式
  8. Dynamics CRM2013 任务列表添加自定义按钮
  9. Unity 4.3 2D 教程:新手上路
  10. windows phone7---MVVM模式