1. Herfried K. Wagner’s VB.Any
  2. .NET
  3. Frequently Asked Questions

Determining the lines as they are being displayed in a textbox control

Determining the lines as they are being displayed in a textbox control
<URL:https://dotnet.currifex.org/dotnet/faqs/textboxdisplayedlines/en/>
----------------------------------------------------------------------------

Determining the lines as they are being displayed in a textbox control

The 'TextBoxBase' class provides a 'GetLines' method which returns the
textbox' lines which are separated by a new line character sequence.
However, textbox controls do not have a built-in method to get the lines as
they are being displayed in the control including wrapped lines.  This can
be achieved using p/invoke together with the 'SendMessage' function as
shown in the listing below.  The functionality is encapsulated in the
'GetTextBoxLines' function:

\\\
Private Declare Auto Function SendMessage Lib "user32.dll" ( _
    ByVal hwnd As IntPtr, _
    ByVal wMsg As Int32, _
    ByVal wParam As IntPtr, _
    ByVal lParam As String _
) As IntPtr

Private Declare Auto Function SendMessage Lib "user32.dll" ( _
    ByVal hwnd As IntPtr, _
    ByVal wMsg As Int32, _
    ByVal wParam As IntPtr, _
    ByVal lParam As IntPtr _
) As IntPtr

Private Const EM_GETLINE As Int32 = &HC4
Private Const EM_GETLINECOUNT As Int32 = &HBA
Private Const EM_LINEINDEX As Int32 = &HBB
Private Const EM_LINELENGTH As Int32 = &HC1

Private Function GetLine( _
    ByVal TextBox As TextBoxBase, _
    ByVal LineNumber As Integer _
) As String
    Dim dwLineStart As Int32 = _
        SendMessage( _
            TextBox.Handle, _
            EM_LINEINDEX, _
            New IntPtr(LineNumber), _
            IntPtr.Zero _
        ).ToInt32()
    Dim dwLineLen As Integer = _
        SendMessage( _
            TextBox.Handle, _
            EM_LINELENGTH, _
            New IntPtr(dwLineStart), _
            IntPtr.Zero _
        ).ToInt32()
    Dim Line As String = _
        ChrW(dwLineLen) & Space(dwLineLen - 1)
    Dim dwLen As Int32 = _
        SendMessage( _
            TextBox.Handle, _
            EM_GETLINE, _
            New IntPtr(LineNumber), _
            Line _
        ).ToInt32()
    Return Strings.Left(Line, dwLen)
End Function

Private Function GetTextBoxLines(ByVal TextBox As TextBoxBase) As String()
    Dim Max As Int32 = _
        SendMessage( _
            TextBox.Handle, _
            EM_GETLINECOUNT, _
            IntPtr.Zero, _
            IntPtr.Zero _
        ).ToInt32() - 1
    Dim Lines(Max) As String
    For i As Integer = 0 To Max
        Lines(i) = GetLine(TextBox, i)
    Next i
    Return Lines
End Function
///

The listing below demonstrates how to determine the lines of a richtextbox
control and add them to a listbox control:

\\\
Me.ListBox1.Items.AddRange(GetTextBoxLines(Me.RichTextBox1))
///