Chapter 1

An Introduction to Microsoft Foundation Classes


Remember when you bought your first VCR? If you got your VCR back when I got mine, it wasn't much more difficult to operate than a standard audio cassette recorder. The VCR had all the standard controls like play, fast forward, rewind, and record. And if you were really lucky, it even had freeze-frame.

If you've purchased a VCR recently, however, you know that there are so many controls and settings that you need a degree in engineering to figure everything out. Today's VCRs include not only freeze-frame, but also slow motion, indexing, multiple-event timers, simulcast recording, multichannel sound, auto repeat, and on-screen clocks. I don't know about you, but to make sure that my recordings come out right, I've resorted to using a checklist to verify that each setting on the VCR is correct.

Programming a computer is a lot like programming a VCR. A few years ago, you could sit down in front of your computer with a simple language like BASIC and a slim volume of instructions and write an impressive program (at least it was impressive for those days). Today, however, if you want to write commercial quality software, you must use sophisticated, object-oriented languages such as C++, and you need enough documentation to cover your desk a foot deep.

Such is progress.

Luckily for today's programmers, while the languages and operating systems are becoming more and more complex, the programming tools are becoming more and more sophisticated. The major Windows compilers today come with code libraries that attempt to make today's programming tasks quicker and easier. This brings us, of course, to the Microsoft Foundation Classes (MFC).

MFC is a C++ code library that simplifies the writing of Windows applications. If you've ever tried to write a Windows program without the help of MFC, you know what an immense task this can be. Using standard C++ programming, you'll need 80 or 90 lines of code just to get an empty window on-screen. A full-fledged Windows application can be immense beyond belief. Using MFC, however, you can get your first window on-screen with only a few lines of code.

Windows Versus MFC

Although Windows is complex, it is a veritable workhorse that handles much of your application's activity automatically. Windows applications usually have a main window with a menu bar, scroll bars, sizing buttons, and other controls all of which are handled to a great extent by Windows. For example, when you create a window with a menu bar, your program doesn't need to control the menu. Windows does this for you, sending your program a message whenever the user selects an item in the menu.

A Windows program can receive hundreds of different messages while it's running. Your application determines whether to respond to these messages or to ignore them. If the user clicks the mouse pointer in your window, for example, your program gets a message (WM_LBUTTONDOWN). If the program determines that the user clicked on something important, the program can handle the message, performing the function the user requested. On the other hand, the program can simply ignore the message and let Windows take care of it. It's up to you.

All of this sounds terrific until you get your first look at a Windows programming manual and see the huge number of functions included in the Application Programming Interface (API). Surely there must be an easier way to program Windows than to plow through thousands of pages of documentation, isn't there?

Yes and no. No matter what route you take, learning to program Windows, although not especially difficult, takes a lot of time and practice. Before you program your first application, you should be familiar with at least the most used functions in the API so that you know the tools you have at your disposal.

However, Microsoft's MFC goes a long way toward simplifying the process of writing Windows applications by hiding many of the details inside custom window classes. As stated earlier in this chapter, by using MFC, you can create a fully operational window with very few lines of code. Of course, learning to use MFC is no picnic, either. MFC has its own set of rules and requirements in addition to those of Windows. This book teaches you those rules and requirements.

The Microsoft Foundation Classes

MFC includes many classes you can use to write your applications more quickly and easily. These classes represent objects from which a Windows application is created objects such as windows, dialog boxes, menu bars, window controls, and many more, including some special objects such as status bars and control bars. In addition, MFC provides many general purpose classes for handling things like strings, arrays, and linked lists.

Specifically, MFC provides the following main categories of classes:

In the following sections, you get a brief look at each of these MFC class categories. If some of the descriptions are confusing at first, don't become discouraged. Most of the classes described in the following sections are covered in detail later in the book, at which point everything will become clear.

The CObject Class

If you examine the MFC class hierarchy, you'll see that almost every class in the library is derived from the CObject class. You might think that a class that is the granddaddy to almost the entire MFC class library would be huge and complex. Ironically, though, CObject is one of the smallest classes in MFC. Of course, if you think a minute, this makes sense. CObject is the base for most MFC classes, so it must contain only the functionality common to all of the classes. With so many diverse classes in MFC, this commonality must be very general in nature.

