📄 ch09.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>Teach Yourself Visual C++® 5 in 24 Hours -- Hour 9 -- The Document/View Architecture</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<CENTER>
<H1><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
<FONT COLOR="#000077">Teach Yourself Visual C++® 5 in 24 Hours</FONT></H1>
</CENTER>
<CENTER>
<P><A HREF="../ch08/ch08.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch10/ch10.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><FONT COLOR="#000077">- Hour 9 -<BR>
The Document/View Architecture</FONT></H1>
</CENTER>
<P>The main topic for this hour is Document/View, the architecture used by programs
written using AppWizard and the MFC class library. In this hour, you will learn
<UL>
<LI>The support offered for Document/View by the MFC class library and tools such
as AppWizard and ClassWizard<BR>
<BR>
<LI>The MFC classes used to implement Document/View<BR>
<BR>
<LI>Using pointers and references and the role they play in Document/View
</UL>
<P>Also in this hour you will build DVTest, a sample program that will help illustrate
how documents and views interact with each other in an MFC program.
<H2><FONT COLOR="#000077"><B>Visual C++ Support for Document/View</B></FONT></H2>
<P>MFC and AppWizard use the Document/View architecture to organize programs written
for Windows. Document/View separates the program into four main classes:
<UL>
<LI>A document class derived from <TT>CDocument</TT><BR>
<BR>
<LI>A view class derived from <TT>CView</TT><BR>
<BR>
<LI>A frame class derived from <TT>CFrameWnd</TT><BR>
<BR>
<LI>An application class derived from <TT>CWinApp</TT>
</UL>
<P>Each of these classes has a specific role to play in an MFC Document/View application.
The document class is responsible for the program's data. The view class handles
interaction between the document and the user. The frame class contains the view
and other user interface elements, such as the menu and toolbars. The application
class is responsible for actually starting the program and handling some general-purpose
interaction with Windows. Figure 9.1 shows the four main parts of a Document/View
program.</P>
<P><A NAME="01"></A><A HREF="01.htm"><B>Figure 9.1.</B></A> <I><BR>
The Document/View architecture.</I></P>
<P>Although the name "Document/View" might seem to limit you to only word-processing
applications, the architecture can be used in a wide variety of program types. There
is no limitation as to the data managed by <TT>CDocument</TT>; it can be a word processing
file, a spreadsheet, or a server at the other end of a network connection providing
information to your program. Likewise, there are many types of views. A view can
be a simple window, as used in the simple SDI applications presented so far, or it
can be derived from <TT>CFormView</TT>, with all the capabilities of a dialog box.
You will learn about form views in Hour 23, "Advanced Views."
<H3><FONT COLOR="#000077"><B>SDI and MDI Applications</B></FONT></H3>
<P>There are two basic types of Document/View programs:
<UL>
<LI>SDI, or Single Document Interface<BR>
<BR>
<LI>MDI, or Multiple Document Interface
</UL>
<P>An SDI program supports a single type of document and almost always supports only
a single view. Only one document can be open at a time. An SDI application focuses
on a particular task and usually is fairly straightforward.</P>
<P>Several different types of documents can be used in an MDI program, with each
document having one or more views. Several documents can be open at a time, and the
open document often uses a customized toolbar and menus that fit the needs of that
particular document.
<H3><FONT COLOR="#000077"><B>Why Use Document/View?</B></FONT></H3>
<P>The first reason to use Document/View is that it provides a large amount of application
code for free. You should always try to write as little new source code as possible,
and that means using MFC classes and letting AppWizard and ClassWizard do a lot of
the work for you. A large amount of the code that is written for you in the form
of MFC classes and AppWizard code uses the Document/View architecture.</P>
<P>The Document/View architecture defines several main categories for classes used
in a Windows program. Document/View provides a flexible framework that you can use
to create almost any type of Windows program. One of the big advantages of the Document/View
architecture is that it divides the work in a Windows program into well-defined categories.
Most classes fall into one of the four main class categories:
<UL>
<LI>Controls and other user-interface elements related to a specific view<BR>
<BR>
<LI>Data and data-handling classes, which belong to a document<BR>
<BR>
<LI>Work that involves handling the toolbar, status bar, and menus, usually belonging
to the frame class<BR>
<BR>
<LI>Interaction between the application and Windows occurring in the class derived
from <TT>CWinApp</TT>
</UL>
<P>Dividing work done by your program helps you manage the design of your program
more effectively. Extending programs that use the Document/View architecture is fairly
simple because the four main Document/View classes communicate with each other through
well-defined interfaces. For example, to change an SDI program to an MDI program,
you must write little new code. Changing the user interface for a Document/View program
impacts only the view class or classes; no changes are needed for the document, frame,
or application classes.
<H3><FONT COLOR="#000077"><B>Using AppWizard</B></FONT></H3>
<P>Use AppWizard to create SDI and MDI applications. In earlier chapters, you use
AppWizard to create the SDI programs used as examples. Although doing so is more
complicated, you can use AppWizard to create an MDI application almost as easily
as an SDI.</P>
<P>The basic difference between an SDI application and an MDI application is that
an MDI application must manage multiple documents and, usually, multiple views. The
SDI application uses only a single document, and normally only a single view.</P>
<P>Both SDI and MDI applications use an object called a document template to create
a relationship between a view, a document, and a frame class, as well as an identifier
used for the program's menu, icon, and other resources. You use the <TT>CSingleDocTemplate</TT>
class for SDI applications and the <TT>CMultiDocTemplate</TT> class for MDI applications.
These two classes share a common base class, <TT>CDocTemplate</TT>. Listing 9.1 is
an example of a document template used for an SDI program.
<H4><FONT COLOR="#000077">TYPE: Listing 9.1. How AppWizard uses a document template
in an SDI application.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>CSingleDocTemplate* pDocTemplate;</TT>
<TT>pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME,</TT>
<TT> RUNTIME_CLASS(CTestDoc),</TT>
<TT> RUNTIME_CLASS(CMainFrame),</TT>
<TT> RUNTIME_CLASS(CTestView));</TT>
<TT>AddDocTemplate(pDocTemplate);</TT>
</FONT></PRE>
<P>Two types of frame windows exist in an MDI program: the main frame, which encompasses
the entire client area, and the child frame, which contains each MDI child window.
The different windows used in an MDI program are shown in Figure 9.2.</P>
<P><A NAME="02"></A><A HREF="02.htm"><B>Figure 9.2.</B> </A><BR>
<I>The windows used in a typical MDI program.</I></P>
<P>The C++ source code generated by Developer Studio for an MDI program is slightly
different than the code it generates for an SDI program. Examine this code, shown
in Listing 9.2, to see some of the differences between MDI objects and SDI objects.
<H4><FONT COLOR="#000077">TYPE: Listing 9.2. AppWizard code that uses a document
template in an MDI application.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>CMultiDocTemplate* pDocTemplate;</TT>
<TT>pDocTemplate = new CMultiDocTemplate( IDR_TESTTYPE,</TT>
<TT> RUNTIME_CLASS(CTestDoc),</TT>
<TT> RUNTIME_CLASS(CChildFrame),</TT>
<TT> RUNTIME_CLASS(CTestView));</TT>
<TT>AddDocTemplate(pDocTemplate);</TT>
</FONT></PRE>
<P><TT>CChildFrame</TT> is a class included in every MDI project created by AppWizard,
and is derived from <TT>CMDIChildFrame</TT>. This class is provided to make customizing
the frame to suit your needs easy. Every MDI child window has a frame that owns the
minimize, maximize, and close buttons and the frame around the view. Any customization
you want to do to the frame is done in the <TT>CChildFrame</TT> class.
<H3><FONT COLOR="#000077"><B>Using ClassWizard</B></FONT></H3>
<P>You have used ClassWizard in previous hours to add member variables to dialog
box classes, add new classes to a project, and handle messages sent to view windows
and dialog boxes. You also use ClassWizard to add interfaces defined as part of the
Document/View architecture. In most cases, default behavior provided by the MFC framework
is enough for simple programs.</P>
<P>You will learn about the interfaces used by the document and view classes in the
next section. However, you add almost all these interfaces using ClassWizard. Let's
look at one of these interfaces, <TT>GetFirstViewPosition</TT>. A document can obtain
a pointer to the first view associated with the document using this function. Normally,
the framework will maintain a list of the views associated with a document, but you
can keep this list yourself by overriding this function. Because the <TT>GetFirstViewPosition</TT>
function is virtual, your implementation of it is always called if available.</P>
<P>To add an implementation for one of the Document/View interface functions, follow
these steps, which are similar to the steps used to add message-handling functions:
<DL>
<DD>1. Open ClassWizard.<BR>
<BR>
2. Select the name of the class that supplies the interface to be added; in this
case, a class derived from <TT>CDocument</TT>.<BR>
<BR>
3. Select the Message Maps tab.<BR>
<BR>
4. Select the <TT>CDocument</TT>-derived class as the object ID.<BR>
<BR>
5. Select the interface function to be added from the list box.<BR>
<BR>
6. Click the Add Function button.<BR>
<BR>
7. Close ClassWizard.
</DL>
<P>You can use ClassWizard to override all the interfaces defined for programs using
the Document/View architecture. Interfaces such as <TT>GetFirstViewPosition</TT>
are rarely overridden, except when debugging. If you provide a new version of <TT>GetFirstViewPosition</TT>,
you probably should override the related function <TT>GetNextView</TT> as well.</P>
<P>For the remaining examples in this hour, you will create an MDI project named
DVTest. To create the DVTest example, use AppWizard to create a default MDI program.
Name the program DVTest. Feel free to accept or change any of the default parameters
offered by AppWizard because they have no impact on these examples. When finished,
DVTest displays a collection of names stored by the document class.
<H2><FONT COLOR="#000077"><B>Pointers and References</B></FONT></H2>
<P>Pointers are important topics in C++ programming. A good understanding of the
ways in which pointers are used will help you write programs that are more flexible
and reliable. C++, and MFC in particular, relies very heavily on proper understanding
and use of pointers.</P>
<P><FONT COLOR="#000077"><B>New Term:</B></FONT><B> </B>A <I>pointer</I> is simply
a numeric variable. This numeric variable is an <I>address</I>, or location in memory
where the actual data resides.<I> </I>Pointers must also follow the same rules that
are applied to other variables. They must have unique names, and they must be declared
before they can be used.</P>
<P>Every object or variable that is used in an application takes up a location or
multiple locations in memory. This memory location is accessed via an address (see
Figure 9.3).</P>
<P><A NAME="03"></A><A HREF="03.htm"><B>Figure 9.3.</B> </A><BR>
<I>The text <TT>Hello</TT> stored beginning at address 1000.</I></P>
<P>In this figure, the text <I><TT>Hello</TT></I> is stored in memory beginning at
address 1000. Each character takes up a unique address space in memory. Pointers
provide a method for holding and getting to these addresses in memory. Pointers make
manipulating the data easier because they hold the address of another variable or
data location.
<BLOCKQUOTE>
<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>Just a Minute:</B></FONT><B> </B>Pointers give flexibility
to C++ programs and enable the programs to grow dynamically. By using a pointer to
a block of memory that is allocated at runtime, a program can be much more flexible
than one that allocates all its memory at once.
<HR>
</BLOCKQUOTE>
<P>A pointer is also easier to store than a large structure or class object. Because
a pointer just stores an address, it can easily be passed to a function. However,
if an object is passed to a function, the object must be constructed, copied, and
destroyed, which can be costly for large objects.
<H3><FONT COLOR="#000077"><B>How Are Pointers Used?</B></FONT></H3>
<P>When using pointers and memory addresses, it is often useful to know the amount
of memory required for each object pointed to. If you must know the amount of storage
required for a particular object or variable, you can use the <TT>sizeof</TT> operator.
You can also use <TT>sizeof</TT> to determine the amount of storage required for
your own classes and structures, as shown in Listing 9.3.
<H4><FONT COLOR="#000077">TYPE: Listing 9.3. Using sizeof with class types.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>void DisplayBtnSize()</TT>
<TT>{</TT>
<TT> int nSize = sizeof(CButton);</TT>
<TT> CString strMsg;</TT>
<TT> strMsg.Format("The size of CButton is %d bytes", nSize);</TT>
<TT> AfxMessageBox(strMsg);</TT>
<TT>}</TT>
</FONT></PRE>
<H3><FONT COLOR="#000077"><B>The Indirection and Address Operators</B></FONT></H3>
<P>Two operators are used when working with addresses in a C++ program: the <I>address-of
operator</I> (<TT>&</TT>) and the <I>indirection operator</I> (<TT>*</TT>). These
operators are different from operators seen previously because they are <I>unary</I>,
meaning that they work with only one operand.</P>
<P>The address-of operator, <TT>&</TT>, returns the address of a variable or
object. This operator is associated with the object to its right, like this:</P>
<PRE><FONT COLOR="#0066FF"><TT>&myAge;</TT>
</FONT></PRE>
<P>This line returns the address of the <TT>myAge</TT> variable.</P>
<P>The indirection operator, <TT>*</TT>, works like the address-of operator in reverse.
It also is associated with the object to its right, and it takes an address and returns
the object contained at that address. For example, the following line determines
the address of the <TT>myAge</TT> variable; then it uses the indirection operator
to access the variable and give it a value of 42:</P>
<PRE><FONT COLOR="#0066FF"><TT>*(&myAge) = 42;</TT>
</FONT></PRE>
<H3><FONT COLOR="#000077"><B>Using the Indirection Operator</B></FONT></H3>
<P>You can use a pointer with the indirection operator to change the value of the
other variable, as shown in the console-mode program in Listing 9.4.
<H4><FONT COLOR="#000077">TYPE: Listing 9.4. Using a pointer variable with the indirection
operator.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>#include <iostream></TT>
<TT>using namespace std;</TT>
<TT>int main()</TT>
<TT>{</TT>
<TT> int nVar;</TT>
<TT> int* pVar;</TT>
<TT> // Store a value in nVar, and display it. Also</TT>
<TT> // display nVar's address.</TT>
<TT> nVar = 5;</TT>
<TT> cout << "nVar's value is " << nVar << "." << endl;</TT>
<TT> cout << "nVar's address is " << &nVar << "." << endl;</TT>
<TT> // Store the address of nVar in pointer pVar. Display</TT>
<TT> // information about pVar and the address it points to.</TT>
<TT> pVar = &nVar;</TT>
<TT> cout << "pVar's value is " << pVar << "." << endl;</TT>
<TT> cout << "*pVar's value is " << *pVar << "." << endl;</TT>
<TT> // Change the value of the variable pointed to by pVar.</TT>
<TT> *pVar = 7;</TT>
<TT> cout << "nVar's value is " << nVar << "." << endl;</TT>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -