日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/4/16 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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中的简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。