⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch10.htm

📁 VC 21天 学习VC 的好东西
💻 HTM
📖 第 1 页 / 共 4 页
字号:
</PRE>
<P>This function loops through the object array, deleting each line object in the
array. Once all the lines are deleted, the array is reset by calling its RemoveAll
method. If you compile and run your application, you'll find that you can select
File|New, and if you decide not to save your current drawing, your window is wiped
clean.</P>
<P>
<H3><A NAME="Heading9"></A>Saving and Restoring the Drawing</H3>
<P>Adding the functionality to save and restore your drawings is pretty easy to implement,
but it might not be so easy to understand. That's okay; you'll spend an entire day
on understanding saving and restoring files, also known as serialization, in three
days. In the meantime, find the Serialize function in the CDay10Doc class. The function
should look something like</P>
<P>
<PRE> 1: void CDay10Doc::Serialize(CArchive&amp; ar)
 2: {
 3:     if (ar.IsStoring())
 4:     {
 5:         // TODO: add storing code here
 6:     }
 7:     else
 8:     {
 9:         // TODO: add loading code here
10:     }
11: }
</PRE>
<P>Remove all the contents of this function, and edit the function so that it looks
like Listing 10.10.</P>
<P>
<H4>LISTING 10.10. THE CDay10Doc Serialize FUNCTION.</H4>
<PRE> 1: void CDay10Doc::Serialize(CArchive&amp; ar)
 2: {
 3:     ///////////////////////
 4:     // MY CODE STARTS HERE
 5:     ///////////////////////
 6: 
 7:     // Pass the serialization on to the object array
 8:     m_oaLines.Serialize(ar);
 9: 
10:     ///////////////////////
11:     // MY CODE ENDS HERE
12:     ///////////////////////
13: }
</PRE>
<P>This function takes advantage of the functionality of the CObArray class. This
object array will pass down its array of objects, calling the Serialize function
on each of the objects. This means that you need to add a Serialize function to the
CLine class. Specify it as a void function type with the declaration of Serialize(CArchive&amp;
ar). Edit the function, adding the code in Listing 10.11.</P>
<P>
<H4>LISTING 10.11. THE CLine Serialize FUNCTION.</H4>
<PRE> 1: void CLine::Serialize(CArchive &amp;ar)
</PRE>
<PRE> 2: {
 3:     CObject::Serialize(ar);
 4: 
 5:     if (ar.IsStoring())
 6:         ar &lt;&lt; m_ptFrom &lt;&lt; m_ptTo;
 7:     else
 8:         ar &gt;&gt; m_ptFrom &gt;&gt; m_ptTo;
 9: }
