Expanding/Contracting Dialog Box

In a moderately complex application, the user is presented with the task of learning the features of the software. It is useful, in some cases, to limit the features that a beginning user has access to; also, an advanced user will appreciate not being inundated with a large number of controls on a dialog, but only the ones that are used most frequently. Hence the need for an expanding and contracting dialog.

The premise of the expanding/contracting dialog is to present a set of controls on a dialog to the user, and then allow access to the rest of the "advanced" controls if the user clicks the appropriate button to expand the dialog. A sample of this is as follows:

The class presented here fits between your dialog class and CDialog, so that the expanding/contracting actions can be automatically managed. There is minimal change to be made to your existing dialog class code, so it is easy to add and remove this expanding/contracting feature to your dialogs.

This code should be UNICODE correct (it has not been tested), and compiles warning free under VC++5 using MFC 4.2.

Instructions

  1. add the ExpandingDialog.h and ExpandingDialog.cpp files to your project.
  2. add a static frame to your dialog (in VC++, this is the "picture control") for the default box, and give it a unique resource ID.
  3. add a button to your dialog which will be the "Advanced" button (the one that expands and contracts the dialog), and give it a unique resource ID.
  4. in your dialog's .h and .cpp files, replace all occurrences of CDialog with CExpandingDialog.
  5. in your dialog's .h file, put a "#include ExpandingDialog.h" above your dialog's class declaration.
  6. modify the constructor of your dialog in your dialog's cpp file, to look something like the following:
    
    CMyDialog1::CMyDialog1(CWnd* pParent) : CExpandingDialog(CMyDialog::IDD,
    pParent,IDC_DEFAULTBOX,IDC_ADVANCEDBUTTON, _T("Advanced >>"),
    _T("Advanced <<"))
    
    (In this example, IDC_DEFAULTBOX was the ID given for the static frame in step 2, and IDC_ADVANCEDBUTTON was the ID given for the button in step 3.)

That is all that needs to be done; recompile and run your application, and the expanding/contracting dialog should work correctly. For extended capabilities, please read the documentation for the utility and virtual functions listed below.


Class Members

Constructor:

CExpandingDialog(
   UINT nIDTemplate,
   CWnd* pParent, 
   int nIDFrame,
   int nIDButton,
   LPCTSTR strExpand = _T("Advanced >>"), 
   LPCTSTR strContract = _T("Advanced <<"),
   BOOL bAllowContract = TRUE)

Normally, the constructor is called from the implementation of your dialog's constructor. The first two parameters are the same as those taken by CDialog. The rest are specific to CExpandingDialog, are are as follows:


int nIDFrame 

the resource ID of the static frame that defines the boundaries of the contracted state of the dialog.


int nIDButton 

the resource ID of the button that will be used to expand and contract the dialog


LPCTSTR strExpand and LPCTSTR strContract 

the strings that will be put on the button identified by nIDButton, when the dialog is in its contracted and expanded state, respectively.


BOOL bAllowContract

if TRUE, the dialog will allow the user to both expand and contract the dialog. If FALSE, the user may expand the dialog, but may not ever contract it again. This flag does *not* affect the operation of the Expand() function; in other words, you may still programatically expand and contract the dialog.

Utility Functions:

BOOL IsExpanded() const

Use this function to query the current expanded or contracted state of the dialog. TRUE denotes an expanded dialog, and FALSE denotes a contracted dialog.


BOOL Expand(BOOL bExpand)

Call this function to expand or contract the dialog manually. This function returns whether the new state matches the state passed in the "bExpand" parameter. In other words, TRUE on success, and FALSE on failure.

If the state passed into this function matches the current state of the dialog, this function returns TRUE immediately without calling any of the virtual notification functions OnDialogExpanding and OnDialogExpanded.

 

Overridables:

BOOL OnDialogExpanding(BOOL bExpand) const

This function is called when the dialog is about to expand or contract. The parameter "bExpand" tells whether we are about to expand or contract the dialog. Return TRUE to allow the operation to continue, and FALSE to keep the dialog from expanding or contracting.

The default implementation of this function simply returns TRUE to allow the dialog to change state.


void OnDialogExpanded(BOOL bExpand) const

This function is called after the dialog has expanded. The parameter "bExpand" tells whether the dialog is now in the expanded or contracted state. This is the appropriate place to do things like set the focus to a particular control, change text in controls on the dialog, etc.

The default implementation of this function does nothing.


Final notes:

If needed, is it possible to handle the message generated by the click of the "Advanced" button, simply by adding the appropriate message handler to your dialog's message map. Handling this message does not affect the operation of the expanding/contracting dialog. If you do choose to handle this message, be aware that this implementation of the expanding/contracting dialog guarantees that the dialog will have fully changed state before you receive the message from the Advanced button that it has been clicked. This is very useful, because you can assume that the dialog is (again) in a static state, with the appropriate controls enabled/disabled, before you receive the message.

Credits: the code in the ExpandBox() member function is based on code by Jeffery Richter in "Windows 95: A Developer's Guide"

Download demo project - 49 KB

Download source - 5 KB