Click here to Skip to main content
11,704,315 members (48,412 online)
Click here to Skip to main content

Stick Figure Animation Using C# and WPF

, 14 Oct 2010 CPOL 135.8K 1.6K 147
Rate this:
Please Sign up or sign in to vote.
Discover how to create complex stick figure animations using simple WPF or Silverlight elements.

StickFigure

Table of Contents

Introduction

Recently I wanted to create a kind of stick figure animation in WPF or Silverlight, but I found no material on the issue. I got frustrated and then decided to do something myself, and fortunately I was successful. This article describes, in some detail, how to create a stick figure animation in WPF, although I'm sure it could be easily ported to Silverlight. This article is intended to share some nice discoveries with the readers.

System Requirements

If you already have Visual Studio 2008 or Visual Studio 2010, that's enough to run the application. If you don't, you can download the following 100% free development tool directly from Microsoft:

Background

For some time, I wondered how to create a pivot stick animation using WPF or Silverlight. In the first attempt, I used sticks that moved independently on a canvas surface. But instead of using the standard WPF Animation classes, I had to control the animation all by myself, using timers to update both the angle and the positions of each individual stick, and also taking rotation speed into consideration. Since a stick figure is an articulated system, when one member is rotated, the dependent members must be rotated accordingly. For example, if I rotated a leg, I also had to rotate the foreleg accordingly, as well as re-calculate the foreleg coordinates based on the new position of the knee. And this was really a cumbersome task to do.

After struggling a lot with the code, in the end, it worked well, but realized that I ended up creating a little monster, a real code horror, and then decided to throw it away and start over from scratch.

The idea is that, in any articulated body, I can choose one particular segment of that body as the "root" for the whole body, and then "link" pieces successively at the edges of the first segment, creating a chain of segments. The good news is that it can be accomplished in WPF (or Silverlight if you wish) by creating a Grid element to represent each individual segment, and adding other Grid elements as child elements of the root segment. The Grid element is the most powerful visual element, and it's not without reason. The magic is done by creating three ColumnDefinitions inside the Grid: one ColumnDefinition residing in the middle of the segment and determines the extension of the segment, while the other two staying at the edges and acting as pivot joints for the child segments.

The Base Segment

The Base Segment

BaseSegment is the abstract class from which we derive the other segment classes. Notice that it does not have any appearance. Instead, it only defines the three grid columns as seen in the figure above.

protected virtual void InitializeSegment()
{
    this.ShowGridLines = false;
    this.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
    this.ColumnDefinitions.Add(new ColumnDefinition() { 
              Width = GridLength.Auto, MinWidth = segmentWidth  });
    this.ColumnDefinitions.Add(new ColumnDefinition() { 
              Width = new GridLength(segmentLength) });
    this.ColumnDefinitions.Add(new ColumnDefinition() { 
              Width = GridLength.Auto, MinWidth = segmentWidth  });

    st = new ScaleTransform()
    {
    };

    tt = new TranslateTransform()
    {
        X = 0,
        Y = 0
    };

    rt = new RotateTransform()
    {
        CenterX = segmentWidth,
        CenterY = segmentWidth
    };

    TransformGroup tGroup = new TransformGroup();

    tGroup.Children.Add(st);
    tGroup.Children.Add(rt);
    tGroup.Children.Add(tt);
    this.RenderTransform = tGroup;
}

The Circle Segment

The Circle Segment

The Circle Segment is used only in the Head of the stick figure. The circle is positioned at the central column, and the two corners at the edge are used as pivot points:

protected override void InitializeSkin()
{
    this.ColumnDefinitions[1].Width = new GridLength(segmentLength * 2);
    this.Height = segmentLength * 2;

    Rectangle rect = new Rectangle()
    {
        Stroke = new SolidColorBrush(Colors.White),
        StrokeThickness = 0.5,
        HorizontalAlignment = HorizontalAlignment.Stretch,
        VerticalAlignment = VerticalAlignment.Stretch,
        RadiusX = segmentWidth * 2,
        RadiusY = segmentWidth * 2
    };
    rect.SetValue(Grid.ColumnProperty, 1);
    rect.SetValue(Panel.ZIndexProperty, 1);

    this.Children.Add(rect);
}

