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
- add the ExpandingDialog.h and ExpandingDialog.cpp files to
your project. - 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. - 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. - in your dialog’s .h and .cpp files, replace all occurrences
of CDialog with CExpandingDialog. - in your dialog’s .h file, put a "#include
ExpandingDialog.h" above your dialog’s class declaration. - 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”