Chapter 22 - The Microsoft Foundation Class Library: Fundamentals
Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
Copyright 1998 The McGraw-Hill Companies
A Simplified MFC Application
Before writing more complicated application code, let’s see what is required to just establish a window on the screen. In the last chapter, you learned to do this in C with a program that spanned two pages in length. When you use the power of the MFC library, the initial program code can be reduced to one-third this size!
This section examines the simplest possible Windows application, SIMPLE.CPP. The simple application will establish a window on the screen and place a title in its title bar area.
Establishing a Window with SIMPLE.CPP
In order to compile this MFC application, you need to enter the source code that follows. The source code file, while initially strange in appearance, is certainly shorter than its procedure-oriented counterparts.
// // simple.cpp // The code needed to establish a window with // the Microsoft Foundation Class library // Copyright William H. Murray and Chris H. Pappas, 1998 //
#include <afxwin.h>
class CTheApp : public CWinApp { public: virtual BOOL InitInstance( ); };
class CMainWnd : public CFrameWnd { public: CMainWnd( ) { Create(NULL,"Hello MFC World", WS_OVERLAPPEDWINDOW,rectDefault,NULL,NULL); } };
Once this C++ file is entered, you can compile this application from the integrated environment by creating a project file that includes the use of the MFC library.
Note
Make sure you set the option in the Project menu to include the static MFC library.
The following sections examine how each piece of code works in establishing the window on the screen.
Using the AFXWIN.H Header File
The AFXWIN.H header file is the gateway to Windows programming with the MFC library. This header file calls all subsequent header files, including WINDOWS.H, as they are needed. Using one header file also aids in creating precompiled header files. Precompiled header files save time when repeated compilation is being done during application development.
It might be a good idea to print a copy of AFXWIN.H for your reference as you develop your own applications using the MFC library. However, be warned, this header file has grown and approaches 100 pages in the current version because of support for OLE features and so on.
Deriving a Class from CWinApp
This application starts by deriving a class, CTheApp, from the MFC parent class, CWinApp. The programmer defines this new object.
class CTheApp : public CWinApp { public: virtual BOOL InitInstance( ); };
The class CTheApp overrides the member function InitInstance( ) of CWinApp. You will find that overriding member functions occurs frequently. By overriding InitInstance( ), you can customize the initialization and execution of the application. In CWinApp, it is also possible to override InitApplication( ), ExitInstance( ),andOnIdle( ), but for most applications, this will not be necessary.
Here is an edited portion of the CWinApp class description as found in the AFXWIN.H header file:
///////////////////////////////////////////////////////////// // CWinApp - the root of all Windows applications
class CWinApp : public CWinThread { DECLARE_DYNAMIC(CWinApp) public:
// Attributes // Startup args (do not change) HINSTANCE m_hInstance; HINSTANCE m_hPrevInstance; LPTSTR m_lpCmdLine; int m_nCmdShow;
// Running args (can be changed in InitInstance) LPCTSTR m_pszAppName; LPCTSTR m_pszRegistryKey; // used for registry entries CDocManager* m_pDocManager;
public: // set in constructor to override default LPCTSTR m_pszExeName; // executable name (no spaces) LPCTSTR m_pszHelpFilePath; // default based on module path LPCTSTR m_pszProfileName; // default based on app name
// Initialization Operations - should be done in InitInstance protected: void LoadStdProfileSettings(UINT nMaxMRU = _AFX_MRU_COUNT); void EnableShellOpen( );
void SetDialogBkColor(COLORREF clrCtlBk = RGB(192,192,192), COLORREF clrCtlText = RGB(0, 0, 0)); // set dialog box and message box background color
void SetRegistryKey(LPCTSTR lpszRegistryKey); void SetRegistryKey(UINT nIDRegistryKey); // enables app settings in registry instead of INI files // (registry key is usually a “company name”)
The CWinApp class is responsible for establishing and implementing the Windows message loop. The Windows message loop was discussed in Chapter 21. This action alone eliminates many lines of repetitive code.
CFrameWnd
The application’s window, established by the CMainWnd class, is defined from the base class, CFrameWnd, as shown in the following segment of code:
class CMainWnd : public CFrameWnd { public: CMainWnd( ) { Create(NULL,"Hello MFC World", WS_OVERLAPPEDWINDOW,rectDefault,NULL,NULL); } };
The constructor for the class, CMainWnd( ), calls the Create( ) member function to establish initial window parameters. In this application, the window’s style and caption are provided as parameters. You’ll see in Chapter 23 that it is also possible to specify a menu name and an accelerator table when this member function is used.
Here is an edited portion of CFrameWnd, also found in the AFXWIN.H header file:
///////////////////////////////////////////////////////////// // CFrameWnd - base class for SDI and other frame windows
class CFrameWnd : public CWnd { DECLARE_DYNCREATE(CFrameWnd)
// special helper for view creation CWnd* CreateView(CCreateContext* pContext, UINT nID = AFX_IDW_PANE_FIRST); . . . // control bar docking void EnableDocking(DWORD dwDockStyle); void DockControlBar(CControlBar* pBar, UINT nDockBarID = 0, LPCRECT lpRect = NULL); void FloatControlBar(CControlBar* pBar, CPoint point, DWORD dwStyle = CBRS_ALIGN_TOP); CControlBar* GetControlBar(UINT nID); . . .
// Implementation public: virtual ~CFrameWnd( ); int m_nWindow; HMENU m_hMenuDefault; // default menu resource HACCEL m_hAccelTable; // accelerator table DWORD m_dwPromptContext; // current help prompt BOOL m_bHelpMode; // if TRUE, help mode is active CFrameWnd* m_pNextFrameWnd; // CFrameWnd in app global list CRect m_rectBorder; // OLE border space negotiation COleFrameHook* m_pNotifyHook;
CPtrList m_listControlBars; // array of control bars that // have this window as dock site int m_nShowDelay; // SW_ command for delay show/hide
The first parameter in the Create( ) member function allows a class name to be specified in compliance with the traditional Windows API RegisterClass( ) function. Normally, this will be set to NULL in the applications you develop (a parent window) and a class name will not be required.
Implementing the InitInstance( ) Member Function
Recall that the derived CTheApp class object overrode the InitInstance( ) member function. Here is how this application implements InitInstance( ):
The new operator invokes the constructor CMainWnd( ), discussed in the previous section. The m_pMainWnd member variable (m_ indicates a member variable) holds the location for the application’s main window. The ShowWindow( )member function is required to display the window on the screen. The parameter, m_nCmdShow, is initialized by the application’s constructor. UpdateWindow( ) displays and paints the window being sent to the screen.
The Constructor
The last piece of code invokes the application’s constructor at startup:
CTheApp TheApp;
The application code for this example is very simple and straightforward. The application merely establishes a window; it does not permit you to draw anything in the window.
In the next chapter, you will create a more generalized template, as you did in Chapter 21. This template will allow you to use basically the same MFC code from one application to another. In addition, this template code will allow you to draw in the client area of the window.
Running the SIMPLE.CPP Application
Figure 22-1 shows a window similar to the one that will appear on your screen. While the application didn’t draw anything in the client area of the window, it did give the application a new title!
Figure 22-1: Establishing a window with the use of the MFC library
This code forms the foundation for all Windows MFC library applications developed in this book. You might want to review the important details one more time before going on to the applications created in Chapter 23.
Application Maintenance Is Easy with the MFC
Reusable classes are one of the main drawing cards in C++ for simplified design and application maintenance. The MFC library for Windows allows C++ to be extended in a natural way, making these classes appear to be part of the language itself. In the next chapter you’ll explore many additional features of the MFC library as you develop applications that range from a simple program template to a robust charting program using menus and dialog boxes.