Example44: Direct Access (Speed Tip)

Category: Controls - Scintilla

Date: 03-28-2012

Return to Index


 
'In most circumstances, the use of SendMessage provides adequate performance. But when
'message frequency is high, performance can suffer. As an alternative, Scintilla provides
'an exposed function which can call it's internal (non-exported) functions directly. By
'avoiding the overhead of the Windows messages, speed improvements of ~25% or so can be
'realized.
 
'The process involves getting a points to the message handling function of Scintilla, and
'sending your messages to that function instead of through the Windows SendMessage function.
 
 
'Primary Code:
'To get the pointer to the Scintilla message handling function, use this message:
 
   ptrSci = SendMessage(hEdit,%SCI_GETDIRECTPOINTER,0,0) 'msg handler pointer
 
'The function that calls the Scintilla message handler must also be declared. However,
'this declaration is found in the INCLUDE file, so you don't need it in your PowerBASIC app.
 
    Declare Function SciMsg LIB "SCILEXER.DLL" ALIAS "Scintilla_DirectFunction" _
                       (ByVal pSciWndData AS DWord, ByVal wMsg AS DWord, _
                        ByVal wParam AS DWord, ByVal lParam As LongAs Long
 
'Now, use the function SciMsg to replcae SendMessage.  These next two statements
'are equivalent, but the second one is faster (SciMsg is faster than SendMessage):
 
      iResult = SendMessage(hSci,   %SCI_GETFOLDLEVEL, LineNumber, 0)
      iResult = SciMsg(ptrSci, %SCI_GETFOLDLEVEL, LineNumber, 0)
 
'The speed improvement generally on the order of ~25%, but as they say, your milage
'may vary depending on which messages you send and how frequently they are sent.
 
 
'Compilable Example:
'This example compares the time to run through 50K iterations of the SendMessage and
'direct access methods.
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
#Include "Win32API.inc"
#Include "scintilla_gb.inc"
 
%ID_Sci = 1000 : %ID_BtnA = 1001 : %ID_BtnB = 1002
Global hDlg, hSci, hLib, ptrSci As DWord
 
Function PBMain() As Long
   hLib = LoadLibrary("SCILEXER.DLL")
   Dialog New Pixels, 0, "Scintilla Example",300,300,300,150, %WS_OverlappedWindow To hDlg
   Control Add Button, hDlg, %ID_BtnA, "SendMessage", 10,10,80,20, %WS_Child Or %WS_Visible
   Control Add Button, hDlg, %ID_BtnB, "Direct Access", 10,40,80,20, %WS_Child Or %WS_Visible
   Control Add "Scintilla", hDlg, %ID_Sci, "", 100,10,180,130, %WS_Child Or %WS_Visible
   Control Handle hDlg, %ID_Sci To hSci     'get handle to Scintilla window
   Dialog Show Modal hDlg Call DlgProc
End Function
 
CallBack Function DlgProc() As Long
   Local txt As String
   txt = "Select Case var$ 'first line" + $CrLf + "End Select 'last line" + Chr$(0)
   Select Case CB.Msg
      Case %WM_InitDialog
         InitializeScintilla
         PostMessage hSci, %SCI_SetSel, 0,0 'unselect initially
      Case %WM_Command
         Select Case CB.Ctl
            Case %ID_BtnA : TestA
            Case %ID_BtnB : TestB
         End Select
      Case %WM_Size
         Control Set Size hDlg, %ID_Sci, Lo(Word, CB.lParam)-110, Hi(Word, CB.lParam)-20
      Case %WM_Destroy
         If hLib Then FreeLibrary hLib      'free the Scintilla library
   End Select
End Function
 
Sub InitializeScintilla
   Local txt As String
   txt = "If x = 2 Then" + $CrLf + "   'do nothing" + $Crlf
   txt = txt + "Else" + $crlf + "   x = 0" + $crlf + "End If" + Chr$(0)
   ptrSci = SendMessage(hSci,%SCI_GETDIRECTPOINTER,0,0) 'msg handler pointer
   SendMessage hSci, %SCI_SetText, 0, StrPTR(txt)
   SendMessage hSci, %SCI_SetMarginWidthN, 0, 20
End Sub
 
Sub TestA
   Local i, iStart, iEnd As Long
   iStart = GetTickCount
   For i = 1 to 50000
      SendMessage hSci, %SCI_STYLESETFORE,    %SCE_B_KEYWORD,    Rgb(0, 0, 255)              'keyword FGcolor
      SendMessage hSci, %SCI_STYLESETFORE,    %SCE_B_STRING,     Rgb(255, 0, 255)            'string color
      SendMessage hSci, %SCI_STYLESETFORE,    %SCE_B_NUMBER,     Rgb(192,100,0)              'number colors
      SendMessage hSci, %SCI_SETLEXER,        %SCLEX_PowerBASIC, 0                           'user PB lexer
   Next i
   iEnd = GetTickCount
   MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
End Sub
 
Sub TestB
   Local i, iStart As Long, iEnd As Long
   iStart = GetTickCount
   For i = 1 to 50000
      SciMsg ptrSci, %SCI_STYLESETFORE,    %SCE_B_KEYWORD,    Rgb(0, 0, 255)              'keyword FGcolor
      SciMsg ptrSci, %SCI_STYLESETFORE,    %SCE_B_STRING,     Rgb(255, 0, 255)            'string color
      SciMsg ptrSci, %SCI_STYLESETFORE,    %SCE_B_NUMBER,     Rgb(192,100,0)              'number colors
      SciMsg ptrSci, %SCI_SETLEXER,        %SCLEX_PowerBASIC, 0                           'user PB lexer
   Next i
   iEnd = GetTickCount
   MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
End Sub
 
'gbs_00662
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm