Sizing Dialog Box

Environment: Windows NT4 SP5, Visual C++ 6 SP3

Have you ever made sizing dialog boxes? Well I've made some (with my bare hands and a bit MFC support). Well it was quite a hack.

Later on, I've found some code on CodeGuru that made the whole thing much easier, but I didn't like the approach: Deriving your dialog box from some other class or having a member variable, handing it the sizing factors I want. Well it's quite easy, but this is layout, and layout is something I want to do in the Resource Editor. My code is complex enough without sizing dialogs. (And, by the way: none of the approaches works for VB or some other language)

So here is my suggestion: You make the dialog box. You turn on the "Sizing border" attribute. You insert the "Sizing Dialog control". Done

You can watch how your controls resize in as you test your dialog from the resource editor (remember: you haven't compiled once until now, nor have you made any code changes!)

There are two ways to use the control:

In Proportional mode all controls are kept at their relative positions. That is, if a control starts at let's say 30% of the dialog width, and takes 20% of the dialog's width, it will always start at 30%, and take 20%, no matter how many pixels that is. The controls behave like they've been stretchblit'd (of course, I don't really make a stretchblt)

In Normal mode, you have 9 fixed positions as shown below (the grey area marks the control):

Sample Image

A control that is completely in the "left, centered" will always stay left, centered. If the top-left edge of a control is in the "left, centered" area, and it's bottom-right edge is in the "centered, bottom" area, the two edges will move seperately. (English is not my first language, so you may prefer to look at the control's behaviour yourself...)

As I've said, I have made a few sizable dialogs, and this is what I've done most of the times. However, if you don't mind a bit of code, you can still change the sizing behavior (seperately for each of your controls) through the control's properties.

So now, the interface:

Note from Web Master : The following code was reformatted (each method was broken into two lines) so that it would display properly in our current format.
interface ISizeCtrl : IDispatch
{
[propget, id(1), helpstring("Property Proportional")] 
 HRESULT Proportional([out, retval] BOOL *pVal);

[propput, id(1), helpstring("Property Proportional")] 
 HRESULT Proportional([in] BOOL newVal);

[propget, id(2), helpstring("Property MinX")] 
 HRESULT MinX([out, retval] double *pVal);

[propput, id(2), helpstring("Property MinX")] 
 HRESULT MinX([in] double newVal);

[propget, id(3), helpstring("Property MinY")] 
 HRESULT MinY([out, retval] double *pVal);

[propput, id(3), helpstring("Property MinY")] 
 HRESULT MinY([in] double newVal);

[propget, id(4), helpstring("Property MaxX")] 
 HRESULT MaxX([out, retval] double *pVal);

[propput, id(4), helpstring("Property MaxX")] 
 HRESULT MaxX([in] double newVal);

[propget, id(5), helpstring("Property MaxY")] 
 HRESULT MaxY([out, retval] double *pVal);

[propput, id(5), helpstring("Property MaxY")] 
 HRESULT MaxY([in] double newVal);

[propget, id(6), helpstring("Property HandleMinMaxInfo")] 
 HRESULT HandleMinMaxInfo([out, retval] BOOL *pVal);

[propput, id(6), helpstring("Property HandleMinMaxInfo")] 
 HRESULT HandleMinMaxInfo([in] BOOL newVal);


[propget, id(7), helpstring("Property PosChangeX")] 
 HRESULT PosChangeX([in] long hwndChild, [out, retval] double *pVal);

[propput, id(7), helpstring("Property PosChangeX")] 
 HRESULT PosChangeX([in] long hwndChild, [in] double newVal);

[propget, id(8), helpstring("Property PosChangeY")] 
 HRESULT PosChangeY([in] long hwndChild, [out, retval] double *pVal);

[propput, id(8), helpstring("Property PosChangeY")] 
 HRESULT PosChangeY([in] long hwndChild, [in] double newVal);

[propget, id(9), helpstring("Property SizeChangeX")] 
 HRESULT SizeChangeX([in] long hwndChild, [out, retval] double *pVal);

[propput, id(9), helpstring("Property SizeChangeX")] 
 HRESULT SizeChangeX([in] long hwndChild, [in] double newVal);

[propget, id(10), helpstring("Property SizeChangeY")] 
 HRESULT SizeChangeY([in] long hwndChild, [out, retval] double *pVal);

[propput, id(10), helpstring("Property SizeChangeY")] 
 HRESULT SizeChangeY([in] long hwndChild, [in] double newVal);


[propget, id(11), helpstring("Property PosChangeXId")] 
 HRESULT PosChangeXId([in] long idChild, [out, retval] double *pVal);

[propput, id(11), helpstring("Property PosChangeXId")] 
 HRESULT PosChangeXId([in] long idChild, [in] double newVal);

[propget, id(12), helpstring("Property PosChangeYId")] 
 HRESULT PosChangeYId([in] long idChild, [out, retval] double *pVal);

[propput, id(12), helpstring("Property PosChangeYId")] 
 HRESULT PosChangeYId([in] long idChild, [in] double newVal);

[propget, id(13), helpstring("Property SizeChangeXId")] 
 HRESULT SizeChangeXId([in] long idChild, [out, retval] double *pVal);

[propput, id(13), helpstring("Property SizeChangeXId")] 
 HRESULT SizeChangeXId([in] long idChild, [in] double newVal);

[propget, id(14), helpstring("Property SizeChangeYId")] 
 HRESULT SizeChangeYId([in] long idChild, [out, retval] double *pVal);

[propput, id(14), helpstring("Property SizeChangeYId")] 
 HRESULT SizeChangeYId([in] long idChild, [in] double newVal);

};

Big interface, isn't it? Well, you don't have to use it if you only want the normal behaviour.

The first property exposes the settings I've already explained: Proportional/Normal. Then there are those "MinX, MaxX, MinY, MaxY" properties. Those control how much the dialog can be resized (values in percentage of the original size) If you want to handle WM_MINMAXINFO yourself, simply set HandleMinMaxInfo to FALSE, which is the default. All these properties are available in the resource editor trough the contol's property sheet.

The following properties: PosChangeX/Y, SizeChangeX/Y control the sizing behaviour of each individual element in your dialog. This way you can tell just what HWND should resize how. (Example: PosChangeX(m_btnOk.GetSafeHWnd, 0.2) means that if you make the dialog 100 pixels bigger, the OK-Button will move 20 pixels (that is 100*0.2) to the right. These changes have to made at run-time (e.g. in OnInitDialog).

PosChangeX/YId and SizeChangeX/YId do the same as their non-Id counterparts, but they take a Dialog-Item ID (IDOK, IDC_EDIT1...) instead of a HWND.

So now, how have I done all this?

Magic!

Ok, I'll tell you: It took me quite a time to figure out how to intercept the messages from a parent window (I've tried Hooks, timers, and other things you sure don't want to know about), until I found a handy ATL class named CContainedWindow. I simply tell this window to "SubclassWindow(GetParent())" and - magic - I recieve my parent's messages like my own ones. I can even decide whether to forward those messages to my parent or eat them all myself at runtime. (As the name suggests, CContainedWindow is usually used only for child windows, however, subclassing works for parent or even completely unrelated windows just as well). The rest is quote straightforward: I keep a map with a HWND-WndPos mapping inside, and iterate through all child windows on a WM_SIZE, to adjust their size.

A last note: The source code is documented, and should not be hard to understand. Unfoutunately, I'm working with a german version of VisualStudio, so some of the Wizard's comments are still german. I assume you know what the wizard would write, and I assume you don't really need his comments. All my comments are in english.

If you like the code, give it to your friends. If you don't, try to give it to your enemies. If you have any suggestions how to improve the usability of this control, feel free to email at me niki.estner@cube.net !

Downloads

Download Source - 18 Kb


Comments

  • How the **** do you use this?

    Posted by Legacy on 02/19/2002 12:00am

    Originally posted by: Clemens

    Please explain. Insert Sizing Dialog??? Where?? How?? This may be great code but I have absolutely no idea how to use it.

    Reply
  • There is a small bug in processing

    Posted by Legacy on 01/10/2002 12:00am

    Originally posted by: Steve Miller

    In SizeCtrl.h:
    
    

    RECT GetControlPos(HWND hWnd)
    {
    WINDOWPLACEMENT sPlace;
    ::GetWindowPlacement(hWnd, &sPlace);
    return sPlace.rcNormalPosition;
    }

    Not initializing the length item causes the process to fail on Win95/98 machines.

    RECT GetControlPos(HWND hWnd)
    {
    WINDOWPLACEMENT sPlace;

    sPlace.length = sizeof(WINDOWPLACEMENT);
    ::GetWindowPlacement(hWnd, &sPlace);

    return sPlace.rcNormalPosition;
    }

    Thanks :)
    Steve

    Reply
  • Sizing Dialog Box

    Posted by Legacy on 12/14/2001 12:00am

    Originally posted by: Raul Bove

    could you send me a sample ?
    
    

    thanks

    Reply
  • Wonderfully Simple

    Posted by Legacy on 12/06/2001 12:00am

    Originally posted by: Steve Miller

    This is just what I was looking for. Thank you

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

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 23, 2014 @ 12:00 p.m. ET / 9:00 a.m. PT Despite the current "virtualize everything" mentality, there are advantages to utilizing physical hardware for certain tasks. This is especially true for backups. In many cases, it is clearly in an organization's best interest to make use of physical, purpose-built backup appliances rather than relying on virtual backup software (VBA - Virtual Backup Appliances). Join us for this eSeminar to learn why physical appliances are preferable to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds