Introduction
I wanted to have a scrolling about box in my project that could display text, images, and automatically scroll them as a credits dialog. This is an additional feature I'd rather add to some of my finished applications. After spending many hours searching on the Internet, I found a few articles and example codes, and especially in this site, I was impressed by the following articles:
Both of the above are done well, but they were not what I wanted. These programs were developed in Visual C++ 6.0 or Visual C++ 7.1 (.NET) but using MFC because of which I couldn't build a C# control based on their modules. And I had to change them to fit them to my work.
Background
As said earlier, these example programs used MFC for coding convenience. The functions CreateCompatibleDC
, CreateCompatibleBitmap
and SelectObject
etc.. within MFC are common ways for image processing and operating with the device context of the drawing window. But, I now work in the .NET Framework, using either VB.NET or C#, so the above programs can't help me any longer.
I began searching on the Internet and looked in MSDN, and came to know that there was a workaround in C# to use the old Win32 API graphics functions for smooth drawing. The idea is to let C# know that you will be using a few functions from an unmanaged DLL, using the DllImport
attribute. The detailed documentation of DllImport
can be found in .NET documentation. I am a newbie in C#, so it's too difficult for me to try solving the problem in that way.
Fortunately, we can achieve the same goal with graphics' System.Drawing
namespace in .NET. Image rendering in .NET is much simple and efficient when compared to MFC. There are two functions in Graphics
class to render your Image
object on the screen, these are DrawImage
and DrawImageUnscaled
. So, we would do our off-screen drawing in an Image
object. After that, we can use these functions to render this object directly to DC and have the smooth animated effects.
As in my code, I'll try to draw all the display objects within the OnPaint()
event of the control:
private void ctlScrollAbout_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
using (System.Drawing.Graphics objGraphics = e.Graphics)
{
objGraphics.DrawImage(m_TempDrawing, m_XMargin, m_YMargin,
m_TempDrawing.Width, m_TempDrawing.Height);
}
}
It is not surprising if you are wondering when the off-screen was drawn. Usually, it is drawn just before we call the DrawImage
function. In this case, our control is an autoscroll aboutbox, so we must have a timer to operate the speed of scrolling. It's OK to draw the off-screen along with timer tick-event and call the OnPaint()
function manually. Look at this:
private void tmeScrolling_Tick(object sender, System.EventArgs e)
{
BuildScrollingBitMap();
this.Invalidate();
}
The next session will describe how the scrolling AboutBox administers its display objects. There are two kinds of display objects for this control: a text object and an image object. It is possible to use a common way that holds all these objects in a list. .NET supports some collection base objects such as ArrayList
, HashTable
, Queue
, Stack
, SortedList
etc., which can be used easily. But, we want our own list for the specific display objects, so we should inherit a new class from the available ones. We have clsDisplayList
to manage the display objects as shown below:
public class clsDisplayList : System.Collections.CollectionBase
{
public int Add(clsDisplayObject value)
{
return List.Add(value);
}
public clsDisplayObject this[int index]
{
get
{
return (clsDisplayObject)List[index];
}
set
{
List[index] = value;
}
}
}
For the display object, it is installed with a class which has all the necessary member variables and corresponding properties. The scrolling AboutBox would use these properties to draw the display object correctly on the screen:
public class clsDisplayObject
{
private string _displayText = "";
private System.Drawing.Font _objFont;
private System.Drawing.FontStyle _fontStyle =
System.Drawing.FontStyle.Bold;
private string _fontName = "Tahoma";
private int _fontSize = 10;
private System.Drawing.Brush _textColor =
System.Drawing.Brushes.White;
private bool _isBitMap = false;
private int _displayHeight = 0;
private int _displayYOffset = 0;
private System.Drawing.Bitmap _bitmap;
private int _bitmapHeight = 100;
private int _bitmapWidth = 100;
.....
}
In the control's class, we declare an instance of clsDisplayList()
and provide some methods to add a new display object:
public class ctlScrollAbout : System.Windows.Forms.UserControl
{
....
private clsDisplayList m_DisplayObject = new clsDisplayList();
...
public void AddDisplayText(string text, string fontName, ?
int fontSize, System.Drawing.FontStyle fontStyle,
System.Drawing.Brush textColor)
{
m_DisplayObject.Add(new clsDisplayObject(text, fontName,
fontSize, fontStyle, textColor));
BuildScrollingBitMap();
}
public void AddDisplayBitmap(string fileName,
int bmpHeight, int bmpWidth)
{
m_DisplayObject.Add(new clsDisplayObject(fileName,
bmpHeight, bmpWidth));
BuildScrollingBitMap();
}
}
Now that everything is clear you can integrate them to make your own control. For a step by step guide on creating a C# control, you can refer to the article: Simple introduction to writing your first .NET control.
Using the code
To use the above control in your application is very simple. Download the control source code and build it to make a C# control. It would be a DLL file in the compile output directory; in my case, it was .\bin\Debug\ScrollerAbout.dll.
After having the DLL file, you create a new Windows Application project. In the design window, please open the Toolbox tab and right click and choose Add/Remove Items. Then browse to our DLL file, select it and press OK. There is a scrolling aboutbox control in your Toolbox.
You can now drag the about control to any form in your .NET application and start using it. The following code shows how to initialize and pass parameters to the about control when a form loads:
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
ctrAbout.LineSpacing = 20
ctrAbout.XMargin = 20
ctrAbout.YMargin = 20
ctrAbout.ScrollingStep = 1
ctrAbout.ScrollingTime = 100
ctrAbout.AddDisplayText("Scrolling AboutBox", "Arial Black", _
15, System.Drawing.FontStyle.Bold, System.Drawing.Brushes.White)
ctrAbout.AddDisplayText("Developed by", "Arial Black", 10, _
System.Drawing.FontStyle.Italic, System.Drawing.Brushes.Olive)
ctrAbout.AddDisplayText("Man_Man2612", "Arial Black", 10, _
System.Drawing.FontStyle.Strikeout, System.Drawing.Brushes.Violet)
ctrAbout.AddDisplayBitmap("images\test.gif", 115, 115)
ctrAbout.AddDisplayBitmap("images\pic0.BMP", 100, 100)
ctrAbout.StartScrolling()
End Sub
// C# example code
private void Form1_Load(object sender, System.EventArgs e)
{
ctrAbout.LineSpacing = 20;
ctrAbout.XMargin = 20;
ctrAbout.YMargin = 20;
ctrAbout.ScrollingStep = 1;
ctrAbout.ScrollingTime = 500;
ctrAbout.AddDisplayText("Scrolling AboutBox", "Arial Black", _
15, System.Drawing.FontStyle.Bold, System.Drawing.Brushes.White);
ctrAbout.AddDisplayText("Developed by", "Arial Black", 10, _
System.Drawing.FontStyle.Italic, System.Drawing.Brushes.Olive);
ctrAbout.AddDisplayText("Man_Man2612", "Arial Black", 10, _
System.Drawing.FontStyle.Strikeout, System.Drawing.Brushes.Violet);
ctrAbout.AddDisplayBitmap(@"images\test.gif",115,115);
ctrAbout.AddDisplayBitmap(@"images\pic0.BMP",320,240);
ctrAbout.StartScrolling()
}
Summary
We now know how to create a custom user control for our specific purpose in .NET Framework. We also saw that making a new inherited collection class that is used to manage our own objects is very simple. This scrolling AboutBox has some advanced features that I would like to improve such as text wrapping, hyperlink object, animation image etc. But due to lack of time, I just created this article, and hope that with this open source code someone can help me make a new useful scrolling AboutBox version.
History
- 25th Oct, 2004 - Version 1.0.
- 20th Jan, 2006