The Code Slinger

November 17, 2008

Color Transitions in Winform Controls

Filed under: .NET,C#,Tuples,Winform — Pete @ 3:02 pm

If you’ve ever used web-sites like the hosted WordPress blogs (like this one!) and others, you’ve noticed the new sweet hotness is to have screens give feedback on success or failure of an operation by showing color gradient transitions.  The most common is simply “Green to White” (success!) or “Red to Pink” (failure!).  This is a quick way to let the user know they can move along and do more work or whether they had an issue.  Granted, more detailed logging and/or messages are needed on the “fail” side of things, however since code slingers like us write perfect code all the time….we are just gonna go with quick feedback for now 😉

So, being as I’ve only started in the last few months writing winform/WPF apps, I thought there must be an easy way to do these gradients on forms and other controls quite easily.  No so.  Sure, there are ForeColor and BackColor properties, however transitioning in a gradient-like fashion from one color to the next isn’t “built in” in any way that I could tell.  NOTE: Yes, I’m well aware of the fact that WPF is going to take over the world.  But for now this is a Winform app, and until such time as WPF becomes the de-facto standard, it will remain as such.  Accordingly, please don’t comment about how WPF can handle this with ease.  I know.

So here’s what I came up with:

        public static void UpdateColor(Control ctl, Color from, Color to)

        {

            int step = 1; //Increase if you want the transition to be faster.

            var fromT = new Tuple<int, int, int>(

                Convert.ToInt32(from.R),

                Convert.ToInt32(from.G),

                Convert.ToInt32(from.B));

            var toT = new Tuple<int, int, int>(

                Convert.ToInt32(to.R),

                Convert.ToInt32(to.G),

                Convert.ToInt32(to.B));

            var curT = new Tuple<int, int, int>(fromT);

            var done = new Tuple<bool, bool, bool>(false, false, false);

 

            while (true)

            {

                //Red

                if (curT.First >= toT.First)

                    done.First = true;

                else

                {

                    var tempval = curT.First < toT.First ? curT.First += step : curT.First -= step;

                    curT.First = tempval > toT.First ? toT.First : tempval;

                }

                //Green

                if (curT.Second >= toT.Second)

                    done.Second = true;

                else

                {

                    var tempval = curT.Second < toT.Second ? curT.Second += step : curT.Second -= step;

                    curT.Second = tempval > toT.Second ? toT.Second : tempval;

                }

                //Blue

                if (curT.Third >= toT.Third)

                    done.Third = true;

                else

                {

                    var tempval = curT.Third < toT.Third ? curT.Third += step : curT.Third -= step;

                    curT.Third = tempval > toT.Third ? toT.Third : tempval;

                }

 

                if (done.First && done.Second && done.Third)

                {

                    ctl.BackColor = to;

                    ctl.Refresh();

                    break;

                }

                ctl.BackColor = Color.FromArgb(curT.First, curT.Second, curT.Third);

                ctl.Refresh();

            }

        }

So, basically I’m just getting the integer values of the RGB color scheme for the from and to colors passed in, looping through adding/subtracting from the start values (from) until I get to the end values (to), refreshing the control along the way.  Not too terribly difficult, but interesting none-the-less and quite a nice little UI feature that doesn’t look like most winform applications.

Also, note I’ve added a step variable that you can tweak to adjust how fast or slow the transition occurs.  It’s a pretty significant jump from say 1 to 3, so if you want more granular timing, you could adjust the int storage to decimal and account for parts of steps (such as += 0.3).  Or you could implement a true timing system that would force the transition to take place within a specific time construct (perhaps the next article on this topic??).  But for my needs currently, this is more than sufficient.

And of course, I’m using my handy little Tuple<T1,T2,T3> class, since tuples (or at least the concept of them) rock.  Hint hint…please make this concept a part of C# 4.0 Anders…puuuleeeeeease?

    public class Tuple<T1,T2,T3>

    {

        public T1 First { get; set;}

        public T2 Second { get; set; }

        public T3 Third { get; set; }

 

        public Tuple(T1 t, T2 k, T3 l)

        {

            First = t;

            Second = k;

            Third = l;

        }

        public Tuple(Tuple<T1,T2,T3> t)

        {

            First = t.First;

            Second = t.Second;

            Third = t.Third;

        }

    }

 

Til next time….keep on slangin!

 

Blog at WordPress.com.