In fact, CObject includes only eight member functions, including its constructor and destructor. These member functions enable the class to perform basic serialization (saving and reading data from and to storage), to provide run-time class information, and to output diagnostic information. To give you a brief overview of the class, the most important CObject member functions and what they do are shown in Table 1.1. Six other functions (not listed in the table) are overloaded C++ operators. They are not directly useful to the average programmer; they are required by MFC to make MFC more efficient and to prevent programming errors. The remaining method, GetBaseClass(), is used internally by MFC.

Table 1.1 Member Functions of the CObject Class

Function Description
AssertValid() Checks whether an object is in a valid state
CObject() Constructs a CObject object
~CObject() Destructs a CObject object
Dump() Displays debugging information about the class
GetRuntimeClass() Returns information such as the class's name and size
IsKindOf() Checks whether an object is derived from a given class
IsSerializable() Checks whether the object can perform serialization
Serialize() Performs the object's serialization duties

The word serialize is just a fancy term for the act of sending or retrieving data to or from some sort of storage. For example, you might have a class that needs to save and restore the data that the user entered into a form. To do this, you would override CObject's Serialize() function in your class derived (directly or indirectly) from CObject. In Serialize(), you would place the code that actually saves or reads the object's data. As you'll see in Chapter 3, "Documents and Views," MFC supplies the CArchive class, which makes saving and reading data unbelievably easy.

Although CObject acts as the base class for the majority of MFC classes, you can derive your own custom classes from CObject and, thus, automatically acquire built-in support for the functionality built into CObject most notably the capability to serialize your custom object. Any custom class you want to develop that needs to save and load data should be derived, directly or indirectly, from CObject.

The Application Class

Every MFC program begins life as an application object. You derive this application object from MFC's CWinApp class, which provides initialization, runtime, and ending services for your Windows program. More specifically, CWinApp registers, creates, and shows an application's main window; sets the application's message loop running (so that the application can interact with the user and Windows); and deletes the application when the user is finished. CWinApp also provides some additional services, such as providing access to the application's command line, handling file activity, processing Windows messages, and detecting when Windows is idle. Every MFC program instantiates a CWinApp-derived object.

In the MFC hierarchy, CWinApp is derived from CWinThread, which is, in turn, derived from CCmdTarget (Figure 1.1). The CWinThread class takes care of thread-related tasks. Because every process running under Windows 95 requires at least one thread of execution, CWinApp is derived from CWinThread. However, CWinThread also provides the power needed to build multithreaded applications.


FIG. 1.1

The CWinApp class is derived from CWinThread.

A thread is nothing more than a subprocess or, more specifically, a path of execution within a process. Your application is a process that contains at least one thread, which is the main thread. Your application can also contain a number of other threads, each of which performs some useful task on behalf of the application. For example, you might want to create a thread that recalculates some values while the main thread continues to gather user input. In a way, you can think of threads as a way of implementing multitasking from within an application, rather than a system, context.

Finally, all MFC classes that must respond to Windows messages can trace their ancestry back to CCmdTarget, which handles MFC's message-mapping. Message-mapping is the process of matching member functions in a class to the Windows messages to which the functions must respond. For example, MFC can map the WM_LBUTTONDOWN message to a message-response function called OnLButtonDown(), which enables your application to automatically respond to left mouse-button clicks without having to resort to clumsy switch statements like those used in a conventional C Windows program.

Thanks to its rich heritage, the CWinApp class can do a lot of work for your application. Its public data members contain handy information about an application, and its member functions enable your application to do everything from create a main window to handle file commands. Table 1.2 lists the most useful CWinApp's public data members, whereas Table 1.3 lists some of CWinApp's most useful member functions. Look over these tables in order to get an idea about this class works.

Table 1.2 Public Data Members of the CWinApp Class

Data member Description
m_bHelpMode Indicates whether the application is in Help context mode
m_hInstance The current instance's handle
m_hPrevInstance The previous instance's handle
m_lpCmdLine A pointer to the application's command line
m_nCmdShow A value indicating how the window is initially displayed
m_pMainWindow A pointer to the application's main frame window
m_pszAppName A pointer to the application's name
m_pszExeName A pointer to the application's module name
m_pszHelpFilePath A pointer to a string holding the application's help-file path
m_pszProfileName A pointer to the application's .INI filename

Table 1.3 Handy CWinApp Member Functions

Function Description
ExitInstance() Performs shutdown cleanup for an instance of the application
GetProfileString() Loads a string from the application's .INI file
InitInstance() Performs start-up initialization for an instance of the application
LoadCursor() Loads a cursor for the application
LoadIcon() Loads an icon for the application
OnIdle() Performs idle-time processing
ParseCommandLine() Parses command lines into individual parameters
ProcessShellCommand() Handles command lines used to run an application
SaveAllModified() Reminds the user to save any changed documents
SetRegistryKey() Stores application settings in the Registry
WriteProfileString() Saves a string to the application's .INI file

Many of the functions listed in Table 1.3 are virtual functions that you override in the class that you derived from CWinApp. For example, when you want to provide an instance of your application with start-up initialization, you would override InitInstance() in your application class. Similarly, to perform last minute cleanup for an instance of your application, you'd override the ExitInstance() function. By overriding virtual functions of an MFC class, you can customize the class to perform exactly as you want it to.

The Window Classes

When you create a basic MFC application, it's up to you to tell MFC the type of main window it should create for the application. This is where MFC's window classes come in. By forcing your MFC application to create your custom main window, you can add all the functionality you need to your application. To make this task easier for you, MFC features several different types of windows. These windows include the following:

All of the window classes are derived from the CWnd base class, which supplies the basic functionality required by any window class. This functionality includes initialization, positioning and sizing, painting, coordinate mapping, scrolling, message handling, and much more. There are, in fact, over 250 member functions in the CWnd class, far too many to list in this chapter. The CWnd class, however, has only one public data member, m_hWnd, which is the handle of the window with which the class is associated. Although you can derive your own window classes directly from CWnd, you're more likely to use one of MFC's specialized window classes. Some of these window classes are discussed in the sections that follow.

Frame Windows

Frame windows, represented by the CFrameWnd class, supply all the functionality of the CWnd class (it is, after all, directly derived from CWnd, as shown in Figure 1.2), and also handle document/view matters, the menu bar, control bars, accelerators, and more. Frame windows also act as the base class from which four other MFC window classes are derived. These classes are CMDIChildWnd, CMDIFrameWnd, CMiniFrameWnd, and COleIPFrameWnd.


FIG. 1.2

The CFrameWnd class is derived from CWnd.

The CFrameWnd class contains only two public data members, m_bAutoMenuEnable and rectDefault, which controls whether menu items are enabled or disabled automatically and controls the window's starting size and position, respectively. Table 1.4 lists some of the more important CFrameWnd class's member functions.

Table 1.4 Member Functions of the CFrameWnd Class

Function Description
ActivateFrame() Activates the frame window
CFrameWnd() Constructs a CFrameWnd object
Create() Creates the frame window
GetActiveDocument() Returns a pointer to the active document
GetActiveFrame() Returns a pointer to the active frame
GetActiveView() Returns a pointer to the active view
LoadAccelTable() Loads an accelerator table
LoadFrame() Creates a frame window using resource information
OnContextHelp() Enables context-sensitive help
OnCreateClient() Creates a client window for the frame window
OnSetPreviewMode() Controls print-preview mode
RecalcLayout() Positions the frame window's control bars
SetActiveView() Activates a view object

In most cases, you'll derive the main window class for an SDI (single-document interface) application from the CFrameWnd class. Such a frame window usually has a complete set of window controls such as minimize, maximize, restore, and close buttons and holds the application's menu bar, toolbar, and status bar. However, MFC is flexible enough that you can create just about any type of frame window that you need from the CFrameWnd class.

View Windows

To make it easier to handle the data associated with an application's window, MFC offers the document/view architecture. Although "document/view architecture" sounds kind of scary, it's really little more than a way to separate data from the way an application displays that data. The CDocument class (which boasts CCmdTarget and CObject as ancestors) is responsible for storing a window's data, whereas the CView class (which traces its ancestry down through CWnd, CCmdTarget, and finally CObject) displays the data, as well as enables the user to manipulate the data.

The CView class (Figure 1.3) provides all the functionality needed by a generic view window. This includes displaying data in the frame window's client area and printing data. A document can be associated with more than one view. For example, you could have a document that stores plain text. This document could be associated with a view that displays the text normally and another view that displays the text as hexadecimal ASCII values. Although a document can have more than one view, an individual view must always be associated with only a single document. Table 1.5 lists the more useful CView class's member functions and what they do.


FIG. 1.3

The CView class is derived from CWnd.

Table 1.5 Member Functions of the CView Class

Function Description
CView() Constructs a CView object
DoPreparePrinting() Initializes a print context
GetDocument() Retrieves the document attached to the view
IsSelected() Determines whether an OLE item in a document is selected
OnActivateView() Called whenever the view is activated
OnBeginPrinting() Called at the start of a print job
OnDraw() Creates the view of the document, usually in a window
OnEndPrinting() Called at the end of a print job
OnEndPrintPreview() Called when the user leaves print preview
OnPrepareDC() Called before OnDraw() or OnPrint() to modify the device context or handle pagination
OnPreparePrinting() Initializes the Print dialog box
OnPrint() Prints a page of the document or displays the print preview
OnUpdate() Called when the document attached to the view has changed

As you may have guessed, MFC derives many specialized view classes from the general CView class. These include CCtrlView, CEditView, CListView, CRichEditView, CTreeView, CScrollView, CFormView, CDaoRecordView, and CRecordView. You can tell by the class names what many of these classes do. You'll also run into many of them later in this book. Of course, you can derive your own custom view classes from CView.

MDI Windows

Most document-oriented Windows applications enable the user to open more than one document simultaneously. Such applications use Windows' MDI (multiple-document interface) to handle the extra chores that must be performed to handle several documents concurrently. MFC provides the CMDIFrameWnd class (which traces its lineage back through the CFrameWnd, CWnd, CCmdTarget, and CObject classes, as shown in Figure 1.4) to encapsulate the extra functionality needed by MDI frame windows. This extra functionality includes handling the MDI client window, which provides an area for MDI child (document) windows; managing the main and child-window menu bars; forwarding messages to MDI child windows; and arranging MDI child windows within the client window (that is, responding to Tile, Cascade, and Arrange commands found on an MDI application's Window menu). Table 1.6 lists the CMDIFrameWnd class's member functions.


FIG. 1.4

The CMDIFrameWnd class is derived from CFrameWnd.

Table 1.6 Member Functions of the CMDIFrameWnd Class

Function Description
CMDIFrameWnd() Constructs a CMDIFrameWnd object
CreateClient() Creates a client window for a frame window
GetWindowPopupMenu() Returns a handle to the Window menu
MDIActivate() Activates a child (document) window
MDICascade() Places all child windows into a cascaded arrangement
MDIGetActive() Returns a pointer to the active child window
MDIIconArrange() Arranges document icons within the client window
MDIMaximize() Maximizes a child window
MDINext() Activates the next child window (going by Z order)
MDIRestore() Restores a child window to its original size
MDISetMenu() Changes the frame window's menu
MDITile() Places all child windows into a tiled arrangement

In order to display the different documents associated with the MDI application, you need to create MDI child windows, which are represented in MFC by the CMDIChildWnd class. The CMDIChildWnd class is found on the same level of the MFC hierarchy as the CMDIFrameWnd class (Figure 1.5), tracing its ancestors from CFrameWnd, back through CWnd, CCmdTarget, and CObject. You can tell by this hierarchy that windows of the CMDIChildWnd class must be a lot like CFrameWnd frame windows. This is because MDI child windows have much the same relationship with their MDI frame window as SDI frame windows have with the Windows desktop. Just like regular frame windows, MDI child windows can contain view windows (instantiated from CView) that depict the data stored in a document object (instantiated from CDocument).


FIG. 1.5

The CMDIChildWnd Class is Derived from CFrameWnd.

Thanks to object-oriented programming (OOP) inheritance, the CMDIChildWnd class gets most of its functionality from the CFrameWnd class. However, the CMDIChildWnd class adds the abilities to share a menu between MDI child windows associated with the same document (this is the menu that replaces the default frame-window menu whenever an MDI child window is active) and to handle changes to the frame window, depending on the active MDI child window. An example of such a change is placing the document's name in the frame window's title bar. Table 1.7 lists the member functions of the CMDIChildWnd class.

Table 1.7 Member Functions of the CMDIChildWnd Class

Function Description
CMDIChildWnd() Constructs a CMDIChildWnd object
Create() Creates an MDI child window
GetMDIFrame() Returns a pointer to the MDI child window's frame window
MDIActivate() Activates the MDI child window
MDIDestroy() Destroys the MDI child window
MDIMaximize() Maximizes the MDI child window
MDIRestore() Restores the MDI child window to its original size

Dialog Boxes

