MFC provides protocols for many standard commands and full implementations for some of them. For example, most of the File Open command is implemented for you. In response to File Open, the MFC framework displays the File Open dialog box, retrieves the selected filename, creates a document object and its associated view and frame window objects, opens the disk file, and tells the document to read the file in. All you have to write is a small amount of document-class code to specify what to read. Correspondingly, MFC documents respond to the Save and Save As commands. All you have to write is the code to write data to a file that the framework opens and closes for you.
Figure 10 and Figure 11 outline the File Open and File Save command sequences, which use file serialization.
MFC's default implementation of these commands is called "document serialization." MFC calls a document object's Serialize member function to read or to write the document's data serially to or from a disk file. To make serialization really useful in an object-oriented environment, MFC makes it easy to store not only built-in C++ data types but also objects, including many of those derived from class CObject. Using this default "object persistence" mechanism, you can read and write the contents of objects, storing them on disk to be read back in later and reconstituted to their former states.
For example, suppose your document contains an array of CPerson objects, where each object contains a set of information about one person: CString objects containing the person's name and address, a CTime object containing date of birth, and perhaps a CPhone object, a WORD storing a social security number, and so on. Your program lets the user create several new person objects, storing them in the array.
When the user chooses the File Save command, MFC calls your document's Serialize member function, as shown in Figure 11. Serialize is passed a pointer to a CArchive object, which encapsulates a pointer to a CFile object already set to the right filename and already opened on disk. Within Serialize, you iterate through the person list, calling CPerson::Serialize for each person in the list. That function, in turn, passes the CPerson object's data to the CArchive, much as variables are passed to the Dump function described earlier. The CPerson object passes its name, address, and other information one by one to the archive, which causes them to be written to the file. A similar process occurs when you read the data back in.
On disk, a serialized object consists of a sequence of data items: some "header" information to identify the type of data, then the data itself. When your program "deserializes" an object, it determines its type, dynamically constructs an empty object of the correct type, and tells the object to read in its own data.
To do your simple part of this complex dance, move your data structures into the document class and then override Serialize in your document class (actually, AppWizard writes the empty shell of this override for you). Here's a simple example of a CPerson::Serialize member function that the document's Serialize function can call:
void CPerson::Serialize(CArchive& ar) { if (ar.IsStoring()) { // insert objects in the archive ar << m_strName; ar << m_wAge; ar << m_wSSN; } else { // extract objects from the archive ar >> m_strName; ar >> m_wAge; ar >> m_wSSN; } }
You write the lines within the if and else blocks. Store data in the archive using the CArchive insertion operator (<<), which is overloaded for most common built-in and MFC data types. Load data with the extraction operator (>>). Notice that you store and load data items in the same order.
If serialization doesn't suit your needs, you can override various member functions of the document class or the application class to implement something else.
For example, SHOWDIB already has file-handling code, so you might incorporate it into an overridden version of the serialization mechanism to take advantage of MFC's existing File Open and Save implementations while still using parts of SHOWDIB's existing code. One approach is to override CDocument::OnOpenDocument and remove the code that creates an archive and calls Serialize, replacing it with SHOWDIB's I/O code.