📄 ch10.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<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 += '</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">-->
<META NAME="GENERATOR" Content="Symantec Visual Page Mac 1.1.1">
<TITLE>YeeHaw -- Ch 10 -- Creating Single Document Interface Applications</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<H1 ALIGN="CENTER"><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM"
BORDER="0"><BR>
Teach Yourself Visual C++ 6 in 21 Days</H1>
<CENTER>
<P><A HREF="../ch09/ch09.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch11/ch11.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>
<H1 ALIGN="CENTER">- 10 -<BR>
Creating Single Document Interface Applications</H1>
<H1></H1>
<UL>
<LI><A HREF="#Heading1">The Document/View Architecture</A>
<LI><A HREF="#Heading2">Creating an SDI Application</A>
<UL>
<LI><A HREF="#Heading3">Building the Application Shell</A>
<LI><A HREF="#Heading4">Creating a Line Class</A>
<LI><A HREF="#Heading5">Implementing the Document Functionality</A>
<LI><A HREF="#Heading6">Showing the User</A>
</UL>
<LI><A HREF="#Heading7">Saving and Loading the Drawing</A>
<UL>
<LI><A HREF="#Heading8">Deleting the Current Drawing</A>
<LI><A HREF="#Heading9">Saving and Restoring the Drawing</A>
</UL>
<LI><A HREF="#Heading10">Interacting with the Menu</A>
<UL>
<LI><A HREF="#Heading11">Adding Color to the CLine Class</A>
<LI><A HREF="#Heading12">Adding Color to the Document</A>
<LI><A HREF="#Heading13">Modifying the Menu</A>
</UL>
<LI><A HREF="#Heading14">Summary</A>
<LI><A HREF="#Heading15">Q&A</A>
<LI><A HREF="#Heading16">Workshop</A>
<UL>
<LI><A HREF="#Heading17">Quiz</A>
<LI><A HREF="#Heading18">Exercise</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<BR>
Today you will learn a different way of approaching application development with
Visual C++ than you have used with the previous days' lessons. Today you will learn
how to create Single Document Interface (SDI) applications. An SDI application is
a document-centric application that can only work with one document at a time, and
can only work with one type of document.</P>
<P>Some good examples of SDI applications are Notepad, WordPad, and Paint. All of
these applications can do only one type of task and can only work on one task at
a time. WordPad is almost like an SDI version of Word. It's able to perform a large
number of the tasks that Word does, but although Word allows you to work on numerous
documents at the same time, WordPad limits you to only one document.</P>
<P>Some of the things that you will learn today are</P>
<UL>
<LI>The Document/View architecture that Visual C++ uses for creating SDI applications.
<P>
<LI>How to create an SDI application shell.
<P>
<LI>How to separate your data from the visual representation of the data.
<P>
<LI>How to encapsulate your data in its own C++ class.
<P>
<LI>How to create interaction between the data and the menus.
</UL>
<H2><A NAME="Heading1"></A>The Document/View Architecture</H2>
<P>When you create an SDI application, more classes are created for an SDI application
than for a dialog-style application. Each of these classes serves a specific purpose
in how SDI applications operate. Ignoring the About window dialog class, four specific
classes make up an SDI application:</P>
<UL>
<LI>The CWinApp-derived class
<P>
<LI>The CFrameView-derived class
<P>
<LI>The CDocument-derived class
<P>
<LI>The CView-derived class
</UL>
<P>The CWinApp class creates all the other components in the application. It is the
class that receives all the event messages and then passes the messages to the CFrameView
and CView classes.</P>
<P>The CFrameView class is the window frame. It holds the menu, toolbar, scrollbars,
and any other visible objects attached to the frame. This class determines how much
of the document is visible at any time. Very little (if any) of your programming
efforts on SDI applications will require making any modifications or additions to
either of these first two classes.</P>
<P>The CDocument class houses your document. This class is where you will build the
data structures necessary to house and manipulate the data that makes up your document.
This class receives input from the CView class and passes display information to
the CView class. This class is also responsible for saving and retrieving the document
data from files.</P>
<P>The CView class is the class that displays the visual representation of your document
for the user. This class passes input information to the CDocument class and receives
display information from the CDocument class. Most of the coding that you will do
for this class consists of drawing the document for the user and handling the input
from the user. The CView class has several descendent classes that can be used as
the ancestor for the view class. These descendent classes are listed in Table 10.1.</P>
<P>
<H4>TABLE 10.1. THE CView DESCENDENT CLASSES.</H4>
<P>
<TABLE BORDER="1">
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT"><I>Class</I></TD>
<TD ALIGN="LEFT"><I>Description</I></TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CEditView</TD>
<TD ALIGN="LEFT">Provides the functionality of a edit box control. Can be used to implement simple
text-editor functionality.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CFormView</TD>
<TD ALIGN="LEFT">The base class for views containing controls. Can be used to provide form-based documents
in applications.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CHtmlView</TD>
<TD ALIGN="LEFT">Provides the functionality of a Web browser. This view directly handles the URL navigation,
hyperlinking, and so on. Maintains a history list for browsing forward and back.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CListView</TD>
<TD ALIGN="LEFT">Provides list-control functionality in the Document/View architecture.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CRichEditView</TD>
<TD ALIGN="LEFT">Provides character and paragraph formatting functionality. Can be used to implement
a word-processor application.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CScrollView</TD>
<TD ALIGN="LEFT">Provides scrolling capabilities to a CView class.</TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">CTreeView</TD>
<TD ALIGN="LEFT">Provides tree-control functionality in the Document/View architecture.</TD>
</TR>
</TABLE>
</P>
<P>All four of these classes work together to make up the full functionality of an
SDI application, as shown in Figure 10.1. By taking advantage of this architecture,
you can build powerful document-centric applications with relative ease.</P>
<P><A HREF="javascript:popUp('10fig01.gif')"><B>FIGURE 10.1.</B></A><B> </B><I>The
Document/View architecture.</I></P>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> Don't let the term document mislead you. This doesn't mean
that you can only create applications such as word processors and spreadsheets. In
this situation, the term document refers to the data that is processed by your application,
whereas view refers to the visual representation of that data. For instance, the
Solitaire application could be implemented as a Document/View application, with the
document being the cards and their position in the playing area. In this case, the
view is the display of the cards, drawing each card where the document specifies
it should be.
<HR>
</BLOCKQUOTE>
<H2><A NAME="Heading2"></A>Creating an SDI Application</H2>
<P>To get a good idea of how the Document/View architecture works, and of how you
can use it to build applications, you will build a new version of the drawing application
you created on Day 3, "Allowing User Interaction--Integrating the Mouse and
Keyboard in Your Application." In this version, the user's drawing will be persistent,
which means it is not erased each time another window is placed in front of the application.
This version will also be able to save and restore drawings.</P>
<P>
<H3><A NAME="Heading3"></A>Building the Application Shell</H3>
<P>To create the application shell for today's application, follow these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Create a new AppWizard project. Name the project <B>Day10</B>.
<P>
<DT></DT>
<DD><B>2. </B>On the first step of the AppWizard, select Single Document.
<P>
<DT></DT>
<DD><B>3. </B>Use the default values on the second step of the AppWizard.
<P>
<DT></DT>
<DD><B>4. </B>On the third step of the AppWizard, uncheck the support for ActiveX
Controls.
<P>
<DT></DT>
<DD><B>5. </B>On the fourth step of the AppWizard, leave all the default values.
Click the Advanced button.
<P>
<DT></DT>
<DD><B>6. </B>In the Advanced Options dialog, enter a three-letter file extension
for the files that your application will generate (for example, dhc or dvp). Click
the Close button to close the dialog and then click Next to move to the next step
of the AppWizard.
<P>
<DT></DT>
<DD><B>7. </B>Use the default settings on the fifth step of the AppWizard.
<P>
<DT></DT>
<DD><B>8. </B>On the sixth and final AppWizard step, you can choose the base class
on which your view class will be based. Leave the base class as CView and click Finish.
The AppWizard will generate the application shell.
<P>
</DL>
<H3><A NAME="Heading4"></A>Creating a Line Class</H3>
<P>One of the first issues that you will need to tackle is how to represent your
data in the document class. For the drawing application, you have a series of lines.
Each line consists of a starting point and ending point. You might think that you
can use a series of points for the data representation. If you do this, you also
have to make special accommodations for where one series of lines between points
ends and the next begins. It makes much more sense to represent the drawing as a
series of lines. This allows you to store each individual line that is drawn on the
window without having to worry where one set of contiguous lines ends and where the
next begins.</P>
<P>
<PRE>Unfortunately, the Microsoft Foundation Classes (MFC) does not have a line object class, although it does have a point object class (CPoint). I guess you'll just have to create your own line class by following these steps:
</PRE>
<DL>
<DT></DT>
<DD><B>1. </B>In the Class View tab of the workspace pane, select the top-level object
in the tree (Day10 classes). Right-click the mouse and select New Class from the
pop-up menu.
<P>
<DT></DT>
<DD><B>2. </B>In the New Class dialog, select Generic Class for the class type. Enter
CLine for the class name and click in the first line in the Base Class list box.
Enter CObject as the base class, leaving the class access as public, as in Figure
10.2.
<P>
</DL>
<P><A HREF="javascript:popUp('10fig06.gif')"><B>FIGURE 10.2.</B></A><B> </B><I>The
New Class Wizard.</I></P>
<DL>
<DT><I></I></DT>
<DD><B>3. </B>When you click the OK button to add the CLine class, you may be told
that the Class Wizard cannot find the appropriate header file for inheriting the
CLine class from the CObject class, as in Figure 10.3. Click on the OK button on
this message box.
<P>
</DL>
<P><A HREF="javascript:popUp('10fig07.gif')"><B>FIGURE 10.3.</B></A><B> </B><I>Warning
about including the base class definition.</I></P>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> The appropriate header class is already included in the CLine
class files. Until your compiler complains because it can't find the definition for
the CObject class, don't worry about this message. However, if you are using a base
class that's a bit further down the MFC class hierarchy, you might need to heed this
message and add the appropriate header file to the include statements in the class
source code file.
<HR>
</BLOCKQUOTE>
<H4>Constructing the CLine Class</H4>
<P>At this time, your CLine class needs to hold only two data elements, the two end
points of the line that it represents. You want to add those two data elements and
add a class constructor that sets both values when creating the class instance. To
do this, follow these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>In the Class View tab of the workspace pane, select the CLine class.
<P>
<DT></DT>
<DD><B>2. </B>Right-click the CLine class and choose Add Member Variable from the
pop-up menu.
<P>
<DT></DT>
<DD><B>3. </B>Enter CPoint as the variable type and m_ptFrom as the variable name,
and mark the access as Private. Click OK to add the variable.
<P>
<DT></DT>
<DD><B>4. </B>Repeat steps 2 and 3, naming this variable m_ptTo.
<P>
<DT></DT>
<DD><B>5. </B>Right-click the CLine class and choose Add Member Function from the
pop-up menu.
<P>
<DT></DT>
<DD><B>6. </B>Leave the function type blank, and enter CLine(CPoint ptFrom, CPoint
ptTo) for the function declaration. Click OK to add the function.
<P>
<DT></DT>
<DD><B>7. </B>Edit the new function, adding the code in Listing 10.1.
<P>
</DL>
<H4>LISTING 10.1. THE CLine CONSTRUCTOR.</H4>
<PRE>1: CLine::CLine(CPoint ptFrom, CPoint ptTo)
2: {
3: //Initialize the from and to points
4: m_ptFrom = ptFrom;
5: m_ptTo = ptTo;
6: }
</PRE>
<P>In this object constructor, you are initializing the from and to points with the
points that were passed in to the constructor.</P>
<P>
<H4>Drawing the CLine Class</H4>
<P>To follow correct object-oriented design, your CLine class should be able to draw
itself so that when the view class needs to render the line for the user, it can
just pass a message to the line object, telling it to draw itself. To add this functionality,
follow these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Add a new function to the CLine class by selecting Add Member Function
from the pop-up menu.
<P>
<DT></DT>
<DD><B>2. </B>Specify the function type as void and the function declaration as Draw(CDC
*pDC).
<P>
<DT></DT>
<DD><B>3. </B>Add the code in Listing 10.2 to the Draw function you just added.
<P>
</DL>
<H4>LISTING 10.2. THE CLine Draw FUNCTION.</H4>
<PRE>1: void CLine::Draw(CDC * pDC)
2: {
3: // Draw the line
4: pDC->MoveTo(m_ptFrom);
5: pDC->LineTo(m_ptTo);
6: }
</PRE>
<P>This function is taken almost directly from the application you built a week ago.
It's a simple function that moves to the first point on the device context and then
draws a line to the second point on the device context.</P>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -