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

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

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

110

Part I

 

INTRODUCING VC++.NET

 

 

 

 

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

 

 

 

 

 

return -1;

 

 

 

 

 

 

 

 

// Code for creating toolbar, status bar, and menu bar goes here.

 

 

 

 

 

return 0;

 

 

 

 

 

 

 

}

 

 

 

 

 

 

PreCreateWindow. The framework invokes this function just before

 

 

 

invoking the OnCreate function, and it is similar to a constructor of a

 

 

 

class. You can use this function to change the default attributes of your

 

 

 

application’s main window. Sample code for the PreCreateWindow func-

 

 

 

tion follows:

 

 

Y

 

 

 

 

L

 

 

 

 

 

 

 

 

 

 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

 

 

{

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

if( !CFrameWnd::PreCreateWindow(cs) )

 

 

 

 

 

 

 

M

 

 

 

 

 

 

 

 

return F LSE;

 

 

 

 

 

 

 

A

 

 

 

 

 

 

// ODO: Modify the Window class or styles here by modifying

 

 

 

 

 

the CREAEES RUCT cs

 

 

 

 

 

 

T

return TRUE;

 

 

 

 

 

 

 

 

}

Besides acting as a container for your application, the CFrameWnd class can also handle notification messages and, if required, transfer them to the view class.

The CWinApp Class

The class that lays the foundation for your entire application is the CWinApp class. Just as any building has only one foundation, you can have only one CWinApp derived class in your application. Let us now consider some of the member functions of the CWinApp class that are the core components of this class:

InitInstance. When you execute an application, the framework immediately invokes the InitInstance function. This function works like the constructor of the application class. As a constructor, this function is involved in the following:

Creating the document template for the application.

Parsing any command-line information and controlling its execution.

Handling the File, New and File, Open commands.

Team-Fly®

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

111

 

 

 

AddDocTemplate. As you learned earlier, the application maintains a list of document templates. Any new document template created must be added to this list, which is accomplished by using the AddDocTemplate member function.

ParseCommandLine. This function parses the command-line parameters. It accepts an object of the CCommandLineInfoClass class that aids in parsing the command line. When you start any application, this class searches for any command-line parameters. If there are no commandline parameters, then by default a new file is created as soon as the application is executed. This happens, for example, when you start Microsoft Word.

ProcessShellCommand. This function dispatches the commands specified on the command line to the appropriate class where they are handled. If the execution is unsuccessful, then this function returns False (zero).

OnFileNew. This function is invoked whenever the File, New command is issued. Also, the framework can invoke this function from within the

InitInstance function. The question is, when will this happen? Recall our discussion about the ProcessShellCommand function, which stated that a new document is displayed if no command-line parameters are passed. How is this done? The application uses the OnFileNew function. As a result, once the application is executed, a new document is created and displayed within the application’s window.

OnFileOpen. This function is invoked whenever the File, Open command is issued. In addition, the framework can also invoke this function from within InitInstance. The reasons are similar to invoking the

OnFileNew function — when executing any application, if any file name is specified on the command line, then the framework invokes the OnFileOpen function automatically. The specified file is opened and displayed by default within the application’s window.

ShowWindow. Once the document template is registered and the com- mand-line processing is done, the framework initializes its member variable m_pMainWnd to point to the application’s window. It then invokes the ShowWindow function to display the window.

The following is a sample of the InitInstance function (of an SDI application) that illustrates the implementation of all other functions just discussed:

112

Part I

INTRODUCING VC++.NET

 

 

 

BOOL CDocViewAppApp::InitInstance()

{

CSingleDocTemplate* pDocTemplate;

DocTemplate=new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CDocViewAppDoc),

RUNTIME_CLASS(CMainFrame),RUNTIME_CLASS(CDocViewAppView));

AddDocTemplate(pDocTemplate);

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

if (!ProcessShellCommand(cmdInfo)) return FALSE;

m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE;

}

Dynamic Object Creation

Based on our discussion about the Document/View architecture, we know that the framework has to create the documents, views, and frame windows on-the-fly. To accomplish this, the framework has to have the ability to create objects dynamically. Two ways exist to do this: one by using the C++ new operator, and the other by using the CRuntimeClass structure and the RUNTIME_CLASS macro, which are described here:

CRuntimeClass structure. The CRuntimeClass structure is used to retrieve information about an object dynamically. Each class belonging to the MFC hierarchy is associated with a CRuntimeClass structure.

RUNTIME_CLASS macro. The CRuntimeClass structure retrieves information dynamically by using the RUNTIME_CLASS macro. This macro returns a pointer to the CRuntimeClass structure for the specified class.

Using the CRuntimeClass structure and the RUNTIME_CLASS macro to create objects

dynamically requires the use of the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE

macros in the class declaration and class definition, respectively. The

NOTE

Refer to the previous sample of the InitInstance function for an example of the usage of the RUNTIME_CLASS macro.

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

113

 

 

 

DECLARE_DYNCREATE macro takes the name of the class, which has to be created dynamically, as the parameter. The IMPLEMENT_DYNCREATE macro takes two parameters, the name of the derived class and the name of the base class.

The following is a sample code snippet illustrating the usage of the DECLARE_DYN-

CREATE and the IMPLEMENT_DYNCREATE macros:

//MDIAppDoc.h file containing the document class declaration class CMDIAppDoc : public CDocument

{

protected: // create from serialization only CMDIAppDoc(); DECLARE_DYNCREATE(CMDIAppDoc)

};

//MDIAppDoc.cpp file containing the definition of the document class #include “stdafx.h”

#include “MDIApp.h” #include “MDIAppDoc.h”

IMPLEMENT_DYNCREATE(CMDIAppDoc, CDocument)

BEGIN_MESSAGE_MAP(CMDIAppDoc, CDocument)

END_MESSAGE_MAP()

Creating an MDI Application

Before we start creating an MDI application, let us quickly glance through the concepts of SDI and MDI applications:

Single Document Interface (SDI) applications support a single document and view, which implies that, at any point of time, only one document can be open and the document can be displayed only using a single view. The most appropriate examples for SDI applications are Notepad and WordPad.

Multiple Document Interface (MDI) applications support multiple documents and views. In order to have multiple documents open simultaneously, MDI allows multiple frame windows to be open in a single instance of the application. A typical MDI application has a main

114

Part I

INTRODUCING VC++.NET

 

 

 

(parent) frame window within which multiple other child windows can be opened. In each of these windows, you can display a different document.

In Chapter 3, you learned to create an SDI application. Now let us create an MDI application using the MFC Application Wizard and examine the different classes of the Document/View architecture that we have been discussing up to this point.

A Sample MDI Application

Now that we have revisited the main concepts of the Document/View architecture, let us go ahead and create an MDI application by using the MFC Application Wizard. This application will have a menu option with choices to draw a line, a rectangle, or an ellipse. The application will also allow the user to save and restore the work done. Do these functionalities sound familiar? Yes, we are on our way to create our own customized version of the Paint application!

To begin with, let us create the application and examine the skeleton generated. Later, we will run through the user-defined functions added to the application to provide the drawing functionality. To end with, we will be looking at the flow of control within a Document/View-based application.

So, let us get started. Here we go!

1.Open the New Project dialog box and create a Visual C++ project.

2.From the Templates list, select MFC Application, name your application, and click OK. The MFC Application Wizard appears.

3.Click Application Type in the left frame of the MFC Application Wizard. Accept the default settings, as shown in Figure 5-2. This will create an MDI application based on the Document/View architecture.

4.Click Generated Classes in the left frame of the MFC Application Wizard. The right frame displays the classes generated by the wizard, the class name, the corresponding header file (.h), the base class, and the

.cpp file. Figure 5-3 displays the Generated Classes page of the wizard.

5.Click Finish to close the MFC Application Wizard.

When you click the Finish button, the wizard generates various files defining the skeletal versions of the classes. As you know, the wizard reduces half the load of a Visual C++ programmer by providing a lot of built-in functionalities. All you need

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

115

 

 

 

FIGURE 5-2 The MFC Application Wizard displaying the Application Type page

FIGURE 5-3 The MFC Application Wizard displaying the Generated Classes page

to do is edit the generated code and enhance it the way you want. So, let’s get started now and examine the classes generated and enhance the application by adding the functionality for drawing.

116

Part I

INTRODUCING VC++.NET

 

 

 

Enhancing the Application

Here, we will be examining code snippets so that we can quickly glance through the skeleton generated.

Before examining the code generated by the wizard and the other user-defined classes, let us spend some time understanding the approach being used to implement the drawing features of the application. The following is an outline of the approach:

NOTE

The classes and the files take the name of your application. In this sample code, the application’s name is MDIApp.

A class named Draw is derived from the CObject class. This class will encapsulate all methods required to provide the drawing feature for the application. The attributes of this class are two CPoint objects (representing the start and the end point of the diagram) and the choice of the diagram, whether a line, a rectangle, or an ellipse.

The Draw class interacts with the view class of the application. The events to be trapped while the user chooses any drawing option from the menu are handled by the view class. The view class also traps the required data and passes them to the Draw class, which then paints the original diagram in the client area.

