Windows NT Systems Programming: Spring 1999
[ Home | Syllabus | Course Notes | Assignments | Search]
Why are Modal Dialog Boxes
easier to program than modeless?
Version 4
Here is a quick sketch of the objects and their relationships
in version 4.
NOTE: there are some bad
design decisions and obsolete code/objects in the current solution. Can you find them?
In an event driven
system used in GUI programming, it is helpful to define the state of the entire
application at points in between user generated events.
It is also helpful to
trace the communications paths between the objects which set up these intermediate stable
state values.
CMsgFolderApp
CMsgFolder
CMessage
m_pMainWnd ---> CMainWindow

- FV1: What is this used for?
- FV2: This comes from the resource compiler which comes from the visual
editing tool.
- FV3: How is this message handler mapped to menu item?
- FV4: What is the result of using this dialog box? How does it
communicate its results?
- FV5: What is the purpose of this data member?
- FV6: What is the purpose of this data member? Who sets it? Who uses
it?
- FV7: Why is this a poitner? What does it point to?
Define Major Stable States of the Application (what is transient and what
is stable?):
- Initial State: no open folder
- Folder Selection View
- Folder Selected and Opened
- Message Selection View
- Message Edit View
Define the Major Events by the User which change these states:
- Open Folder (from main menu)
- Close Folder (from main menu)
- Select Folder (from dialog box)
- Open Message Selection (from main menu)
- Select Message (create if new) (from dialog box)
- Edit Message (from dialog box)
- Close Message (from dialog box)
Some Steps in converting home grown dialogs for message folders
to one using CDialog
Also used the visual editing tool for menus and dialog boxes.
Creating Project
- Open VC++
- Select New to get open project dialog
- select win32
- name it
- choose directory
- OK
- Add files from home grown version (make copies)
- change setting to use shared MFC DLLs
Building the Menu using resource editor
- Insert/Resource to get dialog box
- choose menu
- click to add menu items
- double click to change properties such as ID (if you want)
- save resource script
- add this file to your project
Building a Dialog Box
- Insert/Resource
- Select plain (top level) dialog
- build it using visual editing tools
NOTE: you get OK and Cancel for free.
Connecting CDialog
- New/Header named CFolderDlg
- Derive a new class from CDialog
// FolderDlg.h: interface for the CFolderDlg class.
//
//////////////////////////////////////////////////////////////////////
#ifndef H_FOLDERDLG
#define H_FOLDERDLG
#include <afxwin.h>
#include "resource.h"
class CFolderDlg : public CDialog
{
public:
CFolderDlg(CWnd* pParentWnd = NULL) :
CDialog(IDD_FOLDER
, pParentWnd) { }
virtual BOOL OnInitDialog();
CString m_folderName;
protected:
virtual void OnOK();
afx_msg void OnFolderSelection();
afx_msg void OnFolderDblClk();
DECLARE_MESSAGE_MAP() // set up message map handling
};
#endif

- F1: The default parameter of NULL means to associate this dialog with
the main application window.
- F2: Resource ID assigned when Dialog Resource was created. The default
name is something like "IDD_DIALOG1" but I changed it to "IDD_FOLDER".
Notice the use of the constructor initializer which calls the base classes non-default
constructor. The base class uses the resource ID to load the dialog box object generated
by the resource compiler from the resource script created by the visual editing tool.
"Building in" the resrouce ID into the constructor is safer than letting the
creater of an object pass it as a parameter. WHY?
- F3: WM_CREATE message for Dialog Boxes must create all the controls
contained in the box from information provided by the resource. Since this is provided in
the base class, you don't have to worry about creating all the internal controls. However,
if you want to customize these controls (e.g. by loading a list into a listbox), then you
can overload OnInitDialog - which is the message handler for the WM_INITDIALOG message
sent by the handler that handles the WM_CREATE message. Why is this
a virtual function?
- F4: What is the purpose of this data member?
- F5: Usually the OK button closes the dialog box
and takes an action, the Cancel button closes and takes not action (and usually you use
the base classes OnCancel message handler for this purpose. They affect the return value
of DoModal (see below).
- F6: How is this handler associate with dialog box
control?
Implementation
// FolderDlg.cpp: implementation of the CFolderDlg class.
//
//////////////////////////////////////////////////////////////////////
#include "FolderDlg.h"
#include "main.h"
extern CMsgFolderApp msgFolderApp;
// Message map - maps message IDs to their handlers
BEGIN_MESSAGE_MAP( CFolderDlg, CDialog )
ON_LBN_SELCHANGE(IDC_FOLDER_LIST,OnFolderSelection)
ON_LBN_DBLCLK(IDC_FOLDER_LIST,OnFolderDblClk)
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BOOL CFolderDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// build list of message folders in current directory
HANDLE folder;
WIN32_FIND_DATA findData;
folder = FindFirstFile("*", &findData);
while( folder != INVALID_HANDLE_VALUE) {
if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// assume all directories are folders
((CListBox*)GetDlgItem(IDC_FOLDER_LIST))->AddString(findData.cFileName); // Parse this
}
if(!FindNextFile(folder, &findData))
break;
}
FindClose(folder);
return TRUE;
}
void CFolderDlg::OnOK()
{
((CEdit*)GetDlgItem(IDC_SELECTION))->GetWindowText(m_folderName);
if(msgFolderApp.msgFolder.OpenMsgFolder(m_folderName)) // Parse this - where are these?
CDialog::OnOK(); // clean up and return successfully
else {
MessageBox("Message Folder Corrupted!\n Try another folder", "ERROR");
}
}
void CFolderDlg::OnFolderSelection()
{
CString selection;
int nIndex = ((CListBox*)GetDlgItem(IDC_FOLDER_LIST))->GetCurSel();
if (nIndex != LB_ERR) {
((CListBox*)GetDlgItem(IDC_FOLDER_LIST))->GetText(nIndex,selection);
((CEdit*)GetDlgItem(IDC_SELECTION))->SetWindowText(selection);
}
}
void CFolderDlg::OnFolderDblClk()
{
OnFolderSelection( );
// because this does both selection and opening
OnOK( );
}

- F7: Call the base class for data exchange and validation needed in some
applications (we don't need - but it doesn't hurt)
- F8: True means assign focus to first control in tab order (set in the
visual tool)
- F9: Here is the prototype "CWnd* GetDlgItem( int nID )
const;", cast this pointer into the proper derived class type.
- F10: where is this?
- F11: This call to base class will call "EndDialog" which
will return control from the DoModal function.
- F12: What would happen if OnFolderSelection failed (got LB_ERR)?
The (almost) Final Version 4
Project is here.
Solution consists of:
- 16 files
- 9 Classes
- 5 resources
- 1 menu
- 3 dialogs
- Selecting Folder
- Selecting Message in folder
- Editing Message
- 1 accelerator
in CMsgFolder class:
- Changed name of "PostMsg" function to
"NewMsg"
- Added "UpdateMsg" function which replaces an existing
message with an edited version.
Program Flow
- Using main menu, select Open Folder Dialog
- Pick an existing or new folder name
- This calls OpenMsgFolder function of CMsgFolder on public member
of main application object.
(so message folder has global visibility -
- what else if global visible?
- can you access members of CMainWindow globally?
- how?
- This is the communications between this dialog and the
application (and is reflected in the title bar)
- Using main menu, select Edit Message (dialog)
- User can select by topic or by NEW button.
- New button calls OnOK (to get proper return from DoModal dialog
- passes MsgId (position in list) back to calling program in public data
member of dialog class
- Creates message object, if not new, initialzes from file.
- Calls Message Edit object, passing pointer to message in public data member
of edit dialog object.
- After editing, calls appropriate CMsgFolder function to store in folder.
Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr.
Wild].
Last updated: February 22, 1999.