I did a similar thing to this before, and implemented it using GDI+.
The button should do two things in it's draw method.
- Draw the default button without any regards for transparency.
- Draw the mouseove image with a given alpha.
Use a BackgroundWorker to give you a smooth animation. So on mouseover start the BackgroundWorker and make it run untill Alpha reaches 1.0f. When mouse is removed from button, the worker should reduce Alpha untill it reaches 0.0f. Have a variable called fadingin so that the BackgroundWorker will understand what it should do. Your mouse in and out event should just properly set fadingin to true or false, then start the BackgroundWorker (if it's not already runnung).
The BackgroundWorkers DoWork method can look something like this:
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
long ticks1 = 0;
long ticks2 = 0;
double interval = (double)Stopwatch.Frequency / 60;
while (true) {
ticks2 = Stopwatch.GetTimestamp();
if (ticks2 >= ticks1 + interval) {
ticks1 = Stopwatch.GetTimestamp();
if(_fadeIn){
_fadeAlpha += 0.1f;
if(_fadeAlpha > 1f){
_fadeAlpha = 1f;
break;
}
}else{
_fadeAlpha -= 0.1f;
if(_fadeAlpha < 0f){
_fadeAlpha = 0f;
break;
}
}
backgroundWorker.ReportProgress(0);
}
Thread.Sleep(1);
}
backgroundWorker.ReportProgress(0);
}
The Stopwatch and loop construct here will make the animation aim for a 60fps animation.
The backgroundWorker ProgressChanged should just change the ColorMatrix to the proper alpha value, and bind the ColorMatrix to the ImageAttributes, and invalidate the control by calling Invalidate. This has to be done so that the GUI repaint is requested from the main thread, and not the BackgroundWorker thread. If you do this directly from DoWork you will get an exception if you try to modify ImageAttributes while a draw operation is taking place.
Hope this helps you to make a good smooth animation on your button.