The Draw class also interacts with the application’s document class to facilitate the storage and retrieval of a user’s work.

Now let us get into the details. The application uses an array of the CObArray class, Diag_Count, to store the diagrams created by the user. The array stores objects of the Draw class. The following steps depict the interaction between the Draw class, the view class, and the document class and also the flow of control in the application:

1.When the user chooses an option from the Draw menu, the appropriate event handler, which is coded in the view class, is invoked. For instance, if the user chooses Draw, Line, the OnDrawLine function of the view class is invoked.

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

117

 

 

 

2.The event handler corresponding to the selection traps the choice of the user. For example, if the user’s choice is Line then the variable choice is set to 1.

3.As soon as the user clicks the left mouse button, the control passes onto the OnLButtonDown function, which then traps the starting point of the diagram.

4.When the user moves the mouse, the control passes onto the OnMouseMove function that creates a client DC, and invokes the Diag function of the Draw class. The Diag function checks for your choice and draws the corresponding diagram on the client area.

5.When the user releases the mouse, the OnLButtonUp function is invoked. This function creates an object of the Draw class and invokes the DiagAdd function of the document class. The DiagAdd function then adds the object to the Diag_Count array.

6.When the user chooses File, Save, the Serialize function of the document class is invoked. This function further invokes the Serialize function defined in the Draw class that implements the serialization.

7.When the user chooses File, Open, the Serialize function of the document class is invoked, which further invokes the Serialize function of the

Draw class. After restoring the details, the framework invokes the OnDraw function of the view class.

8.The OnDraw function first traps the total number of diagrams by using the GetDiagCount function of the document class. Then it retrieves each of the Draw objects stored in the Diag_Count array by using the GetDiag

function of the document class. Finally, it invokes the Diag function of the Draw class to paint the corresponding diagram on the client area.

THE SERIALIZATION MACROS

For any CObject derived class to be serialized, it has to use two macros: DECLARE_SERIAL, while declaring the class, and IMPLEMENT_SERIAL, while defining the class. The DECLARE_SERIAL macro accepts the name of the class that has to be serialized as a parameter, and the IMPLEMENT_SERIAL macro accepts the derived class that is to be serialized, its base class, and a version number. Refer to the Draw class, in Listing 5-1, for the usage of these macros.

118

Part I

 

INTRODUCING VC++.NET

 

 

 

 

 

 

Listing 5-1 MDIApp – The Paint Application

 

 

 

 

 

 

//MDIApp.h – The file that contains the declarations for the application class

 

 

#include “resource.h”

 

 

class CMDIAppApp : public CWinApp

 

 

{

 

 

 

public:

 

 

 

CMDIAppApp();

 

 

public:

 

 

 

virtual BOOL InitInstance();

 

 

 

afx_msg void OnAppAbout();

 

 

 

DECLARE_MESSAGE_MAP()

 

 

};

 

 

 

//MDIApp.cpp – The file that contains the definition for the application class

 

 

#include “stdafx.h”

 

 

#include “MDIApp.h”

 

 

#include “MainFrm.h”

 

 

#include “ChildFrm.h”

 

 

#include “MDIAppDoc.h”

 

 

#include “MDIAppView.h”

 

 

BEGIN_MESSAGE_MAP(CMDIAppApp, CWinApp)

ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

END_MESSAGE_MAP()

//The application object creation CMDIAppApp theApp;

BOOL CMDIAppApp::InitInstance()

{

CWinApp::InitInstance();

//Code for registering the application’s document template CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_MDIAppTYPE, RUNTIME_CLASS(CMDIAppDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CMDIAppView));

THE DOCUMENT/VIEW ARCHITECTURE

Chapter 5

119

 

 

 

AddDocTemplate(pDocTemplate);

//Code for creating the application’s frame window CMainFrame* pMainFrame = new CMainFrame;

if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;

m_pMainWnd = pMainFrame; CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo);

if (!ProcessShellCommand(cmdInfo)) return FALSE;

//Code to display the window pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow();

// This function generates the WM_PAINT message to paint the //window on the screen.

return TRUE;

}

//Mainfrm.h – Contains the declaration for your application’s window class class CMainFrame : public CMDIFrameWnd

{

DECLARE_DYNAMIC(CMainFrame)

public:

CMainFrame();

public:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

public:

virtual ~CMainFrame(); protected: // control bar embedded members

CStatusBar m_wndStatusBar;

CToolBar m_wndToolBar;

protected:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); DECLARE_MESSAGE_MAP()

};

//Mainfrm.cpp – Contains the definition of your application’s window class #include “stdafx.h”