Win32 Dialog Data Exchange

Dialog window is the top level window and dialog controles like button, editbox, checkbox, combobox, radio buttons, list box are child windows. These child controls are identified by an identity number or ID. There are Win32 API to retrive values from the UI controls as well as there are APIs for appliying values to UI controls. Each UI controls holds different types information in it thus exchange of data sould be in different types of variables. Lets discuss data exchange routines of UI controls editbox, checkbox, combobox, radio buttons, list box one by one.

User can can retrieve strings, integer, BOOL etc using these calls

int GetWindowText(
HWND   hWnd,
LPTSTR lpString,
int    nMaxCount
);

UINT GetDlgItemText(
HWND   hDlg,
int    nIDDlgItem,
LPTSTR lpString,
int    nMaxCount
);

UINT GetDlgItemInt(
HWND hDlg,
int  nIDDlgItem,
BOOL *lpTranslated,
BOOL bSigned
);

UINT IsDlgButtonChecked(
HWND hDlg,
int  nIDButton
);

These Win32 API are used to apply text or set the state of the button from variable.

BOOL SetWindowText(
HWND    hWnd,
LPCTSTR lpString
);

void SetDlgItemInt(
HWND hDlg,
int nID,
UINT nValue,
BOOL bSigned
);
void SetDlgItemText(
HWND hDlg,
int nID,
LPCTSTR lpszString);
	
void CheckDlgButton(
HWND hDlg,
int nIDButton,
UINT nCheck
);

void CheckRadioButton(
HWND hDlg,
int nIDFirstButton,
int nIDLastButton,
int nIDCheckButton
);

MFC Dialog Data Exchange

MFC applications can use these same APIs wrapped in CWnd class. These APIs often require additional variables to exchange a single value. MFC however has a managed way to exchange data. This is known as MFC Dialog Data exchange. MFC data exchange is not an indipendent way however above Win32 APIs are useed to construct these MFC data exchange macros.

MFC uses C++ style managed approach we take meaningful dialog member variables in dialog class. Sametime dialog has corrosponding UI contols like textbox, checkbox, radio button, combo dropdown etc. One example with student application login dialog. I have two text box IDC_EDITUSER and IDC_EDITPASSWORD and one checkbox IDC_CHKREMEMBER. We have taken two CString type variable named as m_strUsername and m_strPassword for handling these text fields. There is also m_bRemember member which is a BOOL type variable to exchange data between checkbox.

class CStudentDlg : public CDialog
{
public :
    CStudentDlg(void);
    ~CStudentDlg(void);
   virtual void DoDataExchange(CDataExchange* pDX);
private :
    CString m_strUsername;
    CString m_strPassword;
    BOOL    m_bRemember;
};

void CStudentDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_Text(pDX, IDC_EDITUSER, m_strUsername);
   DDX_Text(pDX, IDC_EDITPASSWORD, m_strPassword);
   DDX_Check(pDX, IDC_CHKREMEMBER, m_bRemember);

};

We set initial default values of data members in dialog constructor. MFC framework calls UpdateData(FALSE) before OnInitDialog handler. Framework's DDX mechanism transfers the values of the member variables to the controls in the dialog box using virtual function DoDataExchange(). The default implementation of OnInitDialog in CDialog calls the UpdateData member function of class CWnd to initialize the controls in the dialog box.

UpdateData and DoDataExchange

UpdateData works in both directions, text or BOOL data can be fetched from UI or can be applied to the UI. To carry out the exchange, UpdateData sets up a CDataExchange object and calls your dialog class's override of CDialog's DoDataExchange member function. DoDataExchange takes an argument of type CDataExchange. The CDataExchange object passed to UpdateData represents the context of the exchange, defining such information as the direction of the exchange. The purpose of UpdateData() function is to update member variable with the values from UI controls. This is done with an argument value of TRUE. However a FALSE parameter to this function inverses the flow and UI controls are updated with dialog member variables.

mfc dodataexchange updatedata true false

Code wizard can help users to add data exchange entries in DoDataExchange() function. User can specify member variable name graphically for each controls in the dialog. Code wizard automatically adds DDX functions for each member-control pair in DoDataExchange(). Each DDX function knows how to exchange data in both directions based on the context supplied by the CDataExchange argument passed to your DoDataExchange by UpdateData. MFC provides many DDX functions for different kinds of exchange. The following example shows a DoDataExchange override in which two DDX functions for TEXT BOX and CHECK BOX controls.

void CStudentDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_Text(pDX, IDC_EDITUSER, m_strUsername); /*Exchange for User name */
   DDX_Text(pDX, IDC_EDITPASSWORD, m_strPassword);  /*Exchange for Password */
   DDX_Check(pDX, IDC_CHKREMEMBER, m_bRemember); /*Exchange for remember */
}

DDX Functions

DDX_Text - Initializes or retrieves the current value of an edit control.

DDX_Check - Initializes or retrieves the current state of a check box control.

DDX_Radio - Initializes or retrieves the 0-based index of the radio control that is currently checked within a radio control group.

DDX_CBIndex - Initializes or retrieves the index of the current selection of a combo box control.

DDX_CBString - Initializes or retrieves the current contents of the edit field of a combo box control.

DDX_CBStringExact - Initializes or retrieves the current contents of the edit field of a combo box control.

DDX_Control - Subclasses a given control within a dialog box.

DDX_DateTimeCtrl - Initializes or retrieves date and/or time data of a date and time picker control.

DDX_IPAddress - Initializes or retrieves the current value of an IP address control.

DDX_LBIndex - Initializes or retrieves the index of the current selection of a list box control.

DDX_LBString - Initializes or retrieves the current selection within a list box control.

DDX_LBStringExact - Initializes or retrieves the current selection within a list box control.

DDX_ManagedControl - Creates a .NET control matching the control's resource ID.

DDX_MonthCalCtrl - Initializes or retrieves the current value of a month calendar control.

DDX_Scroll Initializes or retrieves the current position of a scroll control's thumb.

DDX_Slider Initializes or retrieves the current position of a slider control's thumb.

DDX_Text using raw Win32 API

Here we have written our own DDX routine and placed in DoDataExchange(). DDX_MyText() function is written with the help of Win32 APIs like GetWindowText(), GetWindowTextLength(), SetWindowText(). This is to show how DoDataExchange() and DDX routines can be written with Win32 APIs. However MFC implements DDX_Text() inside their framework with same logic and APIs as below.

void DDX_MyText(CDataExchange* pDX, int nIDC, CString& value)
{
  HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  /* Window to variable exchange */
  if (pDX->m_bSaveAndValidate)
  {
    int length;
    LPTSTR buffer;
    length = GetWindowTextLength(hWndCtrl);
    buffer = value.GetBufferSetLength(length + 1);
    GetWindowText(hWndCtrl, buffer, length+1);
  }
  /* Variable to Window/UI exchange */
  else
  {
    SetWindowText(hWndCtrl, (LPCTSTR)value);
  }
}
void CStudentDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_MyText(pDX, IDC_EDITUSER, m_strUsername);
   DDX_MyText(pDX, IDC_EDITPASSWORD, m_strPassword);
   DDX_Check(pDX, IDC_CHKREMEMBER, m_bRemember);

}

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#