如何自动滚动到多行文本框的底部?
我有一个.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(); }