cdxCDynamicWnd and derived classes
by Hans Bühler : codex design

documentation

[ preface | about | techniques | a dynamic dialog | finally ]

1 | Preface, Definition

Definiton:
A dynamic window is a window that automatically repositions its child controls when its size changes.
The opposite behaviour is called static.

The classes described here will help you implementing dynamic dialogs, formviews, property sheets and control bars.

It replaces my former class tree "cdxCSizingDialog, ...".

2 | About this document

Since I found out that not many of you seem to like reading documentation, I shortened this documentation.
If you have any suggestions, problems or questions that are not covered by this text, feel free to write an email to me.

As a result, I won't discuss all my member functions but will give you a quick introduction in making windows dynamic.
The basic example will be a dialog.
The technique is nearly the same for property sheets, formviews and control bars.

Here it is:

small window
(picture#1)

We want to make it dynamic i.e. it should look like this if you change its size:

big window
(picture #2)

3 | Techniques

The cdxCDynamicWnd class is a base class of all the ready-to-use classes as cdxCDynamicDialog.
To implement the resizing code, you need to tell the cdxCDynamicWnd object, which of your child controls should react on a resizing of your windows and how.

To do so, there are now two techniques:

AddSzControl(IDC_BOX_1,mdResize,mdResize);
AddSzControl(IDC_LIST,mdResize,mdResize);
AddSzControl(IDC_EDIT,mdResize,mdRepos);
AddSzControl(IDC_NEW,mdRepos,mdRepos);
AddSzControl(IDOK,mdRelative,mdRepos);
AddSzControl(IDCANCEL,mdRelative,mdRepos);

Among others, the following overloads of AddSzControl() are defined (the wnd parameter might be either an ID or a HWND object while a CWnd casts properly to a HWND):

AddSzControl(wnd, Mode mdX, Mode mdY);
AddSzXControl(wnd, Mode md);
AddSzYControl(hwnd, Mode md);

If you are not satisfied with my predefined modes, you can make your own:
The following overload takes two bytes for each direction: They defined how much percent of the change in width should be added to the left side of the the child control (x1) and to the right side (x2) (equally for height changes):

AddSzControl(wnd, SBYTE x1, SBYTE y1, SBYTE x2, SBYTE y2);
AddSzXControl(wnd, SBYTE x1, SBYTE x2);
AddSzYControl(wnd, SBYTE y1, SBYTE y2);

My predefined modes have the following values:
- mdNone is (x1=0,x2=0)
- mdRepos is (100,100)
- mdResize is (0,100)
- mdRelative is (50,50)

Depending on the base class you use the following functions are suitable places to call AddSzControl():

BEGIN_DYNAMIC_MAP(CTestDlg,cdxCDynamicDialog)
    DYNAMIC_MAP_ENTRY(IDC_BOX_1, mdResize, mdResize)
    DYNAMIC_MAP_ENTRY(IDC_LIST1, mdResize, mdResize)
    DYNAMIC_MAP_ENTRY(IDC_EDIT, mdResize, mdRepos)
    DYNAMIC_MAP_ENTRY(IDC_NEW, mdRepos, mdRepos)
    DYNAMIC_MAP_ENTRY(IDOK, mdRelative, mdRepos)
    DYNAMIC_MAP_ENTRY(IDCANCEL, mdRelative, mdRepos)
END_DYNAMIC_MAP()

If you compare these lines to the above AddSzControl() statements, you'll note that they act similarily.
The following macros are defined:

DYNAMIC_MAP_ENTRY(ID,MODEX,MODEY)
DYNAMIC_MAP_XENTRY(ID,MODEX)
DYNAMIC_MAP_YENTRY(ID,MODEY)

DYNAMIC_MAP_ENTRY_EX(ID,X1,Y1,X2,Y2)
DYNAMIC_MAP_XENTRY_EX(ID,X1,X2)
DYNAMIC_MAP_YENTRY_EX(ID,Y1,Y2)

4 | Example: How to create a dynamic dialog

  1. A dialog:
    I suggest that you used your dialog resource editor to design a dialog as shown in picture #1.
    The names of the controls should indicate their control IDs.
    Important note #1: Every control that should dynamically move need a unique ID (=> it is not possible to move static texts with IDC_STATIC).
    Moreoever, I assume that you have created a dialog class called "CTestDlg" for this dialog.

  2. Resizable border and WS_CLIPCHILDREN for your dialog:
    Please open your dialog's properties (in the resource editor), go to the tab "Styles" and change the "Border" into "resizing" (otherwise use won't be able to resize your dialog although it might be dynamic by code).
    Then, switch to the first tab and activate "clip children".

    NOTE: If "clip children" is on and you use group boxes, these boxes need the WS_EX_TRANSPARENT style (can be found at the "extended styles" tab of the group box).
    This is not a problem with these classes but with the MFC at all !

  3. Changing the base-class of your dialog:
    Open your dialog classes header file, add an
    #include "cdxCDynamicDialog.h"
    to its head and replace all "CDialog" by "cdxCDynamicDialog" in both your header and implementation file.

  4. Define how childs should be moved:
    Since this release, you can choose among the two techniques described above to implement this behaviour (they can be mixed if you need that).

    See above to learn how to do so.

  5. Compile and run.

  6. Open your constructor and try to add  ModifyFlags(flSWPCopyBits,0)  to your code.
    This is an anti-flickering option which does not work with all childconstrols, unfortunately - thus you may need to disable it one time.

Once your code runs, you can modify the behaviour of your class in many ways.

The options you may want to make use of are:

Check the flags, available to you, check functions and if you don't make it work, drop a note to me.

5 | Finally

The classes described in this document have been written by

Hans Bühler, codex design (w)1997 - 2000
hans.buehler@topmail.de

You are free to use and modify the code and the classes but I would like you to note the author (that's me :) in your product's documentation at any place, if possible.
You use this code at your own risk.
Any damange caused by the use or misuse of this code is the sole responsibility of the user.

[ back to top of this document ]