富文本框在有新数据写入时滚动到底部

104

我的程序调用Java,然后将stdout重定向到一个RichTextBox。我的问题是每次写入数据时,垂直滚动条总是停留在框的顶部。

即使你滚动到底部,一旦写入新数据,它就会回到顶部。我希望相反的情况发生。

因此,当写入新数据时,它会停留在底部。我该怎么办?


对于 WPF/XAML 项目,请参考 WPF RichTextBox,自动滚动到末尾 - Danny Beckett
6个回答

194

是的,您可以使用 ScrollToCaret() 方法:

// bind this method to its TextChanged event handler:
// richTextBox.TextChanged += richTextBox_TextChanged;
private void richTextBox_TextChanged(object sender, EventArgs e) {
   // set the current caret position to the end
   richTextBox.SelectionStart = richTextBox.Text.Length;
   // scroll it automatically
   richTextBox.ScrollToCaret();
}

我解决了。在VS 2010中,我不知道为什么必须先单击富文本框,然后单击事件,再找到TExted changed并将其链接到“myrichTextBox_TextChanged”。不知道为什么这样就可以了。 - user1158745
2
由于某些原因,Visual Studio 2017没有将此属性作为选项提供。这个属性已经被弃用了吗? - SubjectX
@SubjectX 文档说明它仍然在当前版本的 .Net 框架中可用。 - Omar
1
虽然这个答案是一个更简单的解决方案,但下面@Prem Kumar Badri的答案在整体上效果更好,因为它不会干扰用户的文本选择,并且也没有奇怪的垂直对齐问题。 - Leo Bottaro

28

我会简洁明了地说明:

  • HideSelection属性设置为false

  • 使用AppendText()方法向RichTextBox添加文本。

代码:

RichTextBox rtbTest;

void InitRichTextBox()
{
    //Init rtbTest...

    rtbTest.HideSelection = false;//Hide selection so that AppendText will auto scroll to the end
}

void AddText(string txt)
{
    rtbTest.AppendText(txt);
}

3
这就是方法。 - BeachMiles
1
确实如此。只需要添加一行代码(rtbTest.HideSelection = false;)即可。 - Ed Graham

26
如果RichTextBox获得焦点并使用AppendText添加信息,它将保持滚动到末尾。如果您将HideSelection设置为False,当失去焦点时它将保留其选择并自动滚动。
我设计了一个日志查看器GUI,使用以下方法。它占用了一个完整的核心。删除此代码并将HideSelection设置为False可将CPU使用率降至1-2%。
//Don't use this!
richTextBox.AppendText(text);  
richTextBox.ScrollToEnd();

3
这是针对WPF RichTextBox的。在WinForms版本中,ScrollToEnd()不是一个可用的方法。 - Jeff B
它继承自TextBoxBase,而TextBoxBase确实具有ScrollToEnd()方法。 - DrWu
我在 System.Windows.Forms.TextBoxBase 的文档中没有看到这个内容,而这个类是 RichTextBox 继承的。 - Jeff B
6
啊,我看错了。你是正确的。然而,我的解决方案并不是使用那个。我能够使用AppendText和HideSelection设置为false来得到一个更高效的解决方案。 - DrWu
1
越多代码,问题就越多。在我看来,这个解决方案没有代码,因此更加优雅。 - Max Carroll
我不相信你,所以我必须亲自尝试一下。效果非常好。当显示某些内容时,我使用ScrollToCaret遇到了问题,它会导致文本“抖动”,但这完全解决了这个问题。 - LordWabbit

15
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
    private const int WM_VSCROLL = 277;
    private const int SB_PAGEBOTTOM = 7;

    internal static void ScrollToBottom(RichTextBox richTextBox)
    {
        SendMessage(richTextBox.Handle, WM_VSCROLL, (IntPtr)SB_PAGEBOTTOM, IntPtr.Zero);
        richTextBox.SelectionStart = richTextBox.Text.Length;
    }

使用上述方法,您可以将RichTextBox滚动到底部。


1
谢谢。其他方法对我都没用。这个方法有效。由于某种原因,一旦文本框开始变得太满,其他方法就不再起作用了。 - Jeremy
非常感谢您发布这个问题!使用 RichTextBox,如果文本末尾没有换行符,则使用其他方法无法完全滚动到底部。 - Walter Bishop
这种方法比ScrollToCaret更有效,并且可以提供更好的性能。谢谢。 - Roman
这个功能非常好用,因为你可以将HideSelection属性设置为true,这样当你用更大的文本替换框中的整个文本时,就不会出现烦人的闪烁。 - luci88filter
当 TextBox 被隐藏时,这对我很有效。 - gridtrak
没有任何区别,与在事件内部使用 richTextBox.SelectionStart = richTextBox.Text.Length; 相同。 - Ray Chakrit

-2

这是一个老问题,但我曾经遇到过这个问题,并使用了上面的richTextBox_TextChanged事件,它有效。但我觉得这是一种解决方法,想记录实际解决方案以防其他人寻找。

如果您添加文本,它将自动滚动,但必须聚焦于RichTextBox。 因此,在AppendText之前调用Focus以确保它自动滚动。

richTextBox.Focus();

richTextBox.AppendText(text);

还是不行。为了让其他用户更容易看到,我要点个踩。 - SubjectX

-2

在编写新数据时,如果使用AppendText(),它不会向上滚动,而是始终停留在底部。


4
错误!它会保持在所选位置。 - jAC
8
只要设置myRichTextBox.HideSelection = false,AppendText方法就可以很好地自动滚动。 - Philippe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接