Automatic Dialog Resizing



Click here for a larger image.

Environment: VC.NET, VC6, Win32, MFC, WTL

Every GUI developer uses dialogs. Sometimes, dialogs should support resizing to make the user's life easier. To create a resizable dialog, you just need to handle a WM_SIZE message and resize/move child controls. But, when a dialog contains many controls, resizing it would be a pain for the developer, and the OnSize function will look like a monster!

When I ran into this problem, I wrote a simple resizer that could help significantly in making resizable dialogs. All you have to do now is:

  1. Create a dialog resource and position the controls as you wish.
  2. Make CResizer m_resizer a member of your dialog class.
  3. Initialize the resizer in OnInitDialog (m_resizer.Init(...)).
  4. Move controls in OnSize simply by calling m_resizer.Move()!

Let's consider the implementation of CResizer class in detail.

The main idea is the following: Each side of a child window (left, top, right, and bottom) is connected to a side of another window, the so-called relative window. The dialog window that owns the children also can be a relative window. When the dialog window is resized, the child window sides are moved after the relative window, thus preserving the connections.

There are several types of connections:

Connection Type Constant Name Description
Fixed CResizer::eFixed Preserves the distance between the side of the child window and the specified side of the relative window
Proportional CResizer::eProportional Preserves the ratio of distance between the side of the child window and left (top) side of the relative window to width (height) of the relative window.
Preserving width CResizer::eWidth An auxiliary connection that preserves the width of the specified child window. It also can be implemented with a fixed connection.
Preserving height CResizer::eHeight An auxiliary connection that preserves the height of the specified child window. It also can be implemented with a fixed connection.

The connections for child windows are specified in a static array of the CResizer::CBorderInfo structures. The format is as follows:

