Initial Flicker on Fade Out

G

Guest

Greetings

Having a bit of a problem with a fade out on a form. I'm using a timer which is enabled via a button and then this timer tick then takes the opacity down to nothing and then eventually closing the application.

However, what is happening is that when the button is clicked that enables the timer and thus the first tick, the form goes all black and then then repaints to the original form and fades out smoothly. I'm sure that this does not occur on the button click event, as I've put the thread to sleep at this point, and verified that it happens upon the first firing of the tick event.

Here's what I've noticed, this is much worse on forms with many controls, it actually appears if the form rolls into the center leaving the black background for just an instant before proceeding normally. Although this "rolling" may be an optical illusion.

Would appreciate if anyone can assist with getting rid of the flicker..........argh... probably something stupid...

Private Sub timerFade_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timerFade.Tic
If Me.Opacity <= 0 The
Me.Close(
Els
Me.Opacity = Me.Opacity - 0.0
End I
End Sub
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Hi,
I tried your code it works just fine. So, i believe the problem is in some
other part of your code. Can you post an working example that demonstrates
your problem. It could be, I guess, problem with your video card as well.
Try to update your video drivers with the latest version.

--
B\rgds
100

Greetings,

Having a bit of a problem with a fade out on a form. I'm using a timer
which is enabled via a button and then this timer tick then takes the
opacity down to nothing and then eventually closing the application.
However, what is happening is that when the button is clicked that enables
the timer and thus the first tick, the form goes all black and then then
repaints to the original form and fades out smoothly. I'm sure that this
does not occur on the button click event, as I've put the thread to sleep at
this point, and verified that it happens upon the first firing of the tick
event.
Here's what I've noticed, this is much worse on forms with many controls,
it actually appears if the form rolls into the center leaving the black
background for just an instant before proceeding normally. Although this
"rolling" may be an optical illusion.
Would appreciate if anyone can assist with getting rid of the
flicker..........argh... probably something stupid....
Private Sub timerFade_Tick(ByVal sender As Object, ByVal e As
System.EventArgs) Handles timerFade.Tick
 
J

Javier Campos

The problem comes when the window is converted internally from a standard
window to a layered window (when alpha is not 100%). That causes a window
repainting depending on your videocard drivers. to correct this and make it
work for all computers, just make alpha "almost-opaque" from the start, so
the window will be a layered window all the time. That'll make the updating
of the window slow if it's too big (layered windows need to be updated
completely, and won't allow invalidating regions, like standard windows do),
but it'll definitely do the trick and prevent the flickering from happening.

Hope this helps,

Javier Campos

Greetings,

Having a bit of a problem with a fade out on a form. I'm using a timer
which is enabled via a button and then this timer tick then takes the
opacity down to nothing and then eventually closing the application.
However, what is happening is that when the button is clicked that enables
the timer and thus the first tick, the form goes all black and then then
repaints to the original form and fades out smoothly. I'm sure that this
does not occur on the button click event, as I've put the thread to sleep at
this point, and verified that it happens upon the first firing of the tick
event.
Here's what I've noticed, this is much worse on forms with many controls,
it actually appears if the form rolls into the center leaving the black
background for just an instant before proceeding normally. Although this
"rolling" may be an optical illusion.
Would appreciate if anyone can assist with getting rid of the
flicker..........argh... probably something stupid....
Private Sub timerFade_Tick(ByVal sender As Object, ByVal e As
System.EventArgs) Handles timerFade.Tick
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Hi folks,

Yes, that is what I found. I hadn't seen the flickering before because my
form was too small.

However, this is true. The flickering occures when the underlaying window is
switched to "layered mode". Actually it flickers even if you set alpha to
255 (fully opaque).

Switching to layered mode involves three steps.
1. Checking the os version - it has to be NT 5 or latter
2. Set WS_EX_LAYERED window style
3. SetWindowLayeredAttributes this method is not defined in user32.dll for
versions before Win2k that's why first step is necessary.

When a Windows Forms control is created it is not a layered window. And it
switches to this mode when set the opacity to some value less then 1.

So my solution is to switch to layered mode in some early stage of the form
life. As soon as the form is created before to become visible. Otherwise
we'll see the flickering.

Javier is completely correct that the layered window has to be fully
redrawn. But it goes only when the window (form) resizes. You can still
invalidate some portions of the form and it will works how ot supposed to
work.
Layered window could even show better performance in some situations.
How internaly layered windows work is all painting is redirected to
off-screen buffer and when the painting's done alpha blending is applied to
the resulting picture and the result is drawn on the screen. This of course
is done internaly in windows and it uses the video card hardware support for
alpha blending if it has any.

Becuse all winodw is double buffered Windows doesn't send WM_PAINT when the
form is moved for example or when some part of the form is uncovered. In
such cases Windows uses double buffered image.
When children control is moved on the form it updates as much as it is
necessary. So the performance hit is not so big.

Anyway, my first solution that I was planning to post involved P\Invoke and
calling all API functions necessary to switch to "layered mode", but then I
found that if one set Opacity to value less then 1 and then return it back
to 1 the form class doesn't switch to the "normal mode" and leave the window
layered.

So the easiest way to get rid if this flickering is by overriding
OnControlCreated method and adding the following two lines:

this.Opacity = 0.9;
this.Opacity = 1;

No more flickering.
 
J

Javier Campos

Hello,

Stoitcho Goutsev (100) said:
Javier is completely correct that the layered window has to be fully
redrawn. But it goes only when the window (form) resizes. You can still
invalidate some portions of the form and it will works how ot supposed to
work.

Layered window could even show better performance in some situations.
How internaly layered windows work is all painting is redirected to
off-screen buffer and when the painting's done alpha blending is applied to
the resulting picture and the result is drawn on the screen. This of course
is done internaly in windows and it uses the video card hardware support for
alpha blending if it has any.

I don't know the Windows.Forms implementation of this, but I've been using
layered windows for a lot of time (in W32/C++), and, while invalidating
controls does force repainting on these controls by the standard GDI API,
invalidating regions of the form does not work, and it has to be composited
again everytime anything changes (be it resizing the form, change a label's
text, press a button, or whatever which invalidates the region), it also
gets fully composited when anything under it (or any other layered window
above it) changes. Basically, anything that changes anything on the
visibility will cause it to redraw fully.

Of course, this is not a problem on any application redrawing the whole
window every frame (say any graphic demo, or some kind of realtime analizer
or visualization program), but for the kind of application that usually
waits for events to be redrawn, it's a pretty slow method taking something
is going on under the form (and that's kinda the whole purpose of
alpha-blended windows).

Hardware accelerators with decent drivers (GeForce + Detonator or Forceware
for example) do matter on this issue, as they make the painting of the
alphablended bitmap (the final window) fast, but the main compositing is
still software-rendered, and it's pretty slow when you have to redraw all
components in the window. Seems like Longhorn will get rid of all those
problems making hardware-accelerated offscreen compositing for all and every
window, including the controls in them... but that'll take some time yet :)
Becuse all winodw is double buffered Windows doesn't send WM_PAINT when the
form is moved for example or when some part of the form is uncovered. In
such cases Windows uses double buffered image.
When children control is moved on the form it updates as much as it is
necessary. So the performance hit is not so big.

Uhm, maybe that's handled correctly now, but it definitely wasn't when I
tried it. It did redraw all and every control on the form (on an offscreen
buffer, yes, you don't get to see that) and it made the thing damn slow.
Invalidating rects would just do nothing when I tried... then again, I
didn't go much deeply on to it, as I basically used layered windows for
things that did redraw the whole form every frame. I might be wrong on that.

So the easiest way to get rid if this flickering is by overriding
OnControlCreated method and adding the following two lines:

this.Opacity = 0.9;
this.Opacity = 1;

No more flickering.

That was a nice thing to know ;)

Javier Campos
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top