Lesson 1: Overview of MFC

The MFC Library is a collection of C++ classes and global functions designed for the rapid development of Microsoft Windows–based applications. MFC offers many advantages to C++ developers at all levels, from beginners to seasoned professionals. It simplifies Windows programming, shortens development time, and makes code more portable without reducing programming freedom and flexibility. MFC provides easy access to hard-to-program technologies like ActiveX and Internet programming. MFC makes it easy to program user interface features such as property sheets, print preview, shortcut menus, and customizable floating toolbars complete with ToolTips.

In this lesson, you will learn how the MFC Library is organized, and how it is designed to encapsulate the Microsoft Win32 API—the low-level application that programmers interface to the Windows operating system services. You will also learn about some of the more important platform issues that need to be considered when using the MFC Library.

After this lesson, you will be able to:

  • Describe the general structure of the MFC Library and how it relates to the Win32 API.
  • Describe some of the issues that should be considered when developing for the different Win32 Platforms: Microsoft Windows NT, Microsoft Windows 95, and Microsoft Windows 98.
  • Describe the general categories of the MFC classes and their hierarchical organization.
  • Describe when to use an MFC extension DLL.
Estimated lesson time: 40 minutes

MFC and the Win32 API

The term Win32 is used to describe an Application Programming Interface (API) that is common to all of the Microsoft 32-bit Windows platforms. These platforms currently include Windows 95, Windows 98, Windows NT, and Microsoft Windows CE. (Note: This book will not cover information specific to Windows CE.) The Win32 API is a set of functions, structures, messages, macros, and interfaces that provides a consistent interface to enable you to develop applications for any of the Win32 platforms. Table 3.1 lists some of the services provided by the Win32 API.

Table 3.1 Win32 API Services

Win32 API service Description
Window Management Provides the means to create and manage a user interface.
Window Controls Provides a set of common user interface controls. Using the common controls helps keep an application's user interface consistent with that of the shell and other applications. It also saves a significant amount of development time.
Shell Features Provides access to system objects and resources such as files, storage devices, printers, and network resources.
Graphics Device Interface Provides functions and related structures used to generate graphical output for displays, printers, and other graphical devices.
System Services Provides access to the resources of the computer via features of the underlying operating system.

Because the Win32 API is distributed as a set of C functions, users of Visual C++ can simply include the appropriate header files and then call the Win32 API functions from their code. Before MFC was available, Windows applications were developed using only the Win32 API—a time-consuming process. Experienced Win32 programmers would invariably reuse code and develop libraries to speed up the development of basic, often-repeated Windows programming tasks. MFC is a formalization of this process that makes this reusable code available to all C++ developers.

MFC was developed to simplify and speed up the development of Windows applications by providing a set of C++ classes that encapsulate key features of the Win32 API. As a C++ programmer, you will be familiar with the way in which a good class design can be used to encapsulate complex features of a software object behind a clear and concise interface.

For example, the Win32 concept of a window is encapsulated by the MFC class CWnd. That is, a C++ class called CWnd encapsulates the HWND handle (HWND is a Win32-defined data type that represents a Win32 window). Encapsulation means that the CWnd class contains a member variable of type HWND, and the class's member functions encapsulate calls to Win32 functions that take an HWND as a parameter. An example of this is the Win32 function:

BOOL ShowWindow(HWND hWnd, int nCmdShow);

that is encapsulated by the MFC function:

BOOL CWnd::ShowWindow(int nCmdShow);

MFC class member functions typically have the same name as the Win32 function they encapsulate.

MFC hides some lower-level aspects of Windows programming through encapsulation, although low-level access is always available if needed. Encapsulation also helps to protect against the possibility that pointer values such as window handles or file handles might become corrupted, or that operations might be performed on an invalid pointer.

When to Use MFC and When to Use the Win32 API

You should use the MFC Library whenever you need to develop anything but the simplest of applications. The advantages of the simplified development model and the benefits of reusing MFC code far outweigh any gains in speed and size made by choosing not to link the MFC Library to your application. Applications that have a command-line user interface, or no user interface, might be as easy to implement as non-MFC applications. Even for these applications you might find MFC helpful because of the application support it provides through utility classes like its string classes and generic collection classes.

