Click here to Skip to main content
15,879,095 members
Articles / Desktop Programming / Win32
Article

Scrolling a Rich/Textbox Automatically

Rate me:
Please Sign up or sign in to vote.
4.12/5 (9 votes)
1 Feb 2008CPOL4 min read 173.8K   3.6K   39   43
How to scroll a textbox by given pixels

Introduction

I’ve been faced with a problem of automatically scrolling a richtextbox. For example: scrolling one pixel every 40 milliseconds.

Using C# under Visual Studio 2005, I’ve dropped a new richtextbox onto my form and expected to see a method similar to scroll(int pixels) under the richtextbox’s available methods.

Using intellisense, we get the following relevant options: ScrollToCaret().

ScrollCaret() will scroll our textbox to a given text, surely that doesn't satisfy our needs.
Ok, so what else have we got? Surprisingly that is all.

Background

So how do we achieve a smooth auto scrolling effect?
We're going to use the Win32 API SendMessage method to send a scroll message to our textbox asking it to scroll itself in pixels.

In case you are not familiar with messages, I strongly recommend reading the following explanation: message_loop.

So How Does a Scroll Message Look Like?

Using Microsoft Spy ++ we are going to view all scroll messages sent to our textbox.
First, launch your ScrollTextBox application which should be a form with a rich/textbox with some text in it. This will give you a scroller to play with.
Then run Spy++ and click the log message icon (ctrl + m).

Drag and drop the scope onto your textbox, next click the Messages tab and select only the Scrollbar option under the Message groups, Click OK.
A new dialog should appear: “Massages (Window 000206B6) though you will probably get a different window number.

Now scroll your textbox using the up/down arrows, or dragging the scroller and watch Spy logs all scroll messages received by the textbox.

scrollMsg.JPG

A Typical Scroll Message

<0007>000206B6 S WM_VSCROLL nScrollCode:SB_THUMBTRACK nPos:16 hwndScrollBar:null) 
  • <0007> is just the logger line number
  • WM_VSCROLL is the type of the message, in our case a Vertical scroll message
  • SB_THUMBTRACK is the first parameter of the message.
    The first message parameter tells us what type of scroll is performed.
    In the example I have given, I'm dragging the scroller.

A full list of first parameter values is given below:

  • nPos specifies the position to scroll to, It is part of the first parameter and is available only for SB_THUMBPOSITION or SB_THUMBTRACK scrolling.
  • hwndScrollBar is the second parameter of the message and is always null.

Here is a list of low-order words of wParam values to a WM_VSCROLL message:

  • SB_LINEUP
  • SB_LINEDOWN
  • SB_THUMBPOSITION
  • SB_THUMBTRACK
  • SB_TOP
  • SB_BOTTOM
  • SB_ENDSCROLL
  • SB_PAGEDOWN
  • SB_PAGEUP

What our simple application will do is send a WM_VSCROLL message to the textbox using the SB_THUMBTRACK parameter. It will set the high-order word of wParam to the desired position we want the scroller to be at.

Importing user32.dll

In order to send messages, we'll need to import the sendmessage method from the Win32 API:

C#
[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
        protected static extern IntPtr SendMessage
	(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

Now we can send messages to any handle we get our hands on.

C#
int SB_LINEUP = 0; 
ptrWparam = new IntPtr(SB_LINEUP);
ptrLparam = new IntPtr(0);
SendMessage(txtArea.Handle, WM_VSCROLL, ptrWparam, ptrLparam); 

The above code will scroll txtArea one line up. To scroll a textbox by n pixels value, we'll need to do a little bit more work.

What we need is a way to determine where our scroller is at the moment. Then we could increase its position by a pixel value and all that's left is to send a new SB_THUMBTRACK message with the new position back to the textbox. Using the Win32 API GetScrollInfo method, we can get all kinds of information on a scroller bar:

C#
GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);  
  • Hwnd is an handle to our textbox.
  • fnBar is the size of the structure SCROLLINFO.
  • lpsi is a structure that will hold information about the scroller.

The SCROLLINFO structure:

C#
struct SCROLLINFO
{
    public uint cbSize;
    public uint fMask;
    public int nMin;
    public int nMax;
    public uint nPage;
    public int nPos;
    public int nTrackPos;
} 

For more information about the structure, visit MSDN.

What we'll need is the nPos variable which will hold the current scroller position. So our basic scroll method will do something like this:

C#
// Scrolls a given textbox. handle: an handle to our textbox. pixles: 
// number of pixels to scroll.
void scroll(IntPtr handle, int pixles)
{            
    // Get current scroller position
            
    SCROLLINFO si = new SCROLLINFO();
    si.cbSize = (uint)Marshal.SizeOf(si);
    si.fMask = (uint)ScrollInfoMask.SIF_ALL;
    GetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si);
            
    // Increase position by pixles
    si.nPos += pixles;
                        
    // Reposition scroller
    SetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si, true);

    // Send a WM_VSCROLL scroll message using SB_THUMBTRACK as wParam
    // SB_THUMBTRACK: low-order word of wParam, si.nPos high-order word of  wParam

    IntPtr ptrWparam = new IntPtr(SB_THUMBTRACK + 0x10000 * si.nPos);
    IntPtr ptrLparam = new IntPtr(0);
        SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);                
} 

