| Tenouk C++ & C | MFC Home | MFC Intro 1 | AppWizard 1 | Download | Site Index |


 

 

 

 

 

Module 1a:

Microsoft Windows, Visual C++

and Microsoft Foundation Class (MFC)

 

 

 

 

 

 

This is a continuation from the previous module. Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

  1. The Gallery

  2. The Microsoft Active Template Library (ATL)

  3. The Microsoft Foundation Class Library

  4. What's an Application Framework?

  5. An Application Framework vs. a Class Library

  6. Convention

  7. Object ID Naming Conventions

  8. Object ID-Numbering Convention

  9. Program Examples 1 - Hello World

  10. Program Examples 2 - Scribble

  11. .Net Framework

  12. Managed vs. Unmanaged Code

 

 

 

 The Gallery

 

The Visual C++ Components and Controls Gallery lets you share software components among different projects. The Gallery manages three types of modules:

  • ActiveX controls: When you install an ActiveX control (OCX - formerly OLE control), an entry is made in the Windows Registry. All registered ActiveX controls appear in the Gallery's window, so you can select them in any project.

  • C++ source modules: When you write a new class, you can add the code to the Gallery. The code can then be selected and copied into other projects. You can also add resources to the Gallery.

  • Visual C++ components: The Gallery can contain tools that let you add features to your project. Such a tool could insert new classes, functions, data members, and resources into an existing project. Some component modules are supplied by Microsoft (Idle time processing, Palette support, and Splash screen, for example) as part of Visual C++. Others will be supplied by third-party software firms.

Visual C++ Components and Controls Gallery

 

Figure 18: Visual C++ Components and Controls Gallery.

 

If you decide to use one of the prepackaged Visual C++ components, try it out first in a dummy project to see if it's what you really want. Otherwise, it might be difficult to remove the generated code from your regular project. All user-generated Gallery items can be imported from and exported to OGX files. These files are the distribution and sharing medium for Visual C++ components.

 

The Microsoft Active Template Library (ATL)

 

ATL is a tool, separate from MFC, for building ActiveX controls. You can build ActiveX controls with either MFC or ATL, but ATL controls are much smaller and quicker to load on the Internet.

 

The Microsoft Foundation Class Library

 

The Microsoft Foundation Class Library (the MFC library, for short) defines the application framework that you'll be learning in this Tutorial. MFC provides a variety of classes designed to serve a wide range of needs. You'll find a handy diagram of the MFC 7.0 class hierarchy here. The majority of MFC classes are derived, either directly or indirectly, from CObject. CObject provides other useful benefits to its derived classes as well. For example, it overloads the new and delete operators to provide protection against memory leaks. If you create an object from a CObject-derived class and fail to delete it before the application terminates, MFC will warn you by writing a message to the debug output window. The overarching importance of this most basic of MFC classes will become increasingly clear as you grow more familiar with MFC.

 

What's an Application Framework?

 

One definition of application framework is "an integrated collection of object-oriented software components that offers all that's needed for a generic application." That isn't a very useful definition, is it? If you really want to know what an application framework is, you'll have to read the rest of this book. The application framework example that you'll familiarize yourself with later in this chapter is a good starting point.

 

An Application Framework vs. a Class Library

 

One reason that C++ is a popular language is that it can be "extended" with class libraries. Some class libraries are delivered with C++ compilers, others are sold by third-party software firms, and still others are developed in-house. A class library is a set of related C++ classes that can be used in an application. A mathematics class library, for example, might perform common mathematics operations, and a communications class library might support the transfer of data over a serial link. Sometimes you construct objects of the supplied classes; sometimes you derive your own classes, it all depends on the design of the particular class library.

An application framework is a superset of a class library. An ordinary library is an isolated set of classes designed to be incorporated into any program, but an application framework defines the structure of the program itself. Microsoft didn't invent the application framework concept. It appeared first in the academic world, and the first commercial version was MacApp for the Apple Macintosh. Since MFC 2.0 was introduced, other companies, including Borland, have released similar products.

 

An Application Framework Example

 

It's time to look at some code, not pseudocode but real code that actually compiles and runs with the MFC library. It's the good old "Hello, world!" application, with a few additions. It's about the minimum amount of code for a working MFC library application for Windows. You don't have to understand every line now. This is Single Document Interface (SDI) without Document /View architecture support application and the full steps to build this program are given in Example 1. By convention, MFC library class names begin with the letter C. Following is the source code for the header and implementation files for our MYAPP application (all the Visual C++ comments have been deleted). The classes CMyApp and CMyFrame are each derived from MFC library base classes. The first is the MyApp.h header file for the MYAPP application:

 

// MyApp.h

// application class

class CMyApp : public CWinApp

{

public:

    virtual BOOL InitInstance();

};

 

// frame window class

class CMyFrame : public CFrameWnd

{

public:

    CMyFrame();

protected:

    // "afx_msg" indicates that the next two functions are part

    //  of the MFC library message dispatch system

    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

    afx_msg void OnPaint();

    DECLARE_MESSAGE_MAP()

};

 

And here is the MyApp.cpp implementation file for the MYAPP application:

 

#include <afxwin.h> // MFC library header file declares base classes

#include "myapp.h"

 

CMyApp theApp; // the one and only CMyApp object

 

BOOL CMyApp::InitInstance()

{

    m_pMainWnd = new CMyFrame();

    m_pMainWnd->ShowWindow(m_nCmdShow);

 

    m_pMainWnd->UpdateWindow();

    return TRUE;

}

 

BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)

    ON_WM_LBUTTONDOWN()

    ON_WM_PAINT()

END_MESSAGE_MAP()

 

CMyFrame::CMyFrame()

{

    Create(NULL, "MYAPP Application");

}

 

void CMyFrame::OnLButtonDown(UINT nFlags, CPoint point)

{

    TRACE("Entering CMyFrame::OnLButtonDown - %lx, %d, %d\n", (long) nFlags, point.x, point.y);

}

 

void CMyFrame::OnPaint()

{

    CPaintDC dc(this);

    dc.TextOut(0, 0, "Hello, world!");

}

 

 

Here are some of the program elements:

 

The WinMain() function: Remember that Windows requires your application to have a WinMain() function. You don't see WinMain() here because it's hidden inside the application framework.

 

The CMyApp class:  An object of class CMyApp represents an application. The program defines a single global CMyApp object, theApp. The CWinApp base class determines most of theApp's behavior.

 

Application startup: When the user starts the application, Windows calls the application framework's built-in WinMain() function, and WinMain() looks for your globally constructed application object of a class derived from CWinApp. Don't forget that in a C++ program global objects are constructed before the main program is executed.

 

The CMyApp::InitInstance member function: When the WinMain() function finds the application object, it calls the virtual InitInstance() member function, which makes the calls needed to construct and display the application's main frame window. You must override InitInstance() in your derived application class because the CWinApp base class doesn't know what kind of main frame window you want.

 

The CWinApp::Run member function: The Run() function is hidden in the base class, but it dispatches the application's messages to its windows, thus keeping the application running. WinMain() calls Run() after it calls InitInstance().

 

The CMyFrame class: An object of class CMyFrame represents the application's main frame window. When the constructor calls the Create() member function of the base class CFrameWnd, Windows creates the actual window structure and the application framework links it to the C++ object. The ShowWindow() and UpdateWindow() functions, also member functions of the base class, must be called in order to display the window.

 

The CMyFrame::OnLButtonDown function: This function is a sneak preview of the MFC library's message-handling capability. We've elected to "map" the left mouse button down event to a CMyFrame member function. You'll learn the details of the MFC library's message mapping in Module 3. For the time being, accept that this function gets called when the user presses the left mouse button. The function invokes the MFC library TRACE macro to display a message in the debugging window.

 

The CMyFrame::OnPaint function: The application framework calls this important mapped member function of class CMyFrame every time it's necessary to repaint the window: at the start of the program, when the user resizes the window, and when all or part of the window is newly exposed. The CPaintDC statement relates to the Graphics Device Interface (GDI) and is explained in later chapters. The TextOut() function displays "Hello, world!".

 

Application shutdown: The user shuts down the application by closing the main frame window. This action initiates a sequence of events, which ends with the destruction of the CMyFrame object, the exit from Run(), the exit from WinMain(), and the destruction of the CMyApp object.

 

Look at the code example again. This time try to get the big picture. Most of the application's functionality is in the MFC library base classes CWinApp and CFrameWnd. In writing MYAPP, we've followed a few simple structure rules and we've written key functions in our derived classes. C++ lets us "borrow" a lot of code without copying it. Think of it as a partnership between us and the application framework. The application framework provided the structure, and we provided the code that made the application unique. Now you're beginning to see why the application framework is more than just a class library. Not only does the application framework define the application structure but it also encompasses more than C++ base classes. You've already seen the hidden WinMain() function at work. Other elements support message processing, diagnostics, DLLs, and so forth.

 

Convention

 

The notation used in MFC is mix of the Hungarian and CamelCase. If you already got familiar with the MFC/Windows programming, you will recognize the codes such as variables, classes, objects etc. based on the notations used. For example, MFC library class names begin with the letter C such as CScrollView and variables prefixed with m_.

 

Object ID Naming Conventions

 

There are several categories or types of IDs found in Windows applications. The MFC ID-naming convention defines different prefixes for different resource types. MFC uses the prefix "IDR_" to refer to a resource ID that applies to multiple resource types. For example, for a given frame window, the same "IDR_" value is used to refer to a menu, accelerator, string and icon resource all at once.

 

Object ID

Description

IDR_

Multiple resource types (Used for Menus, Accelerators primarily).

IDD_

For dialog template resources (for example, IDD_DIALOG1).

IDC_

For Cursor resources.

IDI_

For Icon resources.

IDB_

For Bitmap resources.

IDS_

For String resources.

 

Table 1.

 

Note that the IDS_ value for a string resource is the ID passed to LoadString. The actual implementation of string table resources groups together 16 strings into one segment. For example, within a DIALOG resource, we follow the convention of:

 

Object ID

Description

IDOK , IDCANCEL

For standard push button IDs.

IDC_

For other dialog controls.

 

Table 2.

 

The "IDC_" prefix is also used for cursors. This naming conflict is not usually a problem since a typical application will have few cursors and a large number of dialog controls. Within a Menu resource, we follow the convention of:

 

Object ID

Description

IDM_

For menu items not using the MFC command architecture.

ID_

For menu item commands using the MFC command architecture.

 

Table 3.

 

Commands that follow the MFC command architecture must have an ON_COMMAND command handler and may have an ON_UPDATE_COMMAND_UI handler. If these command handlers follow the MFC command architecture, they will function correctly whether they are bound to a menu item, a toolbar button or a dialog bar button. The same ID_ is also used for a menu prompt string displayed on the program's message bar. Most of the menu items in your application should follow the MFC command convention. All of the standard command IDs (for example, ID_FILE_NEW) follow this convention. MFC also uses "IDP_" as a specialized form of strings (that is, instead of "IDS_"). Strings with the "IDP_" prefix are "prompts," that is, strings used in message boxes. "IDP_" strings may contain "%1" and "%2" as place holders of strings determined by the program. "IDP_" strings usually have help topics, while "IDS_" strings do not. "IDP_" strings are always localized, while "IDS_" strings may or may not be localized. The MFC library also uses the "IDW_" prefix as a specialized form of control IDs (that is, instead of "IDC_"). These IDs are assigned to child windows such as views and splitters by the framework classes. MFC implementation IDs are prefixed with "AFX_".

 

Object ID-Numbering Convention

 

The following lists the valid ranges for the IDs of the specific types. Some of the limits are technical implementation limits while others are just conventions to prevent your IDs from colliding with Windows predefined IDs or MFC default implementations. We strongly recommend you do not defined IDs outside the recommended ranges. Even though the lower limit of many of these ranges is 1 (0 is not used), common convention starts practical use of IDs at 100 or 101.

 

Prefix

Resource type

Valid range

IDR_

multiple

1 → 0x6FFF

IDD_

dialog templates

1 → 0x6FFF

IDC_, IDI_, IDB_

cursors, icons, bitmaps

1 → 0x6FFF

IDS_, IDP_

general strings

1 → 0x7FFF

ID_

commands

0x8000 → 0xDFFF

IDC_

controls

8 → 0xDFFF

 

Table 4.

 

Reasons for these range limits:

Program Examples 1

 

Let go straight to the program example using MFC. This is a Single Document Interface (SDI) "Hello, world!" classic example. The application has only one window, an object of a class derived from CFrameWnd. All drawing occurs inside the frame window and all messages are handled there. This just a warm up session and we are using AppWizard that can automate most of our task in building Windows application. Follow the steps one-by-one.

 

Launch your Visual C++, click the File menu and click the New… sub menu. Click the Projects tab for the AppWizard as shown below. Select the MFC AppWizard (exe), type your project name and set the project location as needed. Leave other setting as default and click the OK button.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---------------------------------------------------------------------------------------------------------------------------------------------

AppWizard dialog

 

Figure 19: AppWizard dialog.

 

The wizard has 6 steps and you can exit at any step. Select the Single document radio button and uncheck the Document/View architecture support then click Next button.

 

Visual C++ AppWizard step 1 of 6

 

Figure 20: Visual C++ AppWizard step 1 of 6.

 

Select the None radio button for database support. Click the Next button. We are going to create the simplest project.

 

Visual C++ AppWizard step 2 of 6

 

Figure 21: Visual C++ AppWizard step 2 of 6.

 

Uncheck the ActiveX Controls. Just to make our code simpler.

 

Visual C++ AppWizard step 3 of 6

 

Figure 22: Visual C++ AppWizard step 3 of 6.

 

Accept the defaults and click the Next button.

 

Visual C++ AppWizard step 4 of 6

 

Figure 23: Visual C++ AppWizard step 4 of 6.

 

 

Accept the defaults and click Next button.

 

Visual C++ AppWizard step 5 of 6

 

Figure 24: Visual C++ AppWizard step 5 of 6.

 

The following are the classes that will be generated (also the related files created) for our project. Click the Next button.

 

Visual C++ AppWizard step 6 of 6

 

Figure 25: Visual C++ AppWizard step 6 of 6.

 

Finally the summary of the project settings. Click the OK button.

 

Visual C++ AppWizard project summary

 

Figure 26: Visual C++ AppWizard project summary.

 

Expand all folders in the FileView and double click the ChildView.cpp. FileView displays all the project files that can be edited, logically. Physically, there are more projects’ files.

 

Visual C++ FileView

 

Figure 27: Visual C++ FileView.

 

Add code to paint in the dialog. Add the following code to the CChildView::OnPaint function in the ChildView.cpp source code file:

void CChildView::OnPaint()

{

    CPaintDC dc(this); // device context for painting

 

    dc.TextOut(0, 0, "Hello, world!");

 

    // Do not call CWnd::OnPaint() for painting messages

}

 

MFC, Visual C++ code segment

 

Listing 1.

 

Compile and run. You now have a complete SDI application that has no dependencies on the document-view architecture.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Visual C++ "Hello world" output

 

Figure 28: Visual C++ "Hello world" output.

 

Program Examples 2

 

The following is another classic example using MFC AppWizard, and Visual C++ to create, build, and run a simple MFC-based single document interface (SDI) Scribble application. We just dealing with the View part of the Document/View architecture. We will learn more detail about the Document/View architecture later.

 

Use MFC AppWizard to create a new project

  1. In Visual C++/Visual Studio, on the File menu, click New.

  2. In the New dialog box, click the Projects tab, and then do the following:

  1. In MFC AppWizard Step 1, click Single document and English, leave the Document/View architecture support checkbox selected, and then click Next to go to Step 2.

  2. Because this project does not need database support, accept the default None for database support and click Next to go to Step 3.

  3. In Step 3, accept None for the document support, because we are not going to create a compound document that using Object Linking and Embedding (OLE), clear the ActiveX Controls check box, and then click Next to go to Step 4.

  4. In Step 4, clear the Printing and print preview check box, accept the defaults (Docking toolbar, Initial status bar, 3D controls, and 4 files for the recent file list) and then click Next to go to Step 5.

  5. In Step 5, leave the project style as MFC Standard, click Yes, please for generating source file comments and select As a shared DLL for MFC support. Click Next to go to Step 6.

  6. In Step 6, click Finish to display the New Project Information dialog box summarizing your choices.

  7. To create the application files with MFC AppWizard, click OK.

 

When MFC AppWizard is finished, you will be returned to Visual C++/Visual Studio. To see the classes that MFC AppWizard created, click the ClassView tab in the Project Workspace window.

 

Add message handlers that will handle several mouse clicking and dragging events. This just the skeleton, we will add the real codes later – myscribbleView.cpp file.

  1. On the View menu, click ClassWizard. The MFC ClassWizard property page appears.

  2. In the Message Maps tab, in the combo boxes provided on the property page, select the myscribble project, the CMyscribbleView class, and the CMyscribbleView Object ID.

  3. We are going to add member functions in the CMyscribbleView class. In the Messages list box, select the WM_LBUTTONDOWN message and click Add Function.

  4. Repeat Step 3 for the WM_MOUSEMOVE and WM_LBUTTONUP messages.

  5. Click OK to close ClassWizard.

 

Implement OnLButtonDown, OnMouseMove, and OnLButtonUp handlers. This is the real codes that will implement the mouse clicking and dragging events.

  1. Declaring variables in the declaration part. Open MyscribbleView.h (or use the ClassView).

  2. In the public attributes section of the CMyscribbleView class declaration, define startpt and endpt variables as follows:

 

CPoint startpt, endpt;

 

Or by using the ClassView, select the CMyscribbleView and right click, select the Add Member Variable:

 

Adding a member variable through the ClassView

 

Figure 29: Adding a member variable through the ClassView.

 

Add member variable dialog

 

Figure 30: Add member variable dialog.

 

  1. Save MyscribbleView.h.

  2. Then, the implementation codes in the implementation part. Open MyscribbleView.cpp.

  3. In the constructor, initialize startpt and endpt coordinates to  –1 as follows:

 

startpt = -1;

endpt = -1;

 

Scribble code segment           

Figure 31: Scribble code segment.

  1. Scroll to the OnLButtonDown handler.

  2. In the OnLButtonDown handler, save the point where the mouse button is pressed as the start point:

 

startpt.x = point.x;

startpt.y = point.y;

  1. Scroll to the OnMouseMove handler.

  2. In the OnMouseMove handler, add the following code to draw a line from the previous detected point in the mouse drag to the current point:

 

CClientDC dc(this);

endpt.x = point.x;

endpt.y = point.y;

if (startpt.x != -1)

{

   dc.MoveTo(startpt.x, startpt.y);

   dc.LineTo(endpt.x, endpt.y);

   startpt.x = endpt.x;

   startpt.y = endpt.y;

}

  1. In the OnLButtonUp handler, add code to reinitialize the variable startpt as follows:

 

startpt = -1;

 

Scribbles’ C++ code segment         

 

Listing 3: Scribbles’ C++ code segment.

 

Build and run the project

  1. On the Build menu, click Build Myscribble.exe. Visual Studio displays the status of the build process as it builds your project.

  2. After the build is complete, on the Build menu, click Execute Myscribble.exe. The Scribble application starts. Try writing something using your mouse.

 

Visual C++’s Scribble program output

 

Figure 32: Visual C++’s Scribble program output.

 

.Net Framework

 

Since its introduction in 2002, people’s attention has focused on the many new features that have formed part of Microsoft .NET, such as the major changes to Microsoft Visual Basic (Visual Basic .Net), the introduction of C#, the new ASP.NET and ADO.NET models, and the increased use of XML. So, from application framework we are introduced the next level, .Net framework (currently version 2.0). C++ developers need not feel left out, however, because a lot of the new features in Microsoft Visual C++ .NET make C++ a first-class member of the .NET family of programming languages. This new functionality is called the Managed Extensions for C++, and as well as providing C++ programmers with access to all the functionality in the .NET class libraries, it also lets you interoperate with existing C++ code, COM objects, and the Win32 API.

 

Managed vs. Unmanaged Code

 

Code and data that live in the .NET world are called managed because locations and lifetimes are managed by the common language runtime (CLR). Code and data that exist outside of .NET are called unmanaged, because there is no central mechanism for managing their lifetimes.

 

Enabling/disabling the /clr for managed/unmanaged code in Visual C++ .Net through the project properties.

 

Figure 33: Enabling/disabling the /clr for managed/unmanaged code in Visual C++ .Net through the project properties.

 

Enabling/disabling the /clr in Visual C++ .Net.

 

Figure 34: Enabling/disabling the /clr in Visual C++ .Net.

 

Sometimes you have to mix the two, calling existing unmanaged code from within .NET. The .NET Framework is the new library of classes that you use to build Windows applications. It is large, quite complex, and far-reaching in its scope. For MFC programming we do not use the /clr (can be enabled in the Visual C++ .Net: Project menu your_project_name Properties General Use Managed Extensions Yes/No, as shown in the above Figures), that is unmanaged. The managed code will be used in the .Net programming and don’t confused that .Net framework is not compiler, it is framework. All program examples used in this Tutorial series are unmanaged and we are using Visual C++ 6.0. The managed code used in Visual C++ .Net provided that the /clr is used.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. Porting & Migrating your older programs.

  4. MSDN Library

  5. DCOM at MSDN.

  6. COM+ at MSDN.

  7. COM at MSDN.

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C++ & C | MFC Home | MFC Intro 1 | AppWizard 1 | Download | Site Index |