FunctionX - Practical Learning Logo

File Processing and the Document

 

Document/View Architecture File Processing

The MFC library provides a more advanced and elaborate system of file processing in the internals of the document/view architecture through the CDocument class. Although this system is not the easiest and is not shared by other programming environments, once you are familiar with it, you may like.

In the Document/View architecture world, a file or its content is displayed in the view while its real estate is managed by the frame. Therefore, while using a document, the user typically uses the view to manipulate the file. The trick for you is when it becomes time to save the file. Since you shouldn't manipulate the document in the document class (?), when it is time to save it, you must "transfer" the values to be saved from the view to the document class. then let the document class handle the processing of the file. This is valid both for saving and opening the file.

Practical Learning: Processing Files in Document/View

  1. Start a new application as Single Document and name it LoanEval
  2. Base its view class on CFormView
  3. Design the form as follows:
     
    Control ID Caption Additional Properties
    Group Box Group Box   Loan Preparation  
    Static Text Static Text   Prepared By:  
    Edit Box IDC_PREPARED_BY    
    Static Text Static Text   Prepared For:  
    Edit Box IDC_PREPARED_FOR    
    Group Box Group Box   Values  
    Static Text Static Text   Principal:
    Edit Box IDC_PRINCIPAL   Align Text: Right
    Static Text   Interest:
    Edit Box IDC_INTEREST_RATE   Align Text: Right
    Static Text   %  
    Static Text   Periods:  
    Edit Box IDC_PERIODS   Align Text: Center
    Number: True
    Static Text   Years  
    Group Box   Compound Frequency  
    Radio Button IDC_COMPOUND Monthly Group: True
    Left Text: True
    Radio Button   Quarterly Left Text: True
    Radio Button   Semiannually Left Text: True
    Radio Button   Annually Left Text: True
    Group Box      
    Static Text   Interest Earned  
    Edit Box IDC_INTEREST_TOEARN   Align Text: Right
    Static Text   Amount Earned  
    Edit Box IDC_FUTURE_VALUE   Align Text: Right
    Button IDC_CALCULATE_BTN Calculate Default Button: True
    Button IDC_RESET_BTN Reset  
  4. Using either the ClassWizard or the Add Member Variable Wizard, add the following member variables to the controls:
     
    Identifier Type Value Variable
    IDC_PREPARED_BY CString m_PreparedBy
    IDC_PREPARED_FOR CString m_PreparedFor
    IDC_PRINCIPAL double m_Principal
    IDC_INTEREST_RATE double m_InterestRate
    IDC_PERIODS UINT m_Periods
    IDC_COMPOUND int m_Compound
    IDC_INTEREST_TOEARN double m_InterestToEarn
    IDC_FUTURE_VALUE double m_FutureValue
  5. Change the design of the IDR_MAINFRAME icon as follows:
     
  6. In the header file of the document class, declare a variable for each value that will be used in file processing:
     
    // LoanEvalDoc.h : interface of the CLoanEvalDoc class
    //
    /////////////////////////////////////////////////////////////////////////////
    
    . . .
    
    
    class CLoanEvalDoc : public CDocument
    {
    protected: // create from serialization only
    	CLoanEvalDoc();
    	DECLARE_DYNCREATE(CLoanEvalDoc)
    
    // Attributes
    public:
    	CString    strEmployee;
    	CString	strCustomer;
    	double	Principal;
    	double	InterestRate;
    	UINT        Periods;
    	int	Compound;
    
    // Operations
    public:
    
    . . .
                  
    };
    
    . . .
                     
  7. To prepare the file for processing, access the Serialize() event of the document and change it as follows:
     
    void CLoanEvalDoc::Serialize(CArchive& ar)
    {
    	if (ar.IsStoring())
    	{
    		ar << strEmployee << strCustomer << Principal 
    		   << InterestRate << Periods << Compound;
    	}
    	else
    	{
    		ar >> strEmployee >> strCustomer >> Principal 
    		   >> InterestRate >> Periods >> Compound;
    	}
    }
  8. Access the StdAfx.h header file and include the math.h header file:
     
    . . .
                    
    #define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
    
    #include <afxwin.h>         // MFC core and standard components
    #include <afxext.h>         // MFC extensions
    #include <afxdisp.h>        // MFC Automation classes
    #include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
    #ifndef _AFX_NO_AFXCMN_SUPPORT
    #include <afxcmn.h>			// MFC support for Windows Common Controls
    #endif // _AFX_NO_AFXCMN_SUPPORT
    
    #include <math.h>
    
    . . .
    
    
  9. Generate a BN_CLICKED message for the the IDC_CALCULATE_BTN control associated with the view class and accept the suggested name of the function
  10. Implement it as follows:
     
    void CLoanEvalView::OnCalculateBtn() 
    {
    	// TODO: Add your control notification handler code here
    	UpdateData();
    	double InterestToEarn;
    	double FutureValue;
    	int CompoundType;
    	
    	switch( m_Compound )
    	{
    	case 0:
    		CompoundType = 12;
    		break;
    	case 1:
    		CompoundType = 4;
    		break;
    	case 2:
    		CompoundType = 2;
    		break;
    	case 3:
    		CompoundType = 1;
    		break;
    	}
    	
    	double i = (m_InterestRate / 100) / CompoundType;
    	int n    = CompoundType * m_Periods;
    
    	FutureValue    = m_Principal * pow(1 + i, n);
    	InterestToEarn = FutureValue - m_Principal;
    
    	CWnd *edtInterestToEarn = reinterpret_cast<CEdit *>(
    					GetDlgItem(IDC_INTEREST_TOEARN));
    	CWnd *edtFutureValue    = reinterpret_cast<CEdit *>(
    					GetDlgItem(IDC_FUTURE_VALUE));
    
    	char InterestAmount[20], FValue[20];
    	sprintf(InterestAmount, "%.2f", InterestToEarn);
    	sprintf(FValue, "%.2f", FutureValue);
    
    	edtInterestToEarn->SetWindowText(InterestAmount);
    	edtFutureValue->SetWindowText(FValue);
    }
  11. Generate a message for the ID_FILE_SAVE menu item associated with the view class and accept the suggested name of the function
  12. Implement it as follows:
     
    void CLoanEvalView::OnFileSave() 
    {
    	// TODO: Add your command handler code here
    	this->UpdateData();
    	CLoanEvalDoc *pDoc = GetDocument();
    
    	pDoc->strEmployee  = this->m_PreparedBy;
    	pDoc->strCustomer  = this->m_PreparedFor;
    	pDoc->Principal    = this->m_Principal;
    	pDoc->InterestRate = this->m_InterestRate;
    	pDoc->Periods      = this->m_Periods;
    	pDoc->Compound     = this->m_Compound;
    
    	CFile flLoan;
    
    	char strFilter[] = { "Loan Files (*.onf)|*.onf|Text Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
    
    	CFileDialog FileDlg(FALSE, ".bcr", NULL, 0, strFilter);
    
    	if( FileDlg.DoModal() == IDOK )
    	{
    		flLoan.Open(FileDlg.GetFileName(), CFile::modeCreate | CFile::modeWrite);
    		CArchive ar(&flLoan, CArchive::store);
    		pDoc->Serialize(ar);
    
    		ar.Close();
    	}
    	else
    		return;
    
    	flLoan.Close();
    }
  13. Generate a message for the ID_FILE_OPEN menu item associated with the view class and accept the suggested name of the function
  14. Implement it as follows:
     
    void CLoanEvalView::OnFileOpen() 
    {
    	// TODO: Add your command handler code here
    	UpdateData();
    	CLoanEvalDoc *pDoc = GetDocument();
    
    	CFile flLoan;
    
    	char strFilter[] = { "BCR Files (*.onf)|*.onf|Text Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
    
    	CFileDialog FileDlg(FALSE, ".bcr", NULL, 0, strFilter);
    
    	
    	if( FileDlg.DoModal() == IDOK )
    	{
    		if( flLoan.Open(FileDlg.GetFileName(), CFile::modeRead) == FALSE )
    			return;
    		CArchive ar(&flLoan, CArchive::load);
    		pDoc->Serialize(ar);
    
    		m_PreparedBy.Format("%s", pDoc->strEmployee);
    		m_PreparedFor.Format("%s", pDoc->strCustomer);
    		m_Principal    = pDoc->Principal;
    		m_InterestRate = pDoc->InterestRate;
    		m_Periods      = pDoc->Periods;
    		m_Compound     = pDoc->Compound;
    
    		ar.Close();
    	}
    	else
    		return;
    
    	flLoan.Close();
    	UpdateData(FALSE);
    }
  15. Access the frame's source file to remove the default title and set your own as follows:
     
    // MainFrm.cpp : implementation of the CMainFrame class
    //
    
    . . .
    
    /////////////////////////////////////////////////////////////////////////////
    // CMainFrame construction/destruction
    
    . . .
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    		return -1;
    	
    	. . .
    	
    	this->SetWindowText("Loan Evaluation");
    	this->CenterWindow();
    
    	return 0;
    }
    
    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
    {
    	if( !CFrameWnd::PreCreateWindow(cs) )
    		return FALSE;
    
    	cs.style &= ~FWS_ADDTOTITLE;
    
    	return TRUE;
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // CMainFrame diagnostics
    
    . . .
    
  16. Execute the application then create and save a record
     

MFC File Processing Options

In the above example, we used the CFile class to discuss file processing. MFC provides more extended file processing support than that. In reality, file processing is one of the strengths of MFC. It excels in it by providing the following classes:

FILE: FILE is a C structure used to perform file processing for that language. You can also use it in your MFC applications.

CStdioFile: MFC provides the same file processing support as the C language through the CStdioFile class.

Win32: The Win32 library provides its own mechanism of file processing through its HANDLE concept. A file is created using the CreateFile() function.

 

Copyright © 2004-2010 FunctionX, Inc.