4

I have a RichTextBox which I want to automatically scroll to the end of the text, when new text gets added.

Here is my code:

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

I manually add a bunch of text to the RichTextBox, like so:

updateOutputWindow("Lorem ipsum dolor sit amet, ..."); //These strings are really long
updateOutputWindow("Lorem ipsum dolor sit amet, ..."); //I shortened them for this question

Here is the result:

screenshot1

In the above screenshot you can just barely make out that there is actually more text underneath the edge. You can also look at the scroll bar on the right, and see that there's a little bit of space left underneath.

screenshot2

In the above screenshot I manually scrolled down to the bottom, using the scroll bar on the right; revealing the before hidden text.

Is there a way to make sure that the RichTextBox automatically gets scrolled to the very end, every time?

  • not sure if this works, but try setting the caret position to the end of the textbox : `rtb_outputWindow.CaretPosition = rtb_outputWindow.CaretPosition.DocumentEnd;` – Timothy Groote Aug 24 '17 at 10:42
  • please check this https://stackoverflow.com/a/9418707/1849024 – imsome1 Aug 24 '17 at 10:42
  • @TimothyGroote RichTextBox doesn't contain a definition for 'CaretPosition'. –  Aug 24 '17 at 10:48
  • @imsome1 If you are referring to the accepted answer of that thread, then that's exactly what I'm currently doing. –  Aug 24 '17 at 10:48
  • @Phrosen oh, this is winforms. hang on – Timothy Groote Aug 24 '17 at 10:52
  • @TimothyGroote I often hear people ask if I'm using win.forms or not. I've come to the conclusion that more skilled programmers use something else? Not sure what to call it. Another API, maybe? I am assuming there are plenty to choose from. Could you recommend one that I should try out? Did you find a solution to my problem at hand, by the way? –  Aug 25 '17 at 09:17
  • @Phrosen their level of skill isn't necessarily a reason for using things other than winForms ;) it's partly a matter of preference. one definitely worth looking at is WPF (which i blindly assumed was the case here), but it introduces many new concepts and paradigms beyond the UI framework, so if you decide to learn about it, be prepared for a lot coming at you at the same time. Didn't find a solution to your problem just yet ; your code already does this the way it should be done. I do suspect your problem may be caused by the timing of the `textchanged` event. – Timothy Groote Aug 25 '17 at 10:43
  • 1
    try placing your "set caret and scroll to it" code directly after your last call to `updateOutputWindow` – Timothy Groote Aug 25 '17 at 10:44
  • did you try setting `rtb_outputWindow.HideSelection = false;` and then using `AppendText` to add the new lines to your textbox? (that should auto-scroll the text-box as well) – Timothy Groote Aug 25 '17 at 10:46

1 Answers1

2

This was adapted from this answer and solved the issue with the last line being cut off sometimes.

I extended the answer to work as a extension method on TextBoxBase so that it can work for both TextBox and RichTextBox.

Usage:

rtb_outputWindow.ScrollToBottom();

Implementation:

public static class RichTextBoxUtils
{
    [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 text box to the bottom.
    /// </summary>
    /// <param name="tb">The text box base to scroll</param>
    public static void ScrollToBottom(this System.Windows.Forms.TextBoxBase tb)
    {
        if (System.Environment.OSVersion.Platform != System.PlatformID.Unix)
            SendMessage(tb.Handle, WM_VSCROLL, new System.IntPtr(SB_BOTTOM), System.IntPtr.Zero);
    }

}
Moop
  • 3,414
  • 2
  • 23
  • 37