The Axis Segment

The Axis Segment

The AxisSegment is used in almost every part in our stick figure. The code below shows that the "skin" of the axis segment is defined by a round-cornered rectangle that spans over the three columns of the BaseSegment element.

protected override void InitializeSkin()
{
    rect = new Rectangle()
    {
        Stroke = new SolidColorBrush(Colors.White),
        StrokeThickness = 0.5,
        Width = segmentLength * 2,
        MaxWidth = segmentLength * 2,
        Height = segmentWidth * 2,
        RadiusX = segmentWidth,
        RadiusY = segmentWidth,
        HorizontalAlignment = HorizontalAlignment.Left,
        VerticalAlignment = VerticalAlignment.Stretch,
        Margin = new Thickness(0, 0, 0, 0)
    };

    rect.SetValue(Grid.ColumnProperty, 0);
    rect.SetValue(Grid.ColumnSpanProperty, 3);
    
    Rectangle dash1 = new Rectangle()
    {
        Stroke = new SolidColorBrush(Colors.Red),
        StrokeDashArray = new DoubleCollection(new double[]{4,4}),
        StrokeThickness = 1,
        Width = 1,
        HorizontalAlignment = HorizontalAlignment.Left,
        VerticalAlignment = VerticalAlignment.Stretch
    };

    Rectangle dash2 = new Rectangle()
    {
        Stroke = new SolidColorBrush(Colors.Green),
        StrokeDashArray = 
          new DoubleCollection(new double[] { 2, 2 }.ToList()),
        StrokeThickness = 1,
        Width = 1,
        HorizontalAlignment = HorizontalAlignment.Right,
        VerticalAlignment = VerticalAlignment.Stretch
    };

    dash1.SetValue(Grid.ColumnProperty, 1);
    dash2.SetValue(Grid.ColumnProperty, 1);

    this.Children.Add(dash1);
    this.Children.Add(dash2);

    this.Children.Add(rect);
}

Building Mr. StickMan: Head and Trunk

Head And Trunk

The Head is the first part in the stick figure. Then the Trunk is added as a child, positioned at the third column of the Head segment. Notice that, since the columns are positioned horizontally, we have to rotate the head 90 degrees so that the body can stand vertically. The head has a length of 10, while the Trunk has a length of 20. The Trunk is attached to PivotPoint P2 of the Head, that is, at the bottom of the Head segment:

private void CreateStickFigure()
{
    ...

    head = new CircleSegment(10);
    head.TT.X = currentPoint.X;
    head.TT.Y = currentPoint.Y;
    head.RT.Angle = 90;
    head.VerticalAlignment = VerticalAlignment.Top;
    head.HorizontalAlignment = HorizontalAlignment.Left;

    trunk = new AxisSegment(20);

    ...

    head.AddChildElement(trunk, PivotPoint.P2, Layer.ForeGround);

    ...

    this.Children.Add(head);
}

Head, Trunk, and Arms

Head, Trunk And Arms

The arms must be positioned at the shoulder point of the stick figure; that is, the arms are children of the Trunk segment and positioned at the PivotPoint P1, that is, the first column of the grid, at the top of the Trunk.

private void CreateStickFigure()
{
    ...

    head = new CircleSegment(10);
    head.TT.X = currentPoint.X;
    head.TT.Y = currentPoint.Y;
    head.RT.Angle = 90;
    head.VerticalAlignment = VerticalAlignment.Top;
    head.HorizontalAlignment = HorizontalAlignment.Left;

    trunk = new AxisSegment(20);

    ...
    
    arm1 = new AxisSegment(12);
    arm2 = new AxisSegment(12);
    
    ...

    trunk.AddChildElement(arm1, PivotPoint.P1, Layer.BackGround);
    trunk.AddChildElement(arm2, PivotPoint.P1, Layer.ForeGround);

    head.AddChildElement(trunk, PivotPoint.P2, Layer.ForeGround);

    ...

    this.Children.Add(head);
}

The Whole Body

The Whole Body

Now we have all the body segments. The segment hierarchy is defined by the tree list below:

  • Head
    • Trunk
      • Left Arm
        • Left Forearm
      • Right Arm
        • Right Forearm
      • Left Leg
        • Left Foreleg
      • Right Leg
        • Right Foreleg

Here is the code for building all parts of the body of Mr. StickMan:

private void CreateStickFigure()
{
    ...

    head = new CircleSegment(10);
    head.TT.X = currentPoint.X;
    head.TT.Y = currentPoint.Y;
    head.RT.Angle = 90;
    head.VerticalAlignment = VerticalAlignment.Top;
    head.HorizontalAlignment = HorizontalAlignment.Left;

    trunk = new AxisSegment(20);

    leg1 = new AxisSegment(15);
    leg1.Margin = new Thickness(5, 0, 0, 0);

    leg2 = new AxisSegment(15);
    leg2.Margin = new Thickness(5, 0, 0, 0);

    foreleg1 = new AxisSegment(15);
    foreleg2 = new AxisSegment(15);
    arm1 = new AxisSegment(12);
    arm2 = new AxisSegment(12);
    forearm1 = new AxisSegment(12);
    forearm2 = new AxisSegment(12);

    ...

    leg1.AddChildElement(foreleg1, PivotPoint.P2, Layer.BackGround);
    leg2.AddChildElement(foreleg2, PivotPoint.P2, Layer.ForeGround);
    arm1.AddChildElement(forearm1, PivotPoint.P2, Layer.BackGround);
    arm2.AddChildElement(forearm2, PivotPoint.P2, Layer.ForeGround);

    trunk.AddChildElement(leg1, PivotPoint.P2, Layer.BackGround);
    trunk.AddChildElement(leg2, PivotPoint.P2, Layer.ForeGround);

    trunk.AddChildElement(arm1, PivotPoint.P1, Layer.BackGround);
    trunk.AddChildElement(arm2, PivotPoint.P1, Layer.ForeGround);

    head.AddChildElement(trunk, PivotPoint.P2, Layer.ForeGround);

    ...

    this.Children.Add(head);
}

Setting Up Chained Animations

Here is the heart of our stick figure animation. The SetAngleAnimations method exists inside the BaseSegment class, and defines a sequence of animations from a given array of predefined angles. All you have to do is pass to the method the name of the animation key, an array of angles (which will become the start angle and end angle for each stick member), and finally define whether the animation is continuous or not. Notice that for a given array of N angles, the method not only creates N - 1 animations, but also implements the Completed event of each animation, so that after any animation is completed, another animation is started:

public void SetAngleAnimations(string key, int[] angles, bool repeatForever)
{
    List<DoubleAnimation> angleAnimationList;
    if (!angleAnimationDictionary.ContainsKey(key))
    {
        angleAnimationList = new List<DoubleAnimation>();
        angleAnimationDictionary.Add(key, angleAnimationList);
    }
    else
    {
        angleAnimationList = angleAnimationDictionary[key];
    }

    angleAnimationList.Clear();
    for (int i = 0; i < angles.Length - 1; i++)
    {
        DoubleAnimation da = new DoubleAnimation()
            {
                Name = "da" + i.ToString(),
                Duration = 
                  new Duration(new TimeSpan(0, 0, 0, 0, minAnimationDuration))
            };

        angleAnimationList.Add(da);
    }

    for (int i = 0; i < angleAnimationList.Count; i++)
    {
        angleAnimationList[i].From = angles[i];
        angleAnimationList[i].To = angles[i + 1];
        if (i < angleAnimationList.Count - 1)
        {
            angleAnimationList[i].Completed += (sender, e) =>
                {
                    var clock = sender as AnimationClock;
                    var animation = clock.Timeline as DoubleAnimation;
                    int nextIndex = Convert.ToInt32(
                       (animation.Name.Replace("da", ""))) + 1;
                    this.BeginAngleAnimation(angleAnimationList[nextIndex]);
                };
        }
        else
        {
            if (repeatForever)
            {
                angleAnimationList[i].Completed += (sender, e) =>
                {
                    var clock = sender as AnimationClock;
                    var animation = clock.Timeline as DoubleAnimation;
                    int nextIndex = 0;
                    this.BeginAngleAnimation(angleAnimationList[nextIndex]);
                };
            }
        }
    }
}

