vb.net 自动滚动到多行文本框的底部

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26586675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 18:24:40  来源:igfitidea点击:

Autoscroll to the bottom of a multiline textbox

vb.netwinformstextboxvisual-studio-2015

提问by AStopher

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.

带有“发现 4 个已安装处理器”的大文本框是一个“控制台”,它使用主服务器输出发送到客户端/游戏服务器和从客户端/游戏服务器发送的原始事件消息。不能输入,管理员(唯一可以访问主服务器程序这个界面的人)只能从文本框中复制;他们不能删除/添加任何东西。

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 onefor example), but I haven't been able to get it working (the textbox doesn't scroll down) when placing the code within the console_TextChangedsubroutine. I have tried this:

Stack Overflow 上有很多问题涵盖了这一点(例如这个),但是在将代码放置在console_TextChanged子例程中时,我无法让它工作(文本框没有向下滚动)。我试过这个:

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 Overflowbut I haven't been able to get these working either.

过去,一些 C# 解决方案在 Visual Basic .Net 中也对我有用,所以我尝试了 Stack Overflow 上的一些解决方案,但我也无法让它们工作。

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

采纳答案by Sriram Sakthivel

If you're using AppendText, you can completely get rid of that console_TextChangedmethod because AppendTextalready does this for you.

如果您正在使用AppendText,则可以完全摆脱该console_TextChanged方法,因为AppendText已经为您执行了此操作。

For some reason (may be a bug?) when the TextBoxis not exposed to the screen, AppendTextdoesn't seem to scroll to end. I have no good explanation now, need to look into the .Net framework source.

出于某种原因(可能是一个错误?)当TextBox未暴露在屏幕上时,AppendText似乎没有滚动到结尾。我现在没有很好的解释,需要查看.Net框架源。

As a workaround just move all your code to MyBase.Shownevent, not Loadevent. That works as expected, difference is Shownevent will be raised as soon as the Form is first rendered in the screen as opposed to Loadwhich gets fired before the form is rendered.

作为一种解决方法,只需将所有代码移动到MyBase.Shown事件,而不是Load事件。这按预期工作,不同之处在于Shown,一旦表单首次在屏幕中呈现,事件就会引发,而不是Load在呈现表单之前触发。

回答by Mikhail_Sam

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!

它只是将光标放在文本框中文本的末尾并滚动到当前光标位置。完美地对我来说有效!

回答by γηρ?σκω δ' αε? πολλ? διδασκ?με

You can do it in load eventbut it is more complicated:

您可以在load 事件中执行此操作,但它更复杂:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

After setting the text in textbox:

在设置文本后textbox

If (console.IsHandleCreated) Then
    'set focus
    SendMessage(console.Handle, &H7, IntPtr.Zero, IntPtr.Zero) 'WM_SETFOCUS
    'move caret to the end
    SendMessage(console.Handle, &HB1, CType(-1, IntPtr), CType(-1, IntPtr)) 'EM_SETSEL
    'scroll to the end
    SendMessage(console.Handle, &HB6, IntPtr.Zero, CType(console.Lines.Length, IntPtr)) 'EM_LINESCROLL
Else
    MsgBox("console window is not created")
End If

回答by tezzo

Using a RichTextBoxinstead of a TextBoxyou can use this code.

使用 aRichTextBox而不是 aTextBox您可以使用此代码。

'SENDMESSAGE constants
'move to the last row in a RichTextBox
'you can obtain the same effect using ScrollToCaret but it works only if Focus is on RichTextBox
Private Const WM_VSCROLL As Int32 = &H115
Private Const SB_BOTTOM As Int32 = 7

Private Sub WriteLog(ByVal strLineLog As String)

    If Me.rtbLog.Text = "" Then
        Me.rtbLog.Text = strLineLog
    Else
        Me.rtbLog.AppendText(System.Environment.NewLine & strLineLog)
    End If

    SendMessage(Me.rtbLog.Handle, WM_VSCROLL, SB_BOTTOM, 0)

End Sub