Vb.net – Autoscroll to the bottom of a multiline textbox

textboxvb.netvisual-studio-2015winforms

I have started to make a master-server program for a small project involving rebuilding a game on a newer engine.
The master server program currently looks like this:

enter image description here

The large textbox with the 'Found 4 installed processor(s)' is a 'console' which outputs raw event messages sent to and from clients/gameservers using the master-server. It cannot be inputted into and the administrator (the only person who has access to this interface of the master-server program) can only copy from the textbox; they cannot delete/add anything.

The issue is that because it's supposed to be a 'console', it should automatically scroll down to the last line of the multiline textbox.

There are many questions on Stack Overflow which cover this (this one for example), but I haven't been able to get it working (the textbox doesn't scroll down) when placing the code within the console_TextChanged subroutine.
I have tried this:

Private Sub console_TextChanged(sender As Object, e As EventArgs) Handles console.TextChanged
    console.AppendText(Text)
    console.Select(console.TextLength, 0)
    console.ScrollToCaret()
End Sub

It doesn't work, but it does however cause a bug in the program where each line is appended with the program's title quite a few times:

[net 11:32:22.243] System Started.Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5Server Network | Crysis Wars 1.5

Some C# solutions have also worked for me in Visual Basic .Net in the past, and so I have tried some of the ones on Stack Overflow but I haven't been able to get these working either.

Is this really the correct way to autoscroll a multilined textbox, and if so, why is it not working for me?

The complete (relevant) code:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    console.Text = GetNetTime() + "System Started."
    WriteToConsole("Working Area: " + CStr(My.Computer.Screen.WorkingArea().Width) + "*" + CStr(My.Computer.Screen.WorkingArea().Height))
    WriteToConsole("Found " + CStr(Environment.ProcessorCount) + " installed processor(s)")
    Dim i As Integer = 0
    While (i < Environment.ProcessorCount)
        WriteToConsole("Processor " + CStr(i) + ": " + My.Computer.Registry.LocalMachine.OpenSubKey("Hardware\Description\System\CentralProcessor\" + CStr(i)).GetValue("ProcessorNameString"))
        WriteToConsole("            Family: " + My.Computer.Registry.LocalMachine.OpenSubKey("Hardware\Description\System\CentralProcessor\" + CStr(i)).GetValue("Identifier"))
        WriteToConsole("            Manufacturer: " + My.Computer.Registry.LocalMachine.OpenSubKey("Hardware\Description\System\CentralProcessor\" + CStr(i)).GetValue("VendorIdentifier"))
        i += 1
    End While
    WriteToConsole("Starting networking services")
End Sub
Private Sub console_TextChanged(sender As Object, e As EventArgs) Handles console.TextChanged
    console.AppendText(Text)
    console.Select(console.TextLength, 0)
    console.ScrollToCaret()
End Sub
Function GetNetTime()
    Return "[net " + CStr(DateTime.UtcNow.Hour) + ":" + CStr(DateTime.UtcNow.Minute) + ":" + CStr(DateTime.UtcNow.Second) + "." + CStr(DateTime.UtcNow.Millisecond) + "] "
End Function
Function WriteToConsole(ByVal input As String)
    console.AppendText(Environment.NewLine & GetNetTime() + input)
    Return -1
End Function

Best Answer

One more useful solution:

textBox1.SelectionStart = textBox1.Text.Length
textBox1.ScrollToCaret()

It just put cursor at the end of text in textbox and scroll to current cursor position. Worked for me perfectly!

Related Topic