Poor Men's AboutBox with Animated Auto Scroll TextBox






4.17/5 (5 votes)
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