For many applications, a dialog provides a sufficient user interface. The dialog window immediately appears when the user starts the application. The user can minimize the dialog window, and as long as the dialog is not system modal, the user can freely switch to other applications.
In this example, the dialog functions as a simple calculator, as shown in Figure 23-1. ClassWizard takes charge of defining the class data members and generating the DDX (Dialog Data Exchange) function callseverything but the coding of the compute function. The application's resource script, ex23a.rc, defines an icon as well as the dialog.
Figure 23-1. The EX23A Calculator dialog.
AppWizard gives you the option of generating a dialog-based application. Here are the steps for building the EX23A example:
In the next dialog, enter EX23A Calculator as the dialog title.
Open the Properties dialog box and click on the Styles tab. Select the System Menu and Minimize Box options.
Control | ID |
Left operand edit control | IDC_LEFT |
Right operand edit control | IDC_RIGHT |
Result edit control | IDC_RESULT |
First radio button (group property set) | IDC_OPERATION |
Compute pushbutton | IDC_COMPUTE |
Control ID | Member Variable | Type |
IDC_LEFT | m_dLeft | double |
IDC_RIGHT | m_dRight | double |
IDC_RESULT | m_dResult | double |
IDC_OPERATION | m_nOperation | int |
Add the message handler OnCompute for the IDC_COMPUTE button.
void CEx23aDlg::OnCompute() { UpdateData(TRUE); switch (m_nOperation) { case 0: // add m_Result = m_dLeft + m_dRight; break; case 1: // subtract m_dResult = m_dLeft - m_dRight; break; case 2: // multiply m_dResult = m_dLeft * m_dRight; break; case 3: // divide if (m_dRight != 0.0) { m_dResult = m_dLeft / m_dRight; } else { AfxMessageBox("Divide by zero"); m_dResult = 0.0; } break; default: TRACE("default; m_nOperation = %d\n", m_nOperation); } UpdateData(FALSE); }
The critical element of the EX23A application is the CEx23aApp::InitInstance function generated by AppWizard. A normal InitInstance function creates a main frame window and returns TRUE, allowing the program's message loop to run. The EX23A version constructs a modal dialog object, calls DoModal, and then returns FALSE. This means that the application exits after the user exits the dialog. The DoModal function lets the Windows dialog procedure get and dispatch messages, as it always does. Note that AppWizard does not generate a call to CWinApp::SetRegistryKey.
Here is the generated InitInstance code from ex23a.cpp:
BOOL CEx23aApp::InitInstance() { AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CEx23aDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we // exit the application, rather than start the application's // message pump. return FALSE; }
The generated CEx23aDlg class contains these two message map entries:
ON_WM_PAINT() ON_WM_QUERYDRAGICON()
The associated handler functions take care of displaying the application's icon when the user minimizes the program. This code applies only to Microsoft Windows NT version 3.51, in which the icon is displayed on the desktop. You don't need the three handlers for Windows 95, Windows 98, or Windows NT 4.0 because those versions of Windows display the program's icon directly on the taskbar.
There is some icon code that you do need. It's in the dialog's handler for WM_INITDIALOG, which is generated by AppWizard. Notice the two SetIcon calls in the OnInitDialog function code below. If you checked the About box option, AppWizard generates code to add an About box to the System menu. The variable m_hIcon is a data member of the dialog class that is initialized in the constructor.
BOOL CEx23aDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this // automatically when the application's main window // is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control }