Monday, February 14, 2011

A flicker free Canvas on Windows

Control flickering on Windows has always been one of our biggest complaints. The OS does not double buffer any controls for us and in turn we don't try and double buffer for you. Although this is not entirely the issue, it is definitely the root cause. We try to limit what needs to be refreshed, especially when resizing a control. There is one control however that we do have control over and that is the Canvas. In most cases a flicker free Canvas is desirable as long as you don't need it to be transparent. By default the Canvas control is transparent (i.e. if you don't paint over the entire control then whatever is in the background shows through). For example, if you overlayed two canvas controls and drew circles in each you'd see something like this:

As long as you don't anticipate moving/resizing your Canvases, this is not going to cause you any flicker issues. However, imagine now what would happen if you decided that these Canvases need to grow/shrink with the Window (i.e. having the Canvases locked Top/Left/Bottom/Right). Now every time the "Blue" Canvas needs to resize it must tell its background to refresh so that it shows through, then it can draw itself. This is the root cause of flicker. Well great, I see an EraseBackground property on the Canvas, can I not just uncheck that and get rid of flicker? Well yes, but look what happens in this case with the two transparent Canvases:

The Canvases no longer flicker when resized, but you can see that the background no longer erases so you get some funky streaks left behind in the transparent areas of the Canvas. What you want to do in this case is check the DoubleBuffer property. You will lose transparency by doing so which means overlapping Canvases probably isn't what you want to do in this case:

But partially overlapped controls is actually not something we recommend anyway.  In this case you would have to redesign your layout and instead of having overlapped Canvases you should have just one double buffered Canvas that drew two overlapped circles. A flicker free Canvas is achievable, it may require some UI reworking on your part, but you will be that much closer to a flicker free experience on Windows.


Anthony said...

I think the best way to avoid flicker and artifacts for Windows is still to doublebuffer yourself and redraw your buffer only when there are changes in size or content.

Using Refresh, Invalidate, or ClearRect to take care of forced refreshes goes a long way, assuming you don't use the EraseBackground property.

Jason said...

Yes, but I continue to struggle with supporting transparency while allowing for resize and no flicker. Basically what I have no issue whatsoever in OSX causes me horrible grief in Win... I have my own double-buffering that attempts to handle the mask as well to maintain transparency, but it does not always work perfectly and many times yields some strange results (drawing artifacts, halos, etc).