The Microsoft Foundations Classes (MFC)                                 

   Contact
   Search
   C
   C++
   Visual Basic
   Java
   JavaScript
   DHTML
   Style Sheets
   About
   Active X
   TDC Binding
   PHP
   Perl and CGI
   Flash
   XML
   SQL
   Messages
   Chat
   MCSE
   Linux
   Cabling   
   ActionScript
   Downloads
   E-Cards   
 
    
    
I. General Introduction - The Microsoft Foundation Classes

The Microsoft Foundation Classes, known as the "MFC", are used for creating Windows Applications.  The MFC provides a common application
programming interface (API) for Windows programs.  It provides all of the features we expect from a Windows program: menus, minimize and
maximize buttons, text boxes, checkboxes, list boxes, combo boxes, radio buttons, graphics and multimedia.  The MFC in Visual C++ can be
compared to the Abstract Windows Toolkit (AWT) in Java.   
In contrast to the basic 32-bit console applications we have compiled previously, we must compile Windows applications by selecting "Win32 
application" so that they will incorporate MFC .dll support.  We do this by clicking "Project", and then "Settings".  Then, in the "General" tab, 
select the "Use MFC in a shared DLL" option.

There are three primary classes we deal with when using the MFC.  They are: 
CDialog = for creating basic program Windows with all their functionality
CFrameWnd = for creating basic program Windows with all their functionality
CWinApp = for creating and executing instances of Windows applications 
Windows is an event driven, multi-tasking environment.  As such, it needs a way of distinguishing between input and processes for various 
programs that may be open simultaneously, and multiple instances that may be running of the same program.  To do this, Windows uses
messaging.  Some basic components of Windows messaging are:
Messages - Everything in a Windows GUI communicates using messages.  Programs listen for messages to be sent and when they are
received, corresponding functions are executed.

WindowProc() or WndProc() - Function for handling Windows messages.

DECLARE_MESSAGE_MAP() - MFC programs that use messages must declare their message map by using the macro
"DECLARE_MESSAGE_MAP()" within the class declaration.  Forgetting to include this macro is a non-fatal logic error
- your program will compile, but it will fail to function properly.

Message Map - The message map is declared in the source file (.cpp) and ties message identifiers to message handlers with message
macros.  All of this must be sandwiched between BEGIN_MESSAGE_MAP and END_MESSAGE_MAP tags.   

Message Macros - indicate the messages the program will handle.  MFC pre-defined message macros have the same name as their
message identifiers, but they are prefixed with "ON_".  For customized, programmer-defined macros, the command "ON_COMMAND"
associate's custom message identifiers with custom message handlers. 

Message Identifier -  unique number (can be arbitrarily assigned as long as each is unique)

Message Handler - functions that execute in response to messages
Here's a syntax example:
BEGIN_MESSAGE_MAP(owner class name, base class)

           //Message Handlers, identifiers and macros.

END_MESSAGE_MAP()
Some predefined message identifiers and their predefined message handlers are:
Message Identifier

WM_PAINT

ON_COMMAND (programmer defined)
Message Handler

ON_WM_PAINT()

ON_COMMAND (programmer defined)
Message Queue - Queued messages are those that WinMain() extracts from the queue in a cyclical fashion.  Non-queued messages call
the WindowProc() function directly and override the messages in the queue being processed by WinMain().   

Message Loop - A block of code for retrieving Windows messages from the queue.  Its structure is like:
MSG msg;

while( GetMessage(&msg, 0, 0, 0) == TRUE) )
{
         TranslateMessage(&msg);
         DispatchMessage(&msg);
}

  This details a three part process:
1 - GetMessage() - retrieve message from queue
2- TranslateMessage() - perform necessary covnersions
3 - DispatchMessage() - call WindowProc() to deal with the message
The structure of a Windows message is as follows:
struct MSG
{
          HWND hwnd;                         //Handle for the particular window
          UINT message;                      //Message ID
          WPARAM wParam;                     //Message parameter (32-bit)
          LPARAM lParam;                     //Message parameter (32-bit)
          DWORD time;                        //Time message was queued
          POINT pt;                          //Mouse position
}
Cooperative multitasking - prevalent in Windows 3.1, depends on each individual application periodically giving up control of the CPU.
Pre-emptive multi-tasking - prevalent with Win 95 and beyond, the operating system can interrupt an application and transfer control to
another application.

