mfc c语言 编辑器,语法高亮编辑控件Scintilla在MFC中的简单使用
项目中要使用代码编辑器,搜索之后,发现了强大的编辑器控件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中的简单使用相关推荐
- MFC界面控件BCGControlBar v33.3 - 编辑控件功能升级
BCGControlBar库拥有500多个经过全面设计.测试和充分记录的MFC扩展类. 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间. BCGControlBar专业版和B ...
- BCGControlBar Pro for MFC v13.3现已发布:着重改进图表、属性/编辑控件等,打造全面、易上手的MFC库
亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC v31.3正式发布啦! BCGControlBar Pro for MFC v31.3 ...
- 手把手带你实现Markdown编辑器语法高亮
如果喜欢不如给个star鼓励一下:ZYMarkdownEditor 什么是正则表达式? iOS开发如何使用正则表达式? 使用正则表达式匹配Markdown 性能劣势? 配合YYTextView实现语法 ...
- vs中c语言图形显示出来,VS2010+Opencv+MFC读取图像和视频显示在Picture控件
VS2010+Opencv+MFC读取图像和视频显示在Picture控件,供大家参考,具体内容如下 1.新建MFC对话框应用程序. 其余选项默认,单击完成,创建出对话框应用程序.删掉原来自带的一些控件 ...
- VS2019/MFC编程入门教程:组合框控件Combo Box
上一节讲了列表框控件ListBox的使用,本节主要讲解组合框控件Combo Box.组合框同样相当常见,例如,在Windows系统的控制面板上设置语言或位置时,有很多选项,用来进行选择的控件就是组合框 ...
- VS2010/MFC编程入门之三十(常用控件:树形控件Tree Control 上)
前面两节为大家讲了列表视图控件List Control,这一节开始介绍一种特殊的列表--树形控件Tree Control. 树形控件简介 树形控件在Windows系统中是很常见的,例如资源管理器左侧的 ...
- TeeChart替代品,MFC下好用的高速绘图控件-(Hight-Speed Charting)
相关链接: C++ GUI 绘图控件目录 MFC VS2010 使用TeeChart绘图控件 - 之一 - 控件和类的导入 VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图, ...
- 如何用 Swift 语言构建一个自定控件
本文译自:How To Make a Custom Control in Swift 用户界面控件是所有应用程序重要的组成部分之一.它们以图形组件的方式呈现给用户,用户可以通过它们与应用程序进行交互. ...
- VCL组件之编辑控件
VCL组件之编辑控件 Note 以后将用两种方式提及组件,以组件的名称或定义组件的VCL类的名称.可以说"Label组件用于--"或说"TLabel用于--", ...
最新文章
- python使用符号 表示单行注释-【转】Pyhton 单行、多行注释符号使用方法及规范...
- libevent之Reactor模式详解
- Binary Tree Level Order Traversal
- 【收集】几款浏览器兼容性测试工具
- [vue] 组件和插件有什么区别?
- MVC.Net:将Reponse Redirect从Get变为Post
- python下绘制叠加区域图和叠加柱状图
- 快安排!QQ更新被吐槽低龄化 但这个功能让微信用户们“羡慕”哭了
- (转)非常完善的Log4net详细说明
- 图像复原技术及其MATLAB实现
- http协议及基于http协议的文件下载
- WordPiece是如何基于词表对文本进行切分的
- 输入身份证判断性别python最后一位是英文怎么写_身份证号码最后一位,是表示性别用的吗?...
- K210入门必看(MAIX DOCK)(一)
- php 判断华为手机,一招教你如何看穿华为手机的内存类型
- 华尔街见闻-2016年2月
- CSP-J2019普及组复赛T4:加工零件
- 设置css手机屏幕 media all,手机屏幕自适应之css写法@media
- 台式计算机不休眠,台式机不休眠的解决方法
- Monthly Expense