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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/898307/
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-08-05 22:06:05  来源:igfitidea点击:

How do I automatically scroll to the bottom of a multiline text box?

c#winformstextboxscroll

提问by GWLlosa

I have a textbox with the .Multiline property set to true. At regular intervals, I am adding new lines of text to it. I would like the textbox to automatically scroll to the bottom-most entry (the newest one) whenever a new line is added. How do I accomplish this?

我有一个 .Multiline 属性设置为 true 的文本框。每隔一段时间,我就会向其中添加新的文本行。我希望文本框在添加新行时自动滚动到最底部的条目(最新的条目)。我该如何实现?

采纳答案by Bob

At regular intervals, I am adding new lines of text to it. I would like the textbox to automatically scroll to the bottom-most entry (the newest one) whenever a new line is added.

每隔一段时间,我就会向其中添加新的文本行。我希望文本框在添加新行时自动滚动到最底部的条目(最新的条目)。

If you use TextBox.AppendText(string text), it will automatically scroll to the end of the newly appended text. It avoids the flickering scrollbar if you're calling it in a loop.

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

It also happens to be an order of magnitude faster than concatenating onto the .Textproperty. Though that might depend on how often you're calling it; I was testing with a tight loop.

它也恰好比连接到.Text属性上快一个数量级。尽管这可能取决于您调用它的频率;我正在用一个紧密的循环进行测试。



This will not scroll if it is called before the textbox is shown, or if the textbox is otherwise not visible (e.g. in a different tab of a TabPanel). See TextBox.AppendText() not autoscrolling. This may or may not be important, depending on if you require autoscroll when the user can't see the textbox.

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

It seems that the alternative method from the other answers also don't work in this case. One way around it is to perform additional scrolling on the VisibleChangedevent:

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

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


Internally, AppendTextdoes something like this:

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

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

But there should be no reason to do it manually.

但是应该没有理由手动执行此操作。

(If you decompile it yourself, you'll see that it uses some possibly more efficient internal methods, and has what seems to be a minor special case.)

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

回答by GWLlosa

You can use the following code snippet:

您可以使用以下代码片段:

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

which will automatically scroll to the end.

这将自动滚动到最后。

回答by GWLlosa

Try to add the suggested code to the TextChanged event:

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

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

回答by h4nd

I needed to add a refresh:

我需要添加刷新:

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

回答by JohnDRoach

It seems the interface has changed in .NET4.0. There is the following methodthat achieves all of the above. As Tommy Engebretsen suggested, putting it in a TextChanged event handler makes it automatic.

.NET4.0 中的界面似乎发生了变化。有以下方法可以实现以上所有内容。正如 Tommy Engebretsen 建议的那样,将它放在 TextChanged 事件处理程序中会使其自动进行。

textBox1.ScrollToEnd();

回答by TooGeeky

This only worked for me...

这只对我有用...

txtSerialLogging->Text = "";

txtSerialLogging->Text = "";

txtSerialLogging->AppendText(s);

txtSerialLogging->AppendText(s);

I tried all the cases above, but the problem is in my case text s can decrease, increase and can also remain static for a long time. static means , static length(lines) but content is different.

我尝试了上述所有情况,但问题是在我的情况下 text 可以减少,增加并且也可以长时间保持静止。静态意味着,静态长度(行)但内容不同。

So, I was facing one line jumping situation at the end when the length(lines) remains same for some times...

所以,当长度(行)保持不变一段时间时,我最后面临着一行跳跃的情况......

回答by DMike92

I use a function for this :

我为此使用了一个函数:

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

回答by Stefan Steiger

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

didn't work for me (Windows 8.1, whatever the reason).
And since I'm still on .NET 2.0, I can't use ScrollToEnd.

But this works:

对我不起作用(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:

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

回答by Pete

I found a simple difference that hasn't been addressed in this thread.

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

If you're doing all the ScrollToCarat()calls as part of your form's Load()event, it doesn't work. I just added my ScrollToCarat()call to my form's Activated()event, and it works fine.

如果您将所有ScrollToCarat()调用作为表单Load()事件的一部分进行,则它不起作用。我刚刚将我的ScrollToCarat()电话添加到我的表单Activated()事件中,它工作正常。

Edit

编辑

It's important to only do this scrolling the first time form's Activatedevent is fired (not on subsequent activations), or it will scroll everytime your form is activated, which is something you probably don't want.

重要的是只在第一次Activated触发表单事件时进行滚动(而不是在后续激活时),否则每次激活表单时它都会滚动,这可能是您不想要的。

So if you're only trapping the Activated()event to scroll your text when your program loads, then you can just unsubscribe to the event inside the event handler itself, thusly:

因此,如果您只是Activated()在程序加载时捕获事件以滚动文本,那么您可以取消订阅事件处理程序本身内的事件,因此:

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

If you have other things you need to do each time your form is activated, you can set a boolto true the first time your Activated()event is fired, so you don't scroll on subsequent activations, but can still do the other things you need to do.

如果您在每次激活表单时还有其他事情需要做,您可以bool在第一次Activated()触发事件时将 a 设置为 true ,这样您就不会在后续激活时滚动,但仍然可以做您需要做的其他事情做。

Also, if your TextBoxis on a tab that isn't the SelectedTab, ScrollToCarat()will have no effect. So you need at least make it the selected tab while you're scrolling. You can wrap the code in a YourTab.SuspendLayout();and YourTab.ResumeLayout(false);pair if your form flickers when you do this.

另外,如果您TextBox是一个标签,是不是在SelectedTabScrollToCarat()不会有任何效果。因此,您至少需要在滚动时将其设为选定的选项卡。如果执行此操作时表单闪烁,您可以将代码包装在 aYourTab.SuspendLayout();YourTab.ResumeLayout(false);pair 中。

End of edit

编辑结束

Hope this helps!

希望这可以帮助!

回答by Eric Shreve

This will scroll to the end of the textbox when the text is changed, but still allows the user to scroll up

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

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

tested on Visual Studio Enterprise 2017

在 Visual Studio Enterprise 2017 上测试