如何自动滚动到多行文本框的底部?

我有一个.Multiline属性设置为true的文本框。 我会定期添加新的文本。 我希望文本框自动滚动到最下面的条目(最新的),每当添加一个新行。 我如何做到这一点?

我会定期添加新的文本。 我希望文本框自动滚动到最下面的条目(最新的),每当添加一个新行。

如果使用TextBox.AppendText(string text) ,它将自动滚动到新添加的文本的末尾。 它避免了闪烁的滚动条,如果你在一个循环中调用它。

它也恰好比连接到.Text属性上快一个数量级。 尽pipe这可能取决于你打电话的频率。 我正在testing一个紧密的循环。


如果在显示文本框之前调用它,或者文本框不可见(例如,在TabPanel的不同选项卡中),则这将不会滚动。 请参阅TextBox.AppendText()不自动滚动 。 这可能也可能不重要,具体取决于用户无法看到文本框时是否需要自动滚动。

似乎来自其他答案的替代方法在这种情况下也不起作用。 其中一种方法是在VisibleChanged事件上执行额外的滚动VisibleChanged

 textBox.VisibleChanged += (sender, e) => { if (textBox.Visible) { textBox.SelectionStart = textBox.TextLength; textBox.ScrollToCaret(); } }; 

在内部, AppendText做这样的事情:

 textBox.Select(textBox.TextLength + 1, 0); textBox.SelectedText = textToAppend; 

但是没有理由手动去做。

(如果你自己反编译,你会发现它使用了一些可能更有效的内部方法,并且似乎是一个小小的特例。)

你可以使用下面的代码片段:

 myTextBox.SelectionStart = myTextBox.Text.Length; myTextBox.ScrollToCaret(); 

它会自动滚动到最后。

看来.NET 4.0中的接口已经改变了。 有以下方法可以达到上述所有。 正如Tommy Engebretsen所build议的,把它放在一个TextChanged事件处理程序中会自动执行。

 textBox1.ScrollToEnd(); 

尝试将build议的代码添加到TextChanged事件:

 private void textBox1_TextChanged(object sender, EventArgs e) { textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); } 

我需要添加刷新:

 textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); textBox1.Refresh(); 
 textBox1.Focus() textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); 

没有为我工作(Windows 8.1,无论原因)。
由于我仍然在.NET 2.0,我不能使用ScrollToEnd。

但是这个工作:

 public class Utils { [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] private static extern int SendMessage(System.IntPtr hWnd, int wMsg, System.IntPtr wParam, System.IntPtr lParam); private const int WM_VSCROLL = 0x115; private const int SB_BOTTOM = 7; /// <summary> /// Scrolls the vertical scroll bar of a multi-line text box to the bottom. /// </summary> /// <param name="tb">The text box to scroll</param> public static void ScrollToBottom(System.Windows.Forms.TextBox tb) { if(System.Environment.OSVersion.Platform != System.PlatformID.Unix) SendMessage(tb.Handle, WM_VSCROLL, new System.IntPtr(SB_BOTTOM), System.IntPtr.Zero); } } 

VB.NET:

 Public Class Utils <System.Runtime.InteropServices.DllImport("user32.dll", CharSet := System.Runtime.InteropServices.CharSet.Auto)> _ Private Shared Function SendMessage(hWnd As System.IntPtr, wMsg As Integer, wParam As System.IntPtr, lParam As System.IntPtr) As Integer End Function Private Const WM_VSCROLL As Integer = &H115 Private Const SB_BOTTOM As Integer = 7 ''' <summary> ''' Scrolls the vertical scroll bar of a multi-line text box to the bottom. ''' </summary> ''' <param name="tb">The text box to scroll</param> Public Shared Sub ScrollToBottom(tb As System.Windows.Forms.TextBox) If System.Environment.OSVersion.Platform <> System.PlatformID.Unix Then SendMessage(tb.Handle, WM_VSCROLL, New System.IntPtr(SB_BOTTOM), System.IntPtr.Zero) End If End Sub End Class 

我发现了一个简单的区别,在这个线程中没有得到解决。

如果您正在执行所有ScrollToCarat()调用作为您的窗体的Load()事件的一部分,它不起作用。 我只是将我的ScrollToCarat()调用添加到我的表单的Activated()事件,它工作正常。

编辑

只有在第一次执行滚动窗体的Activated事件被Activated (而不是在随后的激活),这是非常重要的,否则每次激活表单时都会滚动,这是您可能不想要的。

所以,如果您只是在您的程序加载时陷入Activated()事件来滚动文本,那么您可以在事件处理程序本身中取消订阅事件,从而:

 Activated -= new System.EventHandler(this.Form1_Activated); 

如果每次激活表单时都需要执行其他操作,则可以在第一次Activated()事件时将bool设置为true,以便在后续激活时不滚动,但仍然可以执行其他操作你需要做的事情。

另外,如果您的TextBox位于不是SelectedTab的选项卡上, ScrollToCarat()将不起作用。 所以当你滚动的时候你至less需要把它做成选定的标签。 你可以把代码包装在一个YourTab.SuspendLayout();YourTab.ResumeLayout(false); 如果你的表单闪烁,当你这样做。

编辑结束

希望这可以帮助!

当文本被改变时,这将滚动到文本框的末尾,但仍然允许用户向上滚动

 outbox.SelectionStart = outbox.Text.Length; outbox.ScrollToEnd(); 

在Visual Studio Enterprise 2017上进行了testing

这只对我有用…

txtSerialLogging-> Text =“”;

txtSerialLogging-> AppendText通过(一个或多个);

我尝试了以上所有的情况,但问题是在我的情况下文本可以减less,增加,也可以保持静态很长一段时间。 静态的手段,静态的长度(线),但内容是不同的。

所以,当长度(线条)保持相同的时候,我在最后面临一行跳跃情况…

我使用这个function:

 private void Log (string s) { TB1.AppendText(Environment.NewLine + s); TB1.ScrollToCaret(); }