Using Multiple Inheritance to Enhance DDX


This article was contributed by Malcolm Keller Beyer III.

Environment: VC5 SP3

Overview

This article presents a technique of using one operation to set or retrieve all CDialog DDX data members. Unfortunately, this technique does this at the expense of limiting MFC Class Wizard's ability to maintain the dialog's DDX data members.

Background

MFC Dialog Data Exchange (DDX) makes it easier to exchange data between CDialog data members and dialog box controls. MFC Applications often use dialog boxes to obtain and store user input using code similar to the following:

	// Construct the dialog
	CDerivedDlg	dlg(AfxGetMainWnd());

	// Set the dialog's data members
	dlg.m_fCheck = m_fCheck;
	dlg.m_nRadio = m_nRadio;
	// ...

	// Call DoModal()
	if (dlg.DoModal() == IDOK)
	{
		// Get the dialog's data members
		m_fCheck = dlg.m_fCheck;
		m_nRadio = dlg.m_nRadio;
		// ...
	}		

Using multiple inheritance the individual member assignments may be replaced with two statements:


	// Construct the dialog
	CDerivedDlg	dlg(AfxGetMainWnd());

	// Set the dialog's data members
	static_cast<CDialogData &>(dlg) = m_dlgdata;

	// Call DoModal()
	if (dlg.DoModal() == IDOK)
	{
		// Get the dialog's data members
		m_dlgdata = dlg;
	}		

Design

When MFC Class Wizard is used to create DDX member variables, it makes them members of the derived CDialog. The technique presented here moves all of the dialog's DDX data members variables into their own class (e.g. CDialogData) and the dialog is then modified to also inherit from CDialogData. For example the following CDerivedDlg:

class CDerivedDlg : public CDialog
{
// Construction
public:
	CDerivedDlg(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CDerivedDlg)
	enum { IDD = IDD_DERIVED };
	int	m_nRadio;
	BOOL	m_fCheck;
	CString	m_strCombo;
	CString	m_strEdit;
	CString	m_strStatic;
	//}}AFX_DATA
	...
};
Becomes:

class CDialogData
{
public:
	int	m_nRadio;
	BOOL	m_fCheck;
	CString	m_strCombo;
	CString	m_strEdit;
	CString	m_strStatic;
};

class CDerivedDlg : public CDialog, public CDialogData
{
// Construction
public:
	CDerivedDlg(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CDerivedDlg)
	enum { IDD = IDD_DERIVED };
	//}}AFX_DATA
	...
};

Implementation

The included demo project (see picture above) has a dialog box resource i.e. IDD_OPTIONS used to implement both approaches to DDX. The project's CTraditionalOptionsDlg class uses IDD_OPTIONS to implement the traditional approach to DDX, and the project's CAlternativeOptionsDlg class uses IDD_OPTIONS to implement this alternative approach.

After using Class Wizard to created CAlternativeOptionsDlg, it was modified using the following steps:

These modifications (especially the last step) prevent MFC Class Wizard from being used to maintain the DDX data members. This is disappointing, but can be dealt with some what by leaving the DDX data members commented out in CAlternativeOptionsDlg's source files and moving them back into the appropriate AFX_DATA_*() section as necessary (the demo project does this).

Demo Application

The included demo application (shown in the picture above) is a CDialog based app with a menu bar. The Options Menu has two submenus, Alternative... and Traditional... which are used to demonstrate the traditional method of DDX and the alternative method presented here. Both display the same dialog (IDD_OPTIONS) which contains several different types of controls. If the user presses the OK button the application stores the dialogs data members.

Downloads

Download demo project - 22 KB

History


Date Posted: September 22, 2001