SubClassing

Shell Reparenting

Scintilla in  VB


Before I begin let me state that yes I am aware that there is an activex control which wraps some of Scintilla's features. However like any such control it lacks many of the features Scintilla offers, and isn't updated to support any new features Scintilla adds. Along with that it has several fairly large bugs in it. My goal in this tutorial is to explain how to either use Scintilla without a wrapper or learn enough about how to make use of it to add any features that the control lacks.

What is Scintilla

For those of you who havn't seen Scintilla yet Check it out here. I take absolutly no credit for Scintilla. I didn't write it, nor have I even modified it. I'll admit it's code goes way beyond my own abilities. As for what it is? Well it's an excellent, free and opensource Library providing extensive support for syntax highlighting and it even offers code folding. It's quite stable, and cross platform. You can make use of it from just about any language that supports API calls in windows. This means yes VB can make use of it :)

The total source code for this tutorial is included with this submission. Before we get started you should download the source as this code makes use of 2 modules. These modules are fairly basic and very self explanitory. The one is some ini reading and writing code. Credit for this module goes total an author on PSC. Unfortunatly I was unable to find the original on PSC as I've had it quite some time, so I don't know who to name credit to so I'll just leave it at I didn't write it. The second module is actually from the ScintillaVB control and it's some of Scintilla's major constants.

Starting Out The first thing you will need to do is create an application. Name the form whatever you want. This is not important. Add the following api's at the top of the form's source code. You can also make them public and place them in a module if you want.

Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Integer
Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function SetFocusEx Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wp As Long, ByVal lp As Long) As Long
Private Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wp As Long, ByVal lp As Any) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal m As Long, ByVal left As Long, ByVal top As Long, ByVal width As Long, ByVal height As Long, ByVal flags As Long) As Long

Dim sci As Long

Those are just a few API's we will need for doing this work. Now let's move on to the form load event. This is where we will actually make it all happen.

    'Dim str as string.  This variable will do nothing more than hold
    'a default piece of text.
    Dim str As String
   
    'Here we actually load the DLL into memory.  sciLexer.dll is the
    'Scintilla DLL
    LoadLibrary ("SciLexer.DLL")
   
    'Here we create a window using the Scintilla library which we
    'created with the previous line.  We assign it a generic name,
    'set it as a child and visible.  Give it's parents Handle, and
    'set it to the application in question and assign the newly created
    'handle to the variable sci
    sci = CreateWindowEx(WS_EX_CLIENTEDGE, "Scintilla", _
        "TEST", WS_CHILD Or WS_VISIBLE, 0, 0, 200, 200, _
        frmMain.hwnd, 0, App.hInstance, 0)
       
    'Here just for fun we are setting the background color for highlighting
    'to a different color
    SendMessage sci, SCI_SETSELBACK, 1, &HFFEFD0
   
    'Give the str variable a string.  This will be placed in the new Scintilla
    'Window as text.
    str = "int Main(){" & Chr(10) & "  printf('Hello world\n\r');" & Chr(10) & "  return 0;" & Chr(10) & "}"
   
    'Add the text that we assigned to the string variable to the scintilla window
    SendMessageString sci, SCI_ADDTEXT, Len(str), str
   
    'Load a custom highlighter.  This is the fun part
    LoadHighlighter
   
    'Setfocus to the scintilla window
    SetFocusEx sci

The variables explain what each line does. But basicly as a recap what were doing here is loading the DLL into memory, Creating a window using that library, and Setting some text to it. The LoadHighlighter code does some of the major stuff. The rest of the code is as follows:

Private Sub Form_Resize()
    'Resize window
    SetWindowPos sci, 0, 2, 2, frmMain.width / 15 12, _
        frmMain.height / 15 30, 0
End Sub

Public Sub LoadHighlighter()
  'Declare a few variables we will use
  Dim i As Long
  Dim s As String
  Dim m As Long
  Dim l
  Dim d() As String
 
  'Clear all the scintilla styles
  SetScintilla SCI_STYLECLEARALL, 0, 0
 
  'Set the keywords to the scintilla control
  For i = 0 To 7
    s = ReadINI("data", "Keywords[" & i & "]", App.Path & "\CPP.chl")
    SetScintillaString SCI_SETKEYWORDS, i, s
  Next i
 
  'Set the styles.
  For i = 0 To 127
    s = ReadINI("data", "style[" & i & "]", App.Path & "\CPP.chl")
    If s <> "" Then
      d = Split(s, ":")
      l = Hex(d(9))
      m = Int(d(9))
      SetScintilla SCI_STYLESETSIZE, i, 12
      If (d(0) = "B") Then
        SetScintilla SCI_STYLESETBOLD, i, 1
      Else
        SetScintilla SCI_STYLESETBOLD, i, 0
      End If
      SetScintilla SCI_STYLESETFORE, i, m
    End If
  Next i
  'SendMessageString sci, SCI_SETKEYWORDS, 0, "if then else"
  SetScintilla SCI_SETLEXER, 3, 0
End Sub

Private Sub SetScintillaString(lSCIData, lDataNum As Long, strWords As String)
  'Sends a message containing a string to the scintilla window
  SendMessageString sci, lSCIData, lDataNum, strWords
End Sub


Private Sub SetScintilla(lWhatToDo As Long, lNumber As Long, lValue As Long)
  'Sends a message containing a long value to the scintilla window
  SendMessage sci, lWhatToDo, lNumber, lValue
End Sub

Recap

Essentially everything is sent to scintilla threw SendMessage or SendMessageString. The 2 functions, SetScintilla and SetScintillaString just wrap around those 2 api calls to make what your sending to scintilla a little easier to understand. Examples of which to use would be to set the keywords you'd use SetScintillaString. To set the colors or any of the styles IE forecolor, backcolor, bold, italic, etc. You'd use SetScintilla.

In the sample source for setting the keywords we use This: SetScintillaString SCI_KEYWORDS, I, STR

* SCI_KEYWORDS is a constant which tells scintilla you want to set the keywords.

* I is just a number. Scintilla supports up to 8 sets of keywords so what were doing here is in LoadHighlighter were going 0 to 7 and reading the keywords out of each keyword number and I here tells scintilla we are setting that set of keywords.

* STR is the string which we have set using the ini reading code to the appropriate Keywords. In the sample source for setting the forecolor we use This:

SetScintilla SCI_STYLESETFORE, i, m

* SCI_STYLESETFORE is a constant which when sent to scintilla tells it were setting a forecolor to one of the styles. * i is a number from 0 to 127. Scintilla supports a total of 128 style bits. * m is the value we are setting the forecolor to. VB color values will work for this.

Once again this is a really basic tutorial. You can do a ton of things with Scintilla. Because of it's setup you can have embeded language IE ASP and PHP within HTML, code folding such as what the Visual Studio .Net supports, and much more. It also makes it incredibly easy to add exporting features so you can export the highlighted source code to another format IE HTML or RTF. In fact all the highlighting involved in the code on this tutorial was done using cEditMX which utilizes Scintilla.

I highly recomend you go to The Scintilla Site and check out all the great information available as well as the dll itself which is updated on a regular basis. Also check out ScintillaVB Control. It is a good starting point, it just needs a lot of work, especially in it's overall support for scintilla. Hopefully with this tutorial you got a basic understanding of how it all works so you can do just that.

This content was originally created by the guy who created cEditMX which uses Scintilla.  He has long since abandoned the effort in this area.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *