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

Label with shadow and animation

0.00/5 (No votes)
23 Mar 2008 1  
A label with shadow effect that can be animated using rotatation, transparency, and zoom.

Introduction

The control explained in the article is a label with added shadow effect and animation for transparency, zoom, and rotation. This was done in C# and .NET 2.0 (tested in .NET 3.5 and works fine).

Background

I needed a text control with cool effects for a project, and I decided to make a standalone control.

Using the code

You can use the control in two standard ways:

  • Include the project 'dzzControls' in your solution so it automatically appears in the Toolbox (in the dzzControls section), but it has a generic icon.
  • In the Toolbox, right click on 'General' and click 'Choose items...'. Click 'Browse' and find 'dzzControls.dll'. Make sure the checkbox next to 'EffectsLabel' is ticked, and click OK.

Now, drag and drop it onto the form. In Properties, choose the 'Categorized' view and go to the 'Effects' section. Play with the properties (changes are immediately visible in the designer).

The control exposes a few properties:

  • ShadowColor, combined with ForeColor and BackColor affect the colorization of the control.
  • ShadowColor makes sense only if ShadowOffset differs from the default 0; 0. X and Y values can be negative!
  • If MinZoom is below 100, the control will be animated with a gradual zoom between 100% and the set minimum percentage.
  • If MinAlpha is less than MaxAlpha, the control will be animated with a gradually changing transparency between the given values.
  • If MinRotate is less than MaxRotate, the control will be animated with a gradually rotating text between the specified angles (in degrees). Note: these values are limited to sbyte (-128 to +127), so changing these to match your own needs is an easy exercise.
  • Letterwise specifies whether effects are applied to individual letters or to the whole string (the Text property inherited from the Control).

A bit under the hood

The inherited properties Text, Font, ForeColor, and Enabled are overriden to accomodate control-specific logic.

The new properties (mentioned above) are all implemented with private variables, and setters usually contain some code (to refresh the control or similar). For example:

private byte _MinZoom;
[Category("Effects"), DefaultValue((byte)100),
Description("Animate text zoom, in range MinZoom%-100%")]
public byte MinZoom
{
    get { return _MinZoom; }
    set
    {
        _MinZoom = value <= 100 ? value : (byte)100;
        if (_MinZoom == 0)
            _MinZoom = 1;
        if (_CurrentZoom < _MinZoom)
            _CurrentZoom = _MinZoom;
        if (_MinZoom < 100)
        {
            aTimer.Start();
        }
        else
            RecalculateTimer();
        Refresh();
    }
}

There are also private variables which contain the current state of the animation, like:

private byte _CurrentZoom;
private sbyte _ZoomStep = 1;

Animation is achieved using an internal timer (called aTimer, with a timeout of 20ms - equivalent of 50fps). When the timer ticks, one step of the animation is performed:

private void aTimer_Tick(object sender, EventArgs e)//animation timer tick
{
    ...
    if (_MinZoom < 100)//zoom animation enabled?
    {
        if (_CurrentZoom == 100)
            _ZoomStep = (sbyte)-1;
        if (_CurrentZoom == _MinZoom)
            _ZoomStep = (sbyte)1;
        _CurrentZoom = (byte)(_CurrentZoom + _ZoomStep);
    }
    Refresh();//redraw control
}

The internal procedure RecalculateSize re-adjusts the size of the control when the text, font, min or max rotation changes. It also calculates the size of individual characters, and those sizes are used in the paint event handler.

The brains of the this custom control is the OnPaint event handler, and is way too large to be completely explained here, but the basic version is:

e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
//rotation is not smooth without anti-aliasing
e.Graphics.TranslateTransform(Size.Width / 2, Size.Height / 2);
//set coordinate system origin to center of the control
if (_CurrentRotate != 0)
    e.Graphics.RotateTransform(_CurrentRotate); //apply rotation ...
if (_CurrentZoom < 100)
    e.Graphics.ScaleTransform(_CurrentZoom / 100.0f, _CurrentZoom / 100.0f);
    //... and zoom
e.Graphics.DrawString(Text, Font, new SolidBrush(base.ForeColor), 
                      -tsize.Width / 2, -tsize.Height / 2);
//draw text in coordinate system, so text's 
//center matches coordinate system's center

Note: most of the properties are integral types (int, byte, sbyte). This was sufficient for my current needs, changing these to floats should be a nice exercise for the reader.

Some problems

When extra long strings are used (which I encountered during the use of this control), the control tends to put a high load on the processor if animation is enabled.

More than one of these controls on the form also tends to produce high processor usage if animation is enabled or controls are being moved over the form (and thus repeatedly redrawn).

Points of interest

The limitation of MeasureCharacterRanges to only 32 measured ranges made me rewrite the OnPaint for the letterwise case (after some time spent on debugging).

As this is my first control, I also spent quite some time on making the control 'Designer-friendly', e.g.:

[Category("Effects"), DefaultValue(typeof(Point), "0, 0"),
Description("If differs from (0,0), creates shadow" + 
            " with specified offset from Left and Top")]
public Point ShadowOffset
{
    get { ...

... so when not set, this property is not bolded in the Visual Studio properties grid.

History

  • The first version of the article was written on 11th March 2008.
  • 12th March 2008: Minor modification to source code + some unneeded properties are hidden from the Visual Studio designer property grid (used code provided by Bob Powell).
  • 24th March 2008: Replaced old demo application with new one (the old one required the DLL with the control).

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