102

My program calls Java and then redirects stdout to a RichTextBox. My problem is that the vertical scrollbar always stays at the top of the box every time data is written.

Even if you scroll to the bottom, once new data has been written it goes to the top. I would like the opposite.

So when new data is written, it stays at the bottom. How can I do this?

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
user1158745
  • 2,402
  • 9
  • 41
  • 60

6 Answers6

194

Yes, you can use the ScrollToCaret() method:

// 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();
}
Omar
  • 16,329
  • 10
  • 48
  • 66
  • I figured it out. for some reason in VS 2010, I had to click on the rich text box, then click events, then find TExted changed and link it to "myrichTextBox_TextChanged". Forsome reason that worked. – user1158745 Feb 23 '12 at 19:41
  • 2
    For some reason, Visual Studio 2017 doesnt offer this property as an option. Is this deprecated? – SubjectX Jul 13 '17 at 16:26
  • @SubjectX The documentation states that it's still available in the current version of the .Net framework. – Omar Jul 14 '17 at 19:38
  • 1
    Although this answer is a simpler solution, [@Prem Kumar Badri](https://stackoverflow.com/a/50236755/8908827) answer bellow works better overall as it doesn't mess with the user's text selection and it also don't have weird vertical alignment issues – Leo Bottaro Jun 12 '19 at 15:36
26

The RichTextBox will stay scrolled to the end if it has focus and you use AppendText to add the information. If you set HideSelection to False it will keep its selection when it loses focus and stay auto scrolled.

I designed a Log Viewer GUI that used the method below. It used up to a full core keeping up. Getting rid of this code and setting HideSelection to False got the CPU usage down to 1-2%

//Don't use this!
richTextBox.AppendText(text);  
richTextBox.ScrollToEnd();
DrWu
  • 574
  • 5
  • 10
  • 3
    This is for the WPF RichTextBox. `ScrollToEnd()` is not a method available on the WinForms version. – Jeff B Aug 20 '14 at 19:54
  • It inherits from TextBoxBase which does have `ScrollToEnd()` – DrWu Sep 03 '14 at 22:58
  • I don't see it in the documentation for [`System.Windows.Forms.TextBoxBase`](http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase(v=vs.110).aspx) which is inherited by the [`RichTextBox`](http://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox(v=vs.110).aspx) for WinForms. – Jeff B Sep 04 '14 at 03:25
  • 6
    Ah I was looking at the wrong one. You are correct. However my solution was NOT to use that anyways. I was able to use AppendText and HideSelection to false to get a much more efficient solution. – DrWu Sep 04 '14 at 16:30
  • 1
    more code more problems, this soloution has no code and therefore is more ellegant in my opinion – Max Carroll Jan 15 '20 at 14:48
  • I did not believe you, so I had to try it out myself. Works like a charm. I was having issues using ScrollToCaret when displaying certain things, it would cause the text to "jiggle", this resolved that completely. – LordWabbit Jul 12 '21 at 10:18
26

I'll keep it simple:

  • Set HideSelection property to false

  • Use AppendText() method to add text to RichTextBox.

Code:

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);
}
123iamking
  • 2,387
  • 4
  • 36
  • 56
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;
    }

ScrollToBottom(richTextBox);

by using above method you can scroll rich text box to bottom

  • 1
    Thank you. None of the other methods worked for me. This one worked. For some reason once the text box started getting too full the other methods didn't work anymore. – Jeremy Dec 18 '18 at 17:13
  • Thank you very much for posting this! It seems with RichTextBox, using the other methods don't make it scroll quite all the way down if you do not have a new line at the end of the text. – Walter Bishop Feb 20 '19 at 23:13
  • This works and provides better performance than ScrollToCaret. Thanks. – Roman Mar 24 '20 at 14:47
  • This works really nice, since you can leave the HideSelection property set to true and so you don't get annoying flickering when you replace the whole text in the box with larger text. – luci88filter Jun 30 '20 at 08:46
  • This works for me with a TextBox when it is hidden too. – gridtrak Jul 07 '21 at 17:27
  • No difference from just using `richTextBox.SelectionStart = richTextBox.Text.Length;` inside an event – Ray Chakrit Feb 09 '23 at 02:08
-2

When writing new data, if you use AppendText() it wont scroll up and will always stay at the bottom.

Gayan Dasanayake
  • 1,933
  • 2
  • 17
  • 22
-2

This is an old question, but I had this problem and I used the richTextBox_TextChanged event as above, which works. But I feel this is a workaround and wanted to document the actual solution in case anybody else looks for it.

If you append it will auto-scroll, however the RichTextBox has to be focused. So call Focus before AppendText to make sure it auto-scrolls.

richTextBox.Focus();

richTextBox.AppendText(text);
RamenChef
  • 5,557
  • 11
  • 31
  • 43
DocWho
  • 29
  • 1