Date: 02-16-2022
Return to Index
created by gbSnippets
'This code shows how to get various text areas and the corresponding char/line boundaries -
'all text, selection, caret, current line, LinesM, LineM-N, CharM and CharsM-N.
'Both DDT and direct API solutions are provided.
'Compiler Comments:
'This code is written to compile with PBWin10. To compile with PBWin9,
'add this line:
#Include "CommCtrl.inc"
'Primary Code:
'Because of size, only a single copy of the primary code is shown, as part
'of the compilable example below. All code is shown as Functions.
'But, in summary, here are the basic statements used. These can be used
'individually to get information, whereas the Functions in the compilable example
'below return several pieces of information with each call.
'DDT
Control Get Text 'used to get entire text of RichEdit control
Instr 'find start/end positions of lines
ParseCount 'determine how many lines are in the control text
Parse$ 'retrieve specific line content
'API
SendMessage(hRichEdit, %EM_EXGetSel, 0, VarPTR(P)) 'start/stop of selection, caret position if no selection
SendMessage(hRichEdit, %EM_LineIndex, n&, 0) 'position of 1st char in line m&
SendMessage(hRichEdit, %EM_LineLength, iStartPos&, 0) 'length of specified line
SendMessage(hRichEdit, %EM_GetTextLengthEX, VarPTR(D),0) 'length of all text in control
SendMessage(hRichEdit, %EM_EXLineFromChar, 0, -1) 'line#, current
SendMessage(hRichEdit, %EM_EXLineFromChar, 0, iStartPos&) 'line# containing specified character
SendMessage(hRichEdit, %EM_GetLineCount, 0,0) 'total line count in control
SendMessage(hRichEdit, %EM_GetLine, iStartLine&, StrPTR(buf$)) 'get text, specified line
SendMessage(hRichEdit, %EM_GetSelText, 0, StrPTR(buf$)) 'get text, selected
SendMessage(hRichEdit, %EM_GetTextEX, VarPTR(T), StrPTR(buf$)) 'get text, specified char range or from selection
'Compilable Example: (Jose Includes)
'This example gets all of the text, the selected text, text from specific
'lines or character positions, character/Line positions of selections, and
'character/line position of the caret. Both DDT and SKD solutions are
'demonstrated in the example.
'Line numbers start at 0. 'Char positions start at 0.
'Char positions include $crlf at end of previous lines.
'If there is no selection, the selection function returns the caret position.
'If there is a selection, the caret function returns the starting position of the selection.
#Compiler PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Include "win32api.inc"
#Include "RichEdit.inc"
Global hDlg as DWord, hRichEdit as DWord
%ID_RichEdit = 500
Function PBMain() As Long
Local style&, buf$
buf$ = "This is sample" + $CrLf + "text for the" + $CrLf + "edit control."
style& = %WS_Child Or %WS_Visible Or %ES_MultiLine Or %WS_VScroll Or %ES_AutoHScroll _
Or %WS_HScroll Or %ES_AutoVScroll Or %ES_WantReturn Or %ES_NoHideSel Or %WS_TabStop
Dialog New Pixels, 0, "Test Code",300,300,200,330, %WS_OverlappedWindow To hDlg
LoadLibrary("riched32.dll") : InitCommonControls
Control Add "RichEdit", hDlg, %ID_RichEdit, buf$,20,10,160,50, style&, %WS_EX_ClientEdge
Control Handle hDlg, %ID_RichEdit To hRichEdit
Control Add Button, hDlg, 100,"All DDT", 10,70,80,20 : Control Add Button, hDlg, 180,"Line 1 DDT", 100,70,90,20
Control Add Button, hDlg, 110,"All API", 10,100,80,20 : Control Add Button, hDlg, 190,"Line 1 API", 100,100,90,20
Control Add Button, hDlg, 120,"Sel DDT", 10,130,80,20 : Control Add Button, hDlg, 200,"Lines 0-1 DDT", 100,130,90,20
Control Add Button, hDlg, 130,"Sel API", 10,160,80,20 : Control Add Button, hDlg, 210,"Lines 0-1 API", 100,160,90,20
Control Add Button, hDlg, 140,"Caret DDT", 10,190,80,20 : Control Add Button, hDlg, 210,"Chars 11-11 DDT", 100,190,90,20
Control Add Button, hDlg, 150,"Caret API", 10,220,80,20 : Control Add Button, hDlg, 220,"Chars 11-11 API", 100,220,90,20
Control Add Button, hDlg, 160,"Current Ln DDT", 10,250,80,20 : Control Add Button, hDlg, 230,"Chars 10-20 DDT", 100,250,90,20
Control Add Button, hDlg, 170,"Current Ln API", 10,280,80,20 : Control Add Button, hDlg, 240,"Chars 10-20 API", 100,280,90,20
Control Add Button, hDlg, 240,"Restore", 100,310,80,20
Dialog Show Modal hDlg Call DlgProc
End Function
CallBack Function DlgProc() As Long
Local iStartPos&, iStopPos&, iStartLine&, iStopLine&
If CB.Msg = %WM_Command AND CB.Ctl = 100 Then GetTextBoundary_AllText_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'all text replaced
If CB.Msg = %WM_Command AND CB.Ctl = 110 Then GetTextBoundary_AllText_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'all text replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 120 Then GetTextBoundary_Selection_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'selection replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 130 Then GetTextBoundary_Selection_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'selection replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 140 Then GetTextBoundary_CurrentLine_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'current line"
If CB.Msg = %WM_Command AND CB.Ctl = 150 Then GetTextBoundary_CurrentLine_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'current line"
If CB.Msg = %WM_Command AND CB.Ctl = 160 Then GetTextBoundary_LinesMN_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Line 1 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 170 Then GetTextBoundary_LinesMN_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Line 1 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 180 Then GetTextBoundary_LinesMN_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Lines 0,1 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 190 Then GetTextBoundary_LinesMN_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Lines 0,1 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 200 Then GetTextBoundary_CharsMN_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'XX"
If CB.Msg = %WM_Command AND CB.Ctl = 210 Then GetTextBoundary_CharsMN_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'XX"
If CB.Msg = %WM_Command AND CB.Ctl = 220 Then GetTextBoundary_CharsMN_DDT hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Chars 10,20 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 230 Then GetTextBoundary_CharsMN_API hRichEdit, iStartPos&, iStopPos&, iStartLine&, iStopLine& 'Chars 10,20 replaced"
If CB.Msg = %WM_Command AND CB.Ctl = 240 Then Control Set Text hDlg, %ID_RichEdit, "This is sample" + $CrLf + "text for the" + $CrLf + "edit control."
End Function
Function GetTextBoundary_AllText_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
'returns all text in control, 1st/last char pos, 1st/last/line #
'char #'s are zero-based. line #'s are zero-based.
Local temp$
Control Get Text hDlg, %ID_RichEdit To temp$
iStartPos& = 0 : iStopPos& = Len(temp$) - 1
iStartLine& = 0 : iStopLine& = ParseCount(temp$, $crlf) -1
Function = temp$
DisplayResult ("All-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_AllText_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local D as GetTextLengthEX, T as TextRange, iLengthText&, buf$
D.flags = %GTL_Default 'return number of characters
iLengthText& = SendMessage(hRichEdit, %EM_GetTextLengthEX, VarPTR(D),0) 'total length (# char's in control)
buf$ = Space$(iLengthText&)
iStartPos& = 0
iStopPos& = iLengthText& - 1
iStartLine& = 0
iStopLine& = SendMessage(hRichEdit, %EM_GetLineCount, 0,0) - 1
T.Chrg.cpmin = iStartPos& : T.Chrg.cpmax = iStopPos& - 1
SendMessage(hRichEdit, %EM_GetTextEX, VarPTR(T), StrPTR(buf$)) 'returns all chars in buf$
Function = buf$
DisplayResult ("All-API", buf$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_Selection_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local temp$
'DDT Requires some API code to work
DisplayResult ("Selection-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_Selection_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local P as CharRange, iResult&, buf$
iResult& = SendMessage(hRichEdit, %EM_EXGetSel, 0, VarPTR(P)) 'start/stop of selection, caret position if no selection
iStartPos& = P.cpmin
iStopPos& = P.cpmax
iStartLine& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, iStartPos&) 'line containing iStartPos&
iStopLine& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, iStopPos&) 'line containing iStopPos&
buf$ = Space$(iStopPos& - iStartPos& +1)
SendMessage(hRichEdit, %EM_GetSelText, 0, StrPTR(buf$)) 'selection start/stop, caret if none
Function = buf$
DisplayResult ("Selection-API", buf$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_Caret_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local temp$
'DDT - there is no PowerBASIC DDT command for getting the caret location
DisplayResult ("Caret-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_Caret_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local P as CharRange, iResult&
iResult& = SendMessage(hRichEdit, %EM_EXGetSel, 0, VarPTR(P)) 'start/stop of selection, caret position if no selection
iStartPos& = P.cpmin
iStopPos& = P.cpmin
iStartLine& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, iStartPos&) 'line containing iStartPos&
' iStartLine& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, -1) 'current line# / 1st line# of selection
iStopLine& = iStartLine& 'caret covers only 1 line
Function = ""
DisplayResult ("Caret-API", "<caret>", iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_CurrentLine_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local temp$
'DDT - there is no PowerBASIC DDT command for getting the current line
DisplayResult ("CurrentLine-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_CurrentLine_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local buf$, iLengthText&
iStartLine& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, -1) 'current line# or 1st line# of selection
iStartPos& = SendMessage(hRichEdit, %EM_EXLineFromChar, 0, iStartLine&) '1st char of current line
iLengthText& = SendMessage(hRichEdit, %EM_LineLength, iStartPos&, 0) 'length of current line
iStopPos& = iStartPos& + iLengthText& - 1 'last char of current line
iStopLine& = iStartLine& 'same as current line
buf$ = Space$(iLengthText&)
SendMessage(hRichEdit, %EM_GetLine, iStartLine&, StrPTR(buf$)) 'entire line of text
Function = buf$
DisplayResult ("CurrentLine-API", buf$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_LinesMN_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local iLengthText&, temp$, i as Long
Control Get Text hDlg, %ID_RichEdit To temp$
For i = 1 to 4 : iStartPos& = Instr(iStartPos&, temp$, $crlf) : Next i
iStartPos& = iStartPos& + 3 '1st character of line m
temp$ = Parse$(temp$, $crlf, iStartLine&) 'text of line m
iStopPos& = iStartPos& + Len(temp$) - 1 'last character of line m
DisplayResult ("LinesMN-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_LinesMN_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local buf$, iLineNLength&, iCharPosN&
iStartPos& = SendMessage(hRichEdit, %EM_LineIndex, iStartLine&, 0) 'position of 1st char in line m&
iCharPosN& = SendMessage(hRichEdit, %EM_LineIndex, iStopLine&, 0) 'position of 1st char in line m&
iLineNLength& = SendMessage(hRichEdit, %EM_LineLength, iCharPosN&, 0) 'length of line starting at that char position
iStopPos& = iCharPosN& + iLineNLength& - 1
buf$ = Space$(iStopPos& - iStartPos& - 1)
SendMessage(hRichEdit, %EM_GetLine, iStartLine&, StrPTR(buf$)) 'entire line of text
Function = buf$
DisplayResult ("LinesMN-API", buf$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_CharsMN_DDT(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local iLengthText&, temp$, i as Long
Control Get Text hDlg, %ID_RichEdit To temp$
For i = 1 to 4 : iStartPos& = Instr(iStartPos&, temp$, $crlf) : Next i
iStartPos& = iStartPos& + 3 '1st character of line m
temp$ = Parse$(temp$, $crlf, iStartLine&) 'text of line m
iStopPos& = iStartPos& + Len(temp$) - 1 'last character of line m
DisplayResult ("CharsMN-DDT", temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Function GetTextBoundary_CharsMN_API(ByVal hRichEdit as DWord, iStartPos&, iStopPos&, iStartLine&, iStopLine&) As String
Local buf$, iLineNLength&, iCharPosN&
iStartPos& = SendMessage(hRichEdit, %EM_LineIndex, iStartLine&, 0) 'position of 1st char in line m&
iCharPosN& = SendMessage(hRichEdit, %EM_LineIndex, iStopLine&, 0) 'position of 1st char in line m&
iLineNLength& = SendMessage(hRichEdit, %EM_LineLength, iCharPosN&, 0) 'length of line starting at that char position
iStopPos& = iCharPosN& + iLineNLength& - 1
buf$ = Space$(iStopPos& - iStartPos& + 1)
SendMessage(hRichEdit, %EM_GetLine, iStartLine&, StrPTR(buf$)) 'entire line of text
Function = buf$
DisplayResult ("CharsMN-API", buf$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
End Function
Sub DisplayResult (desc$, temp$, iStartPos&, iStopPos&, iStartLine&, iStopLine&)
MsgBox desc$ + $crlf + $crlf + temp$ + $crlf + $crlf + "StartPos " + Str$(iStartPos&) + $crlf _
+ "EndPos " + Str$(iStopPos&) + $crlf _
+ "StartLine " + Str$(iStartLine&) + $crlf _
+ "EndLine " + Str$(iStopLine&)
End Sub
'gbs_00221
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm