Click here to Skip to main content
14,873,128 members
Articles / Desktop Programming / MFC
Posted 4 Sep 2005


65 bookmarked

Resize/Reposition the Controls in a Dialog at your Pleasure

Rate me:
Please Sign up or sign in to vote.
4.55/5 (38 votes)
1 Mar 2006CPOL7 min read
You can resize or reposition the controls in your dialog derived from CSizingDialog to anywhere you wish just by specifying some simple strings or numbers. In addition, most kinds of controls almost don't flicker when moving, which is often a problem in some other solutions.
Sample Image - maximum width is 600 pixels
1. Original Dialog

Sample Image - maximum width is 600 pixels
2. Dialog after being resized


A dialog is a simple but also important user interface which can be used as the complementarities in a SDI or MDI project. In many cases, it's also used as the main window of the project. Unfortunately the MFC architecture doesn't provide methods for resizing the controls in a dialog. When you change the size of a resizable dialog, all the controls stay still in the top-left corner.

Many people put forward several kinds of solutions, but they hardly meet my need. Some solutions use very complex techniques that are hard to understand and so it's hard to improve and extend. Some solutions are too simple to meet even a slightly complex need. Some are not very convenient for secondary developers to use. And most of them move the controls to the destination positions without thinking of the flicker of controls.

The following class, CSizingDialog, gives you some simple but powerful methods to change the situation in a way which can make your dialogs more usable and professional. I thank many people for their intelligent work of giving me many good elicitations.


The movement of controls in a dialog can be simply regarded as the movement of the four borders of controls, which make the whole control resize and reposition in a dialog. The class CSizingDialog is just based on such a simple fact and is encapsulated for better use.

Using the Code

Let's start with how to use the class. The details will be discussed later:

  1. Change the base class of your dialog class (for example CYourDlg) from CDialog to baseCYourDialog where CDialog occurs as the base class of CYourDlg. Add the following code to header file YourDlg.h:

    #include <span class="code-string">"SizingDialog.h"</span>
    #ifndef baseCYourDialog
    #define baseCYourDialog CSizingDialog

    Of course, you can use CSizingDialog to take the place of CDialog directly.

  2. Copy files SizingDialog.h and SizingDialog.cpp to your project directory, and add SizingDialog.cpp to your project.
  3. Now you can specify the controls you want to move or size in the function CYourDlg::OnInitDialog() just as the following examples do. The functions will be explained below.

    this->AddResizableCtrl(IDC_EDIT1, _T("(-0.5)C"));
    this->AddResizableCtrl(IDC_STATIC1, _T("X+CY"));
    this->AddResizableCtrlArray(IDC_CHECK1, IDC_CHECK3, 0.0, 1.0, FALSE);

That's all to use the code.

Functions to Define the Moving Way of Controls

  1. Add a single control specified by nID.

    void AddResizableCtrl(UINT nID, LPCTSTR lpszString = NULL);
    void AddResizableCtrl(UINT nID,
            double dRateLeft, double dRateRight,
            double dRateTop, double dRateBottom);

    lpszString and dRateLeft, dRateRight, dRateTop, dRateBottom are parameters to describe the moving way of controls. They will be discussed in details below.

    Tips: If nID == NULL, all the controls in the dialog will be added using the same parameters.

  2. Add (or modify) a control-range where IDs range from nIDStart to nIDEnd or from nIDEnd to nIDStart.

    void AddResizableCtrlRange(UINT nIDStart, UINT nIDEnd,
            LPCTSTR lpszString = NULL);
    void ModifyResizableCtrlRange(UINT nIDStart, UINT nIDEnd,
            LPCTSTR lpszString = NULL);
    void AddResizableCtrlRange(UINT nIDStart, UINT nIDEnd,
            double dRateLeft, double dRateRight,
            double dRateTop, double dRateBottom);
  3. Add a control-range where IDs range from nIDStart to nIDEnd or from nIDEnd to nIDStart.

    void AddResizableCtrlArray(UINT nIDStart, UINT nIDEnd,
            double dSelfGain = 0.0, double dBorderIntervalRate = 1.0,
                BOOL bHori = TRUE);

The difference between this control-set definition method and the former methods is that in the former cases, all controls use the same moving parameters so they all behave the same while in the last case the moving parameters are not given directly and have to be calculated from other parameters. The typical result is that the controls' moving parameters are gradually changed from the first control to the last control.

The parameters of this function will be discussed separately below. You may also refer to moving parameters explanation.

dSelfGainThe size gain of a control relative to the dialog window size gain in the dimension specified by bHori.
dBorderIntervalRateThe proportion between the "border" size, offset between the first control's left border and its original position, and the interval size between two controls in horizontal direction. The case of vertical direction is similar.
bHoriThe direction in which the controls are rearranged.


  • Set dBorderIntervalRate = 0.0 to keep Ctrls near the border Close To Border
  • Set dBorderIntervalRate = 1.0 to keep Ctrls Rearranged Uniformly
  • Set dBorderIntervalRate = 1.0e20 to keep Intervals between Ctrls Constant

Moving Parameters Explanation

The moving offset of the right/bottom border of the dialog window relative to its original position is regarded as 1.0 in the follow definition.

  1. Defined using numbers:

    dRateLeftThe moving rate of a control's left border to the right
    dRateRightThe moving rate of a control's right border to the right

    The vertical case is similar.

  2. Defined using strings:

    A right defined string can be divided into different sections which are connected by the character '+' (other characters can also be specified). Each section is made up of a coefficient and a key word such as 0.5X, (-0.3)C, (-15.5RXY). If the coefficient is not specified, it is set to 1.0. The string is not sensitive to upper/lower characters.

    As you can guess, in a key word, X represents the horizontal dimension, while Y represents the vertical dimension. And if there is no X or Y, the definition is applied to both the horizontal dimension and vertical dimension.

    X, Y, XYThe whole control moves following the dialog's right/bottom border.
    C, CX, CY, CXYOnly the right/bottom border of the control moves following the dialog's right/bottom border. The left/upper border of the control stays still when the dialog is resizing.
    R, RX, RY, RXYThe whole control will keep constant proportion to the dialog's client rectangle when the dialog is resizing.

Now, all the resizing and repositioning problems are discussed. Note that if a control's moving way in some direction is defined more than once, only the last definition can work.

Guess what the following sentences can bring about?



this->AddResizableCtrl(NULL, _T("R"));

If you are not sure, add one of them to your CYourDlg::OnInitDialog() just before the sentence return TRUE; to see the effect. Of course, the first two steps in using the code are required to compile correctly.

Points Of Interest

Now I will discuss something about how to avoid control flicker when moving the dialog as far as possible. Anyone who just wants to use the class can jump over this section.

The first improvement is to set the redraw flag to FALSE before moving controls and restore it to TRUE after moving the controls as follows:


(The original code is different since the visible state of the control is considered.)

The second improvement is in the way of erasing the old rectangle (for instance, rcCtrlOld) of a control. Instead of using this->InvalidateRect(&rcCtrlOld), we just update the area which belongs to rcCtrlOld and at the same time DOESN'T belong to rcCtrl where the control stays currently. This is implemented by the following function:

void CSizingDialog::InvalidateCtrlBorder(     // XR: erase lpRectOld - lpRectNew
        LPCRECT lpRectOld, LPCRECT lpRectNew, BOOL bErase /*= TRUE*/)

There are still problems when you move a groupbox control. The previous two steps can't solve the problems. There are some old traces which remain IN the new groupbox control. But if you don't apply these two steps, the groupbox control and all the other controls in the groupbox control will flicker severely.

My solution is to divide the groupbox control's area into 9 parts. Each part is an individual rectangle. The work is done by the following function:

void GetGroupBoxRgn(const CWnd* pGBox, const CWnd* pParent, CRect* pRc)

pRc points to a CRect array with 9 elements. The meaning of pRc's elements in a GroupBox is illustrated as follows, 0 means whole rectangle.

//        ______________9____________
//       |                           |
//       7                           8
//       |_____5_____[ 4 ]_____6_____|
//       |                           |
//       |                           |
//       |                           |
//       |                           |
//       2                           3
//       |                           |
//       |                           |
//       |                           |
//       |                           |
//       |_____________1_____________|

Note that 7th, 8th and 9th part of the groupbox control do not exist in a groupbox with the default style.

So a Groupbox can be regarded as 9 "controls". Each of them can be applied the first two steps and the problem is solved. But I don't consider it as a good solution.

Of the 24 kinds of typical controls, the following kinds of controls still flicker more or less when moving even after applying the two steps. They are:

  • Combobox
  • Listbox
  • Slider control
  • List control
  • Tree control
  • Tab control

More effort is needed to solve this problem.