API - Application Programming Interface

II. MFC Basics

CWinApp - Every MFC program MUST have exactly one instance of a class derived from CWinApp.  Some call it
"InitInstance()" or "WinMain()" or "WndProc()" or WindowProc()", and it is comparable to main() in a console
application.  It is "boiler plate code", used for an instantiation of a class derived from CWinApp.  Example:
// A typical WinMain() function and its 4 basic arguments:

      
                                       1                                        2                                        3                            4
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{         
                                
             // function code goes here

}
Analysis of WinMain()'s 4 arguments:

* = WINAPI is placed in front of functions called by Windows
1 = hInstance - 32bit int handle to a running instance of program, distinguishes between multiple instances
2 = hPrevInstance - old 16bit relic used with old Windows 3.1 programs, to prevent multiple instances
3 = lpCmdLine - pointer to string for accepting command line arguments when launched from command prompt
4 = nCmdShow - how window is to look when created

The code that would be placed into the WinMain() function would typically include:
BOOL StartTheWindow() {

     m_pMainWnd = new WelcomeWindow();
     m_pMainWnd->ShowWindow(m_nCmdShow);
     m_pMainWnd->UpdateWindow();

     return TRUE
;
}
There are two basic objects we must derive from that we will deal with repetitively in Windows:

CStatic - A static MFC text box.  Displays text but does not send messages, so it can not be used for input.
CDialog - A dynamic dialog box.  They can send messages, therefore they can accept input and pass it to the program. 
CEdit - editable textbox that can receive user input.

GetDlgItem() - grabs address of CEdit, CStatic, checkbox or other user object.  Can then assign it to a pointer.

GetWindowText() - returns as string whatever text is in an object.

 SetWindowText() - sets text of object pointed to with what is passed in.

SetFocus() - switches focus/cursor  to window calling this function.

DoModal() - makes window called upon modal (modality).

atoi() - converts string to integer (input from CEdit boxes comes in as string data, must be converted).

itoa() - converts integer to string.

DS_MODALFRAME - resource file specifies that other windows can not be accessed until this one closed 

DEFPUSHBUTTON - resource file button.

PUSHBUTTON - resource file button.

WS_CAPTION - resource file title bar.

WS_POPUP - resource setting indicates a stand alone window, not a child.

WS_SYSMENU - resource setting indicating system menu with close and move menu items.

IDC_STATIC - static control

LTEXT - left text control

RTEXT - right text control

CTEXT - center text control

R
esource file - A plain ASCII text file with a ".rc" extension.  You can create and edit a resource file as a text file, then add to project manually.  Or you can use the graphical editor and tool box to design a resource form manually.  The language used for this is a scripting language, separate from C++, and is explicitly for user interface design.  It is compiled with the final project.  Some resource file keywords are:
MENU - resource keyword in resource script to create a menu
POPUP - resource keyword to create menu label
MENUITEM - resource keyword selectable menu item
afx_msg - denotes message ID
ON_COMMAND - prefixes message handlers between message map tags

MFC components will be examined in detail, each one at a time in subsequent tutorials.  You may begin these tutorials and your study
of MFC objects here:

Hungarian Notation - a case sensitive method of prefixing variables in most MFC programs according to their data types.  
                                  A table of prefixes follows:
Prefix     

ar
b
c
c
d
l
lp
m_
n
i
p
s
sz
s_
Meaning

array
bool
char
class
double
long
long pointer
class member variable
integer
integer
pointer
string
string with null termination
static class member variable

 

Let's start off our MFC studies with the traditional "Hello World" application.  In this example, we will only use 2 files, a header and a source, and we will not be using a resource file.  This will give us an introduction to a basic MFC file:        Source File:     HelloMFC.exe .
// File 1 of 2.  "Welcome.h" - First Program in C++ with MFC
//-----------------------------------------------------------------------------------------------------------------------------

class HelloWorldWindow : public CFrameWnd {

      public:
      HelloWorldWindow();    // constructor initializes window
      ~HelloWorldWindow();   // destructor releases resources
      private:
      CStatic * TextMessage;   // Will hold the message
};

//-----------------------------------------------------------------------------------------------------------------------------
//CStatic is a static text box.  Static meaning it does not send messages.  
//Therefore it can not be used for user input.
In the header file above, we must derive from "CFRameWnd", so we create a class called "HellowWorldWindow" to serve that purpose.  As a private data member, we create a pointer to a CStatic text box that will later be used to create a new Static textbox on the heap. 
// File 2 of 2.   "Welcome.cpp" - First Program in C++ with MFC
// Include application framework windows class definitions:

#include <afxwin.h>     // application frameworks header
#include "Welcome.h"    // class definition for application

//---------------------------------------------------------------------------------------------------------------------------
// constructor initializes the window
HelloWorldWindow::HelloWorldWindow()     
{
   // Create Window with Title Bar
   Create( NULL,                            // default CFrameWnd class
           "Adventure Game 10.1",           // window title
           WS_OVERLAPPEDWINDOW,             // full-featured window
           CRect( 100, 100, 350, 300 ) );   // screen coordinates
   TextMessage = new CStatic;   // create a static control on heap.  Point to it.
   TextMessage->Create(                  // create Windows control
      "Introduction to My Game",                // text
      WS_CHILD | WS_VISIBLE | WS_BORDER  // window styles
      | SS_CENTER,                       // static object styles
      CRect( 60, 50, 185, 100 ),         // window coordinates
      this );                            // context that owns child window
}

//---------------------------------------------------------------------------------------------------------------------------
HelloWorldWindow::~HelloWorldWindow()
{
   delete TextMessage;
}

//---------------------------------------------------------------------------------------------------------------------------
// declare our application class based on CWinApp
class HelloMFC : public CWinApp {

      public:
      BOOL InitInstance()   // override default function
      {
           m_pMainWnd = new HelloWorldWindow();    // create window on heap
           m_pMainWnd->ShowWindow( m_nCmdShow ); // make visible
           m_pMainWnd->UpdateWindow();           // force refresh
      
           return TRUE;                          // report success
      }
};  
HelloMFC TEST;  // creating an instance of the class will display the window.

//---------------------------------------------------------------------------------------------------------------------------

In the second file, notice that we first include "afxwin.h", which we need for MFC and windows objects.  Next, we define the constructor of
our "HelloWorldWindow" class which derived from our mandatory CFrameWnd.  Notice that inside the constructor, we call the function "Create" and pass it several parameters.  This creates the main application window, set is size, position, label and properties.

Next, we take our pointer to a CStatic textbox object and use it to point to a new CStatic textbox we create on the heap.  We then call the
text box's Create() method and use its arguments to assign text, properties, position and size attributes to the CStatic textbox.  We code
our constructor to take care of the pointer and heap object we set up as a private data member in our class. 

Finally, we create a class, "HelloMFC", which derives from our mandatory "CWinApp" class.   This defines a special method that will be called
when this class is instantiated - "InitInstance()".  InitInstance() needs to do three things:

  • Create an instance on the heap of our HelloWorldWindow class that derives from CFrameWnd

  • Call the ShowWindow() method to make the window visible

  • Call UpdateWindow() to refresh/repaint the screen so it will display the window

Yes, there is a lot of data hiding going on here.  The authors of the MFC intended programmers to be able to use their objects without having
to fathom all of their bits and pieces.  At this point, we will begin to deviate from standard C++ and focus solely upon the MFC, Microsoft's
unique and specific toolkit for writing Windows C++ applications.   We don't need to learn how to create check boxes, radio buttons and text
boxes on our own - we simply need to learn how to use the ones that have already been provided for us by Microsoft.

Let's look at a basic Windows program form scratch. 

Note:  If you choose to compile this example, you must NOT select the "Use MFC in a shared .DLL" option. 