Most Windows applications rely on dialog boxes to retrieve information from the user. Because dialog boxes are so ubiquitous in Windows programming, MFC features a whole set of classes dedicated to these specialized windows. MFC features a basic dialog box class, CDialog (Figure 1.6), which handles all the details of constructing, executing, and closing a dialog box, including built-in responses for the most often used buttons and a mechanism for transferring data to and from the dialog box. In addition, your MFC dialog boxes can be modal or modeless and can contain any number of controls.


FIG. 1.6

The CDialog class is derived from CWnd.

MFC also includes classes for Windows' common dialog boxes and other "prefab" dialog boxes. These dialog classes including CColorDialog, CFileDialog, CFindReplaceDialog, CFontDialog, and CPrintDialog enable users to select file names, find text strings, set up a printer, and choose colors and fonts. The common dialog classes are derived from CCommonDialog (Figure 1.7), which is itself derived from CDialog.


FIG. 1.7

The CCommonDialog class is derived from CDialog.

You actually create your dialog box using a resource editor such as the dialog box editor included as part of the Microsoft Developer Studio, which comes with Visual C++. The dialog box you create with the editor comprises the visual elements of the dialog box, including the dialog box's main window and all of the controls that window contains. To add MFC functionality to the dialog box, you then derive a class from CDialog, attaching that class to the dialog box template you created with the dialog box editor.

To pass data to and from the dialog box, you create data members for the class and associate those data members with the controls for which they are to store data. You can then initialize the dialog box controls by setting these data members. Similarly, you can retrieve data from the dialog box's controls after it's closed by checking the contents of the associated data members. Table 1.8 lists CDialog's member functions.

Table 1.8 Member Functions of the CDialog Class

Function Description
CDialog() Constructs a CDialog object
Create() Creates a modeless dialog box associated with the class
CreateIndirect() Creates a modeless dialog box from a template stored in memory
DoModal() Displays a modal dialog box
EndDialog() Closes a modal dialog box
GetDefID() Returns the default button control's ID
GotoDlgCtrl() Moves the focus to a given dialog box control
InitModalIndirect() Creates a modal dialog box from a template stored in memory
MapDialogRect() Converts dialog box measurements to screen measurements
NextDlgCtrl() Moves the focus to the next dialog box control
OnCancel() Responds to the dialog box's Cancel button
OnInitDialog() Initializes a dialog box immediately before it's displayed
OnOK() Responds to the dialog box's OK button
OnSetFont() Sets a dialog box's font
PrevDlgCtrl() Moves the focus to the previous dialog box control
SetDefID() Sets the default button for the dialog box
SetHelpID() Sets the dialog box's context-sensitive help ID

Property Sheets

Windows 95 uses a lot of special multipage dialog boxes called property sheets (Figure 1.8). Because a property sheet features tab controls, the user can easily flip from page to page and, so, quickly find the information needed, without having to decipher a cluttered dialog box or search through a series of standard one-page dialog boxes. MFC supports property sheets through its class CPropertySheet, which is derived from CWnd as shown in Figure 1.9.


FIG. 1.8

Property sheets organize information into tabbed pages.


FIG. 1.9

The CPropertySheet class is derived from CWnd.

The CPropertySheet class works in conjunction with the CPropertyPage class, which represents each page in your property sheet. Because each page of a property sheet is very similar to a dialog box, you might not be surprised to learn that the CPropertyPage class is derived from CDialog, as shown in Figure 1.10. To create a property sheet, you use a dialog box editor to create each page. You then derive a class from CPropertyPage for each page of the property sheet, associating each derived class with a property sheet page. Finally, you create the CPropertySheet object that will hold the page objects.


FIG. 1.10

The CPropertyPage class is derived from CDialog.

The CPropertySheet class has a single data member, m_psh, which is a pointer to a PROPSHEETHEADER structure. This structure holds information about the property sheet, as you'll learn later in this book, in Chapter 12, "Property Sheets and Wizards." The CPropertyPage class has a single data member, m_psp, which is a pointer to a PROPSHEETPAGE structure. This structure holds information about the property page. Table 1.9 lists the CPropertySheet class's member functions, whereas Table 1.10 lists the CPropertyPage class's member functions.

Table 1.9 Member Functions of the CPropertySheet Class