{IDC_CTRL_ID, {(conn type), (rel id), (rel side)}, //Left side
              {(conn type), (rel id), (rel side)}, //Top side
              {(conn type), (rel id), (rel side)}, //Right side
              {(conn type), (rel id), (rel side)}, //Bottom side

Here, (conn type) is one of the connection types listed above, (rel id) is an identifier of the relative window or IDC_MAIN if you want to reference parent dialog, and (rel side) is the side of the relative window to which a connection is bound.

Each child window has four sides, so it has four connections—for left, top, right, and bottom. They are listed subsequently in the CResizer::CBorderInfo initialization above.

Let's consider the connection format (CResizer::CBorder structure) in more detail.

 {(conn type)            , (rel id)    , (rel side)         }

  CResizer::eFixed                       CResizer::eLeft
  CResizer::eProportional  IDC_MAIN      CResizer::eTop
 {CResizer::eWidth       , IDC_CTRL_ID , CResizer::eRight   }
  CResizer::eHeight                      CResizer::eBottom
                                         CResizer::eXCenter
                                         CResizer::eYCenter

A fixed connection can bind the child window side not only to a side of the relative window, but also to its horizontal (CResizer::eXCenter) or vertical (CResizer::eYCenter) center line.

A proportional connection needs only the width or height as relative window side. To specify width, use one of the horizontal sides (eLeft, eRight, or eXCenter); to specify height, use one of vertical sides (eTop, eBottom, or eYCenter).

Connections preserving width or height don't require relative window info. So, there can be any.

Typical Usage

  1. Make CResizer m_resizer a member variable of your dialog class.

  2. Add the following code to OnInitDialog(), replacing the control IDs to your specific ones and adjusting connections as you wish (described above).

    static const CResizer::CBorderInfo s_bi[] = {
     {IDC_CTRL1, {CResizer::eFixed, IDC_MAIN, CResizer::eLeft},   //l
                 {CResizer::eFixed, IDC_MAIN, CResizer::eTop},    //t
                 {CResizer::eFixed, IDC_MAIN, CResizer::eRight},  //r
                 {CResizer::eFixed, IDC_MAIN, CResizer::eBottom}},//b
     {IDC_CTRL2, {CResizer::eFixed, IDC_MAIN, CResizer::eLeft},
                 {CResizer::eFixed, IDC_MAIN, CResizer::eBottom},
                 {CResizer::eFixed, IDC_MAIN, CResizer::eRight},
                 {CResizer::eFixed, IDC_MAIN, CResizer::eBottom}},
    };
    const nSize = sizeof(s_bi)/sizeof(s_bi[0]);
    m_resizer.Init(m_hWnd, NULL, s_bi, nSize);
    
  3. Add the following code to the OnSize() handler:

    m_resizer.Move();
  4. Everything should work now.

Some Final Tips

  1. Resizer resizes controls in the order they are defined in the array, so (rel id) should always be defined (and, therefore, moved by the resizer) before it is used as relative window. Otherwise, resizer ASSERTs.
  2. Windows that are defined earlier in the array have higher priority. When windows have too small a size and child windows overlap, the window with lower priority is hidden.
  3. If you need to limit minimum or maximum window size, you can handle the WM_GETMINMAXINFO message.

Downloads

Download demo project - 103 Kb
Download source - 5 Kb

IT Offers

Comments

  • Nike Zephyr Max 1 FB publicity, have a fervent color fabric, the unheard of shoes

    Posted by Geozyoceada on 04/23/2013 09:42pm

    In the summer in a goblet interior the imperturbable sprite seems to be a godlike fitting, but if the sprite "feet"? Will also give you a lapse, get a invigorating! This summer, Nike and Sprite [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache free[/url] and his sneakers to a blend of outstanding example snow spread of unripened, unsullied and blue color blueprint in the time-honoured Nike Feeling Max 1 shoes let it be known a like a breath of fresh air chill scent.[url=http://markwarren.org.uk/goodbuy.cfm]nike free run uk[/url] Summer is the duration to pick a purified shoe, shoes should be a acceptable choice. Qualifying series Nike Quality Max HomeTurf megalopolis recently definitely comes up, this series in the immortal Melody Max shoes to London, Paris and Milan the three paid eulogy to the iconic see of Europe, combined with the characteristics of the three cities, Feeling Max 1 HYP,Tell Max 90 HYP,Connected Max 1 and shoes such as Style Max 95, combined [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] with the Hyperfuse, as kind-heartedly as a heterogeneity of materials, such as suede, Whether you after functional or retro-everything.

    Reply
  • Jordan shoes mentioned Gene to go for the variety, a division of Nike

    Posted by TaddyGaffic on 04/20/2013 02:02pm

    Where did that get us? A bunch of banks writing loans that they didnt care if poeple would be able to pay for because they were conforming [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] loans and Fannie and Freddie would back them. And their $150+ billion losses show that they are just as unable to predict or control the market as the rest of us. It won't work because it doesn't reward investors for taking the risks involved. In order to set a good example of following your dreams, you may wish to consider strictly limiting, or eliminating TV from your life. When people are involved in pursuing their dreams they often find that they do not have the time to watch TV. TV just gets in the way of pursuing other dreams.. Take a limousine ride with Aerosmith on one of the fastest rollercoaster you have to face. Live shows throughout the day from Beauty and the Beast [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] will bring memories flooding back for young and old. You can get closer to the action and feel that he wanted to be in the spotlight. Other technology advancements are the midsole. It has a compression molded EVA for lasting impact protection. A Vibrakill shock-absorber in the heel provides a lot of [url=http://markwarren.org.uk/property-waet.cfm]air max 90[/url] comfort, and the Exact Pro technology combines a pebax plate and a Dynamic camflex in the forefoot for improved energy return on every step. Meindl Borneo Lady Pro - This shoe is just one of my wifes most popular hiking boots. It is appropriate for lengthy outdoor hikes and you can actually do a tiny stretch of hill hiking whilst sporting them. This product also includes memory foam

    Reply
  • updates

    Posted by Sharon on 07/04/2012 04:43am

    Are there any updates on this Where can I find the update of Andrey del Pozo? Thanks

    Reply
  • Problem with button

    Posted by Dasein on 08/27/2007 10:19pm

    I have a button IDC_BUTTON3 in the right top corner of the dialog. I added code like this
    
    {IDC_BUTTON3,     {CResizer::eWidth, IDC_MAIN, CResizer::eLeft},
                              {CResizer::eHeight, IDC_MAIN, Resizer::eBottom},
                              {CResizer::eFixed, IDC_MAIN, CResizer::eRight},
                              {CResizer::eFixed, IDC_MAIN, CResizer::eTop}},
    
    After resizing this button disappeared only. Wherein was I wrong?

    Reply
  • My dialog having ActiveX control

    Posted by dino on 07/19/2005 06:10am

    This class is really very useful and easy to use..thnx for that. But I am facing problem when I try to resize my dialog which is containing ActiveX control on it. The ActiveX control is not getting resized when i resize the dialog. What may be the problem?

    Reply
  • license and copyright considerations to use this class

    Posted by padmawar on 06/13/2005 10:14am

    This is a great class to resize the controls. I would like to know are there any license and copyright considerations to use this class. Thanks.

    Reply
  • license and copyright considerations to use this class

    Posted by padmawar on 06/13/2005 10:09am

    This is a great class to resize the controls. I would like to know are there any license and copyright considerations to use this class. Thanks.

    Reply
  • Suggested improvement for ovelapping problem

    Posted by floppystein on 05/11/2004 08:29pm

    I had a problem with my Group boxes hiding the controls they were grouping.
    So, I made the following improvement to allow the option of not doing any hiding,
    which is just what I needed.
    1. Added a bool member variable m_bHideOverlapped and set it to true in the constructor.
    2. Added bool parameter bHideOverlapped to the Init() method, defaulted to true, and simply
    copied it to the member variable.
    3. In Andrey Del Pozos version of the MoveAndHideOverlapped() method, I bypassed the
    section which checked for overlapping if bHideOverlapped is false:
      
      :
      :
      CRectInfo &riSlave = m_vRectInfo[i];
      if (m_bHideOverlapped)
      {
        for(int j=0; j<i j++){
          const CRectInfo &riMaster = m_vRectInfo[j];
          if(riMaster.bVisible && riSlave.bVisible && !riSlave.bHide){ 
            RECT rc;
            ::IntersectRect(&rc, &riMaster.rc, &riSlave.rc);
            riSlave.bHide = !::IsRectEmpty(&rc);
          }
        }
      }
      else
      {
        riSlave.bHide = false;
      }
      :
      :
    
    Works for me. There may be other better ways, and I'd be happy to hear them.

    • Parent Window Corruption

      Posted by Kiarra on 07/20/2005 02:56am

      I discovered that when using a modeless dialog with microsft examples of a tool bar and status window, I had quite a bit of screen corruption, with parts of the dialog appearing as transparent. A cure for this was to to invalidate the parent window after the status bar and tool bar where moved and then call the resizer move. Although this does create a lot of Paint messages, especially as they ripple down through the children, it does cure the problem. Id be grateful if anyone has discovered an better cure for this. But thanks for a great utility

      Reply
    • Re: Original Code & Various improvements

      Posted by neauva on 06/25/2004 01:11am

      Thanks to Dmitry for the original code. And also thanks to Andrey and Andrew for improvements which were just what I needed as well!

      Reply
    Reply
  • Andrey del pozo improvmnet works perfectly and solves the problem

    Posted by elloko on 04/02/2004 09:42am

    I faced a problem when resizing more than 60 controls it was simply too slow thus, I have implemented Andrey del pozo improvement (DeferWindowPos) and now the class rock and rolls. Thanks Guys,

    Reply
  • Andrey del pozo improvmnet works perfectly and solves the problem

    Posted by elloko on 04/02/2004 09:40am

    I faced a problem when resizing more than 60 controls it was simply too slow thus, I have implemented Andrey del pozo improvement (DeferWindowPos) and now the class rock and rolls. Thanks Guys,

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Go Deeper

  • When the economy is stable, a company's IT organization may view Finance as just one of many internal customers competing for attention. But …
  • In Hollywood, nothing is more chic than analytics. On TV shows like CSI and in films like Iron Man, the industry's most iconic stars depend …
  • Increasing demands placed on IT, along with tightening budgets has prompted IT leaders to seek out alternative technologies and improved …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds