Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Poor Men's AboutBox with Animated Auto Scroll TextBox

0.00/5 (No votes)
2 Oct 2014 1  
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.

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.

    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:

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:

/// <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:

/// <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:

/// <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.

 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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here