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 - 12 KB
Date Posted: January 31, 1999