MFC Dialog-Based Applications


Click here to change the theme.

This is a little tutorial about Microsoft Visual C++ MFC Dialog-based applications. This will hopefully be a good lesson for a beginner that might not yet have used Microsoft Visual C++ (VC) for anything. I have not completed this; sorry.

The Files

The AppWizard generates the following files, plus a file called ReadMe.txt. The ReadMe.txt file describes most of the the other files.

  • HelloDlg.h
  • HelloDlg.cpp
  • HelloDlg.rc
  • res\HelloDlg.ico
  • res\HelloDlg.rc2
  • HelloDlg.clw
  • HelloDlgDlg.h
  • HelloDlgDlg.cpp
  • StdAfx.h
  • StdAfx.cpp
  • Resource.h
  • HelloDlg.dsp
  • HelloDlg.dsw
  • HelloDlg.ncb

The last three files are not described in the ReadMe.txt file. The dsp file is the project file. The dsw is the workspace file. The ncb file is a temporary file that can be deleted when needed; VC will recreate it when it needs to.

The clw file is the ClassWizard file; it can be recreated by the ClassWizard when needed. Occasionally, the ClassWizard gets confused and when that happens, we often need to delete the ClassWizard file. That is not likely to happen before you learn much more about MFC and the ClassWizard, so I won't explain that any further here.

The Classes and Member Functions

The classes generated for the project are:

  • CHelloDlgApp derived from CWinApp
  • CHelloDlgDlg derived from CDialog
  • CAboutDlg derived from CDialog (not generated if About box was not selected in step 2 of the AppWizard)

The following lists the classes and describes the member functions that the AppWizard generates for the application.

CHelloDlgApp

For the application class, the AppWizard generates only a constructor and an override of the InitInstance function. It is the InitInstance function that does most everything in a MFC Dialog-based application. Normally when the InitInstance function in a MFC Dialog-based application returns the application ends. This is different for most other types of applications. The name InitInstance is misleading since it implies that it only initializes the application. The reason for calling it InitInstance is the result of Windows programs in general. In order to fully understand the reason and such it would help to understand Windows programming much more than would be appropriate for now. So for now all you need to know is that the InitInstance function is where the main processing for the application exists.

The most important portions of the InitInstance function are:

CHelloDlgDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();

The first line above defines an instance of the dialog (CHelloDlgDlg) object. The second line stores a pointer to the dialog in a member variable (m_pMainWnd) of the application. The third line executes the DoModal function of the dialog object, which shows the dialog. In the lines that follow the three lines above, the AppWizard generates lines for checking which button was clicked to end the dialog. You can add code to do things depending on which button was clicked to end the dialog.

The m_pMainWnd variable is quite important to MFC. In applications that are not dialog-based m_pMainWnd stores a pointer to the main window and requires that it be set to the main window. It is not that important in dialog-based applications.

CHelloDlgDlg

For the main dialog class of a dialog-based application, the AppWizard generates the following:

  • a constructor
  • DoDataExchange
  • OnInitDialog
  • OnSysCommand
  • OnPaint
  • OnQueryDragIcon

For beginners, it is usually not necessary to modify the constructor and the OnSysCommand, OnPaint and OnQueryDragIcon functions. Also the DoDataExchange function will be modified by the ClassWizard and as a beginner it is best to use the ClassWizard to do that.

The only function you need to be concerned with in the beginning is the OnInitDialog function. This is where you will add code to initialize the dialog when needed.

CAboutDlg

The CAboutDlg is the About dialog, of course. It also has a constructor and a DoDataExchange function. For now, you don't need to modify them either. Note that the About dialog is not generated if the About checkbox was not selected (checked) in step 2 of the AppWizard.

The Dialog and the Resource Editor

Probably the first thing you will want to modify is the dialog. At the left of Visual Studio you should see the tabs shown at that bottom of the image to the left of here. The tabs are for the three views ClassView, ResourceView and FileView. Click on the ResourceView tab and expand the "Dialog" branch so you see the dialogs as shown on the left. The IDD_ABOUTBOX dialog will not be there if there is not an About dialog.

Double-click on IDD_HELLODLG_DIALOG to edit the program's dialog. There should be a Controls Toolbar very similar to the one shown on the right here.

Some Notes

The following is more material I need to rewrite for here.

Normally, for a regular (non-dialog based) application, the InitInstance function is called by MFC to initialize the application and the ExitInstance function is called by MFC to clean up whatever is done in the application. Usually, I would prefer to clean up in ExitInstance only what has been done in the InitInstance, but ExitInstance is a good place to do other cleanup also.

For dialog-based applications, usually the entire application is done in the InitInstance function. I don't know how much you know about Windows, so I won't try to explain about why it is that everything is done in the InitInstance function, but it is.

So what you can do is to do initialization in your InitInstance, then do the dialog using DoModal, then do whatever cleanup is needed after the DoModal but still in InitInstance.

There is usually some initialization of the dialog done in the dialog's OnInitDialog. Then any corresponding cleanup would usually be done in the OnOk and/or OnCancel overrides. If the user presses the Ok button, then the data from the dialog should be processed as expected. If the Cancel button is pressed, then the OnCancel function could do whatever cleanup is needed, but it normally would ignore whatever is in the dialog; the user would expect the data to not be used.

After the dialog returns, you can check the return code of the DoModal to determine if it is IDOK (the user pressed Ok) or IDCANCEL (the user pressed Cancel). You can do something in the InitInstance if the return code is IDOK. So you have multiple places to put processing of the dialog data, depending on what you need to do where.

I have not completed this article; sorry.