Introduction to MFC Programming with Visual
C++ v5.x
Introduction to MFC
Visual C++ is much more than a compiler. It is a complete application
development environment that, when used as intended, lets you fully exploit the object
oriented nature of C++ to create professional Windows applications. In order to take
advantage of these features, you need to understand the C++ programming language. If you
have never used C++, please turn to the C++ tutorials in the C/C++ Tutorials page for an
introduction. You must then understand the Microsoft Foundation Class (MFC) hierarchy.
This class hierarchy encapsulates the user interface portion of the Windows API, and makes
it significantly easier to create Windows applications in an object oriented way. This
hierarchy is available for and compatible with all versions of Windows. The code you
create in MFC is extremely portable.
These tutorials introduce the fundamental concepts and vocabulary behind MFC and event driven programming. In this tutorial you will enter, compile, and run a simple MFC program using Visual C++. Tutotial 2 provides a detailed explanation of the code used in Tutorial 1. Tutorial 3 discusses MFC controls and their customization. Tutorial 4 covers message maps, which let you handle events in MFC.
Let's say you want to create a Windows application. You might, for example, need to create a specialized text or drawing editor, or a program that finds files on a large hard disk, or an application that lets a user visualize the interrelationships in a big data set. Where do you begin?
A good starting place is the design of the user interface. First, decide what the user should be able to do with the program and then pick a set of user interface objects accordingly. The Windows user interface has a number of standard controls, such as buttons, menus, scroll bars, and lists, that are already familiar to Windows users. With this in mind, the programmer must choose a set of controls and decide how they should be arranged on screen. A time-honored procedure is to make a rough sketch of the proposed user interface (by tradition on a napkin or the back of an envelope) and play with the elements until they feel right. For small projects, or for the early prototyping phase of a larger project, this is sufficient.
The next step is to implement the code. When creating a program for any Windows platform, the programmer has two choices: C or C++. With C, the programmer codes at the level of the Windows Application Program Interface (API). This interface consists of a collection of hundreds of C functions described in the Window's API Reference books. For Window's NT, the API is typically referred to as the "Win32 API," to distinguish it from the original 16-bit API of lower-level Windows products like Windows 3.1.
Microsoft also provides a C++ library that sits on top of any of the Windows APIs and makes the programmer's job easier. Called the Microsoft Foundation Class library (MFC), this library's primary advantage is efficiency. It greatly reduces the amount of code that must be written to create a Windows program. It also provides all the advantages normally found in C++ programming, such as inheritance and encapsulation. MFC is portable, so that, for example, code created under Windows 3.1 can move to Windows NT or Windows 95 very easily. MFC is therefore the preferred method for developing Windows applications and will be used throughout these tutorials.
When you use MFC, you write code that creates the necessary user interface controls and customizes their appearance. You also write code that responds when the user manipulates these controls. For example, if the user clicks a button, you want to have code in place that responds appropriately. It is this sort of event-handling code that will form the bulk of any application. Once the application responds correctly to all of the available controls, it is finished.
You can see from this discussion that the creation of a Windows program is a straightforward process when using MFC. The goal of these tutorials is to fill in the details and to show the techniques you can use to create professional applications as quickly as possible. The Visual C++ application development environment is specifically tuned to MFC, so by learning MFC and Visual C++ together you can significantly increase your power as an application developer.
The vocabulary used to talk about user interface features and software development in Windows is basic but unique. Here we review a few definitions to make discussion easier for those who are new to the environment.
Windows applications use several standard user controls:
![]() |
Static text labels |
![]() |
Push buttons |
![]() |
List boxes |
![]() |
Combo boxes (a more advanced form of list) |
![]() |
Radio boxes |
![]() |
Check boxes |
![]() |
Editable text areas (single and multi-line) |
![]() |
Scroll bars |
You can create these controls either in code or through a "resource editor" that can create dialogs and the controls inside of them. In this set of tutorials we will examine how to create them in code. See the tutorials on the AppWizard and ClassWizard on the MFC Tutorials page for an introduction to the resource editor for dialogs.
Windows supports several types of application windows. A typical application will live inside a "frame window". A frame window is a fully featured main window that the user can re-size, minimize, maximize to fill the screen, and so on. Windows also supports two types of dialog boxes: modal and modeless. A modal dialog box, once on the screen, blocks input to the rest of the application until it is answered. A modeless dialog box can appear at the same time as the application and seems to "float above" it to keep from being overlaid.
Most simple Windows applications use a Single Document Interface, or SDI, frame. The Clock, PIF editor, and Notepad are examples of SDI applications. Windows also provides an organizing scheme called the Multiple Document Interface, or MDI for more complicated applications. The MDI system allows the user to view multiple documents at the same time within a single instance of an application. For example, a text editor might allow the user to open multiple files simultaneously. When implemented with MDI, the application presents a large application window that can hold multiple sub-windows, each containing a document. The single main menu is held by the main application window and it applies to the top-most window held within the MDI frame. Individual windows can be iconified or expanded as desired within the MDI frame, or the entire MDI frame can be minimized into a single icon on the desktop. The MDI interface gives the impression of a second desktop out on the desktop, and it goes a long way towards organizing and removing window clutter.
Each application that you create will use its own unique set of controls, its own menu structure, and its own dialog boxes. A great deal of the effort that goes into creating any good application interface lies in the choice and organization of these interface objects. Visual C++, along with its resource editors, makes the creation and customization of these interface objects extremely easy.
All window-based GUIs contain the same basic elements and all operate in the same way. On screen the user sees a group of windows, each of which contains controls, icons, objects and such that are manipulated with the mouse or the keyboard. The interface objects seen by the user are the same from system to system: push buttons, scroll bars, icons, dialog boxes, pull down menus, etc. These interface objects all work the same way, although some have minor differences in their "look and feel." For example, scroll bars look slightly different as you move from Windows to the Mac to Motif, but they all do the same thing.
From a programmer's standpoint, the systems are all similar in concept, although they differ radically in their specifics. To create a GUI program, the programmer first puts all of the needed user interface controls into a window. For example, if the programmer is trying to create a simple program such as a Fahrenheit to Celsius converter, then the programmer selects user interface objects appropriate to the task and displays them on screen. In this example, the programmer might let the user enter a temperature in an editable text area, display the converted temperature in another un-editable text area, and let the user exit the program by clicking on a push-button labeled "quit".
As the user manipulates the application's controls, the program must respond appropriately. The responses are determined by the user's actions on the different controls using the mouse and the keyboard. Each user interface object on the screen will respond to events differently. For example, if the user clicks the Quit button, the button must update the screen appropriately, highlighting itself as necessary. Then the program must respond by quitting. Normally the button manages its appearance itself, and the program in some way receives a message from the button that says, "The quit button was pressed. Do something about it." The program responds by exiting.
Windows follows this same general pattern. In a typical application you will create a main window and place inside it different user interface controls. These controls are often referred to as child windows-each control is like a smaller and more specialized sub-window inside the main application window. As the application programmer, you manipulate the controls by sending messages via function calls, and they respond to user actions by sending messages back to your code.
If you have never done any "event-driven" programming, then all of this may seem foreign to you. However, the event-driven style of programming is easy to understand. The exact details depend on the system and the level at which you are interfacing with it, but the basic concepts are similar. In an event-driven interface, the application paints several (or many) user interface objects such as buttons, text areas, and menus onto the screen. Now the application waits-typically in a piece of code called an event loop-for the user to do something. The user can do anything to any of the objects on screen using either the mouse or the keyboard. The user might click one of the buttons, for example. The mouse click is called an event. Event driven systems define events for user actions such as mouse clicks and keystrokes, as well as for system activities such as screen updating.
At the lowest level of abstraction, you have to respond to each event in a fair amount of detail. This is the case when you are writing normal C code directly to the API. In such a scenario, you receive the mouse-click event in some sort of structure. Code in your event loop looks at different fields in the structure, determines which user interface object was affected, perhaps highlights the object in some way to give the user visual feedback, and then performs the appropriate action for that object and event. When there are many objects on the screen the application becomes very large. It can take quite a bit of code simply to figure out which object was clicked and what to do about it.
Fortunately, you can work at a much higher level of abstraction. In MFC, almost all these low-level implementation details are handled for you. If you want to place a user interface object on the screen, you create it with two lines of code. If the user clicks on a button, the button does everything needed to update its appearance on the screen and then calls a pre-arranged function in your program. This function contains the code that implements the appropriate action for the button. MFC handles all the details for you: You create the button and tell it about a specific handler function, and it calls your function when the user presses it. Tutorial 4 shows you how to handle events using message maps
One of the best ways to begin understanding the structure and style of a typical MFC program is to enter, compile, and run a small example. The listing below contains a simple "hello world" program. If this is the first time you've seen this sort of program, it probably will not make a lot of sense initially. Don't worry about that. We will examine the code in detail in the next tutorial. For now, the goal is to use the Visual C++ environment to create, compile and execute this simple program.
//hello.cpp #include <afxwin.h> // Declare the application class class CHelloApp : public CWinApp { public: virtual BOOL InitInstance(); }; // Create an instance of the application class CHelloApp HelloApp; // Declare the main window class class CHelloWindow : public CFrameWnd { CStatic* cs; public: CHelloWindow(); }; // The InitInstance function is called each // time the application first executes. BOOL CHelloApp::InitInstance() { m_pMainWnd = new CHelloWindow(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } // The constructor for the window class CHelloWindow::CHelloWindow() { // Create the window itself Create(NULL, "Hello World!", WS_OVERLAPPEDWINDOW, CRect(0,0,200,200)); // Create a static label cs = new CStatic(); cs->Create("hello world", WS_CHILD|WS_VISIBLE|SS_CENTER, CRect(50,80,150,150), this); }
This small program does three things. First, it creates an "application object." Every MFC program you write will have a single application object that handles the initialization details of MFC and Windows. Next, the application creates a single window on the screen to act as the main application window. Finally, inside that window the application creates a single static text label containing the words "hello world". We will look at this program in detail in the next tutorial to gain a complete understanding of its structure.
The steps necessary to enter and compile this program are straightforward. If you have not yet installed Visual C++ on your machine, do so now. You will have the option of creating standard and custom installations. For the purposes of these tutorials a standard installation is suitable and after answering two or three simple questions the rest of the installation is quick and painless.
The compilation instructions supplied here apply specifically to Visual C++ version 5.x under Windows NT or Windows 95. If you are using Visual C++ version 1.5, 2.x, 4.x, or 6.x then you will want to see the tutorials for these versions on the MFC Tutorials page.
Start VC++ by double clicking on its icon in the Visual C++ group of the Program Manager. If you have just installed the product, you will see an empty window with a menu bar. If VC++ has been used before on this machine, it is possible for it to come up in several different states because VC++ remembers and automatically reopens the project and files in use the last time it exited. What we want right now is a state where it has no project or code loaded. If the program starts with a dialog that says it was unable to find a certain file, clear the dialog by clicking the "No" button. Go to the Window menu and select the Close All option if it is available. Go to the File menu and select the Close option if it is available to close any remaining windows. Now you are at the proper starting point. If you have just installed the package, you will see a window that looks something like this:
This screen can be rather intimidating the first time you see it. To eliminate some of the intimidation, click on the lower of the two "x" buttons that you see in the upper right hand corner of the screen if it is available. This action will let you close the "InfoViewer Topic" window. You may later get that window back if you desire by clicking on the little house button in the InfoViewer toolbar. If you want to get rid of the InfoViewer toolbar as well, you can drag it so it docks somewhere along the side of the window, or close it and later get it back by choosing the Customize option in the Tools menu.
What you see now is "normal". Along the top is the menu bar and several toolbars. Along the left side are all of the topics available from the on-line book collection (you might want to explore by double clicking on several of the items you see there - the collection of information found in the on-line books is gigantic). Along the bottom is a status window where various messages will be displayed.
Now what? What you would like to do is type in the above program, compile it and run it. Before you start, switch to the File Manager (or the MS-DOS prompt) and make sure your drive has at least five megabytes of free space available. Then take the following steps.
In order to compile any code in Visual C++, you have to create a project. With a very small program like this the project seems like overkill, but in any real program the project concept is quite useful. A project holds three different types of information:
If you are familiar with makefiles, then it is easy to think of a project as a machine-generated makefile that has a very easy-to-understand user interface to manipulate it. For now we will create a very simple project file and use it to compile HELLO.CPP.
To create a new project for HELLO.CPP, choose the New option in the File menu. Under the Projects tab, highlight Win32 Application. In the Location field type an appropriate path name or click the Browse button. Type the word "hello" in for the project name, and you will see that word echoed in the Location field as well. Click the OK button. Visual C++ will create a new subdirectory named HELLO and place the project files named HELLO.OPT, HELLO.NCB, HELLO.DSP, and HELLO.DSW in that directory. If you quit and later want to reopen the project, double-click on HELLO.DSW.
The area along the left side of the screen will now change so that three tabs are available. The InfoView tab is still there, but there is now also a ClassView and a FileView tab. The ClassView tab will show you a list of all of the classes in your application and the FileView tab gives you a list of all of the files in the project.
Now it is time to type in the code for the program. In the File menu select the New option to create a new editor window. In the dialog that appears, make sure the Files tab is active and request a "Text File". Visual C++ comes with its own intelligent C++ editor, and you will use it to enter the program shown above. Type the code in the listing into the editor window. You will find that the editor automatically colors different pieces of text such as comments, key words, string literals, and so on. If you want to change the colors or turn the coloring off, go to the Options option in the Tools menu, choose the Format tab and select the Source Windows option from the left hand list. If there is some aspect of the editor that displeases you, you may be able to change it using the Editor tab of the Options dialog.
After you have finished entering the code, save the file by selecting the Save option in the File menu. Save it to a file named HELLO.CPP in the new directory Visual C++ created.
Now choose the Add To Project option in the Project menu, and select Files... You will see a dialog that lets you select the source files that you want to include in your project. You can call up this dialog at any time to edit the project's files by selecting the Add To Project option. In this case, the HELLO.CPP file is the only source file needed, so double click on it.
In the area on the left side of the screen, click the FileView tab and double-click the folder icon labeled HELLO. You will see the file named HELLO.CPP. Click on the ClassView tab and double-click on the folder icon and you will see the classes in the application. You can remove a file from a project at any time by going to the FileView, clicking the file, and pressing the delete button.
Finally, you must now tell the project to use the MFC library. If you omit this step the project will not link properly, and the error messages that the linker produces will not help one bit. Choose the Settings option in the Project menu. Make sure that the General tab is selected in the tab at the top of the dialog that appears. In the Microsoft Foundation Classes combo box, choose the third option: "Use MFC in a Shared DLL." Then close the dialog.
Having created the project file and adjusted the settings, you are ready to compile the HELLO.CPP program. In the Build menu you will find three different compile options:
The first option simply compiles the source file listed and forms the object file for it. This option does not perform a link, so it is useful only for quickly compiling a file to check for errors. The second option compiles all of the source files in the project that have been modified since the last build, and then links them to form an executable. The third option recompiles all of the source files in the project and relinks them. It is a "compile and link from scratch" option that is useful after you change certain compiler options or move to a different platform.
In this case, choose the Build HELLO.EXE option in the Build menu to compile and link the code. Visual C++ will create a new subdirectory named Debug and place the executable named HELLO.EXE in that new subdirectory. This subdirectory holds all disposable (easily recreated) files generated by the compiler, so you can delete this directory when you run short on disk space without fear of losing anything important.
If you see compiler errors, simply double click on the error message in the output window. The editor will take you to that error. Compare your code against the code above and fix the problem. If you see a mass of linker errors, it probably means that you specified the project type incorrectly in the dialog used to create the project. You may want to simply delete your new directory and recreate it again following the instructions given above exactly.
To execute the program, choose the Execute HELLO.EXE option in the Build menu. A window appears with the words "hello world". The window itself has the usual decorations: a title bar, re-size areas, minimize and maximize buttons, and so on. Inside the window is a static label displaying the words "hello world". Note that the program is complete. You can move the window, re-size it, minimize it, and cover and uncover it with other windows. With a very small amount of code you have created a complete Window application. This is one of the many advantages of using MFC. All the details are handled elsewhere.
To terminate the program, click on its system menu (the small box to the left of the title bar) and select the Close option.
In this tutorial you have successfully compiled and executed your first program. You will use these same steps for each of the programs you create in the following tutorials. You will find that you can either create a separate directory for each project that you create, or you can create a single project file and then add and remove different source files.
In the next tutorial, we will examine this program in detail so you
may gain a more complete understanding of its structure.
Part 2
A Simple MFC Program
In this tutorial we will examine a simple MFC program piece by piece to
gain an understanding of its structure and conceptual framework. We will start by looking
at MFC itself and then examine how MFC is used to create applications.
MFC is a large and extensive C++ class hierarchy that makes Windows application development significantly easier. MFC is compatible across the entire Windows family. As each new version of Windows comes out, MFC gets modified so that old code compiles and works under the new system. MFC also gets extended, adding new capabilities to the hierarchy and making it easier to create complete applications.
The advantage of using MFC and C++ - as opposed to directly accessing the Windows API from a C program-is that MFC already contains and encapsulates all the normal "boilerplate" code that all Windows programs written in C must contain. Programs written in MFC are therefore much smaller than equivalent C programs. On the other hand, MFC is a fairly thin covering over the C functions, so there is little or no performance penalty imposed by its use. It is also easy to customize things using the standard C calls when necessary since MFC does not modify or hide the basic structure of a Windows program.
The best part about using MFC is that it does all of the hard work for you. The hierarchy contains thousands and thousands of lines of correct, optimized and robust Windows code. Many of the member functions that you call invoke code that would have taken you weeks to write yourself. In this way MFC tremendously accelerates your project development cycle.
MFC is fairly large. For example, Version 4.0 of the hierarchy contains something like 200 different classes. Fortunately, you don't need to use all of them in a typical program. In fact, it is possible to create some fairly spectacular software using only ten or so of the different classes available in MFC. The hierarchy is broken into several different class categories which include (but is not limited to):
![]() |
Application Architecture |
![]() |
Graphical Drawing and Drawing Objects |
![]() |
File Services |
![]() |
Exceptions |
![]() |
Structures - Lists, Arrays, Maps |
![]() |
Internet Services |
![]() |
OLE 2 |
![]() |
Database |
![]() |
General Purpose |
We will concentrate on visual objects in these tutorials. The list below shows the portion of the class hierarchy that deals with application support and windows support.
![]() |
CObject |
![]() |
CCmdTarget |
![]() |
CWinThread |
![]() |
CWinApp |
![]() |
CWnd |
![]() |
CFrameWnd |
![]() |
CDialog |
![]() |
CView |
![]() |
CStatic |
![]() |
CButton |
![]() |
CListBox |
![]() |
CComboBox |
![]() |
CEdit |
![]() |
CScrollBar |
There are several things to notice in this list. First, most classes in MFC derive from a base class called CObject. This class contains data members and member functions that are common to most MFC classes. The second thing to notice is the simplicity of the list. The CWinApp class is used whenever you create an application and it is used only once in any program. The CWnd class collects all the common features found in windows, dialog boxes, and controls. The CFrameWnd class is derived from CWnd and implements a normal framed application window. CDialog handles the two normal flavors of dialogs: modeless and modal respectively. CView is used to give a user access to a document through a window. Finally, Windows supports six native control types: static text, editable text, push buttons, scroll bars, lists, and combo boxes (an extended form of list). Once you understand this fairly small number of pieces, you are well on your way to a complete understanding of MFC. The other classes in the MFC hierarchy implement other features such as memory management, document control, data base support, and so on.
To create a program in MFC, you either use its classes directly or, more commonly, you derive new classes from the existing classes. In the derived classes you create new member functions that allow instances of the class to behave properly in your application. You can see this derivation process in the simple program we used in Tutorial 1, which is described in greater detail below. Both CHelloApp and CHelloWindow are derived from existing MFC classes.
Before discussing the code itself, it is worthwhile to briefly discuss the program design process under MFC. As an example, imagine that you want to create a program that displays the message "Hello World" to the user. This is obviously a very simple application but it still requires some thought.
A "hello world" application first needs to create a window on the screen that holds the words "hello world". It then needs to get the actual "hello world" words into that window. Three objects are required to accomplish this task:
Every program that you create in MFC will contain the first two objects. The third object is unique to this particular application. Each application will define its own set of user interface objects that display the application's output as well as gather input from the user.
Once you have completed the user interface design and decided on the controls necessary to implement the interface, you write the code to create the controls on the screen. You also write the code that handles the messages generated by these controls as they are manipulated by the user. In the case of a "hello world" application, only one user interface control is necessary. It holds the words "hello world". More realistic applications may have hundreds of controls arranged in the main window and dialog boxes.
It is important to note that there are actually two different ways to create user controls in a program. The method described here uses straight C++ code to create the controls. In a large application, however, this method becomes painful. Creating the controls for an application containing 50 or 100 dialogs using C++ code to do it would take an eon. Therefore, a second method uses resource files to create the controls with a graphical dialog editor. This method is much faster and works well on most dialogs.
The listing below shows the code for the simple "hello world" program that you entered, compiled and executed in Tutorial 1. Line numbers have been added to allow discussion of the code in the sections that follow. By walking through this program line by line, you can gain a good understanding of the way MFC is used to create simple applications.
If you have not done so already, please compile and execute the code below by following the instructions given in Tutorial 1.
1 //hello.cpp 2 #include <afxwin.h> 3 // Declare the application class 4 class CHelloApp : public CWinApp 5 { 6 public: 7 virtual BOOL InitInstance(); 8 }; 9 // Create an instance of the application class 10 CHelloApp HelloApp; 11 // Declare the main window class 12 class CHelloWindow : public CFrameWnd 13 { 14 CStatic* cs; 15 public: 16 CHelloWindow(); 17 }; 18 // The InitInstance function is called each 19 // time the application first executes. 20 BOOL CHelloApp::InitInstance() 21 { 22 m_pMainWnd = new CHelloWindow(); 23 m_pMainWnd->ShowWindow(m_nCmdShow); 24 m_pMainWnd->UpdateWindow(); 25 return TRUE; 26 } 27 // The constructor for the window class 28 CHelloWindow::CHelloWindow() 29 { 30 // Create the window itself 31 Create(NULL, 32 "Hello World!", 33 WS_OVERLAPPEDWINDOW, 34 CRect(0,0,200,200)); 35 // Create a static label 36 cs = new CStatic(); 37 cs->Create("hello world", 38 WS_CHILD|WS_VISIBLE|SS_CENTER, 39 CRect(50,80,150,150), 40 this); 41 }
Take a moment and look through this program. Get a feeling for the "lay of the land." The program consists of six small parts, each of which does something important.
The program first includes afxwin.h (line 2). This header file contains all the types, classes, functions, and variables used in MFC. It also includes other header files for such things as the Windows API libraries.
Lines 3 through 8 derive a new application class named CHelloApp from the standard CWinApp application class declared in MFC. The new class is created so the InitInstance member function in the CWinApp class can be overridden. InitInstance is a virtual function that is called as the application begins execution.
In Line 10, the code declares an instance of the application object as a global variable. This instance is important because it causes the program to execute. When the application is loaded into memory and begins running, the creation of that global variable causes the default constructor for the CWinApp class to execute. This constructor automatically calls the InitInstance function defined in lines 18 though 26.
In lines 11 through 17, the CHelloWindow class is derived from the CFrameWnd class declared in MFC. CHelloWindow acts as the application's window on the screen. A new class is created so that a new constructor, destructor, and data member can be implemented.
Lines 18 through 26 implement the InitInstance function. This function creates an instance of the CHelloWindow class, thereby causing the constructor for the class in Lines 27 through 41 to execute. It also gets the new window onto the screen.
Lines 27 through 41 implement the window's constructor. The constructor actually creates the window and then creates a static control inside it.
An interesting thing to notice in this program is that there is no main or WinMain function, and no apparent event loop. Yet we know from executing it in Tutorial 1 that it processed events. The window could be minimized and maximized, moved around, and so on. All this activity is hidden in the main application class CWinApp and we therefore don't have to worry about it-event handling is totally automatic and invisible in MFC.
The following sections describe the different pieces of this program in more detail. It is unlikely that all of this information will make complete sense to you right now: It's best to read through it to get your first exposure to the concepts. In Tutorial 3, where a number of specific examples are discussed, the different pieces will come together and begin to clarify themselves.
Every program that you create in MFC will contain a single application object that you derive from the CWinApp class. This object must be declared globally (line 10) and can exist only once in any given program.
An object derived from the CWinApp class handles initialization of the application, as well as the main event loop for the program. The CWinApp class has several data members, and a number of member functions. For now, almost all are unimportant. If you would like to browse through some of these functions however, search for CWinApp in the MFC help file by choosing the Search option in the Help menu and typing in "CWinApp". In the program above, we have overridden only one virtual function in CWinApp, that being the InitInstance function.
The purpose of the application object is to initialize and control your application. Because Windows allows multiple instances of the same application to run simultaneously, MFC breaks the initialization process into two parts and uses two functions-InitApplication and InitInstance-to handle it. Here we have used only the InitInstance function because of the simplicity of the application. It is called each time a new instance of the application is invoked. The code in Lines 3 through 8 creates a class called CHelloApp derived from CWinApp. It contains a new InitInstance function that overrides the existing function in CWinApp (which does nothing):
3 // Declare the application class 4 class CHelloApp : public CWinApp 5 { 6 public: 7 virtual BOOL InitInstance(); 8 };
Inside the overridden InitInstance function at lines 18 through 26, the program creates and displays the window using CHelloApp's data member named m_pMainWnd:
18 // The InitInstance function is called each 19 // time the application first executes. 20 BOOL CHelloApp::InitInstance() 21 { 22 m_pMainWnd = new CHelloWindow(); 23 m_pMainWnd->ShowWindow(m_nCmdShow); 24 m_pMainWnd->UpdateWindow(); 25 return TRUE; 26 }
The InitInstance function returns a TRUE value to indicate that initialization completed successfully. Had the function returned a FALSE value, the application would terminate immediately. We will see more details of the window initialization process in the next section.
When the application object is created at line 10, its data members (inherited from CWinApp) are automatically initialized. For example, m_pszAppName, m_lpCmdLine, and m_nCmdShow all contain appropriate values. See the MFC help file for more information. We'll see a use for one of these variables in a moment.
MFC defines two types of windows: 1) frame windows, which are fully functional windows that can be re-sized, minimized, and so on, and 2) dialog windows, which are not re-sizable. A frame window is typically used for the main application window of a program.
In the code shown in listing 2.1, a new class named CHelloWindow is derived from the CFrameWnd class in lines 11 through 17:
11 // Declare the main window class 12 class CHelloWindow : public CFrameWnd 13 { 14 CStatic* cs; 15 public: 16 CHelloWindow(); 17 };
The derivation contains a new constructor, along with a data member that will point to the single user interface control used in the program. Each application that you create will have a unique set of controls residing in the main application window. Therefore, the derived class will have an overridden constructor that creates all the controls required in the main window. Typically this class will also have an overridden destructor to delete them when the window closes, but the destructor is not used here. In Tutorial 4, we will see that the derived window class will also declare a message handler to handle messages that these controls produce in response to user events.
Typically, any application you create will have a single main application window. The CHelloApp application class therefore defines a data member named m_pMainWnd that can point to this main window. To create the main window for this application, the InitInstance function (lines 18 through 26) creates an instance of CHelloWindow and uses m_pMainWnd to point to the new window. Our CHelloWindow object is created at line 22:
18 // The InitInstance function is called each 19 // time the application first executes. 20 BOOL CHelloApp::InitInstance() 21 { 22 m_pMainWnd = new CHelloWindow(); 23 m_pMainWnd->ShowWindow(m_nCmdShow); 24 m_pMainWnd->UpdateWindow(); 25 return TRUE; 26 }
Simply creating a frame window is not enough, however. Two other steps are required to make sure that the new window appears on screen correctly. First, the code must call the window's ShowWindow function to make the window appear on screen (line 23). Second, the program must call the UpdateWindow function to make sure that each control, and any drawing done in the interior of the window, is painted correctly onto the screen (line 24).
You may wonder where the ShowWindow and UpdateWindow functions are defined. For example, if you wanted to look them up to learn more about them, you might look in the MFC help file (use the Search option in the Help menu) at the CFrameWnd class description. CFrameWnd does not contain either of these member functions, however. It turns out that CFrameWnd inherits its behavior-as do all controls and windows in MFC-from the CWnd class (see figure 2.1). If you refer to CWnd in the MFC documentation, you will find that it is a huge class containing over 200 different functions. Obviously, you are not going to master this particular class in a couple of minutes, but among the many useful functions are ShowWindow and UpdateWindow.
Since we are on the subject, take a minute now to look up the CWnd::ShowWindow function in the MFC help file. You do this by clicking the help file's Search button and entering "ShowWindow". As an alternative, find the section describing the CWnd class using the Search button, and then find the ShowWindow function under the Update/Painting Functions in the class member list. Notice that ShowWindow accepts a single parameter, and that the parameter can be set to one of ten different values. We have set it to a data member held by CHelloApp in our program, m_nCmdShow (line 23). The m_nCmdShow variable is initialized based on conditions set by the user at application start-up. For example, the user may have started the application from the Program Manager and told the Program Manager to start the application in the minimized state by setting the check box in the application's properties dialog. The m_nCmdShow variable will be set to SW_SHOWMINIMIZED, and the application will start in an iconic state. The m_nCmdShow variable is a way for the outside world to communicate with the new application at start-up. If you would like to experiment, you can try replacing m_nCmdShow in the call to ShowWindow with the different constant values defined for ShowWindow . Recompile the program and see what they do.
Line 22 initializes the window. It allocates memory for it by calling the new function. At this point in the program's execution the constructor for the CHelloWindow is called. The constructor is called whenever an instance of the class is allocated. Inside the window's constructor, the window must create itself. It does this by calling the Create member function for the CFrameWnd class at line 31:
27 // The constructor for the window class 28 CHelloWindow::CHelloWindow() 29 { 30 // Create the window itself 31 Create(NULL, 32 "Hello World!", 33 WS_OVERLAPPEDWINDOW, 34 CRect(0,0,200,200));
Four parameters are passed to the create function. By looking in the MFC documentation you can see the different types. The initial NULL parameter indicates that a default class name be used. The second parameter is the title of the window that will appear in the title bar. The third parameter is the style attribute for the window. This example indicates that a normal, overlappable window should be created. Style attributes are covered in detail in Tutorial 3. The fourth parameter specifies that the window should be placed onto the screen with its upper left corner at point 0,0, and that the initial size of the window should be 200 by 200 pixels. If the value rectDefault is used as the fourth parameter instead, Windows will place and size the window automatically for you.
Since this is an extremely simple program, it creates a single static text control inside the window. In this particular example, the program uses a single static text label as its only control, and it is created at lines 35 through 40. More on this step in the next section.
The program derives the CHelloWindow class from the CFrameWnd class (lines 11 through 17). In doing so it declares a private data member of type CStatic*, as well as a constructor.
As seen in the previous section, the CHelloWindow constructor does two things. First it creates the application's window by calling the Create function (line 31), and then it allocates and creates the control that belongs inside the window. In this case a single static label is used as the only control. Object creation is always a two-step process in MFC. First, the memory for the instance of the class is allocated, thereby calling the constructor to initialize any variables. Next, an explicit Create function is called to actually create the object on screen. The code allocates, constructs, and creates a single static text object using this two-step process at lines 36 through 40:
27 // The constructor for the window class 28 CHelloWindow::CHelloWindow() 29 { 30 // Create the window itself 31 Create(NULL, 32 "Hello World!", 33 WS_OVERLAPPEDWINDOW, 34 CRect(0,0,200,200)); 35 // Create a static label 36 cs = new CStatic(); 37 cs->Create("hello world", 38 WS_CHILD|WS_VISIBLE|SS_CENTER, 39 CRect(50,80,150,150), 40 this); 41 }
The constructor for the CStatic item is called when the memory for it is allocated, and then an explicit Create function is called to create the CStatic control's window. The parameters used in the Create function here are similar to those used for window creation at Line 31. The first parameter specifies the text to be displayed by the control. The second parameter specifies the style attributes. The style attributes are discussed in detail in the next tutorial but here we requested that the control be a child window (and therefore displayed within another window), that it should be visible, and that the text within the control should be centered. The third parameter determines the size and position of the static control. The fourth indicates the parent window for which this control is the child. Having created the static control, it will appear in the application's window and display the text specified.
In looking at this code for the first time, it will be unfamiliar
and therefore potentially annoying. Don't worry about it. The only part in the entire
program that matters from an application programmer's perspective is the CStatic
creation code at lines 36 through 40. The rest you will type in once and then ignore. In
the next tutorial you will come to a full understanding of what lines 36 through 40 do,
and see a number of options that you have in customizing a CStatic control.