Home

Microsoft Visual C++/MFC File Processing: Introduction to Files

       

Description

 

Most of the file processing in an MFC application is performed in conjunction with a class named CArchive. The CArchive class serves as a relay between the application and the medium used to either store data or make it available. The CArchive class is an accessory and not an end to itself. As such, it provides its services to the MFC classes that need to perform file transfer.

Although used by MFC, the CArchive class is semi-independent. That is, it is not derived from CObject. It only provides its services to the MFC objects that need archiving. To provide this support, the parent class of MFC objects, CObject, is equipped with a member function named Serialize. The syntax of the CObject::Serialize() member function is:

virtual void Serialize(CArchive& ar);

The CObject::Serialize() member function takes one argument, which is a CArchive reference variable.

This means that the MFC library already provides file processing at a very high level in the hierarchy. This also implies that almost every MFC class is ready to save its value(s) to a medium or to retrieve (an) existing value(s) from a medium. Based on this, to provide file processing for an object in your application, you can simply override the Serialize() member function.

Practical LearningPractical Learning: Introducing MFC's Standard File Processing

  1. To create a new application, on the main menu, click File -> New Project...
  2. In the middle list, click MFC Application
  3. Set the Name to CPAR1
  4. Click OK
  5. In the first page of the MFC Application Wizard, click Next
  6. In the second page of the wizard, click Dialog Box
  7. Click Next
  8. In the third page of the wizard, change the Dialog Title to College Park Auto Repair
  9. Click Next twice
  10. Click Finish
  11. On the dialog box, click TODO: and press Delete
  12. Press the OK button and press Delete
  13. Click the Cancel button to select it
  14. In the Properties window, click Caption, type Close and press Enter
  15. Design the dialog box as follows:
     
    College Park Auto Repair
    Control Caption ID Number Right Align Text
    Static Text Static Text Customer Information ________________      
    Static Text Static Text Customer Name:      
    Edit Control Edit Control   IDC_CUSTOMERNAME    
    Static Text Static Text Phone #:      
    Edit Control Edit Control   IDC_PHONENUMBER    
    Static Text Static Text Car Information ________________      
    Static Text Static Text Make / Model:      
    Edit Control Edit Control   IDC_MAKE    
    Edit Control Edit Control   IDC_MODEL    
    Static Text Static Text Year:      
    Edit Control Edit Control   IDC_YEAR True  
    Static Text Static Text Problem Description      
    Edit Control Edit Control   IDC_PROBLEMDESCRIPTION    
    Static Text Static Text Repair Summary _________________      
    Static Text Static Text Parts Cost:      
    Edit Control Edit Control   IDC_PARTSCOST   True
    Static Text Static Text Labor Cost:      
    Edit Control Edit Control   IDC_LABORCOST   True
    Static Text Static Text Total:      
    Edit Control Edit Control   IDC_TOTAL   True
    Static Text Static Text _________________      
    Static Text Static Text Save Repair Order As:      
    Edit Control Edit Control   IDC_FILESAVE    
    Button Button Open IDC_OPEN_BTN    
    Button Button Reset IDC_RESET_BTN    
    Static Text Static Text Repair Order Name:      
    Edit Control Edit Control   IDC_FILEOPEN    
    Button Button Open IDC_OPEN_BTN    
    Button Button Close IDCANCEL    
  16. Right-click each edit control, click Add Variable, select the category as Value, set the options as follows and click Finish on each:
     
    Control ID Category Variable Type Variable Name
    IDC_CUSTOMERNAME Value CString m_CustomerName
    IDC_PHONENUMBER Value CString m_PhoneNumber
    IDC_MAKE Value CString m_Make
    IDC_MODEL Value CString m_Model
    IDC_YEAR Value int m_Year
    IDC_PROBLEMDESCRIPTION Value CString m_ProblemDescription
    IDC_PARTSCOST Value double m_PartsCost
    IDC_LABORCOST Value double m_LaborCost
    IDC_TOTAL Value CString m_Total
    IDC_FILESAVE Value CString m_FileSave
    IDC_FILEOPEN Value CString m_FileOpen
  17. On the main menu, click Project -> Class Wizard...
  18. From the Commands tab, in the Members list, click IDC_PARTSCOST
  19. In the Messages list, click EN_KILLFOCUS
  20. Click Add Handler...
  21. Set the name to OnPartsCostLostFocus
     
    MFC Class Wizard
  22. Click OK
  23. Click Edit Code
  24. Implement the event as follows:
    void CCPAR1Dlg::OnPartsCostLostFocus()
    {
    	UpdateData(TRUE);
    	m_Total.Format(L"%.2f", m_PartsCost + m_LaborCost);
    	UpdateData(FALSE);
    }
  25. Return to the dialog box
  26. Right-click the Labor Cost edit control and click Add Event Handler...
  27. In the Message Type, select EN_KILLFOCUS
  28. In the Function Handler Name, replace the name with OnLaborCostLostFocus
     
    Event Handler Wizard
  29. Click Add and Edit
  30. Implement the event as follows:
    void CCPAR1Dlg::OnLaborCostLostFocus()
    {
    	OnPartsCostLostFocus();
    }
  31. Return to the dialog box
  32. Double-click the Reset button
  33. Implement the event as follows:
    void CCPAR1Dlg::OnBnClickedResetBtn()
    {
    	m_CustomerName = L"";
    	m_PhoneNumber  = L"";
    	m_Make = L"";
    	m_Model = L"";
    	m_Year = 1960;
    	m_ProblemDescription = L"";
    	m_PartsCost = 0.00;
    	m_LaborCost = 0.00;
    	m_Total = L"";
    	m_FileSave = L"";
    	m_FileOpen = L"";
    
    	UpdateData(FALSE);
    }
 
 
 

Storing an Archive

One of the most regular ways you will use the CArchive class consists of storing or retrieving values through their Serialize() member function. To do this directly and easily in the class, the CArchive class overloads two operators: << and >>.

To store one or more values, the CArchive class provides the << operator. The values you can store are of MFC, BYTE, short, WORD, int, unsigned int, long, LONG, DWORD, float, or double types. The class also provides an exception handler for each kind. Therefore, the syntaxes for this operator for the different data types are:

friend CArchive& operator <<( CArchive& ar, const CObject* pOb );
throw( CArchiveException, CFileException );
CArchive& operator <<( BYTE by );
throw( CArchiveException, CFileException );
CArchive& operator <<( WORD w );
throw( CArchiveException, CFileException );
CArchive& operator <<( int i );
throw( CArchiveException, CFileException );
CArchive& operator <<( LONG l );
throw( CArchiveException, CFileException );			
CArchive& operator <<( DWORD dw );
throw( CArchiveException, CFileException );
CArchive& operator <<( float f );
throw( CArchiveException, CFileException );
CArchive& operator <<( double d );
throw( CArchiveException, CFileException );

As you may have realized, there is only one version of the Serialize() member function. That is, this member function is called once for both storing and retrieving. Therefore, when using it, you must specify what operation you want to perform. This checking process can be performed by calling the CArchive::IsStoring() Boolean member function. Its syntax is:

BOOL IsStoring() const;

This member function returns TRUE if you are storing data. If the answer is then TRUE, you can use the << operator to store each necessary value.

