Visual C++ / MFC - Common Guidelines
In developing MFC programs, you will find yourself repeatedly doing the
same type of similar programming that you did in SDK programming (responding
to messages in a switch statement). This document will attempt to describe
the basic steps you do to implement an MFC program.
CDocument
The document class that AppWizard
created for you is derived from the CDocument class (in SDI and
MDI projects). This is the class where data is stored during runtime and
it's primary task (that you must implement) is the saving and loading of
that data to and from a disk file.
The CDocument (all CObject-derived classes, actually) have a Serialize
function that is called by MFC to load and save a disk file. The Serialize
function has the following basic format (as created by AppWizard):
void CAppNameDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
The if test inside the function determines if you are being asked
to save or load the data for the document. MFC will have already handled
the File Open and Save menu choices, and opened the
file by the time this function is called. The ar parameter represents
the open file and is very similar to an ifstream object (you can use <<,
>>, Read, and Write to store or load data).
The CArchive class provide a set of << and >> operators for
fundamental data types, as well as many of the other MFC classes such as
CString and CPoint, and even the collection classes like CObArray and CArray.
In addition, since most of the collection classes also provide a Serialize
routine, you can also those serialize routines, for those classes. The
following are example is a Serialize routine for a CPoint object,
called Point, that's a data member of the document class:
void CAppNameDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << Point;
}
else
{
ar >> Point;
}
}
The View Classes
The View classes represent the user
interface to the document. There are two basic types of views you will
be using: CView which is a view without controls, similar to SDK programming,
and CFormView which is a view that is easy to place child controls on.
The CView is the default view, but can be changed in the last dialog of
AppWizard.
Data output (Drawing)
Your primary purpose in the view
is to display data from the document to the user, and get user changes
(in the form of events). These changes are given to the document. If you
have a CView class, then you will be working with the OnDraw function
of the view class:
void CAppNameView::OnDraw(CDC* pDC)
{
CHwDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
The CDC object is a 'wrapper' for the Windows HDC device context item.
As a class, it has all the functions that work with a device context. For
example, in the above code, you can do the following:
pDC->TextOut( 0, 0, "Hello World", 10 );
The first two lines of code in the function above, get a pointer to the
document associated with the view. This pointer (pDoc) provides you with
access to your document object to get data from for drawing. Your drawing
code should appear after these two lines of code.
The OnDraw function is automatically called by MFC in response to
a WM_PAINT message.
Data Input (User interaction)
In order to process user events,
you add Message Maps using ClassWizard (the Message Maps
tab). ClassWizard can be accessed from the View menu choice. In ClassWizard,
you select the type of object from the Object IDs list, and the
type of message from the Messages list. For Object IDs:
· Select the name of the view class to handle general window's messages,
and special MFC functions (such as OnDraw).
· Select the ID of the menu item or control (if it's a CFormView
view, and you added a control to the form for the view) to handle menu
choices and control notifications.
Once you've selected the desired ID/Class, select the message you want
to map. For menu items and controls, you will see a COMMAND choice, which
means a WM_COMMAND message, or that the user has clicked that control (other
controls like an edit box have more messages). Once you've selected the
desired message, click the Add Function button.
MFC will then add a function to your view class definition and your .cpp
file, and call that function when the previously selected message is sent
to the selected object ID.
Helpful MFC classes
The following classes are basic helpful
classes when writing MFC Windows programs:
Class |
Description |
Serialize() |
CObject |
Base class for most classes, helpful for
collection classes and framework |
Y |
CPoint |
Point management |
<< and >> |
CRect |
Rectangle management |
<< and >> |
CString |
String management |
<< and >> |
CTime |
Date and time management |
<< and >> |
CFile |
File management |
N |
CArchive |
File management, similar to CFile, but supports
other objects |
N |
CStringArray |
Collection of strings |
Y |
CObArray |
Collection of Cobjects pointers, or CObject-derived
pointers |
Y |
CPtrArray |
Collection of pointers |
N |
CDC |
Wrapper class for Device Context |
N |
CDatabase |
A connection to a database (collection of
data files) |
N |
CRecordset |
A query or table in a database. Works with
a CDatabase |
N |
The Array classes above also have matching List and Map
collection classes. While they are all collection classes, they differ
in the following way:
· Arrays are implemented internally as an array, and are slower
to insert than a list or map, searching speed is slower than a map and
similar to list. Elements are accessed by an integer index.
· Lists are implemented internally as a linked list, and are fast
to insert. Searching is slower than a map, and similar to an array. Elements
are accessed sequentially.
· Maps are implemented as a look up table, and are fast to both
insert and sort. Elements are accessed via a key value.
There are also template versions of the array, list, and map classes called
CArray, CList, and CMap.