Hi,

I change the position of controls on the main window (which is a dialog box) when the user resizes; ie I use WM_SIZE to get the new size and update accordingly. Unfortunately, this results in bad flicker on the controls, and some of them bob up-and-down.

How do I stop this from happening?

And while where on the subject, how do I set the minimum size for a window? I think I have to use WM_GETMINMAXINFO right?

thanx.
Posted on 2002-02-08 04:18:57 by pooq
Check Iczelions site at:
http://spiff.tripnet.se/~iczelion/

it has a "Eliminate Screen Flicker" or ESF tutorial by Chris Hobbs in the downloads section.

In theory you must handle WM_Erasebackground and have a backbuffer (a memory DC and fast blit from it) to sumarize tutorial.
Posted on 2002-02-08 11:16:55 by BogdanOntanu
When receive WM_SIZE check if it is less then your minimum size if it is then call MoveWindow specifying your minimum size.
Posted on 2002-02-08 11:44:57 by Quantum
Posted on 2002-02-08 12:18:01 by Thomas

When receive WM_SIZE check if it is less then your minimum size if it is then call MoveWindow specifying your minimum size.

To set window min/max size? Hell no. You catch WM_GETMINMAXINFO
and handle the stuff there.
Posted on 2002-02-08 12:20:02 by f0dder
I should have given more info in the beginning. I had already looked at ESF, but there it seems he draws everything on the offscreen buffer manually, ie the text for each button, etc. But my program has combo boxes, list controls and edit controls, and so drawing these manually will be inconvenient to say the least. Unless of course there is a way to tell a child window to draw itself on a different DC (the backbuffer) ?

The second thing is that I also have group boxes, so WS_CLIPCHILDREN is no use.

I was thinking about the idea of handling WS_ERASEBKGND, (returning 1) and then filling the rest of the window with the background color once the controls were drawn. But how do you make sure that you dont draw over the controls? I've read about the function ExcludeClipRect, but I dont know how it is used properly.

In any case, thanx for the quick replies.
Posted on 2002-02-08 16:49:22 by pooq
I got the feeling that with other than the most simple windows,
trying to paint only the "noncovered" areas could result in more
flicker than doing a normal full background erase... after all, you
can have some quite complicated "noncovered shapes". Then again,
if you cover most of the window and only have a few rectangular
shapes of noncovered area, it *could* be worth a try.
Posted on 2002-02-08 21:44:29 by f0dder
pooq,
a little trick that someone once pointed out to me when i was moving a large number of controls inside a parent window: use BeginDeferWindowPos, DeferWindowPos, and EndDeferWindowPos instead of MoveWindow. When i was moving these controls with MoveWindow, i was getting a quite pronounced 'wipe' effect across the parent window, by using a combination of the other three calls it made the repositioning sweet and instantaneous.

Using these three calls is like doing a transaction on a database: you open the transaction (BeginDeferWindowPos), then do all your updates/moves (DeferWindowPos), then 'commit' the transaction (EndDeferWindowPos), it is real simple to do.

Check out the doco at these links: BeginDeferWindowPos, DeferWindowPos, EndDeferWindowPos.
Posted on 2002-02-09 04:19:50 by sluggy
I tried your suggestion sluggy, but unfortunately there is still the problem of flicker. Also, I would like the controls to change position while the window is being resized, and using Defer does not enable this.

Does anyone know an easy way to tell a control to update itself on a specified DC?
Posted on 2002-02-09 05:27:51 by pooq
A number of things, if it has to be resized, do it in a CreateWindowEx window, not a dialog, you have more control.

In a CreateWindowEx window, remove the styles CS_HREDRAW and CS_VREDRAW from the WNDCLASSEX structure as they force repainting on resize.

If you can cover the client area of the window, make the parent window with a transparent background, it prevents the dual upgrading of the same piece of screen which causes vary bad flickering.

Be aware that some of the controls flicker when resized, you cannot do much about it but you can minimise the effect by a lot if you are careful.

I think there is a backbuffering technique for windows that have a number of controls on them but I do not have the code to do it myself.

Regards,

hutch@movsd.com
Posted on 2002-02-09 06:04:56 by hutch--
IMHO the only solution to make non flicker heavy GDI Gfx is that of Chriss in ESF, you should concentrate on finding a way of making controls draw from/to a backbuffer memory dc DC

Sub or Superclassing? and you handling their client paint messages should do the job....

however this will be pretty hard... do you needd it that hard?

As a joke: you can wait for the release of my OS :) i just changed all my system core GFX to backbuffer for the same reasons (eliminate flicker)

:stupid:
Posted on 2002-02-09 08:22:28 by BogdanOntanu
Here's a littel trick that I tired when I was trying to eliminate flickering on resize... It moght not suite your needs, but it worked okay for me.



Try changing the 'hbrBackground' value of your window structure to NULL instead of COLOR_BTNFACE+1 or whatever you're using.

It worked wonders for me.
Posted on 2002-02-10 16:59:18 by Syntax
Also WS_CLIPCHILDREN, WM_SETREDRAW and LockWindowUpdate are worth looking into.

KetilO
Posted on 2002-02-10 18:00:41 by KetilO
and LockWindowUpdate are worth looking into.

Sorry to dispute this Ketil0, but that function is not the answer. With my experience in using it, i found that it causes a lot of flicker itself, and you can only use it on one window at a time.

pooq, when you have solved your problem, tell us how you did it :)
Posted on 2002-02-10 18:44:58 by sluggy
Hi sluggy

If you use LockWindowUpdate on a window that has the desktop as it's parent the desktop repaints, but it is very useful on child windows. A lot of flicker problems can be solved by setting the WS_CLIPCHILDREN style of the parent window, and if possible also set the back color brush to NULL in WNDCLASSEX if possible.

KetilO
Posted on 2002-02-11 02:29:48 by KetilO
yes, WS_CLIPCHILDREN is good for childs, maybe you didn't know about its function:

all areas of the child windows are removed from the (re)paint region of there parent window. If you do a BeginPaint or GetUpdateRgn, all child window rects are excluded from this region handle.

also worth, its sibling WS_CLIPSIBLINGS:

does the same effect, but excludes child window rects from the paint regions of other child windows.
This is useful if the child windows overlap.
Posted on 2002-02-11 04:05:49 by beaster
WS_CLIPCHILDREN and WS_CLIPSIBLINGS are no good in my case, since I use group boxes.

sluggy, my current solution to the problem is: let it slide.
Posted on 2002-02-11 05:09:21 by pooq
Here is a solution which will work, basically Hutch and Bogdan are both right. Do as hutch said and remove the CS_VREDRAW and CS_HREDRAW styles. Then do as Bogdan said and paint everything to a memory dc.

You then need two Blt functions in your wndproc, one during WM_PAINT, this should be inside Begin and End Paint calls. The second should be in response to a WM_SIZE message.

A third addition which ensures absolutly no flicker is to buffer the size of the bitmap for the memory dc. The problem is that if you need to make a new bitmap for every change in size you'll still suffer flickering. Instead AND the width and height of the window with 0Fh so that you only remake the once for every change of 16 pixels.

Simply store the widths and heights in memory and recreate the bmp only when they change hte new width or height is different.
Posted on 2002-02-11 08:26:56 by Eóin