Professional Documents
Culture Documents
Introduction
The Microsoft foundation Class library (MFC) and Visual C++ provides an environment you can use to easily create a wide variety of applications. This Chapter discusses the various class types and primary architecture that is used in most applications. It introduces the MFC class hierarchy and explains the flow of a typical MFC application. It also explains grouping MFC classes according to specific functions and important features of CObject class. In this chapter we will see how to customize application by overriding CWinApp functions such as InitInstance, Run, ExitInstance and OnIdle. Finally this chapter discusses about message maps, the various macros involved and how it works.
Page 16
Incoming Messages
WM_PAINT WM_PAINT WM_KEYDOWN WM_KEYDOWN WM_COMMAND WM_COMMAND WM_SIZE WM_SIZE WM_LBUTTONDOWN WM_LBUTTONDOWN
Appln3 MessageQueue
Application Message Queue Retrieved Messages WinMain Message Loop Dispatched Messages Message MessageHandler Handler Message MessageHandler Handler Message MessageHandler Handler
Application
Window Procedure
Send Message
Classification of MFC
Features of CObject Application Architecture classes
Page 17
User Interface Classes Database Classes General Purpose classes Global Afx functions.
MFC contains nearly 250 classes. Some of these classes are used directly, while others serve as base classes for your own classes.
Features of CObject
By taking a look at the class hierarchy chart, it can be seen that majority of the classes are directly or indirectly derived from CObject. CObject provides following three features:
Serialization support Run-time class information support Diagnostic and debugging support
Serialization Support
Serialization is a process by which objects archive themselves to and from a storage object such as a file on the disk. CObject includes two member functions that play a role in serialization: IsSerializable and Serialize. The IsSerializable function tests whether object is eligible for serialization. It returns TRUE if an object supports serialization, and FALSE if it does not. Serialize serializes the objects data members to a storage medium represented by a CArchive object.
Page 18
CObjects other benefits are : it overloads the new and delete operators to provide protection against memory leaks.
The application architecture classes represent the basic architectural elements of a program and include CWinApp, CDocument, CCmdTarget and CWinThread. These classes are first instantiated when application starts and they have significant responsibilities.
CWinApp
CWinApp represents the application itself. Virtually all MFC applications derive a class from CWinApp. An application object provides member functions for initializing your application and each instance of the application. It also provides member function for running the application. It encapsulates the WinMain() function of SDK. This application object used by MFC program provides a higher level of abstraction for the developer. This is done by encapsulating all the repetitive code like WinMain(), message loop etc. The application begins with the construction of application object and terminates when application object is destroyed.
CDocument
The CDocument class defines the basic characteristics of the document objects used to store data in document/view applications. CDocument provides some important member functions including IsModified for determining whether a document has been modified since it was last saved, and UpdateAllViews for updating the views of a document when the documents data changes. CDocument overriddables such as DeleteContents and OnNewDocument enable a derived document class to be customized to work in cooperation with the framework. Another of CDocuments new features is the OnFileSendMail function, which sends a mail message with the document attached to it.
CCmdTarget
Most of the application architecture classes are derived from CCmdTarget, which contributes function and data members that transform the class into a command target capable of receiving and processing messages. To use a message map, a class must be
Page 19
CWinThread
Encapsulates threading capabilities of the operating system. Member functions enable MFC programs to create and manipulate threads.
User-Interface Classes
The User-Interface classes encompass the elements of a Window-based application that are visible to the user. These include windows, dialog boxes, menus and controls. They also encapsulate the Windows device context and graphic device interface (GDI) drawing objects.
Window classes
MFCs CWnd class encapsulates the properties of a window. CFrameWnd and CMDIFrameWnd, which model the behavior of top-level windows containing menus, toolbars, and other objects; CView, which forms the foundation for views in the document/view applications; CDialog, which encapsulates dialog boxes, and the MFC control classes corresponding to push buttons, list boxes and other objects.
GDI Classes
GDI stands for Graphics Device Interface and is the component of Windows responsible for output to screens, printers and other devices. MFCs CDC class encapsulates the functionality of the Windows device context, which links an application to a screen, printer or the other output device and allows GDI output functions to be executed. CDC derivatives such as CPaintDC, CClientDC and CWindowDC are special cases of the more generic CDC class. CPaintDC automatically calls the BeginPaint and EndPaint API functions from its constructor and destructor. CMetaFileDC provides a wrapper for GDI metafiles - files in which drawing command are recorded and later played back to do the actual drawing. CGdiObject is the base class for MFCs representation of the GDI objects such as CPen, CBrush, etc. Other classes derived from CGdiObject include CBitmap, which represents bitmaps; CPalette, which represents color palettes and CRgn, which encapsulates GDI objects known as regions - areas on the screen defined by combining rectangles, polygons, ellipses, and other shapes.
Page 20
Database Classes
MFC generalizes the interface to database management system fitted with Open Database Connectivity (ODBC) drivers through the CDatabase and CRecordSet classes. CDatabase represents an ODBC connection to a data source, and CRecordSet represents a set of records in that data source. The CRecordView class further simplifies database operations by connecting a recordset object to a dialog-like form view that displays the values of the fields in the current record. The helper class CLongBinary provides an abstract representation of large binary objects such as bitmaps. When it encounters a CLongBinary object implemented as a data member in a recordset object, MFCs record field exchange (RFX) mechanism allocates memory to store the object and loads it from the database. This prevents the programmer from having to supply special logic to read and write database fields that dont fit nearly into a predefined data type. Data Access Object (DAO) classes encapsulate the OLE interface to the Microsoft Jet database engine that serves Microsoft Access. CDaoDatabase represents an open DAO database, and CDaoWorkspace represents a workspace containing a collection of CDaoDatabase objects. Jet databases can also be accessed through MFCs ODBC classes, but the DAO classes offer richer interfaces than their ODBC counterparts and may deliver superior performance because DAO member functions travel through fewer layers before reaching the underlying database engine. In general, the DAO classes are ideal for accessing small, locally stored Microsoft Access Databases, while the ODBC classes are useful for accessing any database served by an ODBC driver.
A no. of general purpose classes in MFC do not encapsulates the Windows API.
Page 21
File Classes
MFCs CFile class provides an object-oriented interface to files by taking standard file I/O functions such as Read and Write and implementing them in the context of file objects. CFile also serves as the base class for other classes including CMemFile, which represents files that are stored in memory rather than on disk. COleStreamFile, which maps CFile functions to functions in the OLE IStream interface. CSocketFile, which can be combined with a CArchive object to serialize objects over networks using Windows sockets; and CStdioFile, which supports buffered file I/O in text and binary modes.
Exception Classes
CException is an abstract base class from which an assortment of MFC exception classes designed for use with C++s try/ throw/ catch exception handling mechanism are derived. CFileException, describes exceptions generated by file operations. Other exception classes include CMemoryException for out-of-memory errors, CArchiveException for archive errors, COleException for OLE errors and CResourceException for errors loading and creating Windows resources. AfxThrowFileException and AfxThrowMemoryException aid applications in throwing exceptions.
Page 22
A group of classes known as the MFC collection classes provides class library support for common data structures such as arrays and linked lists. CByteArray, CPtrArray, CStringArray, and other array classes implement arrays that can be sized dynamically. Array classes are ideal for storing document data. List classes such as CStringList and CObList implement MFC versions of the doubly linked lists, whose members contain pointers to the next and previous elements in the list. Map classes support cables of datatypes keyed by other datatypes.
Miscellaneous Classes
MFC includes a number of general-purpose classes to represent simple data types such as points and rectangles and more complex datatypes such as strings. E.g. CPoint, CSize, CRect, CTime, CTimeSpan. CPoint and CRect classes are mostly used. CTime represents absolute times and dates and includes a useful static function named GetCurrentTime that returns a CTime object initialized with current date and time.
Page 23
AfxGetInstanceHandle Returns the handle identifying the current application instance. AfxGetAppName
CWinApp Overridables
The CWinApp class is the base class from which you derive a Windows application object. An application object provides member functions for initializing your application (and each instance of it) and for running the application. InitInstance is just one of several virtual CWinApp member functions you can override to customize the behavior of the application object. ExitInstance is useful for cleaning up before an application terminates. If you use InitInstance to allocate memory or other resources, ExitInstance is the perfect place to deallocate those resources. The default implementation of ExitInstance saves certain program settings in document/view applications and performs some routine cleanup chores required by the framework. The value returned by ExitInstance is the exit code returned by WinMain. Other CWinApp overridables include OnIdle, Run and PreTranslateMessage. OnIdle is used for performing background-processing chores such as spooling a document to a printer or performing garbage collection on in-memory data structures. Because OnIdle is called when an application is idle that is when there are no message waiting- it provides an excellent mechanism for performing low priority background tasks without spawning a separate thread of execution. Run can be overridden to customize the message loop by replacing it with a message loop of your own. If you want to perform some specialized preprocessing on certain messages before they are dispatched to the program, you can override PreTranslateMessage.
WinMain() in MFC
MFC provides several raw global functions along with a predefined WinMain() function for the
Page 24
framework (as a global C++ function) The class library uses the function name AfxWinMain(). Initializations (including creating the main application thread and setting several window and object handles) are made in AfxWinInit() , a global C++ function found in APPINIT.CPP Next comes the main Application entry point - the point at which the global code activates the application object, just before it takes control of the process: CWinApp::InitInstance(). You can override and tap into this method for custom application intialization. After asserting the application object pointer is valid, the applications message pump is started with a call to the CWinApp:: Run() method . nReturnCode = pApp - > Run ( ); This is where MFC hides its comprehensive application message loop : the message pump.
CWinApp :: ExitInstance( )
Page 25
The PeekMessage() Win32 API function is used to retrieve messages during the long process of an applications run . PeekMessage() is used for running operations in the background ; it uses the PM_NOREMOVE macro to specify that the messages are not to be removed from the queue after processing . The phase 1 loop then calls CWinApp : : OnIdle() to utilize any application idle time for other duties like Updating menu items and toolbar buttons and cleaning up internal data structures.
Page 26
if(m_msgCur.message != WM_KICKIDLE && ! PrevTranslateMessage ( m_msgCur)) { :: TranslateMessage ( &m_msgCur); :: DispatchMessage( &m_msgCur); } return TRUE ; }
BEGIN_MESSAGE_MAP begins the message map and identifies both the class to which the message map belongs and the base class. END_MESSAGE_MAP ends the message map. In between these two macros are macros identifying message map entries. ON_WM_PAINT is a macro defined in the MFC header file Afxmsg_.h, which adds an entry for WM_PAINT messages to the message map. MFC provides macros for more than 100 Windows messages ranging from WM_ACTIVATE to WM_WININICHANGE. To process a message for which MFC does not provide a message-map macro, create an entry for the message using the ON_MESSAGE macro, which accepts two parameters - the message ID and the address of the corresponding class member function. The following statement maps WM_SETTEXT messages to a member function named OnSetText ON_MESSAGE (WM_SETTEXT, OnSetText) Other special-purpose message-map macros provided by MFC include ON_COMMAND, which maps menu selections and other user-interface (UI) events to class member functions,
Page 27
ON_UPDATE_COMMAND_UI, which correlates menu items and toolbar buttons with special update handlers that keep UI object in sync with other elements of the application. afx_msg void OnPaint ( ); DECLARE_MESSAGE_MAP ( ) afx_msg is a visual reminder that OnPaint is a message handler. You can omit it if youd like because it reduces to whitespace when its complied. The term afx_msg is meant to connote a function that behaves as a virtual function does but without requiring a VTable entry. DECLARE_MESSAGE_MAP is usually the final statement in the class declaration because it uses C++ access specifiers to specify the visibility of its members. You can follow DECLARE_MASSEGE_MAP with member declarations of your own, but if you do you should lead off with a public, protected or private keyword to ensure the visibility you want for those members.
With this infrastructure the framework can call GetMessage() to get a pointer to CMainWindows messageMap structure. It can then scan the _messageEntries array to see if CMainWindow has a handler for the message, and if necessary it can grab a pointer to CFrameWnds messageMap structure and scan the base classs message map, too.
Page 28
MessageMap structures CWnd &CCmdTarget:::messageMap &CWnd:_messageEntries [0] WM_DRAWITEM WM_MEASUREITEM CFrameWnd WM_CTLCOLOR WM_COMPAREITEM ............ ............ &CWnd::messageMap &CFrameWnd:_messageEntries [0] WM_INITMENUPOPUP WM_MENUSELECT WM_CREATE WM_DESTROY ...... .......
CFrameWnd::OnInitMenuPopup CFrameWnd::OnInitMenuPopup CFrameWnd::OnMenuSelect CFrameWnd::OnMenuSelect CFrameWnd::OnCreate CFrameWnd::OnCreate CFrameWnd::OnDestroy CFrameWnd::OnDestroy
CMainWindow
CMainWindow::OnPaint CMainWindow::OnPaint
What MFCs message mapping mechanism amounts to is a very efficient way of connecting messages to message handlers without using virtual function. Virtual functions are not space efficient because they require VTables , and VTables consume memory even if the functions in them are not overridden. The amount of memory used by a message map in contrast is proportional to the number of message entries it contains. Since its extremely rare for programmer to implement a window class that includes handlers for all of the different message types, message mapping conserves a few hundred bytes of memory just about every time a CWnd is wrapped around an HWND.
Page 29
Summary
Majority of the classes in MFC are derive from CObject. CWinApp is the base class from which your windows application object is derived. CWinApp class encapsulates WinMain function. CwinApp overridables are InitInstance Run ExitInstance OnIdle Any class derive from CCmdTarget has a message map. Message map is a table that correlates messages with member function an application provides to handle those messages. Message map macros include DECLARE_MESSAGE_MAP declaration. BEGIN_MESSAGE_MAP of your message map. END_MESSAGE_MAP used to end definition of used to begin definition used at the end of class
Quiz
1) CObject provides following three features _______________, _____________ and _____________ . 2) What is Serialization ? 3) Which MFC class represents the application and encapsulates WinMain? 4) ________________ member function initializes the application. 5) What is a message map?