490 likes | 625 Views
Chapter 16. Reading and Writing Documents—SDI Applications. Serialization. Use in the world of object-oriented programming Persistent objects, Saving the object to disk Saving and restoring objects is called serialization. Microsoft Foundation Class (MFC) library.
E N D
Chapter 16 Reading and Writing Documents—SDI Applications
Serialization • Use in the world of object-oriented programming • Persistent objects, Saving the object to disk • Saving and restoring objects is called serialization
Microsoft Foundation Class (MFC) library • Designated classes have a member function named Serialize • All the objects associated with a document are sequentially read from or written to a single disk file. • No random access
Disk Files CFile • In MFC the CFile object Represents disk files • Not a buffered I/O stream like fopen • It is a handle to a binary file • The application framework uses the file handles: • ReadFile, WriteFile, and SetFilePointer .
Disk Files • If you do no direct disk I/O in the application you can depend on the Serialize function to store your document objects.
Archive Object • Between the Serialize function and the CFile object is an archive object (of class CArchive)
Archives • The CArchive object buffers data for the CFile object • it maintains an internal flag that indicates whether the archive is storing(writing) or loading(reading) from the disk.
Making a Class Serializable • Serializable class is derived from Cobject • Class declaration must contain the DECLARE_SERIAL macro • Class implementation file must contain IMPLEMENT_SERIAL macro
Writing a Serialize Function • You must write the Serialize function • It is a Vertual member function of the CObject class • It must match the parameters and return values of the CObject declaration
Writing a Serialize Function • Example from CStudent of last Chapter void CStudent::Serialize(CArchive& ar) { TRACE("Entering CStudent::Serialize\n"); if (ar.IsStoring()) ar << m_strName << m_nGrade; // into else ar >> m_strName >> m_nGrade; // out of }
Classes and Derived Classes • Most serialization functions call the Serialize functions of their base classes. If CStudent were derived from CPerson, for example, the first line of the Serialize function would be • CPerson::Serialize(ar);
CArchive class • This class has member function • CArchive::IsStoring • It also has overloaded • insertion operators (<<) and extraction operators (>>) for many of the C++ built-in types Next Slide • You may have to cast data types e.g. enumerated types ar << (int) m_nType; ar >> (int&) m_nType;
C++ built-in types TypeDescription BYTE 8 bits, unsigned WORD 16 bits, unsigned LONG 32 bits, signed DWORD 32 bits, unsigned float 32 bits double 64 bits, IEEE standard int 32 bits, signed short 16 bits, signed char 8 bits, unsigned unsigned 32 bits, unsigned
MFC classes • MFC classes that are not derived from CObject, such as CString and CRect, have their own overloaded insertion and extraction operators for CArchive. • What about your own objects that are embedded in the CObject?
Loading from an ArchiveEmbedded Objects vs. Pointers • Let's add a new data member to the CStudent class: public: CTranscript m_transcript; • CTranscript is a custom class derived from CObject • It will have its own Serialize Function • No overload for >> or << operators
An Embedded Objectm_transcript • CStudent::Serialize function void CStudent::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << m_strName << m_nGrade; } else { ar >> m_strName >> m_nGrade; } m_transcript.Serialize(ar); }
Embedded Objectm_transcriptPointers • If I had a pointer to an Object public: CTranscript* m_pTranscript; void CStudent::Serialize(CArchive& ar) { if (ar.IsStoring()) ar << m_strName << m_nGrade; else { m_pTranscript = new CTranscript; ar >> m_strName >> m_nGrade; } m_pTranscript->Serialize(ar); }
Embedded Objectm_transcriptPointers • Or Because the <<, >> are overloaded for CObject, I can do the following: void CStudent::Serialize(CArchive& ar) { if (ar.IsStoring()) ar << m_strName << m_nGrade << m_pTranscript; else ar >> m_strName >> m_nGrade >> m_pTranscript; }
Embedded ObjectPointers • When reading objects are dynamically constructed, by MACROS • In your Serialize functions care must be taken: • To avoid a memory leak, you must be sure that m_pTranscript does not already contain a pointer to a CTranscript object. • If an object was just created it will have a NULL pointer
Embedded ObjectPointers • The insertion and extraction operators do not work with embedded objects of classes derived from CObject, as shown here: • ar >> m_strName >> m_nGrade >> &m_transcript; Null pointer will not work
Serializing Collections • Classes derived from CObject will have the DECLARE_SERIAL macro • If you make a collection of them with CObList • Serialize will be called for each member in the collection
Serializing Collections • Specifics about loading collections from an archive: • If a collection contains pointers to objects of mixed classes (all derived from CObject), the individual class names are stored in the archive so that the objects can be properly constructed with the appropriate class constructor. • If a container object, such as a document, contains an embedded collection, loaded data is appended to the existing collection. You might need to empty the collection before loading from the archive. This is usually done in the document's virtual DeleteContents function, which is called by the application framework.
Serializing Collections • When a collection of CObject pointers is loaded from an archive, the following processing steps take place for each object in the collection: • The object's class is identified. • Heap storage is allocated for the object. • The object's data is loaded into the newly allocated storage. • A pointer to the new object is stored in the collection.
The Serialize Function and the Application Framework • When will the first Serialize function get called to start the serialization process? • With the application framework, everything is keyed to the document • Choosing Save or Open from the file menu • The app framework creates CArcive object • Then it calls the document classes serialize function
The SDI Application • Typically; SDI applications that have one Document Class and one View Class • We will use this to explore the interrelationship among : • application object, main frame window, document, view, document template object, and the associated string and menu resources.
The Windows Application Object • The AppWizard generates the following from CWinApp • CMyApp theApp; • This is the mechanism that starts an MFC application • theApp is a globally declared instance of the class. This global object is called the Windows application object.
Startup steps in a Microsoft Windows MFC library App • Windows loads your program into memory. • The global object theApp is constructed. (All globally declared objects are constructed immediately when the program is loaded.) • Windows calls the global function WinMain, which is part of the MFC library. (WinMain is equivalent to the non-Windows main function—each is a main program entry point.)
Startup steps in a Microsoft Windows MFC library App Cont. • WinMain searches for the one and only instance of a class derived from CWinApp. • WinMain calls the InitInstance member function for theApp, which is overridden in your derived application class. • Your overridden InitInstance function starts the process of loading a document and displaying the main frame and view windows. • WinMain calls the Run member function for theApp, which starts the processes of dispatching window messages and command messages.
The Document Template Class • In the InitInstance function that AppWizard generatesyou will see: CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CStudentDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CStudentView)); AddDocTemplate(pDocTemplate);
AddDocTemplate • This is the only time you'll actually see a document template object. • Unless you use splitter windows and multiple views,. • In this case (SDI), it's an object of class CSingleDocTemplate, which is derived from CDocTemplate • AddDocTemplate is a member function of class CWinApp
AddDocTemplate Cont • The AddDocTemplate call, with the document template constructor call, • Establishes the relationships among classes • The application class, • The document class, • The view window class, • And the main frame window class.
Notable Points • The application object exists, before template construction • The document, view, and frame objects are not constructed at this time. • The application framework later dynamically constructs these objects when they are needed.
Notable Points • This dynamic construction is a sophisticated use of the C++ language. • The DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE macros in a class declaration and implementation enable the MFC library to construct objects of the specified class dynamically. • If this dynamic construction capability weren't present, more relationships among your application's classes would have to be hard-coded. • Your derived application class, for example, would need code for constructing document, view, and frame objects of your specific derived classes. This would compromise the object-oriented nature of your program.
Object Relationships • An SDI • Can only have one • Template • and associated class groups • When Running one • Doc • Main Frame
The Document Template Resource • IDR_MAINFRAMEThe first entry "ex17a\n" // application window caption "\n" // root for default document name // ("Untitled" used if none provided) "Ex17a\n" // document type name "Ex17a Files (*.17a)\n" // doc type desc + filter ".17a\n" // ext for doc of this type "Ex17a.Document\n" // Registry file type ID "Ex17a Document" // Reg file type desc
Multiple Views of an SDI Document • Chapter 20 • But you may provide a menu selection with a switch statement in the OnDraw function to control the way the document class is displayed.
CWinApp::OnFileNew Function • Does the following: • Constructs the document object but does not attempt to read data from disk. • Constructs the main frame object (of class CMainFrame); also creates the main frame window but does not show it. The main frame window includes the IDR_MAINFRAME menu, the toolbar, and the status bar. • Constructs the view object; also creates the view window but doesn't show it.
CWinApp::OnFileNew Function • Cont New app vs new doc (File - New) last 3 will be reused • Establishes connections among the document, main frame, and view objects. Do not confuse these object connections with the class connections established by the call to AddDocTemplate. • Calls the virtual CDocument::OnNewDocument member function for the document object, which calls the virtual DeleteContents function. • Calls the virtual CView::OnInitialUpdate member function for the view object. • Calls the virtual CFrameWnd::ActivateFrame for the frame object to show the main frame window together with the menus, view window, and control bars.
OnNewDocument • An SDI application reuses the same document object So: • You must override OnNewDocument to initialize your document object each time the user chooses File New or File Open.
Connecting File Open to Your Serialization Code • The CWinApp::OnFileOpen Function is mapped to File Open when called the following will occur: • Prompts the user to select a file. • Calls the virtual function CDocument::OnOpenDocument for the already existing document object. This function opens the file, calls CDocument::DeleteContents, and constructs a CArchive object set for loading. It then calls the document's Serialize function, which loads data from the archive. • Calls the view's OnInitialUpdate function.
Document Class's DeleteContents • When you load a new file or create a new document you must erase the contents of the current document • CDocument::DeleteContents virtual function in your derived document class. The overridden function, as you've seen in Chapter 16 , does whatever is necessary to clean up your document class's data members. • It is not the destructor
File Save and File Save Asto Your Serialization Code • AppWizard generates an application, it maps the File Save menu item to the OnFileSave(As) member function of the CDocument class. OnFileSave(As) calls the CDocument function OnSaveDocument, which in turn calls your document's Serialize function with an archive object set for storing.
The Document's "Dirty" Flag • CDocument data member m_bModified • TRUE if the document has been modified (has become "dirty") • Otherwise, it is FALSE. • Accessed through the CDocument member functions SetModifiedFlag and IsModified. • The programmer, must call SetModifiedFlag function to set the flag to TRUE when the document data changes
EX16A ExampleSDI with Serialization • The EX17A example is similar to example EX15B. The student dialog and the toolbar are the same, and the view class is the same. Serialization has been added, together with an update command UI function for File Save.
Explorer Launch (DBLCLICK)and Drag and Drop • Program Registration • Use the Advanced button in AppWizard Step 4. Will add to InitInstance • RegisterShellFileTypes(TRUE); • .17A = Ex17a.Document (will be added to reg)
Explorer Launch (DBLCLICK)and Drag and Drop • Double-Clicking on a Document • AppWizard generates a call to EnableShellOpen in the application class InitInstance function • Enabling Drag and Drop • m_pMainWnd->DragAcceptFiles();
Explorer Launch (DBLCLICK)and Drag and Drop • Program Startup Parameters • The InitInstance function processes the command line with calls to ParseCommandLine and ProcessShellCommand.
Ex16c Example: An MTI Application • This example is an MTI version of the Ex16a we looked at in a previous section. To create this example, in the MFC Application Wizard select Multiple Top-Level Documents on the Application Type page and deselect Printing And Print Preview on the Advanced Features page. On the Generated Classes page, change the view’s base class to CFormView. • See Text