// A native Windows program from scratch to display text in a window
#include <windows.h>
long WINAPI WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
{
   WNDCLASS WindowClass;                 // Structure to hold our window's attributes
   static char szAppName[] = "OFWin";    // Define window class name
   HWND hWnd;                            // Window handle
   MSG msg;                              // Windows message structure
   // Redraw the window if the size changes
   WindowClass.style   = CS_HREDRAW | CS_VREDRAW;
   // Define our procedure for message handling
   WindowClass.lpfnWndProc = WindowProc;
   WindowClass.cbClsExtra = 0;          // No extra bytes after the window class
   WindowClass.cbWndExtra = 0;          // structure or the window instance
   WindowClass.hInstance = hInstance;   // Application instance handle
   // Set default application icon
   WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
   // Set window cursor to be the standard arrow
   WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
   // Set gray brush for background color
   WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH));
   WindowClass.lpszMenuName = 0;           // No menu, so no menu resource name
   WindowClass.lpszClassName = szAppName;  // Set class name
   // Now register our window class
   RegisterClass(&WindowClass);
   //  Now we can create the window
   hWnd = CreateWindow(
          szAppName,                       // the window class name
          "A Basic Window the Hard Way",   // The window title
          WS_OVERLAPPEDWINDOW,             // Window style as overlapped
          CW_USEDEFAULT,         // Default screen position of upper left
          CW_USEDEFAULT,         // corner of our window as x,y...
          CW_USEDEFAULT,         // Default window size
          CW_USEDEFAULT,         // .... 
          0,                     // No parent window
          0,                     // No menu
          hInstance,             // Program Instance handle
          0                      // No window creation data
        );
   ShowWindow(hWnd, nCmdShow);   // Display the window
   UpdateWindow(hWnd);           // Cause window client area to be drawn
   // The message loop
   while(GetMessage(&msg, 0, 0, 0) == TRUE)   // Get any messages
   {
      TranslateMessage(&msg);                 // Translate the message
      DispatchMessage(&msg);                  // Dispatch the message
   }
   return msg.wParam;                         // End so return to Windows
}
// Listing OFWIN_2
long WINAPI WindowProc(HWND hWnd, UINT message, WPARAM wParam,
                       LPARAM lParam)
{
   HDC hDC;                       // Display context handle
   PAINTSTRUCT PaintSt;           // Structure defining area to be drawn
   RECT aRect;                    // A working rectangle
   switch(message)                // Process selected messages
   {
      case WM_PAINT:                       // Message is to redraw the window
         hDC = BeginPaint(hWnd, &PaintSt); // Prepare to draw the window
         // Get upper left and lower right of client area
         GetClientRect(hWnd, &aRect);
         SetBkMode(hDC, TRANSPARENT);      // Set text background mode
         // Now draw the text in the window client area
         DrawText(
             hDC,                  // Device context handle
             "Who am I, and why am I here?  What thoughts these words betray ...",
             -1,                   // Indicate null terminated string
             &aRect,               // Rectangle in which text is to be drawn
             DT_SINGLELINE|        // Text format - single line
             DT_CENTER|            //             - centered in the line
             DT_VCENTER);          //             - line centered in aRect
         EndPaint(hWnd, &PaintSt); // Terminate window redraw operation
         return 0;
      case WM_DESTROY:             // Window is being destroyed
         PostQuitMessage(0);
         return 0;
      default:             // Any other message - we don't want to know,
                           // so call default message processing
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
}

For the next lesson, go on to the :  MFC Menu Application .

Supplementary:

Using the Debugger - Since using the MFC will add complexity to our C++ programs, let's become familiar with the debugger.  You use the C++ debugger by setting "breakpoints".  You do this by clicking "Insert/Remove Breakpoint" from the "Build" toolbar.  Selecting "Go" from the Build -> Start Debug submenu will start the debugging process.  The program will stop between breakpoints and when asking for input.  You can switch back and forth between the debug and run-time program windows with Alt + TAB.  You may use the "Watch" window to view and change the values of variables. 

"Break Execution" allows the programmer to stop the program in mid-execution.  "Apply Code Changes" allows changing
the code while the program is running and seeing its effects.  The "Show Next Statement" repositions the cursor on the next line where execution will begin, and so is useful for editing that line. 

The "Step Into" feature executes program statements, one per click, and the "Step Out" exits them.  "Run to Cursor" executes all code up to the position of the cursor.  "Quick Watch" is useful for monitoring variable values.  The "Call Stack" button displays the program's function call stack - a list of functions that were called in order for the flow of the program to be where it currently is.