September 1995
This paper provides a technical discussion of the major features of the Microsoft® Foundation Class Library version 4.0 (MFC 4.0). MFC 4.0 provides developers with a set of reusable, prebuilt C++ components that provide a completely portable interface for applications for the Microsoft Windows®, Windows 95, and Windows NT™ operating systems, as well as the Macintosh® and UNIX® platforms. These components encapsulate the common Windows-based functions that end users have come to expect in any Windows-based application, such as toolbars and status bars, form and edit views, print and print preview, OLE visual editing and OLE Automation, multiple-document interface, splitter and scroller windows, dialog data exchange and validation, dialog boxes, database access, and even context-sensitive help. Using MFC's prebuilt components, programmers can quickly create professional Windows-based applications that contain preconstructed application behavior. Using the MFC library saves programmers a considerable amount of development time.
MFC 4.0 is integrated with the Microsoft Visual C++® development system version 4.0 and in particular with Component Gallery, ClassWizard, and AppWizard. Many features of MFC are made simpler, less error-prone, and more streamlined by using these tools and the Visual C++ development system. For more information on the Visual C++ development system version 4.0, see the Microsoft Visual C++ Version 4.0 Reviewers Guide.
In this document, MFC 1.0, MFC 2.0, MFC 2.5, MFC 3.0, and MFC 4.0 refer to features specific to that particular version of the Microsoft Foundation Class Library. The name MFC refers to general concepts, architecture, and application programming interfaces (APIs) of the Microsoft Foundation Class Library and focuses on the latest versions of the classes.
The Microsoft Foundation Class Library 4.0 is a robust C++ application framework designed for writing applications in C++ for the Microsoft Windows operating system. MFC 4.0 is the latest version in the growing and evolving MFC library.
MFC 1.0 was released in April 1992 with Microsoft C/C++ version 7. The 32-bit version was released later that year as part of the Win32® Prerelease Development Kit program. The features of MFC 1.0 fell mainly into two categories: general-purpose classes for the nongraphical portion of an application and Windows-related classes for the graphical user-interface (GUI) features of an application.
General-purpose classes were the following:
Windows-related classes were the following:
Ten months later, in February 1993, MFC 2.0 was released as part of Visual C++ version 1.0. The core features of MFC 1.0 were extended to include new architectural classes to help organize and structure application programs as well as high-level abstractions in the form of prebuilt functionality that provides major building blocks. In August of the same year, the 32-bit version of MFC 2.0 was released as part of the 32-bit edition of Visual C++ 1.0.
Architectural classes were the following:
High-level abstractions were the following:
Ten months later, in December 1993, MFC 2.5 was released as part of Visual C++ version 1.5. In addition to all the features of MFC 2.0, this new release added support for databases, giving programmers access to any data source through ODBC and full support for the many features of OLE. This was a 16-bit-only release, and MFC 2.5 continues to be supported for 16-bit application development.
Database classes were the following:
OLE 2.0 classes were the following:
Fewer than 10 months later, in September of 1994, MFC 3.0 was released as part of Visual C++ version 2.0. In addition to all the new features of MFC 2.5, this release added 32-bit functionality, more user-interface idioms, more support for the Win32 API, as well as bootstrapping for OLE controls. MFC 3.0 extended the role of MFC to be the core infrastructure of most Win32-based applications.
New user-interface classes were the following:
New support for Win32 consisted of the following:
New language syntax support included the following features:
In two following Visual C++ subscription releases, MFC was again updated to deliver support for key Windows functionality such as Messaging Application Programming Interface (MAPI), Windows Sockets, and more. The features added to MFC 3.1 and 3.2 include the following:
The latest version, MFC 4.0, is available via the latest release of Visual C++, version 4.0. The new features in MFC 4.0 include the following:
MFC 4.0 builds upon the core set of functionality of MFC 1.0, the architecture and prebuilt high-level abstractions added in MFC 2.0, the OLE and Open Database Connectivity (ODBC) functionality added in MFC 2.5 and MFC 3.0, and the new user-interface and Windows Open Services Architecture (WOSA) features of MFC 3.1 and 3.2. MFC makes it possible to write professional, full-featured Windows-based applications in a fraction of the time it would take using C and the Software Development Kit (SDK) or other application frameworks. Equally important, MFC 4.0 continues the tradition of upward compatibility that is essential to development teams.
MFC offers a high level of abstraction that lets programmers focus on the details specific to the application while allowing its classes to be customized and extended. Like its predecessors, MFC 4.0 also allows access to the native Windows API for maximum flexibility and power. Rigorous tuning and optimizing of the source code have resulted in very high execution speeds and small executable files whose sizes are comparable to those produced using C.
MFC relies on the underlying Windows (Win32) API not only for its implementation but also for the factoring and flavor of many of the lower-level MFC classes. Providing C++ functionality that is tied to the Win32 API is a strength, because the Win32 API provides portability and a good infrastructure, and it makes it easy to call APIs that are not provided by the framework. Of course, MFC will continue to evolve and support the Windows operating system very closely, so developers using MFC will have support for the latest features of the operating system.
MFC uses a safe subset of the C++ language and was designed so that programmers could take advantage of their knowledge about programming to the Windows API. MFC uses C++ idioms in the commonly accepted manner and does not overlook advanced issues such as copy construction, assignment operators, and correct object destruction. These issues are a common source of error in user code and can be difficult to track down. Users of MFC do not have to be experts who understand all the details and idiosyncrasies of the C++ language. At the same time, more experienced C++ developers can use more advanced features of the language and still access the power of MFC. Also, the MFC library source code serves as an example of both professional C++ code and professional Windows-based code.
MFC makes programming in Windows and C++ a much more productive endeavor. Through its carefully designed architecture, MFC provides substantial programming power in an intuitive and uncomplicated package. MFC 4.0 offers more than 100 reusable C++ classes that provide a wide range of functionality.
Microsoft's Visual C++ group continually receives a great deal of feedback on MFC from many users who are working with real-world projects and are shipping applications. Visual C++ received critical acclaim from both developers and the press, and the product was generally recognized as the standard application framework for Windows. Microsoft also received hundreds of suggestions and feature requests through CompuServe® and Microsoft's MSVC e-mail address and from the dozens of conferences and shows where Microsoft team members heard from users who had developed mission-critical applications with MFC. Microsoft has implemented many of these requested features, and this release of the application framework represents the collective wisdom of the user community. MFC 4.0 includes substantial support for OLE controls, fast data access, and the new Windows common controls supported by Windows 95, which have been requested by many users.
The ability to incorporate user feedback is important to the long-term evolution of MFC as Microsoft continues to improve MFC for future releases. Microsoft developers are also part of the user community; the Visual C++ team at Microsoft has been using MFC to develop its own products. As a case in point, the Visual C++ 4.0 development environment, Developer Studio, is an MFC 4.0 application. MFC has also been widely adopted by companies such as Siebel Systems, Micrografx, Attachmate Corporation, and Federal Express to develop mission-critical solutions.
MFC has been designed to be portable to a number of platforms, allowing applications written to MFC to target a variety of different platforms. MFC is also portable to a variety of compiler implementations, and the many companies who have licensed MFC have made it a standard application framework for Windows-based development. Microsoft plans to keep extending and evolving MFC to support new functionality for applications and to exploit new functionality in the operating system.
Writing a program on top of MFC makes that program portable to a wide variety of platforms. Because MFC is built on top of the Win32 API, any platform that supports the Win32 API can be targeted by an MFC application. A powerful aspect of MFC portability is that Win32-based platforms are not limited to Microsoft Windows. Through the use of the Windows Portability Layer, MFC applications built on Win32 can also be built to run under the Macintosh System 7 operating system.
MFC applications can target a large number of platforms today:
In addition, Microsoft continues to working with companies licensed to provide the Windows API on UNIX and VMS™ platforms to make sure that developers can easily port their MFC applications to these platforms as well. These products are available today.
In August 1993, Microsoft announced the licensing of MFC (then version 2.0) to other software vendors, including competing C/C++ compiler vendors. Licensees receive all of the MFC source code, code samples, and help files, along with the right to redistribute them to their customers.
Several major tools vendors are shipping MFC with their products, and the list of MFC licensees continues to grow.
The Microsoft Foundation Class Library is appropriately named because it represents the foundation of a class architecture that is constantly evolving to bring developers the best support for the Windows operating system. The class hierarchy and the functionality it encapsulates have been designed for scalability. Applications written for MFC 1.0 are compatible with MFC 2.0 through MFC 4.0 and beyond. MFC applications that were originally written for 16-bit Windows can be recompiled with very minor source-code modifications to run as full 32-bit programs under any of the many Win32-compatible platforms. (The modifications required are due to converting any 16-bit specific code in the application. The application framework code does not rely on 16-bit or 32-bit implementation details.)
The Microsoft Foundation Class Library represents an entire family of class libraries. The design of MFC 4.0 incorporates an architecture that is highly scalable. As new versions of the Windows operating system are released, the Microsoft Foundation Class Library will grow in a natural manner to encompass new capabilities. As a case in point, MFC 4.0 is designed to facilitate application portability to the many platforms that now support the Win32 API.
MFC 4.0 encompasses most of the functionality available through the Win32 API. Because more than 70,000 lines of portable C++ source code for the application framework are included with the product, developers can use the framework in its original form or fully customize it for their own purposes. This source code serves as an example of robust and professional C++ Windows-based code. In addition, programmers are able to use this code to learn new implementation techniques and look "under the hood" of MFC. Consistent naming conventions and coding style, along with stand-alone documentation, make the learning curve minimal. A tutorial is included that helps programmers step by step through development of a substantial C++ MFC program for Windows, incorporating most application framework features. In addition, more than 70 complete sample applications are included that demonstrate the most common uses (and many advanced uses) of the framework.
Because of the great productivity gains that developers have been achieving from using MFC, an increasing number of developers want to adopt the framework. To help these developers, Microsoft has developed an MFC Migration Kit that is designed to assist the migration to MFC of existing applications for Windows written in C. The MFC Migration Kit supplies the following:
The migration tool can also help developers port 16-bit applications to 32 bits, with or without MFC. The MFC Migration Guide explains where that port fits into your migration strategy. The MFC Migration Kit is available in the latest subscription release of Visual C++, version 4.0. The kit is located in the \MFCKIT directory on the Visual C++ CD-ROM disc. Setup for the kit can be run from that location.
The following features have been introduced in MFC 4.0. Some of these features appeared earlier in subscription updates to Visual C++.
Microsoft Visual C++ version 4.0 supplies MFC classes to encapsulate most of the new Windows common controls supplied with the Windows 95 and Windows NT operating systems. The integrated tools (editors and wizards) in Visual C++ 4.0 also support Windows common controls. These controls are also supported by the Visual C++ Cross-Development system for the Macintosh.
The Windows common controls supported by MFC 4.0 include the following:
Several CView-derived classes are also available to simplify the use of the new controls in document-view architecture applications. CListView, CTreeView and CRichEditView make it easier to use the CListCtrl, CTreeCtrl and CRichEditCtrl objects. To provide further support for rich-text editing, CRichEditDoc, CRichEditView and CRichEditCntrItem classes are available that provide Document/View and control encapsulation.
Note Some of these controls appeared in MFC 3.1, but they have been improved and expanded (with improved documentation) for MFC 4.0.
MFC now supplies complete OLE control container support and integrates the OLE Control Development Kit (CDK) with the rest of MFC. This allows developers to build, use, and share OLE controls with other developers, even those using different tools.
Developers can choose from hundreds of OLE controls already on the market or build their own. These OLE controls are compatible with the latest versions of the Microsoft Visual Basic® programming system and the Microsoft Visual FoxPro™ database management system, as well as with many other development tools. The Visual C++ 4.0 dialog editor supports placing OLE controls in a dialog resource, making it easy to use prebuilt controls in applications.
With the new OLE controls container, developers need not understand all the details of using OLE container applications. Support is based on the CWnd class, which allows users to create both the container and the control sides. In MFC version 4.0, an OLE control becomes a special kind of child window, with CWnd functions, including CWnd::CreateControl, which dynamically creates an OLE control rather than an ordinary window.
Support is also provided for dialog data exchange (DDX), preloaded controls for improved performance, and transparent keyboard translation in IsDialogMessage.
In addition to the existing ODBC database support, the new Data Access Object (DAO) classes for MFC enable developers to directly access the Microsoft Jet database engine, which is the same engine that is used in Microsoft Access for Windows 95 and Microsoft Visual Basic 4.0. The DAO classes encapsulate an OLE Component Object Model (COM) interface to the Jet database engine, so developers don't have to write the structured query language (SQL) themselves unless they want to do so.
As with the ODBC database classes, developers can open and manipulate databases and recordsets and display the data in a form view. With DAO, they can also set up and use work spaces, create and manipulate tables and queries, and use and create indexes for those tables through the use of the SQL data definition language (DDL).
Developers can also access ODBC data sources through attached tables using the DAO classes and the Jet engine.
Two new OLE common dialog classes, CPageSetupDialog and COlePropertiesDialog, have been developed to improve access to several aspects of an OLE object. COlePropertiesDialog encapsulates the Windows common OLE Properties dialog box to provide an easy way to display and modify the properties of an OLE document item in a manner consistent with Windows specifications.
In addition, CPageSetupDialog encapsulates the services provided by the Windows common Page Setup dialog box with additional support for setting and modifying print margins. Several other new common dialogs, including the Windows 95 file I/O dialogs, are now supported by MFC.
Multithread programs often require synchronizing access to shared resources by different concurrent threads. To manage synchronization, MFC supplies a new base class, CSyncObject, and several derived objects that represent common synchronization techniques.
CSyncObject provides functionality common to the derived synchronization objects in the Win32 API. Support includes Lock and Unlock as virtual abstract operations that derived classes override. Classes derived from CSyncObject are CSemaphore, CCriticalSection, CMutex, and CEvent, encapsulating the Win32 synchronization objects. The CSingleLock and CMultiLock classes represent the access-control mechanisms used in controlling access to a resource in a multithread program.
MAPI, the Messaging API for Windows, is a set of functions that mail-enabled and mail-aware applications use to create, manipulate, transfer, and store mail messages. It gives application developers the tools to define the purpose and content of mail messages, and it gives them flexibility in their management of stored mail messages. MAPI also provides a common interface that application developers can use to create mail-enabled and mail-aware applications independent of the underlying messaging system.
Messaging clients provide a human interface for interaction with MAPI. This interaction typically includes requesting services from MAPI-compliant providers such as message stores and address books.
MFC 3.1 includes support for Simple MAPI in classes CDocument and COleDocument. This support is also provided in MFC 2.52 for 16-bit development.
With minimal effort, developers can add the ability to send an application's documents by means of the resident e-mail host. (Sending OLE compound documents is managed correctly in the COleDocument portion of the MAPI implementation.)
New Windows Sockets classes have been added for network programming. MFC provides support for Windows Sockets, the network-independent API for network communications programming under the Microsoft Windows and Windows NT operating systems.
The new classes include CAsyncSocket, CSocket, and CSocketFile. Class CAsyncSocket encapsulates the Windows Sockets API. Class CSocket, derived from CAsyncSocket, additionally provides a simple programming model that lets developers serialize data from one socket application to another via a CArchive object, using a CSocketFile object.
One of the most commonly requested user-interface elements is the toolbar, a row of buttons represented by bitmaps and optional separators. These bitmap buttons can behave like push buttons, check-box buttons, or radio group buttons. The MFC class CToolBar supports the standard toolbar look. All the toolbar buttons are normally taken from a single bitmap image, which is edited using the Visual C++ bitmap editor and contains one image for each button. Storing all the images in one bitmap reduces the amount of system resources used by an application.
One of the key advantages of the MFC CToolBar class is that by using commands, programmers can enable and disable the various buttons in the toolbar in conjunction with any menu items for those same commands. This is important because toolbar buttons almost always duplicate menu items, allowing the programmers to write the command handler once and drive it from either a menu item or a toolbar button.
MFC 4.0 adds dynamic resizing and layout of toolbars, which lets users change not only the toolbar location, but also resize the toolbar window. This makes vertical toolbars and tool "palettes" possible. A dockable toolbar can be attached or "docked" to any side of its parent window, or it can be "floated" in its own miniframe window (using CMiniFrameWnd).
Programmers who use AppWizard to generate the skeleton of an application are asked to choose whether or not they want dockable and resizable toolbars. By default, AppWizard creates code to enable docking, resizing toolbars. CToolBar and CFrameWnd member functions are available to customize the behavior of the docking toolbar and to programatically dock or float a toolbar.
Support for "tool tips" is also included. When the user moves the mouse over a toolbar button, a small box is shown on top of the button to describe the action that would be performed. Also supported are "fly-by" tool tips that provide a more detailed description of the command on the status bar. This saves the user from having to press a toolbar button to find out what the command does.
MFC 3.0 also allowed persistence of toolbar configurations. Like many professional applications, MFC allows users to save the entire state of a given frame window's toolbar configuration, including each toolbar's current position and visible and floating states.
The CToolBar class can easily support additional standard Windows controls, such as drop-down list boxes or edit controls, on the toolbar. In addition, CToolBar provides programmatic APIs for dynamically changing the buttons on the toolbar, customizing docking behavior, and highly customizing user interfaces in other ways.
Figure 1. Resized and floating toolbars
Miniframe windows are frame windows with thin caption bars, like those used in the Visual C++ property windows.
The MFC class CMiniFrameWnd, derived from CFrameWnd, provides an alternative user interface for floating palettes and toolbars. In fact, the CToolBar implementation of tear-off toolbars uses the CMiniFrameWnd class to hold the torn-off toolbar.
A CMiniFrameWnd object represents a half-height frame window typically seen around floating toolbars. These miniframe windows behave like normal frame windows, except that they do not have minimize/maximize buttons or menus, and the user only has to single-click the system menu to dismiss them.
MFC contains support for property sheets, also known as "tabbed dialog boxes." A property sheet is a special kind of dialog box that is generally used to modify the attributes of some external object, such as the current selection in a view. The property sheet has three main parts: the containing dialog box, one or more property pages shown one at a time, and a tab at the top of each page that the user clicks to select that page. Property sheets are useful when a number of similar groups of settings or options need to be changed. An example of a property sheet is the Project Settings dialog box in Visual C++. In this case, a number of different groups of options need to be set. The property sheet allows a large amount of information to be grouped in an easily understood fashion.
This support is provided in two classes: CPropertySheet, which is a class to contain all the pages, with one tab per page; and CPropertyPage, which is a class that each property page is derived from.
To create a property sheet with several pages, first create a dialog template resource for each property page using the Visual C++ dialog editor, then use ClassWizard to create a CPropertyPage-derived class corresponding to each property page dialog template. For each of these new classes, use ClassWizard to create member variables to hold the values for the property page. The process for adding member variables to a property page is exactly the same as adding member variables to a dialog box, because a property page is a specialized dialog box.
Creating the property sheet at run time is easy to do, either by using the CPropertySheet class directly or by deriving a more specialized property sheet from it.
Figure 2. Miniframe property sheet
For Windows 95, MFC is designed so that applications run with the correct user interface depending on which operating system they are running on.
Developers can build one Win32-based executable file using MFC. The application will look and act like a Windows 3.1-based application when run on Windows 3.1 or on Windows NT on an Intel processor.
Figure 3. Scribble demo on Windows NT
When the same executable file runs under Windows 95, the application will look and act like a Windows 95-based application.
Figure 4. Scribble demo on Windows 95
Splitter windows, toolbars, status bars, and miniframe windows all have a markedly different look when running on Windows 95. Also, CScrollView-derived classes automatically take advantage of proportional scroll thumbs, if available. In addition, the property page classes were modeled after the Windows 95 user interface.
MFC continues to play its role as the C++ API to Windows. MFC 3.0 provided expanded and improved encapsulation of some of the Win32 services. Member functions in existing classes improved the Win32 API coverage. Classes support writing multithread applications, Unicode, or Double-Byte Character Sets (DBCS) applications using MFC as a shared DLL. MFC 3.0 also included extended coverage of the Win32 API, including GDI functionality such as Béziers, Paths, and a number of other Win32 USER APIs.
MFC is thread-safe and supports writing multithread MFC applications. Threads of execution are encapsulated in the class CWinThread. The main application class, CWinApp, is derived from CWinThread; it represents the main user-interface thread of the application.
MFC distinguishes two types of threads: user-interface threads and worker threads. User-interface threads are commonly used to handle user input and respond to events and messages generated by the user. Worker threads are commonly used to complete tasks that do not require user input, such as recalculation. MFC handles user-interface threads specially by supplying a message pump for events in the user interface. CWinApp is an example of a user-interface thread object, because it derives from CWinThread and handles events and messages generated by the user.
Developers can create additional threads in their applications if they wish, creating new objects of the class CWinThread or a class derived from CWinThread. In most situations, the developer doesn't even have to create these objects explicitly and can instead call the framework helper function AfxBeginThread, which creates the CWinThread object.
Of course, even with the multithread enabling of MFC, writing and debugging multithread applications is an inherently complicated and tricky undertaking, because the developer must ensure that a given object is not accessed by more than one thread at a time.
Some international markets use languages that have large character sets, such as Japanese and Chinese. To support programming for these markets, the MFC library is enabled for two approaches to handling large character sets, Unicode and Double-Byte Character Sets (DBCS).
DBCS is supported on all platforms. Unicode is supported on all Windows NT platforms. The MFC library is designed to support either option. A special version of the MFC library must be linked in when building a Unicode application.
MFC is provided in a version that directly supports Unicode characters and strings. In particular, class CString is Unicode-enabled. CString is based on the TCHAR data type. If the symbol _UNICODE is defined for a build of the program, TCHAR is defined as type wchar_t, a 16-bit character-encoding type; otherwise, it is defined as type char, the normal 8-bit character encoding. As a result, under Unicode, CStrings are composed of 16-bit characters; without Unicode, they are composed of characters of type char. CString also supplies Unicode-aware constructors, assignment operators, and comparison operators.
If Unicode is not specified, the class library defaults to supporting the ANSI character set, with support specifically for DBCS. Under the DBCS scheme, a character can be either one or two bytes wide. If it is two bytes wide, its first byte is a special "lead" byte, chosen from a particular range depending on which code page is in use. Taken together, the lead and "trail" bytes specify a unique character encoding.
In either case, CString conversion operators and constructors make it easy to convert ANSI and Unicode strings to a CString object, in the case that program deals with both ANSI and Unicode characters.
Note that Unicode string serialization in MFC can read both Unicode and DBCS strings, regardless of which version of the application is running. Because of this, data files are portable between Unicode and DBCS versions of the program.
MFC provides all the application framework in a shared DLL form. MFC 2.0 introduced the shared DLL feature and provided a single DLL for all the MFC features (MFC200.DLL). This feature was continued with MFC 2.5 (MFC*250.DLL). However, this shared DLL was available only on the 16-bit Windows platform.
For MFC 3.0, the functionality was factored into three 32-bit DLLs: one for the core features (MFC30.DLL), one for the OLE 2-specific support (MFCO30.DLL), and one for the database-specific support (MFCD30.DLL). All three DLLs are available in two forms: a freely redistributable retail version and a debugging version.
MFC 4.0 combines all of these DLLs into one unified DLL for simplified distribution. For increased performance, advanced page-tuning techniques reduce overhead for applications that don't use all MFC features.
The benefits of this shared DLL implementation to the programmer are significant. Now, several MFC applications can share framework code if they are running simultaneously, thus reducing system-resource usage. Also, executable files are much smaller than static-link versions of the same applications, although the size of the DLL must be included for a true measurement.
MFC takes advantage of new C++ language features such as C++ templates and exceptions. Version 1.0 of MFC was designed at the time these C++ language features were still under development, so additional tools and macros were needed. Today, with MFC 4.0 and direct compiler support for these language features, the benefits of the original design are visible.
With MFC 4.0, there is no need to use TEMPLDEF or the TRY, CATCH, and THROW exception macros. True C++ syntax for templates and MFC "templatized" collections are supported. C++ exceptions are supported for both new and old code, so objects on the stack will always be destroyed when exceptions are thrown. For backward compatibility, the old ways (prior to MFC 4.0) of doing things are still supported.
MFC provides collection classes based on C++ templates, which makes it easier to derive one's own type-safe collection classes. MFC 3.0 provided two types of collection classes to manage groups of objects: collection classes that are created from C++ templates; and Collection classes that are not created from templates.
The nontemplate collection classes are the same as those provided by MFC in versions 1.0 and later. Developers whose code already uses these classes can continue to use them. Developers who write new type-safe collection classes for their own data types should consider using the newer template-based classes.
A collection class is characterized by its shape and by the types of its elements. The shape refers to the way the objects are organized and stored by the collection. MFC provides three basic collection shapes: lists, arrays, and maps (also known as dictionaries), which provide easy-to-understand yet powerful building blocks for the rest of the application. Developers can pick the collection shape most suited to their particular programming problems:
Shape | Description |
List | The list class provides an ordered, nonindexed list of elements, implemented as a doubly linked list. A list has a "head" and a "tail," and adding or removing elements from the head or tail, or inserting or deleting elements in the middle, is very fast. |
Array | The array class provides a dynamically sized, ordered, and integer-indexed array of objects. |
Map | A map is a collection that associates a key object with a value object. |
The easiest way to implement a type-safe collection that contains objects of any type is to use one of the MFC template-based classes.
Collection contents | Arrays | Lists | Maps | |||
Collections of objects of any type | CArray | CList | CMap | |||
Collections of pointers to objects of any type | CTypedPtrArray | CTypedPtrList | CTypedPtrMap |
For example, to create a dynamically sized array of "doubles," use C++ template syntax:
CArray<double, double> myArray;
If the application already uses MFC nontemplate classes, developers can continue to use them, but they should consider using the template-based classes for new collections.
In MFC, exceptions are used to signal abnormal execution, including situations in which conditions outside the program's control are influencing the outcome of the function, such as low memory or I/O errors. Abnormal situations are handled by catching and throwing exceptions, rather than by using return codes that are often overlooked and so result in inefficient code. The exception syntax is a clean and efficient mechanism for abnormal conditions.
MFC provides two compatible ways of using exceptions: the C++ exceptions, available starting with MFC version 3.0; and the MFC exception macros, available starting with MFC version 1.0.
Developers writing new applications using MFC should use the C++ exceptions mechanism. The macro-based mechanism can be used if the existing application already uses that mechanism extensively. Existing codes can be converted readily to use C++ exceptions instead of the MFC exception macros, if desired.
If an application has already been developed using the MFC exception macros, the developer can continue to use the MFC exception macros in the existing code, while using C++ exceptions in new code.
Whether they use the C++ exceptions directly or use the MFC exception macros, developers will use CException or CException-derived objects that may be thrown by the framework or by the application. MFC provides several predefined exception classes to handle everything from out-of-memory to OLE dispatch exceptions.
Visual C++ provides integrated support in AppWizard, ClassWizard, and the Visual C++ dialog editor for building database applications. In version 3.0, MFC provided database engine functionality. Also, a new mechanism was provided to enable data-bound controls using ClassWizard, which makes it easy for the developer to build forms that view and edit fields in a database without having to write any C++ code.
These database classes provide easy access to any database for which an ODBC driver is available. Also provided with Visual C++ are portions of the ODBC SDK, the ODBC driver manager, and a new set of drivers.
In addition to the new DAO classes, there are two main classes that provide the encapsulation of ODBC data sources: CDatabase and CRecordset. These classes are modeled after the high-level database abstractions used in the Visual Basic programming system and the Microsoft Access database management system. The MFC versions of these abstractions are provided as type-safe C++ classes that allow programmers to access data in an easy and comfortable way, without requiring them to give up the performance and compile-time checking that C++ provides.
The class CDatabase represents a connection to a data source through which developers can operate on the data source. The database engine classes are smart enough to allocate and open a new CDatabase connection as needed by the program. Developers who want to manage their database connections manually, or to optimize performance or control transactions, will want to use the CDatabase class.
The class CRecordset encapsulates a set of records selected from a data source. Recordsets enable scrolling from record to record, updating of records (adding, editing, and deleting records), qualifying the selection with a filter, sorting the selection, and "parameterizing" the selection with information obtained or calculated at run time.
Programmers will normally derive their own custom classes from CRecordset to add type-safe member variables to the class that will be bound to specific columns of a data source. The process of creating a new C++ class and managing the binding of columns to member variables is performed by ClassWizard. The process of moving data between the database and the member variables of the class is called record field exchange (RFX). This technique is similar to the dialog data exchange (DDX) mechanism introduced in MFC 2.0 (see below).
Data values obtained from an ODBC data source are turned into C++ and MFC data types such as short, long, float and CString. For large binary data, a class CLongBinary is provided for efficient management of large data values.
One of the most common types of Windows-based applications is form processing. A form is like a dialog box that the user can interact with to fill in edit controls, select options from list boxes and radio groups, and work with other dialog box controls. For example, an order/entry database application would probably use forms to allow customer service representatives to enter order information.
MFC 2.0 introduced the high-level abstraction of a form view. MFC 3.0 included a class called CRecordView, derived from CFormView, that provides a form directly connected to a recordset object.
Using the same mechanism as for dialog boxes and simple form views, a record view uses the MFC DDX mechanism to exchange data values between the recordset and the controls of the record view. Like all form views, a record view is based on a dialog template resource. Record views also support moving from record to record in the recordset, updating records, and closing the associated recordset when the record view closes.
Like any form view, a record view automatically supports many features, such as scrolling, synchronous update, support for VBX custom controls, support for standard Windows controls, and the ability to place a form view in any window, including MDI child windows.
OLE provides many attractive features to the end user of OLE-capable applications. For the developer, OLE provides a lot of functionality in many APIs but adds the burden of many design decisions and a lot of implementation work.
The MFC support for OLE provides C++ classes integrated with the MFC framework that make developing OLE-capable applications easy. AppWizard has been extended to make it easy to start developing OLE applications. ClassWizard has been extended to make it easier to support OLE Automation in programs.
The MFC support for OLE encapsulates much of the complexity of the OLE API in a small set of C++ classes that provide a higher-level interface to OLE. Of course, following the MFC design philosophy, developers can call the underlying C-language OLE API functions directly wherever the OLE classes don't meet their needs.
Also provided with Visual C++ is the OLE 2.0 SDK, as well as a number of tools and sample applications to help developers test their OLE applications. Online documentation includes overview material, tutorials, an encyclopedia, and a class reference.
This paper divides the features of OLE into two main categories: features for supporting OLE visual editing and features for OLE Automation. The development work involved depends on whether the application will provide these services (as an OLE server), or whether it will use or consume these services (as an OLE client or a container).
OLE is a mechanism that allows users to create and edit documents containing data created by multiple applications. OLE documents seamlessly integrate various types of data, called items. Sound clips, spreadsheets, and bitmaps are typical examples of items found in OLE documents. Supporting OLE in an application allows the user to work with OLE documents without worrying about switching back and forth between the different applications; OLE does the switching.
A container application is used to create OLE documents, and a server application is used to create the items within the container application. Any application may be a container, a server, or both.
OLE incorporates many concepts that all work toward the goal of seamless interaction between applications. These areas include the following:
Feature | Definition |
Linking and embedding | Linking and embedding are used for storing items inside an OLE document that were created in another application. |
In-place activation | Activating an embedded or linked item in the context of the container application is called in-place activation. The interface of the container application changes to incorporate the features of the application that created the embedded or linked item. |
Uniform data transfer | Uniform data transfer (UDT) is a set of interfaces that allows data to be sent and received in a standard fashion, regardless of the actual method chosen to transfer the data. UDT forms the basis for data transfers using the Clipboard and drag and drop. |
Drag and drop | Drag and drop is an easy-to-use, direct-manipulation technique to transfer data between applications, between windows within an application, or even within a single window in an application. The data to be transferred is simply selected and dragged to the desired destination. |
Compound files | Compound files provide a standard file format that simplifies structured storing of OLE documents for OLE applications. Within a compound file, "storages" have many features of directories, and "streams" have many features of files. |
OLE Automation | OLE Automation allows one application to drive another application. The driving application is known as an automation client, and the application being driven is known as an automation server. |
OLE Component Object Model | The OLE Component Object Model (COM) provides the infrastructure used when OLE objects communicate with each other. The Microsoft Foundation Class Library OLE classes simplify OLE COM for the programmer. |
Support for visual editing includes in-place activation and editing, drag and drop, and OLE document (structured) storage. Two sets of MFC classes support visual editing. One set of classes is designed to help developers build OLE servers, the software components that can be embedded or linked inside other applications. This server support lets developers visually export the components in their applications. The other set of classes is designed to help developers build OLE containers that allow the components from other applications to be visually embedded or linked in OLE documents.
A visual editing server application can create OLE items for use by other applications that have the appropriate OLE support to contain these items (for information on container applications, see the following section, "Visual Editing Containers"). Server applications usually support copying their data to the Clipboard or by drag and drop so that container applications can paste the data as an embedded or linked item.
A miniserver is a special type of server application that can be launched only by a container. The Microsoft Draw and Microsoft Graph servers are examples of miniservers. A miniserver does not store its own data as files on disk; instead, it reads its documents from and writes them to items in documents belonging to containers. As a result, a miniserver can only support embedding, not linking.
A full-server can either be run as a stand-alone application or launched by a container application. A full-server can store documents as files on disk. It can support embedding only, both embedding and linking, or only linking. The user of a container application creates an embedded item by choosing the Cut or Copy command in the server and the Paste command in the container. A linked item is created by choosing the Copy command in the server and the Paste Link command in the container.
When a server application is launched by a container application and is in place, MFC handles all of the toolbar and menu negotiation to allow the server's menus and toolbar to display in place of the menus and toolbar of the container. Even advanced user-interface features such as docking toolbars are supported when a server is in-place activated; in this case, the toolbars are docked to the container's frame window. MFC handles all the negotiation with the container for the tool space, including showing correct feedback when the toolbar is being dragged.
A visual editing container application can incorporate embedded or linked items into its own documents. The documents managed by a container application must be able to store and display OLE items as well as the data created by the application itself. A container application allows users to insert new items or edit existing items by activating server applications when needed.
Container applications will launch and contain a server application. Communication between containers and servers is achieved through the OLE system DLLs. These OLE system DLLs provide functions that containers and servers call, and the containers and servers provide call-back functions that the DLLs call. Using this means of communication, a container doesn't need to know the implementation details of the server application. A container can accept items created by any server without having to define the types of servers with which the container can work. As a result, the user of a container application can take advantage of future applications and data formats. As long as these new applications are OLE servers, an OLE document will be able to incorporate items created by those applications.
Drag and drop is an easy-to-use, direct-manipulation technique to transfer data between applications, between windows within an application, or even within a single window in an application. The data to be transferred is simply selected and dragged to the desired destination. One application provides the data for copying, and another application accepts the data for pasting. Each side of the transfer needs to perform different operations on the data for the transfer to succeed. The MFC library provides full support to represent each side of this transfer.
Data sources represent the source side of the data transfer. They are created by the source application when data is provided for a drag-and-drop operation. Data objects represent the destination side of the data transfer. They are created when the destination application has data dropped into it.
Compound files are an integral part of OLE. They are used to facilitate data transfer and OLE-document storage. Compound files are an implementation of the structured-storage model.
MFC supports using both compound files and normal flat files for an application's file storage. The code the developer writes is the same. Using the CArchive abstraction, MFC is able to hide the differences between these two file formats while offering the benefits of each. These benefits include support for serialization to a storage (using the OLE IStorage interface), a stream (using the OLE IStream interface), or a normal or flat file where the developer has complete control over the file format.
An OLE Automation server exposes programmable software components, along with their properties and methods, to other applications. These driving applications are called OLE Automation clients. Exposing objects in this way is beneficial when applications provide functionality that is useful for other applications. For example, a word processor might expose its spelling-check functionality so that other programs can use it. Exposure of objects enables vendors to improve the functionality of their applications by using the ready-made functionality of other applications.
ClassWizard, AppWizard, and the framework all provide extensive support for OLE Automation servers. They handle much of the overhead involved in creating an OLE Automation server so that developers can focus their efforts on the functionality of their applications.
MFC, along with ClassWizard support, makes it extremely easy to expose member variables and member functions from type-safe C++ classes as OLE Automation properties and methods. This allows an application's objects to be driven by an external macro language such as Visual Basic.
MFC provides direct support for creating type libraries. Type libraries are useful for exporting OLE Automation servers to other C++ client applications. The new AppWizard will automatically create an .ODL file, and ClassWizard will automatically maintain the .ODL source file used to create the type library.
An OLE Automation client manipulates components implemented in other applications. The application being manipulated, which is the OLE Automation server, exposes programmable components and allows clients to automate certain procedures by directly accessing the server components, along with their properties and methods.
By creating an OLE Automation client, MFC makes it easy to drive other applications, allowing developers to build an application using C++ language to drive the objects exposed by large applications such as Microsoft Excel, Microsoft Word, or any other OLE Automation server that has a type library.
ClassWizard reads the type library provided by the OLE Automation server and creates new custom C++ classes for the IDispatch interfaces exposed by that server. MFC provides the glue to connect these dynamic OLE (IDispatch) interfaces into type-safe C++ classes. Therefore, most OLE Automation clients written in C++ do not have to deal with the dynamic nature of IDispatch.
The OLE control architecture merges the popular VBX custom control architecture with the open, standard architecture of OLE. OLE controls make component-based development a reality by allowing developers to easily use existing bodies of functional code encapsulated as OLE controls. An OLE control is a custom control, implemented as an OLE object with visual editing and OLE Automation support. An OLE control has additional capabilities beyond those of ordinary OLE components, such as the ability to fire events. With MFC 4.0, containment of OLE controls is supported by using AfxEnableControlContainer.
Most OLE objects require a substantial amount of implementation effort. Fortunately, the OLE Control Development Kit (CDK)—built into Visual C++ 4.0—provides most of the required implementation, so developers only have to fill in details that are specific to the OLE control. The OLE control CDK classes themselves are based on MFC base classes (that is, COleControl derives from CWnd). This makes it easier for developers who are experienced with MFC to create OLE controls. It also makes it easier to use existing MFC code inside the implementation of new OLE controls.
MFC includes support for creating and using 32-bit OLE controls. MFC, along with the newly merged CDK, provides support for creating, testing, and using OLE controls, including hundreds available from third parties.
A key benefit of an application framework is that it not only provides a large body of prebuilt functionality but offers an architecture in which to add new functionality. An elegant architecture gives developers a logical and obvious location to add application-specific code when implementing features in their applications. For example, when developers are implementing the File Save command, the application framework should have an obvious technique (such as a member function or a hook) to add this functionality. It is not enough, however, to point programmers to the right place, because there is often no single right place, or the application framework may not foresee the exact situation. MFC addresses these issues with a group of tightly integrated classes collectively known as the application architecture classes. These classes provide support for the important areas common to many parts of the application, such as commands, documents, views, printing, online help, and dialog processing.
Menu items, keyboard accelerators, and toolbar buttons are the most common sources of commands in an application. A command is an instruction to the program to perform a certain action. Unlike a procedure or function call, a command is a message that is routed to various command targets that may carry out the instruction. Command targets are objects derived from the CCmdTarget class, and they include documents, views, windows, and the application itself.
The command architecture ensures that any user-interface action, such as clicking a toolbar button or selecting a menu item, will route the command to the appropriate handler. Command routing can also be used to update the visual state of menu items or toolbar buttons. For example, the Edit Cut command might have both a menu item and a toolbar button that can be enabled or disabled. Using the command architecture, it is easy to maintain the visually enabled or disabled state of both the menu item and the toolbar button with a single line of code in a single location.
Another integral part of the MFC architecture are message maps, which were introduced in MFC 1.0 and were extended in MFC 2.0 and MFC 3.0. A message map provides a type-safe mechanism for directing any windows message, control notification, or command to a C++ member function in the appropriate class. Each command target has a message map, and it contains entries that map each command ID defined in the Visual C++ resource editor to a C++ member function. Because there can be a large number of commands (as well as Windows-based messages and notifications) handled by each command target, ClassWizard is usually used to create classes and to maintain a class's message maps and message-handler functions.
MFC 3.0 extended the use of the command-handling architecture to support OLE Automation. Any class derived from CCmdTarget can expose member variables and member functions as OLE Automation properties and methods. MFC 3.0 also included macros to make it easier to handle ranges of command IDs, a commonly requested feature.
MFC provides support for extended control notifications (WM_NOTIFY), routed just like any other command. This support is included for new services that are exploited in the release of future operating systems, and it is another example of MFC being on the leading edge of support for new operating systems.
The document/view architecture introduced in MFC 2.0 is the basis for managing the storage and display of application-specific data. The CDocument class provides support for managing an application's data, and an application will typically derive a new class from CDocument for each document type. The key feature of a document class is its ability to save a document object to a file for later use. The programmer's responsibility is to override the Serialize member function, which saves and loads application-specific data to and from storage. By implementing this function, MFC automatically supports high-level commands such as File New, File Save, File Save As, and File Open. MFC does all the work of displaying a dialog box to gather information from the user and managing the disk file. Although most documents are typically associated with disk files, the CDocument architecture is flexible enough to allow manipulation of data stored in other ways, such as in a database file, or to allow manipulation of data without any kind of stored representation. AppWizard provides several options for the initial skeleton of an application that incorporate database functionality in a variety of ways.
Each document in a running application is attached to one or more views of that document. Views control the graphical display of the application's data on the screen. Programmers typically derive a class from the MFC CView class and then implement the display code. A view represents the main area of a window on the screen and is a simple child window that can be manipulated with CWnd member functions. This usually involves implementing the OnDraw member function and writing the code that displays the data that is currently visible to the user. The OnDraw function replaces the low-level OnPaint handler of MFC 1.0 with a high-level abstraction. After implementing OnDraw, the program automatically supports printing and print preview. The CView-derived class is usually the best place to handle most of the commands and window messages that graphically manipulate the data. To support high throughput and fast updates, a number of APIs enable optimization of the drawing process to support most professional applications. It is also easy to have many views on the same document, and each view can be a different CView-derived class. For example, a splitter window will have one view for each pane.
To coordinate documents and views, MFC uses the helper class CDocTemplate. This class orchestrates the creation of documents, views, and frame windows in response to user input. One document-template object is created for each document type and is the glue that connects the document and view types. The application object maintains the document templates. Two document-template classes are supplied: one for multiple-document interface (MDI) and one for single-document interface (SDI). The significant differences between an MDI and SDI user-interface model are encapsulated in the document template and frame window classes.
By leveraging the document/view architecture, MFC is able to provide an application with device-independent printing. This means that the same code written for OnDraw in the CView-derived class can be used to draw on the screen and on the printer. When the user asks to print a document using the standard File Print command, MFC calls the OnDraw member function with a special device context that is aware of the current printer and knows how to translate the screen display into appropriate printed output. MFC also provides support for all the standard printing user-interface dialog boxes.
In combination with the printing and document/view architectures, MFC supports print preview functionality, which shows a reduced image of either one or two pages of a document as they would appear when printed on the currently selected printer. The implementation provides the standard user interface for navigating between pages, toggling between one- and two-page viewing, and zooming the display in and out to different levels of magnification. The ability to support print preview is an excellent example of the level of prebuilt functionality and the high level of abstraction in MFC. The print preview feature represents several thousand lines of code in the application framework, but programmers only need to handle the display output code in the OnDraw member function of class CView and make sure that the File Print Preview menu command is available—the framework does the rest.
The capability known as dialog data exchange (DDX) introduced in MFC 2.0 provides an easy way to initialize the controls in a dialog box and gather input from the user. An associated mechanism known as dialog data validation (DDV) provides validation of the dialog data. The heart of the DDX/DDV feature is the DoDataExchange member function, which is called automatically by the application framework when data must be transferred and/or validated.
Because there are so many possibilities for exchange and validation (for example, the use of custom controls or the need for application-specific validation schemes), Microsoft made the DDX/DDV architecture fully extensible. Developers can supply their own DDX and DDV functions and integrate them seamlessly with MFC.
In MFC 2.0, this mechanism was used primarily for dialogs. Now, the DDX mechanism has been extended to work with data-bound record views as well as with normal dialogs and simple form views. The DDX/DDV architecture is tightly integrated with ClassWizard, which enables developers to define all the necessary member variables and DDX/DDV routines without having to write any code.
Support for online and context-sensitive documentation is essential for most applications. MFC provides an architecture that makes it easy to incorporate the two most common types of help support in Windows-based applications. Help support includes a Help menu with the standard commands and provides an architecture for the application framework to map from command or resource IDs to the various help contexts. Help contexts are easily created in Visual C++, because every time a user-interface element is created in the Visual C++ resource editor, a help context for that element is automatically created. Help files (.HLP) are authored using standard authoring tools.
When a user presses the F1 key, MFC automatically processes the keystroke as a help request for the current command target. For example, the CDialog class processes the help request by invoking WinHelp on the help topic for the currently displayed dialog box. If no help context is defined for the current command target, then the application framework automatically launches the default help. The CFrameWnd, CMDIFrameWnd and CDialog classes all provide handler functions for help support. Developers can add support to any class that is a command target.
When a user presses SHIFT+F1, MFC captures the mouse and changes the cursor into the standard context-sensitive help cursor (arrow + question mark). When this cursor is displayed, clicking a user-interface object tells the application framework to invoke WinHelp with the correct help context based on the selected object.
MFC provides a tool to manage the help-context information, which associates user-interface elements with help contexts. In addition, AppWizard provides much of the standard WinHelp-format file with prewritten information on all of the standard commands. All that is needed is an editor capable of editing Rich Text Format (RTF) text, such as Microsoft Word, to add application-specific information. In this way, MFC, AppWizard, and the Visual C++ development environment work together to provide programmers most of their applications' help features automatically.
MFC 1.0 was the cornerstone of a robust framework for building reusable classes, but it did not provide enough high-level abstractions to reduce programming time. With MFC 2.0 and later, this issue is addressed with a set of classes that support the most common user-interface idioms and provide capabilities for taking advantage of other prebuilt functionality. These classes, collectively called high-level abstractions, are designed to be used as supplied by MFC and can result in a dramatic reduction in programming time. In a few lines of code, programmers can build a text-processing window that integrates seamlessly with other MDI windows, or they can change the base class to turn a view into a scrolling view. In addition to this power, all of these high-level classes are designed to be easily modified using C++ inheritance.
The functionality of CRecordView is built upon the CFormView high-level abstraction introduced in MFC 2.0. CFormView supports many features that true form-processing applications require but which are not available in the native Windows dialog manager, such as scrolling, multiple forms for the same data, synchronous update, and printing.
A CFormView provides a view (a class derived from CView) based on a dialog resource that can be edited with the Visual C++ dialog editor. This view can be used to create form views with arbitrary Windows controls. The user can scroll the form view and tab among controls. The benefit of CFormView over standard dialogs is that CFormView objects integrate with the entire application framework architecture, providing automatic support for command handling and document management. A form view can also be an MDI child window.
CEditView is a simple, plain-text-editor view that has all the functionality of the standard Windows edit control. In addition, however, CEditView supports high-level functionality such as printing, find and replace, cut, copy, paste, and undo, as well as the standard File commands (Open, Save, and Save As). Of course, because CEditView is derived from CView, all of the architectural benefits described above apply. From a simple AppWizard-created application, programmers can use CEditView by simply creating a document template that uses CEditView; applications can have an MDI text editor without the programmers having to derive their own view classes.
Most applications can show only a portion of their data files on the screen at a single time. The CScrollView class, which is another high-level view class derived from CView, supports views that scroll and views that are automatically scaled to the size of the frame window that displays them. By deriving from CScrollView, developers can add the ability to scroll or scale to their view classes. CScrollView manages window sizes and mapping mode for graphics, manages special modes needed for OLE in-place editing, and handles the automatic scrolling in response to user-interface actions such as clicking the scroll bar.
In a splitter window, the window can be split into two or more separately scrollable panes. A splitter control in the window frame next to the scroll bars allows the user to adjust the relative sizes of the panes. Each pane is a different view on the same document. This type of user interface is useful, for example, when a user wishes to view both the beginning and end of a very long document on a single screen. MFC provides the high-level class CSplitterWnd to support this user-interface model. The CSplitterWnd class also supports the two most common types of splitters: dynamic and static. With dynamic splitters, the user can add or remove arbitrary split panes; static splitters have a predefined number of panes. Each of the splitter pane's views can be the same class, or each can be a different derived CView class. In all cases, the application framework automatically manages all aspects of the user interface and standard Windows messages.
CToolBar, CStatusBar, and CDialogBar all derive from the common base class CControlBar. The CControlBar abstraction enables the MFC implementation to reuse code among these classes. CControlBar provides the functionality for automatic layout within the parent frame window of the derived classes. CControlBar demonstrates the power of a base class that provides a partial implementation that is completed in a series of closely related derived classes.
The CStatusBar class implements a row of text-output panes, or indicators. The output panes are commonly used as message lines and status indicators. Examples include the menu help-message lines that briefly describe the selected menu command and the indicators for the keyboard states of Num Lock, Scroll Lock, and Caps Lock. The CStatusBar class supports any number of panes and automatically lays them out based on the width of the contents. Each pane can have a customized style, including three-dimensional borders, pop-out text, disabled, and stretchy. The MFC command architecture supports automatic menu prompt strings, and when using the Visual C++ menu editor to edit menus for MFC applications, programmers can also define the prompt string for the menu item. When creating a new application with AppWizard, developers can specify whether or not the application will provide a status bar.
The CDialogBar class is like a modeless dialog in that it easily supports any combination of Windows controls and is created from a dialog template edited with the Visual C++ dialog editor. Dialog bars support tabbing among controls and can be aligned to the top, bottom, left, or right edge of the enclosing frame window. The most common example of a dialog bar is the print-preview user interface.
With MFC's tradition of providing very good backward compatibility, most MFC 1.0, 2.0, 2.5 and 3.0 programs will work with MFC 4.0 with a few very minor modifications. Very few features of previous versions of MFC are no longer supported in MFC 4.0 or will not be supported in the future.
Obsolete features are in technologies that are replaced by OLE technology.
MFC 1.0 and MFC 2.0 provided nine classes to support version 1.0 of OLE. These classes were obsolete with MFC 2.5 and have been replaced with the OLE 2.0 versions of these classes. Because OLE 2.0 is a functional superset of OLE 1.0 and provides many more features, writing OLE 1.0 applications is no longer recommended.
Microsoft Visual Basic introduced the concept of add-in components known as VBX controls. VBX control functionality is replaced by the new OLE controls model. MFC 4.0 provides support for creating, testing, and using OLE controls.
MFC provides classes that simplify programming for Windows while at the same time permitting application developers to leverage both existing Windows-based code and programming experience. For the inexperienced programmer for Windows, the Microsoft Foundation Class Library simplifies Windows-based programming by providing prebuilt functionality for many standard programming idioms. These classes have evolved from the MFC 1.0 implementation, but backward compatibility has been maintained.
MFC encapsulates the standard application structure in an easily customizable application object. In addition to standard initialization, message processing, and termination, the CWinApp class supports idle-time processing of user-defined operations. Additional features of the CWinApp class include support for profile settings, context-sensitive help, File Manager drag and drop, shell registration for launching the application from File Manager, and other user-interface features. The CWinApp class frees the programmer from the details of the WinMain, LibMain, and WEP routines and provides a standard abstraction across Windows platforms.
Along with an application object, most programs will use a standard frame window. MFC provides support for both the single-document interface (SDI) and the multiple-document interface (MDI). Many of the common MDI commands and user-interface functionality, such as changing the menu bar that is based on the active window, are provided as prebuilt functionality by the framework. In addition, error-prone areas of programming for Windows, such as keyboard accelerators and implementation of default behavior, are handled in a seamless manner by the application framework. Frame windows are managed by the document-template class in applications that take advantage of the document/view architecture. A view is contained within a frame window (usually a CFrameWnd or a CMDIChildWnd).
The MFC 1.0 device-context class, CDC, provided a simple Windows API wrapper. MFC 2.0 extended the CDC implementation to allow polymorphic implementations of device-context output functions. This enables a virtual-display context that allows MFC applications to use the same drawing code to send output to the screen, a printer, a metafile, or a print-preview view. MFC provides a complete set of classes for drawing graphical objects and managing device contexts. These graphical object classes include all of the standard Windows objects, including pens, brushes, bitmaps, fonts, regions, and palettes. Several device-context classes are also supplied to make the handling of common Windows idioms (such as window repainting) simpler and less error-prone. The graphical objects are designed to free system resources automatically when they are no longer needed, which simplifies common object-ownership problems and enables an application to run safely in a resource-constrained environment.
MFC makes it easier to use dialogs within an application. The application framework manages many of the intricate details of Windows-based system-oriented dialogs automatically, including the handling of dialog-specific messages. Dialogs are handled with the CDialog class, which supports both modal and modeless dialogs. Programmers simply derive from a dialog class and customize it by overriding member functions and message handlers. This customization model is exactly like every other CWnd-derived class, which provides good programming consistency.
Controls are windows that are drawn in the client area of frame windows or as controls in a dialog box. MFC provides classes for all of the standard controls: static text, buttons, edit control, list boxes, combo boxes, scroll bars, handwriting controls, and user-defined child windows. MFC makes it easy for developers to derive their own child windows (including deriving from the standard Windows controls) and to customize the behavior of the windows using C++ inheritance and message maps. MFC 4.0 adds classes that support Windows common controls. (See the section titled "Windows Common Control Classes" earlier in this document.)
The general-purpose classes give programmers a wide range of functionality designed to take advantage of the powerful features of C++. These classes are available for programmers to develop the nongraphical portion of the application. In many respects, the general-purpose classes, together with the Windows API classes, are the building blocks for the entire application framework and provide fundamental functionality to those classes as well as programmer-defined classes.
Most MFC classes are derived either directly or indirectly from the class CObject, which provides the most basic object-oriented features of the framework. CObject supports dynamic type checking, which allows the type of an object to be queried at run time. This feature provides programmers with a type-safe means to cast down a pointer from a base class to a derived class. Without dynamic type checking, this cast can be a source of errors and can break the type safety of C++. Most programmers find this feature useful, but because it incurs a very small run-time overhead (approximately 24 bytes per class), its use is optional.
Persistence is the ability of any object to save its state to a persistent storage medium, such as a disk. If a collection is made persistent, then all members of that collection are made persistent. The CArchive class is used to support object persistence and allows type-safe retrieval of object data. To use persistence, a class implementor must override the Serialize member function, call the base class' Serialize function, and then implement the data-storage routines for member data that is specific to a derived class. Entire networks of objects, with references to other objects, including both multiple and circular references, can be saved with a single line of code. As with dynamic type checking, the use of persistence is optional.
MFC excels in the efficiency of standard data structures. The provided collection classes, a standard component of any C++ class library, are well-tested, well-coded, and highly reusable. The MFC collection classes include double-linked list classes, map (dictionary) classes, and dynamic (growable) array classes. All of these have been implemented using the proposed ANSI template syntax for type-safe usage. For example, the list class is supplied with variants supporting UINT, BYTE, WORD, DWORD, void*, CObject*, and CString elements. The map and array classes have similar sets of variants. In all, MFC supplies 17 collection classes. For users who wish to take advantage of the template syntax to generate a type-safe variant of a supplied implementation (or write their own templates), a template-expansion tool written using MFC is provided as a sample application.
The CString class supports a very fast string implementation that is compatible with standard C char* pointers. This class allows strings to be manipulated with syntax similar to the Basic language that includes concatenation operators and functions such as Mid, Left, and Right. CString also provides its own memory management, freeing the programmer from having to allocate and free string memory.
MFC offers three general-purpose file classes: CFile and its two derived classes, CStdioFile and CMemFile. CFile supports low-level binary file I/O (read, write, and seek). CStdioFile provides buffered file I/O similar to the standard I/O run-time libraries. CMemFile supports file semantics in RAM-resident files for managing Clipboard data as well as other forms of interapplication communication. The polymorphism provided by the three file classes (CFile, CStdioFile, and CMemFile) allows the same code to be used for sending data to a variety of destinations using the CFile interface. MFC 2.5 and MFC 4.0 extend the use of the file classes to include compatibility with OLE structure storage (IStream and IStorage).
In addition to the standard time and date functions, a class is provided to conveniently support time-and-date arithmetic using overloaded operators. Binary time values are automatically formatted into human-readable form.
An area overlooked by many class libraries is the inclusion of sophisticated diagnostic and debugging facilities. Incorporated directly into the fabric of MFC is a backbone of diagnostic code that is supported in the debug version of the framework. Applications written with MFC and compiled for debugging can be up to twice as large as their nondebug counterparts—an indication of the extensive diagnostic support within the application framework.
Programmers can add debug code anywhere in an application that will print out all currently allocated heap objects. This capability is invaluable for the detection of serious memory leaks that are often impossible to track by other means. A memory leak is a slow depletion of system resources that can go undetected for several days until all resources are consumed. For all heap-allocated objects, a record is kept of the size, source file, and line number of the allocation. After a debug version of an MFC application terminates, the application framework automatically displays all heap objects that the programmer failed to free.
Other debug support includes functions that are able to validate any pointer and determine if it refers to a genuine C++ CObject-derived object. The framework also provides run-time assertions and class invariants, which were popularized by the Eiffel programming language. Every class in MFC implements a member function that checks the current state of the object and causes a debug assert if the object is not in a proper state. Library member functions validate parameters to functions in the debug version of the framework.
Each of the more than 6,000 ASSERT statements within the implementation of MFC checks the condition of the internal state of a class or parameters passed into an API. If a programmer erroneously causes the application framework to enter an unpredictable state, the application will immediately break into the debugger (if it is running), or an alerting message box will be displayed. ASSERT statements catch errors much earlier and can save hours of development time. All major Microsoft applications use assertion statements extensively. In the release (nondebug) version of an MFC application, ASSERT statements are not executed and generate no code (they are designed for testing purposes only), and thus they incur no cost to the application's end users. The ASSERT mechanism is provided for users of MFC as well, and programmers are encouraged to take advantage of it within their own code.
MFC also provides TRACE statements, which are formatted information messages. As with ASSERT statements, TRACE statements are executed only in the debug version of an application. The TRACE statements in the application framework display possible misuse of a feature, low-memory conditions, rarely executed boundary conditions, and full message and command tracing. Because the output can be verbose (there are over 400 TRACE statements in MFC), it is easy to select which categories of messages are reported using the TRACER.EXE tool. For example, developers who are only interested in information about OLE can filter out all the other TRACE output. The TRACE facility can also be used by programmers within their own codes.