Introduction
Using syntax coloring when editing source code makes navigating the code much easier. If you want to put
syntax coloring to work in your application this seemed to be a complicated tasks. Neil Hodgson from
www.scintilla.org has
written an excellent multiplatform editing control for that task. It is for use on Windows and Linux and does not use MFC. If
you want to integrate this control into your application you have to build a MFC wrapper to use it in a CView
derived class or in a
dialog box. This article describes how to do that by implementing a sample application which handles most of the common tasks.
Background
Syntax coloring uses different colors for portions of a text. Scintilla uses styles for
that task. Each style has a foreground color, a background color and font attributes to draw the text. If text is loaded into
the control a lexer module scans the text and assigns numbered styles to known keywords, strings, numbers or comments. There are a lot
of lexer modules for common languages (HTML, XML, C++, Java etc.) integrated into scintilla. Another concept of scintilla is source
folding. Folding hides or redisplays a portion of source code to make code easier to navigate. Think of folding as a treeview of your source
- if you click on a folding symbol at an "else" statement, the body of the statement is hidden and you you get a visual indicator
(a +-sign) to expand it again.
Using the scintilla control
You may derive your CView
class from CScintillamfcView
or use the CScintillaWnd
class provided.
Loading Scintilla
Scintilla comes as a DLL in two flavors - simple scintilla without advanced lexers as
scintilla.dll
or as SciLexer.dll with all built-in lexers for HTML, XML, C++ etc.
Load the DLL in your
CWinApp::InitInstace()
function:
HMODULE m_hDll = NULL;
m_hDll = ::LoadLibrary(_T("SciLexer.dll"));
In your CWinApp:.ExitInstance()
function unload the
Library by calling:
AfxFreeLibrary(m_hDll);
Creating the Window and setting a lexer
Scintilla is NOT derived from CEdit
or CRichEdit
! You
have to use a member variable in you CView
derived class and create the
Scintilla window yourself by calling:
int CScintillamfcView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndScintilla.Create(_T("Title"), WS_CHILD | WS_VISIBLE,
CRect(0,0,0,0), this, 10000))
{
return -1;
}
return 0;
}
You have to size the scintilla window to fit the size of
the client area of your view:
void CScintillamfcView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (m_wndScintilla.GetSafeHwnd())
{
m_wndScintilla.MoveWindow(0, 0, cx, cy);
}
}
The scintilla window is now ready to use. If you want some reasonable defaults call the CScintillaWnd::Init()
to
set some styles and to allow brace highlighting. The most important part now is to find a lexer which fits your source code.
If you load a file, the view tries to find a matching lexer from the file extension of the document by calling CScintillaWnd::LoadFile()
:
void CScintillamfcView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CDocument *pDoc = GetDocument();
CString strTitle = pDoc->GetPathName();
m_wndScintilla.Init();
m_wndScintilla.LoadFile(strTitle);
}
Exploring Scintilla styles
If you load a C++ source file into the scintilla mfc application and move the cursor around you will notice a status bar display indicating
"Style:xxx". If you move the cursor into a quoted string this display may change to "Style:6". This means the
lexer for the C++ language has detected a quoted string. If you pull down the options menu and select a new
foreground color "red" for this style,
all quoted strings within the control turn red. Scintilla uses up to 128 styles depending on the language used. Most of languages
use only up to 32 styles, but HTML with embedded scripting needs all 128 styles. If you want to let the user customize
the styles for a language you have to take a look at the supplied lexer source code to find out which style is used for what language construct. Nearly
all lexers use up to 8 wordlists of keywords to find language specific keywords like while, if, else etc. The scintilla mfc application has
a menu command to try that for C++ keywords. After setting the default wordlist from the dialog to wordlist (0). All C++ keywords should turn blue. You
can set style attributes by calling the following CScintillaWnd
functions:
virtual void SetFontname(int nStyle, LPCSTR szFontname);
virtual void SetFontheight(int nStyle, int nHeight);
virtual void SetForeground(int nStyle, COLORREF crForeground);
virtual void SetBackground(int nStyle, COLORREF crBackground);
virtual void SetBold(int nStyle, BOOL bFlag);
virtual void SetItalic(int nStyle, BOOL bFlag);
virtual void SetUnderline(int nStyle, BOOL bFlag);
Exploring Scintilla source folding
The status bar of the scintilla mfc applications displays
"Folding levels". If you look at the left margin of the display of a C++ file
you see some minus signs in the margin. If you click on that sign it turns into
a plus sign and some portions of the source code disappear. This is called
"source folding". To activate folding you have to process notification messages
in your CView
derived class. Scintilla sends a notification if the user clicks
in one of the margins supplied by the control. You have to capture this
notification and process them. The CScintillaWnd
class has some standard
function to process standard folding and brace highlighting for you. You must
capture the notification in a OnNotify
handler:
BOOL CScintillamfcView::OnNotify(WPARAM wParam,
LPARAM lParam, LRESULT* pResult)
{
NMHDR *phDR;
phDR = (NMHDR*)lParam;
if (phDR != NULL &&phDR->hwndFrom == m_wndScintilla.m_hWnd)
{
SCNotification *pMsg =
(SCNotification*)lParam;
switch
(phDR->code) {
document modified
case
SCN_SAVEPOINTLEFT: { CDocument
*pDoc=
GetDocument();
pDoc->SetModifiedFlag(TRUE);
} break;
brace matching
case
SCN_UPDATEUI:
{
m_wndScintilla.UpdateUI();
} break;
folding action
case
SCN_MARGINCLICK:{ m_wndScintilla.DoDefaultFolding(
pMsg->margin,pMsg->position);
}
break;
}
return TRUE;
}
return CWnd::OnNotify(wParam, lParam, pResult);
}
More Scintilla features
Scintilla is a solid piece of work and has more features than discussed here. If you want to find out more about
call tips, bookmarks, search and replace with regular expressions, auto-complete and macro recording you have to take a look at the
www.scintilla.org website and the HTML docs about the messages used by scintilla.
History
- 06/07/2003 initial release 1.1 for scintilla 1.53.