Practical LearningPractical Learning: Archiving Some Values

  1. On the dialog box, double-click the Save button
  2. Implement its event as follows:
    void CCPAR1Dlg::OnBnClickedSaveBtn()
    {
    	UpdateData(TRUE);
    	
    	if( m_CustomerName.GetLength() == 0 )
    	{
    		AfxMessageBox(L"You must enter the name of the customer whose car was repaired.");
    		return;
    	}
    	
    	if( (m_Make.GetLength() == 0) || (m_Model.GetLength() == 0) )
    	{
    		AfxMessageBox(L"You must type the make and model of the car that was repaired.");
    		return;
    	}
    	
    	if( m_FileSave.GetLength() == 0 )
    	{
    		AfxMessageBox(L"You must enter a name for the file to save.");
    		return;
    	}
    
    	CFile fleRepairOrder;
    
    	fleRepairOrder.Open(m_FileSave + L".rpr", CFile::modeCreate | CFile::modeWrite);
    	CArchive ar(&fleRepairOrder, CArchive::store);
    
    	ar << m_CustomerName << m_PhoneNumber << m_Make << m_Model << m_Year
    	   << m_ProblemDescription << m_PartsCost << m_LaborCost << m_Total;
    		
    	ar.Close();
    	fleRepairOrder.Close();
    
    	OnBnClickedResetBtn();
    	UpdateData(FALSE);
    }
  3. Execute the application to test
  4. Enter the Customer Name as Edward Rearson
  5. Enter the Phone # as (301) 105-0448
  6. Enter a Make as Ford
  7. Enter the Model as Taurus
  8. Enter the Year as 2005
  9. Enter the Problem Description as The customer wanted all 4 tires replaced
  10. Enter the Parts Cost as 341.80
  11. Enter the Labor Cost as 95.50
  12. In the Save Repair Order As, type EdwardRearson
     
    College Park Auto Repair
  13. Click Save
  14. Create another repair order before clicking Save
     
    College Park Auto Repair
  15. Close the dialog box and return to your programming environment

Retrieving an Archive

As opposed to storing value(s), to retrieve (a) value(s), the CArchive class provides the >> operator. It comes in the following syntaxes:

friend CArchive& operator >>( CArchive& ar, CObject *& pOb );
throw( CArchiveException, CFileException, CMemoryException );
friend CArchive& operator >>( CArchive& ar, const CObject *& pOb );
throw( CArchiveException, CFileException, CMemoryException );
CArchive& operator >>( BYTE& by );
throw( CArchiveException, CFileException );
CArchive& operator >>( WORD& w );
throw( CArchiveException, CFileException );
CArchive& operator >>( int& i );
throw( CArchiveException, CFileException );
CArchive& operator >>( LONG& l );
throw( CArchiveException, CFileException );
CArchive& operator >>( DWORD& dw );
throw( CArchiveException, CFileException );
CArchive& operator >>( float& f );
throw( CArchiveException, CFileException );
CArchive& operator >>( double& d );
throw( CArchiveException, CFileException );

This indicates that you can retrieve an MFC object, a BYTE, a short, a WORD, an int, an unsigned int, a long, a LONG, a DWORD, a float, or a double value.

As mentioned above, the Serialize() member function is used for both operations. Therefore, when using this member function, you should first check what operation is being performed. This can be done by calling the IsLoading() member function. Its syntax is:

BOOL IsLoading() const;

This member function returns TRUE if you are retrieving a value or some values. If it is true, you can then use the >> operator to retrieve the value(s).

Practical LearningPractical Learning: Reading Values From an Archive

  1. On the dialog box, double-click the Open button
  2. Implement its event as follows:
    void CCPAR1Dlg::OnBnClickedOpenBtn()
    {
    	UpdateData(TRUE);
    	
    	if( m_FileOpen.GetLength() == 0 )
    	{
    		AfxMessageBox(L"You must enter a name for the file to open.");
    		return;
    	}
    
    	CFile fleRepairOrder;
    
    	fleRepairOrder.Open(m_FileOpen + L".rpr", CFile::modeRead);
    	CArchive ar(&fleRepairOrder, CArchive::load);
    
    	ar >> m_CustomerName >> m_PhoneNumber >> m_Make >> m_Model >> m_Year
    	   >> m_ProblemDescription >> m_PartsCost >> m_LaborCost >> m_Total;
    		
    	ar.Close();
    	fleRepairOrder.Close();
    
    	UpdateData(FALSE);
    }
  3. Execute the application to test the dialog box
  4. In the File to Open edit control, enter the name of the file you previously created (BG) and click Open
  5. Close the dialog box and return to your programming environment

Automatic File Processing

Automatic File Processing consists of saving or opening a file with little to no intervention from the user. This technique is used to provide values that should be automatically provided to the user. This technique also allows the user to create or add a new value to a list that appears to be incomplete.

 
 
   
 

Home Copyright © 2010 FunctionX, Inc.