This paper is intended for use by developers who want to create extensions for the Microsoft® Foundation Class Library and who want to ensure that their classes are "MFC-friendly"; that is, classes that will function well with MFC. This paper is also useful for anyone writing MFC applications who wants to know the philosophy and development practices used in the Library.
The Microsoft Foundation Class Library, a C++ Windows® interface, is built on top of the C-language Windows application programming interface (API) to ensure long-term compatibility with the thousands of applications already written for Windows. MFC is a truly object-oriented interface designed with the following goals in mind:
The core of the Microsoft Foundation Class Library encapsulates a large portion of the Windows API in C++ form. Library classes represent windows, dialog boxes, device contexts, common GDI objects, and other standard Windows items. These classes provide a convenient C++ member function interface to the structures in Windows that they encapsulate. The Microsoft Foundation Class Library also supplies a layer of additional application functionality built on the C++ encapsulation of the Windows API. This layer is a working application framework for Windows that provides most of the common user interface expected of programs for Windows.
The single characteristic that sets the Microsoft Foundation Class Library apart from other class libraries for Windows is the close mapping to the Windows API written in the C language. You can generally mix calls to the class library freely with direct calls to the Windows API. However, the classes are not a complete replacement for that API. Developers must still occasionally make direct calls to some Windows functions (::GetSystemMetrics, for example). A Windows function is wrapped by a class member function only when there is a clear advantage to doing so.
The remainder of this paper outlines the practices that the MFC developers use when writing new classes for the Library. We recommend that you follow these same practices when writing classes that extend the MFC Library. For optimum performance and compatibility with the Library, we suggest that you:
Classes you expose to the user should be as uncomplicated as you can make them. It is okay for your job as the class library designer to be difficult if doing so makes it easier for your users (in this case, other developers) to understand the classes you have written.
MFC uses a safe subset of the C++ language features. This lowers the level of complexity in the Class Library, and ensures that the classes will be compatible with a wide range of uses. MFC uses C++ idioms in commonly accepted practices. Advanced issues such as copy construction, assignment operators, and correct object destruction are handled in a thorough and consistent manner. To make your classes MFC-friendly, we recommend that you follow these principles as you create your classes.
MFC has a few abstract base classes that serve specific purposes, such as CObject and CCmdTarget. In general we advise developers to combine an abstract base class with a useful implementation if that is possible. CFile and CWnd are examples of classes that are used in both concrete and abstract forms.
Creating a class that is for implementation purposes only, yet is visible to your users, is both confusing and frustrating. Instead, put implementation details below the //Implementation line in your header files. See "MFC: Using the MFC Source Files" in Programming with MFC in the Visual C++ Books Online.
Multiple inheritance adds a high degree of complexity to application development. The Microsoft Foundation Class Library does not use multiple inheritance in the design or implementation of any of its classes. While you can use multiple inheritance with MFC to write an application (see Technical Note 16 in the Visual C++ Books Online), we do not recommend using it in MFC-friendly classes.
Templates in C++ are relatively new to the language and rather complicated to implement. Templates allow your classes to be generic when necessary, but the level of complexity inherent to templates can negate this advantage. Templates are most useful when creating "collection" classes, or for providing type-safe wrappers on a non type-safe base implementation.
There is a philosophy of class design that suggests that all data members should be private or protected and that accessor functions should be used to change the values in those data members. MFC uses public data members instead, frequently offering both a public data member and an accessor function for use by the developer. For example, class CWnd provides both a public data member, CWnd::m_hWnd, and an accessor function, CWnd::GetSafeHwnd. Depending on the needs of a particular application, a developer might use the data member or the member function, or both.
More often, MFC uses accessor functions in significant operations such as setting and retrieving style settings, returning pointers, and obtaining values used in other operations. We encourage developers who are writing MFC-friendly classes to use public data members as often as possible, and reserve accessor functions for operations that do more than simply change values in a data member, such as incrementing a counter or updating another function.
Part of MFC's success lies in the fact that the framework is a very thin layer over the Windows API. Most of the time MFC "wraps" the Windows functionality in C++ without adding functionality. In some cases (for example, dialog boxes), MFC greatly simplifies the Windows API by managing the details for you, but the general rule is to keep the layer as thin as possible. This principle also applies to the Windows Open Services Architecture (WOSA) APIs.
By keeping the framework layer very thin, developers can manipulate aspects of the Windows API more directly while still taking advantage of the power of C++. This layer can be especially helpful in HANDLE-based APIs such as the graphics device interface (GDI) HDCs and USER HWNDS.
To make your classes truly MFC-friendly, we recommend that you keep the encapsulation of any Windows API functions as simple as possible. Remember, however, to allow developers call the Windows API directly whenever they need it.
Table 1 shows examples of the relationship between MFC and the Windows API, as well as common naming conventions used with these objects.
Windows Type |
Example Variable |
MFC Class |
Example Object |
HWND |
hWnd; |
CWnd* |
pWnd; |
HDLG |
hDlg; |
CDialog* |
pDlg; |
HDC |
hDC; |
CDC* |
pDC; |
HGDIOBJ |
hGdiObj; |
CGdiObject* |
pGdiObj; |
HPEN |
hPen; |
CPen* |
pPen; (1) |
HBRUSH |
hBrush; |
CBrush* |
pBrush; (1) |
HFONT |
hFont; |
CFont* |
pFont; (1) |
HBITMAP |
hBitmap; |
CBitmap* |
pBitmap; (1) |
HPALETTE |
hPalette; |
CPalette* |
pPalette; (1) |
HRGN |
hRgn; |
CRgn* |
pRgn; (1) |
HMENU |
hMenu; |
CMenu* |
pMenu; (1) |
HWND |
hCtl; |
CStatic* |
pStatic; (2) |
HWND |
hCtl; |
CButton* |
pBtn; (2) |
HWND |
hCtl; |
CEdit* |
pEdit; (2) |
HWND |
hCtl; |
CListBox* |
pListBox; (2) |
HWND |
hCtl; |
CComboBox* |
pComboBox; (2) |
HWND |
hCtl; |
CScrollBar* |
pScrollbar; (2) |
HSZ |
hszStr; |
CString |
pStr; (2) |
POINT |
pt; |
CPoint |
pt; |
SIZE |
size; |
CSize |
size; |
RECT |
rect; |
CRect |
rect; |
Graphics device interface (GDI) objects typically are allocated as local variables on the stack frame. When allocated as such, the convention is to name them without a prefix, in lowercase characters; for example CPen pen.
Controls typically are allocated at the same time as the parent window is allocated, and usually are embedded by value in the parent window. For example, a CDialog that contains a CButton object will declare a member variable as CButton m_button.
MFC uses two types of classes as the basis for the class library: "value" classes and "framework" classes.
Value classes are encapsulations of single structures that contain values such as a string or coordinates. The MFC value classes allow you to manipulate these values in an efficient manner. Some of the classes (for example, CPoint) add to the basic Windows functionality to make them easier to use.
Framework classes are those classes derived from CObject. These classes provide the basic requirements of a Windows application and encapsulate much of the Windows interface. In some cases the framework classes are a very thin encapsulation of the Windows API, and in other cases the MFC classes add a lot of value to make the manipulation of Windows API details easy to manage.
Table 2 describes some of the characteristics of "value" and "framework" classes.
Characteristics |
Value |
Framework |
Has virtual functions? |
No |
Yes |
Is a base class? |
No |
<STRONG>CObject</STRONG> derived |
Is designed for direct usage? |
Yes |
Maybe |
Is designed to be derived from? |
No |
Yes |
Has a <STRONG>operator=</STRONG>? |
Usually |
No |
Has a copy constructor? |
Usually |
No |
Acts like built-in type? |
Usually |
No |
Comparing values is meaningful? |
Usually |
No |
Comparing address is meaningful? |
No |
Yes (address is identity) |
Using const in your code is a way to protect the accessibility of data. In general, developers could use const more often than they do, and in MFC const is used whenever feasible to make the data less vulnerable. We encourage you to apply const to your data members as often as possible as a guarantee to your users that your accessor functions do not have hidden side effects. This is particularly important because you will derive other classes and objects from the MFC-friendly classes that you write.
It is important to safeguard the data in your value classes by using the following principles:
A const reference should be used as an optimization. If the class data is small (for example, two int members, as is the case with CSize), then pass by value. If the class data is larger, pass by const reference instead. This retains the "by value" semantics of the class, as well as providing efficient parameter passing.
Framework objects cannot be copied, and therefore cannot be passed by value. Passing by reference will work, but is misleading, since it appears to be a "copy by value" parameter. To keep the "framework" semantics and expectations in a class, it is best to pass by address.
To pass as an input parameter:
If you are using a value object, pass it by value. If the object is too big, pass by const reference.
void Do(CMyValue val); void Do( const CMyValue& val ); // from the caller's perspective these look the same
If you are using a framework object, pass it as a const pointer:
void Do( const CMyView* pob );
To pass as an output parameter:
If you are using a value object, pass it as a non-const pointer:
void GetSomething( CMyValue* pval );
If you are using a framework object, pass it as a non-const pointer:
void UpdateSomething( CMyView* pob );
To pass as an input/output parameter:
Passing value objects as input/output parameters should be avoided. If you must, you can use a non-const pointer, or a non-const reference. Ideally, however, you should stay away from passing value objects in this manner.
If you are using a framework object, pass it as a non-const pointer:
void UpdateSomething( CMyView* pob );
To determine return values:
If you are using a value object, return it as an object:
CMyValue GetCurrentValue();
If you are using a framework object, return it as a pointer:
CMyView* GetCurrentView();
The majority of the classes you will create as extensions to MFC will be framework-type classes. For those classes, you should keep to a safe subset of C++ functions. If you do create value classes, be sure to use all the advantages of the C++ language as MFC has done with its value classes. CString and CRect are good examples of classes to review for these features.
In general, framework objects do not behave like the types built-in to C++, so you cannot add them or assign them the way you would with value objects. Deciding what semantics the operator= would represent would be arbitrary, so avoid including this operator in your framework classes. For more information, see "General Rules for Operator Overloading" in Chapter 12 of the C++ Language Reference in the Visual C++ Books Online.
Along the same lines, avoid overloading copy constructors in framework classes. The type of the copy constructor's argument should be "const classname&" whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also allows copying from const objects.
MFC uses a set of conventions to make it easy to identify elements of the code. We recommend that you follow these simple conventions to leverage the ease-of-identification found in MFC.
MFC uses the Windows API data types, API names, and message names whenever possible as the basis for naming classes and functions in the class library. This makes it easy to determine the Windows API is encapsulated by an MFC member function. MFC's member function names do not clash with those found in the Windows API because they operate within a class scope rather than a file scope. On occasion you might need to call a Windows API function instead of an MFC function, and you can do that using the global scoping operator (::). When you write MFC-friendly classes, we encourage you to follow the same conventions to make it easy for your users to understand your intentions.
In both the MFC source files and the files that AppWizard creates, you will find comments like these within class declarations (usually in this order):
// Constructors // Attributes // Operations // Overridables // Implementation
MFC uses these commenting conventions to delineate the sections of the class declarations containing similar kinds of class members. Some classes omit some sections but all classes have at least the // Implementation section, and larger classes may have additional sections besides those listed above.
Following these and other conventions outlined in the article "MFC: Using the MFC Source Files" in Programming with MFC found in the Visual C++ Books Online is optional, of course. However, doing so makes it easy for your users to find the functions they need in your header files.
The following tables describe the subset of Hungarian notation used in MFC. Table 3 shows general prefix naming conventions. Note that all class names and structure names begin with the letter "C", and member variables are preceded by m_.
Prefix |
Type |
Example |
C |
Class or structure |
CDocument, CPrintInfo |
m_ |
Member variable |
m_pDoc, m_nCustomers |
Table 4 lists the prefixes MFC uses for naming variables. If you use these naming conventions in your MFC-friendly classes, users of your classes will appreciate the consistency between your code and MFC.
Prefix |
Type |
Description |
Example |
ch |
char |
8-bit character |
chGrade |
ch |
TCHAR |
16-bit character if _UNICODE is defined |
chName |
b |
BOOL |
Boolean value |
bEnabled |
n |
int |
Integer (size dependent on operating system) |
nLength |
n |
UINT |
Unsigned value (size dependent on operating system) |
nLength |
w |
WORD |
16-bit unsigned value |
wPos |
l |
LONG |
32-bit signed integer |
lOffset |
dw |
DWORD |
32-bit unsigned integer |
dwRange |
p |
* |
Ambient memory model pointer |
pDoc |
lp |
FAR* |
Far pointer |
lpDoc |
lpsz |
LPSTR |
32-bit pointer to character string |
lpszName |
lpsz |
LPCSTR |
32-bit pointer to constant character string |
lpszName |
lpsz |
LPCTSTR |
32-bit pointer to constant character string if _UNICODE is defined |
lpszName |
h |
handle |
Handle to Windows object |
hWnd |
lpfn |
callbackFar pointer to CALLBACK function |
lpfnAbort |
Consistency with MFC helps flatten the learning curve for your users since they will recognize the MFC conventions in your classes and already know what they mean.
Table 5 shows symbols generated and used by AppWizard and ClassWizard in MFC applications. You can also use these prefixes in classes and resource files in your MFC-friendly classes.
Prefix |
Type of Symbol |
Symbol |
Example |
Range |
IDR_ |
Identification shared by multiple resources of different types. |
IDR_MAINFRAME |
1 to 0x6FFF |
|
IDD_ |
Dialog resource |
IDD_SPELL_CHECK |
1 to 0x6FFF |
|
HIDD_ |
Dialog-resource Help context |
HIDD_SPELL_CHECK |
0x20001 to 0x26FF |
|
IDB_ |
Bitmap resource |
IDB_COMPANY_LOGO |
1 to 0x6FFF |
|
IDC_ |
Cursor resource |
IDC_PENCIL |
1 to 0x6FFF |
|
IDI_ |
Icon resource |
IDI_NOTEPAD |
1 to 0x6FFF |
|
ID_ |
Command from menu item or toolbar |
ID_TOOLS_SPELLING |
0x8000 to 0xDFFF |
|
HID_ |
Command Help context |
HID_TOOLS_SPELLING |
0x18000 to 0x1DFFF |
|
IDP_ |
Message-box prompt |
IDP_INVALID_PARTNO |
8 to 0xDFFF |
|
HIDP_ |
Message-box Help context |
HIDP_INVALID_PARTNO |
0x30008 to 0x3DFFF |
|
IDS_ |
String resource |
IDS_COPYRIGHT |
1 to 0x7FFF |
|
IDC_ |
Control within dialog box |
IDC_RECALC |
8 to 0xDFFF |
Table 6 describes some macros used in the framework. For more information on the DEBUG macro, see the article "Diagnostics" in Programming with MFC in the Visual C++ Books Online. The AFXAPI and CALLBACK macros mark specific types of MFC functions.
Macro Name |
Type of Macro |
_DEBUG |
Debug version including diagnostics |
AFXAPI (1) |
Function provided by MFC |
CALLBACK |
Function called back via pointer |
The classes you create should be flexible enough to be used in ways you did not originally intend for them to be used. Here are some guidelines for creating flexible classes.
It is important that your users be able to use your MFC-friendly classes in ways that you might not have originally intended. By keeping the majority of member functions, data members, and operators public, you allow for flexibility in their use. In MFC, even functions declared in the // Implementation section of a class are usually public or protected.
If you are concerned about future changes to functions within your classes that might break functionality, put those functions below the // Implementation line in your code (even if they are declared public). This will indicate that functions in this section should not be relied upon to remain the same in future versions of your classes.
Remember to declare virtual destructors for your classes if they include virtual functions. Using virtual destructors, you can destroy objects without knowing their type—the correct destructor for the object is invoked using the virtual function mechanism. For rules on declaring virtual destructors, see "Declaring Destructors" in the C++ Language Reference in Visual C++ Books Online.
Portability makes your classes more appealing to other developers. Classes that you write as extensions of MFC should allow for Unicode and ANSI variants so that the code is easy to port to other platforms. By using TCHAR in your code, you have the flexibility of creating generic and Unicode-enabled builds with a few simple changes in the build definition.
Unicode is available only under Windows NT. For more information on Unicode, see the article "Unicode Programming Summary" in the Visual C++ Books Online.
MFC is also fully enabled for multibyte character sets (MBCS), specifically for double-byte character sets (DBCS). DBCS characters are composed of one or two bytes. Some ranges of bytes are set aside for use as "lead bytes." A lead byte specifies that it and the following "trail byte" comprise a single two-byte-wide character. You must keep track of which bytes are lead bytes.
MBCS is a good alternative to Unicode, and we encourage you to also MBCS-enable classes you write as extensions to MFC. For more information on MBCS, see "Support for Multibyte Character Sets (MBCS)" in the Visual C++ Books Online.
If your classes contain strings that need to be localized (translated) because they appear in an interface, be sure to put the strings into your resource file rather than coding them elsewhere in an application. In your header and implementation files, use the functions in MFC that refer to localizable strings by ID number rather than, for example, supplying a caption as an argument in a function.
Take advantage of the thousands of lines of pre-tested, versatile code included in the MFC sources to speed construction of your classes. You can leverage the carefully designed code in MFC to save yourself hundreds of hours of work. In addition, by following the recommendations outlined below, your code will be compatible with MFC.
If classes you write as extensions to MFC contain virtual functions, be sure to base them on CObject. If your class already has virtual functions, adding the CObject vtbl entries doesn't add to the size of the object, since you already have the overhead of a vtbl pointer in your object. CObject provides a number of services including serialization, run-time class information, and object diagnostic output. The cost of deriving your class from CObject is minimal: your derived class will have the overhead of four virtual functions and a single CRuntimeClass object. Refer to Table 2 for more information.
Class CString is a robust, flexible, safe way to manipulate strings in your code. CString can store up to INT_MAX (2,145,483,647) characters, and has a built-in memory allocation feature that allows the CString object to grow if necessary. A CString object can also behave like a literal C-style string, and can be substituted for character pointers in function calls. Although class CString is not implemented as an MFC collection class, CString objects can be stored as elements of a collection. We recommend that you use CString in your MFC-friendly classes.
Using class CString for string return values in your classes instead of C-style strings gives you several advantages.
CString objects can grow dynamically, but they behave like built-in primitive types and simple classes. By using CString objects as values, the string contents are copied when you assign one CString to another CString object. That is, each CString object has its own copy of the data.
Beginning with MFC 3.0, you no longer have to write explicit cleanup code for CString objects following an exception. Under the C++ exception handling mechanism that MFC now uses, CString objects are cleaned up for you.
Class CString is both Unicode- and MBCS-enabled. By following the conventions outlined in the main article "Strings" and its sub-articles in Programming with MFC (found in the Visual C++ Books Online), you can write CString object code that will automatically be handled correctly in either Unicode- or MBCS-enabled builds of your application.
Make conversions between your own data types and class CString as easy as possible. Using CString parameters is often more convenient than using LPCTSTR. This is especially true if the parameter can contain embedded NUL characters, or if the function requires a separate length parameter. A good example for study is CDC::TextOut.
Use pointers to the MFC CWnd and CDC objects rather than hWnd or hDC handles in Windows. MFC's encapsulation of the Windows functionality in these classes provides some advantages to using these objects over the direct use of the equivalent Windows handles:
If a temporary C++ object is needed to encapsulate an hWnd or hDC, the object is created for you by MFC and destroyed automatically when the object goes out of scope.
CDC and CWnd present a simpler interface to most of the Windows APIs they encapsulate.
The most effective way to make the classes you write available to users is to create an MFC Extension Dynamic Link Library (DLL). Extension DLLs can be prepared in a variety of formats. For example, you can create versions that are Unicode-enabled or not, debug or retail, and so on.
The Extension DLLs for MFC use the following naming conventions. The library names have the form
uAFXcWd.LIB
where the letters shown in italic lowercase are placeholders for specifiers whose meanings are shown in Table 7:
Specifier |
Values and Meanings |
u |
ANSI (N) or Unicode (U) |
c |
Type of program to create: C=EXE, D=USRDLL |
d |
Debug or Release: D=Debug; omit specifier for Release |
Table 8 shows examples of how static versions of the MFC libraries are prepared and named:
Library |
Description |
NAFXCW.LIB |
Release version: Windows EXE |
NAFXCWD.LIB |
Debug version: Windows EXE (default) |
NAFXDWD.LIB |
Debug USRDLL version |
NAFXDW.LIB |
Release USRDLL version |
UAFXCWD.LIB |
Debug version: Windows EXE with Unicode support |
UAFXCW.LIB |
Release version: Windows EXE with Unicode support |
UAFXDW.LIB |
Release version: DLL with Unicode support |
UAFXDWD.LIB |
Debug version: DLL with Unicode support |
We recommend that you prepare your MFC-friendly classes as an MFC Extension Dynamic Link Library (DLL) or as a static library (LIB) using a variation of the naming scheme described above.
Table 9 describes the macros that are used in the creation of MFC Extension DLLs.
Macro Name |
Type of Macro |
_AFXDLL |
Stand-alone dynamic-link library (DLL) version |
_USRDLL |
Statically linked DLL version |
WINAPI |
Function provided by Windows |
For more information on creating an MFC Extension DLL, see the article "DLLs: Building and Using an Extension DLL" in Programming with MFC in the Visual C++ Books Online.
The #pragma directives offer a way for a compiler to offer machine- or operating system-specific features while retaining overall compatibility with the C++ language. MFC uses the #pragma comment preprocessor directive in AFX.H to determine which version of the MFC library to link with an application when it is compiled.
You can use the same method to assist your users in determining which version of your MFC Extension DLL the compiler should use.
For example, the following code fragment from the AFX.H header file instructs the linker to link in either the NAFXCWD.LIB or NAFXCW.LIB version of MFC, depending on whether you are using the debug version of MFC:
#ifndef _UNICODE #ifdef _DEBUG #pragma comment(lib, "nafxcwd.lib") #else #pragma comment(lib, "nafxcw.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "uafxcwd.lib") #else #pragma comment(lib, "uafxcw.lib") #endif #endif...
For more information on the #pragma comment preprocessor directive, see Chapter 2, "Pragma Directives" in the Preprocessor Reference and the article "Library Versions" in Programming with MFC, both found in the Visual C++ Books Online.
When you finish writing your classes, make sure that users understand and can use the full potential of your work by documenting the classes thoroughly. Writing good reference documentation is important, but you can also write encyclopedia articles, technical notes, and samples help that explain how to use the classes. The MFC documentation has a consistent and accessible style that we describe in the remaining sections of this paper.
The documentation included with the Microsoft Foundation Class Library consists of the Class Library Reference, Programming with MFC, the MFC Technical Notes, the MFC Sample Help, and tutorials found in Introducing Visual C++. The MFC documentation in general has a clear, friendly style that avoids the use of jargon and obscure terms.
The Visual C++ documentation uses a common set of conventions that assist readers in identifying elements of documentation such as code, keyboard key names, procedures, and so on. We suggest that you follow these conventions as you prepare documentation for the classes you write as extensions to MFC. See Documentation Conventions in the Visual C++ Books Online.
The Class Library Reference is the cornerstone of the MFC documentation. This volume contains descriptions of all of the class members in the Library that appear above the // Implementation line in the MFC source code. Each class has a corresponding Overview, Member Functions list, and individual descriptions of the member functions, data members, and operators in each class. We recommend that you follow this structure and the conventions in this book to make it easy for your users to find the information they need.
The individual class Overviews describe the class in just enough detail to help developers decide whether this is the class they want. The Overview points readers to articles in Programming with MFC for details. Here's what a class overview should do:
Describe the purpose of an object of the class (a sentence or two). If the class is a base class used only for deriving other classes, make this clear. In the See Also section below the class overview, list the important classes derived from this class as well as any other related classes.
Provide essential caveats and instructions, e.g. "You must derive an application-specific class...."
Provide a concise description of how to use the class. This description is aimed at developers who don't want or need to navigate through the encyclopedia because they basically understand the class and are ready to use it. The thumbnail is a reminder of basic usage, in a short paragraph.
Refer the reader to the appropriate encyclopedia article(s) for further information. This is the valuable link to conceptual and procedural information that many developers will want.
The Member Functions list in each class corresponds to sections that appear in MFC source code. In some classes, additional sections in the Reference further categorize the member functions to make them easy to locate. Each member function, data member, and operator in a class should have an entry in the list, along with a one or two sentence description.
Each member function, data member, and operator that appear above the // Implementation line in the class has an individual description. Each description has one or more of the following six sections that appear in a specific order:
When viewed online, the See Also entries include hypertext jumps to the individual class Overview, the list of Class Member functions, and the Hierarchy Chart that applies to the class, as well as cross references to other member functions in that class.
Note carefully the use of bold, italics, and alternate fonts in the documentation. These help readers distinguish between example code, syntax, and parameters. Whenever the Windows API functions are cited, they are preceded with the global scoping operator (for example, ::GetSystemMetrics).
Programming with MFC is an encyclopedia-style manual that contains articles which describe aspects of the Class Library. The articles in this book offer both an overview of the class library and procedures you can use in specific situations by functional area. Table 10 describes characteristics of the articles found in Programming with MFC.
By Purpose |
By Level of Appearance in the Encyclopedia |
By Level of Information |
Overview |
<EM>Main</EM> articles (which appear alphabetically within the whole encyclopedia.) |
High-level overviews, e.g. "Database Overview" |
Architecture/Conceptual |
<EM>Child</EM> articles (which appear in a logical sequence following a parent article and have a title prefix followed by a colon) |
Detail articles, e.g. "Performing a Join" |
Procedural (how-to) |
Cross-reference articles, which point to another article |
Including encyclopedic articles with your MFC-friendly class documentation is optional. Nevertheless, we encourage you to at least include a conceptual overview of the uses of your classes (in addition to the one in the Reference section) so that developers can take full advantage of the power and flexibility in your classes. By providing adequate documentation up front, you can avoid or reduce costly product support calls, and ensure customer satisfaction both now and in the future.
Ideally, a class overview included with reference material should contain a short description of the class, a set of high-level procedures for using the class, and cross-references to similar or related classes. The class overview should serve as a quick summary that a developer can read to decide whether the class you have written is the appropriate class for their need. Save any lengthy or detailed descriptions of the class usage for encyclopedic articles.
The MFC Technical Notes are "written by developers for developers." The Technical Notes cover advanced techniques in specific areas, and offer a level of technical detail that average developers don't normally require to do their work.
Writing technical notes for your MFC-friendly classes is optional. When used sparingly and for very specific situations, technical notes can be an invaluable resource for unusual situations. Review the MFC Technical Notes for ideas on how you can write your own to your best advantage.
Sample code is an essential part of any documentation, and providing sample applications for your users is the best way for them to understand the intent and usage of your MFC-friendly classes. MFC provides a substantial number of samples as part of their documentation, and descriptions of each MFC sample appear in the MFC Sample Help file.
The MFC Sample Help file contains an alphabetical list of samples, a cross-reference index by subject, instructions on how to build the sample, and individual descriptions of the features of the sample.
We highly recommend that you document your samples in a similar Help file. Developers can refer again and again to these descriptions to help them locate code they can use in their own applications.
We have covered general principles for developing "MFC-friendly" classes, given examples of how to make your classes robust as well as practical, and outlined methods for documenting your work. We encourage you to follow up on references to the documentation for more information on these principles. You can also get help in class design from the sources listed in the remaining sections.
MSDN is a quarterly subscription CD that contains thousands of pages of information about MFC, including samples, product documentation, backgrounders, and white papers. MSDN is an essential tool for developers who are looking for support and information. Call Microsoft Sales at 1-800-426-9400 for more information.
Knowledge Base
This comprehensive database contains more than 40,000 detailed articles with technical information about Microsoft development products, bug lists, fix lists, documentation errors, and answers to common technical support questions. The Knowledge Base is a primary Microsoft product information source used daily by Microsoft support engineers. You can search the Knowledge Base by keyword, and files can be downloaded for local use. Many Microsoft Knowledge Base articles have associated Software Library items. For the Developer Knowledge Base, type GO MDKB.
© 1995 Microsoft Corporation. All rights reserved. Printed in the United States of America.
The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, this paper should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
This technical overview is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Visual C++, Windows, and Windows NT are trademarks of Microsoft Corporation.