Data exchange in user interface
In C/C++ programming, we hold data in a variable and they are processed in the program. The output of the variable to the user is generally done through printf() which basically converts data type to a string and then displays it in the text console. The input from the user is taken from the console using scanf() function. These two functions primarily act as the data exchange routine in console-based C applications.
Graphical user interface-based programmings like Win32 programming using C and MFC programming with C++, cannot use the console for user interaction. So we use a graphical dialog box or form window for the interactions and exchanges. Programming variables types like a string, integer, boolean etc are exchanged to the graphical user interface for display purposes. Again when we require to take input from the user, we display dialogs, and the input is given to the user interfaces and then exchanged to the variables. This mechanism is called dialog data exchange in Win32/MFC programming practices.
Win32 Dialog Data Exchange
A dialog window is a top-level window and dialog UI controls like button, editbox, checkbox, combobox, radio buttons, list box are child windows. These child controls are identified by an control identification number or control ID.
Win32 Dialog Data Exchange
There are Win32 API to retrieve values from the UI controls. These APIs have a common format of arguments and the dialog window handle is the first argument and then the control ID. Each UI controls holds different types of information in it thus the exchange of data should be in different types of variables. Users can retrieve strings, integers, BOOL etc using these calls.
The below Win32 APIs are used to apply text or set the state of the button from a variable. Here are few examples of APIs for UI controls like editbox, checkbox, radio buttons however there is a collection of APIs available for other UI controls.
MFC Dialog Data Exchange
MFC applications can use these same APIs wrapped in CWnd class. These APIs often require additional parameters to exchange a single value. Calling Win32 C API or using the same APIs through CWnd class members in C++ does not make sense. MFC framework however has a managed way to exchange data and that is known as Dialog Data Exchange (DDX) in MFC framework. MFC data exchange is not an independent way however above Win32 APIs are used internally to construct these MFC data exchange macros. Let us see how to exchange data in dialog boxes and how DDX functions works in DoDataExchange.
Here is one login dialog example in a generic user-based application. This dialog has three UI elements to collect username, password, and a field to remember in future options. We have two textboxes IDC_EDITUSER and IDC_EDITPASSWORD and one checkbox IDC_CHKREMEMBER. We have taken two CString type variables 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 checkboxes. We implement dialog DoDataExchange() and place data exchange macros (DDX_Text, DDX_Check) inside this function.
We use UpdateData() function to invoke data exchange in the dialog. UpdateData() function calls DoDataExchange() abstract function and the parameter tells the direction of the data i.e. whether to update member data from UI (with TRUE) or update UI with member data(with FALSE). We need to call UpdateData(FALSE) when we want to update UI fields and call UpdateData(TRUE) when we want to update member variables from UI.
UpdateData data flow direction
Now we know how to write a data exchange routine with DDX macros placed inside and how to call updatedata function. Let us understand how these functions work and how these functions are implemented. These will help us to understand the mechanism and this will give more insight into the framework.
UpdateData() function calls DoDataExchange() abstract function and the parameter tells the direction of the data exchange. To carry out the exchange, UpdateData sets up a CDataExchange object. It constructs the object with dialog window and the bSaveAndValidate variable from UpdateData() function. It then calls dialog class's override of CDialog's DoDataExchange member function passing the reference of the CDataExchange object as the argument. 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 variables 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. DoDataExchange should have data exchange macro or functions and they do the actual exchange.
Dialog Data Exchange(DDX) function or macros are used in DoDataExchange() routine to carry out the exchange. These functions start with a DDX_ prefix and a suffix of XXX which is the type of control it uses for the exchange. They take an object reference of CDataExchange as the first parameter and the control ID as the second parameter. The suffix part and the datatype of the next parameter depend on the type of UI control it deals with. It can be a string for text control and boolean for check box and so on.
The name of these functions are self-explanatory and they are DDX_Text, DDX_Check, DDX_Radio, DDX_CBIndex, DDX_CBString, DDX_CBStringExact, DDX_Control, DDX_DateTimeCtrl, DDX_IPAddress, DDX_LBIndex, DDX_LBString, DDX_LBStringExact, DDX_ManagedControl, DDX_MonthCalCtrl, DDX_Scroll, DDX_Slider.
Implement DDX_Text using Win32 API
DDX_XXX functions are the key routines to do the data exchange. Here we have written our DDX routine and placed it in DoDataExchange(). This is to show how DDX routines can be written with Win32 APIs and this also gives an idea of how MFC framework implements these DDX functions. Our DDX_MyText() function is written with the help of Win32 APIs like GetWindowText(), GetWindowTextLength(), SetWindowText(). The actual implementation of DDX_Text() in MFC framework might be different but similar logic and APIs are used.
DDX class wizard
MFC dialog class wizard can help users to add data exchange entries in DoDataExchange() function. This wizard can be opened by right click on the dialog resource.
"Add Class" button helps to add the dialog class associated with the dialog. Dialog class is generally derived from CDialog. "Add Variable" button helps to open the data exchange variable wizard.
Users can specify member variable names graphically for each control in the dialog. Class wizard automatically adds DDX functions for each member-control pair in DoDataExchange().
Here is what the class wizard dialog looks like after we fill all the variables for individual controls. The left side shows the control IDs of the dialog and the right side shows the member variables. This in short shows a summary of control IDs vs member variables side by side.
About our authors: Team EQA
MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.
This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...
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.
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.
LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.
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 ...
Learn on Youtube