Create a simple project like the illustration, with a two
multiline textboxes (text1, Text2), two combo's (Combo1, Combo2), a check box (Check1) and a command button (Command1). Add two labels
(label1, Label2) to show the selected character range. The frame and other labels are optional. Add the following to the form: |
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Const EM_GETSEL As Long = &HB0
Private Const EM_SETSEL As Long = &HB1
Private Const EM_GETLINECOUNT As Long = &HBA
Private Const EM_LINEINDEX As Long = &HBB
Private Const EM_LINELENGTH As Long = &HC1
Private Const EM_LINEFROMCHAR As Long = &HC9
Private Const EM_SCROLLCARET As Long = &HB7
Private Const WM_SETREDRAW As Long = &HB
Private Sub Form_Load()
Dim fno As Integer
Dim fname As String
Dim cnt As Integer
Dim lineCount As Long
'obtain the next free file handle
'from the system
fno = FreeFile
fname = "test.txt"
'load the file into the textbox
Open fname For Input As #fno
Text1.Text = Input$(LOF(fno), fno)
Close #fno
'get the number of lines in the textbox
'and add the lines to the combos
lineCount = SendMessage(Text1.hwnd, _
EM_GETLINECOUNT, 0, ByVal 0&)
For cnt = 1 To lineCount
Combo1.AddItem cnt
Combo2.AddItem cnt
Next
Combo1.ListIndex = 0
Combo2.ListIndex = 1
Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2
End Sub
Private Sub Combo1_Click()
Dim x As Integer
Dim y As Integer
x = Val(Combo1.ListIndex)
y = Val(Combo2.ListIndex)
'should the start be greater than the end,
'set the end combo to the same value.
If x > y Then
Combo2.ListIndex = x
End If
End Sub
Private Sub Command1_Click()
Dim startLine As Long
Dim endLine As Long
'set the start and end lines to
'the combo selections
startLine = Val(Combo1.List(Combo1.ListIndex))
endLine = Val(Combo2.List(Combo2.ListIndex))
'assign the result of the function to Text2
Text2.Text = GetBlockText(Text1, startLine, endLine)
End Sub
Private Function GetBlockText(ctl As TextBox, _
passedLineStart As Long, _
passedLineEnd As Long) As String
'params-----
' ctl: control to act on (ie Text1 or Form3.Text1).
' This allows the routine to deal with any control
' passed, or (with the API declarations) to be moved
' into a BAS module for general use.
' passedLineStart: first line (1-based) to select.
' Passing <=0 defaults to start.
' passedLineEnd: last line (1-based) to select.
' Passing > linecount defaults to all text.
'------------
'returns-----
' string of selected text
'features/options-----
' - "transparent" mode (Check1) - no visible action to user
' - by returning an assignment of passedLineStart = copyStart
' and passedLineEnd = copyEnd, you can return the character
' positions for use in labels etc. (see "Debug" below)
'-------------
Dim copyStart As Long
Dim copyEnd As Long
Dim currLine As Long
Dim lineCount As Long
Dim success As Long
Dim currCursorPos As Long
ctl.SetFocus
'-------------------------------
'optional: used to start transparent action
If Check1.Value = 1 Then
currCursorPos = ctl.SelStart
Call SendMessage(ctl.hwnd, WM_SETREDRAW, False, ByVal 0&)
DoEvents
End If
'--------------------------------
'get the number of lines in the textbox
lineCount = SendMessage(ctl.hwnd, EM_GETLINECOUNT, 0, ByVal 0&)
'the control lines are 0-based, but we're making it
'more friendly by allowing 1-based numbers to be passed,
'so subtract 1 from the start number.
'Nothing is subtracted from the end number
'because we want the end line + its contents
'(IOW, the specified line -1 + Len(specified line) )
'to be selected.
'The If statement below takes care of specifying
'a line index larger than the actual number of
'lines available. It is required.
passedLineStart = passedLineStart - 1
'proceeding only if there are lines to work with
If lineCount > 0 Then
'if the startline greater than 0
If passedLineStart > 0 Then
'get the number of chrs up to the
'end of the desired start line
copyStart = SendMessage(ctl.hwnd, _
EM_LINEINDEX, _
passedLineStart, ByVal 0&)
Else 'start at the beginning
'of the textbox
copyStart = 0
End If
'if the lastline greater than 0 and
'less then the number of lines in the
'control..
If passedLineEnd > 0 And _
passedLineEnd <= lineCount Then
'..get the number of chrs up to the
'end of the desired last line
copyEnd = SendMessage(ctl.hwnd, _
EM_LINEINDEX, _
passedLineEnd, ByVal 0&)
Else 'copy the whole thing
copyEnd = Len(ctl)
End If
'Set the selection for the returned range.
'This will return -1 if unsuccessful
success = SendMessage(ctl.hwnd, _
EM_SETSEL, _
copyStart, _
ByVal copyEnd)
If success <> -1 Then
'return the selected text
GetBlockText = ctl.SelText
End If
End If
'-------------------------------
'optional: used to end transparent action
If Check1.Value = 1 Then
ctl.SelStart = currCursorPos
Call SendMessage(ctl.hwnd, WM_SETREDRAW, True, ByVal 0&)
Else
'scroll the selected item into view
Call SendMessage(ctl.hwnd, EM_SCROLLCARET, 0, ByVal 0)
End If
'--------------------------------
'debug only
Label1.Caption = "start: " & copyStart
Label2.Caption = "end: " & copyEnd
End Function
Private Sub Text1_GotFocus()
Command2.Enabled = False
End Sub
Private Sub Text1_LostFocus()
Command2.Enabled = True
End Sub |