Tuesday, November 17, 2009

Lab 4.2: Using AppWizard to Create an MFC Application

Lab 4.2: Using AppWizard to Create an MFC Application


 


In this lab, you will create, build, and run a simple MFC application in the Developer Studio development environment using AppWizard.

To see a demonstration that shows what you will accomplish during the lab, click this icon.

F 

Estimated time to complete this lab: 15 minutes

To complete the exercises in this lab, you must have the required software. For detailed information about the labs and setup for the labs, see Labs in this course.

Objectives

After completing this lab, you will be able to:

®  Use AppWizard to create a simple text editor application using MFC.

®  Use Microsoft Developer Studio and Microsoft Visual C++ 5.0 to build and run the application.

 

Prerequisites

There are no prerequisites for this lab.

Exercise

The following exercise provides practice with the concepts and techniques covered in this chapter.

®  Exercise 1: Creating a Simple Text Editor

In this exercise, you will use Microsoft Developer Studio, MFC AppWizard, and Microsoft Visual C++ 5.0 to create, build, and run a simple MFC single document interface (SDI) text editor application.

 



  1. Exercise 1: Creating a Simple Text Editor


In this exercise, you will create a simple text editor using AppWizard. All of the functionality in this application is provided in the classes automatically generated by AppWizard.

       u  Create a new project using AppWizard

       1.   In Developer Studio, on the File menu, click New.

       2.   In the New dialog box, click the Projects tab, and then do the following:

           a.           For the project type, click MFC AppWizard (exe).

           b.           For the project name, type TextEditor.

           c.           Set the location for your project.

           d.           Accept the default platform Win32.

           e.           To create the new project workspace, click OK.

       3.   MFC AppWizard will start. In MFC AppWizard, Step 1, click Single document and English, and then click Next to go to Step 2.

       4.   Since this project needs no database support, accept the default None for database support and click Next to go to Step 3.

       5.   In Step 3, accept None for the document support, clear the ActiveX Controls check box, and then click Next to go to Step 4.

       6.   In Step 4, accept the defaults (Docking toolbar, Initial status bar, Printing and print preview, 3D controls, and four files for the recent file list) and click Advanced. On the Document Template Strings tab, type txt in the File extension box. Click Close, and then click Next to go to Step 5.

       7.   In Step 5, select Yes, please for generating source file comments and select As a shared DLL for MFC support. Click Next to go to Step 6.

       8.   In Step 6, select the CTextEditorView class and change its base class to CEditView. Click Finish to display the New Project Information dialog box summarizing your choices.

       9.   To cause AppWizard to create the application files, click OK.

When AppWizard is finished, you will be returned to Developer Studio. To see the classes that AppWizard created, click the ClassView tab in the Project Workspace window.

 

       u  Build and run the project

       1.   On the Build menu in Developer Studio, click Build TextEditor.exe or press F7. Developer Studio displays the status of the build process as it builds your project.

       2.   After the build is complete, on the Build menu, click Execute TextEditor.exe. The application, TextEditor, will start.

 

At this point, the TextEditor application contains a minimal set of functionality. However, many of the basics are in place: menus, a toolbar, a status bar, and a window frame. You can write text in the window, save it, close the file, reload the file, and create new text files.

You can find the completed code for this exercise in \Labs\Ch04\Lab02\Ex01.


Self-Check Questions


 


       1.   Which of the following statements is true about the relationship between document and views?

F         A.         The documents and views are derived from the CFrameWnd class.

F         B.         In an MFC application, view objects are embedded in their corresponding document classes.

F         C.         The function CDocument::UpdateAllViews works by calling CView::Invalidate for each view attached to it.

F         D.         The view is responsible for displaying, and perhaps modifying, the document, but not for storing the

                                document.

 

       2.   What is the purpose of the GetDocument member function?

F         A.         To be called by the framework when a document is loaded from disk.

FF         B.         To return a list of currently open documents.

F         C.         To return a pointer to the associated document object.

F         D.         To open the document using the common dialog box.

 

       3.   The minimum classes required to create a Window-based MFC application are:

F         A.         CWinApp and CView

F         B.         CView and CDocument

F         C.         CFrameWnd and CWinApp

F         D.         CView and CFrameWnd

 

       4.   When you derive an application class from CWinApp, what function must you override to create your application's main window object?

F         A.         InitInstance

F         B.         Run

F         C.         AddDocTemplate

F         D.         CreateInstance

  

       5.   What is the purpose of the DECLARE_DYNCREATE macro?

F         A.         To enable objects of CObject-derived classes to be created dynamically at run time.

F         B.         To enable objects of any class to be created dynamically at run time.

FF         C.         To dynamically create documents.

F         D.         To dynamically create views.

 

       6.   If the DECLARE_DYNCREATE macro is included in the class declaration, then what must be included in the class implementation?

F         A.         Use IMPLEMENT_ in header file.

FF         B.         Use the RUNTIME_CLASS macro to dynamically create objects.

F         C.         Include the IMPLEMENT_DYNCREATE macro in the class implementation file.

FFF         D.         Call the PreCreateWindow function.

The CView Derived Class

  1. The CView Derived Class
The class CReaderView, derived from CView, is the view class for the Reader application.

CReaderView contains two member functions, GetDocument and OnDraw. The GetDocument member function is used to retrieve a pointer to the associated document as follows:
inline CReaderDoc* CReaderView::GetDocument()
{ return (CReaderDoc*)m_pDocument; }

The OnDraw member function displays the text line by line on the screen. It uses the GetLineList member function to get a pointer to the CStringList object as follows:

CStringList *pLineList = GetDocument()->GetLineList();

Next, a for loop is executed to go through the strings in the list and display them on the screen. This task is accomplished using the TabbedTextOut function as follows:

for(pos = pLineList->GetHeadPosition(); pos != NULL; )
{
strLine = pLineList->GetAt(pos);
pDC->TabbedTextOut(nXPos,nYPos,strLine,0,NULL,0);
pLineList->GetNext(pos);
nYPos +=nYDelta;
}

To see the source code for the files associated with the CReaderView class, click this icon. For easy reference, the segments of code discussed in this section are highlighted in bold.

// ReaderView.h : interface of the CReaderView class

//

/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_READERVIEW_H__7EC9070F_F96E_11D0_B9C5_00AA00688598__INCLUDED_)

#define AFX_READERVIEW_H__7EC9070F_F96E_11D0_B9C5_00AA00688598__INCLUDED_

#if _MSC_VER >= 1000

#pragma once
#endif // _MSC_VER >= 1000

class CReaderView : public CView

{
protected: // create from serialization only
CReaderView();
DECLARE_DYNCREATE(CReaderView)

// Attributes

public:
CReaderDoc* GetDocument();

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CReaderView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL

// Implementation

public:
virtual ~CReaderView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CReaderView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG // debug version in ReaderView.cpp

inline CReaderDoc* CReaderView::GetDocument()
{ return (CReaderDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_READERVIEW_H__7EC9070F_F96E_11D0_B9C5_00AA00688598__INCLUDED_)

// ReaderView.cpp : implementation of the CReaderView class
//

#include "stdafx.h"

#include "Reader.h"

#include "ReaderDoc.h"

#include "ReaderView.h"

#ifdef _DEBUG

#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////

// CReaderView

IMPLEMENT_DYNCREATE(CReaderView, CView)

BEGIN_MESSAGE_MAP(CReaderView, CView)
//{{AFX_MSG_MAP(CReaderView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CReaderView construction/destruction

CReaderView::CReaderView()

{
// TODO: add construction code here

}

CReaderView::~CReaderView()
{
}

BOOL CReaderView::PreCreateWindow(CREATESTRUCT& cs)

{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

/////////////////////////////////////////////////////////////////////////////

// CReaderView drawing

void CReaderView::OnDraw(CDC* pDC)

{
CStringList *pLineList = GetDocument()->GetLineList();
CString strLine;
POSITION pos;
int nXPos=10; int nYPos=10; int nYDelta = 0;

TEXTMETRIC tm;

pDC->GetTextMetrics(&tm);
nYDelta = tm.tmHeight;
for(pos = pLineList->GetHeadPosition(); pos != NULL; )
{
strLine = pLineList->GetAt(pos);
pDC->TabbedTextOut(nXPos,nYPos,strLine,0,NULL,0);
pLineList->GetNext(pos);
nYPos +=nYDelta;
}
TRACE( "nYDelta = %d\n",nYDelta );
}

/////////////////////////////////////////////////////////////////////////////

// CReaderView printing

BOOL CReaderView::OnPreparePrinting(CPrintInfo* pInfo)

{
// default preparation
return DoPreparePrinting(pInfo);
}

void CReaderView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{
// TODO: add extra initialization before printing
}

void CReaderView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{
// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////

// CReaderView diagnostics

#ifdef _DEBUG

void CReaderView::AssertValid() const
{
CView::AssertValid();
}

void CReaderView::Dump(CDumpContext& dc) const

{
CView::Dump(dc);
}

CReaderDoc* CReaderView::GetDocument() // non-debug version is inline

{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CReaderDoc)));
return (CReaderDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CReaderView message handlers

Sample Applications
A short description follows of the sample application related to this chapter. This sample application is located in \Samples\Ch04.

Sample application subdirectory Description of application

\Reader An SDI application built using AppWizard. The application reads strings of text from a file and displays them on the screen.

The CDocument Derived Class


  1. The CDocument Derived Class


The class CReaderDoc, derived from CDocument, is the document class for the Reader application.

CReaderDoc contains a protected member variable, m_LineList, which is of the type CStringList. This member variable is used to store lines of text read from the file. The accessor function for m_LineList is defined as:

CStringList* GetLineList() { return &m_LineList; }



The member function DeleteContents calls the RemoveAll function to remove all the elements from the CStringList as shown in the following code:

virtual void DeleteContents()

{

m_LineList.RemoveAll();

}



The OnOpenDocument uses the CStdioFile to open the file passed in the pointer, lpszPathName, by constructing a CStdioFile object as follows:

CStdioFile file(lpszPathName,CFile::modeRead | CFile::typeText);



The following statement will cause data to be read from the file as long as there is anything to read:

while (file.ReadString(strLine) != NULL)



This statement returns TRUE if anything was read and FALSE if the end of the file was encountered prior to reading any data. After the line is read, the contents of strLine are added to the CStringList as follows:

m_LineList.AddTail(strLine);



To see the source code for the files associated with the CReaderDoc class, click this icon. For easy reference, the segments of code discussed in this section are highlighted in bold.


// ReaderDoc.h : interface of the CReaderDoc class

//

/////////////////////////////////////////////////////////////////////////////


#if !defined(AFX_READERDOC_H__7EC9070D_F96E_11D0_B9C5_00AA00688598__INCLUDED_)

#define AFX_READERDOC_H__7EC9070D_F96E_11D0_B9C5_00AA00688598__INCLUDED_


#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000



class CReaderDoc : public CDocument

{

protected: // create from serialization only

CReaderDoc();

DECLARE_DYNCREATE(CReaderDoc)


// Attributes

public:

CStringList* GetLineList() { return &m_LineList; }

// Operations

public:


// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CReaderDoc)

public:

virtual BOOL OnNewDocument();

virtual void Serialize(CArchive& ar);

virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);

//}}AFX_VIRTUAL


// Implementation

public:

virtual ~CReaderDoc();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif


protected:

CStringList m_LineList;

virtual void DeleteContents() {m_LineList.RemoveAll();}

// Generated message map functions

protected:


//{{AFX_MSG(CReaderDoc)

// NOTE - the ClassWizard will add and remove member functions here.

// DO NOT EDIT what you see in these blocks of generated code !

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};


/////////////////////////////////////////////////////////////////////////////


//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.


#endif // !defined(AFX_READERDOC_H__7EC9070D_F96E_11D0_B9C5_00AA00688598__INCLUDED_)



// ReaderDoc.cpp : implementation of the CReaderDoc class

//


#include "stdafx.h"

#include "Reader.h"


#include "ReaderDoc.h"


#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif


/////////////////////////////////////////////////////////////////////////////

// CReaderDoc


IMPLEMENT_DYNCREATE(CReaderDoc, CDocument)


BEGIN_MESSAGE_MAP(CReaderDoc, CDocument)

//{{AFX_MSG_MAP(CReaderDoc)

// NOTE - the ClassWizard will add and remove mapping macros here.

// DO NOT EDIT what you see in these blocks of generated code!

//}}AFX_MSG_MAP

END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////

// CReaderDoc construction/destruction


CReaderDoc::CReaderDoc()

{

// TODO: add one-time construction code here


}


CReaderDoc::~CReaderDoc()

{

}


BOOL CReaderDoc::OnNewDocument()

{

if (!CDocument::OnNewDocument())

return FALSE;


// TODO: add reinitialization code here

// (SDI documents will reuse this document)


return TRUE;

}



/////////////////////////////////////////////////////////////////////////////

// CReaderDoc serialization


void CReaderDoc::Serialize(CArchive& ar)

{

if (ar.IsStoring())

{

// TODO: add storing code here

}

else

{

// TODO: add loading code here

}

}


/////////////////////////////////////////////////////////////////////////////

// CReaderDoc diagnostics


#ifdef _DEBUG

void CReaderDoc::AssertValid() const

{

CDocument::AssertValid();

}


void CReaderDoc::Dump(CDumpContext& dc) const

{

CDocument::Dump(dc);

}

#endif //_DEBUG


/////////////////////////////////////////////////////////////////////////////

// CReaderDoc commands



BOOL CReaderDoc::OnOpenDocument(LPCTSTR lpszPathName)

{

// Could be a big file

BeginWaitCursor();


// Clear List, this will cleanup the CString objects



DeleteContents();

// Read the file and store as a list

// of CStrings

CStdioFile file(lpszPathName,

CFile::modeRead | CFile::typeText);



CString strLine;

while (file.ReadString(strLine) != NULL)

{

m_LineList.AddTail(strLine);

}


EndWaitCursor();

return TRUE;

}

The CFrameWnd Derived Class


  1. The CFrameWnd Derived Class


The class CMainFrame, derived from CFrameWnd, is the main frame window class for the Reader application. The frame window class defines the borders of the primary window and automatically positions and sizes the view window. It also "manages" the application adornments, such as menus, scroll bars, and toolbars.

Creating Objects Dynamically

The class declaration for CMainFrame includes the DECLARE_DYNCREATE macro to enable objects of CObject derived classes to be created dynamically at run time. DECLARE_DYNCREATE takes one parameter, the name of the class to be created dynamically, as shown in the following code:

class CMainFrame : public CFrameWnd

{

protected:

         CMainFrame();

         DECLARE_DYNCREATE(CMainFrame)

         ....

};

 

If the DECLARE_DYNCREATE macro is included in the class declaration, then the IMPLEMENT_DYNCREATE macro must be included in the class implementation. IMPLEMENT_DYNCREATE takes two parameters, the name of the class to be created dynamically and the name of its base class, as shown in the following code:

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

 

You can then use the RUNTIME_CLASS macro to create an object dynamically as shown in the CReader::InitInstance member function in the Reader.cpp file. The RUNTIME_CLASS macro takes one parameter, the name of the class, as shown in the following code:

pDocTemplate = new CSingleDocTemplate(....

         RUNTIME_CLASS(CReaderDoc),....)

 

Creating the Window

The header file, CMainFrame.h, includes two member functions, PreCreateWindow and OnCreate, and two member variables, m_wndStatusBar and m_wndToolBar.

Before the window is created, the framework calls the PreCreateWindow member function. If you choose to override PreCreateWindow, you can determine whether the styles used in your application's base class provide the functionality you need by using information gathered from the MFC source code. In the following example, the framework simply calls the base class's PreCreateWindow:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{ 

         return CFrameWnd::PreCreateWindow(cs);

} 

 

Creating and Loading the Toolbar

The OnCreate member function creates and loads the toolbar using the member variable m_wndToolBar as follows:

if (!m_wndToolBar.Create(this) ||

                     !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

 

OnCreate creates and sets the status bar by executing the following code:

if (!m_wndStatusBar.Create(this) ||

                     !m_wndStatusBar.SetIndicators(indicators,

                       sizeof(indicators)/sizeof(UINT)))

 

Docking the Toolbar

Finally, three member functions are called to dock the toolbar as shown in the following code:

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

 

The first line of code enables a control bar to be docked. The next line of code enables dockable control bars in a frame window. The last line of code causes a control bar to be docked to the frame window.

To see the source code for the files associated with the CMainFrame class, click this icon. For easy reference, the segments of code discussed in this section are highlighted in bold.


// MainFrm.h : interface of the CMainFrame class

//

/////////////////////////////////////////////////////////////////////////////


#if !defined(AFX_MAINFRM_H__7EC9070B_F96E_11D0_B9C5_00AA00688598__INCLUDED_)

#define AFX_MAINFRM_H__7EC9070B_F96E_11D0_B9C5_00AA00688598__INCLUDED_


#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000


class CMainFrame : public CFrameWnd

{

protected: // create from serialization only

         CMainFrame();

         DECLARE_DYNCREATE(CMainFrame)


// Attributes

public:


// Operations

public:


// Overrides

         // ClassWizard generated virtual function overrides

         //{{AFX_VIRTUAL(CMainFrame)

         virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

         //}}AFX_VIRTUAL


// Implementation

public:

         virtual ~CMainFrame();

#ifdef _DEBUG

         virtual void AssertValid() const;

         virtual void Dump(CDumpContext& dc) const;

#endif


protected:  // control bar embedded members

         CStatusBar  m_wndStatusBar;

         CToolBar    m_wndToolBar;


// Generated message map functions

protected:

         //{{AFX_MSG(CMainFrame)

         afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

                     // NOTE - the ClassWizard will add and remove member functions here.

                     //    DO NOT EDIT what you see in these blocks of generated code!

         //}}AFX_MSG

         DECLARE_MESSAGE_MAP()

};


/////////////////////////////////////////////////////////////////////////////


//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.


#endif // !defined(AFX_MAINFRM_H__7EC9070B_F96E_11D0_B9C5_00AA00688598__INCLUDED_)


// MainFrm.cpp : implementation of the CMainFrame class

//


#include "stdafx.h"

#include "Reader.h"


#include "MainFrm.h"


#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif


/////////////////////////////////////////////////////////////////////////////

// CMainFrame


IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)


BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

         //{{AFX_MSG_MAP(CMainFrame)

                     // NOTE - the ClassWizard will add and remove mapping macros here.

                     //    DO NOT EDIT what you see in these blocks of generated code !

         ON_WM_CREATE()

         //}}AFX_MSG_MAP

END_MESSAGE_MAP()


static UINT indicators[] =

{

         ID_SEPARATOR,           // status line indicator

         ID_INDICATOR_CAPS,

         ID_INDICATOR_NUM,

         ID_INDICATOR_SCRL,

};


/////////////////////////////////////////////////////////////////////////////

// CMainFrame construction/destruction


CMainFrame::CMainFrame()

{

         // TODO: add member initialization code here

        

}


CMainFrame::~CMainFrame()

{

}


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

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

                     return -1;

        

         if (!m_wndToolBar.Create(this) ||

                     !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

         {

                     TRACE0("Failed to create toolbar\n");

                     return -1;      // fail to create

         }


         if (!m_wndStatusBar.Create(this) ||

                     !m_wndStatusBar.SetIndicators(indicators,

                       sizeof(indicators)/sizeof(UINT)))

         {

                     TRACE0("Failed to create status bar\n");

                     return -1;      // fail to create

         }


         // TODO: Remove this if you don't want tool tips or a resizeable toolbar

         m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

                     CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);


         // TODO: Delete these three lines if you don't want the toolbar to

         //  be dockable

         m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

         EnableDocking(CBRS_ALIGN_ANY);

         DockControlBar(&m_wndToolBar);


         return 0;

}


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

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

         //  the CREATESTRUCT cs


         return CFrameWnd::PreCreateWindow(cs);

}


/////////////////////////////////////////////////////////////////////////////

// CMainFrame diagnostics


#ifdef _DEBUG

void CMainFrame::AssertValid() const

{

         CFrameWnd::AssertValid();

}


void CMainFrame::Dump(CDumpContext& dc) const

{

         CFrameWnd::Dump(dc);

}


#endif //_DEBUG


/////////////////////////////////////////////////////////////////////////////

// CMainFrame message handlers

Analyzing a Document/View Application

Analyzing a Document/View Application

Because theory and background information can only take you so far, it's time to look at the implementation of a working document/view application. Analyzing the code for an actual document/view application should help bring into focus the abstract concepts presented earlier.

In this section, you will take a close look at the source code related to document/view architecture. This will help you better understand what is going on behind the scenes in a typical MFC application. (The CAboutDialog class is not discussed since it is not related to document/view and its only purpose in this application is to provide information in the Help About dialog box.)

The following illustration shows the base classes present in most document/view applications and the derived classes for a sample application called Reader, created using AppWizard.



The five main classes for the Reader application appear at the bottom of the preceding illustration and are derived as follows:

® The application class, CReaderApp, is derived from CWinApp.

® The frame window class, CMainFrame, is derived from CFrameWnd.

® The document class, CReaderDoc, is derived from CDocument.

® The view class, CReaderView, is derived from CView.

® The dialog class, CAboutDialog, is derived from CDialog.

For purposes of illustration, some changes have been made to the code automatically generated by AppWizard for this application. You can find the complete code for the Reader application in \Samples\Ch04\Reader.

This section includes the following topics:

The CWinApp Derived Class

The class CReaderApp, which is derived from CWinApp, is the application class for the Reader application. CReaderApp includes the member function InitInstance. The InitInstance function stores the application settings in the registry, creates a document template, registers the document template, and initializes the command line.

Setting the Registry

The InitInstance function causes application settings to be stored in the registry instead of in private .ini files by executing the following statement:

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

If this function has been called, the list of most recently used (MRU) files is also stored in the registry. The registry key is usually the name of a company.

Loading the Application Profile

InitInstance executes the following statement to load the list of most recently used (MRU) files and the last preview state:

LoadStdProfileSettings();

Creating a Document Template

Finally, the InitInstance function creates a document template from the CSingleDocTemplate class by executing the following statements:

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,

RUNTIME_CLASS(CReaderDoc),

RUNTIME_CLASS(CMainFrame),RUNTIME_CLASS(CReaderView));


The CSingleDocTemplate class defines a document template that implements the single document interface (SDI). An SDI application uses the main frame window to display a document. Only one document can be open at a time. A document template defines the relationship between the three main document/view classes:

® The document class, which is used to represent the application's document

® The view class, which displays data from the document class

® The frame window class, which contains the views of the document

The document template also specifies the ID of the resources used with the document type. Resources can include menus, icons, an accelerator table, and strings.

The following statement adds a document template to the list of available document templates that the application maintains:

AddDocTemplate(pDocTemplate);

Initializing the Command Line

The following statements are executed to initialize a CCommandLineInfo object with the values entered on the command line:

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

if (!ProcessShellCommand(cmdInfo))

return FALSE;


The ProcessShellCommand processes the command-line parameter and returns a nonzero value if the shell command is processed successfully. Otherwise, it returns FALSE from InitInstance.

To see the source code for the implementation file associated with the CReaderApp class, click this icon. For easy reference, the segments of code discussed in this section are highlighted in bold.



// Reader.cpp : Defines the class behaviors for the application.

//


#include "stdafx.h"

#include "Reader.h"


#include "MainFrm.h"

#include "ReaderDoc.h"

#include "ReaderView.h"


#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif


/////////////////////////////////////////////////////////////////////////////

// CReaderApp


BEGIN_MESSAGE_MAP(CReaderApp, CWinApp)

//{{AFX_MSG_MAP(CReaderApp)

ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

// NOTE - the ClassWizard will add and remove mapping macros here.

// DO NOT EDIT what you see in these blocks of generated code!

//}}AFX_MSG_MAP

// Standard file based document commands

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

// Standard print setup command

ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////

// CReaderApp construction


CReaderApp::CReaderApp()

{

// TODO: add construction code here,

// Place all significant initialization in InitInstance

}


/////////////////////////////////////////////////////////////////////////////

// The one and only CReaderApp object


CReaderApp theApp;


/////////////////////////////////////////////////////////////////////////////

// CReaderApp initialization


BOOL CReaderApp::InitInstance()

{

// Standard initialization

// If you are not using these features and wish to reduce the size

// of your final executable, you should remove from the following

// the specific initialization routines you do not need.


#ifdef _AFXDLL

Enable3dControls(); // Call this when using MFC in a shared DLL

#else

Enable3dControlsStatic(); // Call this when linking to MFC statically

#endif


// Change the registry key under which our settings are stored.

// You should modify this string to be something appropriate

// such as the name of your company or organization.

SetRegistryKey(_T("Local AppWizard-Generated Applications"));


LoadStdProfileSettings(); // Load standard INI file options (including MRU)


// Register the application's document templates. Document templates

// serve as the connection between documents, frame windows and views.


CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CReaderDoc),

RUNTIME_CLASS(CMainFrame), // main SDI frame window

RUNTIME_CLASS(CReaderView));

AddDocTemplate(pDocTemplate);


// Parse command line for standard shell commands, DDE, file open

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);


// Dispatch commands specified on the command line

if (!ProcessShellCommand(cmdInfo))

return FALSE;


// The one and only window has been initialized, so show and update it.

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();


return TRUE;

}


/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About


class CAboutDlg : public CDialog

{

public:

CAboutDlg();


// Dialog Data

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX };

//}}AFX_DATA


// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

//}}AFX_VIRTUAL


// Implementation

protected:

//{{AFX_MSG(CAboutDlg)

// No message handlers

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};


CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

//{{AFX_DATA_INIT(CAboutDlg)

//}}AFX_DATA_INIT

}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CAboutDlg)

//}}AFX_DATA_MAP

}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

//{{AFX_MSG_MAP(CAboutDlg)

// No message handlers

//}}AFX_MSG_MAP

END_MESSAGE_MAP()


// App command to run the dialog

void CReaderApp::OnAppAbout()

{

CAboutDlg aboutDlg;

aboutDlg.DoModal();

}


/////////////////////////////////////////////////////////////////////////////

// CReaderApp commands

Document/View Fumdamentals

Document/View Fumdamentals

You have learned about The Application Class and The Frame Window Class and the roles these classes play in MFC applications. In this section, you will learn about additional classes that are used primarily in document/view applications.

Five classes or objects represent the architectural components of a document/view application. As an MFC developer, you need to understand the function of each of these components and their interrelationships. To view an animation that shows the relationships between the architectural components of a document/view application, click this icon.

This section includes the following topics:

Introduction to Document/View Architecture

Let's begin our study of document/view with a conceptual overview of the primary objects in its architecture and how they interact with each other. The following illustration shows the document/view architecture for an MFC application.



The application's data is stored in the document object, which is displayed in the view. The view object is a child window sized to fit the frame window and serves as the client area for the parent. The frame window object is the application's top-level window and usually includes a resizing border, a caption bar, a system menu, and Minimize, Maximize, and Close buttons. The arrows in the illustration show the direction of data flow during various application operations.

To view an animation that shows the interaction between the document, view, and frame window objects, click this icon.

You can see that the interaction between these objects is somewhat complex. The interaction will be easier to understand after you learn more about the role each object plays in a running application and write a couple of document/view applications of your own.

The Document Class

In a document/view application, data is stored in a document object represented by a class derived from CDocument. The CDocument class loads, stores, and manages the program's data. It also contains the functions that are used to access and work with the data. To support the close connection between documents and views within the document/view architecture, each document object maintains a list of all the associated views and each view object maintains a pointer to its associated document.

Key Member Functions

A derived CDocument class inherits some important member functions. The following table lists several key CDocument member functions and describes what they do.

Member function Description

GetFirstViewPosition Returns a POSITION value that can be passed to GetNextView to enumerate the document's views.


GetNextView Returns a CView pointer to the next view in the list of views associated with the document.

GetPathName Retrieves the document's file name and path. Returns a null string if the document has not been named.

GetTitle Retrieves the document's title. Returns a null string if the document has not been named.

IsModified Returns a nonzero value if the document contains unsaved data, or 0 if it does not.

SetModifiedFlag Sets or clears the document's modified flag, which indicates whether the document contains unsaved data.

UpdateAllViews Updates all views associated with the document by calling each view's OnUpdate function.

Overridable Member Functions

The CDocument class includes several overridable functions that you can use to customize a document's behavior. The following table lists several key overridable CDocument member functions and describes what they do.

Member function Description

OnNewDocument Called by the framework when a new document is created. Override to initialize the document object before a new document is created.

OnOpenDocument Called by the framework when a document is loaded from disk. Override to initialize the unserialized data members of the document object before a new document is loaded.

DeleteContents Called by the framework to delete the document's contents. Override to free memory and other resources allocated to the document before it is closed.

Serialize Called by the framework to serialize the document to or from a file. Override to provide document-specific serialization code so that your documents can be loaded and saved.

The View Class

The view object physically represents the client area of the application. Logically, it represents a viewport of the information contained in the document class and allows user input through the mouse or keyboard. While a document object can have any number of views associated with it, a view always belongs to just one document.

The CView class provides the basic framework for output to the view window and the printer, and communicates with the associated document. CView defines the basic properties of the view, and the derived view classes add functionality to the basic definition of a view. Classes derived directly from CView can display information in various ways. They are responsible for supplying all their own painting code.

MFC provides a number of view classes that enable your application to display information in many ways without requiring you to write the underlying painting code. For example, CTreeView and CListView, new with Windows 95, comprise the directory tree and file list views in Explorer. In these extended view classes, the painting functionality is self-contained; in most cases, you need only tell the view class how the painting should appear.

Derived View Classes

The following table describes several classes derived from CView and describes what they do.

View class Description

CCtrlView Base class for CEditView, CRichEditView, CListView, and CTreeView. Can be used to derive other views that wrap Windows controls.

CEditView Provides the functionality of a Windows edit control and adds print, search, and search-and-replace.

CRichEditView Provides the functionality of a Windows rich edit control.

CListView Provides the functionality of a Windows list view control.

CTreeView Provides the functionality of a Windows tree view control.

CScrollView Adds scrolling functions to a view. Base class for CFormView and CRecordView.

CFormView Implements scrolling views using controls created from a dialog template.

CRecordView Provides views of a database.

Overridable Member Functions

The CView class includes overridable functions that you can use to customize a view's behavior. The following table lists the key overridable CView member functions and describes what they do.

Member function Description

GetDocument Returns a pointer to the associated document object.

OnDraw Supports Print, Print Preview, and painting on the screen.
OnInitialUpdate Called when a view is first attached to a document. Override to initialize a view of a freshly loaded or created document.

OnUpdate Called when the document's data has changed and the view needs to be updated. Override to implement "as needed" updating, where only the part of the view that has changed is repainted rather than the whole view.

The Document Template Class

The document template base class, CDocTemplate, is the class that binds together the frame, view, document, and a set of application resources. At least one instance of a document class is dynamically created and maintained by the application class. The document template object maintains a list of all document objects because it is responsible for managing their existence. The template further associates various resources with those objects. In most cases, you do not need to modify the behavior of this class.

SDI and MDI

The framework uses two document template classes: CSingleDocTemplate for SDI applications and CMultiDocTemplate for MDI applications.

A CSingleDocTemplate object provides a single document interface (SDI) and can create and own only one document. An SDI application uses the main frame window to display its document. Only one document can be open at a time.

The CSingleDocTemplate constructor takes four arguments:

® A resource ID identifying the various resources that are linked to the document template

® The run-time class of the CDocument derived class

® The run-time class of the view's frame

® The run-time class of the document's view


A CMultiDocTemplate object can create, own, and manage multiple documents of one document type. It provides a multiple document interface (MDI). An MDI application uses the main frame window as a workspace in which the user can open document frame windows.

Note If an application contains both multiple view classes and a single document class, it must have multiple document templates — one for each view class. If an application has multiple document classes and a single view, one document template is required for each pair.

Writing Applications in Non-Document/View









Untitled Document







Writing Applications in Non-Document/View



 



This section describes the basics of non-document/view architecture and analyzes the code from a simple MFC application.


Before the days of document/view architecture, MFC applications had two principal components: an application object representing the application itself and a window object representing the application's window. The application object's primary duty was to create a window, and the window in turn processed messages. In these early versions, MFC simply encapsulated the Windows API and grafted an object-oriented interface onto standard Windows objects, such as menus and dialog boxes.


Most MFC applications are developed in document/view, but it is not required. Document/view applications include an extensive set of starter files and are inherently bigger and more complex than non-document/view applications. In some cases, such as a simple dialog-based application, document/view may not be architecturally appropriate.


When you are first learning about MFC, you may find it useful to look at the non-document/view architecture, because it has fewer layers of code and uses a simpler messaging model. Developers who rely on code-generation tools such as AppWizard are sometimes unfamiliar with some important aspects of MFC architecture and functionality.


This section includes the following topics:





  1. Getting Started in Non-Document/View




The simplest way to create a non-document/view application is by creating a dialog-based application using AppWizard. The resulting application consists of an empty dialog template that must be edited to fit the needs of the application. In the InitInstance function, the dialog box is invoked and, when dismissed, the application will terminate.


The bold section in the following sample code illustrates a key segment of the AppWizard-generated code that instantiates and displays a dialog box object and allows for specific handling based on its return code. To see the sample code, click this icon.



BOOL CNonDocViewApp::InitInstance()


{


         // Standard initialization


         // If you are not using these features and wish to reduce the size


         //  of your final executable, you should remove from the following


         //  the specific initialization routines you do not need.


 


#ifdef _AFXDLL


         Enable3dControls();                           // Call this when using MFC in a shared DLL


#else


         Enable3dControlsStatic();    // Call this when linking to MFC statically


#endif


 


         CNonDocViewDlg dlg;


         m_pMainWnd = &dlg;


         int nResponse = dlg.DoModal();


         if (nResponse == IDOK)


         {


                     // TODO: Place code here to handle when the dialog is


                     //  dismissed with OK


         }


         else if (nResponse == IDCANCEL)


         {


                     // TODO: Place code here to handle when the dialog is


                     //  dismissed with Cancel


         }


 


         // Since the dialog has been closed, return FALSE so that we exit the


         //  application, rather than start the application's message pump.


         return FALSE;


}



After you remove the dialog template and the dialog code in InitInstance, you can create the non-document/view application of your choice.


In Lab 4.1, you will learn how to manually code a Windows-based MFC application without using AppWizard.





  1. Analyzing a Non-Document/View Application




You can see how CWinApp and CFrameWnd classes are implemented by looking at the code for a simple application. As you look at this code, notice how the classes derived from CWinApp and CFrameWnd can be used for writing MFC applications.


The following code generates an application with a window that can be moved, resized, minimized, maximized, and closed.


#include <afxwin.h>



class CMyApp : public CWinApp


{


public:


         virtual BOOL InitInstance ();


};



class CMainFrame : public CFrameWnd


{


};



CMyApp myApp;


 


BOOL CMyApp::InitInstance ()


{


         m_pMainWnd = new CMainFrame;


         ((CMainFrame*)m_pMainWnd)->Create(NULL,"The MFC Application");


         m_pMainWnd->ShowWindow (m_nCmdShow);


         return TRUE;


}


 


Let's look at some key statements, shown in bold in the preceding code, to see how MFC uses the application and frame window classes to perform various functions.


Declaring the Application Object Globally


In a framework application, you don't write WinMain. It is supplied by the class library and is called when the application starts up. An application built on the framework must have one (and only one) object of a class derived from CWinApp. The application object is declared globally at the beginning of the application because it must exist before the framework calls the WinMain function. The following statement globally declares the application object, myApp, for this application:


CMyApp myApp;


 


Creating the Window


To initialize the application, WinMain calls the application object's InitInstance member function. In this application, InitInstance creates the window by instantiating an object from the CMainFrame class.


The following statement dynamically creates a CMainFrame object and assigns its address to the data member, m_pMainWnd, for the application class.


m_pMainWnd = new CMainFrame;



The next statement creates the window by using CFrameWnd::Create. It uses the default window class and gives the window the caption “The MFC Application.”


((CMainFrame*)m_pMainWnd)->Create(NULL,"The MFC Application");


 


Displaying the Window


The following statement displays the window using the ShowWindow member function.


m_pMainWnd->ShowWindow (m_nCmdShow);


 


If the InitInstance function returns 0, WinMain is terminated and the application is shut down. If InitInstance returns a nonzero value, the WinMain function runs the application's message loop by calling the Run member function. The message loop executes until a WM_QUIT message is retrieved from the message queue. Upon termination, WinMain calls the application object's ExitInstance member function.


For more information about the WinMain functions, see the source code file, WinMain.cpp. This file is included with the set of starter files that you get when you use AppWizard to create your application.



Lab 4.1: Hand-Coding a Minimal MFC Application



In this lab, you will create, build, and run a minimal MFC application in the Developer Studio development environment.


To see a demonstration that shows what you will accomplish during the lab, click this icon.


image 


Estimated time to complete this lab: 20 minutes


To complete the exercises in this lab, you must have the required software. For detailed information about the labs and setup for the labs, see Labs in this course.


Objectives


After completing this lab, you will be able to:


®  Create a simple MFC Windows-based application without using wizards.


®  Use Microsoft Developer Studio and Microsoft Visual C++ to build and run the application.


 


Prerequisites


There are no prerequisites for this lab.


Exercise


The following exercise provides practice with the concepts and techniques covered in this chapter.


®  Exercise 1: Creating a Minimal MFC Application


In this exercise, you will use Microsoft Developer Studio and Microsoft Visual C++ to create, build, and run a simple MFC application. This lab gives you first-hand experience in creating a Windows-based application from scratch without using the MFC wizards.


® Exercise 1: Creating a Minimal MFC Application



In this exercise, you will hand-code a minimal MFC application without using wizards.


       u  Create a new project


       1.   In Developer Studio, on the File menu, click New.


       2.   In the New dialog box, click the Projects tab, and then do the following:


           a.           For the project type, click Win32 Application.


           b.           For the project name, type MinimalApplication.


           c.           Set the location for your project.


           d.           Accept the default platform Win32.


       3.   To create the new project workspace, click OK.


 


       u  Add a header file to the project


       1.   In Developer Studio, on the Project menu, point to Add To Project, and then click New.


       2.   In the New dialog box, click the Files tab, and then do the following:


           a.           For the file type, click C/C++ Header File.


           b.           Select the Add To Project check box.


           c.           For the file name, type MinApp.


       3.   To create the new file, click OK.


 


       u  Derive classes from the base classes CWinApp and CFrameWnd


       1.   Include the Afxwin.h file as follows:


#include <afxwin.h>


 


       2.   Publicly derive a CMyApp class from CWinApp. Override the InitInstance member function in the public section of the class as follows:


class CMyApp : public CWinApp


{


public:


    virtual BOOL InitInstance ();


};


 


       3.   Publicly derive a CMainFrame class from CFrameWnd.


class CMainFrame: public CFrameWnd


{


};


 


       4.   Save and close the file.


 


       u  Add an implementation file to the project


       1.   In Developer Studio, on the Project menu, point to Add To Project, and then click New.


       2.   In the New box, click the Files tab, and then do the following:


           a.           For the file type, click C/C++ Source File.


           b.           Select the Add To Project check box.


           c.           For the file name, type MinApp.


       3.   To create the new file, click OK.


 


       u  Write code for the member function


       1.   Include the MinApp.h file as follows:


#include "MinApp.h"


 


       2.   Declare the following variable in your MinApp.cpp file:


CMyApp myApp;


 


       3.   Implement the InitInstance function for the CMyApp class as follows:


BOOL CMyApp::InitInstance ()


{


         m_pMainWnd = new CMainFrame;


         ((CMainFrame*)m_pMainWnd)->Create(NULL,"The MFC Application");


         m_pMainWnd->ShowWindow (m_nCmdShow);


         return TRUE;


}


 


 


       u  Edit the project settings


       1.   In Developer Studio, on the Project menu, click Settings, and then do the following:


           a.           In the Settings for list box, click Win32 Debug.


           b.           Click the General property sheet tab.


           c.           In the Microsoft Foundation Classes combo box, click Use MFC in a Static Library.


This will bind the binary information from the MFC library directly to your program.


       2.   To return to Developer Studio, click OK.


 


       u  Build and run the current project


       1.   In Developer Studio, on the Build menu, click Build MinimalApplication.exe.


       2.   On the Build menu, click Execute MinimalApplication.exe.


 


You can find the completed code for this exercise in \Labs\Ch04\Lab01\Ex01.







Chapter 4: Creating MFC Applications

Chapter 4: Creating MFC Applications

This chapter describes how to create MFC applications in both document/view and non-document/view architecture. Document/view architecture provides many benefits to the MFC developer, not the least of which is that it makes developing applications faster and simpler. However, the set of starter files and classes automatically generated for a document/view application can seem overwhelming and difficult to decipher.

The first part of this chapter shows how to create a simple MFC application without documents and views so that you can gain an understanding of the basic underlying structure in an easy way. The second part of this chapter explains the document/view architecture fundamentals, helps you analyze the source code of a document/view application, and shows how to create a document/view application.

After completing this chapter, you will be able to:

® Describe the classes used in a minimal MFC application.

® Write a non-document/view application without using MFC wizards.

® Describe the classes used in a document/view application.

® Explain how objects in a document/view application interact with each other.

® Create a document/view application based on the single document interface (SDI) application using AppWizard.

Classes in a Minimal MFC Application

MFC applications are not bound to any particular structure. While some classes are uniquely designed to work in conjunction with one another, all classes can be combined in many different ways to create the solution you want. For example, some applications are based on document/view architecture, while others are based on non-document/view architecture or are dialog-based. Regardless of the type of application, virtually all MFC applications use the same two base classes: the application class, CWinApp, and the frame window class, CFrameWnd.

This section describes the purpose of the CWinApp and CFrameWnd classes and explains how to use them in an application. This section includes the following topics:

The Application Class

The application class, CWinApp, represents the application as a whole. CWinApp is the base application class that encapsulates the initialization, running, message mapping, and termination of a Windows-based application. The application class also creates at least one document template object.

An application built on the MFC framework must have one (and only one) object of a class derived from CWinApp. This object is constructed before windows are created, at the same time as other C++ global objects. It is available when Windows calls WinMain, which is supplied by MFC. You must declare the derived CWinApp object at the global level.

To see where CWinApp fits into the object hierarchy, click this icon.



As with any Windows-based program, your MFC application has a WinMain function. In an MFC application, however, you don't write WinMain. It is supplied by the framework and is called when the application starts up.

To view an animation that describes the life cycle of an MFC application, click this icon.

v

What AppWizard Provides

When you create your startup code for a document/view application, AppWizard declares an application class derived from CWinApp. AppWizard also generates an implementation file that contains the following items:

® A message map for the application class

® An empty class constructor

® A variable that declares the one and only application object

® A standard implementation of your InitInstance member function



The standard implementations and message map supplied are adequate for most purposes, but you can modify them as needed for your application. Usually you will add code to the starter code for InitInstance to provide specific functionality to your application. For more information, see Analyzing a Document/View Application in this chapter.

Overridable Member Functions

The following table lists several key overridable CWinApp member functions and describes what they do.

Member function Purpose


InitInstance Creates the document templates that, in turn, create documents, views, and frame windows. InitInstance is the only member function that you must override.

Run After initialization, called by WinMain to process the message loop. A document/view application spends most of its time in the Run member function.

ExitInstance Called each time a copy of your application terminates, usually as a result of a user's quitting an application.

OnIdle Called by the framework when no Windows messages are being processed. Override OnIdle to perform background tasks.



Overriding InitInstance

When you derive an application class from CWinApp, you must override the InitInstance member function to create your application's main window object. Windows allows multiple "copies" of the same program to run at the same time. Each new instance of your application, including the first, is initialized with the information that you place in the overridden InitInstance function.

In general, every Windows-based application has a main window. For this reason, after completing initialization, the framework checks for a pointer to a valid main window (CWinApp:m_pMainWnd) before continuing. If one does not exist, the application terminates.

When you use AppWizard to build an application, AppWizard overrides the default implementation of InitInstance to construct your main window object and sets the m_pMainWnd data member of CWinApp to point to that window.

The Frame Window Class

The frame window class, CFrameWnd, defines the application's physical workspace on the screen and serves as a container for a view. In a single document interface (SDI) application, only one frame window serves as the application's top-level window and frames the view of the document.

CFrameWnd represents the borders of the primary window and automatically positions and sizes the view window. It also "manages" the application adornments, such as the Maximize, Minimize, Save, and Close buttons, the title bar and the title bar icon, the main application menu, the scroll bars, the status bar, and the toolbar.

The CFrameWnd class provides the functionality of a Windows SDI frame window, along with member functions for managing the window. Through a derived class, CMDIChildWnd, the frame window handles multiple document interface (MDI) windows.

To see an illustration that shows where CFrameWnd fits in the object hierarchy, click this icon.



Key Member Functions

The following table lists two key member functions in the CFrameWnd class and describes what they do.

Member function Description

GetActiveView Returns a pointer to the current CView. If there is no current view, returns NULL.


GetActiveDocument Returns a pointer to the current CDocument. If there is no current document, returns NULL.

The Message Map and Message-Handling Functions

Because the CFrameWnd derived class is indirectly derived from CCmdTarget, the derived class can receive and handle command messages. You can specify what happens when messages are directed to the window by implementing message-map and message-handler member functions in the derived class. The message map associates messages with the specific handler functions that handle the messages. For more information about working with the message map, see Chapter 6: Handling Messages.