MFC encapsulates most, but not all, of theWin32 API. Although you can perform most of the common Windows programming tasks through the use of the MFC classes, you will sometimes need to make direct calls to the Win32 API functions. This usually becomes necessary when you need to access system functionality at a fairly low level. For example, if you were developing a utility to modify user accounts on a network, you would be required to use the Win32 networking functions because there are no MFC classes that provide access to Windows NT network management functions.

Win32 Platform Considerations

As mentioned earlier, Windows 95, Windows 98, and Windows NT are all 32-bit operating systems that use the same Win32 API. Each operating system is intended to serve a different purpose and therefore has unique characteristics in addition to the common features shared with the other Win32 operating systems. These differences necessitate functions in the Win32 API that are operating system-specific.

To learn more about which functions are specific to which operating systems, search in the Visual C++ Help file for "Differences in Win32 API Implementations." This search will result in a useful article that details the differences to be considered when using the Win32 API for the Windows NT, Windows 95, and Windows 98 platforms.

If you need to find out which operating system is currently running your application, perhaps to conditionally branch out part of your code that is specific to one platform, you can use the API function GetVersionEx(), as illustrated by the code sample that follows.

OSVERSIONINFO vinfo; vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ::GetVersionEx(&vinfo); switch(vinfo.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS :      // Windows 95 / 98 specific code case VER_PLATFORM_WIN32_NT :      // Windows NT specific code }

The higher level of abstraction that MFC provides removes you from many platform-specific considerations. Most of the MFC code you write will run across the Windows 32-bit platforms without difficulty, but to ensure that your applications will run without problems, you should be aware of a few platform-specific issues.

Unicode Issues

The ANSI character set used on 16-bit platforms such as MS-DOS and Microsoft Windows 3.1 uses a single byte to represent a character. Since one byte can represent only 256 unique characters, the ANSI character set is insufficient to represent a language with a large number of characters, such as Chinese. Unicode addresses this problem by using two bytes to represent each character. The 16-bit Unicode character set has the capacity to encode 65,536 characters, and so has become a worldwide character-encoding standard.

Windows NT supports both Unicode and ANSI strings. All Windows NT internal character strings, including Windows NTFS File System (NTFS) names, are Unicode strings. The Win32 API provides conditionally defined data types and generic versions of functions that are implemented differently according to whether the _UNICODE symbol is defined for a build of your program. For example, when the _UNICODE symbol is defined, the TCHAR data type is defined as wchar_t, a 16-bit character encoding type; otherwise, it is defined as char, the normal 8-bit character encoding type.

Windows 95 and Windows 98 support only ANSI strings—not Unicode strings. To ensure that your application string data is portable across all Win32 platforms, you should always use the generic data types and functions.

The MFC string class CString is based on the TCHAR data type. Its constructors, assignment operators, and comparison operators are all Unicode-aware. This means that you can use the CString class transparently, safe in the knowledge that it will implement Unicode or ANSI strings as appropriate to the build environment. However, you must be careful to extend the platform independence embodied in the CString class into your own code. To make your application more Unicode-aware, you must also consider the following:

  • Use the _T macro to conditionally code literal strings to be portable to Unicode. For example, use _T("MyString") where you might otherwise use "MyString."
  • When you pass strings to functions, pay attention to whether function arguments require a length in characters or a length in bytes. The difference is important if you're using Unicode strings.
  • Use portable versions of the C run-time string-handling functions. For example, use "_tcslen" rather than "strlen" and _"tcscat" rather than "strcat."
  • Use the following data types for characters and character pointers:
    • TCHAR where you would use char.
    • LPTSTR where you would use char*.
    • LPCTSTR where you would use const char*. CString provides the operator LPCTSTR to convert between CString and LPCTSTR.

File System Considerations

NTFS is a high-performance file system that can be installed on Windows NT systems as an alternative to the older File Allocation Table (FAT) file system used by Windows 95 and Windows 98. In addition to providing Unicode support, NTFS is more robust than FAT and provides direct support for file- and folder-level security.

When programming with MFC, you have fewer worries about the underlying file system. If you use the MFC class CFile to handle access to disk files, filenames will be converted to the correct TCHAR data type. CFile also provides error handling for "access denied" situations. It is important to be aware that file security on a corporate network will be more rigorously enforced than the test directories on your development computer, so your applications should never assume that a file will be accessible. Where you can, use system environment variables in pathnames (SystemRoot, for example, which points to the directory in which the operating system is installed) to avoid dependency on hard-coded paths. System environment variables can be retrieved by the _tgetenv() API function.

Screen Coordinates

Under Windows 95 and Windows 98, all screen coordinates are limited to 16 bits. If you develop on a Windows NT computer, be aware that routines that draw to the screen using coordinate values that lie outside the range -32768 to 32767 will not work properly on Windows 95 and Windows 98 platforms.

MFC Class Hierarchy

The MFC Library is implemented as a set of C++ classes. One of the main methods of code reuse in C++ is the inheritance mechanism. A C++ class can be derived from, and inherit the characteristics of, a parent class. The MFC Library, in common with many other C++ class libraries, organizes its contents into an inheritance hierarchy. This hierarchy contains a large number of classes of specific functions that are derived from a small number of base classes that implement the general functionality common to all their descendants.

As an example, Figure 3.1 shows the inheritance structure of the CDialog class. This MFC class represents a Windows dialog box.

Figure 3.1 Inheritance structure of the CDialog class

At the top of the hierarchy is the CObject class. CObject is the base class for a large number of the MFC classes. CObject provides basic services, including serialization (loading and saving data objects to a file); run-time class information; diagnostic and debugging support (validations and dumps); and compatibility with collection classes.

The CCmdTarget class is the base class for all objects that are capable of handling Windows messages. You will learn more about this in Lesson 3, MFC Application Framework, later in this chapter.

The CWnd class mentioned at the beginning of this chapter represents a window. The fact that the CDialog class is derived from the CWnd class illustrates the idea that a dialog box is a specialized type of window.

Viewing the MFC Object Hierarchy

In this practice exercise, you will learn how to use the Visual C++ Help system to view the MFC Hierarchy Chart, which displays the entire set of MFC classes and their inheritance relationships.

  • To view the MFC Hierarchy Chart
    1. Start Visual C++. On the Help menu, click Index. The Visual Studio version of the MSDN Library will open, with the insertion point positioned in the Type in the keyword to find text box.
    2. In the Type in the keyword to find text box, type hierarchy chart.
    3. In the keyword list, double-click hierarchy chart. The MFC Hierarchy Chart will appear in the right pane. Resize this pane so that you can see as much of the chart as possible.
    4. Explore the Hierarchy Chart. Note how the classes are organized into groups denoted by bold labels. Note which classes are derived from CObject, which are derived from CCmdTarget, and which are derived from CWnd. You might want to keep this chart open for reference while you proceed with this lesson.

    MFC Class Categories

    When learning about the MFC classes, you might find it helpful to organize them into categories, as described in Table 3.2.

    Table 3.2 MFC Class Categories

    MFC class category Description
    Application architecture The application architecture classes represent the basic architectural elements of an application and include CWinApp, which represents the application itself.
    User interface The user interface classes typically encompass the elements of a Windows-based application that are visible to the user. These include windows, dialog boxes, menus, and controls. The user interface classes also encapsulate the Windows device context and graphics device interface (GDI) drawing objects.
    Collections MFC provides a number of easy-to-use collection classes including Arrays, Lists, and Maps. These come in both template and non-template versions.
    General purpose MFC includes a number of general-purpose classes that do not encapsulate functions in the Win32 API. These classes represent simple data types such as points and rectangles, and more complex data types such as strings.
    ActiveX MFC provides classes that simplify the process of adding ActiveX capabilities to your applications and significantly reduce development time. The ActiveX classes work with the other application framework classes to provide easy access to the ActiveX API.
    Database Accessing data by connecting to databases is one of the most common Windows environment programming tasks. MFC provides classes that enable operations on databases through Open Database Connectivity (ODBC) and the Data Access Object (DAO).
    Internet Creating applications that interact with the Internet, across intranets, or both, is becoming a major focus of developers. MFC includes the WinInet APIs and the Internet Server API (ISAPI), which provide classes for client-side and server-side applications, respectively.
    Global functions MFC provides some functions that are not members of classes. These global functions generally have the prefix Afx and provide the programmer with general-purpose utilities. A commonly used example is AfxMessageBox().

    MFC DLLs

    The AppWizard gives you the choice to use the MFC Library either as a shared DLL or as a static library linked to your application's executable file. If you choose the shared DLL option, you have to be sure that the MFC Library MFCxx.DLL (xx stands for the version number you are using), and the Visual C++ standard library MSVCRT.DLL are both available on the user's computer. To ensure that this is the case, the DLLs are usually packaged and shipped with the application.

    NOTE
    Unicode applications must link to the MFCxxU.DLL version of the library.

    By choosing to link to a shared DLL, you can greatly reduce the size of your executable program. It makes sense to adopt this strategy if you are going to install a large number of MFC-based applications on one computer. This way, all the applications can share one set of DLLs rather than unnecessarily consuming disk space with multiple copies of the same DLLs.

    MFC Extension DLLs

    In the course of C++ software development, you will frequently develop custom classes that you later reuse in other applications. Like the MFC Library, these custom classes are often packaged as DLLs. Classes that are made available to other applications via a DLL are said to be exported—that is, their public member functions and data members are made visible to the client applications. For example, the MFC DLLs export the CString class. This means that applications that link to the MFC DLLs can create and use CString objects in their code.

    You can click MFC AppWizard (dll) in the New Projects dialog box to create DLLs to export your own classes. The AppWizard refers to DLLs of this type as regular DLLs.

    Regular DLLs can use MFC classes in their implementation. However, consider what happens if you want to export a class that is derived from an MFC class. Suppose you implement a class for a custom dialog box CMyDialog that derives its functionality from the MFC CDialog class and provides a set of public member functions that a client application can call to set and retrieve values from the controls. How do you ensure that the base class (CDialog) is properly exported and that its public member functions and data members are available to client applications?

    To enable MFC applications to use CMyDialog as an MFC class, to call the CDialog base class member functions, and to reference CMyDialog with CDialog pointers, you need to package the class in a special type of DLL known as an MFC extension DLL. An MFC extension DLL implements reusable classes derived from existing MFC classes. MFC extension DLLs allow you to provide an "extended" version of MFC.

    Extension DLLs are built using the shared DLL version of MFC. Only MFC executables (or DLLs) that are built with the shared version of MFC can use an extension DLL. Both the client application and the extension DLL must use the same version of the MFC DLLs.

    To build an MFC extension DLL, click MFC AppWizard (dll) in the New Projects dialog box, and select MFC Extension DLL on the first page of the MFC DLL AppWizard (shown in Figure 3.2).

    click to view at full size.

    Figure 3.2 Creating an MFC extension DLL

    Lesson Summary

    The Microsoft Foundation Class Library is implemented as a collection of C++ classes designed primarily for creating Microsoft Windows–based applications.

    MFC is designed to encapsulate the most commonly used functions of the Win32 API. The Win32 API is a set of functions, structures, messages, macros, and interfaces exposed by the operating system, which you can use to develop applications on any of Microsoft's 32-bit platforms. MFC simplifies Windows development by hiding some of the more complex features of the Win32 API. MFC should be used wherever possible to save development time and effort. Even though you use MFC, you can still use the Win32 API when you need to perform certain low-level tasks not supported by MFC.

    Although the Win32 API is designed as an interface to all Windows 32-bit operating systems, there are a few differences among the platforms. For example, Windows NT uses Unicode strings internally and supports NTFS but Windows 95 and Windows 98 do not. Although the use of MFC insulates developers from most of the platform differences, you must still be aware of platform issues.

    MFC is implemented as a hierarchical set of C++ classes that use the C++ in-heritance mechanism to provide a reusable and extensible code base for Win32 developers. MFC class categories include:

    • Application architecture classes.
    • User interface classes.
    • Collection classes.
    • General purpose classes.
    • ActiveX classes.
    • Database classes.
    • Internet classes.
    • Global functions.

    An application that uses the MFC classes in its implementation can either statically link the MFC Library to the application's executable file or share the MFC DLLs with other MFC applications. Using the shared DLLs saves disk space on the user's computer, but you must make sure that the appropriate MFC DLL and MSVCRT.DLL are both available to the installed version of the application.

    You can create your own regular DLLs or MFC extension DLLs. An MFC extension DLL implements reusable classes derived from existing MFC classes. Extension DLLs are built using the shared DLL version of MFC.



    Microsoft Press - Desktop Applications with Microsoft Visual C++ 6. 0. MCSD Training Kit
    Desktop Applications with Microsoft Visual C++ 6.0 MCSD Training Kit
    ISBN: 0735607958
    EAN: 2147483647
    Year: 1999
    Pages: 95

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net