That being said, let's take a look at the SetupAngleAnimations method, which defines the animations for each member of Mr. StickMan's body:

private void SetupAngleAnimations()
{
    leg1.SetAngleAnimations("walkToEast", 
       new int[] { MAX_LEG_ANGLE_WALK, MAX_LEG_ANGLE_WALK, 0, 
       -MAX_LEG_ANGLE_WALK, 0 }, false);
    leg2.SetAngleAnimations("walkToEast", 
       new int[] { -MAX_LEG_ANGLE_WALK, -MAX_LEG_ANGLE_WALK, 0, 
       MAX_LEG_ANGLE_WALK, 0 }, false);
    foreleg1.SetAngleAnimations("walkToEast", 
       new int[] { MIN_FORELEG_ANGLE_WALK, MAX_FORELEG_ANGLE_WALK, 0, 
       MIN_FORELEG_ANGLE_WALK, 0 }, false);
    foreleg2.SetAngleAnimations("walkToEast", 
       new int[] { MAX_FORELEG_ANGLE_WALK, MIN_FORELEG_ANGLE_WALK, 0, 
       MAX_FORELEG_ANGLE_WALK, 0 }, false);
    arm1.SetAngleAnimations("walkToEast", 
       new int[] { 0, -MAX_ARM_ANGLE_WALK, 0, MAX_ARM_ANGLE_WALK, 0 }, false);
    arm2.SetAngleAnimations("walkToEast", 
       new int[] { 0, MAX_ARM_ANGLE_WALK, 0, -MAX_ARM_ANGLE_WALK, 0 }, false);
    forearm1.SetAngleAnimations("walkToEast", 
       new int[] { 0, MIN_FOREARM_ANGLE_WALK, 0, MAX_FOREARM_ANGLE_WALK, 0 }, false);
    forearm2.SetAngleAnimations("walkToEast", 
       new int[] { 0, -MIN_FOREARM_ANGLE_WALK, 0, -MAX_FOREARM_ANGLE_WALK, 0 }, false);

    leg1.SetAngleAnimations("walkToWest", 
       new int[] { -MAX_LEG_ANGLE_WALK, -MAX_LEG_ANGLE_WALK, 0, 
       MAX_LEG_ANGLE_WALK, 0 }, false);
    leg2.SetAngleAnimations("walkToWest", 
       new int[] { MAX_LEG_ANGLE_WALK, MAX_LEG_ANGLE_WALK, 0, 
       -MAX_LEG_ANGLE_WALK, 0 }, false);
    foreleg1.SetAngleAnimations("walkToWest", 
       new int[] { -MIN_FORELEG_ANGLE_WALK, -MAX_FORELEG_ANGLE_WALK, 0, 
       -MIN_FORELEG_ANGLE_WALK, 0 }, false);
    foreleg2.SetAngleAnimations("walkToWest", 
      new int[] { -MAX_FORELEG_ANGLE_WALK, -MIN_FORELEG_ANGLE_WALK, 0, 
      -MAX_FORELEG_ANGLE_WALK, 0 }, false);
    arm1.SetAngleAnimations("walkToWest", 
       new int[] { 0, MAX_ARM_ANGLE_WALK, 0, -MAX_ARM_ANGLE_WALK, 0 }, false);
    arm2.SetAngleAnimations("walkToWest", 
       new int[] { 0, -MAX_ARM_ANGLE_WALK, 0, MAX_ARM_ANGLE_WALK, 0 }, false);
    forearm1.SetAngleAnimations("walkToEast", 
       new int[] { 0, -MIN_FOREARM_ANGLE_WALK, 0, -MAX_FOREARM_ANGLE_WALK, 0 }, false);
    forearm2.SetAngleAnimations("walkToEast", 
       new int[] { 0, MIN_FOREARM_ANGLE_WALK, 0, MAX_FOREARM_ANGLE_WALK, 0 }, false);

    leg2.SetAngleAnimations("kickToEast", new int[] { -15, -45, -90, -15, 0 }, false);
    foreleg2.SetAngleAnimations("kickToEast", new int[] { 0, 90, 15, 15, 0 }, false);
    arm1.SetAngleAnimations("kickToEast", new int[] { 0, 0, 0, 0, 0 }, false);
    arm2.SetAngleAnimations("kickToEast", new int[] { 0, MAX_ARM_ANGLE_WALK / 2, 
    MAX_ARM_ANGLE_WALK, MAX_ARM_ANGLE_WALK / 2, 0 }, false);
    forearm1.SetAngleAnimations("kickToEast", 
      new int[] { 0, -MAX_FOREARM_ANGLE_WALK * 2, -MAX_FOREARM_ANGLE_WALK * 2, 
      -MAX_FOREARM_ANGLE_WALK * 2, 0 }, false);
    forearm2.SetAngleAnimations("kickToEast", 
       new int[] { 0, MIN_FOREARM_ANGLE_WALK * 2, MIN_FOREARM_ANGLE_WALK * 2, 
       MIN_FOREARM_ANGLE_WALK * 2, 0 }, false);

    leg2.SetAngleAnimations("kickToWest", new int[] { 0, 0, 90, 15, 0 }, false);
    foreleg2.SetAngleAnimations("kickToWest", new int[] { 0, -90, -15, -15, 0 }, false);
    arm1.SetAngleAnimations("kickToWest", new int[] { 0, 0, 0, 0, 0 }, false);
    arm2.SetAngleAnimations("kickToWest", 
       new int[] { 0, -MAX_ARM_ANGLE_WALK / 2, -MAX_ARM_ANGLE_WALK, 
       -MAX_ARM_ANGLE_WALK / 2, 0 }, false);
    forearm1.SetAngleAnimations("kickToWest", 
       new int[] { 0, MAX_FOREARM_ANGLE_WALK * 2, MAX_FOREARM_ANGLE_WALK * 2, 
       MAX_FOREARM_ANGLE_WALK * 2, 0 }, false);
    forearm2.SetAngleAnimations("kickToWest", 
       new int[] { 0, -MIN_FOREARM_ANGLE_WALK * 2, -MIN_FOREARM_ANGLE_WALK * 2, 
       -MIN_FOREARM_ANGLE_WALK * 2, 0 }, false);
}