</PRE>
<P>This function follows basically the same flow that the original Serialize function
would have followed in the CDay10Doc class. It uses the I/O stream functionality
of C++ to save and restore its contents.</P>
<P>At this point, if you compile and run your application, you expect the save and
open functions to work. Unfortunately, they don't (yet). If you run your application
and try to save a drawing, a message box will tell you that the application was unable
to save the file, as in Figure 10.5.</P>
<P><A HREF="javascript:popUp('10fig09.gif')"><B>FIGURE 10.5.</B></A><B> </B><I>Unable
to save drawings.</I></P>
<P>The reason that you are unable to save your drawing is that Visual C++ must be
told that a class should be serializable. To do this, you add one line to the CLine
class header file and one line to the CLine source code file. Open the CLine header
file (Line.h), and add the DECLARE_SERIAL line in Listing 10.12 just after the first
line of the class definition.</P>
<P>
<H4>LISTING 10.12. THE Line.h EDIT FOR SERIALIZATION.</H4>
<PRE>1: class CLine : public CObject
2: {
3:     DECLARE_SERIAL (CLine)
4: public:
5:     CLine(CPoint ptFrom, CPoint ptTo, UINT nWidth, COLORREF crColor);
</PRE>
<P>Next, open the CLine source code file, and add the IMPLEMENT_SERIAL line in Listing
10.13 just before the class constructor functions.</P>
<P>
<H4>LISTING 10.13. THE Line.cpp EDIT FOR SERIALIZATION.</H4>
<PRE> 1: // Line.cpp: implementation of the CLine class.
 2: //
 3: //////////////////////////////////////////////////////////////////////
 4: 
 5: #include &quot;stdafx.h&quot;
 6: #include &quot;Day10.h&quot;
 7: #include &quot;Line.h&quot;
 8: 
 9: #ifdef _DEBUG
10: #undef THIS_FILE
11: static char THIS_FILE[]=__FILE__;
12: #define new DEBUG_NEW
13: #endif
14: 
15: IMPLEMENT_SERIAL (CLine, CObject, 1)
16: //////////////////////////////////////////////////////////////////////
17: // Construction/Destruction
18: //////////////////////////////////////////////////////////////////////
19: 
20: CLine::CLine()
21: {
22: 
23: }
</PRE>
<P>Now if you compile and run your application, you should be able to draw your own
self-portrait and save it for posterity, as shown in Figure 10.6.</P>
<P><A HREF="javascript:popUp('10fig10.gif')"><B>FIGURE 10.6.</B></A><B> </B><I>My
self-portrait.</I></P>
<P>
<H2><A NAME="Heading10"></A>Interacting with the Menu</H2>
<P>Now that you have a working drawing program, it would be nice if the user could
choose the color with which she wants to draw. Adding this functionality requires
making changes in the CLine class to associate the color with the line and to CDay10Doc
to maintain the currently selected color. Finally, you need to add a pull-down menu
to select the desired color.</P>
<P>
<H3><A NAME="Heading11"></A>Adding Color to the CLine Class</H3>
<P>The changes to the CLine class are fairly straightforward. The first thing that
you need to do is to add another member variable to the CLine class to hold the color
of each line. Next, you need to modify the class constructor to add color to the
list of attributes to be passed in. Third, you need to modify the Draw function to
use the specified color. Finally, you need to modify the Serialize function to save
and restore the color information along with the point information. To do all these
things, follow these steps:</P>

<DL>
	<DT></DT>
	<DD><B>1. </B>Select the CLine class in the Class View tab of the workspace pane.
	Right-click the mouse and select Add Member Variable from the pop-up menu.
	<P>
	<DT></DT>
	<DD><B>2. </B>Specify the variable type as COLORREF, the name as m_crColor, and the
	access as private. Click OK to add the variable.
	<P>
	<DD><B>3. </B>Right-click the CLine constructor in the Class View tree. Select Go
	to Declaration from the pop-up menu.
	<DT></DT>
	<DD><B>4. </B>Add COLORREF crColor as a third argument to the constructor declaration.
	<P>
	<DT></DT>
	<DD><B>5. </B>Right-click the CLine constructor in the Class View tree. Select Go
	to Definition from the pop-up menu.
	<P>
	<DT></DT>
	<DD><B>6. </B>Modify the constructor to add the third argument and to set the m_crColor
	member to the new argument, as in Listing 10.14.
	<P>
</DL>

<H4>LISTING 10.14. THE MODIFIED CLine CONSTRUCTOR.</H4>
<PRE>1: CLine::CLine(CPoint ptFrom, CPoint ptTo, COLORREF crColor)
2: {
3:     //Initialize the from and to points
4:     m_ptFrom = ptFrom;
5:     m_ptTo = ptTo;
6:     m_crColor = crColor;
7: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>7. </B>Scroll down to the Draw function and modify it as in Listing 10.15.
	<P>
</DL>

<H4>LISTING 10.15. THE MODIFIED Draw FUNCTION.</H4>
<PRE> 1: void CLine::Draw(CDC * pDC)
 2: {
 3:     // Create a pen
 4:     CPen lpen (PS_SOLID, 1, m_crColor);
 5: 
 6:     // Set the new pen as the drawing object
 7:     CPen* pOldPen = pDC-&gt;SelectObject(&amp;lpen);
 8:     // Draw the line
 9:     pDC-&gt;MoveTo(m_ptFrom);
10:     pDC-&gt;LineTo(m_ptTo);
11:     // Reset the previous pen
12:     pDC-&gt;SelectObject(pOldPen);
13: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>8. </B>Scroll down to the Serialize function and modify it as in Listing 10.16.
	<P>
</DL>

<H4>LISTING 10.16. THE MODIFIED Serialize FUNCTION.</H4>
<PRE> 1: void CLine::Serialize(CArchive &amp;ar)
 2: {
 3:     CObject::Serialize(ar);
 4: 
 5:     if (ar.IsStoring())
 6:         ar &lt;&lt; m_ptFrom &lt;&lt; m_ptTo &lt;&lt; (DWORD) m_crColor;
 7:     else
 8:         ar &gt;&gt; m_ptFrom &gt;&gt; m_ptTo &gt;&gt; (DWORD) m_crColor;
 9: }
</PRE>
<P>The only part of any of these steps that should be a surprise is that you are
capturing the return value from the SelectObject function when you are specifying
the pen to use in drawing the lines. You didn't do this last week. The return value
from the SelectObject function is the pen that was in use before you changed it.
This way, you can use the previous pen to restore it to the device context when you
are done drawing.</P>
<P>
<H3><A NAME="Heading12"></A>Adding Color to the Document</H3>
<P>The changes that you need to make to the CDay10Doc class are just slightly more
extensive than those made to the CLine class. You need to add a member variable to
hold the current color and a color table to convert color IDs into RGB values. You
need to initialize the current color variable in the OnNewDocument function. Then,
you need to modify the AddLine function to add the current color to the CLine constructor.
Finally, you add a function to return the current color. That's all that you need
to do for now until you start adding menu message handlers for setting the current
color. To do these things, follow these steps:</P>

<DL>
	<DT></DT>
	<DD><B>1. </B>Select the CDay10Doc class in the Class View tab on the workspace pane.
	Right-click the mouse and choose Add Member Variable from the pop-up menu.
	<P>
	<DT></DT>
	<DD><B>2. </B>Specify the variable type as UINT, the name as m_nColor, and the access
	as private. Click OK to add the variable.
	<P>
	<DT></DT>
	<DD><B>3. </B>Repeat step 1.
	<P>
	<DT></DT>
	<DD><B>4. </B>Specify the variable type as &quot;static const COLORREF,&quot; the
	name as m_crColors[8], and the access as public.
	<P>
	<DT></DT>
	<DD><B>5. </B>Open the CDay10Doc source code (Day10Doc.cpp) and add the population
	of the m_crColors color table as in Listing 10.17.
	<P>
</DL>

<H4>LISTING 10.17. THE COLOR TABLE SPECIFICATION.</H4>
<PRE> 1:     //}}AFX_MSG_MAP
 2: END_MESSAGE_MAP()
 3: 
 4: const COLORREF CDay10Doc::m_crColors[8] = {
 5:     RGB(   0,   0,   0),    // Black
 6:     RGB(   0,   0, 255),    // Blue
 7:     RGB(   0, 255,   0),    // Green
 8:     RGB(   0, 255, 255),    // Cyan
 9:     RGB( 255,   0,   0),    // Red
10:     RGB( 255,   0, 255),    // Magenta
11:     RGB( 255, 255,   0),    // Yellow
12:     RGB( 255, 255, 255)    // White
13: };
14: 
15: ////////////////////////////////////////////////////////////////////// 16: // CDay10Doc construction/destruction
17: 
</PRE>
<PRE>18: CDay10Doc::CDay10Doc()
</PRE>
<PRE>19: .
20: .
21: .
22: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>6. </B>Scroll down to the OnNewDocument function and edit it as in Listing
	10.18.
	<P>
</DL>

<H4>LISTING 10.18. THE MODIFIED OnNewDocument FUNCTION.</H4>
<PRE> 1: BOOL CDay10Doc::OnNewDocument()
 2: {
 3:     if (!CDocument::OnNewDocument())
 4:         return FALSE;
 5: 
 6:     // TODO: add reinitialization code here
 7:     // (SDI documents will reuse this document)
 8: 
 9:     ///////////////////////
10:     // MY CODE STARTS HERE
11:     ///////////////////////
12: 
13:     // Initialize the color to black
14:     m_nColor = ID_COLOR_BLACK - ID_COLOR_BLACK;
15: 
16:     ///////////////////////
17:     // MY CODE ENDS HERE
18:     ///////////////////////
19: 
20:     return TRUE;
21: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>7. </B>Scroll down to the AddLine function, and modify it as in Listing 10.19.
	<P>
</DL>

<H4>LISTING 10.19. THE MODIFIED AddLine FUNCTION.</H4>
<PRE> 1: CLine * CDay10Doc::AddLine(CPoint ptFrom, CPoint ptTo)
 2: {
 3:     // Create a new CLine object
 4:     CLine *pLine = new CLine(ptFrom, ptTo, m_crColors[m_nColor]);
 5:     try
 6:     {
 7:         // Add the new line to the object array
 8:         m_oaLines.Add(pLine);
 9:         // Mark the document as dirty
10:         SetModifiedFlag();
11:     }
12:     // Did we run into a memory exception?
13:     catch (CMemoryException* perr)
14:     {
15:         // Display a message for the user, giving him or her the
16:         // bad news
17:         AfxMessageBox(&quot;Out of memory&quot;, MB_ICONSTOP | MB_OK);
18:         // Did we create a line object?
19:         if (pLine)
20:         {
21:             // Delete it
22:             delete pLine;
23:             pLine = NULL;
24:         }
25:         // Delete the exception object
26:         perr-&gt;Delete();
27:     }
28:     return pLine;
29: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>8. </B>Add a new member function to the CDay10Doc class. Specify the function
	type as UINT, the declaration as GetColor, and the access as public.
	<P>
	<DT></DT>
	<DD><B>9. </B>Edit the GetColor function, adding the code in Listing 10.20.
	<P>
</DL>

<H4>LISTING 10.20. THE GetColor FUNCTION.</H4>
<PRE>1: UINT CDay10Doc::GetColor()
</PRE>
<PRE>2: {
</PRE>
<PRE>3:     // Return the current color
4:     return ID_COLOR_BLACK + m_nColor;
5: }
</PRE>
<P>In the OnNewDocument and the GetColor functions, the color is added and subtracted
from ID_COLOR_BLACK. This is the lowest numbered color menu ID when you add the menu
entries. These calculations maintain the variable as a number between 0 and 7, but
when working with the menus, they allow comparison with the actual menu IDs.</P>
<P>
<H3><A NAME="Heading13"></A>Modifying the Menu</H3>
<P>Now comes the fun part. You need to add a new pull-down menu to the main menu.
You need to add menu entries for all the colors in the color table. You need to add
message handlers for all the color menu entries. Finally, you need to add event handlers
to check the menu entry that is the current color. To do all of this, follow these
steps:</P>

<DL>
	<DT></DT>
	<DD><B>1. </B>Select the Resource View tab in the workspace pane. Expand the tree
	so that you can see the contents of the Menu folder. Double-click the menu resource.
	<P>
	<DT></DT>
	<DD><B>2. </B>Grab the blank top-level menu (at the right end of the menu bar) and
	drag it to the left, dropping it in front of the View menu entry.
	<P>
	<DT></DT>
	<DD><B>3. </B>Open the properties for the blank menu entry. Specify the caption as
	&amp;Color. Close the properties dialog.
	<P>
	<DT></DT>
	<DD><B>4. </B>Add submenu entries below the Color top-level menu. Specify the submenus
	in order, setting their properties as specified in Table 10.2. You should wind up
	with a menu looking like Figure 10.7.
	<P>
</DL>

<P><A HREF="javascript:popUp('10fig11.gif')"><B>FIGURE 10.7.</B></A><B> </B><I>The

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -