65.9K
CodeProject is changing. Read more.
Home

Simple and more powerful resizable dialog

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (29 votes)

Sep 27, 2004

4 min read

viewsIcon

236058

downloadIcon

8572

A simple resizable dialog which resizes in NONE, RESIZE, REPOS, RELATIVE, ZOOM, DELTA_ZOOM mode and behaves differently in different directions(left, top, right, bottom)

The Sample Dialog

  1. Original Dialog
  2. Dialog after sized bottom-right
  3. Dialog after sized left-top

Introduction

This resizable dialog class can automatically adjusts controls position and/or size as dialog is sized. the reposition and resize is direction sensitive (left and right, top and bottom can be handled differently respectively) and behave one of six ways: NONE, RESIZE, REPOS, RELATIVE, ZOOM, DELTA_ZOOM (see below for more information).

Background

This class was derived from the Flicker-Free Resizing Dialog (thanks Andy Brown). Andy Brown had solved the flicker problem (which really puzzled me once) and his class supports resizing in NONE, RESIZE, REPOS, RELATIVE mode.

However I need more controllable reposition and/or resize handler, I think someone else need it too. So I enhanced Andy Brown's class and wrote this class which added the following features:

  1. Reposition and resize is direction sensitive. e.g. Andy Brown's class treat dialog's sizing left and right as the same sizing (x-direction). This class can treat them differently.
  2. Zoom control as dialog is zoomed.
  3. Be able to adjust more than one controls' position and/size respectively, which are at the same X-/y-level. e.g. this class can resize two controls which are at the same horizontal line as 50% as dialog's changed-width, in another words, if dialog's width is increased 10 pixels, this class increase each control's width 5 pixels.

Using the code

  1. Add ResizeDlg.cpp and ResizeDlg.h to your project or makefile;
  2. Add "#Include ResizeDlg.h" to stdafx.h file or your dialog header file;
  3. Make your dialog-derived class inherit from CResizeDlg instead of CDialog by replacing all instances of "CDialog" with "CResizeDlg" in your dialog header and implementation files.
  4. Add a handler for WM_INITDIALOG in your dialog class if you haven't done so, as described below.

WM_INITDIALOG (OnInitDialog)

In your OnInitDialog handler you should call the base class's OnInitDialog and call AddControl for those controls that are to be automatically repositioned and/or sized when the dialog is sized. here is an example.

//
// the minimal work you have to do in your OnInitDialog handler.
//
BOOL CMyDialog::OnInitDialog()
{
 CResizeDlg::OnInitDialog();

 AddControl(IDOK, CST_REPOS, CST_REPOS, CST_NONE, CST_NONE, 1);
 AddControl(IDCANCEL, CST_REPOS, CST_REPOS, CST_NONE, CST_NONE, 1);
 
 return TRUE;
}

How Controls Reposition and/or Size

This class allow controls dynamically repositioned and/or sized in each direction (left, top, right, bottom) as one of the following ways.

CST_NONE do not reposition and size in this direction;
CST_RESIZE size controls as much as dialog's changed-size in this direction.
    //
    // in x direction, where deltaX is 
    // dialog's changed-width.
    //
    ctrlRect.right += deltaX;
CST_REPOS reposition controls as much as dialog's change-size in this direction.
    //
    // in x direction, where deltaX is dialog's 
    // changed-width.
    //
    ctrlRect.left += deltaX;
    ctrlRect.right += deltaX;
CST_RELATIVE reposition controls with user-defined proportion (make controls always at the same proportional position in dialog).
    //
    // in x direction, where m_xRatio is 
    // user-defined proportion
    // pnRect is dialog's new ClientRect
    //
    newCx = ctrlRect.Width();
    ctrlRect.left = (int)(m_xRatio * 
        pnRect->Width() - newCx / 2.0);
    ctrlRect.right = ctrlRect.left + newCx;
CST_ZOOM reposition and size controls automatically
    //
    // in x direction, where pnRect is 
    // dialog's new ClientRect.
    // pR0 is dialog's original ClientRect
    // (NOT previous width).
    //
    ctrlRect.left = (int)(1.0 * ctrlRect.left  
       * (double)pnRect->Width() / pR0->Width());
    ctrlRect.right = (int)(1.0 * ctrlRect.right 
       * (double)pnRect->Width() / pR0->Width());
CST_DELTA_ZOOM reposition and size controls proportionally, both proportion can be set respectively.
    //
    // in x direction, where deltaX0 is 
    // the dialog's chenged-width
    // compared with its original width(NOT 
    // previous width, otherwise error 
    // will mess the result).
    // m_xRatio is user defined X-reposition 
    // proportion and
    // m_cxRatio is user defined X-size proportion.
    //
    newCx = ctrlRect.Width();
    ctrlRect.right = (int)(ctrlRect.left + 
      deltaX0 * m_xRatio + newCx + deltaX0 * m_cxRatio);
    ctrlRect.left += (int)(deltaX0 * m_xRatio);

Usage of AddControl

You should call AddControl to set how controls behave as dialog is sized in OnInitDialog. It's prototype as below:

void AddControl( UINT nID, int xl, int xr, int yt, 
              int yb, int bFlickerFree = 0, 
              double xRatio = -1.0, double cxRatio = -1.0,
              double yRatio = -1.0, double cyRatio = -1.0 );
where
nID control's resource ID
xl how controls reposition and/or resize when dialog resize left. set it one of CST_xx.
xr how controls reposition and/or resize when dialog resize right. set it one of CST_xx.
yt how controls reposition and/or resize when dialog resize top. set it one of CST_xx.
yb how controls reposition and/or resize when dialog resize bottom. set it one of CST_xx.
bFlickerFree whether try to avoid flickering when reposition and/or resize this control
xRatio user-defined x-direction reposition proportion. valid only when xl or xr is CST_RELATIVE or CST_DELTA_ZOOM. set it to 0.0~1.0.
cxRatio user-defined x-direction resize proportion. valid only when xl or xr is CST_DELTA_ZOOM. set it to 0.0~1.0.
yRatio user-defined y-direction reposition proportion. valid only when yt or yb is CST_RELATIVE or CST_DELTA_ZOOM. set it to 0.0~1.0.
cyRatio user-defined y-direction resize proportion. valid only when yt or yb is CST_DELTA_ZOOM. set it to 0.0~1.0.

Typical use of AddControl

  1. keep a edit control resize horizontally as dialog sized.
    AddControl(edit-ID, CST_RESIZE, CST_RESIZE,
     CST_NONE, CST_NONE, 1);
  2. keep a top-right button at the same top-right position.
    AddControl(button-ID, CST_REPOS, CST_REPOS,
     CST_NONE, CST_NONE, 1);
  3. Keep a button at the fixed distance to bottom and horizontal-center.
    AddControl(button-ID, CST_RELATIVE, CST_RELATIVE,
     CST_REPOS, CST_REPOS, 1, 1.0);
  4. two edit controls are in a horizontal-line, make left edit control resize and right one keep the same size when dialog left-sized, or left one keep the same size and right one resize when dialog size right.
    AddControl(left-edit-ID, CST_RESIZE, 
     CST_NONE, CST_NONE, CST_NONE, CST_NONE, 1);
    AddControl(right-edit-ID, CST_REPOS,
     CST_RESIZE, CST_NONE, CST_NONE, 1);
  5. two edit controls as example 4. make them size share the same of dialog's changed-width. In another words, if dialog's width increase 10 pixels, then each of the edit-control increase its width 5 pixels respectively.
    AddControl(left-edit-ID, CST_DELTA_ZOOM, CST_DELTA_ZOOM,
     CST_NONE, CST_NONE, 1, 0.0, 0.5);
    AddControl(right-edit-ID, CST_DELTA_ZOOM, CST_DELTA_ZOOM,
     CST_NONE, CST_NONE, 1, 0.5, 0.5);
    where 0.0, 0.5 means left-edit control do not change its position and resize as 50% as dialog's changed-width. 0.5, 0.5 means right-edit control change its position as 50%, because left control resize, so it must reposition, and resize as 50% as dialog's changed-width.

Attention

  1. Resize-grip (, at the bottom-right of dialog) 's resource ID (IDC_DLGSIZEBOX) is defined in ResizeDlg.h. You should set it another unused resource ID if you have used it in somewhere else.
  2. Do not set flicker-free for group-controls in dialog (set bFlickerFree to 0 in calling AddControl).

History

  1. Sep 26, 2004 -Initial public release.