Notice what's being done here: The SetAngleAnimations method is doing all the boring task of defining the rotation animations for us and wiring up those animations with the corresponding stick figure members. Besides, you could create more animations just by adding more elements to the int[] array passed to the SetAngleAnimations method.

What's great about this technique is that you don't have to rotate or move each segment independently anymore - when you move or rotate a "parent" member (in the member hierarchy), all child members will move or rotate automatically! Then we no more have a bunch of pieces dropped on the screen, but a much more consistent "body". Although this is a stick figure animation, it could be easily modified to create structured body animations such as windmills, Ferris wheels, robotic arms, mechanical engines, and so on - sky is the limit!

So after we set up the classes, Mr. StickMan can easily walk around and kick with pretty little effort. I'm sure you could add more interesting movements, such as running, or even doing a "Roundhouse Kick" just like Chuck Norris.

Final Considerations

I'd like to thank you for the patience for reading the article, and I want to know what you think about the concepts presented here. I'm sure there are some improvements that can be made, so please give your feedback, especially if this article was useful for you in some way.

History

  • 2010-09-18: Initial version.

License

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

Share

About the Author

Marcelo Ricardo de Oliveira
Software Developer
Brazil Brazil
Marcelo Ricardo de Oliveira is a senior software developer who lives with his lovely wife Luciana and his little buddy and stepson Kauê in Guarulhos, Brazil, is co-founder of the Brazilian TV Guide TV Map and currently works for ILang Educação.

