?? ch22.htm
字號:
22.2.<H4><FONT COLOR="#000077">Table 22.2. New CString member variables for the CUsersDlgclass.</FONT></H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><B>Resource ID</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Name</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Category</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Variable Type</B></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_EDIT_NAME</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>m_szName</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>Value</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>CString</TT></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_EDIT_ADDR</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>m_szAddr</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>Value</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>CString</TT></TD> </TR></TABLE><H4><FONT COLOR="#000077">Adding a Menu Item</FONT></H4><P>Use the values from Table 22.3 to add a menu item and message-handling functionto the <TT>CCustomersDoc</TT> class. Add the new menu item, labeled New User...,to the Edit menu in the <TT>IDR_CUSTOMTYPE</TT> menu resource. To reduce the amountof source code required for this example, handle the menu item directly with thedocument class. However, the dialog box can also be handled by a view class or <TT>CMainFrame</TT>.<H4><FONT COLOR="#000077">Table 22.3. New member functions for the CCustomersDocclass.</FONT></H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><B>Menu ID</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Caption</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Event</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Function Name</B></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><TT>ID_EDIT_USER</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP">Add User...</TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>COMMAND</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>OnEditUser</TT></TD> </TR></TABLE></P><P>Listing 22.8 contains the complete source code for the <TT>OnEditUser</TT> function,which handles the message sent when the user selects the new menu item. If the userclicks OK, the contents of the dialog box are used to create a new <TT>CUser</TT>object, and a pointer to the new object is added to the <TT>m_setOfUsers</TT> collection.The <TT>SetModifiedFlag</TT> function is called to mark the document as changed.Add the source code provided in Listing 22.8 to the <TT>CCustomersDoc::OnEditUser</TT>member function.<H4><FONT COLOR="#000077">TYPE: Listing 22.8. Adding a new CUser object to the documentclass.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CCustomersDoc::OnEditUser()</TT><TT>{</TT><TT> CUsersDlg dlg;</TT><TT> if( dlg.DoModal() == IDOK )</TT><TT> {</TT><TT> CUser* pUser = new CUser( dlg.m_szName, dlg.m_szAddr );</TT><TT> m_setOfUsers.Add( pUser );</TT><TT> UpdateAllViews( NULL );</TT><TT> SetModifiedFlag();</TT><TT> }</TT><TT>}</TT></FONT></PRE><P>Add the source code provided in Listing 22.9 to the <TT>CustomersDoc.cpp</TT>source file. These functions provide access to the data contained by the document.The view class, <TT>CCustomerView</TT>, calls the two <TT>CCustomersDoc</TT> memberfunctions provided in Listing 22.9 when updating the view window.<H4><FONT COLOR="#000077">TYPE: Listing 22.9. Document class member functions usedfor data access.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>int CCustomersDoc::GetCount() const</TT><TT>{</TT><TT> return m_setOfUsers.GetSize();</TT><TT>}</TT><TT>CUser* CCustomersDoc::GetUser( int nUser ) const</TT><TT>{</TT><TT> CUser* pUser = 0;</TT><TT> if( nUser < m_setOfUsers.GetSize() )</TT><TT> pUser = m_setOfUsers.GetAt( nUser );</TT><TT> return pUser;</TT><TT>}</TT></FONT></PRE><P>Every document needs a <TT>Serialize</TT> member function. The <TT>CCustomersDoc</TT>class has only one data member so its <TT>Serialize</TT> function deals only with<TT>m_setOfUsers</TT>, as shown in Listing 22.10. Add this source code to the <TT>CCustomersDoc::Serialize</TT>member function.<H4><FONT COLOR="#000077">TYPE: Listing 22.10. Serializing the contents of the documentclass.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CCustomersDoc::Serialize(CArchive& ar)</TT><TT>{</TT><TT> m_setOfUsers.Serialize( ar );</TT><TT>}</TT></FONT></PRE><P>As discussed earlier in this hour, the <TT>CArray</TT> class uses the <TT>SerializeElements</TT>helper function when the collection is serialized. Add the <TT>SerializeElements</TT>function that was provided earlier in Listing 22.5 to the <TT>CustomersDoc.cpp</TT>source file.</P><P>Add two <TT>#include</TT> statements to the <TT>CustomersDoc.cpp</TT> file sothat the <TT>CCustomersDoc</TT> class can have access to declarations of classesused by <TT>CCustomersDoc</TT>. Add the source code from Listing 22.11 near the topof the <TT>CustomersDoc.cpp</TT> file, just after the other <TT>#include</TT> statements.<H4><FONT COLOR="#000077">TYPE: Listing 22.11. Include statements used by the CCustomersDocclass.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>#include "Users.h"</TT><TT>#include "UsersDlg.h"</TT></FONT></PRE><H4><FONT COLOR="#000077">Modifying the View</FONT></H4><P>The view class, <TT>CCustomersView</TT>, displays the current contents of thedocument. When the document is updated, the view is repainted and displays the updatedcontents. You must update two functions in the <TT>CCustomersView</TT> class: <TT>OnDraw</TT>and <TT>OnUpdate</TT>.</P><P>AppWizard creates a skeleton version of the <TT>CCustomersView::OnDraw</TT> function.Add the source code from Listing 22.12 to <TT>OnDraw</TT> so that the current documentcontents are displayed in the view. Because this isn't a scrolling view, a limitednumber of items from the document can be displayed.<H4><FONT COLOR="#000077">TYPE: Listing 22.12. Using OnDraw to display the currentdocument's contents.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CCustomersView::OnDraw(CDC* pDC)</TT><TT>{</TT><TT> CCustomersDoc* pDoc = GetDocument();</TT><TT> ASSERT_VALID(pDoc);</TT><TT> // Calculate the space required for a single</TT><TT> // line of text, including the inter-line area.</TT><TT> TEXTMETRIC tm;</TT><TT> pDC->GetTextMetrics( &tm );</TT><TT> int nLineHeight = tm.tmHeight + tm.tmExternalLeading;</TT><TT> CPoint ptText( 0, 0 );</TT><TT> for( int nIndex = 0; nIndex < pDoc->GetCount(); nIndex++ )</TT><TT> {</TT><TT> CString szOut;</TT><TT> CUser* pUser = pDoc->GetUser( nIndex );</TT><TT> szOut.Format( "User = %s, email = %s",</TT><TT> pUser->GetName(),</TT><TT> pUser->GetAddr() );</TT><TT> pDC->TextOut( ptText.x, ptText.y, szOut );</TT><TT> ptText.y += nLineHeight;</TT><TT> }</TT><TT>}</TT></FONT></PRE><P>As with most documents, the <TT>CCustomersDoc</TT> class calls <TT>UpdateAllViews</TT>when it is updated. The MFC framework then calls the <TT>OnUpdate</TT> function foreach view connected to the document.</P><P>Use ClassWizard to add a message-handling function for <TT>CCustomersView::OnUpdate</TT>and add the source code from Listing 22.13 to it. The <TT>OnUpdate</TT> functioninvalidates the view; as a result, the view is redrawn with the updated contents.<H4><FONT COLOR="#000077">TYPE: Listing 22.13. Invalidating the view during OnUpdate.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CCustomersView::OnUpdate( CView* pSender,</TT><TT> LPARAM lHint,</TT><TT> CObject* pHint)</TT><TT>{</TT><TT> InvalidateRect( NULL );</TT><TT>}</TT></FONT></PRE><P>Add an <TT>#include</TT> statement to the <TT>CustomersView.cpp</TT> file so thatthe view can use the <TT>CUser</TT> class. Add the include statement beneath theother include statements in <TT>CustomersView.cpp</TT>.</P><PRE><FONT COLOR="#0066FF"><TT>#include "Users.h"</TT></FONT></PRE><P>Compile and run the Customers project. Add names to the document by selectingAdd User from the Edit menu. Figure 22.7 shows an example of the Customers projectrunning with a few email addresses.</P><P><A NAME="07"></A><A HREF="07.htm"><B>Figure 22.7.</B> </A><I><BR>The Customers example with some email addresses.</I></P><P>Serialize the contents of the document by saving it to a file, and close the document.You can reload the document by opening the file.<H2><FONT COLOR="#000077"><B>Summary</B></FONT></H2><P>In this hour, you learned about serialization and persistence and how they areused in a Document/View application. You also learned about the <TT>CDocument</TT>functions used for serialization and created a small Document/View serializationexample.<H2><FONT COLOR="#000077"><B>Q&A</B></FONT></H2><DL> <DD><B>Q I'm having a problem using serialization with classes that have an abstract base class. What's wrong?</B><BR> <BR> <B>A</B> The MFC serialization process is incompatible with abstract base classes. You can never have an instance of an abstract class; because each serialized object is created as it is read from an instance of <TT>CArchive</TT>, MFC will attempt to create an abstract class. This isn't allowed by the C++ language definition.<BR> <BR> <B>Q Does it matter where I put the <TT>DECLARE_SERIAL</TT> macro in my class declaration? I added the macro to my source file, and now I receive compiler errors.</B><BR> <BR> <B>A</B> The serialization macros can go anywhere, but you must be sure to specify the access allowed for the class declaration after the macro. Place a <TT>public</TT>, <TT>private</TT>, or <TT>protected</TT> label immediately after the macro and your code should be fine.</DL><H2><FONT COLOR="#000077"><B>Workshop</B></FONT></H2><P>The Workshop is designed to help you anticipate possible questions, review whatyou've learned, and begin thinking ahead to putting your knowledge into practice.The answers to the quiz are in Appendix B, "Quiz Answers."<H3><FONT COLOR="#000077"><B>Quiz</B></FONT></H3><DL> <DD>1. What is persistence?<BR> <BR> 2. What is serialization?<BR> <BR> 3. What is the difference between serialization and deserialization?<BR> <BR> 4. What MFC class is used to represent a storage object?<BR> <BR> 5. What virtual function is implemented by all persistent classes?<BR> <BR> 6. What is the name of the helper function that assists in serializing a template collection that contains pointers?</DL><H3><FONT COLOR="#000077"><B>Exercises</B></FONT></H3><DL> <DD>1. Modify the <TT>CUser</TT> class so that it also contains the postal address for a user persistently. Modify the Customers project to use the new version of the <TT>CUsers</TT> class.<BR> <BR> 2. Modify the Customers project so that the number of items stored in a document is displayed when the application starts or a file is opened.<FONT COLOR="#000077"></FONT></DL><CENTER><P><HR><A HREF="../ch21/ch21.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch23/ch23.htm"><IMGSRC="../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> <BR><BR><BR><IMG SRC="../button/corp.gif" WIDTH="284" HEIGHT="45" ALIGN="BOTTOM" ALT="Macmillan Computer Publishing USA"BORDER="0"></P><P>© <A HREF="../copy.htm">Copyright</A>, Macmillan Computer Publishing. Allrights reserved.</CENTER></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -