?? ch07.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
function popUp(pPage) {
var fullURL = document.location;
var textURL = fullURL.toString();
var URLlen = textURL.length;
var lenMinusPage = textURL.lastIndexOf("/");
lenMinusPage += 1;
var fullPath = textURL.substring(0,lenMinusPage);
popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394');
figDoc= popUpWin.document;
zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>';
zhtm += '<link rel="stylesheet" href="/includes/stylesheets/ebooks.css"></head>';
zhtm += '<BODY bgcolor="#FFFFFF">';
zhtm += '<IMG SRC="' + fullPath + pPage + '">';
zhtm += '<P><B>' + pPage + '</B>';
zhtm += '</BODY></HTML>';
window.popUpWin.document.write(zhtm);
window.popUpWin.document.close();
// Johnny Jackson 4/28/98
}
//-->
</SCRIPT>
<link rel="stylesheet" href="/includes/stylesheets/ebooks.css">
<TITLE>Special Edition Using Visual C++ 6 -- Ch 7 -- Persistence and File I/O</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<CENTER>
<H1><IMG SRC="../button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
Special Edition Using Visual C++ 6</H1>
</CENTER>
<CENTER>
<P><A HREF="../ch06/ch06.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch08/ch08.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<CENTER>
<H1>- 7 -</H1>
</CENTER>
<CENTER>
<H1>Persistence and File I/O</H1>
</CENTER>
<UL>
<LI><A HREF="#Heading1">Understanding Objects and Persistence</A>
<LI><A HREF="#Heading2">Examining the File Demo Application</A>
<UL>
<LI><A HREF="#Heading3">A Review of Document Classes</A>
<LI><A HREF="#Heading4">Building the File Demo Application</A>
</UL>
<LI><A HREF="#Heading5">Creating a Persistent Class</A>
<UL>
<LI><A HREF="#Heading6">The File Demo 2 Application</A>
<LI><A HREF="#Heading7">Looking at the CMessages Class</A>
<LI><A HREF="#Heading8">Using the CMessages Class in the Program</A>
</UL>
<LI><A HREF="#Heading9">Reading and Writing Files Directly</A>
<UL>
<LI><A HREF="#Heading10">The CFile Class</A>
</UL>
<LI><A HREF="#Heading11">Creating Your Own CArchive Objects</A>
<LI><A HREF="#Heading12">Using the Registry</A>
<UL>
<LI><A HREF="#Heading13">How the Registry Is Set Up</A>
<LI><A HREF="#Heading14">The Predefined Keys</A>
<LI><A HREF="#Heading15">Using the Registry in an MFC Application</A>
<LI><A HREF="#Heading16">The Sample Applications Revisited</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<CENTER>
<H1></H1>
</CENTER>
<H2><A NAME="Heading1"></A>Understanding Objects and Persistence</H2>
<P>One of the most important things a program must do is save users' data after that
data is changed in some way. Without the capability to save edited data, the work
a user performs with an application exists only as long as the application is running,
vanishing the instant the user exits the application. Not a good way to get work
done! In many cases, especially when using AppWizard to create an application, Visual
C++ provides much of the code necessary to save and load data. However, in some cases--most
notably when you create your own object types--you have to do a little extra work
to keep your users' files up to date.</P>
<P>When you're writing an application, you deal with a lot of different object types.
Some data objects might be simple types, such as integers and characters. Other objects
might be instances of classes, such as strings from the CString class or even objects
created from your own custom classes. When using objects in applications that must
create, save, and load documents, you need a way to save and load the state of those
objects so that you can re-create them exactly as users left them at the end of the
last session.</P>
<P>An object's capability to save and load its state is called <I>persistence</I>.
Almost all MFC classes are persistent because they're derived directly or indirectly
from MFC's CObject class, which provides the basic functionality for saving and loading
an object's state. The following section reviews how MFC makes a document object
persistent.</P>
<P>
<H2><A NAME="Heading2"></A>Examining the File Demo Application</H2>
<P>When you use Visual C++'s AppWizard to create a program, you get an application
that uses document and view classes to organize, edit, and display its data. As discussed
in Chapter 4, "Documents and Views," the document object, derived from
the CDocument class, is responsible for holding the application's data during a session
and for saving and loading the data so that the document persists from one session
to another.</P>
<P>In this chapter, you'll build the File Demo application, which demonstrates the
basic techniques behind saving and loading data of an object derived from CDocument.
File Demo's document is a single string containing a short message, which the view
displays.</P>
<P>Three menu items are relevant in the File Demo application. When the program first
begins, the message is automatically set to the string Default Message. Users will
change this message by choosing Edit, Change Message. The File, Save menu option
saves the document, as you'd expect, and File, Open reloads it from disk.</P>
<P>
<H3><A NAME="Heading3"></A>A Review of Document Classes</H3>
<P>Anyone who's written a program has experienced saving and opening files--object
persistence from the user's point of view. In this chapter you'll learn how persistence
works. Although you had some experience with document classes in Chapter 4, you'll
now review the basic concepts with an eye toward extending those concepts to your
own custom classes.</P>
<P>When working with an application created by AppWizard, you must complete several
steps to enable your document to save and load its state. Those steps are discussed
in this section. The steps are as follows:</P>
<DL>
<DD><B>1. </B>Define the member variables that will hold the document's data.
<P>
<DT></DT>
<DD><B>2. </B>Initialize the member variables in the document class's OnNewDocument()
member function.
<P>
<DT></DT>
<DD><B>3. </B>Display the current document in the view class's OnDraw() member function.
<P>
<DT></DT>
<DD><B>4. </B>Provide member functions in the view class that enable users to edit
the document.
<P>
<DT></DT>
<DD><B>5. </B>Add to the document class's Serialize() member function the code needed
to save and load the data that comprises the document.
<P>
</DL>
<P>When your application can handle multiple documents, you need to do a little extra
work to be sure that you use, change, or save the correct document. Luckily, most
of that work is taken care of by MFC and AppWizard.</P>
<P>
<H3><A NAME="Heading4"></A>Building the File Demo Application</H3>
<P>To build the File Demo application, start by using AppWizard to create an SDI
application. All the other AppWizard choices should be left at their default values,
so you can speed things up by clicking Finish on Step 1 after selecting SDI and making
sure that Document/View support is selected.</P>
<P>Double-click CfileDemoDoc in ClassView to edit the header file for the document
class. In the Attributes section add a CString member variable called m_message,
so that the Attributes section looks like this:</P>
<P>
<PRE>// Attributes
public:
CString m_message;
</PRE>
<P>In this case, the document's storage is nothing more than a single string object.
Usually, your document's storage needs are much more complex. This single string,
however, is enough to demonstrate the basics of a persistent document. It's very
common for MFC programmers to use public variables in their documents, rather than
a private variable with public access functions. It makes it a little simpler to
write the code in the view class that will access the document variables. It will,
however, make future enhancements a little more work. These tradeoffs are discussed
in more detail in Appendix A, "C++ Review and Object-Oriented Concepts."</P>
<P>This string, like all the document's data, must be initialized. The OnNewDocument()
member function is the place to do it. Expand CFileDemoDoc in ClassView and double-click
OnNewDocument() to edit it. Add a line of code to initialize the string so that the
function looks like Listing 7.1. You should remove the TODO comments because you've
done what they were reminding you to do.</P>
<P>
<H4>Listing 7.1  Initializing the Document's Data</H4>
<PRE>BOOL CFileDemoDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
m_message = "Default Message";
return TRUE;
</PRE>
<PRE>}
</PRE>
<P>With the document class's m_message data member initialized, the application can
display the data in the view window. You just need to edit the view class's OnDraw()
function (see Listing 7.2). Expand CFileDemoView in ClassView and double-click OnDraw()
to edit it. Again, you're just adding one line of code and removing the TODO comment.</P>
<P>
<H4>Listing 7.2   Displaying the Document's Data</H4>
<PRE>void CFileDemoView::OnDraw(CDC* pDC)
{
CFileDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(20, 20, pDoc->m_message);
</PRE>
<PRE>}
</PRE>
<P>Getting information onscreen, using device contexts, and the TextOut() function
are all discussed in Chapter 5, "Drawing on the Screen."</P>
<P>Build File Demo now, to make sure there are no typos, and run it. You should see
Default Message appear onscreen.</P>
<P>Now, you need to allow users to edit the application's document by changing the
string. In theory, the application should display a dialog box to let the user enter
any desired string at all. For our purposes, you're just going to have the Edit,
Change Message menu option assign the string a different, hard-coded value. ShowString,
the subject of Chapter 8, "Building a Complete Application: ShowString,"
shows how to create a dialog box such as the one File Demo might use.</P>
<P>Click the Resource tab to switch to ResourceView, expand the resources, expand
Menus, and double-click IDR_MAINFRAME to edit it. Click once on the Edit item in
the menu you are editing to drop it down. Click the blank item at the end of the
list and type <B>Change &Message</B>. This will add another item to the menu.</P>
<P>Choose View, ClassWizard to make the connection between this menu item and your
code. You should see ID_EDIT_CHANGEMESSAGE highlighted already; if not, click it
in the box on the left to highlight it. Choose CFileDemoView from the drop-down box
on the upper right. Click COMMAND in the lower-right box and then click the Add Function
button. Accept the suggested name, OnEditChangemessage(), by clicking OK on the dialog
that appears. Click Edit Code to open the new function in the editor and edit it
to match Listing 7.3.</P>
<P>
<H4>Listing 7.3  Changing the Document's Data</H4>
<PRE>void CFileDemoView::OnEditChangemessage()
{
CTime now = CTime::GetCurrentTime();
CString changetime = now.Format("Changed at %B %d %H:%M:%S");
GetDocument()->m_message = changetime;
GetDocument()->SetModifiedFlag();
Invalidate();
</PRE>
<PRE>}
</PRE>
<P>This function, which responds to the application's Edit, Change Message command,
builds a string from the current date and time and transfers it to the document's
data member. (The CTime class and its Format() function are discussed in Appendix
F, "Useful Classes.") The call to the document class's SetModifiedFlag()
function notifies the object that its contents have been changed. The application
will warn about exiting with unsaved changes as long as you remember to call SetModifiedFlag()
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -