Click here to Skip to main content
15,878,970 members
Articles / Desktop Programming / WTL
Article

AutoSizeDlg - an autoresizing class for ATL/WTL

Rate me:
Please Sign up or sign in to vote.
3.88/5 (5 votes)
16 Jul 2006MIT12 min read 46.4K   1.9K   31   7
AutoSizeDlg - an autoresizing class for ATL/WTL

Sample Image - AutoSizeDlg1.gif Sample Image - AutoSizeDlg2.gif

Introduction

Bwahahahhah... My second article/library/program! This library (based on the ATL libraries and supporting the WTL libraries) will make the controls of your windows auto-sizing. They'll adapt to the size of the window.
The library is quite advanced... It supports transparent controls, nested groups of controls, controls that span multiple rows and columns, scrollable windows, auto-setting the minimum and maximum size of the window and many other things... BUT it's quite beta material... I haven't tested all the features in all the possible combinations.
The library requires VC++ (I have tested it with VC++ 8.0, but it should work with earlier versions... I'm not very sure how much earlier, because I use many "strange tricks" of VC++), ATL (probably at least 7.0) and it supports the WTL libraries (to compile the AutoSizeScroll you'll need a recent version of WTL. WTL 7.5 IS recent... Anything else IS NOT!)

Notes

If you are a purist of C++ you SHOUDN'T look at the library... I have done so many wrong things that you would become ill only by seeing them :-) I've used quite liberally the _alloca "function" even in the middle of array initialization, used the "," operator, and too many other "wrong" things... BUT I have commented all the main methods and constants with Doxygen, so you can "compile" the documentation (already compiled in .html and .chm format). The library doesn't use heap based memory. It only uses the stack.... And it uses it quite much... (no... you won't need megabytes of stack... Only a kilobyte or so probably)

How does the library work

Example grid

(note that this image IS very similar to one of http://www.codeproject.com/dialog/EvaLayout.asp ... But plagiarism IS a form of flattery)
Observe that we have divided our window in cols and rows (the orange lines). Light gray rectangles are the ctrls of the window. The white rectangle is a ctrlless area.
Our ctrls can span multiple columns/rows (for example ctrl 6 and 9 span 2 and 3 columns, the 8 spans 2 rows).
A ctrl can even be an aggregated group of ctrls (a nested area) (see that under the 11-12-13-14 ctrls there is a light gray rectangle that spans three columns and two rows).
The aggregated group of ctrls can in turn be divided in columns and rows (3 columns and two rows, the dark grey rectangles). Now we will learn how to describe this to the library.

Using the library

You'll need to include atlautosizedlg.h after the atlwin.h include (probably in stdafx.h). In the stdafx.h before the first #include put this:

#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
Then in the dlg/window class declaration add this:
class MyClass : public ..., public CAutoSizeWindow<MyClass>
BEGIN_WINDOW_MAP(MyClass, 10, 10, 8, 8) 
    WMB_HEAD(     WMB_COL(60), WMB_COL(_exp), WMB_COL(25), WMB_COL(75)), 
    WMB_ROW(15,   ID1,         _,             ID3,         ID4), 
    WMB_ROW(15,   ID5,         ID6,           _r,          ID7), 
    WMB_ROW(15,   ID8,         ID9,           _r,          _r), 
    WMB_ROW(_exp, _d), 
    WMB_ROW(15,   ID10), 
    WMB_END() 
END_WINDOW_MAP()

What do we see? We see that we have to begin with a BEGIN_WINDOW_MAP(). The first parameter is the name of the class, then we have a left/right margin, a top/down margin, a horizontal gap between ctrls and a vertical gap between controls. Then we have a column header. Each column is described in this format: WMB_COL(size).
REMEMBER: All the sizes can be expressed in Dialog Units (look in the MSDN for what a DLGUnit is, and remember that it's the measure unit used by the Visual Studio) or in Pixels. To use Pixels make the number negative. So 60 is 60 DLGUnits, -60 is 60 Pixels. If you have special flags to pass to macros you can do something like this: 60|FLAG1 or -60 ^ FLAG1 (you HAVE to use the XOR (^) operator with negative numbers). For the empty ID2 we use a single underscore (_) (or even a double underscore (__) will work).
Note that not all the rows need to be "complete". The last row (the one with ID10) is not complete and everything works.
We used _r and _d to make a ctrl span multiple columns and rows (_r = right, _d = down). _exp means that instead of a fixed width/height the column/row will expand to be as large as possible.

We HAVEN'T included ctrls 11-14. Now we will include them... Instead of

WMB_ROW(_exp, _d), 
WMB_ROW(15,   ID10), 

put this:

WMB_ROW(_exp, _d,     WMB_HEAD(     WMB_COL(35), WMB_COL(_exp), WMB_COL(30)),
                      WMB_ROW(_exp, ID12,        ID13,          ID14), 
                      WMB_ROW(30,   ID15,        _r,            _r), 
                      WMB_END()),        
                                  _r, _r), 
WMB_ROW(15,   ID10,   _d), 

Note how the commas are used. There is nearly always a comma after a macro, unless the macro is the last parameter of another macro. The last WMB_END() before END_WINDOW_MAP() MUSTN'T have a comma. Note that to make a ctrl (or a group of ctrls) span multiple cols AND rows you do this:

IDCtrl, _r, _r, 
_d,     __, __, 
_d,     __, __ 

Under the _r you don't need to add _d or _r... You can even put another ctrl (hint hint: group boxes with ctrls)

IDGroup, _r,  _r,  _r,
_d,      ID1, ID2, 
_d,      ID3, ID4,
_d 

The extra _r and _d are to give some space between the right margin of the ID2 and ID4 and the right margin of the group box.

To make everything work at the end of the BEGIN_MSG_MAP() you must add:

BEGIN_MSG_MAP(MyClass) 
    ... 
    CHAIN_MSG_MAP(CAutoSizeWindow<MyClass>) 
END_MSG_MAP() 

To make everything work perfectly you should activate the WS_CLIPCHILDREN, WS_CLIPSIBLINGS styles of the container window and give the transparent style to group boxes and IMAGE controls used as rectangles. Now everything should work...

Transparent controls

This library supports transparent Group Boxes and IMAGE controls used as rectangles. To activate this support add:

TRANSPARENT_LIST(MyClass, IDGroupBox1, IDImageCtrl1, IDGroupBox2, IDImageCtrl2) 

before the BEGIN_WINDOW_MAP() or after the END_WINDOW_MAP() and remember to put the WS_EX_TRANSPARENT extended style to the controls!!

Other tricks

There are too many "special" things you can do...

Column/rows sizes

  • [_auto] Use the maximum width/height of the controls in the column/row as the size. No optional parameter
  • [_exp] The column/row will be proportionally expanded. Optional parameter: "weight" of the column/row (DEFAULT: 100)
  • [_contr] If all the other rows/columns are already maxed out, the remaining space will be divided proportionally between Contractable columns. Optional parameter: "weight" of the column/row (DEFAULT: 100)
  • [_eq] The column/row will have the same width/height and the same min/max width/height of another column/row. Necessary parameter: the number of the column/row (zero based. The first column/row is the number 0)
  • [_gap] The column/row will be GAP wide (useful for some tricks). Optional parameter: "extra" width/height ADDED to the column. Positive if DLGUnits, negative (remember the ^) for Pixels
  • [_gapm] The column/row will be GAP wide (useful for some tricks). Optional parameter: "extra" width/height SUBTRACTED (minimum 0) to the column. Positive if DLGUnits, negative (remember the ^) for Pixels
  • [(nothing)] The width/height of the column is fixed. Necessary parameter: the width/height of the column/row. Positive if DLGUnits, negative (remember the ^) for Pixels. Note that you don't need to use WMSRC_FIXED because it's 0
  • [_nog] (this is a special flag that you have to add to the other flags). Do not prepend the usual gap before this column/row. The first column/row doesn't have a gap.

Cell expansion

  • [_r] The ctrl on the left of this cell will continue in this cell
  • [_d] The ctrl on the top of this cell will continue in this cell
  • [_ & __] The cell is empty (you could directly use 0, but it would be more difficult to debug)

Minimum and maximum sizes of columns and rows

Instead of WMB_COL(size) or WMB_ROW(size, ctrls...) you can use other macros that will let you decide the minimum and maximum width/height of columns/rows.
These macros are named in a standard way: MIN before MAX, nothing means that the program will try to calc the value itself, NOMIN or NOMAX means that there isn't a minimum (the minimum is 0) or there isn't a maximum.
So we have WMB_COL, WMB_COLMIN, WMB_COLMAX, WMB_COLMINMAX, WMB_COLNOMIN, WMB_COLNOMAX, WMB_COLNOMINNOMAX, WMB_COLNOMINMAX, WMB_COLMINNOMAX and the respective WMB_ROW* the minimum and/or maximum value are given in this way:

WMB_COLMIN(sizeflag, minsize) 
WMB_COLMAX(sizeflag, maxsize) 
WMB_COLMINMAX(sizeflag, minsize, maxsize) 

WMB_ROWMIN(sizeflag, minsize, ctrls...) 
WMB_ROWMAX(sizeflag, maxsize, ctrls...) 
WMB_ROWMINMAX(sizeflag, minsize, maxsize, ctrls...) 

NOMIN and NOMAX modifiers don't need a parameter. So WMB_COLNOMIN(sizeflag), WMB_ROWNOMINMAX(sizeflag, maxsize, ctrls...) ... REMEMBER: All the sizes can be expressed in Dialog Units or in Pixels. To use Pixels make the number negative.

References

While I was too much lazy to really read them, this library is based on the pictures (meaning that I opened the page, watched the pictures and found that they were very beautiful and gave me the right direction) of:

(no, I'm not kidding... Initially I only wanted to create a macro based version of EvaLayout... (remember, I didn't truly read the article... my attention span was too much short in that period) So the 1.0 version of the library was born... Then I decided that I wanted nestable groups of ctrls... And, in the end, a strange hybrid of the two articles was born. But I was really too much lazy to read them... they were so long... So if you won't read this article completely I won't be angry with you :-) I'm not very sure I would read my article :-) )

Comparison with other similar libraries

I'm adding this section because some persons has asked for it. The world is FULL of libraries that move controls in a window. WTL has one. Paul DiLascia did one of the most famous in 2001. You can use whatever library you want. My life won't change. I'll even help you... Here there is a small selection: (the first one is the DiLascia's one, it's pure Windows API. The next three ones are MFC (I'm not sure, but they should be)... Perhaps they have ATL Support. The others are WTL (at least one is simply an explanation of the standard WTL library and another is a little expansion of the standard WTL library))

I HATE to compare my programs with the programs of other... I always think I'm sinning of pride when I do it. There are as many ways of doing things as there are programmers... Programs are not always better or worse... very often they are only different. If you can't see the differences in the libraries then you shouldn't program. If you don't have the time to select the right library for your program then you should choose one at random and hope it's the best one. There are persons that buy the first thing they see... There are others that try to discover the differences between similar products and then buy the better one/the cheaper one/the most balanced...

I CAN tell you what my library does:

  • It's ATL/WTL (some libraries are MFC)
  • It's MACRO based. The layout of the controls in the MACRO is similar (in a left-to-right, top-to bottom, rows are rows, cols are cols) to what will appear on the screen
  • It's very fast. The matrix is read only once from the first to the last element (once for each OnSize event at least). No heap memory is allocated. API calls are limited and their results are cached. No extra memory is allocated by the initialization. For a single level ctrl group the matrix is big something like 21 + (3 * cols + 5 * rows + 1 * number of ctrls) integers (give or take one or two integers)
  • It has a solution for group box flickering that supports the alt key in WinXP (in XP the accelerators are normally hidden unless you press the alt key. Then they are showed)
  • It can do nearly all the layouts... some layouts are more difficult of others. You have to use intelligence to use this library... You need variable gaps? Put the standard gap at 0 and add empty rows/columns between your rows/columns. You need to align a ctrl to the left or the right of a bounding box? Add an empty expandable (or contractable) column to the left or to the right of the ctrl

I CAN even tell you what my library can't do:

  • This is a library to move ctrls in a window. It isn't a window management library. I won't give you methods to save the position of the window in the registry. I won't give you grippers to resize the window. I won't give you scrollbars (but scrollbars ARE supported through CScrollImpl)
  • The internal format of the matrix is a mess. The matrix is statically allocated so modifying directly it is not a good thing BUT you can give to the library another matrix: observe that all the methods have as a parameter the matrix.
  • I won't give you a "30% of the total size" ctrl, because it isn't possible... You have a 5 pixel column and a 75% column and a 10 pixel width window. What happens? One of the two constraints can't be respected.

And finally I CAN tell you the main differences between libraries:

  • Some are MACRO based (mine and Paul DiLascia's for example) others are class based (you add the controls to a class in the initialization of the window... Something like Handler += ctrl1; Handler += ctrl2; ... or there is a library where the layout is stored in strings that can even be saved in external files)
  • Some libraries handle only the resizing of controls. They start from what you give them in the dialog editor and then expand/contract the controls proportionally. They can move the controls but they move them relatively to their initial position in the dialog editor (the WTL standard library for example and many others... Nearly all the non-grid based). Other libraries (mine and others) let you decide the position of the controls somewhere in the program. The dialog editor is used only to add the controls and modify their styles.
  • Some are Windows API only, some are MFC, some are ATL/WTL (perhaps there are even MFC/ATL libraries)

History

  • atlautosizedlg.h 1.0 Apr 2006 Initial Release (not published)
  • atlautosizedlg.h 2.0 Jun 2006 Nearly rebuilt. Now supports multilevel
  • License

    I’m a BSD guy, so I’ll license this library under the MIT license (a simplified BSD license).

    Copyright (c) 2006 Massimiliano Alberti xanatos(at)geocities.com

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralNr.1 Pin
Vytas17-Jul-06 22:11
Vytas17-Jul-06 22:11 
GeneralRe: Nr.1 [modified] Pin
xanatos17-Jul-06 23:25
xanatos17-Jul-06 23:25 
Yeah... And the layouts are VERY readable...
Look at his example... (the one under Sample) It's impossible to comprehend how the controls will appear on the screen.
When I built this library I had two prereq:
A) It had to be MACRO BASED
B) The layout of the MACROs had to be very similar to what would have appeared on screen (at least on a left-to-right top-to-bottom level)
C) I wanted everything to be as much fast as possible. The library had to be able to work without using extra memory from the heap and do everything in a single pass.

His library HAS probably more features BUT

A) It isn't MACRO based
B) The last time it was updated was in 2000
C) It's MFC, this library is ATL/WTL
D) I'm not sure but does it have a resolution for the flickering of Group Boxes in XP with themes (it's from 2000)? Looking at the demo, even without themes, the group box flickers a lot (Dialog with Groupbox)

From a layout standpoint I'm pretty sure my library can create all the layouts of the layoutmgr AND some more (I haven't seen options for maximum size, my library can do maximum size of expandable rows/columns). He can do alignment of controls in boxes... My library can do it: you only have to add an extra expandable column to the left or to the right. His library can have variable space between controls. My library can: you use a 0 Gap and add manually the "empty" space as an empty row/column

He has Sizing Grippers and automatic re-/storage of windowsizes in the registry.
My library hasn't... But I'm not even sure it should have... I have done a library to move controls in a window... I don't manipulate the window.


-- modified at 7:06 Tuesday 18th July, 2006
GeneralRe: Nr.1 Pin
xanatos17-Jul-06 23:31
xanatos17-Jul-06 23:31 
GeneralRe: Nr.1 Pin
Vytas18-Jul-06 22:57
Vytas18-Jul-06 22:57 
GeneralCDialogResize Pin
Igor Vigdorchik17-Jul-06 3:27
Igor Vigdorchik17-Jul-06 3:27 
GeneralRe: CDialogResize Pin
xanatos17-Jul-06 4:42
xanatos17-Jul-06 4:42 
GeneralRe: CDialogResize Pin
Igor Vigdorchik17-Jul-06 9:15
Igor Vigdorchik17-Jul-06 9:15 

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.