Select Page

It is often necessary to make a .NET RichTextBox scroll to the top or the bottom. Unfotunately there is no direct method of doing this in the class itself.
One possible solution involves using the ScrollToCaret() function of the control. This method is outlined in my first post about RichTextBox scrolling. It appears that some programmers have had problems with that solution though. It requires careful management of focus in the application to work under all circumstances.

The ScrollingRichTextBox

A far more elegant solution is to use the underlying message system to control the scroll. Using the SendMessage function it is possible to send a WM_VSCROLL message to the control that makes the control scroll without needing to worry about focus.
I think the best solution is to make a small class that inherits from RichTextBox, and neatly wraps the SendMessage calls necessary to make it work. Many programmers are unfamiliar with the syntax involved, so wrapping it in a more familiar syntax is a good idea.

The complete class looks like this:

class ScrollingRichTextBox : System.Windows.Forms.RichTextBox
{
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern IntPtr SendMessage(
    IntPtr hWnd,
    uint Msg,
    IntPtr wParam,
    IntPtr lParam);

  private const int WM_VSCROLL = 277;
  private const int SB_LINEUP = 0;
  private const int SB_LINEDOWN = 1;
  private const int SB_TOP = 6;
  private const int SB_BOTTOM = 7;

  public void ScrollToBottom()
  {
    SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_BOTTOM), new IntPtr(0));
  }

  public void ScrollToTop()
  {
    SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_TOP), new IntPtr(0));
  }

  public void ScrollLineDown()
  {
    SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_LINEDOWN), new IntPtr(0));
  }

  public void ScrollLineUp()
  {
    SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_LINEUP), new IntPtr(0));
  }
}

Feel free to steal…

How it works

The class imports the SendMessage function from the user32.dll system library. I’m not gonna go deeply into that function in this post. It is insanely powerfull and deserves it’s own post someday. It allows the program to send native windows messages to the control. The message in play here is the WM_VSCROLL message that takes a parameter that tells it how to scroll. These parameters are constants that are defined in the winuser.h header file.

I have implemented four functions in this class, allowing it to scroll to the top and bottom, as well as a single line up and down.

With the SendMessage function imported and using winuser.h as a reference you could easily implement even more functionality in the class, such as pageup/pagedown (SB_PAGEUP/SB_PAGEDOWN), but i don’t want to bloat the class with that for this article. The principle is what counts here.

A simple usage example

For applications that require this sort of scrolling, using the ScrollingRichTextBox over the ordinary RichTextBox is the way to go. In a previous blog post, i talked about hooking up to the OnTextChanged event of a RichTextBox and using ScrollToCaret() to do the scrolling. A method that has a few issues.
Now, using the ScrollingRichTextBox, these issues are resolved and the complete code for that event looks like this:

private void scrollingRichTextBox_TextChanged(object sender, EventArgs e)
{
  scrollingRichTextBox.ScrollToBottom();
}

Neat huh?