That's it now to get the filling that the textbox is scrolling itself smoothly. Use a timer to call the above method say every 40 milliseconds and increase the scroller position by 1 pixel each time.

Ending

Surprisingly this simple "feature" is not built into the textbox functionality.
I've spent some time looking for a quick solution for my problem, but couldn't find one.
So I've decided to post my solution. I hope it will come in handy, In case you have any questions or comments, please feel free to post or you could email me.

History

  • 1st February, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect AVG
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionScroll to Centre Pin
Member 85806693-Dec-13 5:32
Member 85806693-Dec-13 5:32 
QuestionSolved: Experimenting changing colors, scroll stops at each last passed line instead of current position when paused? Pin
DarkTyranno4-Mar-13 3:25
DarkTyranno4-Mar-13 3:25 
SuggestionCaution about using WM_VSCROLL! Pin
HillBillyBoy20-Feb-13 12:13
HillBillyBoy20-Feb-13 12:13 
GeneralRe: Caution about using WM_VSCROLL! Pin
Lipman Roi22-Feb-13 1:11
Lipman Roi22-Feb-13 1:11 
GeneralRe: Caution about using WM_VSCROLL! Pin
vlad7812-Mar-13 14:05
vlad7812-Mar-13 14:05 
NewsThanks! Changed code for use in own project. Pin
DarkTyranno12-Feb-13 3:50
DarkTyranno12-Feb-13 3:50 
GeneralRe: Thanks! Changed code for use in own project. Pin
Lipman Roi12-Feb-13 8:01
Lipman Roi12-Feb-13 8:01 
QuestionThis is works for small number of text. Pin
vlad7817-Jun-12 14:33
vlad7817-Jun-12 14:33 
AnswerRe: This is works for small number of text. Pin
Lipman Roi7-Jun-12 20:10
Lipman Roi7-Jun-12 20:10 
Generalmajor help needed! Pin
vlad78127-Jan-11 13:10
vlad78127-Jan-11 13:10 
GeneralRe: major help needed! Pin
Lipman Roi27-Jan-11 22:50
Lipman Roi27-Jan-11 22:50 
GeneralRe: major help needed! [modified] Pin
vlad78128-Jan-11 4:28
vlad78128-Jan-11 4:28 
GeneralThank You Pin
Member 740954115-Nov-10 3:51
Member 740954115-Nov-10 3:51 
Questionhow do you change direction? Pin
cheborneck22-Mar-10 0:19
cheborneck22-Mar-10 0:19 
AnswerRe: how do you change direction? Pin
Lipman Roi22-Mar-10 8:04
Lipman Roi22-Mar-10 8:04 
GeneralRe: how do you change direction? Pin
cheborneck22-Mar-10 9:16
cheborneck22-Mar-10 9:16 
QuestionPlease help take a look at this issue Pin
zystory16-Dec-09 16:12
zystory16-Dec-09 16:12 
AnswerRe: Please help take a look at this issue Pin
Lipman Roi16-Dec-09 19:50
Lipman Roi16-Dec-09 19:50 
GeneralRe: Please help take a look at this issue Pin
zystory17-Dec-09 19:50
zystory17-Dec-09 19:50 
GeneralRefresh Content Pin
Alo198011-Dec-09 1:18
Alo198011-Dec-09 1:18 
Generalcorner case Pin
spelger30-Sep-09 6:08
spelger30-Sep-09 6:08 
GeneralRe: corner case Pin
Lipman Roi30-Sep-09 6:12
Lipman Roi30-Sep-09 6:12 
GeneralRe: corner case Pin
spelger30-Sep-09 6:34
spelger30-Sep-09 6:34 
GeneralPerfect! Pin
Vin552-Sep-09 7:15
Vin552-Sep-09 7:15 
GeneralRe: Perfect! Pin
Lipman Roi2-Sep-09 9:30
Lipman Roi2-Sep-09 9:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.