Function Description
AddPage() Adds a page to a property sheet
Construct() Constructs CPropertySheet objects stored objects in an array
CPropertySheet() Constructs a CPropertySheet object
Create() Creates and displays a modeless property sheet
DoModal() Displays a modal property sheet
EndDialog() Closes a property sheet
GetActiveIndex() Returns the index of the property sheet's active page
GetActivePage() Returns a pointer to the property sheet's active page
GetPage() Returns a pointer to a specific property sheet page
GetPageCount() Returns the number of pages in the property sheet
GetPageIndex() Returns the index of a specific property sheet page
GetTabControl() Returns a pointer to a tab
PressButton() Selects a button in a property sheet
RemovePage() Removes a page from a property sheet
SetActivePage() Sets the property sheet's active page
SetFinishText() Sets the Finish button's text in a wizard property sheet
SetTitle() Sets the property sheet's caption
SetWizardButtons() Enables or disables the Finish, Next, and Back wizard
buttons in a wizard property sheet
SetWizardMode() Makes a property page a wizard property page

Table 1.10 Member Functions of the CPropertyPage Class

Function Description
CancelToClose() Disables the cancel button and changes the OK button to a Close button.
Construct Constructs CPropertyPage objects stored in an array
CPropertyPage Constructs a CPropertyPage object
OnApply() Responds to the Apply Now button
OnCancel() Responds to the Cancel button
OnKillActive() Validates data when a page is no longer active
OnOK() Responds to the OK, Close, or Apply Now buttons
OnQueryCancel() Responds to the Cancel button before the cancel process begins
OnReset() Responds to the Cancel button
OnSetActive() Responds when a page is activated
OnWizardBack() Responds to a wizard property sheet's Back button
OnWizardFinish() Responds to a wizard property sheet's Finish button
OnWizardNext() Responds to a wizard property sheet's Next button
QuerySiblings() Sends a specified message to each property sheet page.
SetModified() Enables or disables the Apply Now button

When looking over Tables 1.9 and 1.10, you might have noticed the word "wizard" used in the class member function names and descriptions. Besides creating regular property sheets with the CPropertySheet and CPropertyPage classes, you can also create wizards, which guide the user step-by-step through a complex process. Incorporating wizards into your programs can make your applications much easier to use.

Other Important MFC Classes

Although the various MFC window classes are the most used classes in the library, in order to create a full-fledged Windows application, those window classes rely heavily on the many classes that encapsulate Windows' menus, graphics, and controls. In addition, many applications will draw upon the MFC file and database classes. In the sections that follow, you get a quick look at these important special classes.

The CMenu Class

Almost every Windows application sports some sort of menu bar, so it only stands to reason that MFC would have a special class for dealing with menus. That class is CMenu, which enables an application to manipulate a Windows menu in various ways, including associating a menu with the class, creating and destroying menus, checking and enabling/disabling menu items, adding bitmaps to menu items, and more. As shown in Figure 1.11, the CMenu class is derived from CObject.


FIG. 1.11

The CMenu class is derived from CObject.

The CDC and CGDIObject Classes

In order to be useful, most Windows applications have to display some sort of data in their windows. A word processor, for example, must display the text of the currently loaded document, whereas a graphics editor must display the bitmap on which the user is currently working. To display data in a window, an application must obtain a device context (DC) and then call functions of Windows' Graphics Device Interface (GDI) to display graphics on the surface represented by the DC. MFC's huge CDC class represents DC's, whereas the CGDIObject class (and all of the classes derived from CGDIObject) represent the objects such as pens and brushes that can be used with a DC.

The CDC class is derived directly from CObject and features hundreds of member functions that, not only encapsulate most of the GDI's functions, but also add some handy functionality of their own. Although you can create CDC objects in your programs, you'll most often create objects from one of the classes derived from CDC (Figure 1.12). These classes CPaintDC, CClientDC, CWindowDC, and CMetaFileDC provide special DCs for specific uses. For example, the CClientDC class represents a DC for the client area of a window, whereas CWindowDC provides access to the entire window, including both its client and nonclient areas.


FIG. 1.12

The CDC class is derived from CObject.

 

A device context (DC) is nothing more than a collection of attributes that determines the type of surface that you can draw on and the specific objects including pens, brushes, and fonts you can use to do that drawing. Each of these drawing objects has its own attributes that are controlled by the DC. For example, when a DC is first created, it contains a default black pen for drawing lines. If you want to draw red lines, you must create a red pen and replace the black pen with the newly created red pen.

CGDIObject is the base class for MFC's drawing-object classes. As you can see from Figure 1.13, these drawing-object classes are, CPen, CBrush, CBitmap, CFont, CPalette, and CRgn and are derived from CGDIObject, which is in turn derived from CObject. To use MFC's classes to draw data in a window, you first create the appropriate CDC object, create and select into the DC the drawing objects you need, and then use the objects to do the drawing.

See “Painting a Window,” (ch 5)


FIG. 1.13

The drawing-object classes are derived from CGDIObject.

The Control classes

One of Windows' most identifiable features is its various controls, including buttons, edit boxes, scroll bars, and list boxes. In addition, Windows 95 adds a collection of new, common controls that assist programmers to create professional and powerful applications. These special common controls include animation, progress, slider, spin, and rich text controls. All of these Windows controls are represented by a collection of classes derived from CWnd, as shown in Figure 1.14, which lists only some of the most commonly used controls.


FIG. 1.14

The control classes are derived from CWnd.

The Windows 95 user interface also features toolbars and status bars, which are encapsulated by MFC's CToolBar and CStatusBar classes. The CToolBar and CStatusBar controls are derived from a special control bar class, called, appropriately enough, CControlBar. The control bar class hierarchy is shown in Figure 1.15.

See “Toolbars and Status Bars,” (ch 11)


FIG. 1.15

The control bar classes are derived from CControlBar.

The CArchive and CFile classes

Most applications, no matter what operating system they run under, must save and load data. In the past, writing the code that handles these file tasks took a great deal of time and effort, forcing the programmer to operate at a level much closer to the hardware than was often comfortable. Because the whole point of creating a library of classes is to make things easier for the programmer, MFC doesn't overlook file handling. The CArchive and CFile classes work together to make the saving and loading of data as painless as possible to perform.

The CFile class, directly derived from CObject (Figure 1.16), enables a program to open a file by simply creating a CFile object. After creating the CFile object, the program can manipulate the file in various ways by calling the CFile object's member functions. For example, reading and writing can be performed by calling the CFile object's Read() and Write() member functions. Other member functions enable the program to get the size of the file, get the status of the file, rename the file, seek to a specific position within the file, and more.


FIG. 1.16

The CFile class is derived from CObject.

Some other interesting classes that can trace their ancestry back to CFile are CInternetFile, CGopherFile, and CHttpFile, which, along with Internet classes like CInternetConnection, make handling data transfer on the Internet remarkably easy.

Closely related to CFile is the CArchive class, which encapsulates the serialization of an object's data. To create a CArchive object, you must have first created a CFile object, which you pass as a parameter to the CArchive class's constructor. The CArchive class is much simpler than CFile in that it provides fewer member functions. In fact, CArchive's member functions do little more than read and write data. CArchive is a class unto itself that is, it is not derived from any other MFC class.

The Database Classes

If you've programmed in a corporate environment, you've undoubtedly had to do extensive work with databases. Databases are a corporation's oxygen; without databases, the corporations would not survive. Unfortunately, there are many types of databases and database managers, so it takes much experience to become familiar with the many ways databases can store and manipulate data.

MFC to the rescue! MFC provides ODBC (Open Database Connectivity), as well as DAO (Database Access Object), classes. Both of these class libraries work similarly, enabling you to program front-end database applications without being too concerned with the details of how the database is implemented. The big difference is that the DAO classes rely on Microsoft's Jet database engine, whereas the ODBC classes encapsulate the ODBC API, which processes database access requests through an ODBC driver.

If all of this DAO and ODBC talk sounds like a lot of high tech mumbo-jumbo, you'll be pleased to know that Chapter 22, “Database Programming,” deals with these subjects in greater detail. After you've worked through that chapter, you'll be able to dazzle even the big boys with your database prowess. As shown in Figures 1.17 and 1.18, the DAO and ODBC classes are derived from MFC's CObject base class.


FIG. 1.17

The DAO database classes are derived from CObject.


FIG. 1.18

The OBDC database classes are also derived from CObject.

The General Support Classes

MFC features a host of other classes that do everything from handling linked lists to enabling you to create OLE applications. The following list introduces you to some of these many classes:

As you can see, MFC provides a class for just about anything you can think of. And, there are many other classes that I haven't even mentioned in this introductory chapter. However, in spite of this slight lack, you should now have a pretty good idea of what MFC can do for you and your programming projects. If you're feeling a bit overwhelmed, you're not alone, I assure you. There's a lot to learn. As you work through this book, you'll become more and more comfortable with MFC's strange ways. Soon, you might wonder how you ever got along without MFC.