He is often working with serious, enterprise projects, although in spare time he's trying to write fun Code Project articles involving WPF, Silverlight, XNA, HTML5 canvas, Windows Phone app development, game development and music.

Published Windows Phone apps:


Awards:

CodeProject MVP 2012
CodeProject MVP 2011

Best Web Dev article of March 2013
Best Web Dev article of August 2012
Best Web Dev article of May 2012
Best Mobile article of January 2012
Best Mobile article of December 2011
Best Mobile article of October 2011
Best Web Dev article of September 2011
Best Web Dev article of August 2011
HTML5 / CSS3 Competition - Second Prize
Best ASP.NET article of June 2011
Best ASP.NET article of May 2011
Best ASP.NET article of April 2011
Best C# article of November 2010
Best overall article of November 2010
Best C# article of October 2010
Best C# article of September 2010
Best overall article of September 2010
Best overall article of February 2010
Best C# article of November 2009

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
Mika Wendelius25-Sep-12 18:58
mvpMika Wendelius25-Sep-12 18:58 
QuestionVery nice Pin
CIDev19-Sep-12 20:00
memberCIDev19-Sep-12 20:00 
AnswerRe: Very nice Pin
Marcelo Ricardo de Oliveira22-Sep-12 12:50
mvpMarcelo Ricardo de Oliveira22-Sep-12 12:50 
GeneralMy Vote of 5 Pin
RaviRanjankr18-Jul-11 4:49
memberRaviRanjankr18-Jul-11 4:49 
GeneralRe: My Vote of 5 Pin
Marcelo Ricardo de Oliveira18-Jul-11 6:19
mvpMarcelo Ricardo de Oliveira18-Jul-11 6:19 
GeneralMy vote of 5 Pin
pophelix2-Apr-11 20:55
memberpophelix2-Apr-11 20:55 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira7-Apr-11 4:44
mvpMarcelo Ricardo de Oliveira7-Apr-11 4:44 
GeneralMy vote of 5 Pin
MSHAO9-Dec-10 13:30
memberMSHAO9-Dec-10 13:30 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira11-Dec-10 6:49
memberMarcelo Ricardo de Oliveira11-Dec-10 6:49 
GeneralMy vote of 5 also Pin
Richard Weselny25-Nov-10 2:31
memberRichard Weselny25-Nov-10 2:31 
GeneralRe: My vote of 5 also Pin
Marcelo Ricardo de Oliveira25-Nov-10 9:48
memberMarcelo Ricardo de Oliveira25-Nov-10 9:48 
GeneralMy vote of 5 Pin
Richard Weselny25-Nov-10 2:31
memberRichard Weselny25-Nov-10 2:31 
GeneralMy vote of 5 Pin
Baesky27-Oct-10 21:10
memberBaesky27-Oct-10 21:10 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira28-Oct-10 2:02
memberMarcelo Ricardo de Oliveira28-Oct-10 2:02 
GeneralMy vote of 5 Pin
Andre' Gardiner27-Oct-10 12:11
memberAndre' Gardiner27-Oct-10 12:11 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira27-Oct-10 21:08
memberMarcelo Ricardo de Oliveira27-Oct-10 21:08 
GeneralMy vote of 5 Pin
Abhijit Jana26-Oct-10 7:49
mvpAbhijit Jana26-Oct-10 7:49 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira26-Oct-10 13:09
memberMarcelo Ricardo de Oliveira26-Oct-10 13:09 
GeneralCongrats! Pin
Al-Farooque Shubho26-Oct-10 0:52
mvpAl-Farooque Shubho26-Oct-10 0:52 
GeneralRe: Congrats! Pin
Marcelo Ricardo de Oliveira26-Oct-10 3:52
memberMarcelo Ricardo de Oliveira26-Oct-10 3:52 
GeneralMuito bom (very good) Pin
antoniohlopes25-Oct-10 15:13
memberantoniohlopes25-Oct-10 15:13 
GeneralRe: Muito bom (very good) Pin
Marcelo Ricardo de Oliveira26-Oct-10 0:23
memberMarcelo Ricardo de Oliveira26-Oct-10 0:23 
GeneralThe whole Brazilian coders community is proud of you!! Pin
Gerson Freire25-Oct-10 11:13
memberGerson Freire25-Oct-10 11:13 
GeneralRe: The whole Brazilian coders community is proud of you!! Pin
Marcelo Ricardo de Oliveira25-Oct-10 12:46
memberMarcelo Ricardo de Oliveira25-Oct-10 12:46 
GeneralMy vote of 5 Pin
Josh Fischer20-Oct-10 6:09
mvpJosh Fischer20-Oct-10 6:09 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira21-Oct-10 0:25
memberMarcelo Ricardo de Oliveira21-Oct-10 0:25 
GeneralMy vote of 5 Pin
JFergulbops14-Oct-10 23:19
memberJFergulbops14-Oct-10 23:19 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira15-Oct-10 4:20
memberMarcelo Ricardo de Oliveira15-Oct-10 4:20 
GeneralMy vote of 5 Pin
JWhattam14-Oct-10 13:36
memberJWhattam14-Oct-10 13:36 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira15-Oct-10 4:18
memberMarcelo Ricardo de Oliveira15-Oct-10 4:18 
GeneralVote of 5 Pin
Kelvin Armstrong14-Oct-10 1:07
memberKelvin Armstrong14-Oct-10 1:07 
GeneralRe: Vote of 5 Pin
Marcelo Ricardo de Oliveira14-Oct-10 6:13
memberMarcelo Ricardo de Oliveira14-Oct-10 6:13 
GeneralMy vote of 5 Pin
SteveQ5611-Oct-10 22:00
memberSteveQ5611-Oct-10 22:00 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira13-Oct-10 1:41
memberMarcelo Ricardo de Oliveira13-Oct-10 1:41 
GeneralMy vote of 5 Pin
Abhinav S7-Oct-10 7:45
memberAbhinav S7-Oct-10 7:45 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira8-Oct-10 6:24
memberMarcelo Ricardo de Oliveira8-Oct-10 6:24 
GeneralInteresting Pin
CIDev25-Sep-10 0:57
memberCIDev25-Sep-10 0:57 
GeneralRe: Interesting Pin
Marcelo Ricardo de Oliveira25-Sep-10 4:51
memberMarcelo Ricardo de Oliveira25-Sep-10 4:51 
GeneralMy vote of 5 Pin
sashidhar23-Sep-10 9:16
membersashidhar23-Sep-10 9:16 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira24-Sep-10 1:37
memberMarcelo Ricardo de Oliveira24-Sep-10 1:37 
GeneralMy vote of 5 Pin
Mass Nerder23-Sep-10 1:44
memberMass Nerder23-Sep-10 1:44 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira23-Sep-10 7:26
memberMarcelo Ricardo de Oliveira23-Sep-10 7:26 
GeneralMy vote of 5 Pin
Brij22-Sep-10 5:34
mentorBrij22-Sep-10 5:34 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira22-Sep-10 6:04
memberMarcelo Ricardo de Oliveira22-Sep-10 6:04 
GeneralMy vote of 5 Pin
Jeroen Vonk22-Sep-10 2:36
memberJeroen Vonk22-Sep-10 2:36 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira22-Sep-10 2:40
memberMarcelo Ricardo de Oliveira22-Sep-10 2:40 
GeneralMy vote of 5 Pin
linuxjr21-Sep-10 10:44
memberlinuxjr21-Sep-10 10:44 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira21-Sep-10 10:55
memberMarcelo Ricardo de Oliveira21-Sep-10 10:55 
GeneralNice Demo! Another 5. Pin
thompsons21-Sep-10 7:47
memberthompsons21-Sep-10 7:47 
GeneralRe: Nice Demo! Another 5. Pin
Marcelo Ricardo de Oliveira21-Sep-10 8:44
memberMarcelo Ricardo de Oliveira21-Sep-10 8:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150819.1 | Last Updated 14 Oct 2010
Article Copyright 2010 by Marcelo Ricardo de Oliveira
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid