General Flicker Free Resizable Control
- General solution, can be used in dialogs, form views, property sheets, etc.
- Possible to split added size between several controls.
- Not necessary to declare all controls with DDX_Control.
- Flicker Free implementation (that also works with group boxes).
- Easy setting of the sizing options though several different interfaces.
- Possible to save window placement in registry.
- Small and simple implementation.
The solution is not a CDialog derived class, but a generic class (CResize) that can be used in other situations as well. It is applied to the dialog (CResizeDialog), property page and sheet (CResizePropertyPage and CResizePropertySheet), and form view (CResizeFormView) classes. The demo project shows how to use the class in these four situations. Notice that the property sheet demo shows how to include minimize and maximize buttons.
Throughout the remaining part of this document, I will assume that the control is applied to a dialog class.
Resize Paradigm
In this example the added horizontal size should be split between the two edit boxes, and the added vertical size should be consumed by the two edit controls. The sides of the edit controls move as shown on the image.
The sizing for the two edit controls can be set in these four different, but functional equal, ways:
// sizing set using array of items static SIZING s_arrSizing[] = { // identifier left top right bottom IDC_EDIT1, 0, 0, 0.5, 1, IDC_EDIT2, 0.5, 0, 1, 1 }; SetResize(s_arrSizing); // sizing set directly with functions SetResize(IDC_EDIT1, 0, 0, 0.5, 1); SetResize(IDC_EDIT2, 0.5, 0, 1, 1); // sizing set with functions using added macros SetResize(IDC_EDIT1, SZ_HORRESIZE(0.5) + SZ_VERRESIZE(1)); SetResize(IDC_EDIT2, SZ_HORRESIZE(0.5) + SZ_HORREPOS(0.5) + SZ_VERRESIZE(1)); // sizing set with multiple functions using macros SetResize(IDC_EDIT1, SZ_HORRESIZE(0.5)); SetResize(IDC_EDIT1, SZ_VERRESIZE(1)); SetResize(IDC_EDIT2, SZ_HORRESIZE(0.5)); SetResize(IDC_EDIT2, SZ_HORREPOS(0.5)); SetResize(IDC_EDIT2, SZ_VERRESIZE(1));The available macros for the definitions are:
SZ_RESIZE(x) // resize SZ_REPOS(x) // reposition SZ_HORRESIZE(x) // horizontal resize SZ_HORREPOS(x) // horizontal reposition SZ_VERRESIZE(x) // vertical resize SZ_VERREPOS(x) // vertical reposition
The values of x must be in the range [0,1], which is verified with assertions.
Notice that the only thing you have to do to implement a resizable dialog, is to derived your own dialog class from CResizeDialog instead of CDialog, and set the sizing options as shown above.
Flickering
The windows style WS_CLIPCHILDREN needs to be set to prevent the dialog from flickering. This causes a problem for group boxes (wrong window painting in the area of the group box), but that can be solved by making the group boxes transparent (they still flicker though). The CResize class automatically sets the WS_CLIPCHILDREN style for the dialog and the WS_EX_TRANSPARENT extended style for the group boxes to cope with these problems (this can be disabled by setting the corresponding flags, see the next section).
Notice that the tabs of the property pages still flicker, I haven't found a way to solve that (yet).
Flags
The following flags are defined to control the behavior:
SZ_NOSIZEICON // do not add size icon SZ_NOHORISONTAL // no horizontal resizing SZ_NOVERTICAL // no vertical resizing SZ_NOMINSIZE // do not require a minimum size SZ_NOCLIPCHILDREN // do not set clip children style SZ_NOTRANSPARENTGROUP // do not set transparent style for group boxes
The flags are set through the last argument of the constructors.
Minimum Size
The default minimum size is the initial size of the dialog, which can be overruled by the flag SZ_NOMINSIZE or by setting the size explicitly with the function SetMinSize. You can set a maximum size as well.
// set the minimum size explicitly (initial size is the default) void SetMinSize(CSize& sz); // set the maximum (no maximum as default) void SetMaxSize(CSize& sz);
Storing the last used Window Placement
The size of the dialog can be saved to and loaded from the registry, which is shown for the demo dialog in the demo project.
// save window placement to registry void SavePlacement(LPCTSTR pszSection); // load saved window placement from registry void LoadPlacement(LPCTSTR pszSection);
Downloads
Download source - 7 KBDownload demo project - 39 KB (including this page)
Comments
Bug in SetResize(SIZING arr[])
Posted by funster10 on 09/21/2005 09:44pmTry CMemDC!
Posted by Legacy on 10/23/2003 07:00amOriginally posted by: Rudolf M�hlbauer
Progress control is still flickering with this class
Posted by Legacy on 10/03/2003 07:00amOriginally posted by: Hover
The class works well on most environments. However, when I add a progress control bar in the dialogbox, and fill the progress control bar, it is still flickering seriously. How does this come?
ReplyGroup box flicker - solution
Posted by Legacy on 05/03/2003 07:00amOriginally posted by: Toomas
groupbox flick ,i have a stupid method
Posted by Legacy on 04/29/2003 07:00amOriginally posted by: xqyz8888
I search ALL THE WORLD,NOT find out the method:preventing groupbox flick.i know the reason,i think you know too:the drawn area overlapped.
Replyi write some code to test .but i think,if i only need a beautiful serface ,i can use picture box and static to take place it.so i use four picture box and one static ,static as title.pic box as frame.set picbox property(in property dialog) :
type as frame
color as etched
it's a too stupid method ,but it do better.never flick .then you can use clipchilder style .but you can not use groupbox 's group property.that's ok?
Memory leak with Visual C++ .NET
Posted by Legacy on 06/30/2002 07:00amOriginally posted by: amauta
Hello,
I use this marvelous code in my programs, but when I complie with Visual C++ .NET, or Visual C++ 7.0 I have memory leaks, in function CResize::SetResize, one for dialog, and two for every control I want to resize.
Does anyone kowns where is the problem?.
Thanks in advance.
Amauta.
ReplyGroupBox flickering
Posted by Legacy on 06/21/2002 07:00amOriginally posted by: Frank Lichtner
It's easy to prevent groupboxes from flickering. You have to subclass them and overwright the WM_ERASEBKGND message to delete the background. Don't set the tranparent flag for that groupbox.
Frank
ReplyCResize group box redraw issue...
Posted by Legacy on 03/25/2002 08:00amOriginally posted by: James E. Melter
Great stuff but I found a
groupbox related bug in BOOL CResize::Defer(HDWP hdwp, CItem* pItem, int dx, int dy) member fcn. The right side of the groupbox frame is sometimes not redrawn. I changed this line of code:
if (DeferWindowPos(hdwp, hwnd, 0, x, y, cx, cy, SWP_NOZORDER) == 0)
to this:
if (DeferWindowPos(hdwp, hwnd, 0, x, y, cx, cy,
SWP_SHOWWINDOW | SWP_DRAWFRAME | SWP_NOZORDER) == 0)
and it seemed to correct the problem.
I also still get "control location bounce" if I use the upper-left or lower-left window resizer handles to resize the window, Whazzup?
Thanks.
ReplyWell done! but maybe a mistake in 'CResize::SetResize(SIZING arr[])'
Posted by Legacy on 12/09/2001 08:00amOriginally posted by: Esoul
Problem with resizing Active X controls using this code
Posted by Legacy on 08/17/2001 07:00amOriginally posted by: Dave G.
I've detected an issue using third party active controls and even ones that I make through Visual C++. Specifically the problem occurs in resize.cpp file -> CResize::SetResize() procedure. Apparently the handle being returned from the control is 0x00000000 and the code can not ::Attach() the handle to the pwnd variable.
You can easily duplicate this by inserting an ActiveX (COM) control made by you with VC++ and using it in your project OR using a third party control - Truegrid DB Ole 7.0 Add it to one of the CFormView objects you create. Add it to the static SIZING array on the InitialUpdate() of the formview, compile, run and viola' you get the Assertion error.
Any help on this issue would be appreciated, I'm guessing that this has something to do with when the Control is actually created - but then again I could be way off. I'll try adding the SetResize() to the OnInitDialog() or other areas of the CFormView and get back to you. Of course if you get a solution before I do, please post here.
Thank you,
ReplyD.G.
Loading, Please Wait ...