Revision History

  • 8th October, 2005 - V1.2: A critical problem has been fixed when the class is used in a modeless dialog.
  • 7th September, 2005 - V1.1: Four statements which are not supported by VC6 were modified, so the class now can be used in a project developed by VC6.
  • 5th September, 2005 - V1.0


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Xia Xiongjun
Software Developer
China China
Xia Xiongjun loves this site. Smile | :)

Comments and Discussions

GeneralVery useful piece of work Pin
Siddharth R Barman8-Jan-15 9:51
MemberSiddharth R Barman8-Jan-15 9:51 
QuestionCDockablePane support Pin
Andrew Truckle23-May-14 0:18
professionalAndrew Truckle23-May-14 0:18 
GeneralThanks for the solution.. Pin
mahigce25-Aug-13 20:31
Membermahigce25-Aug-13 20:31 
GeneralRe: Thanks for the solution.. Pin
Xia Xiongjun29-Aug-13 4:34
MemberXia Xiongjun29-Aug-13 4:34 
QuestionThis class can be applicabled on activeX control? Pin
iishero28-Dec-11 0:49
Memberiishero28-Dec-11 0:49 
AnswerRe: This class can be applicabled on activeX control? Pin
Xia Xiongjun28-Dec-11 4:06
MemberXia Xiongjun28-Dec-11 4:06 
QuestionWhen background of main dialog is erased for applying new color, the static text controls colors are not applied properly. How to proceed? Pin
SharanyaMahi18-Oct-11 1:50
MemberSharanyaMahi18-Oct-11 1:50 
GeneralAdding Invisible Items makes them visible. *solution [modified] Pin
BRWX25-Jul-08 2:08
MemberBRWX25-Jul-08 2:08 
GeneralResizing a custom control Pin
Hatachnat15-Oct-07 14:14
MemberHatachnat15-Oct-07 14:14 
QuestionWhat about using this in a CPropertyPage / Sheet scenario? Pin
andrewtruckle15-Jun-07 23:49
Memberandrewtruckle15-Jun-07 23:49 
NewsFix for Visual C++ 6.0! Pin
cristitomi19-Mar-07 1:08
Membercristitomi19-Mar-07 1:08 
GeneralRe: Fix for Visual C++ 6.0! Pin
Xia Xiongjun21-Mar-07 7:34
MemberXia Xiongjun21-Mar-07 7:34 
GeneralRe: Fix for Visual C++ 6.0! Pin
cristitomi21-Mar-07 21:56
Membercristitomi21-Mar-07 21:56 
QuestionProblem with Combo box control Pin
123rajesh25-Oct-06 20:03
Member123rajesh25-Oct-06 20:03 
AnswerRe: Problem with Combo box control Pin
andrewtruckle21-Mar-07 5:34
Memberandrewtruckle21-Mar-07 5:34 
GeneralRestoreWindowPosition Pin
andrewtruckle26-Sep-06 1:15
Memberandrewtruckle26-Sep-06 1:15 
QuestionWhat about SDI - Applications? Pin
enne8717-Sep-06 1:45
Memberenne8717-Sep-06 1:45 
AnswerRe: What about SDI - Applications? Pin
Xia Xiongjun17-Sep-06 2:26
MemberXia Xiongjun17-Sep-06 2:26 
GeneralRe: What about SDI - Applications? Pin
enne8717-Sep-06 11:35
Memberenne8717-Sep-06 11:35 
QuestionHow can i create a resizeable dialog in my existing project Pin
premkamalg28-Jun-06 21:29
Memberpremkamalg28-Jun-06 21:29 
GeneralWonderful, bravo ! Added a little correction for VC8 Pin
andré_k14-Jun-06 2:03
Memberandré_k14-Jun-06 2:03 
GeneralRe: Wonderful, bravo ! Added a little correction for VC8 Pin
andrewtruckle28-Feb-08 23:37
Memberandrewtruckle28-Feb-08 23:37 
GeneralRe: Wonderful, bravo ! Added a little correction for VC8 Pin
Priya_Sundar20-Jul-08 22:57
MemberPriya_Sundar20-Jul-08 22:57 
GeneralHi, works fine. NEED ONE MORE THING Pin
kevikev202030-May-06 0:05
Memberkevikev202030-May-06 0:05 
GeneralRe: Hi, works fine. NEED ONE MORE THING Pin
kevikev202030-May-06 0:34
Memberkevikev202030-May-06 0:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.