- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Structured Exception Handling
- C++ Exception Handling
- MFC Error and Exception Handling
- Summary
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
MFC Error and Exception Handling
This section introduces the exception-handling mechanisms available in MFC. The two available mechanisms are
- C++ exceptions (available only in MFC 3.0 or later)
- MFC exception macros (available in MFC 1.0 and later)
MFC exception macros should be used only if they already reside in existing code. Better yet, when dealing with an older program using MFC exception macros, use C++ exceptions along with the macros.
MFC Exception Macros
MFC versions lower than 3.0 did not support the C++ exception mechanism. MFC provided macros to deal with exceptions. The macros are TRY, CATCH, and THROW. In contrast, the C++ exception keyword equivalents are try, catch, and throw.
Here is a list of the MFC exception macros:
- AND_CATCH
- AND_CATCH_ALL
- CATCH
- CATCH_ALL
- END_CATCH
- END_CATCH_ALL
- THROW
- THROW_LAST
- TRY
THROW
This macro throws the exception to the CATCH block. The program execution is interrupted. If a CATCH block is specified, program control goes to the CATCH block. If not, control is passed to an MFC library module to print an error message and exit.
THROW_LAST
This macro throws a locally created exception. The macro sends the exception back to the next CATCH block. Usually when an exception that was just caught is thrown, it goes out of scope, thus being deleted. THROW_LAST passes the exception correct to the next CATCH handler.
TRY
You use this macro to set up a TRY block, which signifies the block of code where the throwing of exceptions occurs. The exceptions are processed in the CATCH and AND_CATCH blocks. The TRY block is ended with an END_CATCH or END_CATCH_ALL macro.
CATCH
This macro defines a block of code that catches the first exception thrown by a preceding TRY block. The TRY block should end with END_CATCH.
AND_CATCH
You use this macro to catch additional exceptional types thrown from a preceding TRY block. Use the CATCH macro to catch the first exception type, and then use AND_CATCH for every other exception type. The TRY block should end with END_CATCH.
AND_CATCH_ALL
This macro catches additional exception types thrown by a preceding TRY block. Use the CATCH macro to catch the first exception type, and then use AND_CATCH_ALL for all other exception types. The TRY block should end with END_CATCH_ALL.
END_CATCH
This macro signifies the end of the last CATCH or AND_CATCH block.
END_CATCH_ALL
Signifies the end of the last CATCH_ALL or AND_CATCH_ALL block.
Here are some possible program skeletons using these macros:
TRY
{
}
CATCH()
{
}
AND_CATCH()
{
}
END_CATCH
and
TRY
{
}
CATCH_ALL()
{
THROW_LAST();
}
END_CATCH_ALL
This should give you an idea of how these macros go together.
Here is a list of MFC exception-throwing functions:
- AfxThrowArchiveException
- AfxThrowFileException
- AfxThrowMemoryException
- AfxThrowNotSupportedException
- AfxThrowResourceException
- AfxThrowUserException
These functions are explained in the following sections.
AfxThrowArchiveException
This function throws an archive exception by specifying an integer that indicates the reason for the exception stored in its m_cause member. Here are the enumerators that can be returned:
- CArchiveException::badClass—Tried to read an object into an object of the wrong type.
- CArchiveException::badIndex—File format is invalid.
- CArchiveException::badSchema—Tried to read an object with a different version of the class.
- CArchiveException::endOfFile—The end of the file was reached.
- CArchiveException::generic—Error unspecified.
- CArchiveException::none—No error occurred.
- CArchiveException::readOnly—Tried to write to an archive opened for reading.
- CArchiveException::writeOnly—Tried to write to an archive opened for reading.
AfxThrowFileException
This function throws a file exception by specifying an integer that indicates the reason for the exception. The developer is responsible for determining the cause of the error based on the operating-system error code. Here are the possible enumerators that can be returned:
- CFileException::accessDenied—Access to the specified file is denied.
- CFileException::badPath—The path is invalid.
- CFileException::badSeek—An error occurred while trying to set the file pointer.
- CFileException::directoryFull—There are no more directory entries.
- CFileException::diskFull—The disk is full.
- CFileException::endOfFile—The end-of-file was reached.
- CFileException::fileNotFound—The file was not found where specified.
- CFileException::generic—Error unspecified.
- CFileException::hardIO—A hardware error occurred.
- CFileException::invalidFile—The file handle is invalid.
- CFileException::lockViolation—A locked region is trying to be locked again.
- CFileException::none—No error occurred.
- CFileException::removeCurrentDir—The current directory could not be removed.
- CFileException::sharingViolation—A shared region is locked, or the program SHARE.EXE is not loaded.
- CFileException::tooManyOpenFiles—The number of files currently open is too many.
AfxThrowMemoryException
This function throws a memory exception. This function should be called when using memory allocators, such as GlobalAlloc and malloc functions.
AfxThrowNotSupportedException
This function throws an exception when an unsupported feature is requested.
AfxThrowResource
This function throws a resource exception.
AfxThrowResourceException
This function throws a resource exception when an unsupported feature is requested.
AfxThrowUserException
This function throws an exception to stop an end-user operation. AfxMessageBox normally calls this function after it reports an error to the user. The MFC OLE exception functions follow:
- AfxThrowOleDispatchException
- AfxThrowOleException
AfxThrowOleDispatchException
This function throws an exception within an OLE automation.
AfxThrowOleException
This function throws an exception and creates an object of type COleException. The MFC termination function is AfxAbort.
AfxAbort
This function is called internally by the MFC member function when a fatal error occurs. This is the default termination for MFC. AfxAbort usually is called by MFC when an exception occurs that cannot be handled. AfxAbort can be called by the developer when an error is encountered that makes recovery impossible.
Using MFC Exception Macros with C ++ Exception Handling
You can use MFC exception macros and C++ exception keywords in the same program. Again, it is advisable to do this only when MFC exception macros already exist in the program. Always use C++ exception handling to handle exceptions.
Note, however, that you cannot use MFC macros together with C++ exception keywords in the same block. The reason is that the macros automatically delete exception objects when their scope is lost. Caught C++ exception keywords in a catch block have to be explicitly deleted. When MFC macros and C++ exception keywords are mixed, memory leaks can arise if an exception object is not deleted; or, when an exception is deleted twice.
The Advantages of Converting from MFC Exception Macros
It is almost never necessary to convert from MFC exception macros, because they are compatible with even the latest version of MFC. In fact, MFC macros can coincide with C++ exception handling, but there are advantages to converting.
One advantage is that the code that uses C++ exception handling compiles slightly smaller EXEs and COMs. Another reason to convert is that C++ exception-handling keywords are much more versatile: They can handle exceptions of all data types (that can be copied). The macros can handle only exceptions of the class CException and classes derived from it.
With C++ exception handling, the caught exception is deleted only by explicit instruction. Macros delete the caught exception when the exception goes out of scope.
Converting Code from MFC Macros to C++ Exception Handling
Perform the following steps to convert code from macros to C++ exception keywords:
- Find every occurrence of the MFC macros THROW, THROW_LAST, TRY, CATCH, AND_CATCH, and END_CATCH.
- Replace each THROW with throw.
- Replace each THROW_LAST with throw.
- Replace each TRY with try.
- Replace each CATCH with catch.
- Replace each AND_CATCH with catch.
- Delete each END_CATCH.
- Modify each macro argument so that it forms a valid C++ exception declaration.
- Modify each catch block so that it deletes exception objects where necessary.
Not too difficult, really. The only step that may require more explanation is number 8. Consider this example:
CATCH( CException, e )
to
catch( CException* e )
Predefined Exceptions for MFC
Here is a list of predefined exceptions to use the MFC. Each of these exceptions is derived from the base class CException. You can use these with C++ exceptions directly or with the MFC exception macros.
- CArchiveException—A serialization exception condition. These are constructed and thrown from inside CArchive member functions.
- CDAOException—An exception condition from the MFC database classes based on data access objects (DAOs).
- CDBException—An exception condition coming from the database classes.
- CFileException—A file-related exception condition. These objects are constructed and thrown in CFile member functions and in member functions of derived classes.
- CInternetException—An exception condition coming from the Internet classes.
- CMemoryException—A memory exception that signifies an out-of-memory condition. Memory exceptions are thrown new.
- CNotSupportedException—An exception that results from a request of a feature not supported.
- COleDispatchException—Handles exceptions specific to the OLE IDispatch interface.
- COleException—An exception condition from an OLE operation.
- CResourceException—Generated when a resource cannot be found or allocated.
- CUserException—Thrown to stop an end-user operation in the same manner as covered in the earlier section on C++ exception handling, using the throw/catch exception mechanism.
Using CFileException
For a quick introduction, take a look at the following code fragment, which uses CFileException:
//Try Block
try
{
CFile fileNotOpen
fileNotOpen.SeekToBegin();
}
catch(CFileException* e) //Catch the file exceptions
{
if (e->m_cause == CFileException::fileNotFound)
AfxMessageBox("The File has not been opened.");
e->Delete();
}
The try block guards the code to perform file operations. When a CException is raised, the catch block will catch the thrown exception and create the exception class object e. Note that this is very similar to C++ exception examples in the earlier section. Object e now points to any exception that was created. If this exception is equal to fileNotFound, a message appears telling the user that The File has not been opened. The final statement deletes the exception class object.
It is important to delete the exception class objects when you are finished with them. Unlike C++ exception handling, this is not taken care of automatically.
There are a few cause codes besides CFileException:
- CFileException::accessDenied
- CFileException::badpath
- CFileException::badseek
- CFileException::directoryFull
- CFileException::diskFull
- CFileException::endOfFile
- CFileException::fileNotFound
- CFileException::generic
- CFileException::hardIO
- CFileException::invalidFile
- CFileException::lockViolation
- CFileException::none
- CFileException::removeCurrentDir
- CFileException::sharingViolation
- CFileException::tooManyOpenFiles
You can trigger this exception by calling the AfxThrowFileException() function. The function can take three parameters: The first one is required, and the other two are optional.
The first parameter, cause, is a cause code for the exception (listed earlier). It is this code that is placed in the m_cause member in the catch group.
The second parameter, lOsError, is used to specify an operating system error code. The third parameter is strFileName. It gets placed in the m_strFileName member string variable and holds the filename of the file that was being accessed when the error occurred.
Using CMemoryException
The CMemoryException exception is raised when the program simply can no longer allocate any more memory. Recovering from such an error is difficult and unlikely. The memory allocation functions C++ uses will trigger this exception.
This exception can be triggered by calling this function:
AfxThrowMemoryException()
Using CResourceCollection
The CResourceCollection exception is raised when the application can't allocate or find the requested system resources.
This exception can be triggered by calling the AfxThrowResourceException() function.
Using CArchiveException
The CArchiveException object represents a serialization exception condition. The class includes a public data member that contains the cause of the exception.
The m_cause member of the CArchiveException class holds the archive-specific cause codes, as listed here:
- CArchiveException::badClass
- CArchiveException::badIndex
- CArchiveException::badSchema
- CArchiveException::endOfFile
- CArchiveException::generic
- CArchiveException::none
- CArchiveException::readOnly
- CArchiveException::writeOnly
Using CDaoException
The CDaoException is used for DAO-based database access.
You can throw this exception by calling the AfxThrowDaoexception() function. This function has two optional parameters: nAfxDaoError and an OLE scode value. The nAfxDaoError is a DAO error code specific to DAO. The errors it returns are always specific to the DAO itself. The OLE scode value comes from a DAO-based OLE call.
The nAfxDaoError codes can be any from the following list:
- AFX_DAO_ERROR_DFX_BIND
- AFX_DAO_ERROR_ENGINE_INITIALIZATION
- AFX_DAO_ERROR_OBJECT_NOT_OPEN
- NO_AFX_DAO_ERROR
Using OLE Exceptions: COleException and COleDispatchException
There are two OLE exception errors: COleException and COleDispatchException.
The COleException error normally is used for server-side or OLE-specific operations. You can trigger this exception by calling the AfxThrowOleException() function, passing an OLE scode value. This value then is stored in the m_sc member of the exception.
The COleDispatchException class is used in conjunction with OLE IDISPATCH interfaces and is thrown by the AfxThrowOleDispatchException() function. There are two forms to this function.
The first form has three parameters—the first two required, the last one optional. The first parameter is a wCodeWORD value that is an application-specific error code. The second parameter is an lpszDescription string pointer to represent the verbal string for describing the error. The last parameter is a help context ID.
The second form has three parameters as well. The first parameter is a wCodeWORD value that is an application-specific error code. The second parameter is nDescriptionID for a UINT resource code, which represents a verbal string describing the error. The last parameter is a help context ID.
Both forms are nearly identical—the difference is the second parameter.
Using NotSupportedException
The CNotSupportedException object is generated when a request is made for an unsupported feature. You can trigger this exception by calling the AfxThrowNotSupportedException() function.
Using CUserException
You use the CUserException class to generate exception objects for application-specific applications.
You can trigger this exception by calling the AfxThrowNotSupportedException() function.
Summary | Next Section

Account Sign In
View your cart