[Home]
[Contents]
[Prev]
[Next]
11. Lesson 2: Generate an Application Framework
In this chapter you begin the process of building a Windows version
of the TML Reader. This version is built around a Microsoft
Foundation Class (MFC) version 2.5 Single Document Interface (SDI)
framework. In this lesson you:
- Use AppExpress to generate a new project containing the
SDI framework
- Build and run the bare application framework, a
standardized skeleton composed of C++ classes derived
from MFC library base classes.
- Use precompiled headers to speed build time
- Add calls to the TRACE macro with Class Editor
- Follow TRACE output in the Trace Messages window
At the end of the lesson you will have a working application
framework with menus, a toolbar, and a status bar. The framework
itself will respond to certain commands, but the functionality needed
to read and display TML files is not yet included. In subsequent
chapters you modify the user interface for the TML Reader and add
the necessary file input and display routines.
There are many ways to create an application framework. This
lesson provides the most straightforward way.
Generating the Framework
In this lesson you use AppExpress to generate a new project
containing an application framework. To start AppExpress:
- Start the IDDE and close any open project by choosing
Close from the Project menu.
- Start AppExpress by choosing AppExpress from the
Tools menu.
The AppExpress window opens (shown in Figure 11-1).
[Figure 11-1 Setting up an SDI application with AppExpress]
AppExpress contains six pages of options that together define the
project to be generated. You define these options in six steps, listed
in the upper-left portion of the window. For this project, you need to
change options on only four of the six pages. Set up the project
options as follows:
- On the Application Type page (shown when AppExpress
is started), select SDI.
- Deselect Include Help to suppress generation of
Windows Help support.
- Click on Next to switch to the Select Directory page.
Change to the samples\tutorial\lesson2
directory under the directory in which you installed
Digital Mars C++, then click on Create New Directory.
- Type start in the textbox and click Create.
Note:
To avoid filename conflicts, it is a good idea to keep
each project you create in a separate directory.
- Click on Next to switch to the Miscellaneous page. Type
your company name and suffix (or your own name) in
the appropriate textboxes. This information is displayed
in the automatically generated About dialog box, and in
comments at the beginning of each source file.
- In the Project Name textbox, type TMLRead.
- Click on Next to switch to the Names page. You can
customize the names of automatically generated classes
here. From the Name drop-down list, select
CTMLReadApp. In the Edit textbox, type CTMLReadApp.
- Click Finish.
AppExpress generates a new project in the directory you created.
The directory contains:
- Source and header files for the MFC-derived classes
- Resource script and binary files
- Project options and other support files
After generating the project, AppExpress closes and control returns
to the IDDE. The new project is loaded automatically. The IDDE
parses the new project's source files for browsing with the Class and
Hierarchy Editors; parsing progress is displayed in the Output
window.
Building and Running the New Project
Next you build the project and learn what the default application
framework can do.
- From the IDDE's Project menu, choose Rebuild All.
- From the Project menu, choose Execute Program.
The IDDE minimizes itself and the TMLRead application opens
(shown in Figure 11-2).
[Figure 11-2 New application framework generated by AppExpress]
At present, default functionality for several menu commands is
provided by the MFC base classes. For example, if you choose Open
from the File menu, a standard Windows File Open dialog box
opens. You can select a file in this dialog box, but the code needed
to read data from the file is not yet installed.
To close TMLRead and return to the IDDE, choose Exit from the
File menu.
The project can take a considerable amount of time to compile. Next
you learn how to decrease compilation time by using precompiled
headers.
Using Precompiled Headers
In the last section, over 70,000 lines of code were read during
compilation. Many of these lines are in Windows and MFC header
files that are changed infrequently (if ever), but still must be included
by almost every source file. To speed compilation, you can
precompile header files; thereafter, the symbols generated by the
compiler can be loaded directly.
To precompile the Windows and MFC header files:
- Choose Settings from the Project menu. The Project
Settings dialog box opens.
- Click on the Build tab.
- In the left listbox, click on Header Files.
- In the Precompile section of the right pane, select
Specific Header.
- In the textbox below the Specific Header selection, type
stdafx.h.
Note:
You can specify multiple specific headers to
precompile by entering in this textbox a list of their
names separated by semicolons or spaces.
[Figure 11-3 Using precompiled headers]
- Click OK.
- An Editor/Browser message box is opens, noting that
project settings have changed and asking if you want to
reparse all files. Click No, because you are about to build
in the next step, which will stop any parse in progress.
- From the IDDE Project menu, choose Rebuild All.
During the rebuild, the header file stdafx.h is precompiled, then
the source files are compiled using the precompiled symbol table.
You should notice a significant reduction in the number of lines
compiled, as well as a corresponding increase in compile speed.
Now that you have created, compiled, and executed the application
framework, the rest of the chapter helps you to understand the
framework's structure. The following three sections are optional.
Adding TRACE Calls with Class Editor
In the remainder of this chapter, you investigate calls to member
functions of the MFC-derived classes created by AppExpress to
understand the structure of the application framework and the
relationships between the classes. To do this, you use the Class
Editor to insert calls to the MFC global TRACE macro into the
member functions, then watch the output in the Trace Messages
window.
To add a TRACE call to the application class's constructor:
- Choose Class Editor from the Goto View submenu of
the IDDE Window menu. The Class Editor window
opens (see Figure 11-4).
- Under Classes, click on CTMLReadApp. The application
class's members appear in the Members list.
- Under Members, double-click on CTMLReadApp. The
application class constructor's source code is shown in
the source pane.
- Add the following line to the constructor:
TRACE("CTMLReadApp::CTMLReadApp()\n");
The constructor should now appear as follows:
//////////////////////////////////////////////////////////////////
// CTMLReadApp construction
CTMLReadApp:: CTMLReadApp()
{
TRACE("CTMLReadApp::CTMLReadApp()\n");
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
- Press Ctrl+S to save the modified constructor.
[Figure 11-4 Adding TRACE calls with Class Editor]
You can add similar TRACE calls to these other member functions:
- CTMLReadApp::InitInstance()
- CMainFrame::CMainFrame()
- CMainFrame::~CMainFrame()
- CMainFrame::OnCreate()
- CTMLReadDoc::CTMLReadDoc()
- CTMLReadDoc::~CTMLReadDoc()
- CTMLReadDoc::OnNewDocument()
- CTMLReadDoc::Serialize()
- CTMLReadView::CTMLReadView()
- CTMLReadView::~CTMLReadView()
- CTMLReadView::OnDraw()
When you have finished, choose Build from the IDDE Project
menu to recompile the source files you have changed.
In the next section you execute the application and watch the
TRACE output in the Trace Messages window.
Watching TRACE Output in the Trace Messages Window
To watch TRACE output, first you must set up the Trace Messages
window to receive and display TRACE messages.
- Choose Trace Messages from the Goto View submenu
of the IDDE's Window menu. The Trace Messages
window opens.
- Choose Output to Window from the Options menu of
the Trace Messages window.
- Choose MFC Debug Messages from the Options menu.
The MFC Trace Debug Options dialog box opens.
- Check Enable Tracing and uncheck any other options
that are checked. Click OK.
You are now prepared to run the application and view the output of
the TRACE macro calls.
- Choose Execute Program from the IDDE's Project
menu.
- The IDDE is minimized and the application window
opens. Double-click on the IDDE icon to reopen the
IDDE windows. Position the windows so you can watch
the Trace Messages window while the program executes.
The Trace Messages window has already received several messages
from the application's class constructors and initialization code
(Figure 11-5). You see more messages if you choose Open or New
from TMLRead's File menu, or when the window needs to be
repainted.
When you close TMLRead, the Trace Messages window receives
messages from the application's class destructors.
[Figure 11-5 TRACE output in the Trace Messages window]
The next section gives an overview of the classes in the application
framework and explains the messages you see in the Trace Messages
window.
The Application Framework and MFC Classes
In this chapter, you have used AppExpress to build an application
framework, a skeleton on which you can build a Windows
application, consisting of C++ classes contained in and derived from
classes in the Microsoft Foundation Class (MFC) library.
The MFC library is a C++ class library that supports programming for
Windows. It encapsulates most of the Windows Application
Programming Interface (API), and provides additional C++
programming support such as container and string classes. The MFC
library makes it easy to work with Windows elements in an object-oriented
manner. For example, MFC library classes exist to represent
objects such as windows, dialog boxes, controls, device contexts,
Graphic Device Interface (GDI) objects, and so on. Windows API
functions are implemented as member functions of the classes with
which they are logically associated.
TMLRead is built on a Single Document Interface (SDI) framework.
The SDI framework contains five fundamental objects:
- Document:
- The document contains data, reads the data
from disk, and provides access to the data. In TMLRead,
the document is an object of type CTMLReadDoc,
derived from the MFC library class CDocument.
- View:
- The view displays the data contained by the
document. In TMLRead, the view is an object of type
CTMLReadView, derived from the MFC library class
CView (which is, in turn, derived from CWnd, the base
class for all types of windows).
- Document Template:
- The document template defines the
association between document and view classes. In an
SDI application, this is an object of type
CSingleDocTemplate.
- Frame Window:
- The frame window object is the
application's main window. In TMLRead it contains a
toolbar, a status bar, and the view. The frame window is
an object of type CMainFrame, derived from the MFC
library class CFrameWnd.
- Application:
- The application object creates and controls
the other objects, and takes care of general program
initialization and cleanup. In TMLRead the application is
an object of type CTMLReadApp, derived from the MFC
library class CApplication.
The framework itself provides standard user-interface
implementations for some commands (for example, file open and
save); you must add support for certain framework functions (such
as file input and output), as well as add other command and
message-handling capability specific to your application.
The TRACE output from the previous section lets you see the
creation, use, and destruction of objects in the application. For
example, when you start the application, you see the following
messages:
[00001] NOTIFY(StartTask)
[00002] CTMLReadApp::CTMLReadApp()
[00003] CTMLReadApp::InitInstance()
[00004] CTMLReadDoc::CTMLReadDoc()
[00005] CMainFrame::CMainFrame()
[00006] CMainFrame::OnCreate()
[00007] CTMLReadView::CTMLReadView()
[00008] CTMLReadDoc::OnNewDocument()
[00009] CTMLReadView::OnDraw()
The application object is created first. Using a document template,
the application object creates the document, frame window, and
view objects. It then calls the document object to set up a new
document. Finally, when the window is shown, the framework calls
the view's OnDraw() function to repaint the window.
If you choose New from TMLRead's File menu, you see the
following messages:
[00010] CTMLReadDoc::OnNewDocument()
[00011] CTMLReadView::OnDraw()
Or, if you choose Open from the File menu, then select a file, you
see:
[00012] CTMLReadDoc::Serialize()
[00013] CTMLReadView::OnDraw()
The document object is called either to create a new document or to
read a document from a file, depending on the menu item that was
chosen. Note that neither the document object nor the view object is
destroyed; in an SDI application, they are reused continually.
When you choose Exit from TMLRead's File menu, the application's
objects are destroyed in reverse order in which they were created.
You see these messages in the Trace Messages window:
[00014] CTMLReadView::~CTMLReadView()
[00015] CMainFrame::~CMainFrame()
[00016] CTMLReadDoc::~CTMLReadDoc()
[00017] NOTIFY(ExitTask)
[00018] NOTIFY(DelModule)
There is no message from the application object's destructor,
because it is not defined explicitly in the framework.
You may find it useful to continue to add TRACE calls to the
application as it is built. It is often difficult to follow the workings of
a message-driven system; the Trace Messages window, however, acts
as a kind of passive debugger that keeps you informed of the
internal workings of your application.
In the next chapter, you begin to shape the application framework to
the specific needs of the application. The first step in this process is
to customize the user interface with the Resource Editor.