Nefzen
Nefzen

Reputation: 7939

How to scroll down in a textbox by code in C#

I am using winforms, and I update a text box once in a while (showing messages). however, when the text reaches the end of the box it produces scrollbars and I don't know how to scroll down to the bottom. The only thing I see is ScrollToCaret, but Caret is at the beginning of the text. What is the command to scroll?

Upvotes: 29

Views: 47979

Answers (7)

Joe
Joe

Reputation: 21

After searching and never finding a legitimate solution that works with and without focus as well as horizontally and vertically, I stumbled across an API solution that works (at least for my platform - Win7 / .Net4 WinForms).

using System;
using System.Runtime.InteropServices;

namespace WindowsNative
{
    /// <summary>
    /// Provides scroll commands for things like Multiline Textboxes, UserControls, etc.
    /// </summary>
    public static class ScrollAPIs
    {
        [DllImport("user32.dll")]
        internal static extern int GetScrollPos(IntPtr hWnd, int nBar);

        [DllImport("user32.dll")]
        internal static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

        [DllImport("user32.dll")]
        internal static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

        public enum ScrollbarDirection
        {
            Horizontal = 0,
            Vertical = 1,
        }

        private enum Messages
        {
            WM_HSCROLL = 0x0114,
            WM_VSCROLL = 0x0115
        }

        public static int GetScrollPosition(IntPtr hWnd, ScrollbarDirection direction)
        {
            return GetScrollPos(hWnd, (int)direction);
        }

        public static void GetScrollPosition(IntPtr hWnd, out int horizontalPosition, out int verticalPosition)
        {
            horizontalPosition = GetScrollPos(hWnd, (int)ScrollbarDirection.Horizontal);
            verticalPosition = GetScrollPos(hWnd, (int)ScrollbarDirection.Vertical);
        }

        public static void SetScrollPosition(IntPtr hwnd, int hozizontalPosition, int verticalPosition)
        {
            SetScrollPosition(hwnd, ScrollbarDirection.Horizontal, hozizontalPosition);
            SetScrollPosition(hwnd, ScrollbarDirection.Vertical, verticalPosition);
        }

        public static void SetScrollPosition(IntPtr hwnd, ScrollbarDirection direction, int position)
        {
            //move the scroll bar
            SetScrollPos(hwnd, (int)direction, position, true);

            //convert the position to the windows message equivalent
            IntPtr msgPosition = new IntPtr((position << 16) + 4);
            Messages msg = (direction == ScrollbarDirection.Horizontal) ? Messages.WM_HSCROLL : Messages.WM_VSCROLL;
            SendMessage(hwnd, (int)msg, msgPosition, IntPtr.Zero);
        }
    }
}

With a multiline textbox (tbx_main) use like:

        int horzPos, vertPos;
        ScrollAPIs.GetScrollPosition(tbx_main.Handle, out horzPos, out vertPos);

        //make your changes
        //something like the following where m_buffer is a string[]
        tbx_main.Text = string.Join(Environment.NewLine, m_buffer);

        tbx_main.SelectionStart = 0;
        tbx_main.SelectionLength = 0;

        ScrollAPIs.SetScrollPosition(tbx_main.Handle, horzPos, vertPos);

Upvotes: 0

Toxig
Toxig

Reputation: 31

C# Use Scroll Up/Down by Windows API (user32.dll)

First, we have to define a constant value:

const int EM_LINESCROLL = 0x00B6;
const int SB_HORZ = 0;
const int SB_VERT = 1;

Then, we have to declare two external methods of user32.dll:

[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

Finally, use these methods to do the real thing:

SetScrollPos(myTextBox.Handle,SB_VERT,myTextBox.Lines.Length-1,true);
SendMessage(myTextBox.Handle,EM_LINESCROLL,0,myTextBox.Lines.Length-1);

Done! Simple and easy! Tested! original post

Upvotes: 3

Doctor Jones
Doctor Jones

Reputation: 21674

You can do this by making use of a function called ScrollToCaret. You need to first set the caret position to the end of the text box, then you can scroll to it. Here's how to do it:

        //move the caret to the end of the text
        textBox.SelectionStart = textBox.TextLength;
        //scroll to the caret
        textBox.ScrollToCaret();

Upvotes: 42

Julian
Julian

Reputation: 20324

This is a bit of an old question, but none of the suggested answers worked for me (ScrollToCaret() only works when the TextBox has focus). So in case any more should be searching for this at some point, I thought I'd share what I found to be the solution:

public class Utils
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, 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(TextBox tb)
    {
        SendMessage(tb.Handle, WM_VSCROLL, (IntPtr)SB_BOTTOM, IntPtr.Zero);
    }
}

Credit for the solution should go to this post at bytes.com: http://bytes.com/topic/c-sharp/answers/248500-scroll-bottom-textbox#post1005377

Upvotes: 31

Metro
Metro

Reputation: 1514

If you use the AppendText() method of the Textbox, the text will be added to the bottom of any existing text and the control will scroll to display it.

Upvotes: 17

Thomas Levesque
Thomas Levesque

Reputation: 292675

You can use the SetScrollPos API :

[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

[DllImport("user32.dll")]
static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);

const int SB_HORZ = 0;
const int SB_VERT = 1;
const int SB_CTL = 2;


...

void ScrollToBottom(Control ctl)
{
    int min;
    int max;
    if (GetScrollRange(ctl.Handle, SB_VERT, out min, out max))
    {
        SetScrollPos(ctl.Handle, SB_VERT, max, true);
    }
}

(untested)

Upvotes: 0

Francis B.
Francis B.

Reputation: 7208

You need to set your caret at the end of your text:

textBox1.Text += "your new text";
textBox1.Select(textBox1.Text.Length - 1, 0);
textBox1.ScrollToCaret();

Upvotes: 4

Related Questions