While searching for code to fade a winform, I came across this page on the MSDN forum.
for (double i = 0; i < 1; i+=0.01)
{
this.Opacity = i;
Application.DoEvents();
System.Threading.Thread.Sleep(0);
}
The for
loop has a non-integer increment and, from a previous question I asked, that's not a good programming technique (due to inexact representation of most decimals).
I came up with this alternative.
for (double i = 0; i < 100; ++i)
{
this.Opacity = i/100;
Application.DoEvents();
System.Threading.Thread.Sleep(0);
}
Which of these is more efficient?
If there's a better algorithm for fading a form, I'll be very glad if it is included.
Thanks.
Forget timers (pun intended).
With Visual Studio 4.5 or higher, you can just await
a task that is delayed. An advantage of this method is that it's asynchronous, unlike a thread Sleep
or DoEvents
loop, which blocks the application during the fade (and the other aforementioned DoEvents
problems).
private async void FadeIn(Form o, int interval = 80)
{
//Object is not fully invisible. Fade it in
while (o.Opacity < 1.0)
{
await Task.Delay(interval);
o.Opacity += 0.05;
}
o.Opacity = 1; //make fully visible
}
private async void FadeOut(Form o, int interval = 80)
{
//Object is fully visible. Fade it out
while (o.Opacity > 0.0)
{
await Task.Delay(interval);
o.Opacity -= 0.05;
}
o.Opacity = 0; //make fully invisible
}
Usage:
private void button1_Click(object sender, EventArgs e)
{
FadeOut(this, 100);
}
You should check if the object is disposed before you apply any transparency to it. I used a form as the object, but you can pass any object that supports transparency as long as it's cast properly.
So, first off, application.DoEvents should be avoided unless you really know what you're doing and are sure that this is both an appropriate use of it, and that you are using it correctly. I'm fairly certain that neither is the case here.
Next, how are you controlling the speed of the fading? You're basically just letting the computer fade as quickly as it can and relying on the the inherent overhead of the operations (and background processes) to make it take longer. That's really not very good design. You're better off specifying how long the fade should take from the start so that it will be consistent between machines. You can use a Timer
to execute code at the appropriate set intervals and ensure that the UI thread is not blocked for the duration of the fade (without using DoEvents
).
Just modify the duration
below to change how long the fade takes, and modify the steps
to determine how "choppy" it is. I have it set to 100 because that's effectively what your code was doing before. In reality, you probably don't need that many and you can just lower to just before it starts getting choppy. (The lower the steps the better it will perform.)
Additionally, you shouldn't be so worried about performance for something like this. The fade is something that is going to need to be measured on the scale of about a second or not much less (for a human to be able to perceive it) and for any computer these days it can do so, so much more than this in a second it's not even funny. This will consume virtually no CPU in terms of computation over the course of a second, so trying to optimize it is most certainly micro-optimizing.
private void button1_Click(object sender, EventArgs e)
{
int duration = 1000;//in milliseconds
int steps = 100;
Timer timer = new Timer();
timer.Interval = duration / steps;
int currentStep = 0;
timer.Tick += (arg1, arg2) =>
{
Opacity = ((double)currentStep) / steps;
currentStep++;
if (currentStep >= steps)
{
timer.Stop();
timer.Dispose();
}
};
timer.Start();
}
I wrote a class specifically for fading forms in and out. It even supports ShowDialog
and DialogResults.
I've expanded on it as I've needed new features, and am open to suggestions. You can take a look here:
https://gist.github.com/nathan-fiscaletti/3c0514862fe88b5664b10444e1098778
Example Usage
private void Form1_Shown(object sender, EventArgs e)
{
Fader.FadeIn(this, Fader.FadeSpeed.Slower);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With