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:
- Create a dialog resource and position the controls as you wish.
- Make CResizer m_resizer a member of your dialog class.
- Initialize the resizer in OnInitDialog (m_resizer.Init(...)).
- 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
- Make CResizer m_resizer a member variable of your dialog class.
- 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); - Add the following code to the OnSize() handler:
m_resizer.Move();
- Everything should work now.
Some Final Tips
- 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.
- 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.
- If you need to limit minimum or maximum window size, you can handle the WM_GETMINMAXINFO message.
Downloads
Download demo project - 103 KbDownload source - 5 Kb

Comments
Nike Zephyr Max 1 FB publicity, have a fervent color fabric, the unheard of shoes
Posted by Geozyoceada on 04/23/2013 09:42pmIn 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.
ReplyJordan shoes mentioned Gene to go for the variety, a division of Nike
Posted by TaddyGaffic on 04/20/2013 02:02pmWhere 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
Replyupdates
Posted by Sharon on 07/04/2012 04:43amAre there any updates on this Where can I find the update of Andrey del Pozo? Thanks
ReplyProblem with button
Posted by Dasein on 08/27/2007 10:19pmI 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?ReplyMy dialog having ActiveX control
Posted by dino on 07/19/2005 06:10amThis 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?
Replylicense and copyright considerations to use this class
Posted by padmawar on 06/13/2005 10:14amThis 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.
Replylicense and copyright considerations to use this class
Posted by padmawar on 06/13/2005 10:09amThis 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.
ReplySuggested improvement for ovelapping problem
Posted by floppystein on 05/11/2004 08:29pmI 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.-
-
ReplyParent Window Corruption
Posted by Kiarra on 07/20/2005 02:56amI 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
ReplyRe: Original Code & Various improvements
Posted by neauva on 06/25/2004 01:11amThanks to Dmitry for the original code. And also thanks to Andrey and Andrew for improvements which were just what I needed as well!
ReplyAndrey del pozo improvmnet works perfectly and solves the problem
Posted by elloko on 04/02/2004 09:42amI 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,
ReplyAndrey del pozo improvmnet works perfectly and solves the problem
Posted by elloko on 04/02/2004 09:40amI 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,
ReplyLoading, Please Wait ...