Enabling/Disabling a Group of Controls

Overview

The MFC FAQ "Item 6.3.5. How do I enable/disable a bank
of checkboxes?" discusses a technique for enabling/disabling
a "bank" of check boxes. I would like to present a
method of enabling/disabling a "Group" of controls.

Background

If a control uses the WS_GROUP style, it "Specifies the
first control of a group of controls in which the user can move
from one control to the next by using the arrow keys. All
controls in the tab order after the first control with the Group
property set to False belong to the same group. The next control
in the tab order with Group set to True ends the first group of
controls and starts the next group. Type: Bool. Default:
False"[1]. A "Group Box" control is often used to
group controls, with the Group Box having the WS_GROUP style.

Design

The method of enabling/disabling a Group of controls presented
here simply iterates thru the controls in a Group
enabling/disabling each control as it is encountered.
Unfortunately, the MFC CWnd::GetNextDlgGroupItem() method is not
suitable for this task because it skips over controls that are
not enabled[2]. The technique presented here derives a new class
from CDialog named CDialogEx, and adds two methods
CDialogEx::EnableDlgGroup() and
CDialogEx::GetNextDlgGroupItemEx(). These functions are
prototyped as follows:


BOOL	CDialogEx::EnableDlgGroup(int nDlgItemId, BOOL fEnable);
CWnd	* CDialogEx::GetNextDlgGroupItemEx(CWnd *pCtrlWnd);

Implementation

CDialogEx::EnableDlgGroup() and
CDialogEx::GetNextDlgGroupItemEx() are simple wrappers for the
lower level functions CWnd_EnableDlgGroup() and
CWnd_GetNextDlgGroupItemEx(). CDialogEx was implemented this way
so the user may also use CWnd_EnableDlgGroup() and
CWnd_GetNextDlgGroupItemEx() directly (instead of always having
to derive a new class from CDialogEx).

CDialogEx::EnableDlgGroup() and
CDialogEx::GetNextDlgGroupItemEx() are defined as follows:


BOOL	CDialogEx::EnableDlgGroup(int nDlgItemId, BOOL fEnable)
{
	// nDlgItemId is typically the resource id of
	// a (Group Box) control with WS_GROUP style
	return CWnd_EnableDlgGroup(this, nDlgItemId, fEnable);
}

CWnd	*CDialogEx::GetNextDlgGroupItemEx(CWnd *pCtrlWnd)
{
	return CWnd_GetNextDlgGroupItemEx(pCtrlWnd);
}

CWnd_EnableDlgGroup() and CWnd_GetNextDlgGroupItemEx() are
defined as follows:


BOOL	CWnd_EnableDlgGroup(CWnd *pDlgWnd, int nDlgItemId, BOOL fEnable)
{
	CWnd	*pCtrlWnd;

	if (pDlgWnd == NULL
	|| (pCtrlWnd = pDlgWnd->GetDlgItem(nDlgItemId)) == NULL)
	{
		return FALSE;
	}

	do
	{
		pCtrlWnd->EnableWindow(fEnable);
	} while ((pCtrlWnd = CWnd_GetNextDlgGroupItemEx(pCtrlWnd)) != NULL);

	return TRUE;
}

CWnd	*CWnd_GetNextDlgGroupItemEx(CWnd *pCtrlWnd)
{
	CWnd	*pWnd;

	if (pCtrlWnd == NULL
	|| pCtrlWnd->GetDlgCtrlID() == 0
	|| (pWnd = pCtrlWnd->GetWindow(GW_HWNDNEXT)) == NULL
	|| (pWnd->GetStyle() & WS_GROUP))
	{
		return NULL;
	}

	return pWnd;
}

Test Application

The source for CDialogEx along with a test project is
included. The test project is an MFC App Wizard Dialog based
application built using MSVC 5.0 with SP3 applied. It’s main
window is a dialog box derived from CDialogEx. The dialog box
contains two check boxes and two group boxes. Checking a check
box enables/disables the controls in it’s associated group box.

References

[1] MS Windows Win32 SDK online help

[2] MS Knowledge Base article Q114980

Download CDialogEx source code and
demo project – 11 KB

More by Author

Must Read