Programming Microsoft Visual C++

The EX17A example is similar to example EX16B. The student dialog and the toolbar are the same, and the view class is the same. Serialization has been added, together with an update command UI function for File Save. The header and implementation files for the view and document classes will be reused in example EX18A in the next chapter.

All the new code (code that is different from EX16B) is listed, with additions and changes to the AppWizard-generated code and the ClassWizard code in boldface. A list of the files and classes in the EX17A example is shown in the following table.

Header File Source Code FileClassDescription
ex17a.hex17a.cppCEx17aAppApplication class (from AppWizard)
  CAboutDlgAbout dialog
MainFrm.hMainFrm.cppCMainFrameSDI main frame
StuDoc.hStuDoc.cppCStudentDocStudent document
StuView.hStuView.cppCStudentViewStudent form view (from EX16B)
Student.hStudent.cppCStudentStudent record
StdAfx.hStdAfx.cpp Precompiled headers (with afxtempl.h included)

CStudent

The EX17A Student.h file is almost the same as the file in the EX16A project. (See Figure 16-2.) The header contains the macro

DECLARE_SERIAL(CStudent)

instead of

DECLARE_DYNAMIC(CStudent)

and the implementation file contains the macro

IMPLEMENT_SERIAL(CStudent, CObject, 0)

instead of

IMPLEMENT_DYNAMIC(CStudent, Cobject)

The virtual Serialize function has also been added.

CEx17aApp

The application class files, shown in Figure 17-4, contain only code generated by AppWizard. The application was generated with a default file extension and with the Microsoft Windows Explorer launch and drag-and-drop capabilities. These features are described later in this chapter.

To generate additional code, you must do the following when you first run AppWizard: in the AppWizard Step 4 page, click the Advanced button. When the Advanced Options dialog appears, you must enter the filename extension in the upper-left control, as shown here.

This ensures that the document template resource string contains the correct default extension and that the correct Explorer-related code is inserted into your application class InitInstance member function. You can change some of the other resource substrings if you want.

The generated calls to Enable3dControls and Enable3dControlsStatic in CEx17aApp::InitInstance are not necessary with Microsoft Windows 95, Microsoft Windows 98, or Microsoft Windows NT 4.0. These two functions support an older DLL that is shipped with Microsoft Windows 3.51.

EX17A.H

// ex17a.h : main header file for the EX17A application // #if !defined(AFX_EX17A_H__1A036EA3_821A_11D0_8FE2_00C04FC2A0C2__INCLUDED_) #define AFX_EX17A_H__1A036EA3_821A_11D0_8FE2_00C04FC2A0C2__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifndef __AFXWIN_H__ #error include `stdafx.h' before including this file for PCH #endif #include "resource.h" // main symbols /////////////////////////////////////////////////////////////////////// // CEx17aApp: // See ex17a.cpp for the implementation of this class // class CEx17aApp : public CWinApp { public: CEx17aApp(); // Overrides // ClassWizard generated virtual function overrides //AFX_VIRTUAL // Implementation //AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////// // // // Microsoft Visual C++ will insert additional declarations // immediately before the previous line. #endif // !defined(AFX_EX17A_H__1A036EA3_821A_11D0_8FE2_00C04FC2A0C2__INCLUDED_)

EX17A.CPP

// ex17a.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "ex17a.h" #include "MainFrm.h" #include "StuDoc.h" #include "StuView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////////////////////////// // CEx17aApp BEGIN_MESSAGE_MAP(CEx17aApp, CWinApp) //AFX_MSG_MAP // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP() /////////////////////////////////////////////////////////////////////// // CEx17aApp construction CEx17aApp::CEx17aApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } /////////////////////////////////////////////////////////////////////// // The one and only CEx17aApp object CEx17aApp theApp; /////////////////////////////////////////////////////////////////////// // CEx17aApp initialization BOOL CEx17aApp::InitInstance() { AfxEnableControlContainer(); // 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(CStudentDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CStudentView)); AddDocTemplate(pDocTemplate); // Enable DDE Execute open EnableShellOpen(); RegisterShellFileTypes(TRUE); // 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(); // Enable drag/drop open m_pMainWnd->DragAcceptFiles(); 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 // Implementation protected: //AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //AFX_MSG_MAP END_MESSAGE_MAP() // App command to run the dialog void CEx17aApp::OnAppAbout() { CAboutDlg aboutDlg; aboutDlg.DoModal(); } /////////////////////////////////////////////////////////////////////// // CEx17aApp commands

Figure 17-4. The CEx17aApp class listing.

CMainFrame

The main frame window class code, shown in Figure 17-5, is almost unchanged from the code that AppWizard generated. The overridden ActivateFrame function and the WM_DROPFILES handler exist solely for trace purposes.

MAINFRM.H

// MainFrm.h : interface of the CMainFrame class // /////////////////////////////////////////////////////////////////////// #if !defined(AFX_MAINFRM_H__1A036EA7_821A_11D0_8FE2_00C04FC2A0C2__INCLUDED_) #define AFX_MAINFRM_H__1A036EA7_821A_11D0_8FE2_00C04FC2A0C2__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 // 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 DECLARE_MESSAGE_MAP() }; /////////////////////////////////////////////////////////////////////// // // Microsoft Visual C++ will insert additional declarations // immediately before the previous line. #endif // !defined(AFX_MAINFRM_H__1A036EA7_821A_11D0_8FE2_00C04FC2A0C2__INCLUDED_)

MAINFRM.CPP

// MainFrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "ex17a.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 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 void CMainFrame::ActivateFrame(int nCmdShow) { TRACE("Entering CMainFrame::ActivateFrame\n"); CFrameWnd::ActivateFrame(nCmdShow); } void CMainFrame::OnDropFiles(HDROP hDropInfo) { TRACE("Entering CMainFrame::OnDropFiles\n"); CFrameWnd::OnDropFiles(hDropInfo); }

Figure 17-5. The CMainFrame class listing.

CStudentDoc

The CStudentDoc class is the same as the CStudentDoc class from the previous chapter (shown in Figure 16-4) except for four functions: Serialize, DeleteContents, OnOpenDocument, and OnUpdateFileSave.

Serialize

One line has been added to the AppWizard-generated function to serialize the document's student list, as shown here:

/////////////////////////////////////////////////////////////////////// // CStudentDoc serialization void CStudentDoc::Serialize(CArchive& ar) { TRACE("Entering CStudentDoc::Serialize\n"); if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } m_studentList.Serialize(ar); }

DeleteContents

The Dump statement is replaced by a simple TRACE statement. Here is the modified code:

void CStudentDoc::DeleteContents() { TRACE("Entering CStudentDoc::DeleteContents\n"); while (m_studentList.GetHeadPosition()) { delete m_studentList.RemoveHead(); } }

OnOpenDocument

This virtual function is overridden only for the purpose of displaying a TRACE message, as shown below.

BOOL CStudentDoc::OnOpenDocument(LPCTSTR lpszPathName) { TRACE("Entering CStudentDoc::OnOpenDocument\n"); if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; // TODO: Add your specialized creation code here return TRUE; }

OnUpdateFileSave

This message map function grays the File Save toolbar button when the document is in the unmodified state. The view controls this state by calling the document's SetModifiedFlag function, as shown here:

void CStudentDoc::OnUpdateFileSave(CCmdUI* pCmdUI) { // Disable disk toolbar button if file is not modified pCmdUI->Enable(IsModified()); }

CStudentView

The code for the CStudentView class comes from the previous chapter. Figure 16-5 shows the code.

Testing the EX17A Application

Build the program and start it from the debugger, and then test it by typing some data and saving it on disk with the filename Test.17a. (You don't need to type the .17a.)

Exit the program, and then restart it and open the file you saved. Did the data you typed come back? Take a look at the Debug window and observe the sequence of function calls. Is the following sequence produced when you start the application and open the file?

Entering CStudentDoc constructor Entering CStudentView constructor Entering CStudentDoc::OnNewDocument Entering CStudentDoc::DeleteContents Entering CStudentView::OnInitialUpdate Entering CStudentView::OnUpdate Entering CMainFrame::ActivateFrame Entering CStudentDoc::OnOpenDocument Entering CStudentDoc::DeleteContents Entering CStudentDoc::Serialize Entering CStudent::Serialize Entering CStudent::Serialize Entering CStudent::Serialize Entering CStudentView::OnInitialUpdate Entering CStudentView::OnUpdate Entering CMainFrame::ActivateFrame

Категории