Private Const EM_GETLINE As Long = &HC4
Private Const EM_GETLINECOUNT As Long = &HBA
Private Const EM_GETSEL As Long = &HB0
Private Const EM_LINEFROMCHAR As Long = &HC9
Private Const EM_LINEINDEX As Long = &HBB
Private Const EM_LINELENGTH As Long = &HC1
'here's the API way if anyone wants to know how it was done
Public Property Get LinesAPI(ByVal lngLineNumber As Long) As String
Dim lngLineCount As Long
Dim lngFirstChar As Long
Dim lngLineLength As Long
Dim hWnd As Long
Dim abyteBuffer() As Byte
LinesAPI = ""
If Not blnClassBound Then Exit Property
hWnd = txtSource.hWnd
lngLineCount = SendMessage(hWnd, EM_GETLINECOUNT, 0, 0)
If (lngLineNumber < 0) Or (lngLineNumber > (lngLineCount - 1)) Then Exit Property
lngFirstChar = SendMessage(hWnd, EM_LINEINDEX, lngLineNumber, 0)
lngLineLength = SendMessage(hWnd, EM_LINELENGTH, lngFirstChar, 0)
If lngLineLength = 0 Then Exit Property
ReDim abyteBuffer(0 To (lngLineLength - 1))
abyteBuffer(0) = lngLineLength And &HFF
If lngLineLength > 255 Then abyteBuffer(1) = lngLineLength And &H100
SendMessage hWnd, EM_GETLINE, lngLineNumber, VarPtr(abyteBuffer(0))
LinesAPI = StrConv(abyteBuffer, vbUnicode)
End Property
'this is the Split() way, which takes less work, but may be slower for longer text
Public Property Get Lines(ByVal lngLineNumber As Long) As String
Dim astrLines As Variant 'may be astrLines() As String for VB6 users
Lines = ""
If Not blnClassBound Then Exit Property
If txtSource.Text = "" Then Exit Property
astrLines = Split(txtSource.Text, vbCrLf)
If (lngLineNumber < 0) Or (lngLineNumber > UBound(astrLines)) Then Exit Property
Lines = astrLines(lngLineNumber)
End Property
Public Property Let Lines(ByVal lngLineNumber As Long, ByVal strNewLine As String)
Dim astrLines As Variant 'may be astrLines() As String for VB6 users
If Not blnClassBound Then Exit Property
If txtSource.Text = "" Then
txtSource.Text = strNewLine
Exit Property
End If
astrLines = Split(txtSource.Text, vbCrLf)
If (lngLineNumber < 0) Or (lngLineNumber > UBound(astrLines)) Then Exit Property
astrLines(lngLineNumber) = strNewLine
txtSource.Text = Join(astrLines, vbCrLf)
End Property
'the next two are mainly for multiline textboxes, but work on single line ones too
'the row will always be 1 for a single line textbox
Public Property Get Column() As Long
Dim lngReturn As Long
Dim lngCharIndex As Long
Dim lngRow As Long
If Not blnClassBound Then Exit Property
lngReturn = SendMessage(txtSource.hWnd, EM_GETSEL, 0, 0)
lngCharIndex = (lngReturn / 65536) And &HFFFF
lngReturn = SendMessage(txtSource.hWnd, EM_LINEINDEX, -1, 0)
Column = lngCharIndex - lngReturn + 1
End Property
Public Property Get Row() As Long
Dim lngReturn As Long
Dim lngCharIndex As Long
If Not blnClassBound Then Exit Property
lngReturn = SendMessage(txtSource.hWnd, EM_GETSEL, 0, 0)
lngCharIndex = (lngReturn / 65536) And &HFFFF
Row = SendMessage(txtSource.hWnd, EM_LINEFROMCHAR, lngCharIndex, 0) + 1
End Property