Click here to Skip to main content
15,884,425 members
Articles / Programming Languages / C#
Tip/Trick

Poor Men's AboutBox with Animated Auto Scroll TextBox

Rate me:
Please Sign up or sign in to vote.
4.17/5 (5 votes)
2 Oct 2014CPOL 13.6K   257   10   3
How to make from a simple TextBox an animated eye candy.

Introduction

The standard AboutBox of Visual Studio contains a TextBox where you can show some useful information about your program. I wanted to implement some animation in it, so I made this simple extension for automatic scrolling.

Image 1

Using the Code

Add AboutBox class to your project, and you can use it as is.

The Code

We need a separate thread for the animation, an event to be able to stop/start it and another event to indicate if the thread is ready.

C#
    partial class AboutBox : Form
    {
        // BackgroundWorker for the animation
        BackgroundWorker scroller = new BackgroundWorker();
        // If this event is signaled, the scrolling will stop
        ManualResetEvent scrollStop = new ManualResetEvent(true);
        // Closing the form should wait till the thread exits
        AutoResetEvent scrollThreadReady = new AutoResetEvent(false);
...

In the constructor, you can fill the TextBox and set the properties of the animation thread:

C#
public AboutBox()
{
    InitializeComponent();
...
    // Add the content of the ReadMe.txt into the TextBox
    string readMeFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ReadMe.txt");
    if (File.Exists(readMeFile))
        textBoxDescription.Text = File.ReadAllText(readMeFile);

    // With mouse click you can start/stop the animation
    textBoxDescription.MouseClick += new MouseEventHandler(textBoxDescription_MouseClick);
    // Set scroller thread
    scroller.DoWork += new DoWorkEventHandler(scroller_DoWork);
    scroller.WorkerSupportsCancellation = true;
}

MouseClick event handler will signal the scrollStop event:

C#
/// <summary>
/// MouseClick on textbox stops/starts scrolling
/// </summary>
void textBoxDescription_MouseClick(object sender, EventArgs e)
{
  // WaitOne(0) returns immediately with true if signaled or false if not signaled
  if (scrollStop.WaitOne(0))
    scrollStop.Reset();
  else
    scrollStop.Set();
}

DoWork event handler:

C#
/// <summary>
/// Scroller thread
/// </summary>
void scroller_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        Debug.WriteLine("Scroll thread started.");

        int direction = 1;
        int line = -1;
        while (true)
        {
            if (scroller.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            // If mouse clicked on the box, we'll wait until the next click.
            scrollStop.WaitOne();

            int maxLine = textBoxDescription.Lines.Length - 1;
            if (line >= -1 && line <= maxLine) line = direction > 0 ? line + 1 : line - 1;
            if (line == 0 && direction < 0) direction = 1;
            if (line == maxLine && direction > 0) direction = -1;

            BeginInvoke((MethodInvoker)(() => ScrollByLine(textBoxDescription, direction)));

            if (!scroller.CancellationPending)
            {
                Thread.Sleep(300);
            }
        }
    }
    finally
    {
        Debug.WriteLine("Scroll thread ended.");
        scrollThreadReady.Set();
    }
}

The very simple scroll method:

C#
/// <summary>
/// Scrolls a textbox by line up or down
/// </summary>
/// <param name="textBox">The textbox control</param>
/// <param name="line">if negative, scrolling will go up, else down</param>
void ScrollByLine(TextBox textBox, int line)
{
    int firstCharIndex = textBox.GetFirstCharIndexOfCurrentLine();
    int lineNumber = textBox.GetLineFromCharIndex(firstCharIndex);
    int lineCount = textBox.Lines.Length;

    lineNumber = lineNumber + line < 0 ?
      0 : (lineNumber + line >= lineCount ?
      lineCount - 1 : lineNumber + line);

    int charIndex = textBox.GetFirstCharIndexFromLine(lineNumber);

    // select the button, so selection in the textbox won't be visible
    okButton.Select();

    // this will do the scrolling
    textBox.Select(0, charIndex);
    textBox.ScrollToCaret();
}

We should set the appropriate events before start and stop the scroller thread. If the window is not visible, we stop the thread.

C#
private void AboutBox_VisibleChanged(object sender, EventArgs e)
{
    if (Visible)
    {
        scrollThreadReady.Reset();
        scroller.RunWorkerAsync();
    }
    else
    {
        scroller.CancelAsync();
        scrollStop.Set();
    }
}

private void AboutBox_FormClosing(object sender, FormClosingEventArgs e)
{
    scroller.CancelAsync();
    scrollStop.Set();
    Debug.WriteLine("Wait for ending scroll thread.");
    scrollThreadReady.WaitOne();
    Debug.WriteLine("Scroll thread ready event received.");
}

That's it.

Points of Interest

With these few changes, you can make your AboutBox a bit special.

History

  • 02.10.2014 Initial version

License

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


Written By
Hungary Hungary
I'm software developer & scrum master with several years of experience in project and line management.

Comments and Discussions

 
GeneralMy vote of 2 Pin
bekiser3-Oct-14 6:43
bekiser3-Oct-14 6:43 
GeneralRe: My vote of 2 Pin
Akos Mattiassich5-Oct-14 23:32
Akos Mattiassich5-Oct-14 23:32 
GeneralRe: My vote of 2 Pin
John B Oliver13-Oct-14 11:22
John B Oliver13-Oct-14 11:22 
You not being able to see a use for this tip does not negate the fact that this tip does show how to automatically scroll a multi-line text box.
If the text scrolls too fast, change the Thread.Sleep() value.

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.