Click here to Skip to main content
15,881,715 members
Articles / Desktop Programming / MFC
Article

Using Scintilla for syntax coloring in MFC

Rate me:
Please Sign up or sign in to vote.
4.91/5 (45 votes)
29 Jun 20034 min read 409.4K   7.4K   139   109
The article describes how to use the scintilla control in a MFC application to display syntax coloring information

Image 1

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:

// @cmember set the fontname for a style number
   virtual void SetFontname(int nStyle, LPCSTR szFontname);
// @cmember set the fontname height in points for a style number
   virtual void SetFontheight(int nStyle, int nHeight);
// @cmember set the foregroundcolor for a style number
   virtual void SetForeground(int nStyle, COLORREF crForeground);
// @cmember set the backgroundcolor for a style number
   virtual void SetBackground(int nStyle, COLORREF crBackground);
// @cmember set given style to bold
   virtual void SetBold(int nStyle, BOOL bFlag);
// @cmember set given style to bold
   virtual void SetItalic(int nStyle, BOOL bFlag);
// @cmember set given style to bold
   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;
// does notification come from my scintilla window?
   if (phDR !=  NULL &&phDR->hwndFrom == m_wndScintilla.m_hWnd)
   {
      SCNotification *pMsg = 
       (SCNotification*)lParam;
      switch
(phDR->code)       { // called when the document is changed - mark
         document modified
         case
            SCN_SAVEPOINTLEFT: {  CDocument
            *pDoc=
         GetDocument();
         pDoc->SetModifiedFlag(TRUE);
}       break; // called when something changes and 
               // we want to show new indicator state or
         brace matching
         case
            SCN_UPDATEUI:
         {
         m_wndScintilla.UpdateUI();
}       break; // user clicked margin - try
         folding action
         case
            SCN_MARGINCLICK:{ m_wndScintilla.DoDefaultFolding(
                      pMsg->margin,pMsg->position);
         }
         break;
      }
      return TRUE; // we processed the message
   }
   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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: How to Capture the keydown message? Pin
Kelven.Liu26-Apr-05 15:25
Kelven.Liu26-Apr-05 15:25 
GeneralRe: How to Capture the keydown message? Pin
Kelven.Liu26-Apr-05 15:43
Kelven.Liu26-Apr-05 15:43 
AnswerRe: How to Capture the keydown message? Pin
onegray26-Apr-05 22:07
onegray26-Apr-05 22:07 
GeneralRe: How to Capture the keydown message? Pin
Kelven.Liu7-May-05 22:57
Kelven.Liu7-May-05 22:57 
QuestionHow to make a full row select? Like the list control with LVS_EX_FULLROWSELECT style~ Pin
Sam Jiang17-Mar-05 21:13
Sam Jiang17-Mar-05 21:13 
GeneralProblem about line number Pin
billdavidxp2-Mar-05 15:26
billdavidxp2-Mar-05 15:26 
GeneralRe: Problem about line number Pin
mattf063-Mar-05 1:59
mattf063-Mar-05 1:59 
Questionhow to replace line number? Pin
mattf0623-Feb-05 2:44
mattf0623-Feb-05 2:44 
Hi,

I use scintilla control to display logs, and I would like to display time stamp for each row.
Is it possible to replace line-number or to customize it to display what we want, in my case: time stamp.

regards,

Matt
GeneralNewline feed problem Pin
Anonymous27-Jan-05 9:51
Anonymous27-Jan-05 9:51 
GeneralWhy crashed! Pin
zhou_wz24-Nov-04 19:00
zhou_wz24-Nov-04 19:00 
GeneralRe: Why crashed! Pin
Kurt M. S.8-Jun-05 2:20
Kurt M. S.8-Jun-05 2:20 
QuestionOCX version of this?? Pin
Anonymous24-Oct-04 1:18
Anonymous24-Oct-04 1:18 
AnswerRe: OCX version of this?? Pin
toffy26-Oct-04 20:26
toffy26-Oct-04 20:26 
GeneralRe: OCX version of this?? Pin
avins_7526-Oct-04 22:25
avins_7526-Oct-04 22:25 
GeneralSyntax HTML so simple!!! Pin
Tcpip20056-Jul-04 3:51
Tcpip20056-Jul-04 3:51 
GeneralRe: Syntax HTML so simple!!! Pin
toffy6-Jul-04 4:55
toffy6-Jul-04 4:55 
GeneralRe: Syntax HTML so simple!!! Pin
Tcpip20056-Jul-04 5:28
Tcpip20056-Jul-04 5:28 
GeneralUnicode and non-English text. Pin
S.Cartwright29-Jun-04 22:03
S.Cartwright29-Jun-04 22:03 
GeneralCompiling in VC7.1.3091 Pin
farlongchen14-Jun-04 23:13
farlongchen14-Jun-04 23:13 
GeneralRe: Compiling in VC7.1.3091 Pin
leven4-Feb-05 8:31
leven4-Feb-05 8:31 
GeneralMicrosoft Script Controller Pin
repekcan1-Jun-04 3:29
repekcan1-Jun-04 3:29 
GeneralFlickering in editor during resize Pin
dugbug28-May-04 8:56
dugbug28-May-04 8:56 
GeneralRe: Flickering in editor during resize Pin
YoSilver19-Nov-04 17:44
YoSilver19-Nov-04 17:44 
QuestionHow to implement smart indent Pin
yxh2-May-04 17:14
yxh2-May-04 17:14 
AnswerRe: How to implement smart indent Pin
YoSilver19-Nov-04 18:35
YoSilver19-Nov-04 18:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.