Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
168
Добавлен:
24.05.2014
Размер:
25.78 Mб
Скачать

So far, you have created applications using the MFC Application Wizard that generated the basic skeleton of your application. In Chapter 3, you were intro-

duced to the basic Microsoft Foundation Classes (MFC) involved in creating the

Y of MFC: the Document/View architecture.LFurther, in Chapter 4, you learned to

application’s framework. Chapter 3 gave an overview of one of the salient features

design the user interface for these applicationsFby using menus, dialog boxes, and other common window controls.MAfter designing the user interface, you learned to add interactivity for the applications by implementing event handling.

Now that you are familiar withAthe basics of creating VC++ applications using the MFC Application Wizard,Ethis chapter will take you through the intricacies of the Document/ViewTarchitecture. The chapter recapitulates the basics of the Document/View architecture and then moves on to discuss the components and the working of the architecture. It also points out the differences in the implementation and workings of SDI and MDI applications. The latter half of the chapter guides you through the steps to create MDI applications.

Taking a Closer Look at the

Document/View Architecture

By now, you know that when you create an application using the MFC Application Wizard, the wizard automatically generates the application’s framework based on your input. You also know that you can create different types of applications, such as SDI applications, MDI applications, dialog box–based applications, and multiple top-level document applications. The wizard, by default, creates all applications other than dialog box–based applications based on the Document/View architecture.

The Document/View architecture is a framework that provides the skeleton for developing document-centric applications. Document-centric applications segregate data presentation and data management by providing separate classes for handling these two activities. In simple terms, the user interface that handles data presentation is isolated from the back-end operations used to handle data

Team-Fly®

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

101

 

 

 

management. The highlight of this architecture is that it allows you to present the same data in multiple formats to the user.

Let us now discuss the various components of the Document/View architecture and the role of each of these components.

Components in the Document/View Architecture

You are familiar with the two basic components of any MFC application: Application and Frame Window. In addition to these, the Document/View architecture adds two more components: Document and View. These four components form the backbone of the Document/View architecture and are represented by MFC classes in the framework. The classes for each of these components are as follows:

A document class derived from CDocument

A view class derived from CView or its derived classes

A frame class derived from CFrameWnd

An application class derived from CWinApp

If you recall, you had a glimpse of these classes in Chapter 3. Let us first quickly revisit those concepts and then identify the functionality of these components/ classes in the Document/View architecture and how they are implemented.

Document

As stated earlier, the document class is one of the core components of the Document/View architecture because it exclusively manages an application’s data. The document object handles the retrieval and storage of data to any persistent storage, such as a database or a disk file. In addition, the document class handles any tasks related to editing data and updating the views appropriately.

View

The view class is another vital class in the Document/View architecture. This class exclusively handles the presentation of an application’s data to the user. It acts as the interface between the user and the document, which is the data repository. MFC supports different types of views: a simple window, a form, a dialog box, a single document interface, or a multiple document interface. Based on the manner in which you want to present your application’s data, you can select the appropriate view. For example, if you want to design an application that will be

102

Part I

INTRODUCING VC++.NET

 

 

 

used to conduct a customer survey, then the most appropriate view for this application will be the Form view.

Frame Window

Windows-based applications have been around for a long time; hence, we know that one of the static components of all of these applications is the “window.” With this basic fact in mind, we can easily realize the importance of the frame class. This is the class that creates the basic container of your application — the window. As a container, a window holds the view, which displays the application’s data, and other user interface components such as menus, toolbars, and scroll bars.

Application

The application class is an integral part of any type of application you create in MFC. Whenever you execute your application, it is this class that gets the control first and hence is responsible for starting the application. Since the application class is designated to start the application, it creates all other components in the application. It also handles the routing of messages for the entire application. It receives the messages and routes them to the appropriate classes. For example, any message related to displaying data is routed to the view class, whereas any message related to storing or retrieving data is routed to the document class. In a nutshell, the application class acts as the interface between the application and its windows.

From the concepts that we have been discussing till now, we can figure that a Document/View architecture–based application has a well-defined structure, and the functionality of the various classes involved is clearly demarcated. Figure 5-1 illustrates the skeleton of a Document/View application and the four classes involved in the Document/View architecture.

Functionality of the Document/View Classes

By now, you have a fair idea about the basics of the Document/View architecture. If you have worked with previous versions of Visual C++, you know that an indepth knowledge of how the various functionalities of these four classes are implemented is vital for designing and working with a Document/View application. Hence, let’s now spend some time understanding the implementation part of the Document/View architecture.

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

103

 

 

 

File

Edit

View

Help

CDocument

 

 

 

 

 

 

CView

CFrameWnd

 

 

FIGURE 5-1 The skeleton of a Document/View-based application

The CDocument Class

The CDocument class is derived from the CCmdTarget class, which is further derived from the CObject class. As discussed earlier, the document class handles the creating, retrieving, and saving of documents. Remember that an application can support zero or more documents based on the type of application you create, and can also support single or multiple views. If you ponder on this point, you will have one question: How is the relationship maintained between the application’s data (represented by documents) and the various views associated with the same set of data? The Document/View architecture answers this by associating each of the documents you create with a document template. The document template is created in the application class and links the frame window, the document, the view, and the menu of the application. When you execute your application, the application class, which is derived from the CWinApp class, creates a pointer to the document template that can be either a CSingleDocTemplate or a CMultiDocTemplate. While creating the document template, the framework creates the document object, its view, and the frame window. Following is sample code that creates the document template for an SDI application:

104

Part I

INTRODUCING VC++.NET

 

 

 

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,

RUNTIME_CLASS(CTextEditorDoc),RUNTIME_CLASS(CMainFrame),

RUNTIME_CLASS(CTextEditorView));

You will learn about the RUNTIME_CLASS macro later in the chapter.

Apart from creating a document template in the application class, you also need to perform the following tasks in the CDocument class:

Derive a class from the CDocument class for each type of document you want in your application.

Add the required data members for each document to store its data.

Implement member functions for retrieving, storing, and modifying data.

Override the Serialize function, which is a member function of the CObject class, if you want to store and retrieve data from the disk.

Let’s now discuss the various member functions of the CDocument class that you use to accomplish these tasks.

OnNewDocument. After you create a document class, your very first activity will be to create a document object. To accomplish this in an SDI application, you override the OnNewDocument function of the document class. Since an SDI application has only one document, whenever the File, New command is issued, the framework reuses the same document object. The OnNewDocument function implements this functionality by invoking the DeleteContents function that clears any content in the document object. The following code segment illustrates the steps involved in creating a new document:

BOOL CTextEditorDoc::OnNewDocument()

{

if (!CDocument::OnNewDocument())

return FALSE;

return TRUE;

}

IsModified. Yet another important function of the CDocument class is the IsModified function that checks whether the document object has been modified since it was last saved. Before closing any document, the

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

105

 

 

 

framework invokes this function (from within the OnCloseDocument function), thus ensuring that the document is updated with the latest changes. The usage of the IsModified function is as follows:

If (IsModified()==TRUE)

{

AfxMessageBox(“Save changes now?”, MB_YESNO);

}

Serialize. MFC uses a process called serialization for storing and retrieving data. In this process, data is added as data members into an archive that is a binary stream of objects. An archive object is associated with the CArchive class, and hence whenever a document is opened, the

OnFileOpen member function of the application class creates an object of the CArchive class. You use the overloaded insertion (<<) and extraction (>>) operators and the IsStoring and IsLoading member functions of the CArchive class for saving and restoring data.

UpdateAllViews. By now, you know that in a Document/View-based application, the view class handles the display-related activities. Therefore, the framework has to keep the view class informed about any changes to the document object. To accomplish this, the framework uses the OnUpdate function of the CView class. The OnUpdate function further invokes the OnDraw function that displays data. This works fine if yours is an SDI application. What happens if it is an MDI application? How does your application ensure that all views attached to the same document are updated with the changes? This is handled by the UpdateAllViews function.

The following is sample code to illustrate the use of the Serialize and the UpdateAllViews functions. This code snippet is a part of a text editor application. The view class of this application traps the text entered by the user. When the user chooses File, Save, the framework invokes the Serialize function of the document class. Within the Serialize function, the control is transferred to the IsStoring function. The IsStoring function writes the following in the archive object that is associated with the file name specified by the user in the Save As dialog box:

The total number of lines

The lines entered along with the total number of characters in each of the lines

106

Part I

 

INTRODUCING VC++.NET

 

 

 

 

 

 

When the user chooses File, Open, the control is transferred to the IsLoading

 

 

function, which is within the Serialize function of the document class. The

 

 

IsLoading function then retrieves the data stored in the file and populates the

 

 

archive object. Once the data is retrieved, to display the data, the framework has

 

 

to transfer the control to the view class. Hence, the IsLoading function invokes

 

 

the UpdateAllViews function, which further invokes the OnDraw function. The

 

 

OnDraw function then displays the data on the screen using the archive object.

 

 

void CEditorDoc::Serialize(CArchive& ar)

 

 

{

 

 

 

 

int iRow, iColumn;

 

 

// These two variables will be used in the array

 

 

 

if (ar.IsStoring())

 

 

{

ar.Write(&xPosition, sizeof(int));

// xPosition stores the total number of lines entered by the user.

This variable has been

// populated in the OnChar function of the view class where we

stored the data entered by

// the user into an array named storage. for(iRow=0; iRow<=xPosition; iRow++)

//This loop writes the content of the array to an archive object.

{

 

iColumn=lstrlen(storage[iRow]);

 

// Counting the total number of characters in a line

 

ar.Write(&iColumn, sizeof(int));

// Storing the total

number of characters in the file

 

ar.WriteString(storage[iRow]);

// Storing the line in

the file

 

}

 

}

 

else

 

{

 

ar.Read(&xPosition, sizeof(int));

 

// Retrieving the number of lines stored in the file

 

for(iRow=0; iRow<=xPosition; iRow++)

 

//This loop reads the content from the file and stores it into the array named storage

{

VARIATION OF THE SERIALIZE FUNCTION
The implementation of the Serialize function slightly varies in the CEditView class when compared to the other view classes. No, definitely no more complications in life! In fact, things are simpler if you choose to use the CEditView class for creating a text editor. Trying to
figure out how? Here is the answer. The CEditView class invokes the SerializeRaw function from within the
Serialize function. The SerializeRaw function encapsulates the implementation of the IsStoring and IsLoading functions and, hence, you need not code these functions explicitly in your view class derived from CEditView.

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

107

 

 

 

ar.Read(&iColumn, sizeof(int));

//Retrieving the total number of characters in the

//current line to be read

ar.Read(storage[iRow], iColumn);

//Retrieving the specified number of characters,

//which is equivalent to a line, and storing it into

//the array

}

yPosition=iColumn;

UpdateAllViews(NULL);

//To invoke the OnDraw function of the view

//class to display the content read

}

}

The CView Class

As the name suggests, the CView class provides the functionality of your application’s view. Whenever you open a new window, the framework creates the window and attaches a view to it. Therefore, a view is always associated with a document object that is created using the document template. If you recall, there can be multiple views in your application. Also, a view is responsible only for displaying the data. It is the document that supplies the data to be displayed. Hence, the view always maintains a pointer to the associated document object and uses this pointer to communicate with the document. By now you know that there must

be a member function to handle this. The GetDocument member function of the CView class handles this. Sample code of the GetDocument function follows:

108

Part I

INTRODUCING VC++.NET

 

 

 

CTextEditorDoc* GetDocument() const

{

return (CTextEditorDoc*)m_pDocument;

}

In the preceding sample code, m_pDocument refers to the document that is currently in use. It represents the file selected by the user while issuing the File, Open or File, Save commands.

Let’s look at a few other vital member functions of the CView class:

OnDraw. The CView class also provides the OnDraw function that you need to override to display the required data. The framework invokes the

OnDraw function when you execute your application and whenever the view has to be redrawn. A typical situation when a view is redrawn is when you minimize or maximize your application’s window.

OnInitialUpdate. The framework calls this function as soon as the view is attached to its document. This function acts as a constructor of the view class; hence, you can override this function to do any initializations.

NOTE

OnActivateView is yet another function of the view class. The framework invokes this function, whenever a view is activated or deactivated.

FLEXIBILITY OF THE ONDRAW FUNCTION

With your experience with any Windowsbased application, you know that you can view your application’s data either on the screen or printed out. As a programmer, you would definitely have been curious to know how this is done. Now you know that this is established by using the OnDraw function, which is capable of displaying your application’s view on any device context: screen or printer.

The following are the tasks that you need to perform with the view class:

Create a view class for your application. Based on the manner in which you want to display the data, you can derive this class from the CView or any of its derived classes, such as CEditView. We will list the various CView derived classes and their use later.

Override the OnInitialUpdate function, if any initialization is to be done.

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

109

 

 

 

Override the OnDraw function.

Table 5-1 gives a brief description of all CView derived classes.

Table 5-1 CView Derived Classes

Class

Use

CEditView

Used to create text editor applications, such as Microsoft

 

Word

CFormView

Used to create form-based applications

CHtmlView

Used to create applications with functionalities of a browser,

 

such as Internet Explorer

CRichEditView

Used to create text editors with additional formatting func-

 

tionalities, such as character and paragraph formatting

CListView

Used to create applications that display their contents in list

 

boxes

CScrollView

Used to add the scroll feature to your application’s view

CTreeView

Used to create applications that display their contents in a

 

tree-like structure

 

 

The CFrameWnd Class

You have been using the CFrameWnd class in simple applications to attach a frame window to them. It is the same class that enables you to attach a frame window to a Document/View-based application. The frame window acts as a container for the view and other components, such as the menu, toolbar, and status bar. The framework is responsible for the creation and destruction of the main application window and other windows associated with your application’s documents and views. When you close the main application window, the framework closes the application.

Some of the member functions of the CFrameWnd class used to implement the discussed functionalities are listed here:

OnCreate. The framework creates the application’s frame window using this function. All other components attached to the application’s main window, such as the menu bar, toolbar, and status bar, are also created within this function. The following is a sample OnCreate function: