Copyright Notice
Copyright Notice for Visual Workbench Help

Information in this document is subject to change without notice. Companies, names, and data used in examples herein are fictitious unless otherwise noted. No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose, without express written permission of Microsoft Corporation.

© 1993 Microsoft Corporation. All rights reserved.

Microsoft is a registered trademark and Windows and Windows NT are trademarks of Microsoft Corporation.


Introduction
C++ Language Reference

Introduction

This manual explains the C++ programming language as it is implemented in Microsoft® C++. Microsoft C++ is based on The Annotated C++ Reference Manual by Margaret Ellis and Bjarne Stroustrup (the ANSI base document for C++) and the current working paper for the draft proposed standard. For information about the Microsoft C compiler, see the C Language Reference.


Book Location
C++ Language Reference


  Scope and Organization of This Manual

C++, like C, is a language that is heavily reliant on a rich set of library functions to provide the following:

•	Portable operating-system interface (file and screen I/O)

•	String and buffer manipulation

•	Floating-point math transformations

•	Other supporting functionality

For information about the run-time library functions, see the Run-Time Library Reference. For information on the Microsoft Foundation classes or the iostream classes, see the Class Library Reference or the iostream Class Library Reference, respectively.

This manual is organized as follows:

»Chapter 1, Lexical Conventions,« introduces the fundamental elements of a C++ program as they are meaningful to the compiler. These elements, called "lexical elements," are used to construct statements, definitions, declarations, and so on, which are used to construct complete programs.

»Chapter 2, Basic Concepts,« explains concepts such as scope, linkage, program startup and termination, storage classes, and types. These concepts are key to understanding C++. Terminology used in this book is also introduced in this chapter.

»Chapter 3, Standard Conversions,« describes the type conversions the compiler performs between built-in, or "fundamental," types. It also explains how the compiler performs conversions among pointer, reference, and pointer-to-member types.

»Chapter 4, Expressions,« describes C++ expressions — sequences of operators and operands that are used for computing values, designating objects or functions, or generating other side effects.

»Chapter 5, Statements,« explains the C++ program elements that control how and in what order programs are executed. Among the statements covered are expression statements, null statements, compound statements, selection statements, iteration statements, jump statements, and declaration statements.

»Chapter 6, Declarations,« is one of three chapters devoted to how complete declarations are used to form declaration statements. This chapter describes such topics as storage-class specifiers, function definitions, initializations, enumerations, class, struct, and union declarations, and typedef declarations. Related information can be found in »Chapter 7, Declarators,« and »Appendix B, Microsoft-Specific Modifiers.«

»Chapter 7, Declarators,« explains the portion of a declaration statement that names an object, type, or function.

»Chapter 8, Classes,« introduces C++ classes. C++ treats an object declared with the class, struct, or union keyword as a class type. This chapter explains how to use these class types.

»Chapter 9, Derived Classes,« covers the details of inheritance — a process by which you can define a new type as having all the attributes of an existing type, plus any new attributes you add.

»Chapter 10, Member-Access Control,« explains how you can control access to class members. Use of access-control specifiers can help produce more robust code because you can limit the number of ways an object's state can be changed.

»Chapter 11, Special Member Functions,« describes special functions unique to class types. These special functions perform initialization (constructor functions), cleanup (destructor functions), and conversions. This chapter also describes the new and delete operators, which are used for dynamic memory allocation.

»Chapter 12, Overloading,« explains a C++ feature that allows you to define a group of functions with the same name but different arguments. Which function in the group is called depends on the argument list in the actual function call. In addition, this chapter covers overloaded operators, a mechanism for defining your own behavior for C++ operators.

»Appendix A, Grammar Summary,« is a summary of the C++ grammar with the Microsoft extensions. Portions of this grammar are shown throughout this manual in "Syntax" sections.

»Appendix B, Microsoft-Specific Modifiers,« describes the modifiers specific to Microsoft C++. These modifiers control memory addressing, calling conventions, and so on.

»Appendix C, Decorated Names,« discusses decorated names for functions in C++ programs. You must use a decorated name when you need to specify a C++ function name exactly as it is known internally by the linker.

»Appendix D, Charts,« contains the following charts: ASCII Character Codes, ASCII Multilingual Codes, ANSI Character Codes, and Key Codes.

Note  For information on Microsoft product support, see "Microsoft Support Services" in the Introduction to Getting Started.


  Document Conventions

This book uses the following typographic conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
char, _setcolor, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. Within discussions of syntax, bold type indicates that the text must be entered exactly as shown.
	Many functions and constants begin with either a single or double underscore. These are part of the name and are mandatory. For example, to have the __cplusplus manifest constant be recognized by the compiler, you must enter the leading double underscore.
expression	Words in italic indicate placeholders for information you must supply, such as a filename.
grammar-element (opt)	The subscript indicates that this element of the grammar is optional and can be omitted.
[option]	Items inside square brackets are optional.
#pragma pack {1 | 2}	Braces and a vertical bar indicate a choice among two or more items. You must choose one of these items unless square brackets ([ ]  )surround the braces.
#include <io.h>	This font is used for examples, user input, program output, and error messages in text.
CL [option...]  file...	Three dots (an ellipsis) following an item indicate that more items having the same form may appear.
while() {  .  .  . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second. The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
"argument"	Quotation marks enclose a new term the first time it is defined in text.
"C string"	Some language constructs, such as strings, require quotation marks. Quotation marks required by the language have the form " " and ' ' rather than " " and ' '.
Dynamic-Link Library (DLL)	The first time an acronym is used, it is usually spelled out.
Microsoft Specific	This manual documents the C++ language, as it is implemented in Microsoft C++. As a result, some of the features of C++ that are implementation dependent or undefined in the ANSI base document are defined by the Microsoft implementation. You can find these features by looking for the "Microsoft Specific" heading in the left margin.
32-Bit Specific 16-Bit Specific	When a particular feature is specific only to 32-bit compilations or to 16-bit compilations, it is marked by the appropriate heading in the left margin. In text, such compilations are referred to as "32-bit (or 16-bit) target compilations."
♦	This symbol denotes the end of "Microsoft Specific," "16-Bit Specific," or "32-Bit Specific" information.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  Special Terminology

In this manual, the term "argument" refers to the entity that is passed to a function. In some cases, it is modified by "actual" or "formal," which mean the argument expression specified in the function call and the argument declaration specified in the function definition, respectively.

The term "variable" refers to a simple C-type data object. The term "object" refers to both C++ objects and variables; it is an inclusive term.

For more information on terminology used in this manual, see »Terms« in Chapter 2.


Chapter 1: Lexical Conventions
  Chapter 1  Lexical Conventions

This chapter introduces the fundamental elements of a C++ program as they are meaningful to the compiler. These elements, called "lexical elements" or "tokens," are used to construct statements, definitions, declarations, and so on, which are used to construct complete programs. Tokens include:

•	Comments

•	Identifiers

•	C++ keywords

•	Punctuators

•	Operators

•	Literals

C++ programs, like C programs, consist of one or more files. Each of these files is translated in the following conceptual order (the actual order follows the "as if" rule: translation must occur as if these steps had been followed):

1.	Lexical tokenizing. In this translation phase, character mapping and trigraph processing, line splicing, and tokenization are performed.

2.	Preprocessing. This translation phase brings in ancillary source files referenced by #include directives, handles "stringizing" and "charizing" directives, and performs token pasting and macro expansion (see Chapter 1 of the Preprocessor Reference for more information about preprocessor behavior). The result of the preprocessing phase is a sequence of tokens that, taken together, define a "translation unit."

Preprocessor directives always begin with the number-sign (#) character (that is, the first nonwhite-space character on the line must be a number sign). Only one preprocessor directive can appear on a given line. For example:

#include <iostream.h>  // Include text of iostream.h in
                       //  translation unit.
#define NDEBUG         // Define NDEBUG (NDEBUG contains empty
                       //  text string).

3.	Code generation. This translation phase uses the tokens generated in the preprocessing phase to generate object code.

During this phase, syntactic and semantic checking of the source code is performed.

See Appendix A of the Preprocessor Reference for more specific information about translation of source programs.

The C++ preprocessor is a strict superset of the ANSI C preprocessor, but the C++ preprocessor does differ in a few instances. The following list describes several differences between the ANSI C and the C++ preprocessors:

•	Single-line comments are supported. See »Comments« for more information.

•	One predefined macro, __cplusplus, is defined only for C++. See Chapter 1 of the Preprocessor Reference for a list of predefined macros.

•	The C preprocessor does not recognize the C++ operators: .*, −>*, and ::. See »Operators« and »Chapter 4, Expressions,« for more information about operators.


  1.1  Tokens

A token is the smallest element of a C++ program that is meaningful to the compiler. The C++ parser recognizes these kinds of tokens: identifiers, keywords, literals, operators, punctuators, and other separators. A stream of these tokens makes up a translation unit.

Tokens are most commonly separated by "white space." White space can be one or more:

•	Blanks

•	Horizontal or vertical tabs

•	New lines

•	Formfeeds

•	Comments

Syntax

token:
keyword
identifier
constant
operator
punctuator

preprocessing-token:
header-name
identifier
pp-number
character-constant
string-literal
operator
punctuator
each nonwhite-space character that cannot be one of the above

The parser separates tokens out of the input stream by creating the longest token possible using the input characters in a left-to-right scan. Consider the following code fragment:

a = i+++j;

The intention of the programmer who wrote the code might have been either of these two statements:

a = i + (++j)

a = (i++) + j

Because the parser creates the longest token possible from the input stream, it chooses the second interpretation, making the tokens i++, +, and j.


  1.2  Comments

A comment is text that the compiler ignores but that is useful for programmers. Comments are normally used to annotate code for future reference. The compiler treats them as white space. Comments can be used in testing to render certain lines of code inactive; however, #if/#endif preprocessor directives work better for this because you can surround code that contains comments but you cannot nest comments.

A C++ comment is written in one of the following ways:

•	The /* (slash, asterisk) characters, followed by any sequence of characters (including new lines), followed by the */ characters. This syntax is the same as ANSI C.

•	The // (two slashes) characters, followed by any sequence of characters. A new line not immediately preceded by a backslash terminates this form of comment. Therefore, it is commonly called a "single-line comment."

The comment characters (/*, */, and //) have no special meaning within a character constant, string literal, or comment. Comments using the first syntax, therefore, cannot be nested. Consider this example:

/* Intent:  Comment out this block of code.
   Problem: Nested comments on each line of code are illegal.
FileName = String( "hello.dat" ); /* Initialize file string */
cout << "File: " << FileName << "\n"; /* Print status message */
*/

The preceding code will not compile because the compiler scans the input stream from the first /* to the first */ and considers it a comment. In this case, the first */ occurs at the end of the Initialize file string comment. The last */, then, is no longer paired with an opening /*.

Note that the single-line form (//) of a comment followed by the line-continuation token (\) can have surprising effects. Consider this code:

#include <stdio.h>

int main()
{
    printf( "This is a number %d", // \
             5 );
    return 0;
}

After preprocessing, the preceding code appears as follows:

#include <stdio.h>

int main()
{
    printf( "This is a number %d",
    return 0;
}

Because the single-line comment causes all further text on the same line to be considered a comment, the preceding program generates error messages.


  1.3  Identifiers

An identifier is a sequence of characters used to denote one of the following:

•	Object or variable name

•	Class, structure, or union name

•	Enumerated type name

•	Member of a class, structure, union, or enumeration

•	Function or class-member function

•	typedef name

•	Label name

•	Macro name

•	Macro parameter

Syntax

identifier:
nondigit
identifier nondigit
identifier digit

nondigit:  one of
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

digit:  one of
0 1 2 3 4 5 6 7 8 9

Microsoft Specific

Microsoft C++ identifiers are sequences of characters of which only the first 247 characters are significant. This restriction is complicated by the fact that names for user-defined types are "decorated" by the compiler to preserve type information; the resultant name, including the type information, cannot be longer than 247 characters. (See »Appendix C, Decorated Names,« for more information on decorated names.) Factors that can influence the length of a decorated identifier are:

•	Whether the identifier denotes an object of user-defined type or a type derived from a user-defined type.

•	Whether the identifier denotes a function or a type derived from a function.

•	The number of arguments to a function. ♦

The first character of an identifier must be an alphabetic character, either uppercase or lowercase, or an underscore (_). Because C++ identifiers are case sensitive, fileName is different from FileName.

Identifiers cannot be exactly the same spelling and case as keywords. Identifiers that contain keywords are legal. For example, Pint is a legal identifier, even though it contains int, which is a keyword.

Use of two sequential underscore characters (__) at the beginning of an identifier, or a single leading underscore followed by a capital letter, is reserved for C++ implementations in all scopes. Use of one leading underscore followed by a lowercase letter should also be avoided for names with file scope because of possible conflicts with current or future reserved identifiers.


  1.4  C++ Keywords

Keywords are predefined reserved identifiers that have special meanings. They cannot be used as identifiers in your program. The following keywords are reserved for C++:

Syntax

keyword: one of

asm (1)	float	signed
auto	for	sizeof
break	friend	static
case	goto	struct
catch	if	switch
char	inline	template
class	int	this
const	long	throw
continue	new	typedef
default	operator	union
delete	private	unsigned
do	protected	virtual
double	public	void
else	register	volatile
enum	return	while
extern	short
(1) 	Reserved for compatibility with other C++ implementations, but not implemented. Use __asm.

Microsoft Specific

In Microsoft C++, identifiers with two leading underscores are reserved for compiler implementations. Therefore, the Microsoft convention is to precede Microsoft-specific keywords with double underscores. These words cannot be used as identifier names.

The following keywords are recognized for both 16-bit and 32-bit targets:

__asm (1)

__based (2)

__cdecl

__fastcall

 (1) 	Replaces C++ asm syntax.

 (2) 	The __based keyword has limited uses for 32-bit target compilations.

The following keywords are recognized only for 16-bit targets:

__export	__interrupt	__saveregs
__far	__loadds	__segment
__fortran	__near	__segname
__huge	__pascal	__self
The following keywords are recognized only for 32-bit targets:

__declspec	__finally	__stdcall
__except	__leave	__try
Microsoft extensions are enabled by default. To ensure that your programs are fully portable, you can disable Microsoft extensions by specifying the /Za command-line option (compile for ANSI compatibility) during compilation. When you do this, Microsoft-specific keywords are disabled.

When Microsoft extensions are enabled, you can use the keywords listed above in your programs. For ANSI compliance, these keywords are prefaced by a double underscore. For backward compatibility, single-underscore versions of all the keywords except __except, __finally, __leave and __try are supported. In addition, __cdecl, __far, __fortran, __huge, __interrupt, __near, and __pascal are available with no leading underscore. ♦


  1.5  Punctuators

Punctuators in C++ have syntactic and semantic meaning to the compiler but do not, of themselves, specify an operation that yields a value. Some punctuators, either alone or in combination, can also be C++ operators or be significant to the preprocessor.

Syntax

punctuator:  one of
!  %  ^  &  *  (  )  −  +  =  {  }  |  ~
[  ]  \  ;  '  :  "  <  >  ?  ,  .  /  #

The punctuators [ ], ( ), and { } must appear in pairs after translation phase 4. (For more information, see Appendix A of the Preprocessor Reference.)


  1.6  Operators

Operators specify an evaluation to be performed on one of the following:

•	One operand (unary operator)

•	Two operands (binary operator)

•	Three operands (ternary operator)

The C++ language includes all C operators and adds several new operators. Table 1.1 lists the operators available in Microsoft C++.

Operators follow a strict precedence. This precedence defines the evaluation order of expressions containing these operators. Operators associate with either the expression on their left or the expression on their right; this is called "associativity." Operators in the same group have equal precedence and are evaluated left to right in an expression unless explicitly forced by a pair of parentheses, ( ). Table 1.1 shows the precedence and associativity of C++ operators (from highest to lowest precedence).

Table 1.1    C++ Operator Precedence, Syntax, and Associativity

Operator	Name or Meaning	Syntax	Associativity
::	Scope resolution	class-name :: name	None
::	Global	:: name	None
[ ]	Array subscript	postfix-expression [expression(opt) ]	Left to right
( )	Function call	postfix-expression      ( expression-list(opt) )	Left to right
( )	Conversion	simple-type-name      ( expression-list(opt) )	None
.	Member selection (object)	postfix-expression . name	Left to right
−>	Member selection (pointer)	postfix-expression −> name	Left to right
++	Postfix increment	postfix-expression ++	None
−−	Postfix decrement	postfix-expression −−	None
new	Allocate object	::(opt) new placement(opt)      new-type-name      new-initializer (opt)	None
		::(opt) new placement(opt)      ( type-name )      new-initializer (opt)	None
delete	Deallocate object	:: (opt)  delete cast-expression	None
delete[ ]	Deallocate object	:: (opt)  delete [ ] cast-expression	None
++	Prefix increment	++ unary-expression	None
−−	Prefix decrement	−−unary-expression	None
*	Dereference	* cast-expression	None
&	Address-of	& cast-expression	None
+	Unary plus	+ cast-expression	None
−	Arithmetic negation (unary)	− cast-expression	None
!	Logical NOT	! cast-expression	None
~	Bitwise complement	~ cast-expression	None
:>	Base operator (16-bit specific; Microsoft specific)	base-expression :> expression	None
sizeof	Size of object	sizeof unary-expression	None
sizeof ( )	Size of type	sizeof( type-name )	None
(type)	Type cast (conversion)	( type-name ) cast-expression	Right to left
.*	Apply pointer to class member (objects)	pm-expression .* cast-expression	Left to right
−>*	Dereference pointer to class member	pm-expression −>* cast-expression	Left to right
*	Multiplication	multiplicative-expression *      pm-expression	Left to right
/	Division	multiplicative-expression /     pm-expression	Left to right
%	Remainder (modulus)	multiplicative-expression %     pm-expression	Left to right
+	Addition	additive-expression +      multiplicative-expression	Left to right
−	Subtraction	additive-expression −      multiplicative-expression	Left to right
<<	Left shift	shift-expression <<     additive-expression	Left to right
>>	Right shift	shift-expression >>     additive-expression	Left to right
<	Less than	relational-expression <     shift-expression	Left to right
>	Greater than	relational-expression >     shift-expression	Left to right
<=	Less than or equal to	relational-expression <=     shift-expression	Left to right
>=	Greater than or equal to	relational-expression >=     shift-expression	Left to right
==	Equality	equality-expression ==     relational-expression	Left to right
!=	Inequality	equality-expression !=     relational-expression	Left to right
&	Bitwise AND	and-expression &     equality-expression	Left to right
^	Bitwise exclusive OR	exclusive-or-expression ^      and-expression	Left to right
|	Bitwise OR	inclusive-or-expression |      exclusive-or-expression	Left to right
&&	Logical AND	logical-and-expression &&      inclusive-or-expression	Left to right
||	Logical OR	logical-or-expression ||      logical-and-expression	Left to right
e1?e2:e3	Conditional	logical-or-expression ?      expression :      conditional-expression	Right to left
=	Assignment	unary-expression =      assignment-expression	Right to left
*=	Multiplication assignment	unary-expression *=      assignment-expression	Right to left
/=	Division assignment	unary-expression /=      assignment-expression	Right to left
%=	Modulus assignment	unary-expression %=      assignment-expression	Right to left
+=	Addition assignment	unary-expression +=      assignment-expression	Right to left
−=	Subtraction assignment	unary-expression −=      assignment-expression	Right to left
<<=	Left-shift assignment	unary-expression <<=      assignment-expression	Right to left
>>=	Right-shift assignment	unary-expression >>=      assignment-expression	Right to left
&=	Bitwise AND assignment	unary-expression &=      assignment-expression	Right to left
|=	Bitwise inclusive OR assignment	unary-expression |=      assignment-expression	Right to left
^=	Bitwise exclusive OR assignment	unary-expression ^=      assignment-expression	Right to left
,	Comma	expression, assignment-expression	Left to right


  1.7  Literals

Invariant program elements are called "literals" or "constants." The terms "literal" and "constant" are used interchangeably here. Literals fall into four major categories: integer, character, floating-point, and string literals.

Syntax

literal:
integer-constant
character-constant
floating-constant
string-literal


  Integer Constants

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. Integer constants can be specified in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

Syntax

integer-constant:
decimal-constant integer-suffix (opt)
octal-constant integer-suffix (opt)
hexadecimal-constant integer-suffix (opt)
'c-char-sequence'

decimal-constant:
nonzero-digit
decimal-constant digit

octal-constant:
0
octal-constant octal-digit

hexadecimal-constant:
0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit:  one of
1 2 3 4 5 6 7 8 9

octal-digit:  one of
0 1 2 3 4 5 6 7

hexadecimal-digit:  one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

integer-suffix:
unsigned-suffix long-suffix (opt)
long-suffix unsigned-suffix (opt)

unsigned-suffix:  one of
u U

long-suffix:  one of
l L

To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.

To specify a decimal constant, begin the specification with a nonzero digit. For example:

int i = 157;   // Decimal constant
int j = 0198;  // Not a decimal number; erroneous octal constant
int k = 0365;  // Leading zero specifies octal constant, not decimal

To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in the specification of an octal constant. For example:

int i = 0377;	// Octal constant
int j = 0397;	// Error: 9 is not an octal digit

To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:

int i = 0x3fff;	// Hexadecimal constant
int j = 0X3FFF;	// Equal to i

To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:

unsigned uVal = 328u;             // Unsigned value
long lVal = 0x7FFFFFL;            // Long value specified
                                  //  as hex constant
unsigned long ulVal = 0776745ul;  // Unsigned long value


  Character Constants

Character constants are one or more members of the "source character set," the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the "execution character set," the character set on the machine where the program executes.

Microsoft Specific

For Microsoft C++, the source and execution character sets are both ASCII. ♦

There are three kinds of character constants:

•	Normal character constants

•	Multicharacter constants

•	Wide-character constants

Note  Use wide-character constants in place of multicharacter constants to ensure portability.

Character constants are specified as one or more characters enclosed in single quotation marks. For example:

char ch = 'x';          // Specify normal character constant.
int mbch = 'ab';        // Specify system-dependent
                        //  multicharacter constant.
wchar_t wcch = L'ab';   // Specify wide-character constant.

Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. The number of meaningful characters in a multicharacter constant is equal to the expression sizeof( int ). For 16-bit targets, this is 2; for 32-bit targets, this is 4. Specifying too many characters for a multicharacter constant generates an error message.

Syntax

character-constant:
'c-char-sequence'
L'c-char-sequence'

c-char-sequence:
c-char
c-char-sequence c-char

c-char:
any member of the source character set except the single quotation mark ('),
    backslash (\), or newline character
escape-sequence

escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence:  one of
\'  \"  \?  \\
\a  \b  \f  \n  \r  \t  \v

octal-escape-sequence:
\octal-digit
\octal-digit octal-digit
\octal-digit octal-digit octal-digit

hexadecimal-escape-sequence:
\xhexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit

Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)

The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:

char schar = 'x';               // Normal character constant
wchar_t wchar = L'\x81\x19';    // Wide-character constant

Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.

Table 1.2    C++ Reserved or Nongraphic Characters

Character	ASCII Representation	ASCII Value	Escape Sequence
Newline	NL (LF)	10 or 0x0a	\n
Horizontal tab	HT	9	\t
Vertical tab	VT	11 or 0x0b	\v
Backspace	BS	8	\b
Carriage return	CR	13 or 0x0d	\r
Formfeed	FF	12 or 0x0c	\f
Alert	BEL	7	\a
Backslash	\	92 or 0x5c	\\
Question mark	?	63 or 0x3f	\?
Single quotation mark	'	39 or 0x27	\'
Double quotation mark	"	34 or 0x22	\"
Octal number	ooo	—	\ooo
Hexadecimal number	hhh	—	\xhhh
Null character	NUL	0	\0
If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning ("unrecognized character escape sequence") is issued.

Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.

Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:

wchar_t och = L'\076a';  // Sequence terminates at a
char    ch = '\233';     // Sequence terminates after 3 characters

Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.

Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (See Appendix A of the Preprocessor Reference for more information about line continuation.)


  Floating-Point Constants

Floating-point constants specify values that must have a fractional part. These values contain decimal points (.) and can contain exponents.

Syntax

floating-constant:
fractional-constant exponent-part (opt )  floating-suffix (opt)
digit-sequence exponent-part floating-suffix (opt)

fractional-constant:
digit-sequence (opt)  . digit-sequence
digit-sequence .

exponent-part:
e sign (opt)  digit-sequence
E sign (opt)  digit-sequence

sign:  one of
+ −

digit-sequence:
digit
digit-sequence digit

floating-suffix:  one of
f l F L

Floating-point constants have a "mantissa," which specifies the value of the number, an "exponent," which specifies the magnitude of the number, and an optional suffix that specifies the constant's type. The mantissa is specified as a sequence of digits followed by a period, followed by an optional sequence of digits representing the fractional part of the number. For example:

18.46
38.

The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following example:

18.46e0	// 18.46
18.46e1	// 184.6

If an exponent is present, the trailing decimal point is unnecessary in whole numbers such as 18E0.

Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.

32-Bit Specific

For 32-bit targets, long double and double have the same representation even though they are not the same type. For example, you can have overloaded functions like

void foo( double );

and

void foo( long double );  ♦


  String Literals

A string literal consists of zero or more characters from the source character set surrounded by double quotation marks ("). A string literal represents a sequence of characters that, taken together, form a null-terminated string. Although some C++ class libraries, including the Microsoft libraries, supply sophisticated string-handling functionality, the strings defined in the language are relatively simple.

Syntax

string-literal:
"s-char-sequence (opt) "
L"s-char-sequence (opt) "

s-char-sequence:
s-char
s-char-sequence s-char

s-char:
any member of the source character set except the double quotation mark ( (") ),
   backslash (\), or newline character
escape-sequence

C++ strings have these types:

•	Array of char[n], where n is the length of the string (in characters) plus 1 for the terminating '\0' that marks the end of the string

•	Array of wchar_t, for wide-character strings

The result of modifying a string constant is undefined. For example:

char *szStr = "1234";
szStr[2] = 'A';	// Results undefined

Microsoft Specific

In some cases, identical string literals can be "pooled" to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal. The /Gf command-line option enables string pooling.

See Chapter 2 of the Build Tools User's Guide for more information on /Gf. ♦

When specifying string literals, adjacent strings are concatenated. Therefore, this declaration:

char szStr[] = "12" "34";

is identical to this declaration:

char szStr[] = "1234";

This concatenation of adjacent strings makes it easy to specify long strings across multiple lines:

cout << "Four score and seven years "
        "ago, our forefathers brought forth "
        "upon this continent a new nation.";

In the preceding example, the entire string Four score and seven years ago, our forefathers brought forth upon this continent a new nation. is spliced together. This string can also be specified using line splicing as follows:

cout << "Four score and seven years \
ago, our forefathers brought forth \
upon this continent a new nation.";

After all adjacent strings in the constant have been concatenated, the NULL character, '\0', is appended to provide an end-of-string marker for C string-handling functions.

When the first string contains an escape character, string concatenation can yield surprising results. Consider the following two declarations:

char szStr1[] = "\01" "23";
char szStr2[] = "\0123";

Although it is natural to assume that szStr1 and szStr2 contain the same values, the values they actually contain are shown in »Figure 1.1.«

Microsoft Specific

The maximum length of a string literal is approximately 2,048 bytes. This limit applies to strings of type char[] and wchar_t[]. If a string literal consists of parts enclosed in double quotation marks, the preprocessor concatenates the parts into a single string, and for each line concatenated, it adds an extra byte to the total number of bytes.

For example, suppose a string consists of 40 lines with 50 characters per line (2,000 characters), and one line with 7 characters, and each line is surrounded by double quotation marks. This adds up to 2,007 bytes plus one byte for the terminating null character, for a total of 2,008 bytes. On concatenation, an extra character is added to the total number of bytes for each of the first 40 lines. This makes a total of 2,048 bytes. (The extra characters are not actually written to the string.) Note, however, that if line continuations (\) are used instead of double quotation marks, the preprocessor does not add an extra character for each line. ♦

Determine the size of string objects by counting the number of characters and adding 1 for the terminating '\0' or 2 for type wchar_t.

Because the double quotation mark (") encloses strings, use the escape sequence (\") to represent enclosed double quotation marks. The single quotation mark (') can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a string, you must type two backslashes (\\). (For more information about line continuation, see Appendix A of the Preprocessor Reference.)

To specify a string of type wide-character (wchar_t[]), precede the opening double quotation mark with the character L. For example:

wchar_t wszStr[] = L"1a1g";

All normal escape codes listed in »Character Constants« are valid in string constants. For example:

cout << "First line\nSecond line";
cout << "Error! Take corrective action\a";

Because the escape code terminates at the first character that is not a hexadecimal digit, specification of string constants with embedded hexadecimal escape codes can cause unexpected results. The following example is intended to create a string literal containing ASCII 5, followed by the characters five:

"\x05five"

The actual result is a hexadecimal 5F, which is the ASCII code for an underscore, followed by the characters ive. The following example produces the desired results:

"\005five"     // Use octal constant.
"\x05" "five"  // Use string splicing.


Chapter 2: Basic Concepts
  Chapter 2  Basic Concepts

This chapter explains some concepts that are key to understanding C++. While many of these concepts are familiar to C programmers, there are some subtle differences that can cause unexpected program results. Some of the topics covered in this chapter are:

•	Terminology. Terms used later in this book are introduced and defined.

•	Declarations and definitions. »Declarations and Definitions« explains and illustrates the difference between these two concepts.

•	Scope. The scope of a C++ object or function is different from C; the scoping rules are defined. See »Scope«.

•	Linkage. Linkage rules are described as is the definition of a "program." See »Program and Linkage«.

•	Program startup, termination, and the main function. The sequence of startup and termination is discussed, as is defining the purpose and behavior of the main function. See »Startup and Termination«.

•	Storage classes. The treatment of auto and static objects in C++, including initialization and destruction, is discussed. See »Storage Classes«.

•	Types. The behavior of C++ fundamental (built-in) types is explained. The discussion includes derived types, type names, name spaces, and limits for each type. See »Types«.

Additional topics include l-values, r-values, name spaces, and numerical limits.


  2.1  Terms

The following short definitions explain C++ terminology used in this chapter and in the rest of the book.

Table 2.1    C++ Terminology

Term	Meaning
Declaration	A declaration introduces names and their types into a program without necessarily defining an associated object or function. However, many declarations do serve as definitions.
Definition	A definition provides information that allows the compiler to allocate memory for objects or generate code for functions.
Lifetime	The lifetime of an object is the period during which an object exists, including its creation and destruction.
Linkage	Names can have external linkage, internal linkage, or no linkage. Within a program (a set of translation units), only names with external linkage denote the same object or function. Within a translation unit, names with either internal or external linkage denote the same object or function (except when functions are overloaded). (For more information on translation units, see Appendix A of the Preprocessor Reference.) Names with no linkage denote unique objects or functions.
Name	A name denotes an object, function, set of overloaded functions, enumerator, type, class member, template, value, or label. C++ programs use names to refer to their associated language element. Names can be type names or identifiers.
Object	An object is an instance (a data item) of a user-defined type (a class type). The difference between an object and a variable is that variables retain state information, whereas objects can also have behavior. This manual draws a distinction between objects and variables: "object" means instance of a user-defined type, whereas "variable" means instance of a fundamental type. In cases where either object or variable is applicable, the term "object" is used as the inclusive term, meaning "object or variable."
Scope	Names can be used only within specific regions of program text. These regions are called the scope of the name.
Storage class	The storage class of a named object determines its lifetime, initialization, and, in certain cases, its linkage.
Type	Names have associated types that determine the meaning of the value or values stored in an object or returned by a function.
Variable	A variable is a data item of a fundamental type (for example, int, float, or double). Variables store state information but define no behavior for how that information is handled. See the list item "Object" above for information about how the terms "variable" and "object" are used in this manual.


  2.2  Declarations and Definitions

Declarations explain to the compiler that a program element or name exists; definitions specify to the compiler what code or data the name describes. A name must be declared before it can be used.


  Declarations

A declaration introduces one or more names into a program. Declarations also serve as definitions, except in the following cases:

•	The declaration is a function prototype (a function declaration with no function body).

•	The declaration contains the extern specifier but no initializer (objects and variables) or function body (functions). This signifies that the definition is not necessarily in the current translation unit and gives the name external linkage.

•	The declaration is of a static data member inside a class declaration.

Because static class data members are discrete variables shared by all objects of the class, they must be defined and initialized outside the class declaration. (For more information about classes and class members, see »Chapter 8, Classes.«)

•	The declaration is a class name declaration with no following definition, such as class T;.

•	The declaration is a typedef statement.

Examples of declarations that are also definitions are:

// Declare and define int variables i and j.
int i;
int j = 10;

// Declare enumeration suits.
enum suits { Spades = 1, Clubs, Hearts, Diamonds };

// Declare class CheckBox.
class CheckBox : public Control
{
public:
            Boolean IsChecked();
    virtual int     ChangeState() = 0;
};

Some declarations that are not definitions are:

extern int i;
char *strchr( const char *Str, const char Target );


  Definitions

A definition is a unique specification of an object or variable, function, class, or enumerator. Because definitions must be unique, a program can contain only one definition for a given program element. Declarations can occur more than once in a program. Therefore, classes, structures, enumerated types, and other user-defined types can be declared for each compilation unit. The constraint on this multiple declaration is that all declarations must be identical.

There can be a many-to-one correspondence between declarations and definitions. There are two cases in which a program element can be declared and not defined:

•	A function is declared but never referenced with a function call or with an expression that takes the function's address.

•	A class is used only in a way that does not require its definition be known. However, the class must be declared. The following code illustrates such a case:

class WindowCounter;    // Forward reference; no definition

class Window
{
    static WindowCounter windowCounter;  // Definition of
                                         //  WindowCounter
                                         //  not required.
};


  2.3  Scope

C++ names can be used only in certain regions of a program. This area is called the "scope" of the name. Scope determines the "lifetime" of a name that does not denote an object of static extent. Scope also determines the visibility of a name, when class constructors and destructors are called, and when variables local to the scope are initialized. (For more information, see »Constructors« and »Destructors« in Chapter 11.) There are five kinds of scope:

•	Local scope. A name declared within a block is accessible only within that block and blocks enclosed by it, and only after the point of declaration. The names of formal arguments to a function in the scope of the outermost block of the function have local scope, as if they had been declared inside the block enclosing the function body. Consider the following code fragment:

{
    int i;
}

Because the declaration of i is in a block enclosed by curly braces, i has local scope and is never accessible because no code accesses it before the closing curly brace.

•	Function scope. Labels are the only names that have function scope. They can be used anywhere within a function but are not accessible outside that function.

•	File scope. Any name declared outside all blocks or classes has file scope. It is accessible anywhere in the translation unit after its declaration. Names with file scope that do not declare static objects are often called "global" names.

•	Class scope. Names of class members have class scope. Class member functions can be accessed only by using the member-selection operators (. or −>) or pointer-to-member operators (.* or −>*) on an object or pointer to an object of that class; nonstatic class member data is considered local to the object of that class. Consider the following class declaration:

class Point
{
    int x;
    int y;
};

The class members x and y are considered to be in the scope of class Point.

•	Prototype scope. Names declared in a function prototype are visible only until the end of the prototype. The following prototype declares two names (szDest, szSource); these names go out of scope at the end of the prototype:

char *strcpy( char *szDest, const char *szSource );


  Point of Declaration

A name is considered to be declared immediately after its declarator but before its (optional) initializer. (For more information on declarators, see »Chapter 7, Declarators.«) An enumerator is considered to be declared immediately after the identifier that names it but before its (optional) initializer.

Consider this example:

double dVar = 7.0;

int main()
{
    double dVar = dVar;
}

If the point of declaration were after the initialization, then the local dVar would be initialized to 7.0, the value of the global variable dVar. However, since that is not the case, dVar is initialized to an undefined value.

Enumerators follow the same rule. However, enumerators are exported to the enclosing scope of the enumeration. In the following example, the enumerators Spades, Clubs, Hearts, and Diamonds are declared. Because the enumerators are exported to the enclosing scope, they are considered to have global scope. The identifiers in the example are already defined in global scope.

Consider the following code:

const int Spades = 1, Clubs = 2, Hearts = 3, Diamonds = 4;

enum Suits
{
    Spades = Spades,	    // error
    Clubs,              // error
    Hearts,             // error
    Diamonds	            // error
};

Because the identifiers in the preceding code are already defined in global scope, an error message is generated.

Note  Using the same name to refer to more than one program element — for example, an enumerator and an object — is considered poor programming practice and should be avoided. In the preceding example, this practice causes an error.


  Hiding Names

A name can be hidden by declaring that name in an enclosed block. In »Figure 2.1«, i is redeclared within the inner block, thereby hiding the variable associated with i in the outer block scope.

The output from the program shown in »Figure 2.1« is:

i = 0
i = 7
j = 9
i = 0

Note  The argument szWhat is considered to be in the scope of the function. Therefore, it is treated as if it had been declared in the outermost block of the function.


  Hiding Names with File Scope

Names with file scope can be hidden by explicitly declaring the same name in block scope. However, file-scope names can be accessed using the scope-resolution operator (::). For example:

#include <iostream.h>

int i = 7;      // i has file scope--declared
                // outside all blocks

int main( int argc, char *argv[] )
{
int i = 5;  // i has block scope--hides
                // the i with file scope

cout << "Block-scoped i has the value: " << i << "\n";
cout << "File-scoped i has the value: " << ::i << "\n";

return 0;
}

The result of the preceding code is:

Block-scoped i has the value: 5
File-scoped i has the value: 7


  Hiding Class Names

Class names can be hidden by declaring a function, object or variable, or enumerator in the same scope. However, the class name can still be accessed when prefixed by the keyword class.

// Declare class Account at file scope.
class Account
{
public:
    Account( double InitialBalance )
        { balance = InitialBalance; }
    double GetBalance()
        { return balance; }
    double Deposit( double HowMuch )
        { return balance += HowMuch; }
    double Withdraw( double HowMuch )
        { return balance -= HowMuch; }
private:
    double balance;
};

double Account = 15.37;            // Hides class name Account

int main( int argc, char *argv[] )
{
    class Account Checking( Account ); // Qualifies Account as
                                       //  class name

    cout << "Opening account with balance of: "
         << Checking.GetBalance() << "\n";
    cout << "Depositing $10.57, for a remaining balance of: "
         << Checking.Deposit( 10.57 ) << "\n";
    cout << "Withdrawing $27.16, for a remaining balance of: "
         << Checking.Withdraw( 27.16 ) << "\n";

    return 0;
}

Note that any place the class name (Account) is called for, the keyword class must be used to differentiate it from the file-scoped variable Account. This rule does not apply when the class name occurs on the left side of the scope-resolution operator (::). Names on the left side of the scope-resolution operator are always considered class names. The following example demonstrates how to declare a pointer to an object of type Account using the class keyword:

class Account *Checking = new class Account( Account );

Note that the Account in the initializer (in parentheses) in the preceding statement has file scope; it is of type double.

Note  The reuse of identifier names as shown in this example is considered poor programming style.

For more information about pointers, see »Derived Types«. For information about declaration and initialization of class objects, see »Chapter 8, Classes.« For information about using the new and delete free-store operators, see »Chapter 11, Special Member Functions.«


  Scope of Formal Arguments to Functions

Formal arguments (arguments specified in function definitions) to functions are considered to be in the scope of the outermost block of the function body.


  2.4  Program and Linkage

A program consists of one or more translation units linked together. Execution (conceptually) begins in the translation unit that contains the function main. (For more information about translation units, see Appendix A of the Preprocessor Reference. For more information about the main function, see »Program Startup — the main Function«.)


  Types of Linkage

The way the names of objects and functions are shared between translation units is called "linkage." These names can have:

•	Internal linkage, in which case they refer only to program elements inside their own translation units; they are not shared with other translation units.

The same name in another translation unit may refer to a different object or a different class. Names with internal linkage are sometimes referred to as being "local" to their translation units.

An example declaration of a name with internal linkage is:

static int i;   // The static keyword ensures internal linkage.

•	External linkage, in which case they can refer to program elements in any translation unit in the program — the program element is shared among the translation units.

The same name in another translation unit is guaranteed to refer to the same object or class. Names with external linkage are sometimes referred to as being "global."

An example declaration of a name with external linkage is:

extern int i;

•	No linkage, in which case they refer to unique entities. The same name in another scope may not refer to the same object. An example is an enumeration. (Note, however, that you can pass a pointer to an object with no linkage. This makes the object accessible in other translation units.)


  Linkage in Names with File Scope

The following linkage rules apply to names (other than typedef and enumerator names) with file scope:

•	If a name is explicitly declared as static, it has internal linkage and identifies a program element inside its own translation unit.

•	Enumerator names and typedef names have no linkage.

•	All other names with file scope have external linkage.

Microsoft Specific

•	If a function name with file scope is explicitly declared as inline, it has external linkage if it is instantiated or its address is referenced. Therefore, it is possible for a function with file scope to have either internal or external linkage. ♦

A class has internal linkage if it meets these criteria:

•	Uses no C++ functionality (for example, member-access control, member functions, constructors, destructors, and so on).

•	Not used in the declaration of another name that has external linkage. This constraint means that objects of class type that are passed to functions with external linkage cause the class to have external linkage.


  Linkage in Names with Class Scope

The following linkage rules apply to names with file scope:

•	Static class members have external linkage.

•	Class member functions have external linkage.

•	Enumerators and typedef names have no linkage.

Microsoft Specific

•	Functions declared as friend functions must have external linkage. Declaring a static function as a friend generates an error. ♦


  Linkage in Names with Block Scope

The following linkage rules apply to names with block scope (local names):

•	Names declared as extern have external linkage unless they were previously declared as static.

•	All other names with block scope have no linkage.


  Names with No Linkage

The only names that have no linkage are:

•	Function parameters.

•	Block-scoped names not declared as extern or static.

•	Enumerators.

•	Names declared in a typedef statement. An exception is when the typedef statement is used to provide a name for an unnamed class type. The name may then have external linkage if the class has external linkage. The following example shows a situation in which a typedef name has external linkage:

typedef struct
{
    short x;
    short y;
} POINT;
extern int MoveTo( POINT pt );

The typedef name, POINT, becomes the class name for the unnamed structure. It is then used in the declaration of a function with external linkage.

Because typedef names have no linkage, their definitions can differ between translation units. Because the compilations take place discretely, there is no way for the compiler to detect these differences. As a result, errors of this kind are not detected until link time. Consider the following case:

// Translation unit 1
typedef int INT

INT myInt;
...

// Translation unit 2
typedef short INT

extern INT myInt;
...

The preceding code generates an "unresolved external" error at link time.

C++ functions can be defined only in file or class scope. The following example illustrates how to define functions and shows an erroneous function definition:

#include <iostream.h>

void ShowChar( char ch );    // Declare function ShowChar.

void ShowChar( char ch )     // Define function ShowChar.
{                            // Function has file scope.
cout << ch;
}

struct Char                  // Define class Char.
{
    char Show();             // Declare Show function.
    char Get();              // Declare Get function.
    char ch;
};

char Char::Show()            // Define Show function
{                            //  with class scope.
    cout << ch;
    return ch;
}

void GoodFuncDef( char ch )  // Define GoodFuncDef
{                            //  with file scope.
    int BadFuncDef( int i )  // Erroneous attempt to
    {                        //  nest functions.
        return i * 7;
    }
    for( int i = 0; i < BadFuncDef( 2 ); ++i )
        cout << ch;
    cout << "\n";
}


  Linkage to Non-C++ Functions

C functions and data can be accessed only if they are previously declared as having C linkage. However, they must be defined in a separately compiled translation unit.

Syntax

linkage-specification:
extern string-literal { declaration-list (opt ) }
extern string-literal declaration

declaration-list:
declaration
declaration-list declaration

Microsoft C++ supports the strings "C" and "C++" in the string-literal field. The following example shows alternative ways to declare names that have C linkage:

// Declare printf with C linkage.
extern "C" int printf( const char *fmt, ... );

//  Cause everything in the header file "cinclude.h"
//   to have C linkage.
extern "C"
{
#include <cinclude.h>
}

//  Declare the two functions ShowChar and GetChar
//   with C linkage.
extern "C"
{
    char ShowChar( char ch );
    char GetChar( void );
}

//  Define the two functions ShowChar and GetChar
//   with C linkage.
extern "C" char ShowChar( char ch )
{
    putchar( ch );
    return ch;
}

extern "C" char GetChar( void )
{
    char ch;

    ch = getchar();
    return ch;
}

// Declare a global variable, errno, with C linkage.
extern "C" int errno;


  2.5  Startup and Termination

Program startup and termination is facilitated by using two functions: main and exit. Additionally, other startup and termination code may be executed.


Program Startupthe main Function
  Program Startup — the main Function

A special function called main is the entry point to all C++ programs. This function is not predefined by the compiler; rather, it must be supplied in the program text. The declaration syntax for main is as follows:

int main( );

or, optionally:

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );

Alternatively, the main function can be declared as returning void (no return value). If you declare main as returning void, you cannot return an exit code to the parent process or operating system using a return statement; to return an exit code when main is declared as void, you must use the exit function.


  Argument Definitions

The arguments in the prototype

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );

allow convenient command-line parsing of arguments and, optionally, access to environment variables. The argument definitions are as follows:

argc

An integer that contains the count of arguments that follow in argv. The argc parameter is always greater than or equal to 1.

argv

An array of null-terminated strings representing command-line arguments entered by the user of the program. By convention, argv[0] is the command with which the program is invoked, argv[1] is the first command-line argument, and so on, until argv[argc], which is always NULL.

The first command-line argument is always argv[1] and the last one is argv[argc − 1].

Microsoft Specific

envp

The envp array, which is a common extension in many UNIX® systems, is used in Microsoft C++. It is an array of strings representing the variables set in the user's environment. This array is terminated by a NULL entry. ♦

The following example shows how to use the argc, argv, and envp arguments to main:

/* Program to demonstrate the environment variables.
 * If the /n command-line option is specified,
 * the listing of environment variables is line-
 * numbered.
 */

#include <iostream.h>
#include <string.h>

#define NL "\n"

int main( int argc, char *argv[], char *envp[] )
{
    int iNumberLines = 0;    // Default is no line numbers.

    // If more than .EXE filename supplied, and
    //  user supplies  /n or /N, flag option for line numbers.
    if( argc == 2 && stricmp( argv[1], "/n" ) == 0 )
        iNumberLines = 1;

    // Walk through list of strings until a NULL is encountered.
    for( int i = 0; envp[i] != NULL; ++i )
    {
        if( iNumberLines )
            cout << i << ": " << envp[i] << NL;
    }
    return 0;
}

Note  The return 0 statement at the end of the program is necessary because main is a function declared as returning an int value. If no return statement is present, or if the return statement does not specify a value, the compiler generates an error message.


  Wildcard Expansion (Microsoft Specific)

You can use wildcards — the question mark (?) and asterisk (*) — to specify filename and path arguments on the command line.

Command-line arguments are handled by a routine called _setargv.

32-Bit Specific

By default, _setargv expands wildcards into separate strings in the argv string array. If no matches are found for the wildcard argument, the argument is passed literally. ♦

16-Bit Specific

By default, _setargv does not expand wildcards into separate strings in the argv string array. However, by linking with the SETARGV.OBJ file, you can replace the default _setargv routine with a version that handles wildcards.

To include SETARGV.OBJ, specify it on the CL command line. The /NOE option (no extended dictionary search) must be supplied to the linker to avoid multiple-definition errors for the _setargv function. A sample CL command follows:

CL PROG.C \MSC\LIB\SETARGV.OBJ /LINK /NOE;

The result of the preceding command is that wildcard filenames are expanded in the same manner as operating-system commands. (See your operating system user's guide if you are unfamiliar with these characters.) Enclosing a command-line argument in quotation marks (" ") suppresses the wildcard expansion. Within quoted arguments, you can represent quotation marks literally by preceding the double quotation mark with a backslash (\).

Note  If you write your own _setargv function, it must be specified as extern "C" for the linker to recognize it.♦

If no matches are found for the wildcard argument, the argument is passed literally.


  Parsing Command-Line Arguments (Microsoft Specific)

Microsoft C startup code uses the following rules when interpreting arguments given on the operating system command line:

•	Arguments are delimited by white space, which is either a space or a tab.

•	The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.

•	A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.

•	A double quotation mark preceded by a backslash ( \") is interpreted as a literal double quotation mark character (").

•	Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

•	If an even number of backslashes is followed by a double quotation mark, then one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.

•	If an odd number of backslashes is followed by a double quotation mark, then one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

The following program demonstrates how command-line arguments are passed:

#include <iostream.h>

int main( int argc,       // Number of strings in array argv
          char *argv[],   // Array of command-line argument strings
          char *envp[] )  // Array of environment variable strings
{
    int count;

    // Display each command-line argument.
    cout << "\nCommand-line arguments:\n";
    for( count = 0; count < argc; count++ )
         cout << "  argv[" << count << "]   "
                << argv[count] << "\n";

    return 0;
}

Table 2.2 shows example input and expected output, demonstrating the rules in the preceding list.

Table 2.2    Results of Parsing Command Lines

Command-Line Input	argv[1]	argv[2]	argv[3]
"abc" d e	abc	d	e
a\\\b d"e f"g h	a\\\b	de fg	h
a\\\"b c d	a\"b	c	d
a\\\\"b c" d e	a\\b c	d	e
Customizing Command-Line Processing (Microsoft Specific)

If your program does not take command-line arguments, you can save a small amount of space by suppressing use of the library routine that performs command-line processing. This routine is called _setargv and is described in »Wildcard Expansion«. To suppress its use, define a routine that does nothing in the file containing the main function, and name it _setargv. The call to _setargv is then satisfied by your definition of _setargv, and the library version is not loaded.

Similarly, if you never access the environment table through the envp argument, you can provide your own empty routine to be used in place of _setenvp, the environment-processing routine. Just as with the _setargv function, _setenvp must be declared as extern "C".

Your program might make calls to the spawn or exec family of routines in the C run-time library. If this is the case, you should not suppress the environment processing routine, since this routine is used to pass an environment from the parent process to the child process.


  main Function Restrictions

Several restrictions apply to the main function that do not apply to any other C++ functions. The main function:

•	Cannot be overloaded (see »Chapter 12, Overloading«).

•	Cannot be declared as inline.

•	Cannot be declared as static.

•	Cannot have its address taken.

•	Cannot be called.


  Program Termination

There are several ways to exit a program:

•	Call the exit function.

•	Call the abort function.

•	Execute a return statement from main.


  exit Function

The exit function, declared in the standard include file STDLIB.H, terminates a C++ program.

The value supplied as an argument to exit is returned to the operating system as the program's return code or exit code. By convention, a return code of zero means that the program completed successfully.

Note  You can use the constants EXIT_FAILURE and EXIT_SUCCESS, defined in STDLIB.H, to indicate success or failure of your program.

Issuing a return statement from the main function is equivalent to calling the exit function with the return value as its argument.


  abort Function

The abort function, also declared in the standard include file STDLIB.H, terminates a C++ program. The difference between exit and abort is that exit allows the C++ run-time termination processing to take place (global object destructors will be called), whereas abort causes immediate program termination.


  return Statement

Issuing a return statement from main is functionally equivalent to calling the exit function. Consider the following example:

int main()
{
    exit( 3 );
    return 3;
}

The exit and return statements in the preceding example are functionally identical. However, C++ requires that functions that have return types other than void return a value. The return statement allows you to return a value from main.


  Additional Startup Considerations

In C++, object construction and destruction can involve executing user code. Therefore, it is important to understand which initializations happen before entry to main and which destructors are invoked after exit from main. (For detailed information about construction and destruction of objects, see »Constructors« and »Destructors« in Chapter 11.)

The following initializations take place prior to entry to main:

•	Default initialization of static data to zero. All static data without explicit initializers are set to zero prior to executing any other code, including run-time initialization. Static data members must still be explicitly defined.

•	Initialization of global static objects in a translation unit. This may occur either before entry to main or before the first use of any function or object in the object's translation unit.

Microsoft Specific

In Microsoft C++, global static objects are initialized before entry to main. ♦

Global static objects that are mutually interdependent but in different translation units may cause incorrect behavior.


  Additional Termination Considerations

You can terminate a C++ program by using exit, return, or abort. You can add exit processing using the atexit function. These are discussed in the following sections.


  Using exit or return

When you call exit or execute a return statement from main, static objects are destroyed in the reverse order of their initialization. This example shows how such initialization and cleanup works:

#include <stdio.h>

class ShowData
{
public:
    // Constructor opens a file.
    ShowData( const char *szDev )
    {
        OutputDev = fopen( szDev, "w" );
    }

    // Destructor closes the file.
    ~ShowData() { fclose( OutputDev ); }

    // Disp function shows a string on the output device.
    void Disp( char *szData )
    {
        fputs( szData, OutputDev );
    }
private:
    FILE *OutputDev;
};

//  Define a static object of type ShowData. The output device
//   selected is "CON" -- the standard output device.
ShowData sd1 = "CON";

//  Define another static object of type ShowData. The output
//   is directed to a file called "HELLO.DAT"
ShowData sd2 = "hello.dat";

int main()
{
    sd1.Disp( "hello to default device\n" );
    sd2.Disp( "hello to file hello.dat\n" );

    return 0;
}

In the preceding example, the static objects sd1 and sd2 are created and initialized before entry to main. After this program terminates using the return statement, first sd2 is destroyed and then sd1. The destructor for the ShowData class closes the files associated with these static objects. (For more information about initialization, constructors, and destructors, see »Chapter 11, Special Member Functions.«)

Another way to write this code is to declare the ShowData objects with block scope, allowing them to be destroyed when they go out of scope:

int main()
{
    ShowData sd1, sd2( "hello.dat" );

    sd1.Disp( "hello to default device\n" );
    sd2.Disp( "hello to file hello.dat\n" );

    return 0;
}


  Using atexit

The atexit function allows you to specify an exit-processing function that executes prior to program termination. No global static objects initialized prior to the call to atexit are destroyed prior to execution of the exit-processing function.


  Using abort

Calling the abort function causes immediate termination. It bypasses the normal destruction process for initialized global static objects. It also bypasses any special processing that was specified using the atexit function.


  2.6  Storage Classes

Storage classes govern the lifetime, linkage, and treatment of objects and variables in C++. A given object can have only one storage class. The following sections discuss the C++ storage classes for data: automatic, static, register, and external.


  Automatic

Objects and variables with automatic storage are local to a given instance of a block. In recursive or multithreaded code, automatic objects and variables are guaranteed to have different storage in different instances of a block. Microsoft C++ stores automatic objects and variables on the program's stack.

Objects and variables defined within a block have auto storage unless otherwise specified using the extern or static keyword. Automatic objects and variables can be specified using the auto keyword, but explicit use of auto is unnecessary. Automatic objects and variables have no linkage.

Automatic objects and variables persist only until the end of the block in which they are declared.


  Static

Objects and variables declared as static retain their values for the duration of the program's execution. In recursive code, a static object or variable is guaranteed to have the same state in different instances of a block of code.

Objects and variables defined outside all blocks have static lifetime and external linkage by default. A global object or variable that is explicitly declared as static has internal linkage.

Static objects and variables persist for the duration of the program's execution.


  Register

16-Bit Specific

Variables declared as register are allocated to a CPU register if there is a suitable register available. These variables behave as automatic variables, except that the compiler gives them preference over automatic variables when allocating register storage. ♦

Only function arguments and local variables can be declared with the register storage class.

Like automatic variables, register variables persist only until the end of the block in which they are declared.

32-Bit Specific

The 32-bit compiler does not honor user requests for register variables; instead, it makes its own register choices when global optimizations are on. However, all other semantics associated with the register keyword are honored by the 32-bit compiler. ♦


  External

Objects and variables declared as extern declare an object that is defined in another translation unit or in an enclosing scope as having external linkage.

Declaration of const variables with the extern storage class forces the variable to have external linkage. An initialization of an extern const variable is allowed in the defining translation unit. Initializations in translation units other than the defining translation unit produce undefined results.

The following code shows two extern declarations, DefinedElsewhere (which refers to a name defined in a different translation unit) and DefinedHere (which refers to a name defined in an enclosing scope):

extern int DefinedElsewhere;        // Defined in another translation
                                    //  unit.
int main()
{
    int DefinedHere;
    {
       extern int DefinedHere;     // Refers to DefinedHere in
                                   //  the enclosing scope.
    }
    return 0;
}


  Initialization of Objects

A local automatic object or variable is initialized every time the flow of control reaches its definition. A local static object or variable is initialized the first time the flow of control reaches its definition. Consider the following example, which defines a class that logs initialization and destruction of objects and then defines three objects, I1, I2, and I3:

#include <iostream.h>
#include <string.h>

// Define a class that logs initializations and destructions.
class InitDemo
{
public:
    InitDemo( const char *szWhat );
    ~InitDemo();
private:
    char *szObjName;
};

// Constructor for class InitDemo
InitDemo::InitDemo( const char *szWhat )
{
    if( szWhat != 0 && strlen( szWhat ) > 0 )
    {
        // Allocate storage for szObjName, then copy
        //  initializer szWhat into szObjName.
        szObjName = new char[ strlen( szWhat ) + 1 ];
        strcpy( szObjName, szWhat );
            cout << "Initializing: " << szObjName << "\n";
    }
    else
        szObjName = 0;
}

// Destructor for InitDemo
InitDemo::~InitDemo()
{
    if( szObjName != 0 )
    {
        cout << "Destroying: " << szObjName << "\n";
        delete szObjName;
    }
}

// Enter main function
int main()
{
    InitDemo I1( "Auto I1" );
    {
        cout << "In block.\n";
        InitDemo I2( "Auto I2" );
        static InitDemo I3( "Static I3" );
    }
    cout << "Exited block.\n";

    return 0;
}

The preceding code demonstrates how and when the objects I1, I2, and I3 are initialized and when they are destroyed. The output from the program is:

Initializing: Auto I1
In block.
Initializing: Auto I2
Initializing: Static I3
Destroying: Auto I2
Exited block.
Destroying: Auto I1
Destroying: Static I3

There are several points to note about the program.

First, I1 and I2 are automatically destroyed when the flow of control exits the block in which they are defined.

Second, in C++, it is not necessary to declare objects or variables at the beginning of a block. Furthermore, these objects are initialized only when the flow of control reaches their definitions. (I2 and I3 are examples of such definitions.) The output shows exactly when they are initialized.

Finally, static local variables such as I3 retain their values for the entire duration of the program but are destroyed as the program terminates.


  2.7  Types

C++ supports three kinds of object types:

•	Fundamental types, which are built into the language (such as int, float, or double). Instances of these fundamental types are often called "variables." These are discussed in »Fundamental Types«.

•	Derived types, which are new types derived from built-in types. These are discussed in »Derived Types«.

•	Class types, which are new types created by combining existing types. These are discussed in »Chapter 8, Classes.«


  Fundamental Types

Fundamental types in C++ are divided into four categories: "integral," "floating," "void," and "segment." Integral types are capable of handling whole numbers, whereas floating types are capable of specifying values that may have fractional parts.

The void type describes an empty set of values. No variable of type void can be specified — it is primarily used in declaring functions that return no values or in declaring "generic" pointers to untyped or arbitrarily typed data. Any expression can be explicitly converted or cast to type void. However, such expressions are restricted to the following uses:

•	An expression statement. (See »Chapter 4, Expressions,« for more information.)

•	The left operand of the comma operator. (See »Comma Operator« in Chapter 4 for more information.)

•	The second or third operand of the conditional operator (? :). (See »Expressions with the Conditional Operator« in Chapter 4 for more information.)

16-Bit Specific

The __segment type is a Microsoft-specific type that is used only when specifying the segment for a based object or pointer. ♦

Table 2.3 explains the restrictions on type sizes. These restrictions are independent of the Microsoft implementation.

Table 2.3    Fundamental Types of the C++ Language

Category	Type	Contents
Integral	char	Type char is an integral type that usually contains members of the execution character set — in Microsoft C++, this is ASCII.
		The C++ compiler treats variables of type char, signed char, and unsigned char as having different types. Variables of type char are promoted to int as if they are type signed char by default, unless the /J compilation option is used, in which case they are treated as type unsigned char and are promoted to int without sign extension.
	short	Type short int (or simply short) is an integral type that is larger than or equal to the size of type char and shorter than or equal to the size of type int.
		Objects of type short can be declared as signed short or unsigned short. Signed short is a synonym for short.
	int	Type int is an integral type that is larger than or equal to the size of type short int and shorter than or equal to the size of type long.
		Objects of type int can be declared as signed int or unsigned int. Signed int is a synonym for int.
	long	Type long (or long int) is an integral type that is larger than or equal to the size of type int.
		Objects of type long can be declared as signed long or unsigned long. Signed long is a synonym for long.
Floating	float	Type float is the smallest floating type.
	double	Type double is a floating type that is larger than or equal to type float but shorter than or equal to the size of type long double. (1)
	long double (1)	Type long double is a floating type that is larger than or equal to type double.
(1)  For 32-bit targets, the representation of long double and double is identical. However, long double and double are separate types.
Microsoft Specific

In Microsoft C++, variables of various fundamental types require different amounts of storage, depending on whether the program is compiled for a 16-bit or 32-bit target. Table 2.4 shows these differences.

Table 2.4    Sizes of Fundamental Types

Type	16-Bit Target Compilation	32-Bit Target  Compilation
char, unsigned char, signed char	1 byte	1 byte
short, unsigned short	2 bytes	2 bytes
int, unsigned int	2 bytes	4 bytes
long, unsigned long	4 bytes	4 bytes
float	4 bytes	4 bytes
double	8 bytes	8 bytes
long double (1)	10 bytes	8 bytes
(1)  For 32-bit targets, the representation of long double and double is identical. However, long double and double are separate types.
For more information about type conversion, see »Chapter 3, Standard Conversions.« ♦


  Derived Types

Derived types are new types that can be used in a program. They can conceptually be divided into types that are directly derived and types that are composed of other types. Both types are discussed in this section.


  Directly Derived Types

New types derived directly from existing types are types that point to, refer to, or (in the case of functions) transform type data to return a new type. These types are discussed in the sections that follow.

Arrays of Variables or Objects

Arrays of variables or objects can contain a specified number of a particular type. For example, an array derived from integers is an array of type int. The following code sample declares and defines an array of 10 int variables and an array of 5 objects of class SampleClass:

int         ArrayOfInt[10];
SampleClass aSampleClass[5];

Functions

Functions take zero or more arguments of given types and return objects of a specified type (or return nothing, if the function has a void return type).

Pointers of a Given Type

Pointers to variables or objects select an object in memory. The object can be global, local (or stack-frame), or dynamically allocated. Pointers to functions of a given type allow a program to defer selection of the function used on a particular object or objects until run time. The following example shows a definition of a pointer to a variable of type char:

char *szPathStr;

References to Objects

References to objects provide a convenient way to access objects by reference but use the same syntax required to access objects by value. The following example demonstrates how to use references as arguments to functions and as return types of functions:

BigClassType &func( BigClassType &objname )
{
    objname.DoSomething();    // Note that member-of operator(.)
                              //  is used.
    objname.SomeData = 7;     // Data passed by non-const
                              //  reference is modifiable.
    return objname;
}

The important points about passing objects to a function by reference are:

•	The syntax for accessing members of class, struct, and union objects is the same as if they were passed by value: the member-of operator (.).

•	The objects are not copied prior to the function call; their addresses are passed. This can reduce the overhead of the function call.

Additionally, functions that return a reference need only accept the address of the object to which they refer, instead of a copy of the whole object.

Although the preceding example describes references only in the context of communication with functions, references are not constrained to this use. Consider, for example, a case where a function needs to be an l-value — a common requirement for overloaded operators:

class Vector
{
public:
    Point &operator[]( int nSubscript ); // Function returns a
                                         //  reference type
    ...
};

The preceding declaration specifies a user-defined subscript operator for class Vector. In an assignment statement, two possible conditions occur:

Vector v1;
int    i;
Point p;
v1[7] = p;   // Vector used as an l-value
p = v1[7];   // Vector used as an r-value

The latter case, where v1[7] is used as an r-value, can be implemented without use of references. However, the former case, where v1[7] is used as an l-value, cannot be implemented easily without functions that are of reference type. Conceptually, the last two statements in the preceding example translate to the following code:

v1.operator[]( 7 ) = 3;    // Vector used as an l-value
i = v1.operator[]( 7 );    // Vector used as an r-value

When viewed in this way, it is easier to see that the first statement must be an l-value to be semantically correct on the left side of the assignment statement.

For more information about overloading, and about overloaded operators in particular, see »Overloaded Operators« in Chapter 12.

Another use for references is in declaring a const reference to a variable or object. A reference declared as const retains the efficiency of passing an argument by reference, while preventing the called function from modifying the original object. Consider the following code:

// IntValue is a const reference.
void PrintInt( const int &IntValue )
{
    printf( "%d\n", IntValue );
}

Reference initialization is different from assignment to a variable of reference type. Consider the following code:

int i = 7;
int j = 5;

// Reference initialization
int &ri = i;  // Initialize ri to refer to i.
int &rj = j;  // Initialize rj to refer to j.

// Assignment
ri = 3;       // i now equal to 3.
rj = 12;      // j now equal to 12.
ri = rj;      // i now equals j (12).

Constants

See »Literals« in Chapter 1 for more information about the various kinds of constants allowed in C++.

Pointers to Class Members

These pointers define a type that points to a class member of a particular type. Such a pointer can be used by any object of the class type or any object of a type derived from the class type.

Use of pointers to class members enhances the type safety of the C++ language. Several new operators and constructs are used with pointers to members, as shown in Table 2.5.

Table 2.5    Operators and Constructs Used with Pointers to Members

Operator or Construct	Syntax	Use
::*	type::*ptr-name	Declaration of pointer to member. The type specifies the class name, and ptr-name specifies the name of the pointer to member. Pointers to members can be initialized. For example:
		MyType::*pMyType = &MyType::i;
.*	obj-name.*ptr-name	Dereference a pointer to a member using an object or object reference. For example:
		int j = Object.*pMyType;
−>*	obj-ptr−>*ptr-name	Dereference a pointer to a member using a pointer to an object. For example:
		int j = pObject->*pMyType;
Consider this example that defines a class AClass and the derived type pDAT,  which points to the member I1:

#include <iostream.h>

// Define class AClass.
class AClass
{
public:
    int I1;
    Show() { cout << I1 << "\n"; }
};

// Define a derived type pDAT that points to I1 members of
// objects of type AClass.
int AClass::*pDAT = &AClass::I1;

int main()
{
    AClass aClass;             // Define an object of type AClass.
    AClass *paClass = &aClass;  // Define a pointer to that object.

    int i;

    aClass.*pDAT = 7777;      // Assign to aClass::I1 using .* operator.
    aClass.Show();

    i = paClass->*pDAT;       // Dereference a pointer
                              //  using ->* operator.
    cout << i << "\n";

    return 0;
}

The pointer to member pDAT is a new type derived from class AClass. It is more strongly typed than a "plain" pointer to int because it points only to int members of class AClass (in this case, I1). Pointers to static members are plain pointers rather than pointers to class members. Consider the following example:

class HasStaticMember
{
public:
    static int SMember;
};
int HasStaticMember::SMember = 0;

int *pSMember = &HasStaticMember::SMember;

Note that the type of the pointer is "pointer to int," not "pointer to HasStaticMember::int."

Pointers to members can refer to member functions as well as member data. Consider the following code:

#include <stdio.h>

// Declare a base class, A, with a virtual function, Identify.
// (Note that in this context, struct is the same as class.)
struct A
{
    virtual void Identify() = 0; // No definition for class A.
};

// Declare a pointer to the Identify member function.
void (A::*pIdentify)() = &A::Identify;

// Declare class B derived from class A.
struct B : public A
{
    void Identify();
};

// Declare class C derived from class A.
struct C : public A
{
    void Identify();
};

// Define Identify functions for classes B and C.
void B::Identify()
{
    printf( "Identification is B::Identify\n" );
}

void C::Identify()
{
    printf( "Identification is C::Identify\n" );
}

int main()
{
    B  BObject;          // Declare objects of type B
    C  CObject;          //  and type C.
    A *pA;               // Declare pointer to type A.

    pA = &BObject;       // Make pA point to an object of type B.
    (pA->*pIdentify)();  // Call Identify function through pointer
                         //  to member pIdentify.
    pA = &CObject;       // Make pA point to an object of type C.
    (pA->*pIdentify)();  // Call Identify function through pointer
                         //  to member pIdentify.

    return 0;
}

The output from this program is:

Identification is B::Identify
Identification is C::Identify

The function is called through a pointer to type A. However, because the function is a virtual function, the correct function for the object to which pA refers is called.


  Composed Derivative Types

The following sections discuss composed derivative types. Information about aggregate types and initialization of aggregate types can be found in »Initializing Aggregates« in Chapter 7.

Classes

Classes are a composite group of member objects, functions to manipulate these members, and (optionally) access-control specifications to member objects and functions.

By grouping composite groups of objects and functions in classes, C++ allows programmers to create derivative types that define not only data but also the behavior of objects.

Class members default to private access and private inheritance. Classes are covered in »Chapter 8, Classes«; access control is covered in »Chapter 10, Member-Access Control.«

Structures

C++ structures are the same as classes, except that all member data and functions default to public access, and inheritance defaults to public inheritance.

For more information about access control, see »Chapter 10, Member-Access Control.«

Unions

Unions allow programmers to define types capable of containing different kinds of variables in the same memory space. The following code shows how you can use a union to store several different types of variables:

//  Declare a union that can hold data of types char, int, long,
//   float, double, or char *.
union ToPrint
{
    char   chVar;
    int    iVar;
    long   lVar;
    float  fVar;
    double dVar;
    char  *szVar;
};

// Declare an enumerated type that describes what type to print.
enum PrintType { CHAR_T, INT_T, LONG_T,
                 FLOAT_T, DOUBLE_T, STRING_T };

void Print( ToPrint Var, PrintType Type )
{
    switch( Type )
    {
    case CHAR_T:
        printf( "%c", Var.chVar );
        break;
    case INT_T:
        printf( "%d", Var.iVar );
        break;
    case LONG_T:
        printf( "%ld", Var.lVar );
        break;
    case FLOAT_T:
        printf( "%d", Var.fVar );
        break;
    case DOUBLE_T:
        printf( "%f", Var.dVar );
        break;
    case STRING_T:
        printf( "%s", Var.szVar );
        break;
    }
}


  Type Names

Synonyms for both fundamental and derived types can be defined using the typedef keyword. The following code illustrates the use of typedef:

typedef unsigned char BYTE;   // 8-bit unsigned entity.
typedef BYTE *        PBYTE;  // Pointer to BYTE.

BYTE Ch;                      // Declare a variable of type BYTE.
PBYTE pbCh;                   // Declare a pointer to a BYTE
                              //  variable.

The preceding example shows uniform declaration syntax for the fundamental type unsigned char and its derivative type unsigned char *. The typedef construct is also helpful in simplifying declarations. A typedef declaration defines a synonym, not a new independent type. The following example declares a type name (PVFN) representing a pointer to a function that returns type void. The advantage of this declaration is that, later in the program, an array of these pointers is declared very simply.

// Prototype two functions.
void func1();
void func2();

//  Define PVFN to represent a pointer to a function that
//   returns type void.
typedef void (*PVFN)();

...

// Declare an array of pointers to functions.
PVFN pvfn[] = { func1, func2 };

// Invoke one of the functions.
(*pvfn[1])();


  2.8  L-Values and R-Values

Expressions in C++ can evaluate to "l-values" or "r-values." L-values are expressions that evaluate to a type other than void and that designate a variable.

L-values appear on the left side of an assignment statement (hence the "l" in
l-value). Variables that would normally be l-values can be made nonmodifiable by using the const keyword; these cannot appear on the left of an assignment statement. Reference types are always l-values.

The term r-value is sometimes used to describe the value of an expression and to distinguish it from an l-value. All l-values are r-values but not all r-values are
l-values.

Some examples of correct and incorrect usages are:

i = 7;            // Correct. A variable name, i, is an l-value.
7 = i;            // Error. A constant, 7, is an r-value.
j * 4 = 7;        // Error. The expression j * 4 yields an r-value.
*p = i;           // Correct. A dereferenced pointer is an l-value.
const int ci = 7; // Declare a const variable.
ci = 9;           // ci is a nonmodifiable l-value, so the
                  //  assignment causes an error message to
                  //  be generated.
((i < 3) ? i : j) = 7; // Correct. Conditional operator (? :)
                       //  returns an l-value.

Note  The examples in this section illustrate correct and incorrect usage when operators are not overloaded. By overloading operators, you can make an expression such as j * 4 an l-value.


  2.9  Name Spaces

"Name space" refers to the place the compiler keeps symbols used to refer to various program elements. The place a symbol is kept influences whether two program symbols will conflict. C has two name spaces, but C++ maintains only one name space.

The two C name spaces are:

•	Variable, function, typedef, and enumerator name space

•	Structure, enumeration, and union tag name space

In C++, all these names share a single name space. However, some names can be reused in a scope. In particular, a class can use the same name as an object or function.


  2.10  Numerical Limits

The two standard include files, LIMITS.H and FLOAT.H, define the "numerical limits," or minimum and maximum values, a variable of a given type can hold. These minimums and maximums are guaranteed to be portable to any C++ compiler that uses the same data representation as ANSI C. The LIMITS.H include file defines the numerical limits for integral types, and FLOAT.H defines the numeric limits for floating types.


Integer Limits
  Integer Limits (Microsoft Specific)

The limits for integer types are listed in Table 2.6 (for 16-bit targets) and Table 2.7 (for 32-bit targets). These limits are also defined in the standard header file LIMITS.H.

Table 2.6    Limits on Integer Constants (16-Bit Specific)

Constant	Meaning	Value
CHAR_BIT	Number of bits in the smallest variable that is not a bit field.	8
SCHAR_MIN	Minimum value for a variable of type signed char.	−127
SCHAR_MAX	Maximum value for a variable of type signed char.	127
UCHAR_MAX	Maximum value for a variable of type unsigned char.	255 (0xff)
CHAR_MIN	Minimum value for a variable of type char.	−127; 0 if /J option used
CHAR_MAX	Maximum value for a variable of type char.	127; 255 if /J option used
MB_LEN_MAX	Maximum number of bytes in a multicharacter constant.	2
SHRT_MIN	Minimum value for a variable of type short.	−32767
SHRT_MAX	Maximum value for a variable of type short.	32767
USHRT_MAX	Maximum value for a variable of type unsigned short.	65535 (0xffff)
INT_MIN	Minimum value for a variable of type int.	−32767
INT_MAX	Maximum value for a variable of type int.	32767
UINT_MAX	Maximum value for a variable of type unsigned int.	65535 (0xffff)
LONG_MIN	Minimum value for a variable of type long.	−2147483647
LONG_MAX	Maximum value for a variable of type long.	2147483647
ULONG_MAX	Maximum value for a variable of type unsigned long.	4294967295 (0xffffffff)
Table 2.7    Limits on Integer Constants (32-Bit Specific)

Constant	Meaning	Value
CHAR_BIT	Number of bits in the smallest variable that is not a bit field.	8
SCHAR_MIN	Minimum value for a variable of type signed char.	−128
SCHAR_MAX	Maximum value for a variable of type signed char.	127
UCHAR_MAX	Maximum value for a variable of type unsigned char.	255 (0xff)
CHAR_MIN	Minimum value for a variable of type char.	−128; 0 if /J option used
CHAR_MAX	Maximum value for a variable of type char.	127; 255 if /J option used
MB_LEN_MAX	Maximum number of bytes in a multicharacter constant.	2
SHRT_MIN	Minimum value for a variable of type short.	−32768
SHRT_MAX	Maximum value for a variable of type short.	32767
USHRT_MAX	Maximum value for a variable of type unsigned short.	65535 (0xffff)
INT_MIN	Minimum value for a variable of type int.	−2147483647 − 1
INT_MAX	Maximum value for a variable of type int.	2147483647
UINT_MAX	Maximum value for a variable of type unsigned int.	4294967295 (0xffffffff)
LONG_MIN	Minimum value for a variable of type long.	−2147483647 − 1
LONG_MAX	Maximum value for a variable of type long.	2147483647
ULONG_MAX	Maximum value for a variable of type unsigned long.	4294967295 (0xffffffff)
If a value exceeds the largest integer representation, the Microsoft compiler generates an error.


Floating Limits
  Floating Limits (Microsoft Specific)

Limits on the values of floating-point constants are given in Table 2.8 (for 16-bit targets) and Table 2.9 (for 32-bit targets). The header file FLOAT.H that the setup program installs contains this information.

Table 2.8    Limits on Floating-Point Constants (16-Bit Specific)

Constant	Meaning	Value
FLT_DIG DBL_DIG LDBL_DIG	Number of digits, q, such that a floating-point number with q decimal digits can be rounded into a floating-point representation and back without loss of precision.	6 15 18
FLT_EPSILON DBL_EPSILON LDBL_EPSILON	Smallest positive number x, such that x + 1.0 is not equal to 1.0	1.192092896e−07F 2.2204460492503131e−016 1.0842022172485504434e−019L
FLT_GUARD		0
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG	Number of digits in the radix specified by FLT_RADIX in the floating-point significand. The radix is 2; hence these values specify bits.	24 53 64
FLT_MAX DBL_MAX LDBL_MAX	Maximum representable floating-point number.	3.402823466e+38F 1.7976931348623158e+308 1.189731495357231765e+4932L
FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP	Maximum integer such that 10 raised to that number is a representable floating-point number.	38 308 4932
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP	Maximum integer such that FLT_RADIX raised to that number is a representable floating-point number.	128 1024 16384
FLT_MIN DBL_MIN LDBL_MIN	Minimum positive value.	1.175494351e−38F 2.2250738585072014e−308 3.3621031431120935063e−4932L
FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP	Minimum negative integer such that 10 raised to that number is a representable floating-point number.	−37 −307 −4931
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP	Minimum negative integer such that FLT_RADIX raised to that number is a representable floating-point number.	−125 −1021 −16381
FLT_NORMALIZE		0
FLT_RADIX _DBL_RADIX _LDBL_RADIX	Radix of exponent representation.	2 2 2
FLT_ROUNDS _DBL_ROUNDS _LDBL_ROUNDS	Rounding mode for floating-point addition.	1  (near) 1  (near) 1  (near)
Table 2.9    Limits on Floating-Point Constants (32-Bit Specific)

Constant	Meaning	Value
FLT_DIG DBL_DIG LDBL_DIG	Number of digits, q, such that a floating-point number with q decimal digits can be rounded into a floating-point representation and back without loss of precision.	6 15 15
FLT_EPSILON DBL_EPSILON LDBL_EPSILON	Smallest positive number x, such that x + 1.0 is not equal to 1.0.	1.192092896e−07F 2.2204460492503131e−016 2.2204460492503131e−016
FLT_GUARD		0
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG	Number of digits in the radix specified by FLT_RADIX in the floating-point significand. The radix is 2; hence these values specify bits.	24 53 53
FLT_MAX DBL_MAX LDBL_MAX	Maximum representable floating-point number.	3.402823466e+38F 1.7976931348623158e+308 1.7976931348623158e+308
FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP	Maximum integer such that 10 raised to that number is a representable floating-point number.	38 308 308
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP	Maximum integer such that FLT_RADIX raised to that number is a representable floating-point number.	128 1024 1024
FLT_MIN DBL_MIN LDBL_MIN	Minimum positive value.	1.175494351e−38F 2.2250738585072014e−308 2.2250738585072014e−308
FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP	Minimum negative integer such that 10 raised to that number is a representable floating-point number.	−37 −307 −307
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP	Minimum negative integer such that FLT_RADIX raised to that number is a representable floating-point number.	−125 −1021 −1021
FLT_NORMALIZE		0
FLT_RADIX _DBL_RADIX _LDBL_RADIX	Radix of exponent representation.	2 2 2
FLT_ROUNDS _DBL_ROUNDS _LDBL_ROUNDS	Rounding mode for floating-point addition.	1  (near) 1  (near) 1  (near)
Note that the information in Tables 2.8 and 2.9 may differ in future versions of the product.


Chapter 3: Standard Conversions
  Chapter 3  Standard Conversions

The C++ language defines conversions between its fundamental types. It also defines conversions for pointer, reference, and pointer-to-member derived types. These conversions are called "standard conversions." (For more information about types, standard types, and derived types, see »Types« in Chapter 2.)

This chapter discusses the following standard conversions:

•	Integral promotions

•	Integral conversions

•	Floating conversions

•	Floating and integral conversions

•	Arithmetic conversions

•	Pointer conversions

•	Reference conversions

•	Pointer-to-member conversions

Note  User-defined types can specify their own conversions. Conversion of user-defined types is covered in »Constructors« and »Conversions« in Chapter 11.

The following code causes conversions (in this example, integral promotions):

long  lnum1, lnum2;
int   inum;

// inum promoted to type long prior to assignment.
lnum1 = inum;

// inum promoted to type long prior to multiplication.
lnum2 = inum * lnum2;

Note  The result of a conversion is an l-value only if it produces a reference type. For example, a user-defined conversion declared as

operator int&()

returns a reference and is an l-value. However, a conversion declared as

operator int()

returns an object and is not an l-value.

|


  3.1  Integral Promotions

Objects of an integral type can be converted to another wider integral type (that is, a type that can represent a larger set of values). This widening type of conversion is called "integral promotion." Integral promotion allows the following to be used in an expression wherever another integral type can be used:

•	Objects, literals, and constants of type char and short int

•	Enumeration types

•	int bit fields

•	Enumerators

C++ promotions are "value-preserving." That is, the value after the promotion is guaranteed to be the same as the value before the promotion. In value-preserving promotions, objects of shorter integral types (such as bit fields or objects of type char) are promoted to type int if int can represent the full range of the original type. If int cannot represent the full range of values, then the object is promoted to type unsigned int. Although this strategy is the same as that used by ANSI C, value-preserving conversions do not preserve the "signedness" of the object.

Value-preserving promotions and promotions that preserve signedness normally produce the same results. However, they can produce different results if the promoted object is one of the following:

•	An operand of  /, %, /=, %=, <, <=, >, or  >=

These operators rely on sign for determining the result. Therefore, value-preserving and sign-preserving promotions produce different results when applied to these operands.

•	The left operand of  >> or  >>=

These operators treat signed and unsigned quantities differently when performing a shift operation. For signed quantities, shifting a quantity right causes the sign bit to be propagated into the vacated bit positions. For unsigned quantities, the vacated bit positions are zero-filled.

•	An argument to an overloaded function or operand of an overloaded operator that depends on the signedness of the type of that operand for argument matching. (See »Overloaded Operators« in Chapter 12 for more about defining overloaded operators.)

Integer promotion rules depend on the target environment. For 16-bit targets, unsigned integers are converted to type long because a long can hold any 16-bit unsigned value. For 32-bit targets, unsigned integers must be converted to unsigned long because a long cannot hold any 32-bit unsigned value.

For example, the expression ( -1L < 1U ) evaluates to 1 (true) on 16-bit targets because the compiler converts both operands to type signed long. In this case, -1L is less than 1L, so the expression is true.

However, for 32-bit targets, the compiler converts -1L and 1U to type unsigned long. The resulting comparison is between -1UL and 1UL. Since -1UL equals 2 (32)  − 1, the expression ( -1L < 1U ) is false (0) for 32-bit targets.


  3.2  Integral Conversions

Integral conversions are performed between integral types. The integral types are char, int, and long (and the short, signed, and unsigned versions of these types).


  Converting Signed to Unsigned

Objects of signed integral types can be converted to corresponding unsigned types. When these conversions occur, the actual bit pattern does not change; however, the interpretation of the data changes. Consider this code:

#include <iostream.h>

int main()
{
    short  i = -3;
    unsigned short u;

    cout << (u = i) << "\n";

    return 0;
}

The following output results:

65533

In the preceding example, a signed short, i, is defined and initialized to a negative number. The expression (u = i) causes i to be converted to an unsigned short prior to the assignment to u.


  Converting Unsigned to Signed

Objects of unsigned integral types can be converted to corresponding signed types. However, such a conversion can cause misinterpretation of data if the value of the unsigned object is outside the range representable by the signed type, as demonstrated in the following example:

#include <iostream.h>

void main()
{
 short  i;
 unsigned short u = 65533;

 cout << (i = u) << "\n";
}

The following output results:

-3

In the preceding example, u is an unsigned short integral object that must be converted to a signed quantity to evaluate the expression (i = u). Because its value cannot be properly represented in a signed short, the data is misinterpreted as shown.


  Standard Conversion

Objects of integral types can be converted to shorter signed or unsigned integral types. However, this can result in loss of data if the value of the original object is outside the range representable by the shorter type. Such a conversion is called "standard conversion."

Note  The compiler issues a high-level warning when a conversion to a shorter type takes place.


  3.3  Floating Conversions

An object of a floating type can be safely converted to a more precise floating type — that is, the conversion causes no loss of significance. For example, conversions from float to double or from double to long double are safe, and the value is unchanged.

An object of a floating type can also be converted to a less precise type, if it is in a range representable by that type. (See »Floating Limits« in Chapter 2 for the ranges of floating types.) If the original value cannot be represented precisely, it can be converted to either the next higher or the next lower representable value. If no such value exists, the result is undefined. Consider the following example:

cout << (float)1E300 << endl;

The maximum value representable by type float is 3.402823466E38 — a much smaller number than 1E300. Therefore, the number is converted to infinity, and the result is 1.#INF.


  3.4  Floating and Integral Conversions

Certain expressions can cause objects of floating type to be converted to integral types, or vice versa.


  Floating to Integral

When an object of floating type is converted to an integral type, the fractional part is truncated. No rounding takes place in the conversion process. Truncation means that a number like 1.3 is converted to 1, and −1.3 is converted to −1.


  Integral to Floating

When an object of integral type is converted to a floating type and the original value cannot be represented exactly, the result is either the next higher or the next lower representable value.


  3.5  Arithmetic Conversions

Many binary operators (discussed in »Expressions with Binary Operators« in Chapter 4) cause conversions of operands and yield results the same way. The way these operators cause conversions is called "usual arithmetic conversions." Arithmetic conversions of operands of different types are performed as shown in Table 3.1.

Table 3.1    Conditions for Type Conversion

Conditions Met	Conversion
Either operand is of type long double.	Other operand is converted to type long double.
Preceding condition not met and either operand is of type double.	Other operand is converted to type double.
Preceding conditions not met and either operand is of type float.	Other operand is converted to type float.
Preceding conditions not met (none of the operands are of floating types).	Integral promotions are performed on the operands as follows: • If either operand is of type unsigned long, the other operand is converted to type unsigned long. • If preceding condition not met, and if either operand is of type long and the other of type unsigned int, the operand of type unsigned int is converted to type long (in 16-bit compilations) or both operands are converted to type unsigned long (in 32-bit compilations). • If the preceding two conditions are not met, and if either operand is of type long, the other operand is converted to type long. • If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int. • If none of the preceding conditions are met, both operands are converted to type int.
The following code illustrates the conversion rules described in Table 3.1:

float   fVal;
double  dVal;
int   iVal;
unsigned long ulVal;

dVal = iVal * ulVal; // iVal converted to unsigned long;
                     // result of multiplication converted to double.

dVal = ulVal + fVal; // ulVal converted to float;
                     // result of addition converted to double.

The first statement in the preceding example shows multiplication of two integral types, iVal and ulVal. The condition met is that neither operand is of floating type and one operand is of type unsigned int. Therefore, the other operand, iVal, is converted to type unsigned int. The result is assigned to dVal. The condition met is that one operand is of type double; therefore, the unsigned int result of the multiplication is converted to type double.

The second statement in the preceding example shows addition of a float and an integral type, fVal and ulVal. The ulVal variable is converted to type float (third condition in Table 3.1). The result of the addition is converted to type double (second condition in Table 3.1) and assigned to dVal.


  3.6  Pointer Conversions

Pointers can be converted during assignment, initialization, comparison, and other expressions. These conversions are described in the following sections.


  Null Pointers

An integral constant expression that evaluates to zero, or such an expression cast to type void *, is converted to a pointer called the "null pointer." This pointer is guaranteed to compare unequal to a pointer to any valid object or function (except for pointers to based objects, which can have the same offset and still point to different objects).


  Pointers to Type void

Pointers to type void can be converted to pointers to any other type, but only with an explicit type cast (unlike in C). (See »Expressions with Explicit Type Conversions« in Chapter 4 for more information about type casts.) A pointer to any type can be converted implicitly to a pointer to type void.

A pointer to an incomplete object of a type can be converted to a pointer to void (implicitly) and back (explicitly). The result of such a conversion is equal to the value of the original pointer. An incomplete object is an object that is declared, but for which insufficient information is available to determine its size or base class.


  Pointers to Objects

A pointer to any object that is not const or volatile can be implicitly converted to a pointer of type void *.


  Pointers to Functions

A pointer to a function can be converted to type void *, if type void * is large enough to hold that pointer.

Microsoft Specific

In medium-model 16-bit target compilations, the data pointer size is 2 bytes, and the code pointer size is 4 bytes. Therefore, a pointer to type void is too small to hold a pointer to a function. ♦


  Pointers to Classes

There are two cases in which a pointer to a class can be converted to a pointer to a base class.

The first case is when the specified base class is accessible and the conversion is unambiguous. (See »Multiple Base Classes« in Chapter 9 for more information about ambiguous base-class references.)

Whether a base class is accessible depends on the kind of inheritance used in derivation. Consider the inheritance situation illustrated in »Figure 3.1.«

Table 3.2 shows the base-class accessibility for the situation illustrated in »Figure 3.1.«

Table 3.2    Base-Class Accessibility

Type of Function	Derivation	Conversion from B* to A* Legal?
External (not class-scoped) function	Private	No
	Protected	No
	Public	Yes
B member function (in B scope)	Private	Yes
	Protected	Yes
	Public	Yes
C member function (in C scope)	Private	No
	Protected	Yes
	Public	Yes
The second case in which a pointer to a class can be converted to a pointer to a base class is when you use an explicit type conversion. (See »Expressions with Explicit Type Conversions« in Chapter 4 for more information about explicit type conversions.)

The result of such a conversion is a pointer to the "subobject," the portion of the object that is completely described by the base class.

The following code defines two classes, A and B, where B is derived from A. (For more information on inheritance, see »Chapter 9, Derived Classes.«) It then defines bObject, an object of type B, and two pointers (pA and pB) that point to the object.

class A
{
public:
    int AComponent;
    int AMemberFunc();
};

class B : public A
{
public:
    int BComponent;
    int BMemberFunc();
};
B bObject;
A *pA = &bObject;
B *pB = &bObject;

pA->AMemberFunc();   // OK in class A
pB->AMemberFunc();   // OK: inherited from class A
pA->BMemberFunc();   // Error: not in class A

The pointer pA is of type A *, which can be interpreted as meaning "pointer to an object of type A." Members of bObject (such as BComponent and BMemberFunc) are unique to type B and are therefore inaccessible through pA. The pA pointer allows access only to those characteristics (member functions and data) of the object that are defined in class A.


  Expressions

Any expression with an array type can be converted to a pointer of the same type. The result of the conversion is a pointer to the first array element. The following example demonstrates such a conversion:

char szPath[_MAX_PATH]; // Array of type char.
char *pszPath = szPath; // Equals &szPath[0].

An expression that results in a function returning a particular type is converted to a pointer to a function returning that type, except when:

•	The expression is used as an operand to the address-of operator (&).

•	The expression is used as an operand to the function-call operator.


Pointers Modified by Microsoft Keywords
  Pointers Modified by Microsoft-Specific Keywords

The 16-bit specific keywords __near, __far, and __huge, and the __based keyword, which has limited functionality in 32-bit targets, modify types to specify the addressing desired. The following standard conversions between pointers modified by these keywords are performed (provided the types obey the conversion rules discussed elsewhere in this chapter):

•	A near pointer can be promoted to a far pointer.

•	Any pointer can be converted to a huge pointer by first converting the pointer to a far pointer and then converting it to a huge pointer.

•	A huge pointer can be converted to a far pointer. Because far addressing has different implications than huge addressing, the compiler issues a warning.

•	A pointer based on a near address can be converted to a near pointer.

•	A pointer based on any segment other than void can be converted to a far pointer.

Microsoft C++ supplies no standard conversions to any form of based pointer or from any form of address that contains or implies segment information (far, huge, or based) to a near pointer.

C++ does not supply a standard conversion from a const or volatile type to a type that is not const or volatile. However, any sort of conversion can be specified using explicit type casts (including conversions that are unsafe).

Note  C++ pointers to members, with the exception of pointers to static members, are different from normal pointers and do not have the same standard conversions. Pointers to static members are normal pointers and have the same conversions as normal pointers. (See »Pointers to Class Members« in Chapter 2 for more information.)


  3.7  Reference Conversions

A reference to a class can be converted to a reference to a base class in the following cases:

•	The specified base class is accessible (as defined in »Pointers to Classes«).

•	The conversion is unambiguous. (See »Multiple Base Classes« in Chapter 9 for more information about ambiguous base-class references.)

The result of the conversion is a pointer to the subobject that represents the base class.

For more information about references, see »References to Objects« in Chapter 2.


  3.8  Pointer-to-Member Conversions

Pointers to class members can be converted during assignment, initialization, comparison, and other expressions. These conversions are discussed in the next two sections.


  Integral Constant Expressions

An integral constant expression that evaluates to zero is converted to a pointer called the "null pointer." This pointer is guaranteed to compare unequal to a pointer to any valid object or function (except for pointers to based objects, which can have the same offset and still point to different objects).

The following code illustrates the definition of a pointer to member i in class A. The pointer, pai, is initialized to 0, which is the null pointer.

class A
{
public:
 int i;
};

int A::*pai = 0;


  Pointers to Base-Class Members

A pointer to a member of a base class can be converted to a pointer to a member of a class derived from it, when the following conditions are met:

•	The inverse conversion, from pointer to derived class to base-class pointer, is accessible.

•	The derived class does not inherit virtually from the base class.

When the left operand is a pointer to member, the right operand must be of pointer-to-member type or be a constant expression that evaluates to 0. This assignment is valid only in the following cases:

•	The right operand is a pointer to a member of the same class as the left operand.

•	The left operand is a pointer to a member of a class derived publicly and unambiguously from the class of the right operand.


Chapter 4: Expressions
  Chapter 4  Expressions

This chapter describes C++ expressions. Expressions are sequences of operators and operands that are used for one or more of these purposes:

•	Computing a value from the operands.

•	Designating objects or functions.

•	Generating "side effects." (Side effects are any actions other than the evaluation of the expression — for example, modifying the value of an object.)

In C++, operators can be overloaded and their meanings can be user-defined. However, their precedence and the number of operands they take cannot be modified. This chapter describes the syntax and semantics of operators as they are supplied with the language, not overloaded. (For more information about overloaded operators, see »Overloaded Operators« in Chapter 12.)

Note  Operators for built-in types cannot be overloaded; their behavior is predefined.


  4.1  Types of Expressions

C++ expressions are divided into several categories:

•	Primary expressions. These are the building blocks from which all other expressions are formed. (See »Primary Expressions«.)

•	Postfix expressions. These are primary expressions followed by an operator — for example, the array subscript or postfix increment operator. (See »Postfix Expressions«.)

•	Expressions formed with unary operators. Unary operators act on only one operand in an expression. (See »Expressions with Unary Operators«.)

•	Expressions formed with binary operators. Binary operators act on two operands in an expression. (See »Expressions with Binary Operators«.)

•	Expressions formed with the conditional operator. The conditional operator is a ternary operator — the only such operator in the C++ language — and takes three operands. (See »Expressions with the Conditional Operator«.)

•	Constant expressions. Constant expressions are formed entirely of constant data. (See »Constant Expressions«.)

•	Expressions with explicit type conversions. Explicit type conversions, or "casts," can be used in expressions. (See »Expressions with Explicit Type Conversions«.)

•	Expressions with pointer-to-member operators. (See »Expressions with Pointer-to-Member Operators«.)


  Primary Expressions

Primary expressions are the building blocks of more complex expressions. They are literals, names, and names qualified by the scope-resolution operator (::).

Syntax

primary-expression:
literal
this
::  identifier
::  operator-function-name
::  qualified-name
(  expression  )
name

A literal is a constant primary expression. Its type depends on the form of its specification. See »Literals« in Chapter 1 for complete information about specifying literals.

The this keyword is a pointer to a class object. It is available within nonstatic member functions and points to the instance of the class for which the function was invoked. The this keyword cannot be used outside the body of a class-member function.

The type of the this pointer is type *const (where type is the class name) within functions not specifically modifying the this pointer. The following example shows member function declarations and the types of this:

class Example
{
public:
    void Func();          //  * const this
    void Func() const;    //  const * const this
    void Func() volatile; //  volatile * const this
};

See »Type of this Pointer« in Chapter 8 for more information about modifying the type of the this pointer.

Microsoft Specific

The this pointer has an associated addressing model — from the compilation options, the "ambient data model" of the class, or one that is explicitly specified in the declaration of an object of class type. Therefore, the this pointer can be a near, far, or huge pointer. For more information about addressing models as they affect classes, see »Memory-Model Modifiers and Member Functions« in Appendix B. ♦

The scope-resolution operator (::) followed by an identifier, operator-function-name, or qualified-name constitutes a primary expression. The type of this expression is determined by the declaration of the identifier, operator-function-name, or name. It is an l-value if the declaring name is an l-value. The scope-resolution operator allows a global name to be referred to, even if that name is hidden in the current scope. See »Scope« in Chapter 2 for an example of how to use the scope-resolution operator.

An expression enclosed in parentheses is a primary expression whose type and value are identical to those of the unparenthesized expression. It is an l-value if the unparenthesized expression is an l-value.


  Names

In the C++ syntax for primary-expression, a name is a primary expression that can appear only after the member-selection operators (. or −>), and names the member of a class.

Syntax

name:
identifier
operator-function-name
conversion-function-name
~ class-name
qualified-name

Any identifier that has been declared is a name.

An operator-function-name is a name that is declared in the form

operator operator-name( argument1 [ , argument2] );

See »Overloaded Operators« in Chapter 12 for more information about declaration of operator-function-name.

A conversion-function-name is a name that is declared in the form

operator type-name( )

Note  You can supply a derivative type name such as char * in place of the type-name when declaring a conversion function.

Conversion functions supply conversions to and from user-defined types. For more information about user-supplied conversions, see »Conversion Functions« in Chapter 11.

A name declared as ~ class-name is taken as the "destructor" for objects of a class type. Destructors typically perform cleanup operations at the end of an object's lifetime. Destructors are discussed in depth in »Destructors« in Chapter 11.


  Qualified Names

Syntax

qualified-name:
qualified-class-name  ::  name

If a qualified-class-name is followed by the scope-resolution operator (::) and then the name of a member of either that class or a base of that class, then the scope-resolution operator is considered a qualified-name. The type of a qualified-name is the same as the type of the member, and the result of a qualified-name expression is the member. If the member is an l-value, then the qualified-name is also an l-value. For information about declaring qualified-class-name, see »Type Specifiers« in Chapter 6 or »Class Names« in Chapter 8.

The class-name part of a qualified-class-name can be hidden by redeclaration of the same name in the current or enclosing scope; the class-name is still found and used. See »Scope« in Chapter 2 for an example of how to use a qualified-class-name to access a hidden class-name.

Note  Class constructors and destructors of the form class-name :: class-name and class-name :: ~ class-name, respectively, must refer to the same class-name.

A name with more than one qualification, such as the following, designates a member of a nested class:

class-name :: class-name :: name


  Postfix Expressions

Postfix expressions consist of primary expressions or expressions in which postfix operators (see Table 4.1) follow a primary expression.

Table 4.1    Postfix Operators

Operator Name	Operator Notation
Subscript operator	[ ]
Function-call operator	( )
Explicit type conversion operator	type-name( )
Member-selection operator	. or −>
Postfix increment operator	++
Postfix decrement operator	−−
Syntax

postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-list (opt)  )
simple-type-name ( expression-list (opt)  )
postfix-expression . name
postfix-expression −> name
postfix-expression ++
postfix-expression −−

expression-list:
assignment-expression
expression-list , assignment-expression


  Subscript Operator

A postfix-expression followed by the subscript operator, [ ], specifies array indexing. One of the expressions must be of pointer or array type — that is, it must have been declared as type* or type[ ]. The other expression must be of an integral type (including enumerated types). In common usage, the expression enclosed in the brackets is the one of integral type, but that is not strictly required. Consider the following example:

MyType m[10];     // Declare an array of a user-defined type.

MyType n1 = m[2]; // Select third element of array.
MyType n2 = 2[m]; // Select third element of array.

In the example above, the expression m[2] is identical to 2[m]. Although m is not of an integral type, the effect is the same. The reason that m[2] is equivalent to 2[m] is that the result of a subscript expression e1[ e2 ] is given by:

*( (e2) + (e1) )

The address yielded by the above expression is not e2 bytes from the address e1. Rather, the address is scaled to yield the next object in the array e2. For example:

#include <iostream.h>

int main()
{
    double aDbl[2];

    cout << "Address of first element is: "
         << &aDbl[0] << "\n";
    cout << "Address of second element is: "
         << &aDbl[1] << "\n";

    return 0;
}

The preceding program prints two addresses that are 8 bytes apart — the size of an object of type double. This scaling according to object type is done automatically by the C++ language and is defined in »Additive Operators«, where addition and subtraction of operands of pointer type is discussed.

Positive and Negative Subscripts

The first element of an array is element 0. The range of a C++ array is from array[0] to array[size − 1]. However, C++ supports positive and negative subscripts. Negative subscripts must fall within array boundaries or results are unpredictable. The following code illustrates this concept:

#include <iostream.h>

main()
{
    int iNumberArray[1024];
    int *iNumberLine = &iNumberArray[512];

    cout << iNumberArray[-256] << "\n";  	// Unpredictable
    cout << iNumberLine[-256] << "\n";	// OK

    return 0;
}

The negative subscript in iNumberArray can produce a run-time error because it yields an address 256 bytes lower in memory than the actual origin of the array. The object iNumberLine is initialized to the middle of iNumberArray; it is therefore possible to use both positive and negative array indexes on it. Array subscript errors do not generate compile-time errors, but they yield unpredictable results.

The subscript operator is commutative. Therefore, the expressions array[index] and index[array] are guaranteed to be equivalent as long as the subscript operator is not overloaded (see »Overloaded Operators« in Chapter 12). The first form is the most common coding practice, but either works.


  Function-Call Operator

A postfix-expression followed by the function-call operator, ( ), specifies a function call. The arguments to the function-call operator are zero or more expressions separated by commas — the actual arguments to the function.

The postfix-expression must be of one of these types:

•	Function returning type T. An example declaration is

T func( int i )

•	Pointer to a function returning type T. An example declaration is

T (*func)( int i )

•	Reference to a function returning type T. An example declaration is

T (&func)(int i)

•	Pointer-to-member function dereference returning type T. Example function calls are

(pObject->*pmf)();
(Object.*pmf)();

Formal and Actual Arguments

Calling programs pass information to called functions in "actual arguments." The called functions access the information using corresponding "formal arguments."

When a function is called, the following tasks are performed:

•	All actual arguments (those supplied by the caller) are evaluated. There is no implied order in which these arguments are evaluated, but all arguments are evaluated and all side effects completed prior to entry to the function.

•	Each formal argument is initialized with its corresponding actual argument in the expression list. (A formal argument is an argument that is declared in the function header and used in the body of a function.) Conversions are done as if by initialization — both standard and user-defined conversions are performed in converting an actual argument to the correct type. The initialization performed is illustrated conceptually by the following code:

void Func( int i ); // Function prototype
...
Func( 7 );          // Execute function call

The conceptual initializations prior to the call are shown below:

int Temp_i = 7;
Func( Temp_i );

Note that the initialization is performed as if using the equal-sign syntax instead of the parentheses syntax. A copy of i is made prior to passing the value to the function. (For more information, see »Initializers« in Chapter 7 and »Conversions,« »Initialization Using Special Member Functions,« and »Explicit Initialization« in Chapter 11.

Therefore, if the function prototype (declaration) calls for an argument of type long, and if the calling program supplies an actual argument of type int, the actual argument is promoted using a standard type conversion to type long (see »Chapter 3, Standard Conversions«).

It is an error to supply an actual argument for which there is no standard or user-defined conversion to the type of the formal argument.

For actual arguments of class type, the formal argument is initialized by calling the class's constructor. (See »Constructors« in Chapter 11 for more about these special class member functions.)

•	The function call is executed.

The following program fragment demonstrates a function call:

void func( long param1, double param2 );

int main()
{
    int i, j;

    // Call func with actual arguments i and j.
    func( i, j );
    ...
}

// Define func with formal parameters param1 and param2.
void func( long param1, double param2 )
{
    ...
}

When func is called from main, the formal parameter param1 is initialized with the value of i (i is converted to type long to correspond to the correct type using a standard conversion), and the formal parameter param2 is initialized with the value of j (j is converted to type double using a standard conversion).

Treatment of Argument Types

Formal arguments declared as const types cannot be changed within the body of a function. Functions can change any argument that is not of type const. However, the change is local to the function and does not affect the actual argument's value unless the actual argument was a reference to an object not of type const.

The following functions illustrate some of these concepts:

int func1( const int i, int j, char *c )
{
    i = 7;         // Error: i is const.
    j = i;         // OK, but value of j is
                   //  lost at return.
    *c = 'a' + j;  // OK: changes value of c
                   //  in calling function.

    return i;
}

double& func2( double& d, const char *c )
{
    d = 14.387;    // OK: changes value of d
                   //  in calling function.
    *c = 'a';      // Error: c is a pointer to
                   //  a const object.

    return d;
}

Ellipses and Default Arguments

Functions can be declared to accept fewer arguments than specified in the function definition, using one of two methods: ellipsis (...) or default arguments.

Ellipses denote that arguments may be required but that the number and types are not specified in the declaration. This is normally poor C++ programming practice because it defeats one of the benefits of C++: type safety. Different conversions are applied to functions declared with ellipses than to those functions for which the formal and actual argument types are known:

•	If the actual argument is of type float, it is promoted to type double prior to the function call.

•	Any signed or unsigned char, short, enumerated type, or bit field is converted to either a signed or an unsigned int using integral promotion.

•	Any argument of class type is passed by value as a data structure; the copy is created by binary copying instead of by invoking the class's copy constructor (if one exists).

Ellipses, if used, must be declared last in the argument list. For more information about passing a variable number of arguments, see the Run-Time Library Reference, under the topics va_arg, va_list, and va_start.

Default arguments allow the programmer to specify the value an argument should assume if none is supplied in the function call. The following code fragment shows how default arguments work. For more information about restrictions on specifying default arguments, see »Default Arguments« in Chapter 7 .

#include <iostream.h>

// Declare the function print that prints a string,
// then a terminator.
void print( const char *string,
            const char *terminator = "\n" );

int main()
{
    print( "hello," );
    print( "world!" );

    print( "good morning", ", " );
    print( "sunshine." );

    return 0;
}

// Define print.
void print( char *string, char *terminator )
{
    if( string != NULL )
        cout << string;

    if( terminator != NULL )
        cout << terminator;
}

The above program declares a function, print, that takes two arguments. However, the second argument, terminator, has a default value, "\n". In main, the first two calls to print allow the default second argument to supply a new line to terminate the printed string. The third call specifies an explicit value for the second argument. The output from the program is

hello,
world!
good morning, sunshine.

Function-Call Results

A function call evaluates to an r-value unless the function is declared as a reference type. Functions with reference return type evaluate to l-values, and it is legal to use them on the left side of an assignment statement as follows:

#include <iostream.h>

class Point
{
public:
    // Define "accessor" functions as
    // reference types.
    unsigned& x() { return _x; }
    unsigned& y() { return _y; }
private:
    unsigned _x;
    unsigned _y;
};

int main()
{
    Point ThePoint;

    ThePoint.x() = 7;           // Use x() as an l-value.
    unsigned y = ThePoint.y();  // Use y() as an r-value.

    // Use x() and y() as r-values.
    cout << "x = " << ThePoint.x() << "\n"
         << "y = " << ThePoint.y() << "\n";

    return 0;
}

The above code defines a class called Point, which contains private data objects that represent x and y coordinates. These data objects must be modified and their values retrieved. The above program is only one of several designs for such a class; use of the GetX and SetX or GetY and SetY functions is another possible design.

Functions that return class types, pointers to class types, or references to class types can be used as the left operand to member-selection operators. Therefore, the following code is legal:

class A
{
public:
    int SetA( int i ) { return (I = i); }
    int GetA()    { return I; }

private:
    int I;
};

// Declare three functions:
//  func1, which returns type A
//  func2, which returns a pointer to type A
//  func3, which returns a reference to type A
A func1();
A* func2();
A& func3();

int iResult = func1().GetA();
func2()->SetA( 3 );
func3().SetA( 7 );

Functions can be called recursively. For more information about function declarations, see »Function Specifiers« in Chapter 6 and »Member Functions« in Chapter 8. Related material is in »Program and Linkage« in Chapter 2.


  Member-Selection Operator

A postfix-expression followed by the member-selection operator (.) and a name is another example of a postfix-expression. The first operand of the member-selection operator must have class or class reference type, and the second operand must identify a member of that class.

The result of the expression is the value of the member, and it is an l-value if the named member is an l-value.

A postfix-expression followed by the member-selection operator (−>) and a name is a postfix-expression. The first operand of the member-selection operator must have type pointer to a class object (an object declared as class, struct, or union type), and the second operand must identify a member of that class.

The result of the expression is the value of the member, and it is an l-value if the named member is an l-value. The −> operator dereferences the pointer. Therefore, the expressions e−>member and (*e).member (where e represents an expression) yield identical results (except when the operators −> or * are overloaded).

When a value is stored through one member of a union but retrieved through another member, no conversion is performed. The following program stores data into the object U as int but retrieves the data as two separate bytes of type char:

#include <iostream.h>

int main()
{
    struct ch
    {
        char b1;
        char b2;
    };
    union u
    {
        struct ch uch;
        int    i;
    };

    u U;

    U.i = 0x6361;  // Bit pattern for "ac"
    cout << U.uch.b1 << U.uch.b2 << "\n";

    return 0;
}

Note  The preceding code is not portable because it assumes that an int is two bytes long and that a char is one byte long. In 32-bit target compilations, these assumptions are false.


  Postfix Increment and Decrement Operators

C++ provides prefix and postfix increment and decrement operators; this section describes only the postfix increment and decrement operators. (For more information, see »Increment and Decrement Operators«.) The difference between the two is that in the postfix notation, the operator appears after postfix-expression, whereas in the prefix notation, the operator appears before expression. The following example shows a postfix-increment operator:

i++

The effect of applying the postfix increment, or "postincrement," operator (++) is that the operand's value is increased by one unit of the appropriate type. Similarly, the effect of applying the postfix decrement, or "postdecrement," operator (−−) is that the operand's value is decreased by one unit of the appropriate type.

For example, applying the postincrement operator to a pointer to an array of objects of type long actually adds four to the internal representation of the pointer. This behavior causes the pointer, which previously referred to the nth element of the array, to refer to the (n+1)th element.

The operands to postincrement and postdecrement operators must be modifiable (not const) l-values of arithmetic or pointer type. The result of the postincrement or postdecrement expression is the value of the postfix-expression prior to application of the increment operator. The type of the result is the same as that of the postfix-expression, but it is no longer an l-value.

Postincrement and postdecrement, when used on enumerated types, yield integral values. Therefore, the following code is illegal:

enum Days {
    Sunday = 1,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

int main()
{
  Days Today = Tuesday;
  Days SaveToday;

  SaveToday = Today++;  // error

  return 0;
}

The intent of the above code is to save today's day and then move to tomorrow. However, the result is that the expression Today++ yields an int — an error when assigned to an object of the enumerated type Days.


  Expressions with Unary Operators

Unary operators are those operators that act on only one operand in an expression. The unary operators are:

•	Indirection operator (*)

•	Address-of operator (&)

•	Unary plus operator (+)

•	Unary negation operator (−)

•	Logical NOT operator (!)

•	One's complement operator (~)

•	Prefix increment operator (++)

•	Prefix decrement operator (−−)

•	sizeof operator

•	new operator

•	delete operator

These operators have right-to-left associativity.

Syntax

unary-expression:
postfix-expression
++unary-expression
−−unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
allocation-expression
deallocation-expression

unary-operator: one of
* & + − ! ~


  Indirection Operator (*)

The unary indirection operator (*) "dereferences" a pointer; that is, it converts a pointer value to an l-value. The operand of the indirection operator must be a pointer to a type. The result of the indirection expression is the type from which the pointer type is derived. The use of the * operator in this context is different from its meaning as a binary operator, which is multiplication.


  Address-Of Operator (&)

The unary address-of operator (&) takes the address of its operand. The address-of operator can be applied only to the following:

•	Functions (although its use for taking the address of a function is unnecessary)

•	L-values

•	Qualified names

In the first two cases listed above, the result of the expression is a pointer type (an r-value) derived from the type of the operand. For example, if the operand is of type char, the result of the expression is of type pointer to char. The address-of operator, applied to const or volatile objects, evaluates to const type * or volatile type *, where type is the type of the original object.

The result produced by the third case, applying the address-of operator to a qualified-name, depends on whether the qualified-name specifies a static member. If so, the result is a pointer to the type specified in the declaration of the member. If the member is not static, the result is a pointer to the member name of the class indicated by qualified-class-name. (See »Primary Expressions« for more about qualified-class-name.) The following code fragment shows how the result differs, depending on whether the member is static:

class PTM
{
public:
           int   iValue;
    static float fValue;
};

int   PTM::*piValue = &PTM::iValue;  // OK: non-static
float PTM::*pfValue = &PTM::fValue;  // Error: static
float *spfValue     = &PTM::fValue;  // OK

In the above example, the expression &PTM::fValue yields type float * instead of type float PTM::* because fValue is a static member.

The address of an overloaded function can be taken only when it is clear which version of the function is being referred to. See »Address of Overloaded Functions«" in Chapter 12 for information about how to obtain the address of a particular overloaded function.

Applying the address-of operator to a reference type gives the same result as applying the operator to the object to which the reference is bound. The following program demonstrates this concept:

#include <iostream.h>

int main()
{
    double d;        // Define an object of type double.
    double& rd = d;  // Define a reference to the object.

    // Compare the address of the object to the address
    //  of the reference to the object.
    if( &d == &rd )
        cout << "&d equals &rd" << "\n";
    else
        cout << "&d is not equal to &rd" << "\n";

    return 0;
}

The output from the program is always &d equals &rd.


  Unary Plus Operator (+)

The result of the unary plus operator (+) is the value of its operand. The operand to the unary plus operator must be of an arithmetic type.

Integral promotion is performed on integral operands. The resultant type is the type to which the operand is promoted. Thus, the expression +ch, where ch is of type char, results in type int; the value is unmodified.

See »Integral Promotions« in Chapter 3 for more information about how the promotion is done.


Unary Negation Operator ()
  Unary Negation Operator (−)

The unary negation operator (−) produces the negative of its operand. The operand to the unary negation operator must be of an arithmetic type.

Integral promotion is performed on integral operands, and the resultant type is the type to which the operand is promoted. See »Integral Promotions« in Chapter 3 for more information on how the promotion is done.

Microsoft Specific

Unary negation of unsigned quantities is performed by subtracting the value of the operand from 2 (n) , where n is the number of bits in an object of the given unsigned type. (Microsoft C++ runs on processors that utilize two's-complement arithmetic. On other processors, the algorithm for negation can differ.) ♦


  Logical NOT Operator (!)

The result of the logical NOT operator (!) is 0 if its operand evaluates to a nonzero value; the result is 1 only if the operand is equal to 0. The operand must be of arithmetic or pointer type. The result is of type int.

For an expression e, the unary expression !e is equivalent to the expression
(e == 0), except where overloaded operators are involved.


Ones Complement Operator (~)
  One's Complement Operator (~)

The one's complement operator (~), sometimes called the "bitwise complement" operator, yields a bitwise one's complement of its operand. That is, every bit that is set in the operand is 0 in the result. Conversely, every bit that is 0 in the operand is set in the result. The operand to the one's complement operator must be an integral type.

Integral promotion is performed on integral operands, and the resultant type is the type to which the operand is promoted. See »Integral Promotions« in Chapter 3 for more information on how the promotion is done.


Increment and Decrement Operators (++, )
  Increment and Decrement Operators (++, −−)

The prefix increment operator (++), also called the "preincrement" operator, adds one to its operand; this incremented value is the result of the expression. The operand must be an l-value not of type const. The result is an l-value of the same type as the operand.

The prefix decrement operator (−−), also called the "predecrement" operator, is analogous to the preincrement operator, except that the operand is decremented by one and the result is this decremented value.

Both the prefix and postfix increment and decrement operators affect their operands. The key difference between them is when the increment or decrement takes place in the evaluation of an expression. (For more information, see »Postfix Increment and Decrement Operators«.) In the prefix form, the increment or decrement takes place before the value is used in expression evaluation, so the value of the expression is different from the value of the operand. In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand.

Because increment and decrement operators have side effects, using expressions with increment or decrement operators in a macro can have undesirable results (see Chapter 1 of the Preprocessor Reference for more information about macros). Consider this example:

#define max(a,b) ((a)<(b))?(b):(a)

...

int i, j, k;

k = max( ++i, j );

In the code fragment above, the macro expands to:

k = ((++i)<(j))?(j):(++i);

If i is greater than or equal to j, it will be incremented twice.

Note  C++ inline functions are preferable to macros in many cases because they eliminate side effects such as those described above, and they allow the language to perform more complete type checking.


  sizeof Operator

The sizeof operator yields the size of its operand with respect to the size of type char. The result of the sizeof operator is of type size_t, an integral type defined in the include file STDDEF.H. The operand to sizeof can be one of the following:

•	A type name. To use sizeof with a type name, the name must be enclosed in parentheses.

•	An expression. When used with an expression, sizeof can be specified with or without the parentheses. The expression is not evaluated.

When the sizeof operator is applied to an object of type char, it yields 1. When the sizeof operator is applied to an array, it yields the total number of bytes in that array. For example:

#include <iostream.h>

int main()
{
    char szHello[] = "Hello, world!";

    cout << "The size of the type of " << szHello << " is: "
         << sizeof( char ) << "\n";
    cout << "The length of " << szHello << " is: "
         << sizeof szHello << "\n";

    return 0;
}

The program output is:

The size of the type of Hello, world! is: 1
The length of Hello, world! is: 14

When the sizeof operator is applied to a class, struct, or union type, the result is the number of bytes in an object of that class, struct, or union type, plus any padding added to align members on word boundaries. (The /Zp [pack structure members] compiler option and the pack pragma affect alignment boundaries for members.) The sizeof operator never yields 0, even for an empty class.

The sizeof operator cannot be used with the following operands:

•	Functions. (However, sizeof can be applied to pointers to functions.)

•	Bit fields.

•	Undefined classes.

•	The type void.

•	Incomplete types.

•	Parenthesized names of incomplete types.

When the sizeof operator is applied to a reference, the result is the same as if sizeof had been applied to the object itself.

The sizeof operator is often used to calculate the number of elements in an array using an expression of the form:

sizeof array / sizeof array[0]


  new Operator

The new operator attempts to dynamically allocate (at run time) one or more objects of type-name. The new operator cannot be used to allocate a function; however, it can be used to allocate a pointer to a function.

Syntax

allocation-expression:
:: (opt)  new nmodel (opt)  placement (opt)  new-type-name  new-initializer (opt)
:: (opt)  new nmodel (opt)  placement (opt)  ( type-name )  new-initializer (opt)

placement:
( expression-list )

new-type-name:
type-specifier-list new-declarator (opt)

The new operator is used to allocate objects and arrays of objects. The new operator allocates from an area of program memory called the "free store." In C, the free store is often referred to as the "heap."

When new is used to allocate a single object, it yields a pointer to that object; the resultant type is new-type-name * or type-name *. When new is used to allocate a singly dimensioned array of objects, it yields a pointer to the first element of the array, and the resultant type is new-type-name * or type-name *. When new is used to allocate a multidimensional array of objects, it yields a pointer to the first element of the array, and the resultant type preserves the size of all but the leftmost array dimension. For example:

new float[10][25][10]

yields type float (*)[25][10]. Therefore, the following code will not work because it attempts to assign a pointer to an array of float with the dimensions [25][10] to a pointer to type float:

float *fp;
fp = new float[10][25][10];

The correct expression is:

float (*cp)[25][10];
cp = new float[10][25][10];

The definition of cp allocates a pointer to an array of type float with dimensions [25][10] — it does not allocate an array of pointers.

All array dimensions but the leftmost must be constant expressions that evaluate to positive values; the leftmost array dimension can be any expression that evaluates to a positive value. When allocating an array using the new operator, the first dimension can be zero — the new operator returns a unique pointer.

The type-specifier-list cannot contain const, volatile, class declarations, or enumeration declarations. Therefore, the following expression is illegal:

volatile char *vch = new volatile char[20];

The new operator does not allocate reference types because they are not objects.

Lifetime of Objects Allocated with new

Objects allocated with the new operator are not destroyed when the scope in which they are defined is exited. Because the new operator returns a pointer to the objects it allocates, the program must define a pointer with suitable scope to access those objects. For example:

int main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
        ...
    }

    delete AnotherArray; // Error: pointer out of scope.
    delete AnArray;      // OK: pointer still in scope.
}

Once the pointer AnotherArray goes out of scope in the example above, the object can no longer be deleted.

Initializing Objects Allocated with new

An optional new-initializer field is included in the syntax for the new operator. This allows new objects to be initialized with user-defined constructors. For more information about how initialization is done, see »Initializers« in Chapter 7.

The following example illustrates how to use an initialization expression with the new operator:

#include <iostream.h>

class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

int main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double ( 43.0 );

    ...

    return 0;
}

In the example above, the object CheckingAcct is allocated using the new operator, but no default initialization is specified. Therefore, the default constructor for the class, Acct(), is called. Then the object SavingsAcct is allocated the same way, except that it is explicitly initialized to 34.98. Because 34.98 is of type double, the constructor that takes an argument of that type is called to handle the initialization. Finally, the nonclass type HowMuch is initialized to 43.0.

If an object is of a class type and that class has constructors (as in the above example), the object can be initialized by the new operator only if one of these conditions is met:

•	The arguments provided in the initializer agree with those of a constructor.

•	The class has a default constructor (a constructor that can be called with no arguments).

Access control and ambiguity control are performed on operator new and on the constructors according to the rules set forth in »Ambiguity« in Chapter 9 and »Initialization Using Special Member Functions« in Chapter 11.

No explicit per-element initialization can be done when allocating arrays using the new operator; only the default constructor, if present, is called. See »Default Arguments« in Chapter 7 for more information.

If the memory allocation fails (operator new returns a value of 0), no initialization is performed. This protects against attempts to initialize data that does not exist.

As with function calls, the order of evaluation of initialization expressions is not defined. Furthermore, it is unsafe to rely on these expressions being completely evaluated before the memory allocation is performed. If the memory allocation fails and the new operator returns zero, it is possible that not all expressions in the initializer are completely evaluated.

How new Works

The allocation-expression — the expression containing the new operator — does three things:

•	Locates and reserves storage for the object or objects to be allocated. When this stage is complete, the correct amount of storage is allocated, but it is not yet an object.

•	Initializes the object(s). Once initialization is complete, enough information is present for the allocated storage to be an object.

•	Returns a pointer to the object(s) of a pointer type derived from new-type-name or type-name. This pointer is used by the program to access the newly allocated object.

The new operator actually invokes the function operator new. For arrays of any type, and for objects that are not of class, struct, or union types, a global function, ::operator new, is called to allocate storage. Class-type objects can define their own operator new static member function on a per-class basis.

When the compiler encounters the new operator to allocate an object of type type, it issues a call to type::operator new( sizeof( type ) ) or, if no user-defined operator new is defined, ::operator new( sizeof( type ) ). Therefore, the new operator can allocate the correct amount of memory for the object.

Note  The argument to operator new is of type size_t. This type is defined in DIRECT.H, MALLOC.H, MEMORY.H, SEARCH.H, STDDEF.H, STDIO.H, STDLIB.H, STRING.H, and TIME.H.

An option in the syntax allows specification of placement (see Syntax for »new Operator«). The placement parameters can be used only for user-defined implementations of operator new; it allows extra information to be passed to operator new. An expression with a placement field such as

T *TObject = new ( 0x0040 ) T;

is translated to

T *TObject = T::operator new( sizeof( T ), 0x0040 );

The original intention of the placement field was to allow hardware-dependent objects to be allocated at user-specified addresses.

Note  Although the example above shows only one argument in the placement field, there is no restriction on how many extra arguments can be passed to operator new this way.

Even when operator new has been defined for a class type, the global operator can be used by using the form of this example:

T *TObject =::new TObject;

The scope-resolution operator (::) forces use of the global new operator.


  delete Operator

The delete operator deallocates an object created with the new operator. The delete operator has a result of type void and therefore does not return a value. The operand to delete must be a pointer returned by the new operator.

Using delete on a pointer to an object not allocated with new gives unpredictable results. You can, however, use delete on a pointer with the value 0. This provision means that, because new always returns 0 on failure, deleting the result of a failed new operation is harmless.

Syntax

deallocation-expression:
:: (opt)  delete cast-expression
:: (opt)  delete [ ] cast-expression

Using the delete operator on an object deallocates its memory. A program that dereferences a pointer after the object is deleted can have unpredictable results or crash.

If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.

Pointers to const objects cannot be deallocated with the delete operator.

How delete Works

The delete operator actually invokes the function operator delete. For objects of class types (class, struct, and union), the delete operator invokes the destructor for an object prior to deallocating memory (if the pointer is not null). For objects not of class type, the global delete operator is invoked. For objects of class type, the delete operator can be defined on a per-class basis; if there is no such definition for a given class, then the global operator is invoked.

Microsoft Specific

For 16-bit targets, Microsoft C++ allows multiple delete operators to be present for a given class type — one for each data memory model. This guarantees that the correct object is deleted when the delete operator is invoked in the program. See »Declaring Destructors« in Chapter 11, »Overloaded Operators« in Chapter 12, and »Memory-Model Specifiers and Overloading« in Appendix B. ♦

Using delete

There are two syntactic variants for the delete operator: one for single objects and the other for arrays of objects. The following code fragment shows how these differ:

int main()
{
    // Allocate a user-defined object, UDObject, and an object
    //  of type double on the free store using the
    //  new operator.
    UDType *UDObject = new UDType;
    double *dObject = new double;
    ...
    // Delete the two objects.
    delete UDObject;
    delete dObject;
    ...

    // Allocate an array of user-defined objects on the
    // free store using the new operator.
    UDType (*UDArr)[7] = new UDType[5][7];
    ...
    // Use the array syntax to delete the array of objects.
    delete [] UDArr;

    return 0;
}

These two cases produce undefined results: using the array form of delete (delete [ ]) on an object and using the nonarray form of delete on an array.


  Expressions with Binary Operators

Binary operators act on two operands in an expression. The binary operators are:

•	Multiplication (*)

•	Division (/)

•	Modulus (%)

•	Addition (+)

•	Subtraction (−)

•	Right shift (>>)

•	Left shift (<<)

•	Less than (<)

•	Greater than (>)

•	Less than or equal to (<=)

•	Greater than or equal to (>=)

•	Equal to (==)

•	Not equal to (!=)

•	Bitwise AND (&)

•	Bitwise exclusive OR (^)

•	Bitwise inclusive OR (|)

•	Logical AND (&&)

•	Logical OR (||)


  Multiplicative Operators

The multiplicative operators are:

•	Multiplication (*)

•	Division (/)

•	Modulus or "remainder from division" (%)

These binary operators have left-to-right associativity.

Syntax

multiplicative-expression:
pm-expression
multiplicative-expression * pm-expression
multiplicative-expression / pm-expression
multiplicative-expression % pm-expression

The multiplicative operators take operands of arithmetic types. The modulus operator (%) has a stricter requirement in that its operands must be of integral type. (To get the remainder of a floating-point division, use the run-time function, fmod.) The conversions covered in »Arithmetic Conversions« in Chapter 3 are applied to the operands, and the result is of the converted type.

The multiplication operator yields the result of multiplying the first operand by the second.

The division operator yields the result of dividing the first operand by the second.

The modulus operator yields the remainder given by the following expression, where e1 is the first operand and e2 is the second: e1 − (e1 / e2) * e2, where both operands are of integral types.

Division by 0 in either a division or a modulus expression is undefined and causes a run-time error. Therefore, the following expressions generate undefined, erroneous results:

i % 0
f / 0.0

If both operands to a multiplication, division, or modulus expression have the same sign, the result is positive. Otherwise, the result is negative. The result of a modulus operation's sign is implementation-defined.

Microsoft Specific

In Microsoft C++, the result of a modulus expression is always the same as the sign of the first operand. ♦

If the computed division of two integers is inexact and only one of the operands is negative, the result is the largest integer (in magnitude, disregarding the sign) that is less than the exact value the division operation would yield. For example, the exact value of −11 / 3 is −3.666666666 (not a rational number). The result of that integral division is −3.

The relationship between the multiplicative operators is given by the identity
(e1 / e2) * e2 + e1 % e2 == e1.


  Additive Operators

The additive operators are:

•	Addition (+)

•	Subtraction (−)

These binary operators have left-to-right associativity.

Syntax

additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression − multiplicative-expression

The additive operators take operands of arithmetic or pointer types. The result of the addition (+) operator is the sum of the operands. The result of the subtraction (−) operator is the difference between the operands. If one or both of the operands are pointers, they must be pointers to objects, not to functions.

Additive operators take operands of arithmetic, integral, and scalar types. These are defined in Table 4.2.

Table 4.2    Types Used with Additive Operators

Type	Meaning
arithmetic	Integral and floating types are collectively called "arithmetic" types.
integral	Types char and int of all sizes (long, short) and enumerations are "integral" types.
scalar	Scalar operands are operands of either arithmetic or pointer type.
The legal combinations for these operators are:

arithmetic + arithmetic
scalar + integral
integral + scalar
arithmetic − arithmetic
scalar − scalar

Note that addition and subtraction are not equivalent operations.

If both operands are of arithmetic type, then the conversions covered in »Arithmetic Conversions« in Chapter 3 are applied to the operands, and the result is of the converted type.

Addition of Pointer Types

If one of the operands in an addition operation is a pointer to an array of objects, the other must be of integral type. The result is a pointer that is of the same type as the original pointer and that points to another array element. The following code fragment illustrates this concept:

short IntArray[10]; // Objects of type short occupy 2 bytes
short *pIntArray = IntArray;

for( int i = 0; i < 10; ++i )
{
    *pIntArray = i;
    cout << *pIntArray << "\n";
    pIntArray = pIntArray + 1;
}

Although the integral value 1 is added to pIntArray, it does not mean "add 1 to the address"; rather it means "adjust the pointer to point to the next object in the array" that happens to be 2 bytes (or sizeof( int )) away.

Note  Code of the form pIntArray = pIntArray + 1 is rarely found in C++ programs; to perform an increment, these forms are preferable: pIntArray++ or pIntArray += 1.

Subtraction of Pointer Types

If both operands are pointers, then the result of subtraction is the difference (in array elements) between the operands. The subtraction expression yields a signed integral result of type ptrdiff_t (defined in the standard include file STDDEF.H).

One of the operands can be of integral type, as long as it is the second operand. The result of the subtraction is of the same type as the original pointer. The value of the subtraction is a pointer to the (n − i)th array element, where n is the element pointed to by the original pointer and i is the integral value of the second operand.


  Shift Operators

The bitwise shift operators are:

•	Right shift (>>)

•	Left shift (<<)

These binary operators have left-to-right associativity.

Syntax

shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

Both operands of the shift operators must be of integral types. Integral promotions are performed according to the rules described in »Integral Promotions« in Chapter 3. The type of the result is the same as the type of the left operand. The value of a right-shift expression e1 >> e2 is e1 / 2 (e2) , and the value of a left-shift expression e1 << e2 is e1 * 2 (e2) .

The results are undefined if the right operand of a shift expression is negative or if the right operand is greater than or equal to the number of bits in the (promoted) left operand.

The left-shift operator causes the bit pattern in the first operand to be shifted left the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled. The shift is a logical shift, as opposed to a shift-and-rotate operation.

The right-shift operator causes the bit pattern in the first operand to be shifted right the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled for unsigned quantities. For signed quantities, the sign bit is propagated into the vacated bit positions. The shift is a logical shift if the left operand is an unsigned quantity; otherwise, it is an arithmetic shift.

Microsoft Specific

The result of a right shift of a signed negative quantity is implementation dependent. Although Microsoft C++ propagates the most-significant bit to fill vacated bit positions, there is no guarantee other implementations will do likewise. ♦


  Relational and Equality Operators

The relational and equality operators determine equality, inequality, or relative values of their operands. The relational operators are shown in Table 4.3.

Table 4.3    Relational and Equality Operators

Operator	Meaning
==	Equal to
!=	Not equal to
<	Less than
>	Greater than
<=	Less than or equal to
>=	Greater than or equal to
Relational Operators

The binary relational operators determine the following relationships:

•	Less than

•	Greater than

•	Less than or equal to

•	Greater than or equal to

Syntax

relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression

The relational operators have left-to-right associativity. Both operands of relational operators must be of arithmetic or pointer type. They yield values of type int. The value returned is 0 if the relationship in the expression is false; otherwise, it is 1. Consider the following code, which demonstrates several relational expressions:

#include <iostream.h>

int main()
{
    cout << "The true expression 3 > 2 yields: "
         << (3 > 2) << "\n";
    cout << "The false expression 20 < 10 yields: "
         << (20 < 10) << "\n";
    cout << "The expression 10 < 20 < 5 yields: "
         << (10 < 20 < 5) << "\n";

    return 0;
}

The output from this program is:

The true expression 3 > 2 yields 1
The false expression 20 < 10 yields 0
The expression 10 < 20 < 5 yields 1

The expressions in the example above must be enclosed in parentheses because the insertion operator (<<) has higher precedence than the relational operators. Therefore, the first expression without the parentheses would be evaluated as follows:

(cout << "The true expression 3 > 2 yields: " << 3) < (2 << "\n");

Note that the third expression evaluates to 1 — because of the left-to-right associativity of relational operators, the explicit grouping of the expression 10 < 20 < 5 is:

(10 < 20) < 5

Therefore, the test performed is:

1 < 5

and the result is 1 (or true).

The usual arithmetic conversions covered in »Arithmetic Conversions« in Chapter 3 are applied to operands of arithmetic types.

Comparing Pointers Using Relational Operators

When two pointers to objects of the same type are compared, the result is determined by the location of the objects pointed to in the program's address space. Pointers can also be compared to a constant expression that evaluates to 0 or to a pointer of type void *. If a pointer comparison is made against a pointer of type void *, the other pointer is implicitly converted to type void *. Then the comparison is made.

Two pointers of different types cannot be compared unless:

•	One type is a class type derived from the other type.

•	At least one of the pointers is explicitly converted (cast) to type void *. (The other pointer is implicitly converted to type void * for the conversion.)

Two pointers of the same type that point to the same object are guaranteed to compare equal. If two pointers to nonstatic members of an object are compared, the following rules apply:

•	If the class type is not a union, and if the two members are not separated by an access-specifier, such as public, protected, or private, the pointer to the member declared last will compare greater than the pointer to the member declared earlier. (For information on access-specifier, see the "Syntax" section in »Access Specifiers« in Chapter 10.)

•	If the two members are separated by an access-specifier, the results are undefined.

•	If the class type is a union, pointers to different data members in that union compare equal.

If two pointers point to elements of the same array or to the element one beyond the end of the array, the pointer to the object with the higher subscript compares higher. Comparison of pointers is guaranteed valid only when the pointers refer to objects in the same array or to the location one past the end of the array.

Microsoft Specific

In Microsoft C++, far pointers that are compared for magnitude (using any operator other than ==) are compared using their offsets only. The segments are not considered in the comparison. Far pointers compared for equality, however, are compared using a segment and offset comparison. ♦

Equality Operators

The binary equality operators compare their operands for strict equality or inequality.

Syntax

equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

The equality operators, equal to (==) and not equal to (!=), have lower precedence than the relational operators, but they behave similarly in all other respects.

The equal-to operator (==) returns true if both operands have the same value; otherwise, it returns false. The not-equal-to operator (!=) returns true if the operands do not have the same value; otherwise, it returns false.

Equality operators can compare pointers to members of the same type. In such a comparison, pointer-to-member conversions, as discussed in »Pointer-to-Member Conversions« in Chapter 3 are performed. Pointers to members can also be compared to a constant expression that evaluates to 0.


  Bitwise Operators

The bitwise operators are:

•	Bitwise AND (&)

•	Bitwise exclusive OR (^)

•	Bitwise inclusive OR (|)

These operators return bitwise combinations of their operands.

Bitwise AND Operator

The bitwise AND operator (&) returns the bitwise AND of the two operands. All bits that are on (1) in both the left and right operand are on in the result; bits that are off (0) in either the left or the right operand are off in the result.

Syntax

and-expression:
relational-expression
and-expression & equality-expression

Both operands to the bitwise AND operator must be of integral types. The usual arithmetic conversions covered in »Arithmetic Conversions« in Chapter 3, are applied to the operands.

Bitwise Exclusive OR Operator

The bitwise exclusive OR operator (^) returns the bitwise exclusive OR of the two operands. All bits that are on (1) in either the left or right operand, but not both, are on in the result. Bits that are the same (either on or off) in both operands are off in the result.

Syntax

exclusive-or-expression:
and-expression
exclusive-or-expression ^ and-expression

Both operands to the bitwise exclusive OR operator must be of integral types. The usual arithmetic conversions covered in »Arithmetic Conversions« in Chapter 3 are applied to the operands.

Bitwise Inclusive OR Operator

The bitwise inclusive OR operator (|) returns the bitwise inclusive OR of the two operands. All bits that are on (1) in either the left or right operand are on in the result. Bits that are off (0) in both operands are off in the result.

Syntax

inclusive-or-expression:
exclusive-or-expression
inclusive-or-expression | exclusive-or-expression

Both operands to the bitwise inclusive OR operator must be of integral types. The usual arithmetic conversions covered in »Arithmetic Conversions« in Chapter 3 are applied to the operands.


  Logical Operators

The logical operators, logical AND (&&) and logical OR (||), are used to combine multiple conditions formed using relational or equality expressions.

Logical AND Operator

The logical AND operator (&&) returns the integral value 1 if both operands are nonzero; otherwise, it returns 0. Logical AND has left-to-right associativity.

Syntax

logical-and-expression:
inclusive-or-expression
logical-and-expression && inclusive-or-expression

The operands to the logical AND operator need not be of the same type, but they must be of integral or pointer type. The operands are commonly relational or equality expressions.

The first operand is completely evaluated and all side effects are completed before continuing evaluation of the logical AND expression.

The second operand is evaluated only if the first operand evaluates to true (nonzero). This "short-circuit" evaluation eliminates needless evaluation of the second operand when the logical AND expression has already been determined false. Short-circuit evaluation can be used to prevent null-pointer dereferencing, as shown in the following example:

char *pch = 0;
...
(pch) && (*pch = 'a');

If pch is null (0), the right side of the expression is never evaluated. Therefore, the assignment through a null pointer is impossible.

Logical OR Operator

The logical OR operator (||) returns the integral value 1 if either operand is nonzero; otherwise, it returns 0. Logical OR has left-to-right associativity.

Syntax

logical-or-expression:
logical-and-expression
logical-or-expression || logical-and-expression

The operands to the logical OR operator need not be of the same type, but they must be of integral or pointer type. The operands are commonly relational or equality expressions.

The first operand is completely evaluated and all side effects are completed before continuing evaluation of the logical OR expression.

The second operand is evaluated only if the first operand evaluates to false (0). This "short-circuit" evaluation eliminates needless evaluation of the second operand when the logical OR expression has already been determined true.


  Assignment Operators

Assignment operators store a value in the object designated by the left operand. There are two kinds of assignment operations: "simple assignment," in which the value of the second operand is stored in the object specified by the first operand, and "compound assignment," in which an arithmetic, shift, or bitwise operation is performed prior to storing the result. All of the assignment operators in Table 4.4 except the = operator are compound assignment operators.

Table 4.4    Assignment Operators

Operator	Meaning
=	Store the value of the second operand in the object specified by the first operand ("simple assignment").
*=	Multiply the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
/=	Divide the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
%=	Take modulus of the first operand specified by the value of the second operand; store the result in the object specified by the first operand.
+=	Add the value of the second operand to the value of the first operand; store the result in the object specified by the first operand.
−=	Subtract the value of the second operand from the value of the first operand; store the result in the object specified by the first operand.
<<=	Shift the value of the first operand left the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
>>=	Shift the value of the first operand right the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
&=	Obtain the bitwise AND of the first and second operands; store the result in the object specified by the first operand.
^=	Obtain the bitwise exclusive OR of the first and second operands; store the result in the object specified by the first operand.
|=	Obtain the bitwise inclusive OR of the first and second operands; store the result in the object specified by the first operand.
Syntax

assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator: one of
=    *=    /=    %=    +=    −=    <<=    >>=    &=    ^=    |=

Result of Assignment Operators

The assignment operators return the value of the object specified by the left operand after the assignment. The resultant type is the type of the left operand. The result of an assignment expression is always an l-value. These operators have right-to-left associativity. The left operand must be a modifiable l-value.

Note  In ANSI C, the result of an assignment expression is not an l-value. Therefore, the legal C++ expression (a += b) += c is illegal in C.

Simple Assignment

The simple assignment operator (=) causes the value of the second operand to be stored in the object specified by the first operand. If both objects are of arithmetic types, the right operand is converted to the type of the left, prior to storing the value.

Objects of const and volatile types can be assigned to l-values of types that are just volatile or that are neither const nor volatile.

Assignment to objects of class type (struct, union, and class types) is performed by a function named operator=. The default behavior of this operator function is to perform a bitwise copy; however, this behavior can be modified using overloaded operators. (See »Overloaded Operators« in Chapter 12 for more information about operator overloading.)

An object of any unambiguously derived class from a given base class can be assigned to an object of the base class. The reverse is not true because there is an implicit conversion from derived class to base class but not from base class to derived class. For example:

#include <iostream.h>

class ABase
{
public:
    ABase() { cout << "constructing ABase\n"; }
};

class ADerived : public ABase
{
public:
    ADerived() { cout << "constructing ADerived\n"; }
};

int main()
{
    ABase aBase;
    ADerived aDerived;

    aBase = aDerived; // OK
    aDerived = aBase; // Error

    return 0;
}

Assignments to reference types behave as if the assignment were being made to the object to which the reference points.

For class-type objects, assignment is different from initialization. To illustrate how different assignment and initialization can be, consider the code

UserType1 A;
UserType2 B = A;

The above code shows an initializer; it calls the constructor for UserType1 that takes an argument of type UserType1. Given the code

UserType1 A;
UserType2 B;

B = A;

the assignment statement

B = A;

can have one of the effects listed below:

•	Call the function operator= for UserType2, provided operator=  is provided with a UserType1 argument.

•	Call the explicit conversion function UserType1::operator UserType2, if such a function exists.

•	Call a constructor UserType2::UserType2, provided such a constructor exists, that takes a UserType1 argument and copies the result.

Compound Assignment

The compound assignment operators, shown in Table 4.4 above, are specified in the form e1 op= e2, where e1 is a modifiable l-value not of const type and e2 is one of the following:

•	An arithmetic type

•	A pointer, if op is + or −

The e1 op= e2 form behaves as e1 = e1 op e2, but e1 is evaluated only once.

Compound assignment to an enumerated type generates an error message. If the left operand is of a pointer type, the right operand must be of a pointer type or it must be a constant expression that evaluates to 0. If the left operand is of an integral type, the right operand must not be of a pointer type.


  Comma Operator

The comma operator allows grouping two statements where one is expected.

Syntax

expression:
assignment-expression
expression , assignment-expression

The comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to right. The left operand is guaranteed evaluated, and all side effects are completed before evaluation of the right operand.

Consider the expression

e1 , e2

The type and value of the expression are the type and value of e2; the result of evaluating e1 is discarded. The result is an l-value if the right operand is an lvalue.

Where the comma has special meaning (for example in actual arguments to functions or aggregate initializers), the comma operator and its operands must be enclosed in parentheses. Therefore, the following function calls are not equivalent:

// Declare functions:
void Func( int, int );
void Func( int );

Func( arg1, arg2 );    // Call Func( int, int )
Func( (arg1, arg2) );  // Call Func( int )


  Expressions with the Conditional Operator

The conditional operator (? :) is a ternary operator (it takes three operands). The conditional operator works as follows:

•	The first operand is evaluated and all side effects are completed before continuing.

•	If the first operand evaluates to true (a nonzero value), the second operand is evaluated.

•	If the first operand evaluates to false (0), the third operand is evaluated.

The result of the conditional operator is the result of whichever operand is evaluated — the second or the third. Only one of the last two operands is evaluated in a conditional expression.

Syntax

conditional-expression:
logical-or-expression
logical-or-expression ? expression : conditional-expression

Conditional expressions have no associativity. The first operand must be of integral or pointer type. The following rules apply to the second and third expressions:

•	If both expressions are of the same type, the result is of that type.

•	If both expressions are of arithmetic types, usual arithmetic conversions (covered in »Arithmetic Conversions« in Chapter 3) are performed to convert them to a common type.

•	If both expressions are of pointer types or if one is a pointer type and the other is a constant expression that evaluates to 0, pointer conversions are performed to convert them to a common type.

•	If both expressions are of reference types, reference conversions are performed to convert them to a common type.

•	If both expressions are of type void, the common type is type void.

•	If both expressions are of a given class type, the common type is that class type.

Any combinations of second and third operands not in the list above are illegal. The type of the result is the common type, and it is an l-value if both the second and third operands are of the same type and both are l-values.


  Constant Expressions

C++ requires constant expressions — expressions that evaluate to a constant — for declarations of:

•	Array bounds

•	Selectors in case statements

•	Bit-field length specification

•	Enumeration initializers

Syntax

constant-expression:
conditional-expression

The only operands that are legal in constant expressions are:

•	Literals

•	Enumeration constants

•	Values declared as const that are initialized with constant expressions

•	sizeof expressions

Nonintegral constants must be converted (either explicitly or implicitly) to integral types to be legal in a constant expression. Therefore, the following code is legal:

const double Size = 11.0;

char chArray[(int)Size];

Explicit conversions to integral types are legal in constant expressions; all other types and derived types are illegal except when used as operands to the sizeof operator.

The comma operator and assignment operators cannot be used in constant expressions.


  Expressions with Explicit Type Conversions

C++ provides implicit type conversion, as described in »Chapter 3, Standard Conversions.« You can also specify explicit type conversions when you need more precise control of the conversions applied.


  Explicit Type Conversion Operator

C++ allows explicit type conversion using a syntax similar to the function-call syntax. A simple-type-name followed by an expression-list enclosed in parentheses constructs an object of the specified type using the specified expressions. The following example shows an explicit type conversion to type int:

int i = int( d );

The following example uses the Point class defined in »Function-Call Results« with a few modifications.

#include <iostream.h>

class Point
{
public:
    // Define default constructor.
    Point() { _x = _y = 0; }
    // Define another constructor.
    Point( int X, int Y ) { _x = X; _y = Y; }

    // Define "accessor" functions as
    // reference types.
    unsigned& x() { return _x; }
    unsigned& y() { return _y; }
    void Show()   { cout << "x = " << _x << ", "
                         << "y = " << _y << "\n"; }
private:
    unsigned _x;
    unsigned _y;
};

int main()
{
    Point Point1, Point2;

    // Assign Point1 the explicit conversion
    //  of ( 10, 10 ).
    Point1 = Point( 10, 10 );

    // Use x() as an l-value by assigning an explicit
    //  conversion of 20 to type unsigned.
    Point1.x() = unsigned( 20 );
    Point1.Show();

    // Assign Point2 the default Point object.
    Point2 = Point();
    Point2.Show();

    return 0;
}

The output from this program is:

x = 20, y = 10
x = 0, y = 0

Although the above example demonstrates explicit type conversion using constants, the same technique works to perform these conversions on objects. The following code fragment demonstrates this:

int i = 7;
float d;

d = float( i );

Explicit type conversions can also be specified using the "cast" syntax. The previous example, rewritten using the cast syntax, follows:

d = (float)i;

Both cast and function-style conversions have the same results when converting from single values. However, in the function-style syntax, you can specify more than one argument for conversion. This difference is important for user-defined types. Consider a Point class and its conversions:

struct Point
{
    Point( short x, short y ) { _x = x; _y = y; }
    ...
    short _x, _y;
};
...
Point pt = Point( 3, 10 );

The example above, which uses function-style conversion, shows how to convert two values (one for x and one for y) to the user-defined type Point.

Important  Explicit type conversions override the C++ compiler's built-in type checking. These conversions should be used with care.

Syntax

cast-expression:
unary-expression
( type-name ) cast-expression

The cast notation must be used for conversions to types that do not have a simple-type-name (pointer or reference types, for example). Conversion to types that can be expressed with a simple-type-name can be written in either form. See »Type Specifiers« in Chapter 6 for more information about what constitutes a simple-type-name.

Type definition within casts is illegal.


  Legal Conversions

Explicit conversions from a given type to another type can be done if the conversion can be done using standard conversions. The results are the same.

In addition, the conversions described in the following sections are legal; any other conversions not explicitly defined by the user (for a class type) are illegal.

A value of integral type can be explicitly converted to a pointer if the pointer is large enough to hold the integral value. A pointer that is converted to an integral value can be converted back to a pointer; its value is the same. This identity is given by the following (where p represents a pointer of any type):

p == (type *) integral-conversion( p )

Note that with explicit conversions, the compiler does not check whether the converted value fits in the new type except when converting from pointer to integral type or vice versa.

Converting Pointer Types

A pointer to one object type can be explicitly converted to a pointer of another object type. A pointer declared as void * is considered a pointer to any object type.

A pointer to a base class can be explicitly converted to a pointer to a derived class as long as these conditions are met:

•	There is an unambiguous conversion.

•	The base class is not declared as virtual at any point.

Because conversion to type void * can change the representation of an object, there is no guarantee that the conversion type1*  void *  type2* is equivalent to the conversion type1*  type2* (which is a change in value only).

When such a conversion is performed, the result is a pointer to the subobject of the original object representing the base class.

See »Chapter 9, Derived Classes,« for more information about ambiguity and virtual base classes.

16-Bit Specific

A pointer to a function can be explicitly converted to a pointer-to-object type, provided the pointer to the object has enough bits. This restriction is sensitive to memory-model selection; as a result, memory-model selection can change the size of pointers to functions. Code that works in small model can fail in medium model, as shown in this example:

void func();

int main()
{
    int iPtr;
    void (*fPtr)() = func;

    iPtr = (int)fPtr;

    return 0;
}

In small model (for the 16-bit compiler), both objects of type int and pointers to functions are 16 bits. However, changing to medium model changes pointers to functions to 32-bit pointers, causing a compilation error. ♦

C++ allows explicit conversions of pointers to objects or functions to type void *.

Pointers to object types can be explicitly converted to pointers to functions if the function pointer type has enough bits to accommodate the pointer to object type.

A pointer to a const object can be explicitly converted to a pointer not of const type. The result of this conversion points to the original object. An object of const type, or a reference to an object of const type, can be cast to a reference to a type that is not const. The result is a reference to the original object. The original object was probably declared as const because it was to remain constant across the duration of the program. Therefore, an explicit conversion defeats this safeguard, allowing modification of such objects. The behavior in such cases is undefined.

A pointer to an object of volatile type can be cast to a pointer to a type that is not volatile. The result of this conversion refers to the original object. Similarly, an object of volatile type can be cast to a reference to a type that is not volatile.

Converting the Null Pointer

The null pointer (0) is converted into itself.

Converting to a Forward-Reference Class Type

A class that has been declared but not yet defined (a forward reference) can be used in a pointer cast. In this case, the compiler returns a pointer to the original object, not to a subobject as it might if the class's relationships were known.

Converting to Reference Types

Any object whose address can be converted to a given pointer type can also be converted to the analogous reference type. For example, any object whose address can be converted to type char * can also be converted to type char &. No constructors or class conversion functions are called to make a conversion to a reference type.

Objects or values can be converted to class-type objects only if a constructor or conversion operator has been provided specifically for this purpose. For more information about these user-defined functions, see »Conversion Constructors« in Chapter 11.

Conversion of a reference to a base class, to a reference to a derived class (and vice versa) is done the same way as for pointers.

A cast to a reference type results in an l-value. The results of casts to other types are not l-values. Operations performed on the result of a pointer or reference cast are still performed on the original object.

Converting Among Pointer-to-Member Types

A pointer to a member can be converted to a different pointer-to-member type subject to these rules: Either the pointers must both be pointers to members in the same class or they must be pointers to members of classes, one of which is derived unambiguously from the other. When converting pointer-to-member functions, the return and argument types must match.


  Expressions with Pointer-to-Member Operators

The pointer-to-member operators, .* and −>*, return the value of a specific class member for the object specified on the left side of the expression. The following example shows how to use these operators:

#include <iostream.h>

class Window
{
public:
    void Paint(); // Causes window to repaint.
    int WindowId;
};

// Define derived types pmfnPaint and pmWindowId.
// These types are pointers to members Paint() and
// WindowId, respectively.
void (Window::*pmfnPaint)() = &Window::Paint;
int Window::*pmWindowId = &Window::WindowId;

int main()
{
    Window AWindow;
    Window *pWindow = new Window;
// Invoke the Paint function normally, then use pointer to member.
    AWindow.Paint();
    (AWindow.*pmfnPaint)();

    pWindow->Paint();
    (pWindow->*pmfnPaint)(); // Parentheses required since * binds
                             //  less tightly than the function call.

    int Id;
    // Retrieve window id.
    Id = AWindow.*pmWindowId;
    Id = pWindow->*pmWindowId;

    return 0;
}

In the above example, a pointer to a member, pmfnPaint, is used to invoke the member function Paint. Another pointer to a member, pmWindowId, is used to access the WindowId member.

Syntax

pm-expression:
cast-expression
pm-expression .* cast-expression
pm-expression −>* cast-expression

The binary operator .* combines its first operand, which must be an object of class type, with its second operand, which must be a pointer-to-member type.

The binary operator −>* combines its first operand, which must be a pointer to an object of class type, with its second operand, which must be a pointer-to-member type.

In an expression containing the .* operator, the first operand must be of the class type of, and be accessible to, the pointer to member specified in the second operand or of an accessible type unambiguously derived from and accessible to that class.

In an expression containing the −>* operator, the first operand must be of the type "pointer to the class type" of the type specified in the second operand, or it must be of a type unambiguously derived from that class.

Consider the following classes and program fragment:

class BaseClass
{
public:
    BaseClass(); // Base class constructor.
    void Func1();
};

// Declare a pointer to member function Func1.
void (BaseClass::*pmfnFunc1)() = &BaseClass::Func1;

class Derived : public BaseClass
{
public:
    Derived();  // Derived class constructor.
    void Func2();
};

// Declare a pointer to member function Func2.
void (Derived::*pmfnFunc2)() = &Derived::Func2;

int main()
{
    BaseClass ABase;
    Derived ADerived;

    (ABase.*pmfnFunc1)();    // OK: defined for BaseClass.
    (ABase.*pmfnFunc2)();    // Error: cannot use base class to
                             //  access pointers to members of
                             //  derived classes.
    (ADerived.*pmfnFunc1)(); // OK: Derived is unambiguously
                             //  derived from BaseClass.
    (ADerived.*pmfnFunc2)(); // OK: defined for Derived.

    return 0;
}

The result of the .* or −>* pointer-to-member operators is an object or function of the type specified in the declaration of the pointer to member. So, in the example above, the result of the expression ADerived.*pmfnFunc1() is a pointer to a function that returns void. This result is an l-value if the second operand is an l-value.

Note  If the result of one of the pointer-to-member operators is a function, then the result can be used only as an operand to the function call operator.


  4.2  Semantics of Expressions

This section explains when, and in what order, expressions are evaluated (»Order of Evaluation« and »Sequence Points«). In addition, it describes certain expressions that are ambiguous in their meaning (»Ambiguous Expressions«) and compatible types that can be used in expressions (»Notation in Expressions«).


  Order of Evaluation

This section discusses the order in which expressions are evaluated but does not explain the syntax or the semantics of the operators in these expressions. The earlier sections in this chapter provide a complete reference for each of these operators.

Expressions are evaluated according to the precedence and grouping of their operators. (»Table 1.1« in Chapter 1, "Lexical Conventions," shows the relationships the C++ operators impose on expressions.) Consider this example:

#include <iostream.h>

int main()
{
    int a = 2, b = 4, c = 9;

    cout << a + b * c << "\n";
    cout << a + (b * c) << "\n";
    cout << (a + b) * c << "\n";

    return 0;
}

The output from the above code is:

38
38
54

»Figure 4.1« shows the order in which the expressions are evaluated.

The order in which the expression shown in »Figure 4.1« is evaluated is determined by the precedence and associativity of the operators:

1.	Multiplication (*) has the highest precedence in this expression; hence the subexpression b * c is evaluated first.

2.	Addition (+) has the next highest precedence, so a is added to the product of b and c.

3.	Left shift (<<) has the lowest precedence in the expression, but there are two occurrences. Because the left-shift operator groups left-to-right, the left subexpression is evaluated first and then the right one.

When parentheses are used to group the subexpressions, they alter the precedence and also the order in which the expression is evaluated, as shown in »Figure 4.2.«

Expressions such as those shown in »Figure 4.2« are evaluated purely for their side effects — in this case, to transfer information to the standard output device.

Note  The left-shift operator is used to insert an object in an object of class ostream. It is sometimes called the "insertion" operator when used with iostream. For more about the iostream library, see the iostream Class Library Reference.


  Sequence Points

An expression can modify an object's value only once between consecutive "sequence points."

Microsoft Specific

The C++ language definition does not currently specify sequence points. Microsoft C++ uses the same sequence points as ANSI C for any expression involving C operators and not involving overloaded operators. When operators are overloaded, the semantics change from operator sequencing to function-call sequencing. Microsoft C++ uses the following sequence points:

•	Left operand of the logical AND operator (&&). The left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated.

•	Left operand of the logical OR operator (||). The left operand of the logical OR operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical OR operator will be evaluated.

•	Left operand of the comma operator. The left operand of the comma operator is completely evaluated and all side effects completed before continuing. Both operands of the comma operator are always evaluated.

•	Function-call operator. The function-call expression and all arguments to a function, including default arguments, are evaluated and all side effects completed prior to entry to the function. No order of evaluation among the arguments or the function-call expression is specified.

•	First operand of the conditional operator. The first operand of the conditional operator is completely evaluated and all side effects completed before continuing.

•	The end of a full initialization expression, such as the end of an initialization in a declaration statement.

•	The expression in an expression statement. Expression statements consist of an optional expression followed by a semicolon (;). The expression is completely evaluated for its side effects.

•	The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects completed before the code dependent on the selection is executed.

•	The controlling expression of a while or do statement. The expression is completely evaluated and all side effects completed before any statements in the next iteration of the while or do loop are executed.

•	Each of the three expressions of a for statement. Each expression is completely evaluated and all side effects completed before moving to the next expression.

•	The expression in a return statement. The expression is completely evaluated and all side effects completed before control returns to the calling function. ♦


  Ambiguous Expressions

Certain expressions are ambiguous in their meaning. These expressions occur most frequently when an object's value is modified more than once in the same expression. These expressions rely on a particular order of evaluation where the language does not define one. Consider the following example:

int i = 7;

func( i, ++i );

The C++ language does not guarantee in which order the arguments to a function call are evaluated. Therefore, in the example above, func could receive the values 7 and 8, or 8 and 8 for its parameters, depending on whether the parameters are evaluated from left to right or from right to left.


  Notation in Expressions

The C++ language specifies certain compatibilities when specifying operands. Table 4.5 shows the types of operands acceptable to operators that require operands of type type.

Table 4.5    Operand Types Acceptable to Operators

Type Expected	Types Allowed
type	const type volatile type type& const type& volatile type& volatile const type volatile const type&
type*	type* const type* volatile type* volatile const
const type	type const type const type&
volatile type	type volatile type volatile type&
Because the preceding rules can always be used in combination, a const pointer to a volatile object can be supplied where a pointer is expected.


Chapter 5: Statements
  Chapter 5  Statements

C++ statements are the program elements that control how and in what order objects are manipulated.

Statements fall into one of the following categories:

•	»Expression statements.« These statements evaluate an expression either for its side effects or for its return value.

•	»Null statements.« These statements can be provided where a statement is required by the C++ syntax but where no action is to be taken.

•	»Compound statements.« These statements are groups of statements enclosed in curly braces ({ }). They can be used wherever the grammar calls for a single statement.

•	»Selection statements.« These statements perform a test; they then execute one section of code if the test evaluates to true (nonzero). They may execute another section of code if the test evaluates to false.

•	»Iteration statements.« These statements provide for repeated execution of a block of code until some termination criterion is met.

•	»Jump statements.« These statements either transfer control immediately to another location in the function or return control from the function.

•	»Declaration statements.« Declarations introduce a name into a program. (»Chapter 6« provides more detailed information about declarations.)

•	Structured exception handling statements, which include the »try-except statement,« the »try-finally statement,« and the »leave statement«. The try-except statement provides a method to gain control of a program when events that normally terminate execution occur. The try-finally and leave statements provide a method to guarantee execution of cleanup code when execution of a block of code is interrupted.


  5.1  Overview

C++ statements are executed sequentially, except when an expression statement, a selection statement, an iteration statement, or a jump statement specifically modifies that sequence.

Syntax

statement:
labeled-statement
expression-statement
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
try-except-statement  	// Microsoft Specific
try-finally-statement  	// Microsoft Specific

In most cases, the C++ statement syntax is identical to that of ANSI C. The primary difference between the two is that in C, declarations are allowed only at the start of a block; C++ adds the declaration-statement, which effectively removes this restriction. This allows introduction of variables at a point in the program where a precomputed intialization value can be calculated.

Declaring variables inside blocks also allows you to exercise precise control over the scope and lifetime of those variables.


  5.2  Labeled Statements

In order for program control to be transferred directly to a given statement, the statement must be labeled.

Syntax

labeled-statement:
identifier  :  statement
case  constant-expression  :  statement
default  :  statement


  Using Labels with the goto Statement

The appearance of an identifier label in the source program declares a label. Only a goto statement can transfer control to an identifier label. The following code fragment illustrates use of the goto statement and an identifier label to escape a tightly nested loop:

for( p = 0; p < NUM_PATHS; ++p )
{
    NumFiles = FillArray( pFileArray, pszFNames )
    for( i = 0; i < NumFiles; ++i )
    {
        if( (pFileArray[i] = fopen( pszFNames[i], "r" )) == NULL )
            goto FileOpenError;

        // Process the files that were opened.
    }
}

FileOpenError:
    cerr << "Fatal file open error. Processing interrupted.\n" );

In the above example, the goto statement transfers control directly to the statement that prints an error message if an unknown file-open error occurs.

A label cannot appear by itself but must always be attached to a statement. If a label is needed by itself, place a null statement after the label.

The label has function scope and cannot be redeclared within the function. However, the same name can be used as a label in different functions.


  Using Labels in the case Statement

Labels that appear after the case keyword cannot also appear outside a switch statement. (This restriction also applies to the default keyword.) The following code fragment shows the correct use of case labels:

// Sample Microsoft Windows message processing loop.
switch( msg )
{
case WM_TIMER:    // Process timer event.
    SetClassWord( hWnd, GCW_HICON, ahIcon[nIcon++] );
    ShowWindow( hWnd, SW_SHOWNA );
    nIcon %= 14;
    Yield();
    break;

case WM_PAINT:
    // Obtain a handle to the device context.
    // BeginPaint will send WM_ERASEBKGND if appropriate.

    memset( &ps, 0x00, sizeof(PAINTSTRUCT) );
    hDC = BeginPaint( hWnd, &ps );

    // Inform Windows that painting is complete.

    EndPaint( hWnd, &ps );
    break;

case WM_CLOSE:
    // Close this window and all child windows.

    KillTimer( hWnd, TIMER1 );
    DestroyWindow( hWnd );
    if( hWnd == hWndMain )
        PostQuitMessage( 0 );  // Quit the application.
    break;

default:
    // This choice is taken for all messages not specifically
    //  covered by a case statement.

    return DefWindowProc( hWnd, Message, wParam, lParam );
    break;
}


  5.3  Expression Statement

Expression statements cause expressions to be evaluated. No transfer of control or iteration takes place as a result of an expression statement.

Syntax

expression-statement:
expression (opt)   ;

All expressions in an expression statement are evaluated and all side effects are complete before the next statement is executed. The most common expression statements are assignments and function calls. C++ also provides a null statement.


  The Null Statement

The "null statement" is an expression statement with the expression missing. It is useful when the syntax of the language calls for a statement but no expression evaluation. It consists of a semicolon.

Null statements are commonly used as placeholders in iteration statements or as statements on which to place labels at the end of compound statements or functions.

The following code fragment shows how to copy one string to another and incorporates the null statement:

char *strcpy( char *Dest, const char *Source )
{
    char *DestStart = Dest;

    // Assign value pointed to by Source to
    //  Dest until the end-of-string 0 is
    //  encountered.
    while( *Dest++ = *Source++ )
        ;                          // Null statement.

    return DestStart;
}


  5.4  Compound Statements (Blocks)

A compound statement consists of zero or more statements enclosed in curly braces ({ }). A compound statement can be used anywhere a statement is expected. Compound statements are commonly called "blocks."

Syntax

compound-statement:
{  statement-list (opt )  }

statement-list:
statement
statement-list  statement

The following example uses a compound statement as the statement part of the if statement (see »The if Statement« for details about the syntax):

if( Amount > 100 )
{
    cout << "Amount was too large to handle\n";
    Alert();
}
else
    Balance -= Amount;

Note  Because a declaration is a statement, a declaration can be one of the statements in the statement-list. The result of this is that names declared inside a compound statement, but not explicitly declared as static, have local scope and (for objects) lifetime. See »Scope« in Chapter 2 for details about treatment of names with local scope.


  5.5  Selection Statements

The C++ selection statements, if and switch, provide a means to conditionally execute sections of code.

Syntax

selection-statement:
if  (  expression  )  statement
if  (  expression  )  statement  else  statement
switch  (  expression  )  statement


  The if Statement

The if statement evaluates the expression enclosed in parentheses. The expression must be of arithmetic or pointer type, or it must be of a class type that defines an unambiguous conversion to an arithmetic or pointer type. (For information about conversions, see »Chapter 3, Standard Conversions.«)

In both forms of the if syntax, if the expression evaluates to a nonzero value (true), the statement dependent on the evaluation is executed; otherwise, it is skipped.

In the if...else syntax, the second statement is executed if the result of evaluating the expression is zero.

The else clause of an if...else statement is associated with the closest previous if statement that does not have a corresponding else statement. The following code fragment demonstrates how this works:

if( condition1 == true )
    if( condition2 == true )
        cout << "condition1 true; condition2 true\n";
    else
        cout << "condition1 true; condition2 false\n";
else
    cout << "condition 1 false\n";

Many programmers use curly braces ({ }) to explicitly clarify the pairing of complicated if and else clauses. The following example uses curly braces for this purpose:

if( condition1 == true )
{
    if( condition1 == true )
        cout << "condition1 true; condition2 true\n";
    else
        cout << "condition1 true; condition2 false\n";
}
else
    cout << "condition 1 false\n";

Although the braces are not strictly necessary, they clarify the pairing between if and else statements.


  The switch Statement

The C++ switch statement allows selection among multiple sections of code, depending on the value of an expression. The expression enclosed in parentheses, the "controlling expression," must be of an integral type or of a class type for which there is an unambiguous conversion to integral type. Integral promotion is performed as described in »Integral Promotions« in Chapter 3.

The switch statement causes an unconditional jump to, into, or past the statement that is the "switch body," depending on the value of the controlling expression, the values of the case labels, and the presence or absence of a default label. The switch body is normally a compound statement (although this is not a syntactic requirement). Usually, some of the statements in the switch body are labeled with case labels or with the default label. Labeled statements are not syntactic requirements, but the switch statement is meaningless without them. The default label can appear only once.

Syntax

case  constant-expression : statement

default  : statement

The constant-expression in the case label is converted to the type of the controlling expression and is then compared for equality. In a given switch statement, no two constant expressions in case statements can evaluate to the same value. The behavior is shown in Table 5.1.

Table 5.1    Switch Statement Behavior

Condition	Action
Converted value matches that of the promoted controlling expression.	Control is transferred to the statement following that label.
None of the constants match the constants in the case labels; default label is present.	Control is transferred to the default label.
None of the constants match the constants in the case labels; default label is not present.	Control is transferred to the statement after the switch statement.
An inner block of a switch statement can contain definitions with initializations as long as they are reachable — that is, not bypassed by all possible execution paths. Names introduced using these declarations have local scope. The following code fragment shows how the switch statement works:

switch( tolower( *argv[1] ) )
{
    // Error. Unreachable declaration.
    char szChEntered[] = "Character entered was: ";

case 'a' :
    {
    // Declaration of szChEntered OK. Local scope.
    char szChEntered[] = "Character entered was: ";
    cout << szChEntered << "a\n";
    }
    break;

case 'b' :
    // Value of szChEntered undefined.
    cout << szChEntered << "b\n";
    break;

default:
    // Value of szChEntered undefined.
    cout << szChEntered << "neither a nor b\n";
    break;
}

A switch statement can be nested. In such cases, case or default labels associate with the most deeply nested switch statements that enclose them. For example:

switch( msg )
{
case WM_COMMAND:      // Windows command. Find out more.
    switch( wParam )
    {
    case IDM_F_NEW:   // File New menu command.
        delete wfile;
        wfile = new WinAppFile;
        break;
    case IDM_F_OPEN:  // File Open menu command.
        wfile->FileOpenDlg();
        break;
    ...
    }
case WM_CREATE:       // Create window.
    ...
    break;
case WM_PAINT:        // Window needs repainting.
    ...
    break;
default:
    return DefWindowProc( hWnd, Message, wParam, lParam );
}

The above code fragment from a Microsoft Windows™ message loop shows how switch statements can be nested. The switch statement that selects on the value of wParam is executed only if msg is WM_COMMAND. The case labels for menu selections, IDM_F_NEW and IDM_F_OPEN, associate with the inner switch statement.

Control is not impeded by case or default labels. To stop execution at the end of a part of the compound statement, insert a break statement. This transfers control to the statement after the switch statement. This example demonstrates how control "drops through" unless a break statement is used:

BOOL fClosing = FALSE;

...

switch( wParam )
{
case IDM_F_CLOSE:       // File close command.
    fClosing = TRUE;
    // fall through

case IDM_F_SAVE:        // File save command.
    if( document->IsDirty() )
        if( document->Name() == "UNTITLED" )
            FileSaveAs( document );
        else
            FileSave( document );

    if( fClosing )
        document->Close();

    break;
}

The preceding code shows how to take advantage of the fact that case labels do not impede the flow of control. If the switch statement transfers control to IDM_F_SAVE, fClosing is FALSE. Therefore, after the file is saved, the document is not closed. However, if the switch statement transfers control to IDM_F_CLOSE,  fClosing is set to TRUE, and the code to save a file is executed.


  5.6  Iteration Statements

Iteration statements cause statements (or compound statements) to be executed zero or more times, subject to some loop-termination criteria. When these statements are compound statements, they are executed in order, except when either the break statement or the continue statement is encountered. (For a description of these statements, see »The break Statement« and »The continue Statement«.)

C++ provides three iteration statements — while, do, and for. Each of these iterates until its termination expression evaluates to zero (false) or until loop termination is forced with a break statement. Table 5.2 summarizes these statements and their actions; each is discussed in detail in the sections that follow.

Table 5.2    C++ Iteration Statements

Statement	Evaluated At	Initialization	Increment
while	Top of loop	No	No
do	Bottom of loop	No	No
for	Top of loop	Yes	Yes
Syntax

iteration-statement:
while  (  expression  )  statement
do  statement  while  (  expression  )  ;
for  (  for-init-statement expression (opt)   ;  expression (opt )  )  statement

for-init-statement:
expression-statement
declaration-statement

The statement part of an iteration statement cannot be a declaration. However, it can be a compound statement containing a declaration.


  The while Statement

The while statement executes a statement  repeatedly until the termination condition (the expression) specified evaluates to zero. The test of the termination condition takes place before each execution of the loop; therefore, a while loop executes zero or more times, depending on the value of the termination expression. The code below uses a while loop to trim trailing spaces from a string:

char *trim( char *szSource )
{
    char *pszEOS;

    // Set pointer to end of string to point to the character just
    //  before the 0 at the end of the string.
    pszEOS = szSource + strlen( szSource ) - 1;

    while( pszEOS >= szSource && *pszEOS == ' ' )
        *pszEOS-- = '\0';

    return szSource;
}

The termination condition is evaluated at the top of the loop. If there are no trailing spaces, the loop never executes.

The expression must be of an integral type, a pointer type, or a class type with an unambiguous conversion to an integral or pointer type.


  The do Statement

The do statement executes a statement repeatedly until the specified termination condition (the expression) evaluates to zero. The test of the termination condition is made after each execution of the loop; therefore, a do loop executes one or more times, depending on the value of the termination expression. The following function uses the do statement to wait for the user to press a specific key:

void WaitKey( char ASCIICode )
{
    char chTemp;

    do
    {
        chTemp = _getch();
    }
    while( chTemp != ASCIICode );
}

A do loop rather than a while loop is used in the above code — with the do loop, the _getch function is called to get a keystroke before the termination condition is evaluated. This function can be written using a while loop, but not as concisely:

void WaitKey( char ASCIICode )
{
    char chTemp;

    chTemp = _getch();

    while( chTemp != ASCIICode )
    {
        chTemp = _getch();
    }
}

The expression must be of an integral type, a pointer type, or a class type with an unambiguous conversion to an integral or pointer type.


  The for Statement

The for statement can be divided into three separate parts, as shown in Table 5.3.

Table 5.3    for Loop Elements

Syntax Name	When Executed	Contents
for-init-statement	Before any other element of the for statement or the substatement.	Often used to initialize loop indices. It can contain expressions or declarations.
expression1	Before execution of a given iteration of the loop, including the first iteration.	An expression that evaluates to an integral type or a class type that has an unambiguous conversion to an integral type.
expression2	At the end of each iteration of the loop; expression1 is tested after expression2 is evaluated.	Normally used to increment loop indices.
The for-init-statement is commonly used to declare and initialize loop-index variables. The expression1 is often used to test for loop-termination criteria. The expression2 is commonly used to increment loop indices.

The for statement executes the statement repeatedly until expression1 evaluates to zero. The for-init-statement, expression1, and expression2 fields are all optional.

The following for loop:

for( for-init-statement; expression1; expression2 )
{
    // Statements
}

is equivalent to the following while loop:

for-init-statement;
while( expression1 )
{
    // Statements
    expression2;
}

A convenient way to specify an infinite loop using the for statement is:

for( ; ; )
{
    // Statements to be executed.
}

This is equivalent to:

while( 1 )
{
    // Statements to be executed.
}

The initialization part of the for loop can be a declaration statement or an expression statement, including the null statement. The initializations can include any sequence of expressions and declarations, separated by commas. Any object declared inside a for-init-statement has local scope, as if it had been declared immediately prior to the for statement. Although the name of the object can be used in more than one for loop in the same scope, the declaration can appear only once. For example:

#include <iostream.h>

int main()
{
    for( int i = 0; i < 100; ++i )
        cout << i << "\n";

    // The loop index, i, cannot be declared in the
    //  for-init-statement here because it is still in scope.
    for( i = 100; i >= 0; --i )
        cout << i << "\n";

    return 0;
}

Although the three fields of the for statement are normally used for initialization, testing for termination, and incrementing, they are not restricted to these uses. For example, the following code prints the numbers 1 to 100. The substatement is the null statement:

#include <iostream.h>

int main()
{
    for( int i = 0; i < 100; cout << ++i << endl )
        ;

    return 0;
}


  5.7  Jump Statements

The C++ jump statements perform an immediate local transfer of control.

Syntax

jump-statement:
break   ;
continue    ;
return  expression (opt )  ;
goto  identifier   ;


  The break Statement

The break statement is used to exit an iteration or switch statement. It transfers control to the statement immediately following the iteration substatement or switch statement.

The break statement terminates only the most tightly enclosing loop or switch statement. In loops, break is used to terminate before the termination criteria evaluate to 0. In the switch statement, break is used to terminate sections of code — normally before a case label. The following example illustrates the use of the break statement in a for loop:

for( ; ; )    // No termination condition.
{
    if( List->AtEnd() )
        break;

    List->Next();
}

cout << "Control transfers to here.\n";

Note  There are other ways to escape a loop as simply as the one above. In more complex loops, where it can be difficult to tell if the loop should be terminated before several statements have been executed, using the break statement makes more sense.

For an example of using the break statement within the body of a switch statement, see »The switch Statement«.


  The continue Statement

The continue statement forces immediate transfer of control to the loop-continuation statement of the smallest enclosing loop. (The "loop-continuation" is the statement that contains the controlling expression for the loop.) Therefore, the continue statement can appear only in the dependent statement of an iteration statement (although it may be the sole statement in that statement). In a for loop, execution of a continue statement causes expression2 to be evaluated and then expression1.

The following example shows how the continue statement can be used to bypass sections of code and skip to the next iteration of a loop:

#include <conio.h>

// Get a character that is a member of the zero-terminated
//  string, szLegalString. Return the index of the character
//  entered.
int GetLegalChar( char *szLegalString )
{
    char *pch;

    do
    {
        char ch = _getch();

        // Use strchr library function to determine if the
        //  character read is in the string. If not, use the
        //  continue statement to bypass the rest of the
        //  statements in the loop.
        if( (pch = strchr( szLegalString, ch )) == NULL )
            continue;

        // A character that was in the string szLegalString
        //  was entered. Return its index.
        return (pch - szLegalString);

        // The continue statement transfers control to here.
    } while( 1 );

    return 0;
}


  The return Statement

The return statement allows a function to immediately transfer control back to the calling function (or, in the case of the main function, transfer control back to the operating system). The return statement accepts an expression, which is the value passed back to the calling function. Functions of type void, constructors, and destructors cannot specify expressions in the return statement; functions of all other types must specify an expression in the return statement.

The expression, if specified, is converted to the type specified in the function declaration, as if an initialization were being performed. Conversion from the type of the expression to the return type of the function can cause temporary objects to be created. See »Temporary Objects« in Chapter 11 for more information about how and when temporaries are created.

When the flow of control exits the block enclosing the function definition, the result is the same as it would be if a return statement with no expression had been executed. This is illegal for functions that are declared as returning a value.

A function can have any number of return statements.


  The goto Statement

The goto statement performs an unconditional transfer of control to the named label. The label must be in the current function.

For more information about labels and the goto statement, see »Labeled Statements« and »Using Labels with the goto Statement«.


  5.8  Declaration Statements

Declaration statements introduce new names into the current scope. These names can be:

•	Type names (class, struct, union, enum, typedef, and pointer-to-member).

•	Object names.

•	Function names.

Syntax

declaration-statement:
declaration

If a declaration within a block introduces a name that is already declared outside the block, the previous declaration is hidden for the duration of the block. After termination of the block, the previous declaration is again visible.

Multiple declarations of the same name in the same block are illegal.

For more information about declarations and name hiding, see »Declarations and Definitions« and »Scope« in Chapter 2.


  Declaration of Automatic Objects

In C++, objects can be declared with automatic storage class using the auto or register keyword. If no storage-class keyword is used for a local object (an object declared inside a function), auto is assumed. C++ handles initializations and declarations of these objects differently than objects declared with static storage classes.


  Initialization

Each time declaration statements for objects of storage class auto or register are executed, initialization takes place. The following example, from »The continue Statement«, shows initialization of the automatic object ch inside the do loop.

#include <conio.h>

// Get a character that is a member of the zero-terminated
//  string, szLegalString. Return the index of the character
//  entered.
int GetLegalChar( char *szLegalString )
{
    char *pch;

    do
    {
        // This declaration statement is executed once for each
        //  execution of the loop.
        char ch = _getch();

        if( (pch = strchr( szLegalString, ch )) == NULL )
            continue;

        // A character that was in the string szLegalString
        //  was entered. Return its index.
        return (pch - szLegalString);
    } while( 1 );
}

For each iteration of the loop (each time the declaration is encountered), the macro _getch is evaluated and ch is initialized with the results. When control is transferred outside the block using the return statement, ch is destroyed (in this case, the storage is deallocated).

See »Storage Classes« in Chapter 2 for another example of initialization.


  Destruction

Objects defined in a loop are destroyed once per iteration of the loop, on exit from the block, or when control transfers to a point prior to the declaration. Objects declared in a block that is not a loop are destroyed on exit from the block or when control transfers to a point prior to the declaration.

Note  Destruction can mean simply deallocating the object or, for class-type objects, invoking the object's destructor.

When a jump statement transfers control out of a loop or block, objects declared in the block transferred from are destroyed; objects in the block transferred to are not destroyed.

When control is transferred to a point prior to a declaration, the object is destroyed.


  Transfers of Control

Using the goto statement or a case label in a switch statement, it is possible to specify a program that branches past an initializer. Such code is illegal unless the declaration that contains the initializer is in a block enclosed by the block in which the jump statement occurs.

The following example shows a loop that declares and initializes the objects total, ch, and i. There is also an erroneous goto statement that transfers control past an initializer.

// Read input until a nonnumeric character is entered.
while( 1 )
{
    int total = 0;

    char ch = _getch();

    if( ch >= '0' || ch <= '9' )
    {
        goto Label1;       // Error: transfers past initialization
                           //  of i.

        int i = ch - '0';
Label1:
        total += i;
    } // i would be destroyed here if the
      //  goto error were not present.
    else
        // Break statement transfers control out of loop,
        //  destroying total and ch.
        break;
}

In the above example, the goto statement tries to transfer control past the initialization of i. However, if i were declared but not initialized, the transfer would be legal.

The objects total and ch, declared in the block that serves as the statement of the while statement, are destroyed when that block is exited using the break statement.


  Declaration of Static Objects

An object can be declared with static storage class using the static or extern keyword. Local objects must be explicitly declared as static or extern to have static storage class. All global objects (objects declared outside all functions) have static storage class. You cannot declare static instances in a tiny-model program.


  Initialization

Global objects are initialized at program startup. (For more information about construction and destruction of global objects, see »Additional Startup Considerations« and »Additional Termination Considerations« in Chapter 2.)

Local objects declared as static are initialized the first time their declarations are encountered in the program flow. The following class, introduced in »Chapter 2, Basic Concepts,« shows how this works:

#include <iostream.h>
#include <string.h>

// Define a class that logs initializations and destructions.
class InitDemo
{
public:
InitDemo( char *szWhat );
~InitDemo();
private:
char *szObjName;
};

// Constructor for class InitDemo.
InitDemo::InitDemo( char *szWhat )
{
if( szWhat != 0 && strlen( szWhat ) > 0 )
{
szObjName = new char[ strlen( szWhat ) + 1 ];
strcpy( szObjName, szWhat );
}
else
szObjName = 0;

clog << "Initializing: " << szObjName << "\n";
}

// Destructor for InitDemo.
InitDemo::~InitDemo()
{
if( szObjName != 0 )
{
clog << "Destroying: " << szObjName << "\n";
delete szObjName;
}
}

// Main function.
int main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
        cerr << "Supply a one-letter argument.\n";
        return -1;
    }

    if( *argv[1] == 'a' )
    {
        cout << "*argv[1] was an 'a'\n";

        // Declare static local object.
        static InitDemo I1( "static I1" );
    }
    else
        cout << "*argv[1] was not an 'a'\n";

    return 0;
}

If the command-line argument supplied to this program starts with the lowercase letter "a," the declaration of I1 is executed, the initialization takes place, and the result is:

*argv[1] was an 'a'
Initializing: static I1
Destroying: static I1

Otherwise, the flow of control bypasses the declaration of I1 and the result is:

*argv[1] was not an 'a'

When a static local object is declared with an initializer that does not evaluate to a constant expression, the object is given the value 0 (converted to the appropriate type) at the point before execution enters the block for the first time. However, the object is not visible and no constructors are called until the actual point of declaration.

At the point of declaration, the object's constructor (if the object is of a class type) is called as expected. (Static local objects are only initialized the first time they are seen.)


  Destruction

Local static objects are destroyed during termination specified by atexit.

If a static object was not constructed because the program's flow of control bypassed its declaration, no attempt is made to destroy that object.


  5.9  The try-except Statement (Microsoft Specific)

32-Bit Specific

The try-except statement is a Microsoft extension to the C language that enables 32-bit target applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called "structured exception handling."

Exceptions can be either hardware- or software-based. Even when applications cannot completely recover from hardware or software exceptions, structured exception handling makes it possible to display error information and trap the internal state of the application to help diagnose the problem. This is especially useful for intermittent problems that cannot be reproduced easily.

Note  Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++ and has a limitation that can affect C++ programs: as the stack is unwound, C++ objects allocated on the stack are removed without calling their destructor functions.

Syntax

try-except-statement :
__try compound-statement
__except ( expression ) compound-statement

The compound statement after the __try clause is the guarded section. The compound statement after the __except clause is the exception handler. The handler specifies a set of actions to be taken if an exception is raised during execution of the guarded section. Execution proceeds as follows:

1.	The guarded section is executed.

2.	If no exception occurs during execution of the guarded section, execution continues at the statement after the __except clause.

3.	If an exception occurs during execution of the guarded section or in any routine the guarded section calls, the __except expression is evaluated and the value returned determines how the exception is handled. There are three values:

EXCEPTION_CONTINUE_SEARCH

Exception is not recognized. Continue to search up the stack for a handler, first for containing try-except statements, then for handlers with the next highest precedence.

EXCEPTION_CONTINUE_EXECUTION

Exception is recognized but dismissed. Continue execution at the point where the exception occurred.

EXCEPTION_EXECUTE_HANDLER

Exception is recognized. Transfer control to the exception handler by executing the __except compound statement, then continue execution at the point the exception occurred.

Because the __except expression is evaluated as a C expression, it is limited to a single value, the conditional-expression operator, or the comma operator. If more extensive processing is required, the expression can call a routine that returns one of the three values listed above.

Each routine in an application can have its own exception handler. The __except expression executes in the scope of the __try body. This means it has access to any local variables declared there.

It is illegal to jump into a __try statement, but legal to jump out of one. The exception handler is not called if a process is killed in the middle of executing a try-except statement.

Following is an example of an exception handler and a termination handler. For more information about termination handlers, see the next section.

.
.
.
puts("hello");
__try{
puts("in try");
__try{
puts("in try");
RAISE_AN_EXCEPTION();
}__finally{
puts("in finally");
}
}__except( puts("in filter"), EXCEPTION_EXECUTE_HANDLER ){
puts("in except");
}
puts('world');

This is the output from the example, with commentary added on the right:

hello
in try          // fall into try
in try          // fall into nested try
in filter       // execute filter; returns 1 so accept
in finally      // unwind nested finally
in except       // transfer control to selected handler
world           // flow out of handler

For more information about structured exception handling and the try-except statement, see Chapter 7 of Programming Techniques.♦


  5.10  The try-finally Statement (Microsoft Specific)

32-Bit Specific

The try-finally statement is a Microsoft extension to the C language that enables 32-bit target applications to guarantee execution of cleanup code when execution of a block of code is interrupted. Cleanup consists of such tasks as deallocating memory, closing files, and releasing file handles. The try-finally statement is especially useful for routines that have several places where a check is made for an error that could cause premature return from the routine.

Note  Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++ and has a limitation that can affect C++ programs: as the stack is unwound, C++ objects allocated on the stack are removed without calling their destructor functions.

Syntax

try-finally-statement :
__try compound-statement
__finally compound-statement

The compound statement after the __try clause is the guarded section. The compound statement after the __finally clause is the termination handler. The handler specifies a set of actions that execute when the guarded section is exited, whether the guarded section is exited by an exception (abnormal termination) or by standard fall through (normal termination).

Control reaches a __try statement by simple sequential execution (fall through). When control enters the __try statement, its associated handler becomes active. Execution proceeds as follows:

1.	The guarded section is executed.

2.	The termination handler is invoked.

3.	When the termination handler completes, execution continues after the __finally statement. Regardless of how the guarded section ends (for example, via a goto statement out of the guarded body or via a return statement), the termination handler is executed before the flow of control moves out of the guarded section.

The __leave keyword is valid within a try-finally statement block. The effect of __leave is to jump to the end of the try-finally block. The termination handler is immediately executed. Although a goto statement can be used to accomplish the same result, a goto statement causes stack unwinding. The __leave statement is more efficient because it does not involve stack unwinding.

Exiting a try-finally statement using a return statement or the longjmp run-time function is considered abnormal termination. It is illegal to jump into a __try statement, but legal to jump out of one. All __finally statements that are active between the point of departure and the destination must be run. This is called a local unwind.

The termination handler is not called if a process is killed while executing a try-finally statement.

To see how the try-finally statement works, see the example for the »try-except statement«. For more information about structured exception handling and the try-finally statement, see Chapter 7 of Programming Techniques.♦


Chapter 6: Declarations
  Chapter 6  Declarations

Declarations introduce new names into a program. They can be used to:

•	Specify storage class, type, and linkage for an object.

•	Specify storage class, type, and linkage for a function.

•	Provide the definition of a function.

•	Provide an initial value for an object.

•	Associate a name with a constant (enumerated type declaration).

•	Declare a new type (class, struct, or union declaration).

•	Specify a synonym for a type (typedef declaration).

In addition to introducing a new name, a declaration specifies how an identifier is to be interpreted by the compiler. Declarations do not automatically reserve storage associated with the identifier — reserving storage is done by definitions.

Note  Most declarations are also definitions.

Syntax

declaration:
decl-specifiers (opt )  declarator-list (opt)   ;
function-definition
linkage-specification

The declarators in declarator-list contain the names being declared. Although the declarator-list is shown as optional, it can be omitted only in declarations or definitions of a function.

Note  The declaration of a function is often called a "prototype." This declaration provides type information about arguments and the function's return type that allows the compiler to perform correct conversions and to ensure type safety.

The decl-specifiers part of a declaration is also shown as optional; however, it can be omitted only in declarations of class types or enumerations.

An object declaration is also a definition unless it contains the extern storage-class specifier described in »Storage-Class Specifiers«. A function declaration is also a definition unless it is a prototype — a function header with no defining function body. An object's definition causes the storage for that object to be allocated and appropriate initializations to take place.


  6.1  Specifiers

This section explains the decl-specifiers portion of declarations. (The syntax for declarations is given at the beginning of this chapter.)

Syntax

decl-specifiers:
decl-specifiers (opt)  decl-specifier

decl-specifier:
storage-class-specifier
type-specifier
fct-specifier
friend
typedef
__declspec ( extended-decl-modifier-seq )  // Microsoft Specific

The Microsoft-specific keyword, __declspec, is discussed in »Extended Attribute Syntax« in Appendix B.

The decl-specifiers portion of a declaration is the longest sequence of decl-specifiers that can be construed to be a type name. The remainder of the declaration is the name or names introduced. The examples in the following list illustrate this concept:

Declaration	decl-specifiers	name
char __far *lpszAppName;	char __far *	lpszAppName
typedef char __far * LPSTR;	char __far *	LPSTR
LPSTR _fstrcpy( LPSTR, LPSTR );	LPSTR	_fstrcpy
volatile void *pvvObj;	volatile void *	pvvObj
Because signed, unsigned, long, and short all imply int, a typedef name following one of these keywords is taken to be a member of declarator-list, not of decl-specifiers.

Note  Because a name can be redeclared, its interpretation is subject to the most recent declaration in the current scope. Redeclaration can affect how names are interpreted by the compiler, particularly typedef names.


  Storage-Class Specifiers

The C++ storage-class specifiers tell the compiler about the duration and visibility of the object or function they declare, as well as where an object should be stored.

Syntax

storage-class-specifier:
auto
register
static
extern


  Automatic Storage-Class Specifiers

The auto and register storage-class specifiers can be used only to declare names used in blocks or to declare formal arguments to functions. The term "auto" comes from the fact that storage for these objects is automatically allocated at run time (normally on the program's stack).


  The auto Keyword

Few programmers use the auto keyword in declarations because all block-scoped objects not explicitly declared with another storage class are implicitly automatic. Therefore, the following two declarations are equivalent:

{
auto int i;    // Explicitly declared as auto.
int      j;    // Implicitly auto.
}


  The register Keyword

16-Bit Specific

The register keyword is similar to the auto keyword except that it tells the compiler to keep the object in a machine register if one is available. If no register is available, the compiler treats the object as any other automatic object.

The benefits of the register storage class are increased speed and reduced demands on the application stack. The latter benefit is particularly useful in recursive algorithms. ♦

32-Bit Specific

The 32-bit compiler does not honor user requests for register variables; instead, it makes its own register choices when global optimizations are on. However, all other semantics associated with the register keyword are honored by the 32-bit compiler. ♦

Microsoft Specific

The global register-allocation optimization (/Oe option) instructs the compiler to ignore the register keyword and perform register allocation based on code analysis. For algorithms that depend on register allocation, either compile without this option or use the optimize pragma to shut off global register allocation. ♦

ANSI C does not allow for taking the address of a register object; this restriction does not apply to C++. However, if the address-of operator (&) is used on an object, the compiler must put the object in a location for which an address can be represented — in practice, this means in memory instead of in a register.


  Static Storage-Class Specifiers

The static storage-class specifiers, static and extern, can be applied to objects and functions. Table 6.1 shows where the keywords static and extern can and cannot be used.

Table 6.1    Use of static and extern

Construct	Can static Be Used?	Can extern Be Used?
Function declarations within a block	No	Yes
Formal arguments to a function	No	No
Objects in a block	Yes	Yes
Objects outside a block	Yes	Yes
Functions	Yes	Yes
Class member functions	Yes	No
Class member data	Yes	No
typedef names	No	No
A name specified using the static keyword has internal linkage except for the static members of a class that have external linkage. That is, it is not visible outside the current translation unit. A name specified using the extern keyword has external linkage unless previously defined as having internal linkage. For more information about the visibility of names, see »Scope« and »Program and Linkage« in Chapter 2.

Note  Functions that are declared as inline and that are not class member functions are given the same linkage characteristics as functions declared as static.

A class name whose declaration has not yet been encountered by the compiler can be used in an extern declaration. The name introduced with such a declaration cannot be used until the class declaration has been encountered.


  Names Without Storage-Class Specifiers

File-scope names with no explicit storage-class specifiers have external linkage unless they are:

•	Declared using the const keyword

•	Previously declared with internal linkage


  Function Specifiers

The inline and virtual keywords can be used as specifiers in function declarations. This use of the virtual keyword differs from its use in the base-class specifier of a class definition.


  inline Specifier

The inline specifier instructs the compiler to replace function calls with the code of the function body. This substitution is "inline expansion" (sometimes called "inlining"). Inline expansion alleviates the function-call overhead at the potential cost of larger code size.

The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline. Two cases where this can happen are:

•	Recursive functions.

•	Functions that are referred to through a pointer elsewhere in the translation unit.

Functions that are declared as inline and that are not class member functions have internal linkage unless otherwise specified.

Microsoft Specific

The __inline keyword is equivalent to inline. ♦

As with normal functions, the order of evaluation of the arguments to an inline function is not defined. In fact, it could be different from the order in which the arguments are evaluated when passed using normal function call protocol.

Microsoft Specific

Recursive functions can be substituted inline to a depth specified by the inline_depth pragma. After that depth, recursive function calls are treated as calls to an instance of the function. The inline_recursion pragma controls the inline expansion of a function currently under expansion. See Chapter 2 of the Preprocessor Reference for more information about these pragmas. See Chapter 2 of the Build Tools User's Guide for information about the /Ob command-line option, which controls inline expansion. ♦


  Inline Class Member Functions

A function defined in the body of a class declaration is an inline function. Consider the following class declaration:

class Account
{
public:
    Account(double initial_balance) { balance = initial_balance; }
    double GetBalance();
    double Deposit( double Amount );
    double Withdraw( double Amount );
private:
    double balance;
};

The Account constructor is an inline function. The member functions GetBalance, Deposit, and Withdraw are not specified as inline but can be implemented as inline functions using code such as the following:

inline double Account::GetBalance()
{
    return balance;
}

inline double Account::Deposit( double Amount )
{
    return ( balance += Amount );
}

inline double Account::Withdraw( double Amount )
{
    return ( balance -= Amount );
}

Note  In the class declaration, the functions were declared without the inline keyword. The inline keyword can be specified in the class declaration; the result is the same.

A given inline member function must be defined exactly the same way in every compilation unit. This constraint causes inline functions to behave exactly as if they were instantiated functions. Additionally, there must be exactly one definition of an inline function.

A class member function defaults to external linkage unless a definition for that function contains the inline specifier. The example above shows that these functions need not be explicitly declared with the inline specifier; using inline in the function definition causes it to be an inline function. However, it is illegal to redeclare a function as inline after a call to that function.


  Inline Functions versus Macros

Although inline functions are similar to macros (because the function code is expanded at the point of the call at compile time), inline functions are parsed by the compiler, whereas macros are expanded by the preprocessor. As a result, there are several important differences:

•	Inline functions follow all the protocols of type safety enforced on normal functions.

•	Inline functions are specified using the same syntax as any other function except that they include the inline keyword in the function declaration.

•	Expressions passed as arguments to inline functions are evaluated exactly once. In some cases, expressions passed as arguments to macros can be evaluated more than once. The following example shows a macro that converts lowercase letters to uppercase:

#include <stdio.h>
#include <conio.h>

#define toupper(a) ((a) >= 'a' && ((a) <= 'z') ? ((a)-('a'-'A')):(a))

int main()
{
    char ch = toupper( _getch() );
    printf( "%c", ch );

    return 0;
}

The intent of the expression toupper( _getch() ) is that a character should be read from the console device (stdin) and, if necessary, converted to uppercase.

Because of the implementation, _getch is executed once to determine if the character is greater than or equal to "a" and once to determine if it is less than or equal to "z." If it is in that range, _getch is executed yet again to convert the character to uppercase. This means the program waits for two or three characters when, ideally, it should wait for only one.

Inline functions remedy this problem:

#include <stdio.h>
#include <conio.h>

inline char toupper( char a )
{
    return ((a >= 'a' && a <= 'z') ? a-('a'-'A') : a );
}

int main()
{
    char ch = toupper( _getch() );
    printf( "%c", ch );

    return 0;
}


  When to Use Inline Functions

Inline functions are best used for small functions such as those used to access private data members. The main purpose of these one- or two-line "accessor" functions is to return state information about objects; short functions are sensitive to the overhead of function calls. Longer functions spend proportionately less time in the calling/returning sequence and benefit less from inlining.

The Point class, introduced in »Function-Call Results« in Chapter 4 can be optimized as follows:

class Point
{
public:
    // Define "accessor" functions as
    //  reference types.
    unsigned& x();
    unsigned& y();
private:
    unsigned _x;
    unsigned _y;
};

inline unsigned& Point::x()
{
    return _x;
}

inline unsigned& Point::y()
{
    return _y;
}

Assuming coordinate manipulation is a relatively common operation in a client of such a class, specifying the two accessor functions (x and y in the preceding example) as inline typically saves the overhead of these procedures:

•	Function calls (including parameter passing and placing the object's address on the stack)

•	Preservation of caller's stack frame

•	New stack-frame setup

•	Return-value communication

•	Old stack-frame restore

•	Return


  virtual Specifier

The virtual keyword can be applied only to nonstatic class member functions. It signifies that binding of calls to the function is deferred until run time. Virtual functions are covered in their own section, »Virtual Functions« in Chapter 9.


  typedef Specifier

The typedef specifier is used to define a name that can be used as a synonym for a type or derived type. You cannot use the typedef specifier inside a function definition.

Syntax

typedef-name:
identifier

A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.

One use of typedef declarations is to make declarations more uniform and compact. For example:

typedef char CHAR;          // Character type.
typedef CHAR * PSTR;        // Pointer to a string (char *).
typedef CHAR __far * LPSTR  // Far pointer to a string.
typedef CHAR __near * NPSTR // Near pointer to a string.
...
LPSTR _fstrchr( LPSTR source, CHAR target );

The names introduced by the above declarations are synonyms for the following types:

Name	Synonymous Type
CHAR	char
PSTR	char *
LPSTR	char __far *
NPSTR	char __near *
The preceding example code declares a type name, CHAR. The CHAR type name is then used to define these derived type names: PSTR (a pointer to a string), LPSTR (a far pointer to a string), and NPSTR (a near pointer to a string). Finally, the names are used in declaring the function _fstrchr. To see how the typedef keyword can be used to clarify declarations, contrast the above declaration of _fstrchr with the following declaration:

char __far * _fstrchr( char __far * source, char target );

To use typedef to specify fundamental and derived types in the same declaration, you can separate declarators with commas. For example:

typedef char CHAR, *PSTR,
      __far *LPSTR, __near *NPSTR;

A particularly complicated use of typedef is to define a synonym for a "pointer to a function that returns type T." For example, a typedef declaration that means "pointer to a function that takes no arguments and returns type void" uses this code:

typedef void (*PVFN)();

The synonym can be handy in declaring arrays of functions that are to be invoked through a pointer:

#include <iostream.h>
#include <stdlib.h>

extern void func1();         // Declare 4 functions.
extern void func2();         // These functions are assumed to be
extern void func3();         //  defined elsewhere.
extern void func4();
                             // Declare synonym for pointer to
typedef void (*PVFN)();      //  function that takes no arguments
                             //  and returns type void.

int main( int argc, char * argv[] )
{
    // Declare an array of pointers to functions.
    PVFN pvfn1[] = { func1, func2, func3, func4 };

    // Invoke the function specified on the command line.
    if( argc > 0 && *argv[1] > '0' && *argv[1] <= '4' )
(*pvfn1[atoi( argv[1] ) - 1])();

    return 0;
}


  Redeclaration of typedef Names

The typedef declaration can be used to redeclare the same name to refer to the same type. For example:

// FILE1.H
typedef char CHAR;

// FILE2.H
typedef char CHAR;

// PROG.CPP
#include "file1.h"
#include "file2.h"   // OK
...

The program PROG.CPP includes two header files, both of which contain typedef declarations for the name CHAR. As long as both declarations refer to the same type, such redeclaration is acceptable.

A typedef cannot redefine a name that was previously declared as a different type. Therefore, if FILE2.H contains

// FILE2.H
typedef int CHAR;     // Error

the compiler issues an error because of the attempt to redeclare the name CHAR to refer to a different type. This extends to constructs such as:

typedef char CHAR;
typedef CHAR CHAR;      // OK: redeclared as same type

typedef union REGS      // OK: name REGS redeclared
{                       //  by typedef name with the
    struct wordregs x;  //  same meaning.
    struct byteregs h;
} REGS;


  Use of typedef with Class Types

Use of the typedef specifier with class types is supported largely because of the ANSI C practice of declaring unnamed structures in typedef declarations. For example, many C programmers use the following coding practice:

typedef struct    // Declare an unnamed structure and give it the
{                 //  typedef name POINT.
    unsigned x;
    unsigned y;
} POINT;

The advantage of such a declaration to the C programmer is that it enables declarations like:

POINT ptOrigin;

instead of:

struct point_t ptOrigin;

In C++, the difference between typedef names and real types (declared with the class, struct, union, and enum keywords) is more distinct. Although the C practice of declaring a nameless structure in a typedef statement still works, it provides no notational benefits as it does in C.

In the following code, the POINT function is not a type constructor. It is interpreted as a function declarator with an int return type.

typedef struct
{
    POINT();         // Not a constructor.
    unsigned x;
    unsigned y;
} POINT;

The above example declares a class named POINT using the unnamed class typedef syntax. POINT is treated as a class name; however, the following restrictions apply to names introduced this way:

•	The name (the synonym) cannot appear after a class, struct, or union prefix.

•	The name cannot be used as constructor or destructor names within a class declaration.

In summary, this syntax does not provide any mechanism for inheritance, construction, or destruction.


  Name Space of typedef Names

Names declared using typedef occupy the same name space as other identifiers (except statement labels). Therefore, they cannot use the same identifier as a previously declared name, except in the case of a class-type declaration. Consider the following example:

typedef unsigned long UL;   // Declare a typedef name, UL.
int UL;                     // Error: redefined.

The name-hiding rules that pertain to other identifiers also govern the visibility of names declared using typedef. Therefore, the following example is legal in C++:

typedef unsigned long UL;   // Declare a typedef name, UL.
...
long Beep
{
    unsigned int UL;        // Redeclaration hides typedef name.
    ...
}
// typedef name "unhidden" here.


  friend Specifier

The friend specifier is used to designate functions or classes that have the same access privileges as class member functions. Friend functions and classes are covered in detail in »Friends« in Chapter 10.


  Type Specifiers

Type specifiers determine the type of the name being declared.

Syntax

type-specifier:
simple-type-name
class-specifier
enum-specifier
elaborated-type-specifier
::  class-name
const
volatile

This section discusses simple type names, elaborated type specifiers, and nested type names.


  Simple Type Names

A simple type name is the name of a complete type.

Syntax

simple-type-name:
complete-class-name
qualified-type-name
char
short
int
long
signed
unsigned
float
double
void

Table 6.2 shows how the simple type names can be used together.

Table 6.2    Type Name Combinations

Type	Can Appear With	Comments
int	long or short, but not both	Type int can be used alone, in which case it means short int in 16-bit compilations and long int in 32-bit compilations.
long	int or double	Type long implies type long int.
short	int	Type short implies type short int.
signed	char, short, int, or long	Type signed implies signed int. The most-significant bit of objects of type signed char and bit fields of signed integral types is taken to be the sign bit.
unsigned	char, short, int, or long	Type unsigned implies unsigned int. The most-significant bit of objects of type unsigned char and bit fields of unsigned integral types is not treated as the sign bit.


  Elaborated Type Specifiers

Elaborated type specifiers are used to declare user-defined types. These can be either class- or enumerated-types.

Syntax

elaborated-type-specifier:
class-key  class-name
class-key  identifier
enum  enum-name

class-key:
class
struct
union

If identifier is specified, it is taken to be a class name. For example:

class Window;

The preceding statement declares the Window identifier as a class name. This syntax is used for forward declaration of classes. For more information about class names, see »Class Names« in Chapter 8.

If a name is declared using the union keyword, it must be defined using the union keyword as well. Names that are defined using the class keyword can be declared using the struct keyword (and vice versa). Therefore, the following code samples are legal:

// Legal example 1
struct A;    // Forward declaration of A.

class A      // Define A.
{
public:
    int i;
};

// Legal example 2
class A;     // Forward declaration of A.

struct A     // Define A.
{
private:
    int i;
};

// Legal example 3
union A;      // Forward declaration of A.

union A       // Define A.
{
    int  i;
    char ch[2];
};

These examples, however, are illegal:

// Illegal example 1
union A;      // Forward declaration of A.

struct A      // Define A.
{
    int i;
};

// Illegal example 2
union A;      // Forward declaration of A.

class A       // Define A.
{
public:
    int i;
};
// Illegal example 3
struct A;     // Forward declaration of A.

union A       // Define A.
{
    int  i;
    char ch[2];
};


  Nested Type Names

Microsoft C++ supports declaration of nested types — both named and anonymous.

Syntax

qualified-type-name:
typedef-name
class-name  ::  qualified-type-name

complete-class-name:
qualified-class-name
::  qualified-class-name

qualified-class-name:
class-name
class-name  ::  qualified-class-name

In some programming situations, it makes sense to define nested types. These types are visible only to member functions of the class type in which they are defined. They can also be made visible by constructing a qualified type name using the scope-resolution operator (::).

Note  One commonly used class hierarchy that employs nested types is iostream. In the iostream header files, the definition of class ios includes a series of enumerated types, which are packaged for use only with the iostream library.

The following is an example of how to define nested classes:

class WinSystem
{
public:
    class Window
    {
    public:
        Window();         // Default constructor.
        ~Window();        // Destructor.
        int NumberOf();   // Number of objects of class.
        int Count();      // Count number of objects of class.
    private:
        static int CCount;
    };
    class CommPort
    {
    public:
        CommPort();       // Default constructor.
        ~CommPort();      // Destructor.
        int NumberOf();   // Number of objects of class.
        int Count();      // Count number of objects of class.
    private:
        static int CCount;
    };
};

// Initialize WinSystem static members.
int WinSystem::Window::CCount = 0;
int WinSystem::CommPort::CCount = 0;

To access a name defined in a nested class, use the scope-resolution operator (::) to construct a complete class name. Use of this operator is shown in the initializations of the static members in the example above. To use a nested class in your program, use code such as the following:

WinSystem::Window Desktop;
WinSystem::Window AppWindow;

cout << "Number of active windows: " << Desktop.Count() << "\n";

Nested anonymous classes or structures can be defined as follows:

class Ledger
{
    class
    {
    public:
        double   PayableAmt;
        unsigned PayableDays;
    } Payables;

    class
    {
    public:
        double   RecvableAmt;
        unsigned RecvableDays;
    } Receivables;
};

An anonymous class must be an aggregate that has no member functions and no static members.

Note  Although an enumerated type can be defined inside a class declaration, the reverse is not true; class types cannot be defined inside enumeration declarations.


  6.2  Enumeration Declarations

An enumeration is a distinct integral type that defines named constants. Enumerations are declared using the enum keyword.

Syntax

enum-name:
identifier

enum-specifier:
enum identifier (opt )  {  enum-list (opt)   }

enum-list:
enumerator
enum-list , enumerator

enumerator:
identifier
identifier =  constant-expression

Enumerated types are valuable when an object can assume a known and reasonably limited set of values. Consider the example of the suits from a deck of cards:

class Card
{
public:
    enum Suit
    {
        Diamonds,
        Hearts,
        Clubs,
        Spades
    };
    // Declare two constructors: a default constructor,
    //  and a constructor that sets the cardinal and
    //  suit value of the new card.
    Card();
    Card( int CardInit, Suit SuitInit );

    // Get and Set functions.
    int   GetCardinal();    // Get cardinal value of card.
    int   SetCardinal();    // Set cardinal value of card.
    Suit  GetSuit();        // Get suit of card.
    Suit  SetSuit();        // Set suit of card.
    char *NameOf();         // Get string representation of card.
private:
    Suit  suit;
    int   cardinalValue;
};

// Define a postfix increment operator for Suit.
inline Card::Suit operator++( Card::Suit &rs, int )
{
    return rs = (Card::Suit)(rs + 1);
}

The preceding example defines a class, Card, that contains a nested enumerated type, Suit. To create a pack of cards in a program, use code such as the following:

Card *Deck[52];
int   j = 0;

for( Card::Suit curSuit = Card::Diamonds; curSuit <= Card::Spades;
     curSuit++ )
    for( int i = 1; i <= 13; ++i )
        Deck[j++] = new Card( i, curSuit );

In the preceding example, the type Suit is nested; therefore, the class name (Card) must be used explicitly in public references. In member functions, however, the class name can be omitted.

In the first segment of code, the postfix increment operator for Card::Suit is defined. Without a user-defined increment operator, curSuit could not be incremented. For more information about user-defined operators, see »Overloaded Operators« in Chapter 12.

Consider the code for the NameOf member function (a better implementation is presented later):

char* Card::NameOf() // Get the name of a card.
{
    static char szName[20];
    static char *Numbers[] =
    { "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
    };
    static char *Suits[] =
    { "Diamonds", "Hearts", "Clubs", "Spades" };

    if( GetCardinal() < 13)
        strcpy( szName, Numbers[GetCardinal()] );

    strcat( szName, " of " );

    switch( GetSuit() )
    {
    // Diamonds, Hearts, Clubs, and Spades do not need explicit
    //  class qualifier.
    case Diamonds: strcat( szName, "Diamonds" ); break;
    case Hearts:   strcat( szName, "Hearts" );   break;
    case Clubs:    strcat( szName, "Clubs" );    break;
    case Spades:   strcat( szName, "Spades" );   break;
    }

    return szName;
}

An enumerated type is an integral type. The identifiers introduced with the enum declaration can be used wherever constants appear. Normally, the first identifier's value is 0 (Diamonds, in the example above), and the values increase by one for each succeeding identifier. Therefore, the value of Spades is 3.

Any enumerator in the list, including the first one, can be initialized to a value other than its default value. Suppose the declaration of Suit had been the following:

enum Suit
{
    Diamonds = 5,
    Hearts,
    Clubs = 4,
    Spades
};

Then the values of Diamonds, Hearts, Clubs, and Spades would have been 5, 6, 4, and 5, respectively. Note that 5 is used more than once.

The default values for these enumerators make implementation of the NameOf function simpler:

char* Card::NameOf() // Get the name of a card.
{
    static char szName[20];
    static char *Numbers[] =
    { "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
    };
    static char *Suits[] =
    { "Diamonds", "Hearts", "Clubs", "Spades"};

    if( GetCardinal() < 13)
        strcpy( szName, Numbers[GetCardinal()] );

    strcat( szName, " of " );

    strcat( szName, Suits[GetSuit()] );

    return szName;
}

The accessor function GetSuit returns type Suit, an enumerated type. Because enumerated types are integral types, they can be used as arguments to the array subscript operator. (For more information, see »Subscript Operator« in Chapter 4.)


  Enumerator Names

The names of enumerators must be different from any other enumerator or variable in the same scope. However, the values (as shown above) can be duplicated.


  Definition of Enumerator Constants

Enumerators are considered defined immediately after their initializers; therefore, they can be used to initialize succeeding enumerators. The following example defines an enumerated type that ensures that any two enumerators can be combined with the OR operator:

enum FileOpenFlags
{
    OpenReadOnly  = 1,
    OpenReadWrite = OpenReadOnly  << 1,
    OpenBinary    = OpenReadWrite << 1,
    OpenText      = OpenBinary    << 1,
    OpenShareable = OpenText      << 1
};

In the preceding example, the preceding enumerator is used to initialize each succeeding enumerator.


  Conversions and Enumerated Types

Because enumerated types are integral types, any enumerator can be converted to another integral type by integral promotion. Consider this example:

enum Days
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

int  i;
Days d = Thursday;

i = d;    // Converted by integral promotion.
cout << "i = " << i << "\n";

However, there is no implicit conversion from any integral type to an enumerated type. Therefore (continuing with the preceding example), the following statement is in error:

d = 6;    // Erroneous attempt to set d to Saturday.

Assignments such as the one above, where no implicit conversion exists, must use a cast to perform the conversion:

d = (Days)6;    // Explicit cast-style conversion to type Days.
d = Days( 4 );  // Explicit function-style conversion to type Days.

The example above shows conversions of values that coincide with the enumerators. There is no mechanism that protects you from converting a value that does not coincide with one of the enumerators. For example:

d = Days( 967 );

Some such conversions may work. However, there is no guarantee that the resultant value will be one of the enumerators. Additionally, if the size of the enumerator is too small to hold the value being converted, the value stored may not be what you expect.


  6.3  Linkage Specifications

The term "linkage specification" refers to the protocol for linking functions (or procedures) written in different languages. The following calling conventions are affected:

•	Case sensitivity of names.

•	Decoration of names. In C, the compiler prefixes names with an underscore. This is often called "decoration." In C++, name decoration is used to retain type information through the linkage phase. (For more information, see Appendix A of the Preprocessor Reference and »Appendix C, Decorated Names,« in this book.)

•	Order in which arguments are expected on the stack.

•	Responsibility for adjusting the stack on function return. Either the called function or the calling function is responsible.

•	Passing of hidden arguments (whether any hidden arguments are passed).

Syntax

linkage-specification:
extern string-literal {  declaration-list (opt)   }
extern  string-literal declaration

declaration-list:
declaration
declaration-list

Linkage specification facilitates gradually porting C code to C++ by allowing the use of existing code.

Microsoft Specific

The only linkage specifications currently supported by Microsoft C++ are "C" and "C++". ♦

The following example declares the functions atoi and atol with C linkage:

extern "C"
{
    int  atoi( char *string );
    long atol( char *string );
}

Calls to these functions are made using C linkage. The same result could be achieved with these two declarations:

extern "C" int  atoi( char *string );
extern "C" long atol( char *string );

Microsoft Specific

All Microsoft C standard include files use conditional compilation directives to detect C++ compilation. When a C++ compilation is detected, the prototypes are enclosed in an extern "C" directive as follows:

// Sample.h
#if defined(__cplusplus)
extern "C"
{
#endif

// Function declarations

#if defined(__cplusplus)
}
#endif   ♦

There is no need for you to declare the functions in the standard include files as extern "C".

If a function is overloaded, no more than one of the functions of the same name can have a linkage specifier. (For more information, see »Function Overloading« in Chapter 7.)

Table 6.3 shows how various linkage specifications work.

Table 6.3    Effects of Linkage Specifications

Specification	Effect
On an object	Affects linkage of that object only
On a function	Affects linkage of that function and all functions or objects declared within it
On a class	Affects linkage of all nonmember functions and objects declared within the class
If a function has more than one linkage specification, they must agree; it is an error to declare functions as having both C and C++ linkage. Furthermore, if two declarations for a function occur in a program — one with a linkage specification and one without — the declaration with the linkage specification must be first. Any redundant declarations of functions that already have linkage specification are given the linkage specified in the first declaration. For example:

extern "C" int CFunc1();
...
int CFunc1();            // Redeclaration is benign; C linkage is
                         //  retained.

int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
                         //  CFunc2;  cannot contain linkage
                         //  specifier.

Functions and objects explicitly declared as static within the body of a compound linkage specifier ({ }) are treated as static functions or objects; the linkage specifier is ignored. Other functions and objects behave as if declared using the extern keyword. (See »Storage-Class Specifiers« for details about the extern keyword.)


Chapter 7: Declarators
  Chapter 7  Declarators

A "declarator" is the part of a declaration that names an object, type, or function. Declarators appear in a declaration as one or more names separated by commas; each name can have an associated initializer.

Syntax

declarator-list:
init-declarator
declarator-list  ,  init-declarator

init-declarator:
declarator initializer (opt)


  7.1  Overview

Declarators are the components of a declaration that specify names. Declarators can also modify basic type information to cause names to be functions or pointers to objects or functions. (Specifiers, discussed in »Chapter 6, Declarations,«convey properties such as type and storage class. Modifiers, discussed in this chapter and in »Appendix B, Microsoft-Specific Modifiers,« modify declarators.) »Figure 7.1« shows a complete declaration of two names, szBuf and strcpy, and calls out the components of the declaration.

Microsoft Specific

Most Microsoft extended keywords can be used as modifiers to form derived types; they are not specifiers or declarators. (See »Appendix B, Microsoft-Specific Modifiers.«) ♦

Syntax

declarator:
dname
ptr-operator  declarator
declarator  (  argument-declaration-list  ) cv-mod-list
declarator  [  constant-expression (opt)   ]
(  declarator  )

ptr-operator:
*  cv-qualifier-list (opt)
&  cv-qualifier-list (opt)
complete-class-name  ::  *  cv-qualifier-list (opt)

cv-qualifier-list:
cv-qualifier  cv-qualifier-list (opt)

cv-qualifier:
const
volatile

cv-mod-list:
cv-qualifier cv-mod-list (opt
) 	pmodel cv-mod-list (opt)

pmodel: one of  // 16-Bit Specific; Microsoft Specific
__near
__far
__huge

dname:
name
class-name
~ class-name
typedef-name
qualified-type-name

Declarators appear in the declaration syntax after an optional list of specifiers (decl-specifiers). These specifiers are discussed in »Chapter 6, Declarations.« A declaration can contain more than one declarator, but each declarator declares only one name. The following sample declaration shows how specifiers and declarators are combined to form a complete declaration:

const char *pch, ch;

In the above declaration, the keywords const and char make up the list of specifiers. Two declarators are listed: *pch and ch. The simplified syntax of a declaration, then, is the following, where const char is the type and *pch and ch are the declarators:

type  declarator (1) [, declarator (2) [...,declarator (n) ] ] ;

When the binding of elements in a declarator list does not yield the desired result, you can use parentheses for clarification. A better technique, however, is to use a typedef or a combination of parentheses and the typedef keyword. Consider declaring an array of pointers to functions. Each function must obey the same protocol so that the arguments and return values are known:

//  Function returning type int that takes one
//   argument of type char *.
typedef int (*PIFN)( char * );

//  Declare an array of 7 pointers to functions
//   returning int and taking one argument of type
//   char *.
PIFN pifnDispatchArray[7];

The equivalent declaration can be written without the typedef declaration, but it is so complicated that the potential for error exceeds any benefits:

int ( *pifnDispatchArray[7] )( char * );


  7.2  Type Names

Type names are used in some declarators in the following ways:

•	In explicit conversions

•	As arguments to the sizeof operator

•	As arguments to the new operator

•	In function prototypes

•	In typedef statements

A type name consists of type specifiers, covered in »Chapter 6, Declarations,« and abstract declarators, discussed in the next »section«.

In the following example, the arguments to the function strcpy are supplied using their type names. In the case of the source argument, const char is the specifier and * is the abstract declarator:

static char __far *szBuf, *strcpy( char *dest, const char *source );

Syntax

type-name:
type-specifier-list abstract-declarator (opt)

type-specifier-list:
type-specifier type-specifier-list  (opt)

abstract-declarator:
ptr-operator abstract-declarator (opt)
abstract-declarator (opt )  (  argument-declaration-list  )  cv-qualifier-list (opt)
abstract-declarator (opt)   [  constant-expression (opt)  ]
(  abstract-declarator  )


  7.3  Abstract Declarators

An abstract declarator is a declarator in which the identifier is omitted. (For related information, see »Type Names«.)

The following abstract declarators are discussed in this section:

•	Pointers

•	References

•	Pointers to members

•	Arrays

•	Functions

•	Default arguments

An abstract declarator is a declarator that does not declare a name — the identifier is left out. For example,

char *

declares the type "pointer to type char." This abstract declarator can be used in a function prototype as follows:

char *strcmp( char *, char * );

In the above prototype (declaration), the function's arguments are specified as abstract declarators. The following is a more complicated abstract declarator that declares the type "pointer to a function that takes two arguments, both of type char *," and returns type char *:

char * (*)( char *, char * )

Since abstract declarators completely declare a type, it is legal to form expressions of the form:

// Get the size of array of 10 pointers to type char.
size_t nSize = sizeof( char *[10] );

// Allocate a pointer to a function that has no
//  return value and takes no arguments.
typedef void (PVFN *)();
PVFN *pvfn = new PVFN;

// Allocate an array of pointers to functions that
//  return type WinStatus, and take one argument of
//  type WinHandle.
typedef WinStatus (PWSWHFN *)( WinHandle );
PWSWHFN pwswhfnArray[] = new PWSWHFN[10];


  Ambiguity Resolution

To perform explicit conversions from one type to another, you must use casts, specifying the desired type name. Some type casts result in syntactic ambiguity. The following function-style type cast is ambiguous:

char *aName( String( s ) );

It is unclear whether it is a function declaration or an object declaration with a function-style cast as the initializer: Does the above statement declare a function returning type char * that takes one argument of type String, or does it declare the object aName and initialize it with the value of s cast to type String?

The rule in this case is that if a syntactic construct can be considered a valid function declaration, it is treated as such. Only if it cannot possibly be a function declaration — that is, if it would be syntactically incorrect — is a statement examined to see if it is a function-style type cast. Therefore, the compiler considers the statement to be a declaration of a function and treats the parentheses around the identifier s as gratuitous. On the other hand, the statements:

char *aName( (String)s );

and

char *aName = String( s );

are clearly declarations of objects, and a user-defined conversion from type String to type char * is invoked to perform the initialization of aName.


  Pointers

Pointers are declared using the declarator syntax:

*  cv-qualifier-list (opt ) dname

A pointer is a 16-bit or 32-bit quantity that holds the address of an object. The full declaration, then, is:

decl-specifiers * cv-qualifier-list (opt)  dname ;

A simple example of such a declaration is:

char *pch;

The preceding declaration specifies that pch points to an object of type char.


  const and volatile Pointers

The const and volatile keywords change how pointers are treated. The const keyword specifies that the pointer cannot be modified after initialization; the pointer is protected from modification thereafter.

The volatile keyword specifies that the value associated with the name that follows can be modified by actions other than those in the user application. Therefore, the volatile keyword is useful for declaring objects in shared memory that can be accessed by multiple processes or global data areas used for communication with interrupt service routines.

When a name is declared as volatile, the compiler reloads the value from memory each time it is accessed by the program. This dramatically reduces the possible optimizations. However, when the state of an object can change unexpectedly, it is the only way to ensure predictable program performance.

To declare the object pointed to by the pointer as const or volatile, use a declaration of the form:

const    char *cpch;
volatile char *vpch;

To declare the value of the pointer  —  that is, the actual address stored in the pointer —  as const or volatile, use a declaration of the form:

char * const    pchc;
char * volatile pchv;

The C++ language prevents assignments that would allow an object or pointer declared as const to be modified. Such assignments would remove the information that the object or pointer was declared with, thereby violating the intent of the original declaration. Consider the following declarations:

const char cch = 'A';
char        ch = 'B';

Given the above declarations of two objects (cch, of type const char, and ch, of type char), the following declaration/initializations are valid:

const char        *pch1 = &cch;
const char *const  pch4 = &cch;
const char        *pch5 = &ch;
char              *pch6 = &ch;
char       *const  pch7 = &ch;
const char *const  pch8 = &ch;

The following declaration/initializations are erroneous.

char *pch2 = &cch;        // Error
char *const pch3 = &cch;  // Error

The declaration of pch2 declares a pointer through which a constant object might be modified and is therefore disallowed. The declaration of pch3 specifies that the pointer is constant, not the object; the declaration is disallowed for the same reason the pch2 declaration is disallowed.

The following eight assignments show assigning through pointer and changing of pointer value for the above declarations; for the purposes of this discussion, assume that the initialization had been correct for pch1 through pch8.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

Pointers declared as volatile or as a mixture of const and volatile obey the same rules.

Pointers to const objects are often used in function declarations as follows:

char *strcpy( char *szTarget, const char *szSource );

The preceding statement declares a function, strcpy, that takes two arguments of type "pointer to char" and returns a pointer to type char. Because the arguments are passed by reference and not by value, the function would be free to modify both szTarget and szSource if szSource were not declared as const. The declaration of szSource as const assures the caller that szSource cannot be changed by the called function.

Note  Because there is a standard conversion from typename * to const typename *, it is legal to pass an argument of type char * to strcpy. However, the reverse is not true; no implicit conversion exists to remove the const attribute from an object or pointer.

A const pointer of a given type can be assigned to a pointer of the same type. However, a pointer that is not const cannot be assigned to a const pointer. The following code shows correct and incorrect assignments:

int *const cpObject = 0;
int *pObject;

int main()
{
    pObject = cpObject; // OK
    cpObject = pObject; // Error

    return 0;
}


  References

References are declared using the declarator syntax:

Syntax

&  cv-qualifier-list (opt)  dname

A reference is a 16-bit or 32-bit quantity that holds the address of an object but behaves syntactically like an object. A reference declaration consists of an (optional) list of specifiers followed by a reference declarator.

Syntax

decl-specifiers & cv-qualifier-list (opt ) dname ;

Consider the user-defined type Date:

struct Date
{
    short DayOfWeek;
    short Month;

    short Day;
    short Year;
};

The following statements declare an object of type Date and a reference to that object:

Date  Today;             // Declare the object.
Date& TodayRef = Today;  // Declare the reference.

Both the name of the object, Today, and the reference to the object, TodayRef, can be used identically in programs:

Today.DayOfWeek = 3;   // Tuesday
TodayRef.Month  = 7;   // July


  Reference-Type Function Arguments

When passing large objects to functions, it is often more efficient to pass references to these objects instead. This allows the compiler to pass the address of the object while maintaining the syntax that would have been used to access the object. Consider the following example that uses the Date structure:

// Create a Julian date of the form DDDYYYY
// from a Gregorian date.
long JulianFromGregorian( Date& GDate )
{
    static int cDaysInMonth[] = {
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    long JDate;

    // Add in days for months already elapsed.
    for( int i = 0; i < GDate.Month - 1; ++i )
        JDate += cDaysInMonth[i];

    // Add in days for this month.
    JDate += GDate.Day;

    // Check for leap year.
    if( GDate.Year % 100 != 0 && GDate.Year % 4 != 0 )
        JDate++;

    // Add in year.
    JDate *= 10000;
    JDate += GDate.Year;

    return JDate;
}

The preceding code illustrates the fact that members of a structure passed by reference are accessed using the member-selection operator (.) instead of the pointer member-selection operator (−>).

Although arguments passed as reference types observe the syntax of nonpointer types, they retain one important characteristic of pointer types: they are modifiable unless declared as const. Because the intent of the above code is not to modify the object GDate, a more appropriate function prototype is:

long JulianFromGregorian( const Date& GDate );

This prototype guarantees that the function JulianFromGregorian will not change its argument.

Note that any function prototyped as taking a reference type can accept an object of the same type in its place because there is a standard conversion from typename to typename&.


  Reference-Type Function Returns

Functions can be declared to return a reference type. There are two reasons to make such a declaration:

•	The information being returned is a large enough object that returning a reference is more efficient than returning a copy.

•	The type of the function must be an l-value.

Just as it can be more efficient to pass large objects to functions by reference, it also can be more efficient to return large objects from functions by reference. Reference-return protocol eliminates the necessity of copying the object to a temporary location prior to returning.

Another case in which reference-return types can be useful is when the function must evaluate to an l-value. Most overloaded operators fall into this category, particularly the assignment operator. Overloaded operators are covered in »Overloaded Operators« in Chapter 12. Consider the Point example from Chapter 4:

class Point
{
public:
    // Define "accessor" functions as
    //  reference types.
    unsigned& x();
    unsigned& y();
private:
    unsigned obj_x;
    unsigned obj_y;
};

unsigned& Point :: x()
{
    return obj_x;
}
unsigned& Point :: y()
{
    return obj_y;
}

void main()
{
    Point ThePoint;

    // Use x() and y() as l-values.
    ThePoint.x() = 7;
    ThePoint.y() = 9;

    // Use x() and y() as r-values.
    cout << "x = " << ThePoint.x() << "\n"
         << "y = " << ThePoint.y() << "\n";
}

Notice that the functions x and y are declared as returning reference types. These functions can be used on either side of an assignment statement.

Declarations of reference types must contain initializers except in the following cases:

•	Explicit extern declaration

•	Declaration of a class member

•	Declaration within a class

•	Declaration of an argument to a function or the return type for a function


  References to Pointers

References to pointers can be declared in much the same way as references to objects. Declaring a reference to a pointer yields a modifiable value that is used like a normal pointer. The following code samples illustrate the difference between using a pointer to a pointer and a reference to a pointer:

#include <iostream.h>
#include <string.h>

// Define a binary tree structure.
struct BTree
{
    char  *szText;
    BTree *Left;
    BTree *Right;
};

// Define a pointer to the root of the tree.
BTree *btRoot = 0;

int Add1( BTree **Root, char *szToAdd );
int Add2( BTree*& Root, char *szToAdd );
void PrintTree( BTree* btRoot );

main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
        cerr << "Usage: Refptr [1 | 2]" << "\n";
        cerr << "\n\twhere:\n";
        cerr << "\t1 uses double indirection\n";
        cerr << "\t2 uses a reference to a pointer.\n";
        cerr << "\n\tInput is from stdin.\n";
        return 1;
    }

    char *szBuf = new char[132];

    // Read a text file from the standard input device and
    //  build a binary tree.
    while( !cin.eof() )
    {
        cin.get( szBuf, 132, '\n' );
        cin.get();
        if( strlen( szBuf ) )
            switch( *argv[1] )
            {
            // Method 1: Use double indirection.
            case '1':
                Add1( &btRoot, szBuf );
                break;

            // Method 2: Use reference to a pointer.
            case '2':
                Add2( btRoot, szBuf );
                break;

            default:
                cerr << "Illegal value '" << *argv[1]
                     << "' supplied for add method.\n"
                     << "Choose 1 or 2.\n";
                return -1;
            }
    }

    // Display the sorted list.
    PrintTree( btRoot );
    return 0;
}

// PrintTree: Display the binary tree in order.
void PrintTree( BTree* btRoot )
{
    // Traverse the left branch of the tree recursively.
    if( btRoot->Left )
        PrintTree( btRoot->Left );

    // Print the current node.
    cout << btRoot->szText << "\n";

    // Traverse the right branch of the tree recursively.
    if( btRoot->Right )
        PrintTree( btRoot->Right );
}

// Add1: Add a node to the binary tree.
//       Uses double indirection.
int Add1( BTree **Root, char *szToAdd )
{
    if( (*Root) == 0 )
    {
        (*Root) = new BTree;
        (*Root)->Left = 0;
        (*Root)->Right = 0;
        (*Root)->szText = new char[strlen( szToAdd ) + 1];
        strcpy( (*Root)->szText, szToAdd );
        return 1;
    }

    else if( strcmp( (*Root)->szText, szToAdd ) > 0 )
        return Add1( &((*Root)->Left), szToAdd );
    else
        return Add1( &((*Root)->Right), szToAdd );
}

// Add2: Add a node to the binary tree.
//       Uses reference to pointer

int Add2( BTree*& Root, char *szToAdd )
{
    if( Root == 0 )
    {
        Root = new BTree;
        Root->Left = 0;
        Root->Right = 0;
        Root->szText = new char[strlen( szToAdd ) + 1];
        strcpy( Root->szText, szToAdd );
        return 1;
    }
    else if( strcmp( Root->szText, szToAdd ) > 0 )
        return Add2( Root->Left, szToAdd );
    else
        return Add2( Root->Right, szToAdd );
}

In the preceding program, functions Add1 and Add2 are functionally equivalent (although they are not called the same way). The difference is that Add1 uses double indirection whereas Add2 uses the convenience of a reference to a pointer.


  Pointers to Members

Declarations of pointers to members are special cases of pointer declarations.

Syntax

decl-specifiers  class-name  ::  *  cv-qualifier-list (opt)   dname  ;

A pointer to a member of a class differs from a normal pointer because it has type information for not only the type of the member but also the class to which the member belongs. This is in contrast to a normal pointer, which identifies (has the address of) a single object in memory. A pointer to a member of a class identifies that member in any instance of the class. The following example declares a class, Window, and then some pointers to member data.

class Window
{
public:
    Window();                               // Default constructor.
    Window( int x1, int y1,                 // Constructor specifying
        int x2, int y2 );                   //  window size.

    BOOL SetCaption( const char *szTitle ); // Set window caption.
    const char *GetCaption();               // Get window caption.
    char *szWinCaption;                     // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;

In the preceding example, pwCaption is a pointer to any member of class Window that has type char*. The type of pwCaption is char * Window::*. The next code fragment declares pointers to the SetCaption and GetCaption member functions.

const char * (Window::*pfnwGC)() = &Window::GetCaption;
BOOL (Window::*pfnwSC)( const char * ) = &Window::SetCaption;

The pointers pfnwGC and pfnwSC point to GetCaption and SetCaption of the Window class, respectively. The code copies information to the window caption directly using the pointer to member pwCaption:

Window wMainWindow;
Window *pwChildWindow = new Window;
char   *szUntitled    = "Untitled -  ";
int    cUntitledLen   = strlen( szUntitled );

strcpy( wMainWindow.*pwCaption, szUntitled );
(wMainWindow.*pwCaption)[cUntitledLen - 1] = '1';     //same as
//wMainWindow.SzWinCaption [ ] = '1';
strcpy( pwChildWindow->*pwCaption, szUntitled );
(pwChildWindow->*pwCaption)[szUntitledLen - 1] = '2'; //same as
//pwChildWindow->szWinCaption[ ] = '2';

The difference between the .* and −>* operators (the pointer-to-member operators) is that the .* operator is used to select members given an object or object reference, while the −>* operator is used to select members through a pointer. (For more about these operators, see »Expressions with Pointer-to-Member Operators« in Chapter 4.)

Note that the result of the pointer-to-member operators is the type of the member — in this case, char *.

The following code fragment invokes the member functions GetCaption and SetCaption using pointers to members:

// Allocate a buffer.
char szCaptionBase[100];

// Copy the main window caption into the buffer
//  and append " [View 1]".
strcpy( szCaptionBase, (wMainWindow.*pfnwGC)() );
strcat( szCaptionBase, " [View 1]" );

// Set the child window's caption.
(pwChildWindow->*pfnwSC)( szCaptionBase );


  Restrictions on Pointers to Members

The address of a static member is not a pointer to member. It is a regular pointer to the one instance of the static member. Because only one instance of a static member exists for all objects of a given class, the ordinary address-of (&) and dereference (*) operators can be used.


  Pointers to Members and Virtual Functions

Invoking a virtual function through a pointer-to-member function works exactly as if the function had been called directly: the correct function is looked up in the v-table and invoked. The following code shows how this is done:

class Base
{
public:
    virtual void Print();
};
void (Base ::* bfnPrint)() = &Base :: Print;

void Base :: Print()
{
    cout << "Print function for class 'Base'\n";
}

class Derived : public Base
{
public:
    void Print();  // Print is still a virtual function.
};

void Derived :: Print()
{
    cout << "Print function for class 'Derived'\n";
}

main()
{
    Base   *bPtr;
    Base    bObject;
    Derived dObject;

    bPtr = &bObject;    // Set pointer to address of bObject.
    (bPtr->*bfnPrint)();

    bPtr = &dObject;    // Set pointer to address of dObject.
    (bPtr->*bfnPrint)();

    return 0;
}

The output from this program is:

Print function for class 'Base'
Print function for class 'Derived'

The key to virtual functions working, as always, is invoking them through a pointer to a base class. (For more information about virtual functions, see »Virtual Functions« in Chapter 9.)


  Representing Pointers to Members of Classes Using Inheritance

Declaring a pointer to a member of a class prior to the class definition impacts the size and speed of the resulting executable file. The number of bytes required to represent a pointer to a member of a class and the code required to interpret the representation may depend on whether the class is defined with no, single, multiple, or virtual inheritance.

In general, the more complex the inheritance used by a class, the greater the number of bytes required to represent a pointer to a member of the class and the larger the code required to interpret the pointer.

If you need to declare a pointer to a member of a class prior to defining the class, you must use either the /vmg command-line option or the related pointers_to_members pragma. Or you can specify the inheritance used in the class declaration using the __single_inheritance, __multiple_inheritance, or __virtual_inheritance keywords, thus allowing control of the code generated on a per-class basis. These options are explained below.

Note  If you always declare a pointer to a member of a class after defining the class, you don't need to use any of these options.

Microsoft attempts to optimize the representation and code generated for pointers to members by selecting the most compact representation possible. To do this requires that the class the pointer to member is based upon be defined at the point of declaration of the pointer to member. The pointers_to_members pragma allows you to relax this restriction and to control the pointer size and the code required to interpret the pointer.

Syntax

The syntax is

#pragma pointers_to_members( pointer-declaration, [most-general-
representation] )

The pointer-declaration argument specifies whether you have declared a pointer to a member before or after the associated function definition. The pointer-declaration argument can be either full_generality or best_case.

The most-general-representation argument specifies the smallest pointer representation that the compiler can safely use to reference any pointer to a member of a class in a translation unit. This argument can be single_inheritance, multiple_inheritance, or virtual_inheritance.

The pointers_to_members pragma with the best_case argument is the compiler default. You can use this default if you always define a class before declaring a pointer to a member of the class. When the compiler encounters the declaration of a pointer to a member of a class, it already has knowledge of the kind of inheritance used by the class. Thus, the compiler can use the smallest possible representation of a pointer and generate the smallest amount of code required to operate on the pointer for each kind of inheritance. This is equivalent to using /vmb on the command-line to specify best-case representation for all classes in the compilation unit.

Use the pointers_to_members pragma with the full_generality argument if you ever need to declare a pointer to a member of a class before defining the class. (This need can arise if you define members in two different classes that reference each other using pointers to members. For such mutually referencing classes, one class must be referenced before it is defined.) The compiler uses the most general representation for the pointer to the member. This is equivalent to the /vmg command-line option. If you specify full-generality, you must also specify single-inheritance, multiple-inheritance, or virtual-inheritance. This is equivalent to the /vmg command-line option being used with the /vms, /vmm, or /vmv option. See Chapter 2 of the Build Tools User's Guide for additional information on the /vmx command-line options.

The pointers_to_members pragma with the full_generality, single_inheritance arguments (/vms option with the /vmg option) specifies the most general representation of a pointer to a member of a class to be one that uses either no inheritance or single inheritance. This is the smallest possible representation of a pointer to a member of a class. If the inheritance model of a class definition for which a pointer to a member is declared is multiple or virtual, the compiler generates an error. For example, placing this statement

#pragma pointers_to_members(full_generality, single_inheritance)

before a class definition declares that the class definitions that follow all use only single inheritance. Once specified, the option specified with the pointers_to_members pragma cannot be changed.

The pointers_to_members pragma with the full_generality, multiple_inheritance arguments (/vmm option with the /vmg option) specifies the most general representation of a pointer to a member of a class to be one that uses multiple inheritance. This representation is larger than that required for single inheritance. If the inheritance model of a class definition for which a pointer to a member is declared is virtual, the compiler generates an error.

The pointers_to_members pragma with the full_generality, virtual_inheritance arguments (/vmv option with the /vmg option) specifies the most general representation of a pointer to a member of a class to be one that uses virtual inheritance. In terms of pointer size and the code required to interpret the pointer, this is the most expensive option. This option, however, never causes an error and is the default when the full_generality argument to the #pragma pointers_to_members is specified or when the /vmg command-line option is used.

Syntax

The equivalent language construction uses this syntax:

class-declaration:
class inheritance-type (opt)  class-name;

inheritance-type:
__single_inheritance
__multiple_inheritance
__virtual_inheritance

As shown in this example,

class __single_inheritance S;
int S::*p;

regardless of command-line options or pragmas, pointers to members of class S will use the smallest possible representation.

It is also possible to explicitly give a forward declaration to the pointer-to-member representation of a class that has a forward declaration.

Note  The same forward declaration of a class pointer-to-member representation should occur in every translation unit that declares pointers to members of that class, and the declaration should occur before the pointers to members are declared.


  Arrays

Arrays are collections of like objects. The simplest case of an array is a vector. C++ provides a convenient syntax for declaration of fixed-size arrays:

Syntax

decl-specifiers  dname  [  constant-expression (opt)   ]  ;

The number of elements in the array is given by the constant-expression. The first element in the array is the 0th element, and the last element is the (n-1th) element, where n is the size of the array. The constant-expression must be of an integral type and must be greater than 0. A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft extensions (/Ze) are enabled.

Arrays are derived types and can therefore be constructed from any other derived or fundamental type except functions, references, and void.

Arrays constructed from other arrays are multidimensional arrays. These multidimensional arrays are specified by placing multiple [ constant-expression ] specifications in sequence. For example, consider this declaration:

int i2[5][7];

It specifies an array of type int, conceptually arranged in a two-dimensional matrix of five rows and seven columns, as shown in »Figure 7.2.«

In declarations of multidimensioned arrays that have an initializer-list (as described in »Initializers«), the constant-expression that specifies the bounds for the first dimension can be omitted. For example:

const int cMarkets = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMarkets] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };

The above declaration defines an array that is three rows by four columns. The rows represent factories and the columns represent markets to which the factories ship. The values are the transportation costs from the factories to the markets. The first dimension of the array is left out, but the compiler fills it in by examining the initializer.

The technique of omitting the bounds specification for the first dimension of a multidimensioned array can also be used in function declarations as follows:

#include <float.h>         // Includes DBL_MAX.
#include <iostream.h>

const int    cMkts = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMkts] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };

// Calculate size of unspecified dimension.
const int cFactories = sizeof TransportCosts /
                       sizeof( double[cMkts] );

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts );

main( int argc, char *argv[] )
{
    double MinCost;
    MinCost = FindMinToMkt( *argv[1] - '0', TransportCosts,
                            cFacts );
    cout << "The minimum cost to Market " << argv[1] << " is: "
         << MinCost << "\n";
    return 0;
}

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts )
{
    double MinCost = DBL_MAX;
    for( int i = 0; i < cFacts; ++i )
        MinCost = (MinCost < TransportCosts[i][Mkt]) ?
                   MinCost : TransportCosts[i][Mkt];
    return MinCost;
}

The function FindMinToMkt is written such that adding new factories does not require any code changes, just a recompilation.


  Using Arrays

Individual elements of arrays are accessed using the array subscript operator ([ ]). If a singly dimensioned array is used in an expression with no subscript, the array name evaluates to a pointer to the first element in the array. For example:

char chArray[10];

...

char *pch = chArray;      // Pointer to first element.
char   ch = chArray[0];   // Value of first element.
       ch = chArray[3];   // Value of fourth element.

When using multidimensioned arrays, various combinations are acceptable in expressions. The following example illustrates this:

double multi[4][4][3]; // Declare the array.

double (*p2multi)[3];  // Pointer to two-dimensional array.
double (*p1multi);     // Pointer to four-dimensional array.

cout << multi[3][2][3] << "\n";   // Use three subscripts.
p2multi = multi[3];               // Make p2multi point to
                                  //  fourth "plane" of multi.
p1multi = multi[3][2];            // Make p1multi point to
                                  //  fourth plane, second row
                                  //  of multi.

In the preceding code, multi is a three-dimensional array of type double. The p2multi pointer points to an array of type double of size three, and p1multi is a pointer to an array of type double. The array is used with one, two, and three subscripts in this example. Although it is more common to specify all the subscripts, as in the cout statement, it is sometimes useful to select a specific subset of array elements as shown in the succeeding statements.


  Arrays in Expressions

When an identifier of an array type appears in an expression other than sizeof, address-of (&), or initialization of a reference, it is converted to a pointer to the first array element. For example:

char szError1[] = "Error: Disk drive not ready.";
char *psz = szError1;

The pointer psz points to the first element of the array szError1. Note that arrays, unlike pointers, are not modifiable l-values. Therefore, the following assignment is illegal:

szError1 = psz;


  Interpretation of Subscript Operator

Like other operators, the subscript operator ([ ]) can be redefined by the user. The default behavior of the subscript operator, if not overloaded, is to combine the array name and the subscript using the following method:

*((array-name) + (subscript))

As in all addition that involves pointer types, scaling is performed automatically to adjust for the size of the type. Therefore, the resultant value is not subscript bytes from the origin of array-name; rather, it is the subscriptth element of the array. (For more information about this conversion, see »Additive Operators« in Chapter 4.)

Similarly, for multidimensional arrays, the address is derived using the following method:

 *((array-name) + (subscript (1) * max (2)  * max (3) ...max (n) )
                        + subscript (2 ) * max (3) ...max (n) )
                         . . . + subscript (n) ))


  Indirection on Array Types

Use of the indirection operator (*) on an n-dimensional array type yields an n−1 dimensional array. If n is 1, a scalar (or array element) is yielded.


  Ordering of C++ Arrays

C++ arrays are stored in row-major order. Row-major order means the last subscript varies the fastest.


  Functions

This section explains function declarations. It includes discussions on:

•	Function declaration (prototyping) syntax.

•	Declaration of functions that take a varying number of arguments.

•	Declaration of functions that require no arguments.

•	Overloading of functions (an introduction).

•	Restrictions on function declarations.

•	Specification of argument lists.

•	Default arguments to functions.

Function definition is covered in »Function Definitions«.

Syntax

decl-specifiers  dname  (  argument-declaration-list  )  cv-mod-list (opt)

argument-declaration-list:
arg-declaration-list , ...

arg-declaration-list:
argument-declaration
arg-declaration-list  ,  argument-declaration

argument-declaration:
decl-specifiers  declarator
decl-specifiers  declarator  =  expression
decl-specifiers  abstract-declarator (opt)
decl-specifiers  abstract-declarator (opt)   =  expression

The identifier given by dname has the type "cv-mod-list function, taking argument-declaration-list, and returning type decl-specifiers."

Note that const, volatile, and many of the Microsoft-specific keywords can appear in cv-mod-list and in the declaration of the name. The following example shows two simple function declarations:

char *strchr( char *dest, char *src );
static int atoi( const char *ascnum ) const;

The following syntax explains the details of a function declaration:

Syntax

argument-declaration-list:
arg-declaration-list (opt)   ... (opt)
arg-declaration-list  ,  ...

arg-declaration-list:
argument-declaration
arg-declaration-list  ,  argument-declaration

argument-declaration:
decl-specifiers  declarator
decl-specifiers  declarator  ,  expression
decl-specifiers  abstract-declarator (opt)
decl-specifiers  abstract-declarator (opt)   ,  expression


  Variable Argument Lists

Function declarations in which the last member of argument-declaration-list is the ellipsis (...) can take a variable number of arguments. In these cases, C++ provides type checking only for the explicitly declared arguments. Variable argument lists can be used when it is desirable to make a function so general that even the number and types of arguments can vary. The printf family of functions is an example of functions that use variable argument lists.

To access arguments after those declared, use the macros contained in the standard include file STDARG.H as described in »Functions with Variable Argument Lists«.

Microsoft Specific

Microsoft C++ allows the ellipsis to be specified as an argument if the ellipsis is the first argument and the ellipsis is preceded by a comma. Therefore, the declaration
int Func( int i, ... ); is legal, but int Func( int i ... );
is not. ♦

Declaration of a function that takes a variable number of arguments requires that at least one "placeholder" argument be supplied, even if it is not used. If this place-holder argument is not supplied, there is no way to access the remaining arguments.

When arguments of type char are passed as variable arguments, they are converted to type int. Similarly, when arguments of type float are passed as variable arguments, they are converted to type double. Arguments of other types are subject to the usual integral and floating-point promotions. See »Integral Promotions« in Chapter 3 for more information.


  Declaring Functions That Take No Arguments

A function declared with the single keyword void in argument-declaration-list takes no arguments, as long as the keyword void is the first and only member of argument-declaration list. Arguments of type void elsewhere in argument-declaration-list produce errors. For example:

long GetTickCount( void );            // OK
long GetTickCount( int Reset, void ); // Error
long GetTickCount( void, int Reset ); // Error

In C++, explicitly specifying that a function requires no arguments is the same as declaring a function with no argument-declaration-list. Therefore, the following two statements are identical:

long GetTickCount();
long GetTickCount( void );

Note that, while it is illegal to specify a void argument except as outlined above, types derived from type void (such as pointers to void and arrays of void) can appear anywhere in argument-declaration-list.


  Function Overloading

C++ allows specification of more than one function of the same name in the same scope. These are called "overloaded functions" and are described in detail in Chapter 12, "Overloading." The purpose of overloaded functions is to allow programmers to supply different semantics for a function depending on the types and number of arguments.

For example, a print function that takes a string (or char *) argument performs very different tasks than one that takes an argument of type double. Overloading permits uniform naming and prevents programmers from having to invent names such as print_sz or print_d. Table 7.1 shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.

Table 7.1    Overloading Considerations

Function Declaration Element	Used for Overloading?
Function return type	No
Number of arguments	Yes
Type of arguments	Yes
Presence or absence of ellipsis	Yes
Use of typedef names	No
Unspecified array bounds	No
const or volatile (in cv-mod-list)	Yes
__near (1) ,  __far (1) , or __huge (1)   (in cv-mod-list)	Yes
(1)  Recognized for 16-bit targets only.
Although functions can be distinguished on the basis of return type, they cannot be overloaded on this basis.

The following example illustrates how overloading can be used. Another way to solve the same problem is presented in »Default Arguments«.

#include <iostream.h>
#include <math.h>
#include <stdlib.h>

// Prototype three print functions.
int print( char *s );                  // Print a string.
int print( double dvalue );            // Print a double.
int print( double dvalue, int prec );  // Print a double with a
                                       //  given precision.
main( int argc, char *argv[] )
{
    const double d = 893094.2987;

    if( argc < 2 )
    {
        // These calls to print invoke print( char *s ).
        print( "This program requires one argument." );
        print( "The argument specifies the number of" );
        print( "digits precision for the second number" );
        print( "printed." );
    }

    // Invoke print( double dvalue ).
    print( d );

    // Invoke print( double dvalue, int prec ).
    print( d, atoi( argv[1] ) );

    return 0;
}

// Print a string.
int print( char *s )
{
    cout << s << endl;
    return cout.good();
}

// Print a double in default precision.
int print( double dvalue )
{
    cout << dvalue << endl;
    return cout.good();
}

// Print a double in specified precision.
//  Positive numbers for precision indicate how many digits'
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print( double dvalue, int prec )
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = {
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
        10E1,  10E2,  10E3,  10E4, 10E5,  10E6
    };
    const int iPowZero = 6;

    // If precision out of range, just print the number.
    if( prec < -6 || prec > 7 )
        return print( dvalue );

    // Scale, truncate, then rescale.
    dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
                             rgPow10[iPowZero - prec];

    cout << dvalue << endl;
    return cout.good();
}

The preceding code shows overloading of the print function in file scope.

For restrictions on overloading and information on how overloading affects other elements of C++, see »Chapter 12, Overloading.«


  Restrictions on Functions

Functions cannot return arrays or functions. They can, however, return references or pointers to arrays or functions. Another way to return an array is to declare a structure with only that array as a member:

struct Address
{ char szAddress[31]; };

Address GetAddress();

It is illegal to define a type in either the return-type portion of a function declaration or in the declaration of any argument to a function. The following legal C code is illegal in C++:

enum Weather { Cloudy, Rainy, Sunny } GetWeather( Date Today )

The reason the preceding code is disallowed is because the type Weather has function scope local to GetWeather and the return value cannot be properly used. Because arguments to functions have function scope, declarations made within the argument list would have the same problem if not allowed.

C++ does not support arrays of functions. However, arrays of pointers to functions can be useful. In parsing a Pascal-like language, the code is often separated into a lexical analyzer that parses tokens and a parser that attaches semantics to the tokens. If the analyzer returns a particular ordinal value for each token, code can be written to perform appropriate processing as shown in this example:

int ProcessFORToken( char *szText );
int ProcessWHILEToken( char *szText );
int ProcessBEGINToken( char *szText );
int ProcessENDToken( char *szText );
int ProcessIFToken( char *szText );
int ProcessTHENToken( char *szText );
int ProcessELSEToken( char *szText );
int (*ProcessToken[])( char * ) = {
    ProcessFORToken, ProcessWHILEToken, ProcessBEGINToken,
    ProcessENDToken, ProcessIFToken, ProcessTHENToken,
    ProcessELSEToken };
const int MaxTokenID = sizeof ProcessToken / sizeof( int (*)() );

...

int DoProcessToken( int TokenID, char *szText )
{
    if( TokenID < MaxTokenID )
        return (*ProcessToken[TokenID])( szText );
    else
        return Error( szText );
}


  The Argument Declaration List

The argument-declaration-list portion of a function declaration:

•	Allows the compiler to check type consistency between the arguments the function requires and the arguments supplied in the call.

•	Enables conversions, either implicit or user-defined, to be performed from the supplied argument type to the required argument type.

•	Checks initializations of or assignments to pointers to functions.

•	Checks initializations of or assignments to references to functions.


  Argument Lists in Function Prototypes (Nondefining Declaration)

The form of argument-declaration-list is a list of the type names of the arguments. Consider an argument-declaration-list for a function, func, that takes these three arguments: pointer to type char, char, and int.

The code for such an argument-declaration-list can be written:

char *, char, int

The function declaration (the prototype) might therefore be written:

void func( char *, char, int );

Although the preceding declaration contains enough information for the compiler to perform type checking and conversions, it does not provide much information about what the arguments are. A good way to document function declarations is to include identifiers as they would appear in the function definition, as in the following:

void func( char *szTarget, char chSearchChar, int nStartAt );

These identifiers in prototypes are useful only for default arguments, because they go out of scope immediately. They do, however, provide meaningful program documentation.


  Argument Lists in Function Definitions

The argument list in a function definition differs from that of a prototype only in that the identifiers, if present, represent formal arguments to the function. The identifier names need not match those in the prototype (if there are any).

Note  It is possible to define functions with unnamed arguments. However, these arguments are inaccessible to the functions for which they are defined.


  Default Arguments

In many cases, functions have a number of arguments that are used so infrequently that a default value would suffice. To address this, the default-argument facility allows for specifying only those arguments to a function that are meaningful in a given call. To illustrate this concept, consider the example presented in »Function Overloading«.

// Prototype three print functions.
int print( char *s );                  // Print a string.
int print( double dvalue );            // Print a double.
int print( double dvalue, int prec );  // Print a double with a
                                       //  given precision.

In many applications, a reasonable default can be supplied for prec, eliminating the need for two functions:

// Prototype two print functions.
int print( char *s );                    // Print a string.
int print( double dvalue, int prec=2 );  // Print a double with a
                                         //  given precision.

The implementation of the print function is changed slightly to reflect the fact that only one such function exists for type double:

// Print a double in specified precision.
//  Positive numbers for precision indicate how many digits'
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print( double dvalue, int prec )
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = {
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
        10E1,  10E2,  10E3,  10E4, 10E5,  10E6
    };
    const int iPowZero = 6;
// If precision out of range, just print the number.
    if( prec >= -6 || prec <= 7 )
        // Scale, truncate, then rescale.
        dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
                                 rgPow10[iPowZero - prec];

    cout << dvalue << endl;

    return cout.good();
}

To invoke the new print function, use code such as the following:

print( d );    // Precision of 2 supplied by default argument.
print( d, 0 ); // Override default argument to achieve other
               //  results.

There are several points to note when using default arguments:

•	Default arguments are used only in function calls where trailing arguments are omitted — they must be the last argument(s). Therefore, the following code is illegal:

int print( double dvalue = 0.0, int prec );

•	A default argument cannot be redefined in later declarations even if the redefinition is identical to the original. Therefore, the following code produces an error:

// Prototype for print function.
int print( double dvalue, int prec = 2 );

...

// Definition for print function.
int print( double dvalue, int prec = 2 )
{
...
}

The problem with the preceding code is that the function declaration in the definition redefines the default argument for prec.

•	Additional default arguments can be added by later declarations.

•	Default arguments can be provided for pointers to functions. For example:

int (*pShowIntVal)( int i = 0 );


  Default Argument Expressions

The expressions used for default arguments are often constant expressions, but this is not a requirement. The expression can combine functions that are visible in the current scope, constant expressions, and global variables. The expression cannot contain local variables or nonstatic class-member variables. The following code illustrates this:

BOOL CreateVScrollBar( HWND hWnd, short nWidth =
                       GetSystemMetrics( SM_CXVSCROLL ) );

The preceding declaration specifies a function that creates a vertical scroll bar of a given width for a window. If no width argument is supplied, the Windows API function, GetSystemMetrics, is called to find the default width for a scroll bar.

The default expression is not evaluated until the function call, but the evaluation is completed before the function call actually takes place.

Because formal arguments to a function are in function scope, and because the evaluation of default arguments takes place prior to entry to this scope, formal arguments cannot be used in default argument expressions. Use of local variables in default argument expressions is also disallowed.

Note that any formal argument declared prior to a default argument expression can potentially hide a global name in the function scope, which can cause errors. The following code is illegal:

const int Categories = 9;

void EnumCategories( char *Categories[], int n = Categories );

In the preceding code, the global name Categories is hidden at function scope, making the default argument expression invalid.


  Other Considerations

The default argument is not considered part of the function type. Therefore, it is not used in selecting overloaded functions. Two functions that differ only in their default arguments are considered multiple definitions rather than overloaded functions.

Default arguments cannot be supplied for overloaded operators.


  7.4  Function Definitions

Function definitions differ from function declarations in that they supply function bodies — the code that makes up the function.

Syntax

function-definition:
decl-specifiers (opt)   declarator  ctor-initializer (opt)   fct-body

fct-body:
compound-statement

As discussed in »Functions«, the form of the declarator in the syntax is:

dname  (  argument-declaration-list  )  cv-mod-list (opt)

The formal arguments declared in argument-declaration-list are in the scope of the function body.

»Figure 7.3« shows the parts of a function definition. The shaded area is the function body.

The cv-mod-list element of the declarator syntax specifies how the this pointer is to be treated; it is only for use with class member functions. (For more information about the cv-mod-list, see »const and volatile Pointers« and »Memory-Model Modifiers and Member Functions« in Appendix B.)

The ctor-initializer element of the syntax is used only in constructors. Its purpose is to allow initialization of base classes and contained objects. (For more information about use of ctor-initializer, see »Initializing Bases and Members« in Chapter 11.)


  Functions with Variable Argument Lists

Functions that require variable lists are declared using the ellipsis (...) in the argument list, as described in »Variable Argument Lists«. To access arguments passed to functions using this method, use the types and macros described in the STDARG.H standard include file.

The following example shows how the va_start, va_arg, and va_end macros, along with the va_list type (declared in STDARG.H), work together:

#include <stdio.h>
#include <stdarg.h>

//  Declaration, but not definition, of ShowVar.
int ShowVar( char *szTypes, ... );

main()
{
    ShowVar( "fdcsi", 32.4f, 298.34E3, 'a', "Test string", 4 );

    return 0;
}

//  ShowVar takes a format string of the form
//   "ifdcs", where each character specifies the
//   type of the argument in that position.
//
//  i = int
//  f = float
//  d = double
//  c = char
//  s = string (char *)
//
//  Following the format specification is a list
//   of n arguments, where n == strlen( szTypes ).
int ShowVar( char *szTypes, ... )
{
    va_list vl;
    int i;

    //  szTypes is the last argument specified; all
    //   others must be accessed using the variable-
    //   argument macros.
    va_start( vl, szTypes );

    // Step through the list.
    for( i = 0; szTypes[i] != '\0'; ++i )
    {
        union Printable_t
        {
            int     i;
            float   f;
            double  d;
            char    c;
            char   *s;
        } Printable;

switch( szTypes[i] )    // Type to expect.
        {
        case 'i':
            Printable.i = va_arg( vl, int );
            printf( "%i\n", Printable.i );
            break;

        case 'f':
            Printable.f = va_arg( vl, float );
            printf( "%f\n", Printable.f );
            break;

        case 'd':
            Printable.d = va_arg( vl, double );
            printf( "%f\n", Printable.d );
            break;

        case 'c':
            Printable.c = va_arg( vl, char );
            printf( "%c\n", Printable.c );
            break;

        case 's':
            Printable.s = va_arg( vl, char * );
            printf( "%s\n", Printable.s );
            break;

        default:
            break;
        }
    }
    va_end( vl );

    return 0;
}

The preceding example illustrates these important concepts:

•	A list marker must be established as a variable of type va_list before any variable arguments are accessed. In the preceding example, the marker is called vl.

•	The individual arguments are accessed using the va_arg macro. The va_arg macro needs to be told the type of argument to retrieve so it can transfer the correct number of bytes from the stack. If an incorrect type of a size different than that supplied by the calling program is specified to va_arg, the results are unpredictable.

•	The result obtained using the va_arg macro should be explicitly cast to the desired type.

•	The va_end macro must be called to terminate variable-argument processing.


  7.5  Initializers

Declarators can specify the initial value for objects. The only way to specify a value for objects of const type is in the declarator. The part of the declarator that specifies this initial value is called the "initializer."

Syntax

initializer:
=  assignment-expression
= { initializer-list  , (opt)  }
(  expression-list  )

initializer-list:
expression
initializer-list  ,  expression
{  initializer-list  , (opt)   }

There are two fundamental types of initializers:

•	The initializer invoked using the equal-sign syntax

•	The initializer invoked using function-style syntax

Only objects of classes with constructors can be initialized with the function-style syntax. The two syntax forms also differ in access control and in the potential use of temporary objects. Consider the following code, which illustrates some declarators with initializers:

int      i = 7;                  // Uses equal-sign syntax.
Customer Cust( "Taxpayer, Joe",  // Uses function-style
               "14 Cherry Lane", //  syntax. Requires presence
               "Manteca",        //  of a constructor.
               "CA" );

Declarations of automatic, register, static, and external variables can contain initializers. However, declarations of external variables can contain initializers only if the variables are not declared as extern.

These initializers can contain expressions involving constants and variables in the current scope. The initializer expression is evaluated at the point the declaration is encountered in program flow, or, for global static objects and variables, at program startup. (For more information about initialization of global static objects, see »Additional Startup Considerations« in Chapter 2.)


  Initializing Pointers to const Objects

A pointer to a const object can be initialized with a pointer to an object that is not const, but not vice versa. For example, the following initialization is legal:

Window StandardWindow;
const Window* pStandardWindow( &StandardWindow );

In the preceding code, the pointer pStandardWindow is declared as a pointer to a const object. Although StandardWindow is not declared as const, the declaration is acceptable because it does not allow an object not declared as const access to a const object. The reverse of this is as follows:

const Window StandardWindow;
Window* pStandardWindow( &StandardWindow );

The above code explicitly declares StandardWindow as a const object. Initializing the nonconstant pointer pStandardWindow with the address of StandardWindow generates an error because it allows access to the const object through the pointer. That is, it allows removal of the const attribute from the object.


  Uninitialized Objects

Objects and simple variables of storage class static that are declared with no initializer are guaranteed to be initialized to a bit pattern of zeros. No such special processing takes place for uninitialized objects of automatic or register storage classes. They have undefined values.


  Initializing Static Members

Static member initialization occurs in class scope. Therefore, they can access other member data or functions. For example:

class DialogWindow
{
public:
    static short  GetTextHeight();
private:
    static short nTextHeight;
};

short DialogWindow :: nTextHeight = GetTextHeight();

Note that in the above definition of the static member nTextHeight, GetTextHeight is implicitly known to be DialogWindow :: GetTextHeight.


  Initializing Aggregates

An aggregate type is an array, class, or structure type which:

•	Has no constructors

•	Has no nonpublic members

•	Has no base classes

•	Has no virtual functions

Initializers for aggregates can be specified as a comma-separated list of values enclosed in curly braces. For example, this code declares an int array of 10 and initializes it:

int rgiArray[10] = { 9, 8, 4, 6, 5, 6, 3, 5, 6, 11 };

The initializers are stored in the array elements in increasing subscript order. Therefore, rgiArray[0] is 9, rgiArray[1] is 8, and so on, until rgiArray[9], which is 11. To initialize a structure, use code such as the following:

struct RCPrompt
{
    short nRow;
    short nCol;
    char *szPrompt;
};
RCPrompt rcContinueYN = { 24, 0, "Continue (Y/N?)" };


  Length of Aggregate-Initializer Lists

If an aggregate initializer list is shorter than the array or class type that is being initialized, zeros are stored in the elements for which no initializer is specified. Therefore, the following two declarations are equivalent:

// Explicitly initialize all elements.
int rgiArray[5] = { 3, 2, 0, 0, 0 };

// Allow remaining elements to be zero-initialized.
int rgiArray[5] = { 3, 2 };

Initializer lists can be truncated, as shown above, but supplying too many initializers generates an error.


  Initializing Aggregates That Contain Aggregates

Some aggregates contain other aggregates — for example, arrays of arrays, arrays of structures, or structures that are composed of other structures. Initializers can be supplied for such constructs by initializing each one in the order it occurs with a brace-enclosed list. For example:

// Declare an array of type RCPrompt.
RCPrompt rgRCPrompt[4] =
{ { 4,  7, "Options Are:"  },
  { 6,  7, "1. Main Menu"  },
  { 8,  7, "2. Print Menu" },
  { 10, 7, "3. File Menu"  } };

Note that rgRCPrompt is initialized with a brace-enclosed list of brace-enclosed lists. The enclosed braces are not syntactically required, but they lend clarity to the declaration. The following example program shows how a two-dimensional array is filled by such an initializer:

#include <iostream.h>

main()
{
    int rgI[2][4] = { 1, 2, 3, 4, 5, 6, 7, 8 };

    for( int i = 0; i < 2; ++i )
        for( int j = 0; j < 4; ++j )
            cout << "rgI[" << i << "][" << j << "] = "
                 << rgI[i][j] << endl;

    return 0;
}

The output from this program is:

rgI[0][0] = 1
rgI[0][1] = 2
rgI[0][2] = 3
rgI[0][3] = 4
rgI[1][0] = 5
rgI[1][1] = 6
rgI[1][2] = 7
rgI[1][3] = 8

Short initialization lists can be used only with explicit subaggregate initializers and enclosed in braces. If rgI had been declared as:

int rgI[2][4] = { { 1, 2 }, { 3, 4 } };

the program output would have been:

rgI[0][0] = 1
rgI[0][1] = 2
rgI[0][2] = 0
rgI[0][3] = 0
rgI[1][0] = 3
rgI[1][1] = 4
rgI[1][2] = 0
rgI[1][3] = 0


  Initializing Incomplete Types

Incomplete types, such as unbounded array types, can be initialized as follows:

char HomeRow[] = { 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l' };

The compiler computes the size of the array from the number of initializers provided.

Incomplete types, such as pointers to class types that are declared but not defined, are declared as follows:

class DefinedElsewhere;        // Class definition elsewhere.
class DefinedHere
{
    ...
    friend class DefinedElsewhere;
};


  Initializing Using Constructors

Objects of class type are initialized by calling the appropriate constructor for the class. For complete information about initializing class types, see »Explicit Initialization« in Chapter 11.


  Initializers and Unions

Objects of union type are initialized with a single value (if the union does not have a constructor). This is done in one of two ways:

•	Initialize the union with another object of the same union type. For example:

struct Point
{
    unsigned x;
    unsigned y;
};

union PtLong
{
    long  l;
    Point pt;
};

...

PtLong ptOrigin;
PtLong ptCurrent = ptOrigin;

In the preceding code, ptCurrent is initialized with the value of ptOrigin — an object of the same type.

•	Initialize the union with a brace-enclosed initializer for the first member. For example:

PtLong ptCurrent = { 0x0a000aL };


  Initializing Character Arrays

Character arrays can be initialized in one of two ways:

•	Individually, as follows:

char chABCD[4] = { 'a', 'b', 'c', 'd' };

•	With a string, as follows:

char chABCD[5] = "abcd";

In the second case, where the character array is initialized with a string, the compiler appends a trailing '\0' (end-of-string character). Therefore, the array must be at least one larger than the number of characters in the string.

Because most string handling uses the standard library functions or relies on the presence of the trailing end-of-string character, it is common to see unbounded array declarations initialized with strings:

char chABCD[] = "ABCD";


  Initializing References

Variables of reference type must be initialized with an object of the type from which the reference type is derived or with an object of a type that can be converted to the type from which the reference type is derived. For example:

int  iVar;
long lVar;

long& LongRef1 = lVar;      // No conversion required.
long& LongRef2 = iVar;      // Error.
const long& LongRef3 = iVar // OK

LongRef1 = 23L;        // Change lVar through a reference.
LongRef2 = 11L;        // Change iVar through a reference.
LongRef3 = 11L;        // Error.

The only way to initialize a reference with a temporary object is to actually initialize a constant temporary object. Once initialized, a reference-type variable always points to the same object; it cannot be modified to point to another object.

Although the syntax can be the same, initialization of reference-type variables and assignment to reference-type variables are semantically different. In the preceding example, the assignments that change iVar and lVar look similar to the initializations but have completely different effects. The initialization specifies the object to which the reference-type variable points; the assignment assigns to the referred-to object through the reference.

Because both passing an argument of reference type to a function and returning a value of reference type from a function are initializations, the formal arguments to a function are initialized correctly, as are the references returned.

The only time reference-type variables can be declared without initializers is in the following:

•	Function declarations (prototypes). For example:

int func( int& );

•	Function-return type declarations. For example:

int& func( int& );

•	Declaration of a reference-type class member. For example:

class c
{
public:
    int& i;
};

•	Declaration of a variable explicitly specified as extern. For example:

extern int& iVal;

When initializing a reference-type variable, the compiler uses the decision graph shown in »Figure 7.4« to select between creating a reference to an object or creating a temporary object to which the reference points.

References to volatile types (declared as volatile typename& identifier) can be initialized with volatile objects of the same type or with objects that have not been declared as volatile. They cannot, however, be initialized with const objects of that type. Similarly, references to const types (declared as const typename& identifier) can be initialized with const objects of the same type (or anything that has a conversion to that type or with objects that have not been declared as const). They cannot, however, be initialized with volatile objects of that type.

References that are not qualified with either the const or volatile keyword can be initialized only with objects declared as neither const nor volatile.


Chapter 8: Classes
  Chapter 8  Classes

This chapter introduces C++ classes. Classes, which can contain data and functions, introduce user-defined types into a program. User-defined types in traditional programming languages are collections of data that, taken together, describe an object's attributes and state. Class types in C++ allow description of attributes and state, but they also allow definition of behavior.


  8.1  Overview

Class types are defined using the class, struct, and union keywords. For simplicity, types defined with these keywords are called class declarations, except in discussions of language elements that behave differently depending on which keyword is used.

Microsoft Specific

"Local class" declarations — class declarations made in block scope — are exported to file scope in Microsoft C++. Classes not declared within another class always have file scope. ♦

Names of classes defined within another class ("nested") have class scope of the enclosing class.

Syntax

class-name:
identifier

The variables and functions of a class are called members. When defining a class, it is common practice to supply the following members (although all are optional):

•	Class data members, which define the state and attributes of an object of the class type.

•	One or more "constructor" functions, which initialize an object of the class type. Constructors are described in »Constructors« in Chapter 11.

•	One or more "destructor" functions, which perform cleanup functions such as deallocating dynamically allocated memory or closing files. Destructors are described in »Destructors« in Chapter 11.

•	One or more member functions that define the object's behavior. These functions perform operations particular to objects of a specific class only.


  Defining Class Types

Class types are defined using class-specifiers. Class types can be declared using elaborated-type-specifiers as shown in »Type Specifiers« in Chapter 6.

Syntax

class-specifier:
class-head { member-list (opt)   }

class-head:
class-key imodel (opt )  identifier (opt)  base-spec (opt
) 	class-key imodel (opt )  class-name (opt)  base-spec (opt)

class-key:
class
struct
union

imodel:
__near	// 16-Bit Specific
__far	// 16-Bit Specific
__export	// 16-Bit Specific
__declspec	 	// 32-Bit Specific

Class names are introduced as identifiers immediately after the compiler processes them (before entry into the class body); they can be used to declare class members. This allows declaration of self-referential data structures, such as the following:

class Tree
{
public:
    void *Data;
    Tree *Left;
    Tree *Right;
};


  Structures, Classes, and Unions

The three class types are structure, class, and union. They are declared using the struct, class, and union keywords (see class-key syntax above). Table 8.1 shows the differences among the three class types.

Table 8.1    Access Control and Constraints of Structures, Classes, and Unions

Structures	Classes	Unions
class-key is struct	class-key is class	class-key is union
Default access is public	Default access is private	Default access is public
No usage constraints	No usage constraints	Use only one member at a time


  Anonymous Class Types

Classes can be anonymous — that is, they can be declared without an identifier. This is useful in cases when you replace a class name with a typedef name, as in the following example:

typedef struct
{
    unsigned x;
    unsigned y;
} POINT;

Note  The use of anonymous classes shown in the previous example is useful for preserving compatibility with existing C code. In some C code, the use of typedef in conjunction with anonymous structures is prevalent.

Anonymous classes are also useful when you want a reference to a class member to appear as though it were not contained in a separate class, as in the following example:

struct PTValue
{
    POINT ptLoc;
    union
    {
        int  iValue;
        long lValue;
    };
};

PTValue ptv;

In the preceding code, iValue can be accessed using the object member-selection operator (.) as follows:

int i = ptv.iValue;

Anonymous classes are subject to certain restrictions. (For more information about anonymous unions, see »Unions«.) Anonymous classes:

•	Cannot have a constructor or destructor.

•	Cannot be passed as arguments to functions (unless type checking is defeated using ellipses).

•	Cannot be returned as return values from functions.


  Point of Class Definition

A class is defined at the end of its class-specifier. Member functions need not be defined in order for the class to be considered defined. Consider the following example:

class Point                    // Point class
{                              //  considered defined.
public:
    Point()
        { cx = cy = 0; }       // Constructor defined.
    Point( int x, int y )
        { cx = X, cy = Y; }    // Constructor defined.
    unsigned &x( unsigned );   // Accessor declared.
    unsigned &y( unsigned );   // Accessor declared.
private:
    unsigned  cx, cy;
};

Even though the two accessor functions (x and y) are not yet defined, the class Point is considered defined. (Accessor functions are functions provided to give safe access to member data.)


  Class-Type Objects

An object is a typed region of storage in the execution environment; in addition to retaining state information, it also defines behavior. Class-type objects are defined using class-name. Consider the following code fragment:

class Account                      // Class name is Account.
{
public:
            Account();             // Default constructor.
            Account( double );     // Construct from double.
    double& Deposit( double );
    double& Withdraw( double, int );
    ...
}:

Account CheckingAccount;           // Define object of class type.

The preceding code declares a class (a new type) called Account. It then uses this new type to define an object called CheckingAccount.

The following operations are defined by C++ for objects of class type:

•	Assignment. One object can be assigned to another. The default behavior for this operation is a memberwise copy. This behavior can be modified by supplying a user-defined assignment operator.

•	Initialization using copy constructors.

Each of the following are examples of initialization using user-defined copy constructors:

•	Explicit initialization of an object. For example:

Point myPoint = thatPoint;

declares myPoint as an object of type Point and initializes it to the value of thatPoint.

•	Initialization caused by passing as an argument. Objects can be passed to functions either by value or by reference. If they are passed by value, a copy of each object is passed to the function. The default method for creating the copy is memberwise copy; this can be modified by supplying a user-defined copy constructor (a constructor that takes a single argument of the type "reference to class").

•	Initialization caused by the initialization of return values from functions. Objects can be returned from functions either by value or by reference. The default method for returning an object by value is a memberwise copy; this can be modified by supplying a user-defined copy constructor. An object returned by reference (using pointer or reference types) should not be both automatic and local to the called function. If it is, the object referred to by the return value will have gone out of scope before it can be used.

»Overloaded Operators« in Chapter 12 explains how to redefine other operators on a class-by-class basis.


  Empty Classes

You can declare empty classes, but objects of such types still have nonzero size. The following example illustrates this:

#include <iostream.h>

class NoMembers
{
};

int main()
{
    NoMembers n;  // Object of type NoMembers.

    cout << "The size of an object of empty class is: "
         << sizeof n << endl;

    return 0;
}

This is the output of the preceding program:

The size of an object of empty class is: 1.

The memory allocated for such objects is of nonzero size; therefore, the objects have different addresses. Having different addresses is important because it must be possible to compare pointers to objects for identity. Without distinct addresses, such a comparison is impossible. Also, in arrays, each member array must have a distinct address.

Microsoft Specific

An empty base class typically contributes zero bytes to the size of a derived class. ♦


  8.2  Class Names

Class declarations introduce new types, called class names, into programs. These class declarations also act as definitions of the class for a given translation unit. There may be only one definition for a given class type per translation unit. Using these new class types, you can declare objects, and the compiler can perform type checking to verify that no operations incompatible with the types are performed on the objects.

An example of such type checking is:

class Point
{
public:
    unsigned x, y;
};

class Rect
{
public:
    unsigned x1, y1, x2, y2;
};

// Prototype a function that takes two arguments, one of type
//  Point and the other of type pointer to Rect.
int PtInRect( Point, Rect & );

...

Point pt;
Rect  rect;

rect = pt;   // Error. Types are incompatible.
pt = rect;   // Error. Types are incompatible.

// Error. Arguments to PtInRect are reversed.
cout << "Point is " << PtInRect( rect, pt ) ? "" : "not"
     << " in rectangle" << endl;

As the preceding code illustrates, operations (such as assignment and argument passing) on class-type objects are subject to the same type checking as objects of built-in types.

Because the compiler distinguishes between class types, functions can be over loaded on the basis of class-type arguments as well as built-in type arguments. For more information about overloaded functions, see »Function Overloading« in Chapter 7 and »Chapter 12, Overloading.«


  Declaring and Accessing Class Names

Class names can be declared in global or class scope. If they are declared in class scope, they are referred to as "nested" classes.

Microsoft Specific

Block-scoped class declarations, or "local" class declarations, are not permitted in Microsoft C++. However, use of simple aggregates such as C structures is allowed in block scope. ♦

Any class name introduced in class scope hides other elements of the same name in an enclosing scope. Names hidden by such a declaration can then be referred to only by using an elaborated-type-specifier. The following example shows an example of using an elaborated-type-specifier to refer to a hidden name:

struct A      // Global scope definition of A.
{
    int a;
};

void main()
{
    char A = 'a'; // Redefine the name A as an object.

    struct A AObject;
    ...
}

Because the name A that refers to the structure is hidden by the A that refers to the char object, struct (a class-key) must be used to declare AObject as type A.

You can use the class-key to declare a class without providing a definition. This nondefining declaration of a class introduces a class name for forward reference. This technique is useful when designing classes that refer to one another in friend declarations. It is also useful when class names must be present in header files but the definition is not required. For example:

// RECT.H
class Point;   // Nondefining declaration of class Point.
class Line
{
public:
    int Draw( Point &ptFrom, Point &ptTo );
    ...
};

In the preceding sample, the name Point must be present, but it need not be a defining declaration that introduces the name.


  typedef Statements and Classes

Using the typedef statement to name a class type causes the typedef name to become a class-name. For more information about using typedef, see »typedef Specifier« in Chapter 6.


  8.3  Class Members

Classes can have these kinds of members:

•	Member functions. (See »Member Functions«.)

•	Data members.

•	Classes, which include classes, structures, and unions. (See »Nested Class Declarations« and »Unions«.)

•	Enumerations. (See »Enumeration Declarations« in Chapter 6.)

•	Bit fields. (See »Bit Fields«.)

•	Friends. (See »Friends« in Chapter 10.)

•	Type names. (See »Type Names in Class Scope«.)

Note  Friends are included in the preceding list because they are contained in the class declaration. However, they are not true class members, because they are not in the scope of the class.

Syntax

member-list:
member-declaration member-list (opt)
access-specifier : member-list (opt)

member-declaration:
decl-specifiers (opt)  member-declarator-list (opt)  ;
function-definition (opt)  ;
qualified-name ;

member-declarator-list:
member-declarator
member-declarator-list , member-declarator

member-declarator:
declarator pure-specifier (opt)
identifier (opt)   : constant-expression

pure-specifier:
= 0

The purpose of the member-list is to:

•	Declare the complete set of members for a given class.

•	Specify the access (public, private, or protected) associated with various class members.

In the declaration of a member list, you can declare members only once; redeclaration of members produces an error message. Because a member list is a complete set of the members, you cannot add members to a given class with subsequent class declarations.

Member declarators cannot contain initializers. Supplying an initializer produces an error message. The following code illustrates this error:

class CantInit
{
public:
    long l = 7;       // Error: attempt to initialize
                      //  class member.
    static int i = 9; // Error: must be defined and initialized
                          outside of class declaration.
};

Because a separate instance of nonstatic member data is created for each object of a given class type, the correct way to initialize member data is to use the class's constructor. (Constructors are covered in »Constructors,« in Chapter 11.) Only one shared copy of static data members exists for all objects of a given class type. Static data members must be defined and can be initialized at file scope. (For more information about static data members, see »Static Data Members«.) The following example shows how to perform these initializations:

class CanInit
{
public:
    CanInit() { l = 7; } // Initializes l when new objects of type
                         //  CanInit are created.
    long       l;
    static int i;
    static int j;
};

int CanInit::i = 15;   // i is defined at file scope and
                       //  initialized to 15. The initializer
                       //  is evaluated in the scope of CanInit.
int CanInit::j = i;    // The right side of the initializer
                       //  is in the scope of the object being
                       //  initialized.

Note  The class name, CanInit, must precede i to specify that the i being defined is a member of class CanInit.


  Class-Member Declaration Syntax

Member data cannot be declared as auto, extern, or register storage class. They can, however, be declared as having static storage class.

The decl-specifiers specifiers can be omitted in member-function declarations. For information on decl-specifiers, see »Specifiers« in Chapter 6 and »Member Functions«; see also »Functions« in Chapter 7. The following code is therefore legal and declares a function that returns type int:

class NoDeclSpec
{
public:
NoSpecifiers();
};

When you declare a friend class in a member list, you can omit the member-declarator-list. For more information on friends, see »friend Specifier« in Chapter 6, and »Friends« in Chapter 10. Even if a class name has not been introduced, it can be used in a friend declaration. This friend declaration introduces the name. However, in member declarations for such classes, the elaborated-type-specifier syntax must be used, as shown in the following example:

class HasFriends
{
public:
    friend class NotDeclaredYet;
};

In the preceding example, there is no member-declarator-list after the class declaration. Because the declaration for NotDeclaredYet has not yet been processed, the elaborated-type-specifier form is used: class NotDeclaredYet. A type that has been declared can be specified in a friend member declaration using a normal type specifier:

class AlreadyDeclared
{
    ...
};

class HasFriends
{
public:
    friend AlreadyDeclared;
};

The pure-specifier (shown in the following example) indicates that no implementation is supplied for the virtual function being declared. Therefore, the pure-specifier can be specified only on virtual functions. Consider this example:

class StrBase  // Base class for strings.
{
public:
    virtual int IsLessThan( StrBase& ) = 0;
    virtual int IsEqualTo( StrBase& ) = 0;
    virtual StrBase& CopyOf( StrBase& ) = 0;
    ...
};

The preceding code declares an abstract base class — that is, a class designed to be used only as the base class for more specific classes. Such base classes can enforce a particular protocol, or set of functionality, by declaring one or more virtual functions as "pure" virtual functions, using the pure-specifier.

Classes that inherit from the StrBase class must provide implementations for the pure virtual functions; otherwise, they, too, are considered abstract base classes.

Abstract base classes cannot be used to declare objects. For example, before an object of a type inherited from StrBase can be declared, the functions IsLessThan, IsEqualTo, and CopyOf must be implemented. (For more information about abstract base classes, see »Abstract Classes« in Chapter 9.)


  Declaring Unsized Arrays in Member Lists (Microsoft Specific)

Unsized arrays can be declared in class member lists as the last data member if the program is not compiled with the ANSI-compatibility option ( / Za) Because this is a Microsoft extension, using unsized arrays in this way can make your code less portable. To declare an unsized array, simply omit the first dimension. For example:

class Symbol
{
public:
    int  SymbolType;
    char SymbolText[];
};


  Restrictions

If a class contains an unsized array, it cannot be used as the base class for another class. In addition, a class containing an unsized array cannot be used to declare any member except the last member of another class. A class containing an unsized array cannot have a direct or indirect virtual base class.

The sizeof operator, when applied to a class containing an unsized array, returns the amount of storage required for all members except the unsized array. Implementors of classes that contain unsized arrays should provide alternate methods for obtaining the correct size of the class.

You cannot declare arrays of objects that have unsized array components. Also, performing pointer arithmetic on pointers to such objects generates an error message.


  Storage of Class-Member Data

Nonstatic class-member data is stored in such a way that items falling between access specifiers are stored at successively higher memory addresses. No ordering across access specifiers is guaranteed.

Microsoft Specific

Depending on the /Zp compilation option or the pack pragma, intervening space can be introduced to align member data on word or doubleword boundaries. (For more information about the /Zp compilation option or the pack pragma, see Chapter 2 of the Preprocessor Reference.)

In Microsoft C++, class-member data is stored at successively higher memory addresses, even though the C++ language does not require it. Basing assumptions on this ordering can lead to nonportable code. ♦


  Member Naming Restrictions

A function with the same name as the class in which it is declared is a constructor. A constructor is implicitly called when an object of this class type is created. (For more information about constructors, see »Constructors« in Chapter 11.)

The following items cannot have the same name as the classes in whose scope they are declared: data members (both static and nonstatic), enclosed enumerators, members of anonymous unions, and nested class types.


  8.4  Member Functions

Classes can contain data and functions. These functions are referred to as "member functions." Any nonstatic function declared inside a class declaration is considered a member function and is called using the member-selection operators (. and −>). When calling member functions from other member functions of the same class, the object and member-selection operator can be omitted. For example:

class Point
{
public:
    short x() { return _x; }
    short y() { return _y; }
    void  Show() { cout << x() << ", " << y() << "\n"; }
private:
    short _x, _y;
};

void main()
{
    Point pt;

    pt.Show();
}

Note that in the member function, Show, calls to the other member functions, x and y, are made without member-selection operators. These calls implicitly mean this->x() and this->y(). However, in main, the member function, Show, must be selected using the object pt and the member-selection operator (.).

Static functions declared inside a class can be called using the member-selection operators or by specifying the fully qualified function name (including the class name).

Note  A function declared using the friend keyword is not considered a member of the class in which it is declared a friend (although it can be a member of another class). A friend declaration controls the access a nonmember function has to class data.

The following class declaration shows how member functions are declared:

class Point
{
public:
    unsigned GetX();
    unsigned GetY();
    unsigned SetX( unsigned x );
    unsigned SetY( unsigned y );
private:
    unsigned ptX, ptY;
};

In the preceding class declaration, four functions are declared: GetX, GetY, SetX, and SetY. The next example shows how such functions are called in a program:

int main()
{
    // Declare a new object of type Point.
    Point ptOrigin;

    // Member function calls use the . member-selection operator.
    ptOrigin.SetX( 0 );
    ptOrigin.SetY( 0 );

    // Declare a pointer to an object of type Point.
    Point *pptCurrent = new Point;
// Member function calls use the -> member-selection operator.
    pptCurrent->SetX( ptOrigin.GetX() + 10 );
    pptCurrent->SetY( ptOrigin.GetY() + 10 );

    return 0;
}

In the preceding code, the member functions of the object ptOrigin are called using the member-selection operator (.). However, the member functions of the object pointed to by pptCurrent are called using the −> member-selection operator.


Overview of Member Functions

Member functions are either static or nonstatic. The behavior of static member functions differs from that of other member functions because static member functions have no implicit this argument. Nonstatic member functions do have a this pointer. Member functions, whether static or nonstatic, can be defined either in the class declaration or outside the class declaration.

If a member function is defined inside a class declaration, it is treated as an inline function, and there is no need to qualify the function name with its class name. Although functions defined inside class declarations are already treated as inline functions, you can use the inline keyword to document code.

An example of declaring a function within a class declaration follows:

class Account
{
public:
    // Declare the member function Deposit within the declaration
    //  of class Account.
    double Deposit( double HowMuch )
    {
        balance += HowMuch;
        return balance;
    }
private:
    double balance;
};

If a member function's definition is outside the class declaration, it is treated as an inline function only if it is explicitly declared as inline. In addition, the function name in the definition must be qualified with its class name using the scope-resolution operator (::).

The following example is identical to the previous declaration of class Account, except that the Deposit function is defined outside the class declaration:

class Account
{
public:
    // Declare the member function Deposit but do not define it.
    double Deposit( double HowMuch );
private:
    double balance;
};

inline double Account::Deposit( double HowMuch )
{
    balance += HowMuch;
    return balance;
}

Note  Although member functions can be defined either inside a class declaration or separately, no member functions can be added to a class after the class is defined.

Classes containing member functions can have many declarations, but the member functions themselves must have only one definition in a program. Multiple definitions cause an error message at link time. If a class contains inline function definitions, the function definitions must be identical to observe this "one definition" rule.


  Nonstatic Member Functions

Nonstatic member functions have an implied argument, this, that points to the object through which the function is invoked. The type of this is type * const. These functions are considered to have class scope and can use class data and other member functions in the same class scope directly. In the preceding example, the expression balance += HowMuch adds the value of HowMuch to the class member balance. Consider the following statements:

Account Checking;

Checking.Deposit( 57.00 );

The preceding code declares an object of type Account and then invokes the member function Deposit to add $57.00 to it. In the function Account::Deposit, balance is taken to mean Checking.balance (the balance member for this object).

Nonstatic member functions are intended to operate on objects of their class type. Calling such a function on objects of different types (using explicit type conversions) causes undefined behavior.


  The this Pointer

All nonstatic member functions can use the this keyword, which is a const (nonmodifiable) pointer to the object for which the function was called. Member data is addressed by evaluating the expression this−>member-name (although this technique is seldom used). In member functions, using a member name in an expression implicitly uses this−>member-name to select the correct function or data member.

Note  Because the this pointer is nonmodifiable, assignments to this are not allowed. Earlier implementations of C++ allowed assignments to this.

Occasionally, the this pointer is used directly — for example, in manipulation of self-referential data structures, where the address of the current object is required.


  Type of this Pointer

The this pointer's type can be modified in the function declaration by the const, volatile, __near, __far, and __huge keywords. To declare a function as having the attributes of one or more of these keywords, use the cv-mod-list grammar, which follows. (For more information, see »Memory-Model Modifiers and Member Functions« in Appendix B.)

Syntax

cv-mod-list:
cv-qualifier cv-mod-list (opt)
pmodel cv-mod-list (opt)

cv-qualifier:
const
volatile

pmodel:	// Microsoft Specific
__near	// 16-Bit Specific
__far	// 16-Bit Specific
__huge	// 16-Bit Specific

Consider this example:

class Point
{
    unsigned X() const;
};

The preceding code declares a member function, X, in which the this pointer is treated as a const pointer to a const object. Combinations of cv-mod-list options can be used, but they always modify the object pointed to by this, not the this pointer itself. Therefore, the following declaration declares function X; the this pointer is a const pointer to a const object that is addressed far (using intersegment addressing):

class Point
{
    unsigned X() __far const;
};

The type of this is described by the following syntax, where cv-qualifier-list can be const or volatile, class-type is the name of the class, and imodel is a memory-model option:

cv-qualifier-list (opt)  class-type imodel (opt)  * const this

Table 8.2 explains more about how these modifiers work.

Table 8.2    Semantics of this Modifiers

Modifier	Meaning
const	Cannot change member data; cannot invoke member functions that are not const.
volatile	Member data is loaded from memory each time it is accessed; disables certain optimizations.
__near	Addressing is intrasegment (16-bit). (Microsoft Specific)
__far	Addressing is intersegment; pointer arithmetic is 16-bit. Individual objects must be smaller than 64K. (Microsoft Specific)
__huge	Addressing is intersegment; pointer arithmetic is 32-bit (use __huge for large arrays of large objects). (Microsoft Specific)
It is an error to pass a const object to a member function that is not const. Similarly, it is an error to pass a volatile object to a member function that is not volatile.

Member functions declared as const cannot change member data — in such functions, the this pointer is a pointer to a const object.

Note  Constructors and destructors cannot be declared as const or volatile. They can, however, be invoked on const or volatile objects. Constructors and destructors can be declared as __near, __far, or __huge; which constructor or destructor is called depends on the addressing of the object being created or destroyed.


  Static Member Functions

Static member functions are considered to have class scope. In contrast to nonstatic member functions, these functions have no implicit this argument; therefore, they can use only static data members, enumerators, or nested types directly. Static member functions can be accessed without using an object of the corresponding class type. Consider this example:

class WindowManager
{
public:
    static int  CountOf();              // Return count of open windows.
           void Minimize();             // Minimize current window.
           WindowManager SideEffects(); // Function with side effects.
    ...
private:
    static int wmWindowCount;
};
int WindowManager::wmWindowCount = 0;

...

// Minimize (show iconic) all windows
for( int i = 0; i < WindowManager::CountOf(); ++i )
    rgwmWin[i].Minimize();

In the preceding code, the class WindowManager contains the static member function CountOf. This function returns the number of windows open but is not necessarily associated with a given object of type WindowManager. This concept is demonstrated in the loop where the CountOf function is used in the controlling expression; because CountOf is a static member function, it can be called without reference to an object.

Static member functions have external linkage. These functions do not have this pointers (covered in the next section). As a result, the following restrictions apply to such functions:

•	They cannot access nonstatic class member data using the member-selection operators (. or −>).

•	They cannot be declared as virtual.

•	They cannot have the same name as a nonstatic function that has the same argument types.

Note  The left side of a member-selection operator (. or −>) that selects a static member function is not evaluated. This can be important if the function is used for its side effects. For example, the expression SideEffects().CountOf() does not call the function SideEffects.


  8.5  Static Data Members

Classes can contain static member data and member functions. When a data member is declared as static, only one copy of the data is maintained for all objects of the class. (For more information, see »Static Member Functions«.)

Static data members are not part of objects of a given class type; they are separate objects. As a result, the declaration of a static data member is not considered a definition. The data member is declared in class scope, but definition is performed at file scope. These static members have external linkage. The following example illustrates this:

class BufferedOutput
{
public:
    // Return number of bytes written by any object of this class.
    short BytesWritten() { return bytecount; }

    // Reset the counter.
    static void ResetCount() { bytecount = 0; }

    // Static member declaration.
    static long bytecount;
};

// Define bytecount in file scope.
long BufferedOutput::bytecount;

In the preceding code, the member bytecount is declared in class BufferedOutput, but it must be defined outside the class declaration.

Static data members can be referred to without referring to an object of class type. The number of bytes written using BufferedOutput objects can be obtained as follows:

long nBytes = BufferedOutput::bytecount;

For the static member to exist, it is not necessary that any objects of the class type exist. Static members can also be accessed using the member-selection (. and −>) operators. For example:

BufferedOutput Console;

long nBytes = Console.bytecount;

In the preceding case, the reference to the object (Console) is not evaluated; the value returned is that of the static object bytecount.

Static data members are subject to class-member access rules, so private access to static data members is allowed only for class-member functions and friends. These rules are described in »Chapter 10, Member-Access Control.« The exception is that static data members must be defined in file scope regardless of their access restrictions. If the data member is to be explicitly initialized, an initializer must be provided with the definition.

The type of a static member is not qualified by its class name. Therefore, the type of BufferedOutput::bytecount is long.


  8.6  Unions

Unions are class types that can contain only one data element at a time (although the data element can be an array or a class type). The members of a union represent the kinds of data the union can contain. An object of union type requires enough storage to hold the largest member in its member-list. Consider the following example:

#include <stdlib.h>
#include <string.h>
#include <limits.h>

union NumericType        // Declare a union that can hold the following:
{
    int         iValue;  // int value
    long        lValue;  // long value
    double      dValue;  // double value
};

int main( int argc, char *argv[] )
{
    NumericType *Values = new NumericType[argc - 1];

    for( int i = 1; i < argc; ++i )
        if( strchr( argv[i], '.' ) != 0 )
           // Floating type. Use dValue member for assignment.
            Values[i].dValue = atof( argv[i] );
        else
           // Not a floating type.
        {

                // If data is bigger than largest int, store it in
                //  lValue member.
            if( atol( argv[i] ) >  INT_MAX )
                Values[i].lValue = atol( argv[i] );
            else
                // Otherwise, store it in iValue member.
                Values[i].iValue = atoi( argv[i] );
        }

    return 0;
}

The NumericType union is arranged in memory (conceptually) as shown in »Figure 8.1.«


  Member Functions in Unions

In addition to member data, unions can have member functions, as described in »Member Functions«. Although unions can have special functions such as constructors and destructors, unions cannot contain virtual functions. (For more information, see »Constructors« and »Destructors« in Chapter 11.)


  Unions as Class Types

Unions cannot have base classes; that is, they cannot inherit the attributes of other unions, structures, or classes. Unions also cannot be used as base classes for further inheritance.

Inheritance is covered in detail in »Chapter 9, Derived Classes.«


  Union Member Data

Unions can contain most types in their member lists, except for the following:

•	Class types that have constructors or destructors

•	Class types that have user-defined assignment operators

•	Static data members


  Anonymous Unions

Anonymous unions are unions that are declared without a class-name or declarator-list.

Syntax

union  {  member-list  }  ;

Such union declarations do not declare types — they declare objects. The names declared in an anonymous union cannot conflict with other names declared in the same scope.

Names declared in an anonymous union are used directly, like nonmember variables. The following example illustrates this:

#include <iostream.h>

struct DataForm
{
    enum DataType { CharData = 1, IntData, StringData };
    DataType type;

    // Declare an anonymous union.
    union
    {
        char  chCharMem;
        char *szStrMem;
        int   iIntMem;
    };
    void print();
};

void DataForm::print()
{
    // Based on the type of the data, print the
    // appropriate data type.
    switch( type )
    {
    case CharData:
        cout << chCharMem;
        break;

    case IntData:
        cout << szStrMem;
        break;
    case StringData:
        cout << iIntMem;
        break;
    }
}

In the function DataForm::print, the three members (chCharMem, szStrMem, and iIntMem) are accessed as though they were declared as members (without the union declaration). However, the three union members share the same memory.

In addition to the restrictions listed in »Union Member Data«, anonymous unions are subject to additional restrictions:

•	They must also be declared as static if declared in file scope.

•	They can have only public members; private and protected members in anonymous unions generate errors.

•	They cannot have function members.

Note  Simply omitting the class-name portion of the syntax does not make a union an anonymous union. For a union to qualify as an anonymous union, the declaration must not declare an object.


  8.7  Bit Fields

Classes and structures can contain members that occupy less storage than an integral type. These members are specified as bit fields. The syntax for bit-field member-declarator specification follows:

Syntax

declarator (opt)   : constant-expression

The declarator is the name by which the member is accessed in the program. It must be an integral type (including enumerated types). The constant-expression specifies the number of bits the member occupies in the structure. Anonymous bit fields — that is, bit-field members with no identifier — can be used for padding.

Note  An unnamed bit field of width 0 forces alignment of the next bit field to the next type boundary, where type is the type of the member.

The following example declares a structure that contains bit fields:

struct Date
{
    unsigned nWeekDay  : 3;    // 0..7   (3 bits)
    unsigned nMonthDay : 6;    // 0..31  (6 bits)
    unsigned nMonth    : 5;    // 0..12  (5 bits)
    unsigned nYear     : 8;    // 0..100 (8 bits)
};

The conceptual memory layout of an object of type Date is shown in »Figure 8.2.«

Note that nYear is 8 bits long and would overflow the word boundary of the declared type, unsigned int. Therefore, it is begun at the beginning of a new unsigned int. It is not necessary that all bit fields fit in one object of the underlying type; new units of storage are allocated, according to the number of bits requested in the declaration.

Microsoft Specific

The ordering of data declared as bit fields is from low to high bit, as shown in »Figure 8.2.« ♦

If the declaration of a structure includes an unnamed field of length 0, as shown in the following example, the memory layout is as shown in »Figure 8.3.«

struct Date
{
    unsigned nWeekDay  : 3;    // 0..7   (3 bits)
    unsigned nMonthDay : 6;    // 0..31  (6 bits)
    unsigned           : 0;    // Force alignment to next boundary.
    unsigned nMonth    : 5;    // 0..12  (5 bits)
    unsigned nYear     : 8;    // 0..100 (8 bits)
};

The underlying type of a bit field must be an integral type, as described in »Fundamental Types« in Chapter 2.


  Restrictions on Use of Bit Fields

The following list details erroneous operations on bit fields:

•	Taking the address of a bit field

•	Initializing a reference with a bit field


  8.8  Nested Class Declarations

A class can be declared within the scope of another class. Such a class is called a "nested class." Nested classes are considered to be within the scope of the enclosing class and are available for use within that scope. To refer to a nested class from a scope other than its immediate enclosing scope, you must use a fully qualified name.

The following example shows how to declare nested classes:

class BufferedIO
{
public:
    enum IOError { None, Access, General };

    // Declare nested class BufferedInput.
    class BufferedInput
    {
    public:
        int read();
        int good() { return _inputerror == None; }
    private:
        IOError _inputerror;
    };

    // Declare nested class BufferedOutput.
    class BufferedOutput
    {
        // Member list
    };
};

BufferedIO::BufferedInput and BufferedIO::BufferedOutput are declared within BufferedIO. These class names are not visible outside the scope of class BufferedIO. However, an object of type BufferedIO does not contain any objects of types BufferedInput or BufferedOutput.

Nested classes can directly use names, type names, names of static members, and enumerators only from the enclosing class. To use names of other class members, you must use pointers, references, or object names.

In the preceding BufferedIO example, the enumeration IOError can be accessed directly by member functions in the nested classes, BufferedIO::BufferedInput or BufferedIO::BufferedOutput, as shown in function good.

Note  Nested classes declare only types within class scope. They do not cause contained objects of the nested class to be created. The preceding example declares two nested classes but does not declare any objects of these class types.


  Access Privileges and Nested Classes

Nesting a class within another class does not give member functions of the nested class special access privileges. Similarly, member functions of the enclosing class have no special access to members of the nested class.

For more information about access privileges, see »Chapter 10, Member-Access Control.«


  Member Functions in Nested Classes

Member functions declared in nested classes can be defined in file scope. The preceding example could have been written:

class BufferedIO
{
public:
    enum IOError { None, Access, General };
    class BufferedInput
    {
    public:
        int read(); // Declare but do not define member
        int good(); //  functions read and good.
    private:
        IOError _inputerror;
    };

    class BufferedOutput
    {
        // Member list.
    };
};
// Define member functions read and good in
//  file scope.
int BufferedIO::BufferedInput::read()
{
    ...
}

int BufferedIO::BufferedInput::good()
{
    return _inputerror == None;
}

In the preceding example, the qualified-type-name syntax is used to declare the function name. The declaration:

BufferedIO::BufferedInput::read()

means "the read function that is a member of the BufferedInput class that is in the scope of the BufferedIO class." Because this declaration uses the qualified-type-name syntax, constructs of the following form are possible:

typedef BufferedIO::BufferedInput BIO_INPUT;

int BIO_INPUT::read()

The preceding declaration is equivalent to the previous one, but it uses a typedef name in place of the class names.


  Friend Functions and Nested Classes

Friend functions declared in a nested class are considered to be in the scope of the nested class, not the enclosing class. Therefore, the friend functions gain no special access privileges to members or member functions of the enclosing class. If you want to use a name that is declared in a nested class in a friend function and the friend function is defined in file scope, use qualified type names as follows:

extern char *rgszMessage[];

class BufferedIO
{
public:
    ...
class BufferedInput
    {
    public:
        friend int GetExtendedErrorStatus();
        ...
        static char *message;
        int          iMsgNo;
    };
};
char *BufferedIO::BufferedInput::message;

int GetExtendedErrorStatus()
{
    ...
    strcpy( BufferedIO::BufferedInput::message,
            rgszMessage[iMsgNo] );
    return iMsgNo;
}

The preceding code shows the function GetExtendedErrorStatus declared as a friend function. In the function, which is defined in file scope, a message is copied from a static array into a class member. Note that a better implementation of GetExtendedErrorStatus is to declare it as:

int GetExtendedErrorStatus( char *message )

With the preceding interface, several classes can use the services of this function by passing a memory location where they want the error message copied.


  8.9  Type Names in Class Scope

Type names defined within class scope are considered local to their class. They cannot be used outside that class. The following example demonstrates this concept:

class Tree
{
public:
typedef Tree * PTREE;
PTREE  Left;
PTREE  Right;
void  *vData;
};

PTREE pTree;  // Error: not in class scope.


Chapter 9: Derived Classes
  Chapter 9  Derived Classes

This chapter explains how to use derived classes to produce extensible programs.


  9.1  Overview

New classes can be derived from existing classes using a mechanism called "inheritance" (see the discussion beginning in »Single Inheritance«). Classes that are used for derivation are called "base classes" of a particular derived class. A derived class is declared using the following syntax:

Syntax

base-spec:
: base-list

base-list:
base-specifier
base-list , base-specifier

base-specifier:
complete-class-name
virtual access-specifier (opt)  complete-class-name
access-specifier virtual (opt)  complete-class-name

access-specifier:
private
protected
public


  Single Inheritance

In "single inheritance," a common form of inheritance, classes have only one base class. Consider the relationship illustrated in »Figure 9.1.«

Note the progression from general to specific in »Figure 9.1.« Another common attribute found in the design of most class hierarchies is that the derived class has a "kind of" relationship with the base class. In »Figure 9.1«, a Book is a kind of a PrintedDocument, and a PaperbackBook is a kind of a book.

One other item of note in »Figure 9.1«: Book is both a derived class (from PrintedDocument) and a base class (PaperbackBook is derived from Book). A skeletal declaration of such a class hierarchy is shown in the following example:

class PrintedDocument
{
    // Member list.
};

// Book is derived from PrintedDocument.
class Book : public PrintedDocument
{
    // Member list.
};

// PaperbackBook is derived from Book.
class PaperbackBook : public Book
{
    // Member list.
};

PrintedDocument is considered a "direct base" class to Book; it is an "indirect base" class to PaperbackBook. The difference is that a direct base class appears in the base list of a class declaration and an indirect base does not.

Note that the base class from which each class is derived is completely declared before the declaration of the derived class. It is not sufficient to provide a forward-referencing declaration for a base class; it must be a complete declaration.

A class can serve as the base class for many more specific classes, as illustrated in »Figure 9.2.«

In the diagram in »Figure 9.2«, called a "directed acyclic graph" (or "DAG"), some of the classes are base classes for more than one derived class. However, the reverse is not true: there is only one direct base class for any given derived class. The graph in »Figure 9.2« depicts a "single inheritance" structure.

Note  Directed acyclic graphs are not unique to single inheritance. They are also used to depict multiple-inheritance graphs. This topic is covered in »Multiple Inheritance«.

In inheritance, the derived class contains the members of the base class plus any new members you add. As a result, a derived class can refer to members of the base class (unless those members are redefined in the derived class). The scope-resolution operator (::) can be used to refer to members of direct or indirect base classes when those members have been redefined in the derived class. Consider this example:

class Document
{
public:
    char *Name;           // Document name.
    void  PrintNameOf();  // Print name.
};

// Implementation of PrintNameOf function from class Document.
void Document::PrintNameOf()
{
    cout << Name << endl;
}

class Book : public Document
{
public:
    Book( char *name, long pagecount );
private:
    long  PageCount;
};

// Constructor from class Book.
Book::Book( char *name, long pagecount )
{
    Name = new char[ strlen( name ) + 1 ];
    strcpy( Name, name );
    PageCount = pagecount;
};

Note that the constructor for Book, (Book::Book), has access to the data member, Name. In a program, an object of type Book can be created and used as follows:

//  Create a new object of type Book. This invokes the
//   constructor Book::Book.
Book LibraryBook( "Programming Windows, 2nd Ed", 944 );

...

//  Use PrintNameOf function inherited from class Document.
LibraryBook.PrintNameOf();

As the preceding example demonstrates, class-member and inherited data and functions are used identically. If the implementation for class Book calls for a reimplementation of the PrintNameOf function, the function that belongs to the Document class can be called only by using the scope-resolution (::) operator:

class Book : public Document
{
    Book( char *name, long pagecount );
    void PrintNameOf();
    long  PageCount;
};
void Book::PrintNameOf()
{
    cout << "Name of book: ";
    Document::PrintNameOf();
}

Pointers and references to derived classes can be implicitly converted to pointers and references to their base classes if there is an accessible, unambiguous base class. The following code demonstrates this concept using pointers (the same principle applies to references):

#include <iostream.h>

main()
{
    Document *DocLib[10];  // Library of ten documents.

    for( int i = 0; i < 10; ++i )
    {
        cout << "Type of document: "
             << "P)aperback, M)agazine, H)elp File, C)BT"
             << endl;

        char cDocType;
        cin >> cDocType;

        switch( tolower( cDocType ) )
        {
        case 'p':
            DocLib[i] = new PaperbackBook;
            break;

        case 'm':
            DocLib[i] = new Magazine;
            break;

        case 'h':
            DocLib[i] = new HelpFile;
            break;

        case 'c':
            DocLib[i] = new ComputerBasedTraining;
            break;

        default:
            --i;
            break;
       }
    }

    for( i = 0; i < 10; ++i )
        DocLib[i]->PrintNameOf();

    return 0;
}

In the switch statement in the preceding example, objects of different types are created, depending on what the user specified for cDocType. However, because these types are all derived from the Document class, there is an implicit conversion to Document *. As a result, DocLib is a "heterogeneous list" (a list in which not all objects are of the same type) containing different kinds of objects.

Because the Document class has a PrintNameOf function, it can print the name of each book in the library, although it may omit some of the information specific to the type of document (page count for Book, number of bytes for HelpFile, and so on).

Note  Forcing the base class to implement a function such as PrintNameOf is often not the best design. Virtual functions, described in »Virtual Functions«, offer other design alternatives.


  Multiple Inheritance

Later versions of C++ introduced a "multiple inheritance" model for inheritance. In a multiple-inheritance graph, the derived classes may have a number of direct base classes. Consider the graph in »Figure 9.3.«

The diagram in »Figure 9.3« shows a class, CollectibleString. It is like a Collectible (something that can be contained in a collection), and it is like a String. Multiple inheritance is a good solution to this kind of problem (where a derived class has attributes of more than one base class) because it is easy to form a CollectibleCustomer, CollectibleWindow, and so on.

If the properties of either class are not required for a particular application, either class can be used alone or in combination with other classes. Therefore, given the hierarchy depicted in »Figure 9.3« as a basis, you can form noncollectible strings and collectibles that are not strings. This flexibility is not possible using single inheritance.


  Virtual Functions

Some class hierarchies are broad but have many things in common. The common code is implemented in a base class, whereas the specific code is in the derived classes.

It is important for the base classes to establish a protocol through which the derived classes can attain maximum functionality. These protocols are commonly implemented using virtual functions. Sometimes the base class provides a default implementation for such functions. In a class hierarchy such as the Document hierarchy in »Figure 9.2«, two useful functions are Identify and WhereIs.

When called, the Identify function returns a correct identification, appropriate to the kind of document: For a Book, a function call such as doc->Identify() must return the ISBN number; however, for a HelpFile, a product name and revision number are probably more appropriate. Similarly, WhereIs should return a row and shelf for a Book, but for a HelpFile it should return a disk location — perhaps a directory and filename.

It is important that all implementations of the Identify and WhereIs functions return the same kind of information. In this case, a character string is appropriate.

These functions are implemented as virtual functions and then invoked using a pointer to a base class. The binding to the actual code occurs at run time, selecting the correct Identify or WhereIs function.


  Abstract Classes

Classes can be implemented to enforce a protocol. These classes are called "abstract classes" because no object of the class type can be created. They exist solely for derivation.

Classes are abstract classes if they contain pure virtual functions or if they inherit pure virtual functions and do not provide an implementation for them. Pure virtual functions are virtual functions declared with the pure-specifier (= 0), as follows:

virtual char *Identify() = 0;

The base class, Document, might impose the following protocol on all derived classes:

•	 An appropriate Identify function must be implemented.

•	 An appropriate WhereIs function must be implemented.

By specifying such a protocol when designing the Document class, the class designer can be assured that no nonabstract class can be implemented without
Identify and WhereIs functions. The Document class, therefore, contains these declarations:

class Document
{
public:
    ...
    //  Requirements for derived classes: They must implement
    //   these functions.
    virtual char *Identify() = 0;
    virtual char *WhereIs() = 0;
    ...
};


  Base Classes

As discussed previously, the inheritance process causes a new derived class to be created that is made up of the members of the base class(es) plus any new members the derived class adds. In a multiple-inheritance situation, it is possible to construct an inheritance graph where the same base class is part of more than one of the derived classes. »Figure 9.4« shows such a graph.

In »Figure 9.4«, pictorial representations of the components of CollectibleString and CollectibleSortable are shown. However, the base class, Collectible, is in CollectibleSortableString through the CollectibleString path and the CollectibleSortable path. To eliminate this kind of redundancy, such classes can be declared as virtual base classes when they are inherited.

For information about declaring virtual base classes and how objects with virtual base classes are composed, see »Virtual Base Classes«.


  9.2  Multiple Base Classes

As described in »Multiple Inheritance«, a class can be derived from more than one base class. In a multiple-inheritance model (where classes are derived from more than one base class), the base classes are specified using the base-list grammar element (see "Syntax" in »Overview«). For example, the class declaration for CollectionOfBook, derived from Collection and Book, can be specified:

class CollectionOfBook : public Book, public Collection
{
    // New members
};

The order in which base classes are specified is not significant except in certain cases where constructors and destructors are invoked. In these cases, the order in which base classes are specified affects the following:

•	The order in which initialization by constructor takes place. If your code relies on the Book portion of CollectionOfBook to be initialized before the
Collection part, the order of specification is significant. Initialization takes place in the order the classes are specified in the base-list.

•	The order in which destructors are invoked to clean up. Again, if a particular "part" of the class must be present when the other part is being destroyed, the order is significant. Destructors are called in the reverse order of the classes specified in the base-list.

Note  The order of specification of base classes can affect the memory layout of the class, but it often does not. Do not make any programming decisions based on the order of base members in memory.

When specifying the base-list, you cannot specify the same class name more than once. However, it is possible for a class to be an indirect base to a derived class more than once.


  Virtual Base Classes

Because a class can be an indirect base class to a derived class more than once, C++ provides a way to optimize the way such base classes work. Consider the class hierarchy in »Figure 9.5«, which illustrates a simulated lunch line.

In »Figure 9.5«, Queue is the base class for both CashierQueue and LunchQueue. However, when both classes are combined to form LunchCashierQueue, the following problem arises: the new class contains two subobjects of type Queue, one from CashierQueue and the other from LunchQueue. »Figure 9.6« shows the conceptual memory layout (the actual memory layout might be optimized).

Note that there are two Queue subobjects in the LunchCashierQueue object. The following code declares Queue to be a virtual base class:

class Queue
{
    // Member list
};

class CashierQueue : virtual public Queue
{
    // Member list
};

class LunchQueue : virtual public Queue
{
    // Member list
};

class LunchCashierQueue : public LunchQueue, public CashierQueue
{
    // Member list
};

The virtual keyword ensures that only one copy of the subobject Queue is included (see »Figure 9.7«).

A class can have both a virtual component and a nonvirtual component of a given type. This happens in the conditions illustrated in »Figure 9.8.«

In »Figure 9.8«, CashierQueue and LunchQueue use Queue as a virtual base class. However, TakeoutQueue specifies Queue as a base class, not a virtual base class. Therefore, LunchTakeoutCashierQueue has two subobjects of type Queue: one from the inheritance path that includes LunchCashierQueue and one from the path that includes TakeoutQueue. This is illustrated in »Figure 9.9.«

Note  Virtual inheritance provides significant size benefits when compared with nonvirtual inheritance. However, it can introduce extra processing overhead.

If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or a destructor for the derived base class calls that function using a pointer to the virtual base class, the compiler may introduce additional hidden "vtordisp" fields into the classes with virtual bases. The /vd0 command-line option suppresses the addition of the hidden vtordisp constructor/destructor displacement member. The /vd1 command-line option, the default, enables them where they are necessary. Turn off vtordisps only if you are sure that all class constructors and destructors call virtual functions virtually.

The /vd command-line option affects an entire compilation module. Use the vtordisp pragma to suppress and then reenable vtordisp fields on a class-by-class basis:

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )


  Name Ambiguities

Multiple inheritance introduces the possibility for names to be inherited along more than one path. The class-member names along these paths are not necessarily unique. These name conflicts are called "ambiguities."

Any expression that refers to a class member must make an unambiguous reference. The following example shows how ambiguities develop:

// Declare two base classes, A and B.
class A
{
public:
    unsigned a;
    unsigned b();
};

class B
{
public:
    unsigned a();  // Note that class A also has a member "a"
    int b();       //  and a member "b".
    char c;
};

// Define class C as derived from A and B.
class C : public A, public B
{
};

Given the preceding class declarations, code such as the following is ambiguous because it is unclear whether b refers to the b in A or in B:

C *pc = new C;

pc->b();

Consider the preceding example. Because the name a is a member of both class A and class B, the compiler cannot discern which a designates the function to be called. Access to a member is ambiguous if it can refer to more than one function, object, type, or enumerator.

The compiler detects ambiguities by performing tests in this order:

1.	If access to the name is ambiguous (as just described), an error message is generated.

2.	If overloaded functions are unambiguous, they are resolved. (For more information about function overloading ambiguity, see »Argument Matching« in Chapter 12.)

3.	If access to the name violates member-access permission, an error message is generated. (For more information, see »Chapter 10, Member-Access Control.«)

When an expression produces an ambiguity through inheritance, you can manually resolve it by qualifying the name in question with its class name. To make the preceding example compile properly with no ambiguities, use code such as:

C *pc = new C;

pc->B::a();

Note  When C is declared, it has the potential to cause errors when B is referenced in the scope of C. No error is issued, however, until an unqualified reference to B is actually made in C's scope.


  Ambiguities and Virtual Base Classes

If virtual base classes are used, functions, objects, types, and enumerators can be reached through multiple-inheritance paths. Because there is only one instance of the base class, there is no ambiguity when accessing these names.

»Figure 9.10« shows how objects are composed using virtual and nonvirtual inheritance.

In »Figure 9.10«, accessing any member of class A through nonvirtual base classes causes an ambiguity; the compiler has no information that explains whether to use the subobject associated with B or the subobject associated with C. However, when A is specified as a virtual base class, there is no question which subobject is being accessed.


  Dominance

It is possible for more than one name (function, object, or enumerator) to be reached through an inheritance graph. Such cases are considered ambiguous with nonvirtual base classes. They are also ambiguous with virtual base classes, unless one of the names "dominates" the others.

A name dominates another name if it is defined in both classes and one class is derived from the other. The dominant name is the name in the derived class; this name is used when an ambiguity would otherwise have arisen, as shown in the following example:

class A
{
public:
    int a;
};

class B : public virtual A
{
public:
    int a();
};

class C : public virtual A
{
   ...
};

class D : public B, public C
{
public:
    D() { a(); } // Not ambiguous. B::a() dominates A::a.
};


  Ambiguous Conversions

Explicit and implicit conversions from pointers or references to class types can cause ambiguities. »Figure 9.11« shows the following:

•	The declaration of an object of type D.

•	The effect of applying the address-of operator (&) to that object. Note that the address-of operator always supplies the base address of the object.

•	The effect of explicitly converting the pointer obtained using the address-of operator to the base-class type A. Note that coercing the address of the object to type A* does not always provide the compiler with enough information as to which subobject of type A to select; in this case, two subobjects exist.

The conversion to type A* (pointer to A) is ambiguous because there is no way to discern which subobject of type A is the correct one. Note that you can avoid the ambiguity by explicitly specifying which subobject you mean to use, as follows:

(A *)(B *)&d       // Use B subobject.
(A *)(C *)&d       // Use C subobject.


  9.3  Virtual Functions

"Virtual functions" are functions that ensure that the correct function is called for an object, regardless of the expression used to make the function call.

Suppose a base class contains a function declared as virtual and a derived class defines the same function. The function from the derived class is invoked for objects of the derived class, even if it is called using a pointer or reference to the base class. The following example shows a base class that provides an implementation of the PrintBalance function:

class Account
{
public:
                   Account( double d );  // Constructor.
    virtual double GetBalance();         // Obtain balance.
    virtual void   PrintBalance();       // Default implementation.
private:
    double _balance;
};

// Implementation of constructor for Account.
double Account::Account( double d )
{
    _balance = d;
}

// Implementation of GetBalance for Account.
double Account::GetBalance()
{
    return _balance;
}
// Default implementation of PrintBalance.
void Account::PrintBalance()
{
    cerr << "Error. Balance not available for base type."
         << endl;
}

Two derived classes, CheckingAccount and SavingsAccount, can be created as follows:

class CheckingAccount : public Account
{
public:
    void PrintBalance();
};

// Implementation of PrintBalance for CheckingAccount.
void CheckingAccount::PrintBalance()
{
    cout << "Checking account balance: " << GetBalance();
}

class SavingsAccount : public Account
{
public:
    void PrintBalance();
};

// Implementation of PrintBalance for SavingsAccount.
void SavingsAccount::PrintBalance()
{
    cout << "Savings account balance: " << GetBalance();
}

The PrintBalance function in the derived classes is virtual because it is declared as virtual in the base class, Account. To call virtual functions such as
PrintBalance, code such as the following can be used:

// Create objects of type CheckingAccount and SavingsAccount.
CheckingAccount *pChecking = new CheckingAccount( 100.00 );
SavingsAccount  *pSavings  = new SavingsAccount( 1000.00 );

// Call PrintBalance using a pointer to Account.
Account *pAccount = pChecking;
pAccount->PrintBalance();

// Call PrintBalance using a pointer to Account.
pAccount = pSavings;
pAccount->PrintBalance();

In the preceding code, the calls to PrintBalance are identical, except for the object pAccount points to. Because PrintBalance is virtual, the version of the function defined for each object is called. The PrintBalance function in the derived classes CheckingAccount and SavingsAccount "override" the function in the base class Account.

If a class is declared that does not provide an overriding implementation of the PrintBalance function, the default implementation from the base class Account is used.

Functions in derived classes override virtual functions in base classes only if their type is the same. A function in a derived class cannot differ from a virtual function in a base class in its return type only; the argument list must differ as well.

When calling a function using pointers or references, the following rules apply:

•	A call to a virtual function is resolved according to the underlying type of object for which it is called.

•	A call to a nonvirtual function is resolved according to the type of the pointer or reference.

The following example shows how virtual and nonvirtual functions behave when called through pointers:

#include <iostream.h>

// Declare a base class.
class Base
{
public:
    virtual void NameOf();          // Virtual function.
            void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Base::NameOf()
{
    cout << "Base::NameOf\n";
}

void Base::InvokingClass()
{
    cout << "Invoked by Base\n";
}

// Declare a derived class.
class Derived : public Base
{
public:
    void NameOf();          // Virtual function.
    void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Derived::NameOf()
{
    cout << "Derived::NameOf\n";
}

void Derived::InvokingClass()
{
    cout << "Invoked by Derived\n";
}

void main()
{
    // Declare an object of type Derived.
    Derived aDerived;
    // Declare two pointers, one of type Derived * and the other
    //  of type Base *, and initialize them to point to aDerived.
    Derived *pDerived = &aDerived;
    Base    *pBase    = &aDerived;

    // Call the functions.
    pBase->NameOf();           // Call virtual function.
    pBase->InvokingClass();    // Call nonvirtual function.
    pDerived->NameOf();        // Call virtual function.
    pDerived->InvokingClass(); // Call nonvirtual function.
}

The output from this program is:

Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived

Note that regardless of whether the NameOf function is invoked through a pointer to Base or a pointer to Derived, it calls the function for Derived. It calls the function for Derived because NameOf is a virtual function, and both pBase and pDerived point to an object of type Derived.

Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual.

The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.

Virtual functions in a base class must be defined unless they are declared using the pure-specifier. (For more information about pure virtual functions, see »Abstract Classes«.)

The virtual function-call mechanism can be suppressed by explicitly qualifying the function name using the scope-resolution operator (::). Consider the preceding example. To call PrintBalance in the base class, use code such as the following:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

pChecking->Account::PrintBalance();  //  Explicit qualification.

Account *pAccount = pChecking;  // Call Account::PrintBalance

pAccount->Account::PrintBalance();   //  Explicit qualification.

Both calls to PrintBalance in the preceding example suppress the virtual
function-call mechanism.


  9.4  Abstract Classes

Abstract classes act as expressions of general concepts from which more specific classes can be derived. You cannot create an object of an abstract class type; however, you can use pointers and references to abstract class types.

A class that contains at least one pure virtual function is considered an abstract class. Classes derived from the abstract class must implement the pure virtual function or they, too, are abstract classes.

A virtual function is declared as "pure" by using the pure-specifier syntax (described in »Abstract Classes«). Consider the example presented in »Virtual Functions«. The intent of class Account is to provide general functionality, but objects of type Account have insufficient specificity to be meaningful. Therefore, Account is a good candidate for an abstract class:

class Account
{
public:
                   Account( double d );  // Constructor.
    virtual double GetBalance();         // Obtain balance.
    virtual void   PrintBalance() = 0;   // Pure virtual function.
private:
    double _balance;
};

The only difference between this declaration and the previous one is that
PrintBalance is declared with the pure specifier (= 0).


  Restrictions on Using Abstract Classes

Abstract classes cannot be used for:

•	Variables or member data

•	Argument types

•	Function return types

•	Types of explicit conversions

Another restriction is that if the constructor for an abstract class calls a pure virtual function, either directly or indirectly, the result is undefined. However, constructors and destructors for abstract classes can call other member functions.

Pure virtual functions can be defined for abstract classes, but they can be called directly only by using the syntax:

abstract-class-name :: function-name( )

This helps when designing class hierarchies whose base class(es) include pure virtual destructors, because base class destructors are always called in the process of destroying an object. Consider the following example:

#include <iostream.h>

// Declare an abstract base class with a pure virtual destructor.
class base
{
public:
    base() {}
    virtual ~base()=0;
};

// Provide a definition for destructor.
base::~base()
{
}

class derived:public base
{
public:
    derived() {}
    ~derived(){}
};

void main()
{
    derived *pDerived = new derived;

    delete pDerived;
}

When the object pointed to by pDerived is deleted, the destructor for class derived is called and then the destructor for class base is called. The empty implementation for the pure virtual function ensures that at least some implementation exists for the function.

Note  In the example above, the pure virtual function base::~base is called implicitly from derived::~derived. It is also possible to call pure virtual functions explicitly using a fully qualified member-function name.


  9.5  Summary of Scope Rules

This section supplements »Scope« in Chapter 2 by adding the concepts pertaining to classes.


  Ambiguity

The use of a name must be unambiguous within its scope (up to the point where overloading is determined). If the name denotes a function, the function must be unambiguous with respect to number and type of arguments. If the name remains unambiguous, member-access rules are applied. (Member-access control is described in »Chapter 10«.)


  Global Names

A name of an object, function, or enumerator is global if it is introduced outside any function or class or prefixed by the global unary scope operator (::) and if it is not used in conjunction with any of these binary operators:

•	Scope-resolution (::)

•	Member-selection for objects and references (.)

•	Member-selection for pointers (−>)


  Names and Qualified Names

Names used with the binary scope-resolution operator (::) are called "qualified names." The name specified after the binary scope-resolution operator must be a member of the class specified on the left of the operator or a member of its base class(es).

Names specified after the member-selection operator (. or −>) must be members of the class type of the object specified on the left of the operator or members of its base class(es). Names specified on the right of the member-selection operator (−>) can also be objects of another class type, provided that the left-hand side of −> is a class object and that the class defines an overloaded member-selection operator (−>) that evaluates to a pointer to some other class type. (This provision is discussed in more detail in »Class Member Access« in Chapter 12.)

The compiler searches for names in the following order:

1.	Current block scope if name is used inside a function; otherwise, global scope.

2.	If the name is not found in the current block scope, the compiler searches outward through each enclosing block scope, including the outermost function scope (which includes function arguments).

3.	If the name is still not found and the name is used inside a member function, the class's scope is searched for the name.

4.	If the name is still not found, the class's base classes are searched for the name.

5.	If the name is still not found, the enclosing nested class scope (if any) and its bases are searched. The search continues until the outermost enclosing class scope is searched.

6.	If the name is still not found, global scope is searched.

However, you can make modifications to this search order as follows:

1.	Names preceded by :: force the search to begin at global scope.

2.	Names preceded by the class, struct, and union keywords force the compiler to search only for class, struct, or union names.

3.	Names on the left side of the scope-resolution operator (::) can be only class, struct, or union names.

If the name refers to a nonstatic member but is used in a static member function, an error message is generated. Similarly, if the name refers to any nonstatic member in an enclosing class, an error message is generated because enclosed classes do not have enclosing-class this pointers.


  Function Argument Names

Function argument names in function definitions are considered to be in the scope of the outermost block of the function. Therefore, they are local names and go out of scope when the function is exited.

Function argument names in function declarations (prototypes) are in local scope of the declaration and go out of scope at the end of the declaration.

Default arguments are in the scope of the argument for which they are the default, as described in the preceding two paragraphs. However, they cannot access local variables or nonstatic class members. Default arguments are evaluated at the point of the function call, but they are evaluated in the function declaration's original scope. Therefore, the default arguments for member functions are always evaluated in class scope.


  Constructor Initializers

Constructor initializers (described in »Initializing Bases and Members« in Chapter 11) are evaluated in the scope of the outermost block of the constructor for which they are specified. Therefore, they can use the constructor's argument names.


Chapter 10: Member-Access Control
  Chapter 10  Member-Access Control

C++ allows programmers to specify the level of access to member data and functions. There are three levels of access: public, protected, and private. This chapter explains how access control applies to objects of class type and to derived classes.


  10.1  Controlling Access to Class Members

As a programmer, you can increase the integrity of software built with C++ by controlling access to class member data and functions. Class members can be declared as having private, protected, or public access, as shown in Table 10.1.

Table 10.1    Member-Access Control

Type of Access	Meaning
private	Class members declared as private can be used only by member functions and friends (classes or functions) of the class.
protected	Class members declared as protected can be used by member functions and friends (classes or functions) of the class. Additionally, they can be used by classes derived from the class.
public	Class members declared as public can be used by any function.
Access control prevents you from using objects in ways they were not intended to be used. This protection is lost when explicit type conversions (casts) are performed.

Note  Access control is equally applicable to all names: member functions, member data, nested classes, and enumerators.

The default access to class members (members of a class type declared using the class keyword) is private; the default access to struct and union members is public. For either case, the current access level can be changed using the public, private, or protected keyword.


  10.2  Access Specifiers

In class declarations, members can have access specifiers.

Syntax

access-specifier  :  member-list(opt)

The access-specifier determines the access to the names that follow it, up to the next access-specifier or the end of the class declaration. »Figure 10.1« illustrates this concept.

Although only two access specifiers are shown in »Figure 10.1«, there is no limit to the number of access specifiers in a given class declaration. For example, the Point class in »Figure 10.1« could just as easily be declared using multiple access specifiers as follows:

class Point
{
public:                  // Declare public constructor.
    Point( int, int );
private:                 // Declare private state variable.
    int _x;

public:                  // Declare public constructor.
    Point();
public:                  // Declare public accessor.
    int &x( int );
private:                 // Declare private state variable.
    int _y;
public:                  // Declare public accessor.
    int &y( int );
};

Note that there is no specific order required for member access, as shown in the example above. The allocation of storage for objects of class types is implementation dependent, but members are guaranteed to be assigned successively higher memory addresses between access specifiers.


  10.3  Access Specifiers for Base Classes

Two factors control which members of a base class are accessible in a derived class; these same factors control access to the inherited members in the derived class:

•	Whether the derived class declares the base class using the public access specifier in the class-head (class-head is described in "Syntax" in »Defining Class Types« in Chapter 8).

•	What the access to the member is in the base class.

Table 10.2 shows the interaction between these factors.

Table 10.2    Determining Base-Class Member Access

Member Access in Base Class
private	protected	public
Always inaccessible regardless of derivation access	Private in derived class if you use private derivation	Private in derived class if you use private derivation
	Protected in derived class if you use protected derivation	Protected in derived class if you use protected derivation
	Protected in derived class if you use public derivation	Public in derived class if you use public derivation
The following example illustrates this:

class BaseClass
{
public:
    int PublicFunc();    // Declare a public member.
protected:
    int ProtectedFunc(); // Declare a protected member.
private:
    int PrivateFunc();   // Declare a private member.
};

// Declare two classes derived from BaseClass.
class DerivedClass1 : public BaseClass
{ };

class DerivedClass2 : private BaseClass
{ };

In DerivedClass1, the member function PublicFunc is a public member and ProtectedFunc is a protected member because BaseClass is a public base class. PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

In DerivedClass2, the functions PublicFunc and ProtectedFunc are considered private members because BaseClass is a private base class. Again, PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

You can declare a derived class without a base-class access specifier. In such a case, the derivation is considered private if the derived class declaration uses the class keyword. The derivation is considered public if the derived class declaration uses the struct keyword. For example, the following code:

class Derived : Base
...

is equivalent to:

class Derived : private Base
...

Similarly, the following code:

struct Derived : Base
...

is equivalent to:

struct Derived : public Base
...

Note that members declared as having private access are not accessible to functions or derived classes unless those functions or classes are declared using the friend declaration in the base class.

A union type cannot have a base class.

Note  When specifying a private base class, it is advisable to explicitly use the private keyword so users of the derived class understand the member access.


  Access Control and Static Members

When you specify a base class as private, it affects only nonstatic members. Public static members are still accessible in the derived classes. However, accessing members of the base class using pointers, references, or objects can require a conversion, at which time access control is again applied. Consider the following example:

class Base
{
public:
    int Print();             // Nonstatic member.
    static int CountOf();    // Static member.
};

// Derived1 declares Base as a private base class.
class Derived1 : private Base
{
};
// Derived2 declares Derived1 as a public base class.
class Derived2 : public Derived1
{
    int ShowCount();    // Nonstatic member.
};

// Define ShowCount function for Derived2.
int Derived2::ShowCount()
{
   // Call static member function CountOf explicitly.
    int cCount = Base::CountOf();     // OK.

   // Call static member function CountOf using pointer.
    cCount = this->CountOf();  // Error. Conversion of
                               //  Derived2 * to Base * not
                               //  permitted.
    return cCount;
}

In the preceding code, access control prohibits conversion from a pointer to Derived2 to a pointer to Base. The this pointer is implicitly of type Derived2 *. To select the CountOf function, this must be converted to type Base *. Such a conversion is not permitted because Base is a private indirect base class to Derived2. Conversion to a private base class type is acceptable only for pointers to immediate derived classes. Therefore, pointers of type Derived1 * can be converted to type Base *.

Note that calling the CountOf function explicitly, without using a pointer, reference, or object to select it, implies no conversion. Therefore, the call is allowed.

Members and friends of a derived class, T, can convert a pointer to T to a pointer to a private direct base class of T.


  10.4  Friends

In some circumstances, it is more convenient to grant member-level access to functions that are not members of a class or to all functions in a separate class. The friend keyword allows programmers to designate either the specific functions or the classes whose functions can access not only public members but also protected and private members.


  Friend Functions

Friend functions are not considered class members; they are normal external functions that are given special access privileges. Friends are not in the class's scope, and they are not called using the member-selection operators (. and  − >) unless they are members of another class. The following example shows a Point class and an overloaded operator, operator+. (This example primarily illustrates friends, not overloaded operators. For more information about overloaded operators, see »Overloaded Operators« in Chapter 12.)

#include <iostream.h>

// Declare class Point.
class Point
{
public:
    // Constructors
    Point() { _x = _y = 0; }
    Point( unsigned x, unsigned y ) { _x = x; _y = y; }
    // Accessors
    unsigned x() { return _x; }
    unsigned y() { return _y; }
    void     Print() { cout << "Point(" << _x << ", " << _y << ")"
                            << endl; }

    // Friend function declarations
    friend Point operator+( Point& pt, int nOffset );
    friend Point operator+( int nOffset, Point& pt );

private:
    unsigned _x;
    unsigned _y;
};

// Friend-function definitions
//
// Handle Point + int expression.
Point operator+( Point& pt, int nOffset )
{
    Point ptTemp = pt;
    // Change private members _x and _y directly.
    ptTemp._x += nOffset;
    ptTemp._y += nOffset;

    return ptTemp;
}

// Handle int + Point expression.
Point operator+( int nOffset, Point& pt )
{
    Point ptTemp = pt;

    // Change private members _x and _y directly.
    ptTemp._x += nOffset;
    ptTemp._y += nOffset;

    return ptTemp;
}

// Test overloaded operator.
main()
{
    Point pt( 10, 20 );
    pt.Print();

    pt = pt + 3;     // Point + int
    pt.Print();

    pt = 3 + pt;     // int + Point
    pt.Print();

    return 0;
}

When the expression pt + 3 is encountered in the main function, the compiler determines if an appropriate user-defined operator+ exists. In this case, the function operator+( Point pt, int nOffset ) matches the operands, and a call to the function is issued. In the second case (the expression 3 + pt), the function operator+( Point pt, int nOffset ) matches the supplied operands. Therefore,  supplying these two forms of operator+ preserves the commutative properties of the + operator.

A user-defined operator+ can be written as a member function, but it takes only one explicit argument: the value to be added to the object. As a result, the commutative properties of addition cannot be correctly implemented with member functions; they must use friend functions instead.

Notice that both versions of the overloaded operator+ function are declared as friends in class Point. Both declarations are necessary — when friend declarations name overloaded functions or operators, only the particular functions specified by the argument types become friends. Suppose a third operator+ function were declared as follows:

Point &operator+( Point &pt, Point &pt );

The operator+ function in the preceding example is not a friend of class Point, simply because it has the same name as two other functions that are declared as friends.

Because friend declarations are unaffected by access specifiers, they can be declared in any section of the class declaration.


  Class Member Functions and Classes as Friends

Class member functions can be declared as friends in other classes. Consider the following example:

class A
{
private:
    int _a;
    friend int B::Func1( A );   //  Grant friend access to one
                                //   function in class B.
};

class B
{
public:
    int Func1( A a ) { return a._a; } //  OK: this is a friend.
    int Func2( A a ) { return a._a; } //  Error: _a is a private
                                      //   member.
};

In the preceding example, only the function B::Func1( A ) is granted friend access to class A. Therefore, access to the private member _a is correct in function b of class B but not in function c.

Suppose the friend declaration in class A had been:

friend class B;

In that case, all member functions in class B would have been granted friend access to class A. Note that "friendship" cannot be inherited, nor is there any "friend of a friend" access. »Figure 10.2« shows four class declarations: Base, Derived, aFriend, and anotherFriend. Only class aFriend has direct access to the private members of Base (and to any members Base might have inherited).


  Friend Declarations

If you declare a friend function that was not previously declared, that function is exported to the enclosing nonclass scope.

Functions declared in a friend declaration are treated as if they had been declared using the extern keyword. (For more information about extern, see »Static Storage-Class Specifiers« in Chapter 6.)

Although functions with global scope can be declared as friends prior to their prototypes, member functions cannot be declared as friends before the appearance of their complete class declaration. The following code shows why this fails:

class ForwardDeclared;   // Class name is known.

class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // Error.
};

The preceding example enters the class name ForwardDeclared into scope, but the complete declaration — specifically, the portion that declares the function IsAFriend — is not known. Therefore, the friend declaration in class HasFriends generates an error.

To declare two classes that are friends of one another, the entire second class must be specified as a friend of the first class. The reason for this restriction is that the compiler has enough information to declare individual friend functions only at the point where the second class is declared.

Note  Although the entire second class must be a friend to the first class, you can select which functions in the first class will be friends of the second class.


  Defining Friend Functions in Class Declarations

Friend functions can be defined inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration).

Friend functions defined inside class declarations are not considered in the scope of the enclosing class; they are in file scope.


  10.5  Protected Member Access

Class members declared as protected can be used only by the following:

•	Member functions of the class that originally declared these members.

•	Friends of the class that originally declared these members.

•	Classes derived with public or protected access from the class that originally declared these members.

•	Direct privately derived classes that also have private access to protected members.

Protected members are not as private as private members, which are accessible only to members of the class in which they are declared, but they are not as public as public members, which are accessible in any function.

Protected members that are also declared as static are accessible to any friend or member function of a derived class. Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.


  10.6  Access to Virtual Functions

The access control applied to virtual functions is determined by the type used to make the function call. Overriding declarations of the function do not affect the access control for a given type. For example:

class VFuncBase
{
public:
    virtual int GetState() { return _state; }
protected:
    int _state;
};

class VFuncDerived : public VFuncBase
{
private:
    int GetState() { return _state; }
};

...

VFuncDerived vfd;             // Object of derived type.
VFuncBase *pvfb = &vfd;       // Pointer to base type.
VFuncDerived *pvfd = &vfd;    // Pointer to derived type.
int State;

State = pvfb->GetState();     // GetState is public.
State = pvfd->GetState();     // GetState is private; error.

In the preceding example, calling the virtual function GetState using a pointer to type VFuncBase calls VFuncDerived::GetState, and GetState is treated as public. However, calling GetState using a pointer to type VFuncDerived is an access-control violation because GetState is declared private in class VFuncDerived.

Warning  The virtual function GetState can be called using a pointer to the base class VFuncBase. This does not mean that the function called is the base-class version of that function.


  10.7  Multiple Access

In multiple-inheritance lattices involving virtual base classes, a given name can be reached through more than one path. Because different access control can be applied along these different paths, the compiler chooses the path that gives the most access. See »Figure 10.3.«

In »Figure 10.3«, a name declared in class VBase is always reached through class RightPath. The right path is more accessible because RightPath declares VBase as a public base class, whereas LeftPath declares VBase as private.


Chapter 11: Special Member Functions
  Chapter 11  Special Member Functions

C++ defines several kinds of functions that can be declared only as class members — these are called "special member functions." These functions affect the way objects of a given class are created, destroyed, copied, and converted into objects of other types. Another important property of many of these functions is that they can be called implicitly (by the compiler).

The special member functions are described briefly in the following list:

•	Constructors. These functions enable automatic initialization of objects. See »Constructors«.

•	Destructors. These functions perform cleanup after objects are explicitly or implicitly destroyed. See »Destructors«.

•	Conversion functions. These are used to convert between class types and other types. See »Conversion Functions«.

•	The new operator. This is used to dynamically allocate storage. See »The operator new Function«.

•	The delete operator. This is used to release storage allocated using the new operator. See »The operator delete Function«.

•	The assignment operator (operator=). This operator is used when an assignment takes place. See »Compiler-Generated Copying«.

All of the items in the preceding list can be user-defined for each class.

Special member functions obey the same access rules as other member functions. The access rules are described in »Chapter 10, Member-Access Control.« Table 11.1 is a summary of how member and friend functions behave.

Table 11.1    Summary of Function Behavior

Function Type	Is Function Inherited from Base Class?	Can Function Be Virtual?	Can Function Return a Value?	Is Function a Member or Friend?	Will Compiler Generate Function if User Does Not?
Constructor	No	No	No	Member	Yes
Copy Constructor	No	No	No	Member	Yes
Destructor	No	Yes	No	Member	Yes
Conversion	Yes	Yes	No	Member	No
Assignment (operator=)	No	Yes	Yes	Member	Yes
new	Yes	No	void*	Static member	No
delete	Yes	No	void	Static member	No
Other member functions	Yes	Yes	Yes	Member	No
Friend functions	No	No	Yes	Friend	No


  11.1  Constructors

A member function with the same name as its class is a constructor function. Constructors cannot return values, even if they have return statements. Specifying a constructor with a return type is an error, as is taking the address of a constructor.

If a class has a constructor, each object of that type is initialized with the constructor prior to use in a program. (For more information about initialization, see »Initialization Using Special Member Functions«.)

Constructors are called at the point an object is created. Objects are created as:

•	Global (file-scoped or externally linked) objects.

•	Local objects, within a function or smaller enclosing block.

•	Dynamic objects, using the new operator. The new operator allocates an object on the program heap or "free store."

•	Temporary objects created by explicitly calling a constructor. (For more information, see »Temporary Objects«.)

•	Temporary objects created implicitly by the compiler. (For more information, see »Temporary Objects«.)

•	Data members of another class. Creating objects of class type, where the class type is composed of other class-type variables, causes each object in the class to be created.

•	Base class subobject of a class. Creating objects of derived class type causes the base class components to be created.


  What a Constructor Does

A constructor performs various tasks that are not visible to you as the programmer, even if you write no code for the constructor. These tasks are all associated with building a complete and correct instance of class type.

In Microsoft C++ (and some other implementations of C++), a constructor:

•	Initializes the object's virtual base pointer(s) (vbptr). This step is performed if the class has virtual base classes in the inheritance graph.

•	Calls base class and member constructors in the order of declaration.

•	Initializes the object's virtual function pointers (vfptr). This step is performed if the class has or inherits virtual functions. Virtual function pointers point to the class's virtual function table (v-table) and allow correct binding of virtual function calls to code.

•	Executes optional code in the body of the constructor function.

When the constructor is finished, the allocated memory is an object of a given class type. Because of the steps the constructor performs, "late binding" in the form of virtual functions can be resolved at the point of a virtual function call. The constructor has also constructed base classes and has constructed composed objects (objects included as data members). Late binding is the mechanism by which C++ implements polymorphic behavior for objects.


  Rules for Declaring Constructors

A constructor has the same name as its class. Any number of constructors can be declared, subject to the rules of overloaded functions. (For more information, see »Chapter 12, Overloading.«)

Syntax

class-name  (  argument-declaration-list (opt)   ) cv-mod-list (opt)

C++ defines two special kinds of constructors, default and copy constructors, described in Table 11.2.

Table 11.2    Default and Copy Constructors

Kind of Construction	Arguments	Purpose
Default constructor	Can be called with no arguments	Construct a default object of the class type
Copy constructor	Can accept a single argument of reference to same class type	Copy objects of the class type
Default constructors can be called with no arguments. However, you can declare a default constructor with an argument list, provided all arguments have defaults. Similarly, copy constructors must be declared in such a way that they can accept a single argument of reference to the same class type. More arguments can be supplied, provided all subsequent arguments have defaults.

If you do not supply any constructors, the compiler attempts to generate a default constructor. If you do not supply a copy constructor, the compiler attempts to generate one. These compiler-generated constructors are considered public member functions. Specifying a copy constructor with a first argument that is an object and not a reference generates an error.

A compiler-generated default constructor sets up the object (initializes vftables and vbtables, as described previously), and it calls the default constructors for base classes and members, but it takes no other action. Base class and member constructors are called only if they exist, if they are accessible, and if they are unambiguous.

A compiler-generated copy constructor sets up a new object and performs a memberwise copy of the contents of the object to be copied. If base class or member constructors exist, they are called; otherwise, bitwise copying is performed.

If all base and member classes of a class type have copy constructors that accept a const argument, the compiler-generated copy constructor accepts a single argument of type const type&. Otherwise, the compiler-generated copy constructor accepts a single argument of type type&.

You can use a constructor to initialize a const or volatile object, but the constructor itself cannot be declared as const or volatile. The only legal storage class for a constructor is inline; use of any other storage-class modifier, including the 32-bit-specific __declspec keyword, with a constructor causes a compiler error. Constructors and destructors cannot specify a calling convention other than the default, which is __stdcall for 32-bit targets and __pascal for 16-bit targets.

Constructors of base classes are not inherited by derived classes. When an object of derived class type is created, it is constructed starting with the base class components; then it moves to the derived class components. The compiler uses each base class's constructor as that part of the complete object is initialized (except in cases of virtual derivation, as described in »Initializing Base Classes«).


  Explicitly Called Constructors

Constructors can be explicitly called in a program to create objects of a given type. For example, to create two Point objects that describe the ends of a line, the following code can be written:

DrawLine( Point( 13, 22 ), Point( 87, 91 ) );

Two objects of type Point are created, passed to the function DrawLine, and destroyed at the end of the expression (the function call).

Another context in which a constructor is explicitly called is in an initialization:

Point pt = Point( 7, 11 );

An object of type Point is created and initialized using the constructor that accepts two arguments of type int.

Objects that are created by calling constructors explicitly, as in the preceding two examples, are unnamed and have a lifetime of the expression in which they are created. This is discussed in greater detail in »Temporary Objects«.


  Calling Member Functions and Virtual Functions from Within Constructors

Because the object has been completely set up (virtual tables have been initialized and so on) prior to the execution of the first line of user code, it is usually safe to call any member function from within a constructor. A potentially unsafe member function call has to do with calling a virtual member function for an abstract base class during construction or destruction.

Constructors can call virtual functions. When virtual functions are called, the function invoked is the function defined for the constructor's own class (or inherited from its bases). The following example shows what happens when a virtual function is called from within a constructor:

#include <iostream.h>

class Base
{
public:
    Base();             // Default constructor.
    virtual void f();   // Virtual member function.
};

Base::Base()
{
    cout << "Constructing Base sub-object\n";
    f();                // Call virtual member function
}                       //  from inside constructor.

void Base::f()
{
    cout << "Called Base::f()\n";
}

class Derived : public Base
{
public:
    Derived();          // Default constructor.
    void f();           // Implementation of virtual
};                      //  function f for this class.

Derived::Derived()
{
    cout << "Constructing Derived object\n";
}

void Derived::f()
{
    cout << "Called Derived::f()\n";
}

void main()
{
    Derived d;
}

When the preceding program is run, the declaration Derived d causes the following sequence of events to occur:

1.	The constructor for class Derived (Derived::Derived) is called.

2.	Prior to entering the body of the Derived class's constructor, the constructor for class Base (Base::Base) is called.

3.	Base::Base calls the function f, which is a virtual function. Ordinarily, Derived::f would be called because the object d is of type Derived. Because the Base::Base function is a constructor, the object is not yet of the Derived type, and Base::f is called.


  Constructors and Arrays

Arrays are constructed only using the default constructor. Constructors that either accept no arguments or constructors for which all arguments have a default are considered "default constructors." Arrays are always constructed in ascending order. This means that the initialization for each member of the array is done using the same constructor.


  Order of Construction

For derived classes and classes that have class-type member data, the order in which construction occurs helps you understand what portions of the object you can use in any given constructor.


  Construction and Inheritance

An object of derived type is constructed from the base class to the derived class by calling the constructors for each class in order. Each class's constructor can rely on its base classes being completely constructed.

For a complete description of initialization, including the order of initialization, see »Initializing Bases and Members«.


  Construction and Composed Classes

Classes that contain class-type data members are called "composed classes." When an object of a composed class type is created, the constructors for the contained classes are called before the class's own constructor.

For a more information about this kind of initialization, see »Initializing Bases and Members«.


  11.2  Destructors

"Destructor" functions are the inverse of constructor functions. They are called when objects are destroyed (deallocated). Designate a function as a class's destructor by preceding the class name with a tilde (~). For example, the destructor for class String is declared: ~String().

The destructor is commonly used to "clean up" when an object is no longer necessary. Consider the following declaration of a String class:

#include <string.h>

class String
{
public:
    String( char *ch );  // Declare constructor
    ~String();           //  and destructor.
private:
    char *_text;
};

// Define the constructor.
String::String( char *ch )
{
    // Dynamically allocate the correct amount of memory.
    _text = new char[strlen( ch ) + 1];

    // If the allocation succeeds, copy the initialization string.
    if( _text )
       strcpy( _text, ch );
}

// Define the destructor.
String::~String()
{
    // Deallocate the memory that was previously reserved
    //  for this string.
    delete[] _text;
}

In the preceding example, the destructor String::~String uses the delete operator to deallocate the space dynamically allocated for text storage.


  Declaring Destructors

Destructors are functions with the same name as the class but preceded by a tilde (~).

Syntax

~class-name()

or

class-name  ::  ~class-name()

The first form of the syntax is used for destructors declared or defined inside a class declaration; the second form is used for destructors defined outside a class declaration.

Several rules govern the declaration of destructors. Destructors:

•	Do not accept arguments.

•	Cannot specify any return type (including void).

•	Cannot return a value using the return statement.

•	Cannot be declared as const, volatile, or static. However, they can be invoked for the destruction of objects declared as const, volatile, or static.

•	Can be declared as virtual. Using virtual destructors, you can destroy objects without knowing their type — the correct destructor for the object is invoked using the virtual function mechanism. Note that destructors can also be declared as pure virtual functions for abstract classes.


  Using Destructors

Destructors are called when one of the following events occurs:

•	An object allocated using the new operator is explicitly deallocated using the delete operator. When objects are deallocated using the delete operator, memory is freed for the "most derived object," or the object that is a complete object and not a subobject representing a base class. This "most-derived object" deallocation is guaranteed to work only with virtual destructors. Deallocation may fail in multiple-inheritance situations where the type information does not correspond to the underlying type of the actual object.

•	A local (automatic) object with block scope goes out of scope.

•	The lifetime of a temporary object ends.

•	A program ends and global or static objects exist.

•	The destructor is explicitly called using the destructor function's fully qualified name. (For more information, see »Explicit Destructor Calls«.)

The cases described in the preceding list ensure that all objects can be destroyed with user-defined methods.

If a base class or data member has an accessible destructor, and if a derived class does not declare a destructor, the compiler generates one. This compiler-generated destructor calls the base class destructor and the destructors for members of the derived type. Default destructors are public. (For more information about accessibility, see »Access Specifiers for Base Classes« in Chapter 10.)

Destructors can freely call class member functions and access class member data. When a virtual function is called from a destructor, the function called is the function for the class currently being destroyed. (For more information, see »Order of Destruction«.)

There are two restrictions on the use of destructors. The first restriction is that you cannot take the address of a destructor. The second is that derived classes do not inherit their base class's destructors. Instead, as previously explained, they always override the base class's destructors.


  Order of Destruction

When an object goes out of scope or is deleted, the sequence of events in its complete destruction is as follows:

1.	The class's destructor is called, and the body of the destructor function is executed.

2.	Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration. The optional member initialization list used in construction of these members does not affect the order of construction or destruction. (For more information about initializing members, see »Initializing Bases and Members«.)

3.	Destructors for nonvirtual base classes are called in the reverse order of declaration.

4.	Destructors for virtual base classes are called in the reverse order of declaration.


  Nonvirtual Base Classes

When calling destructors for nonvirtual base classes, the destructors are called in the reverse order in which the base class names are declared. Consider the following class declaration:

class MultInherit : public Base1, public Base2
...

In the preceding example, the destructor for Base2 is called before the destructor for Base1.


  Virtual Base Classes

Destructors for virtual base classes are called in the reverse order of their appearance in a directed acyclic graph (depth-first, left-to-right, postorder traversal). »Figure 11.1« depicts an inheritance graph.

The following lists the class heads for the classes shown in »Figure 11.1.«

class A
class B
class C : virtual public A, virtual public B
class D : virtual public A, virtual public B
class E : public C, public D, virtual public B

To determine the order of destruction of the virtual base classes of an object of type E, the compiler builds a list by applying the following algorithm:

1.	Traverse the graph left, starting at the deepest point in the graph (in this case, E).

2.	Perform leftward traversals until all nodes have been visited. Note the name of the current node.

3.	Revisit the previous node (down and to the right) to find out if the node being remembered is a virtual base class.

4.	If the remembered node is a virtual base class, scan the list to see if it has already been entered. If it is not a virtual base class, ignore it.

5.	If the remembered node is not yet in the list, add it to the bottom of the list.

6.	Traverse the graph up and along the next path to the right.

7.	Go to step 2.

8.	When the last upward path is exhausted, note the name of the current node.

9.	Go to step 3.

10.	Continue this process until the bottom node is again the current node.

So, for class E, the order of destruction is:

1.	The nonvirtual base class E.

2.	The nonvirtual base class D.

3.	The nonvirtual base class C.

4.	The virtual base class B.

5.	The virtual base class A.

This process produces an ordered list of unique entries. No class name appears twice. Once the list is constructed, it is walked in reverse order, and the destructor for each of the classes in the list from the last to the first is called.

The order of construction or destruction is primarily important when constructors or destructors in one class rely on the other component being created first or persisting longer — for example, if the destructor for A (in the graph in »Figure 11.1«) relied on B still being present when its code executed, or vice versa.

Such interdependencies between classes in an inheritance graph are inherently dangerous because classes derived later can alter which is the leftmost path, thereby changing the order of construction and destruction.


  Explicit Destructor Calls

Calling a destructor explicitly is seldom necessary. However, it can be useful to perform cleanup of objects placed at absolute addresses. These objects are commonly allocated using a user-defined new operator that takes a placement argument. The delete operator cannot deallocate this memory because it is not allocated from the free store (for more information, see »The new and delete Operators«). A call to the destructor, however, can perform appropriate cleanup. To explicitly call the destructor for an object, s, of class String, use one of the following statements:

s.String::~String();     // Nonvirtual call
ps->String::~String();   // Nonvirtual call

s.~String();       // Virtual call
ps->~String();     // Virtual call

The notation for explicit calls to destructors, shown above, can be used regardless of whether the type defines a destructor. This allows the programmer to make such explicit calls without knowing if a destructor is defined for the type. An explicit call to a destructor where none is defined has no effect.


  11.3  Temporary Objects

In some cases, it is necessary for the compiler to create temporary objects. These temporary objects can be created for the following reasons:

•	To initialize a const reference with an initializer of a type different from that of the underlying type of the reference being initialized.

•	To store the return value of a function that returns a user-defined type. These temporaries are created only if your program does not copy the return value to an object. For example:

UDT Func1();    //  Declare a function that returns a user-defined
                //   type.

...

Func1();        //  Call Func1, but discard return value.
                //  A temporary object is created to store the return
                //   value.

Because the return value is not copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called. These overloaded operator functions return a user-defined type that often is not copied to another object.

Consider the expression ComplexResult = Complex1 + Complex2 + Complex3. The expression Complex1 + Complex2 is evaluated, and the result is stored in a temporary object. Next, the expression temporary + Complex3 is evaluated, and the result is copied to ComplexResult (assuming the assignment operator is not overloaded).

•	To store the result of a cast to a user-defined type. When an object of a given type is explicitly converted to a user-defined type, that new object is constructed as a temporary object.

Temporary objects have a lifetime that is defined by their point of creation and the point at which they are destroyed. Any expression that creates more than one temporary object eventually destroys them in the reverse order in which they were created. The points at which destruction occurs are shown in Table 11.3.

Table 11.3    Destruction Points for Temporary Objects

Reason Temporary Created	Destruction Point
Result of expression evaluation	All temporaries created as a result of expression evaluation are destroyed at the end of the expression statement (that is, at the semicolon), or at the end of the controlling expressions for for, if, while, do, and switch statements.
Result of expressions using the built-in (not overloaded) logical operators (|| and &&)	Immediately after the right operand. At this destruction point, all temporary objects created by evaluation of the right operand are destroyed.
Initializing const references	If an initializer is not an l-value of the same type as the reference being initialized, a temporary of the underlying object type is created and initialized with the initialization expression. This temporary object is destroyed immediately after the reference object to which it is bound is destroyed.


  11.4  Conversions

Objects of a given class type can be converted to objects of another type. This is done by constructing an object of the target class type from the source class type and copying the result to the target object. This process is called conversion by constructor. Objects can also be converted by user-supplied conversion functions.

When standard conversions (described in »Chapter 3, Standard Conversions,«) cannot completely convert from a given type to a class type, the compiler can select user-defined conversions to help complete the job. In addition to explicit type conversions, conversions take place when:

•	An initializer expression is not the same type as the object being initialized.

•	The type of argument used in a function call does not match the type of argument specified in the function declaration.

•	The type of the object being returned from a function does not match the return type specified in the function declaration.

•	Two expression operands must be of the same type.

•	An expression controlling an iteration or selection statement requires a different type from the one supplied.

A user-defined conversion is applied only if it is unambiguous; otherwise, an error message is generated. Ambiguity is checked at the point of usage. Hence, if the features that cause ambiguity are not used, a class can be designated with potential ambiguities and not generate any errors. Although there are many situations in which ambiguities arise, these are two leading causes of ambiguities:

•	A class type is derived using multiple inheritance, and it is unclear from which base class to select the conversion (see »Ambiguity« in Chapter 9).

•	An explicit type-conversion operator and a constructor for the same conversion exist (see »Conversion Functions«).

Both conversion by constructor and conversion by conversion functions obey access control rules, as described in »Chapter 10, Member-Access Control.« Access control is tested only after the conversion is found to be unambiguous.


  Conversion Constructors

A constructor that can be called with a single argument is used for conversions from the type of the argument to the class type. Such a constructor is called a conversion constructor. Consider the following example:

class Point
{
public:
    Point();
    Point( int );
    ...
};

Sometimes a conversion is required but no conversion constructor exists in the class. These conversions cannot be performed by constructors. The compiler does not look for intermediate types through which to perform the conversion. For example, suppose a conversion exists from type Point to type Rect and a conversion exists from type int to type Point. The compiler does not supply a conversion from type int to type Rect by constructing an intermediate object of type Point.


  Conversions and Constants

Although constants for built-in types such as int, long, and double can appear in expressions, no constants of class types are allowed (this is partly because classes usually describe an object complicated enough to make notation inconvenient). However, if conversion constructors from built-in types are supplied, constants of these built-in types can be used in expressions, and the conversions cause correct behavior. For example, a Money class can have conversions from types long and double:

class Money
{
public:
    Money( long );
    Money( double );
   ...
    Money operator+( const Money& );  // Overloaded addition operator.
};

Therefore, expressions such as the following can specify constant values:

Money AccountBalance = 37.89;
Money NewBalance = AccountBalance + 14L;

The second example involves the use of an overloaded addition operator, which is covered in the next chapter. Both examples cause the compiler to convert the constants to type Money before using them in the expressions.


  Drawbacks of Conversion Constructors

Because the compiler can select a conversion constructor implicitly, you relinquish control over what functions are called when. If it is essential to retain full control, do not declare any constructors that take a single argument; instead, define "helper" functions to perform conversions, as in the following example:

#include <stdio.h>
#include <stdlib.h>

// Declare Money class.
class Money
{
public:
    Money();
// Define conversion functions that can only be called explicitly.
    static Money Convert( char * ch ) { return Money( ch ); }
    static Money Convert( double d )    { return Money( d ); };
    void  Print() { printf( "\n%f", _amount ); }
private:
    Money( char *ch ) { _amount = atof( ch ); }
    Money( double d ) { _amount = d; }
    double _amount;
};

main()
{
    // Perform a conversion from type char * to type Money.
    Money Acct = Money::Convert( "57.29" );
    Acct.Print();
    // Perform a conversion from type double to type Money.
    Acct = Money::Convert( 33.29 );
    Acct.Print();

    return 0;
}

In the preceding code, the conversion constructors are private and cannot be used in type conversions. However, they can be invoked explicitly by calling the Convert functions. Because the Convert functions are static, they are accessible without referencing a particular object.


  Conversion Functions

In conversion by constructors, described in the previous section, objects of one type can be implicitly converted to a particular class type. This section describes a means by which you can provide explicit conversions from a given class type to another type. Conversion from a class type is often accomplished using conversion functions. Conversion functions use the following syntax:

Syntax

conversion-function-name:
operator  conversion-type-name  ()

conversion-type-name:
type-specifier-list  ptr-operator (opt)

The following example specifies a conversion function that converts type Money to type double:

class Money
{
public:
    Money();
    operator double() { return _amount; }
private:
    double _amount;
};

Given the preceding class declaration, the following code can be written:

Money Account;
...
double CashOnHand = Account;

The initialization of CashOnHand with Account causes a conversion from type Account to type double.

Conversion functions are often called "cast operators" because they (along with constructors) are the functions called when a cast is used. The following example uses a cast, or explicit conversion, to print the current value of an object of type Money:

cout << (double)Account << endl;

Conversion functions are inherited in derived classes. Conversion operators hide only base-class conversion operators that convert to exactly the same type. Therefore, a user-defined operator int function does not hide a user-defined operator short function in a base class.

Only one user-defined conversion function is applied when performing implicit conversions. If there is no explicitly defined conversion function, the compiler does not look for intermediate types into which an object can be converted.

If a conversion is required that causes an ambiguity, an error is generated. Ambiguities arise when more than one user-defined conversion is available or when a user-defined conversion and a built-in conversion exist.

The following example illustrates a class declaration with a potential ambiguity:

#include <string.h>

class String
{
public:
    // Define constructor that converts from type char *.
    String( char *s ) { strcpy( _text, s ); }
    // Define conversion to type char *.
    operator char *() { return _text; }
    int operator==( const String &s )
    { return !strcmp( _text, s._text ); }
private:
    char _text[80];
};

main()
{
    String s( "abcd" );
    char  *ch = "efgh";

    // Cause the compiler to select a conversion.
    return s == ch;
}

In the expression s == ch, the compiler has two choices and no way of determining which is correct. It can convert ch to an object of type String using the constructor and then perform the comparison using the user-defined operator==. Or it can convert s to a pointer of type char * using the conversion function and then perform a comparison of the pointers.

Because neither choice is "more correct" than the other, the compiler cannot determine the meaning of the comparison expression, and it generates an error.


  Rules for Declaring Conversion Functions

The following four rules are used when declaring conversion functions (see »Conversion Functions« for syntax):

•	Classes, enumerations, and typedef names cannot be declared in the type-specifier-list. Therefore, the following code generates an error:

operator struct String{ char string_storage; }();

Instead, declare the String structure prior to the conversion function.

•	Conversion functions take no arguments. Specifying arguments generates an error.

•	Conversion functions have the return type specified by the conversion-type-name; specifying any return type for a conversion function generates an error.

•	Conversion functions can be declared as virtual.


  11.5  The new and delete Operators

C++ supports dynamic allocation and deallocation of objects using the new and delete operators. These operators allocate memory for objects from a pool called the "free store." The new operator calls the special function operator new, and the delete operator calls the special function operator delete.


  The operator new Function

When a statement such as the following is encountered in a program, it translates into a call to the function operator new:

char *pch = new char[BUFFER_SIZE];

If there is insufficient memory for the allocation request, operator new returns NULL. However, if the request is for zero bytes of storage, operator new returns a pointer to a distinct object (that is, repeated calls to operator new return different pointers).

There are two scopes for operator new functions. They are described in Table 11.4.

Table 11.4    Scope for operator new Functions

Operator	Scope
::operator new	Global
class-name::operator new	Class
The first argument to operator new must be of type size_t (a type defined in STDDEF.H), and the return type is always void *.

The global operator new function is called when the new operator is used to allocate objects of built-in types, objects of class type that do not contain user-defined operator new functions, and arrays of any type. When the new operator is used to allocate objects of a class type where an operator new is defined, that class's operator new is called.

An operator new function defined for a class is a static member function (which cannot, therefore, be virtual) that hides the global operator new function for objects of that class type. Consider the case where new is used to allocate and set memory to a given value:

#include <malloc.h>
#include <memory.h>

class Blanks
{
public:
    Blanks(){}
    void *operator new( size_t stAllocateBlock, char chInit );
};

void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
    void *pvTemp = malloc( stAllocateBlock );
    if( pvTemp != 0 )
        memset( pvTemp, chInit, stAllocateBlock );
    return pvTemp;
}

For discrete objects of type Blanks, the global operator new function is hidden. Therefore, the following code allocates an object of type Blanks and initializes it to 0xa5:

main()
{
    Blanks *a5 = new( 0xa5 ) Blanks;

    return a5 != 0;
}

The argument supplied in parentheses to new is passed to Blanks::operator new as the chInit argument. However, the global operator new function is hidden, causing code such as the following to generate an error:

Blanks *SomeBlanks = new Blanks;

Nonclass types and all arrays (regardless of whether they are of class type) allocated using the new operator always use the global operator new function.

Microsoft Specific

The operator new function can be overloaded on its return type to allow specification of different new operators for different memory models. Table 11.5 shows the various function declarations for operator new. (For more information about overloading, see »Chapter 12, Overloading.«) ♦

Table 11.5    Declarations for new Operator

Heap	Declaration
Default	void *operator new( size_t ); The argument is the amount of storage (in bytes) to allocate.
Near (1)	void __near *operator new( size_t ); The argument is the amount of storage (in bytes) to allocate.
Far (1)	void __far *operator new( size_t ); The argument is the amount of storage (in bytes) to allocate.
Huge (1)	void __huge *operator new( unsigned long, size_t ); The first argument is the number of elements to allocate, and the second argument is the size of a given element (in bytes).
Based (1)	void __based( void ) *operator new( __segment, size_t ); The first argument is the segment specified in the new expression, and the second argument is the amount of storage (in bytes) to allocate. For example, the expression: new __based( __segname( "_TEXT" ) ) int calls operator new with the segment value corresponding to _TEXT and a size equal to sizeof( int ).
(1)  Recognized for 16-bit targets only
16-Bit Specific

The operator new function is the only function that can be overloaded solely on the basis of return type. It can be overloaded only in the forms shown in Table 11.5. ♦


  Handling Insufficient Memory Conditions

Testing for failed memory allocation can be done with code such as the following:

int *pi = new int[BIG_NUMBER];

if( pi == 0 )
{
    cerr << "Insufficient memory" << endl;
    return -1;
}

In some circumstances, corrective action can be taken during memory allocation and the request can be fulfilled. To gain control when the global operator new function fails, use the _set_new_handler function (defined in NEW.H) as follows:

#include <stdio.h>
#include <new.h>

// Define a function to be called if new fails to allocate memory.
int MyNewHandler( size_t size )
{
    clog << "Allocation failed. Coalescing heap." << endl;

    // Call a fictitious function to recover some heap space.
    return CoalesceHeap();
}

main()
{
    // Set the failure handler for new to be MyNewHandler.
    _set_new_handler( MyNewHandler );

    int *pi = new int[BIG_NUMBER];

    return 0;
}

In the preceding example, the first statement in main sets the new handler to MyNewHandler. The second statement tries to allocate a large block of memory using the new operator. When the allocation fails, control is transferred to MyNewHandler. The argument passed to MyNewHandler is the number of bytes requested. The value returned from MyNewHandler is a flag indicating whether allocation should be retried: a nonzero value indicates that allocation should be retried, and a zero value indicates that allocation has failed.

MyNewHandler prints a warning message and takes corrective action. If MyNewHandler returns a nonzero value, the new operator retries the allocation. Only when MyNewHandler returns a 0 does the new operator stop trying and return a zero value to the program.

The _set_new_handler function returns the address of the previous new handler. Therefore, if a new handler needs to be installed for a short time, the previous new handler can be reinstalled using code such as the following:

#include <new.h>

...

_PNH old_handler = _set_new_handler( MyNewHandler );

// Code that requires MyNewHandler.
...

// Reinstall previous new handler.
_set_new_handler( old_handler );

A call to _set_new_handler with an argument of 0 causes the default new handler to be reinstalled.

The new handler you specify can have any name, but it must be a function returning type int (nonzero indicates the new handler succeeded, and zero indicates that it failed). The argument list is described in Tables 11.6 and 11.7.

If a user-defined operator new is provided, the new handler functions are not automatically called on failure.

Microsoft Specific

In Microsoft C++, objects can be allocated on the default heap, the near heap, the far heap, the huge heap, or a based heap. New handlers for these heaps can be set using the functions declared in NEW.H, which are listed in Table 11.6.

Table 11.6    Functions Used to Set New Handlers

Function Name	New Handler That Is Set	Prototype
_set_new_handler (1)	Default new handler	_PNH _set_new_handler    ( _PNH );
_set_nnew_handler (2)	New handler for objects allocated on the near heap	_PNH _set_nnew_handler    ( _PNH );
_set_fnew_handler (2)	New handler for objects allocated on the far heap	_PNH _set_fnew_handler    ( _PNH );
_set_hnew_handler (2)	New handler for objects allocated on the huge heap	_PNHH _set_hnew_handler    ( _PNHH );
_set_bnew_handler (2)	New handler for objects allocated on the based heap	_PNHB _set_bnew_handler    ( _PNHB );
(1)  For 16-bit and 32-bit targets  (2)  For 16-bit targets only
To facilitate easy declaration of the new handlers, three types are defined. See Table 11.7.

Table 11.7    List of New-Handler Types

Type	Meaning
_PNH (1)	Pointer to a function that returns type int and takes a single argument of type size_t.
_PNHH (2)	Pointer to a function that returns type int and takes arguments of type unsigned long (the number of elements) and type size_t (the size of a given element).
_PNHB (2)	Pointer to a function that returns type int and takes arguments of type __segment (the segment base) and of type size_t.
(1)  For 16-bit and 32-bit targets  (2)  For 16-bit targets only
By using the appropriate "set new handler" function, you can trap memory-allocation failures for default, near, far, huge, and based objects. ♦


  The operator delete Function

Memory that is dynamically allocated using the new operator can be freed using the delete operator. The delete operator causes the operator delete function to be called, which frees memory back to the available pool. Using the delete operator also causes the class destructor (if there is one) to be called.

There are global and class-scoped operator delete functions. Only one operator delete function can be defined for a given class; if defined, it hides the global operator delete function. The global operator delete function is always called for arrays of any type.

The global operator delete function, if declared, takes a single argument of type void *, which contains a pointer to the object to deallocate. The return type is void (operator delete cannot return a value). Two forms exist for class-member operator delete functions:

void operator delete( void * );
void operator delete( void *, size_t );

Only one of the preceding two variants can be present for a given class. The first form works as described for global operator delete. The second form takes two arguments, the first of which is a pointer to the memory block to deallocate and the second of which is the number of bytes to deallocate. The second form is particularly useful when an operator delete function from a base class is used to delete an object of a derived class.

The following example shows user-defined operator new and operator delete functions designed to log allocations and deallocations of memory:

#include <iostream.h>
#include <stdlib.h>

int fLogMemory = 0;       // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0;  // Count of blocks allocated.

// User-defined operator new.
void *operator new( size_t stAllocateBlock )
{
    static fInOpNew = 0;    // Guard flag.

    if( fLogMemory && !fInOpNew )
    {
        fInOpNew = 1;
        clog << "Memory block "   << ++cBlocksAllocated
             << " allocated for " << stAllocateBlock
             << " bytes\n";
        fInOpNew = 0;
    }

    return malloc( stAllocateBlock );
}
// User-defined operator delete.
void operator delete( void *pvMem )
{
    static fInOpDelete = 0;    // Guard flag.
    if( fLogMemory && !fInOpDelete )
    {
        fInOpDelete = 1;
        clog << "Memory block " << --cBlocksAllocated
             << " deallocated\n";
        fInOpDelete = 0;
    }

    free( pvMem );
}

main( int argc, char *argv[] )
{
    fLogMemory = 1;  // Turn logging on.
    if( argc > 1 )
    for( int i = 0; i < atoi( argv[1] ); ++i )
    {
        char *pMem = new char[10];
        delete pMem;
    }

    return cBlocksAllocated;
}

The preceding code can be used to detect "memory leakage" — that is, memory that is allocated on the free store but never freed. To perform this detection, the global new and delete operators are redefined to count allocation and deallocation of memory.

Using delete on a null pointer has no effect. (For more information about the delete operator, see »delete Operator« in Chapter 4.)


  11.6  Initialization Using Special Member Functions

This section describes initialization using special member functions. It expands on the following discussions of initialization:

•	»Initializing Aggregates« in Chapter 7, which describes how to initialize arrays of nonclass types and objects of simple class types. These simple class types cannot have private or protected members, and they cannot have base classes.

•	»Constructors«, which explains how to initialize class-type objects using special constructor functions.

The default method of initialization is to perform a bit-for-bit copy from the initializer into the object to be initialized. This technique is applicable only to:

•	Objects of built-in types. For example:

int i = 100;

•	Pointers. For example:

int i;
int *pi = &i;

•	References. For example:

String sFileName( "FILE.DAT" );
String &rs = sFileName;

•	Objects of class type, where the class has no private or protected members, no virtual functions, and no base classes. For example:

struct Point
{
    int x, y;
};

Point pt = { 10, 20 };   // Static storage class only

Classes can specify more refined initialization by defining constructor functions. (For more information about declaring such functions, see »Constructors«.) If an object is of a class type that has a constructor, the object must be initialized, or there must be a default constructor. Objects that are not specifically initialized invoke the class's default constructor.


  Explicit Initialization

Two forms of explicit initialization are supported in C++.

•	Supplying an initializer list in parentheses:

String sFileName( "FILE.DAT" );

The items in the parenthesized list are considered arguments to the class constructor. This form of initialization enables initialization of an object with more than one value and can also be used in conjunction with the new operator. For example:

Rect *pRect = new Rect( 10, 15, 24, 97 );

•	Supplying a single initializer using the equal-sign initialization syntax. For example:

String sFileName = "FILE.DAT";

Although the preceding example works the same way as the example shown for String in the first list item, the syntax is not adaptable to use with objects allocated on the free store.

The single expression on the right of the equal sign is taken as the argument to the class's copy constructor; therefore, it must be a type that can be converted to the class type.

Note that because the equal sign (=) in the context of initialization is different from an assignment operator, overloading operator= has no effect on initialization.

The equal-sign initialization syntax is different from the function-style syntax, even though the generated code is identical in most cases. The difference is that when the equal-sign syntax is used, the compiler has to behave as if the following sequence of events were taking place:

•	Creating a temporary object of the same type as the object being initialized.

•	Copying the temporary object to the object.

The constructor must be accessible before the compiler can perform these steps. Even though the compiler can eliminate the temporary creation and copy steps in most cases, an inaccessible copy constructor causes equal-sign initialization to fail. Consider the following example:

class anInt
{
    anInt( const anInt& );    //  Private copy constructor.
public:
    anInt( int );             //  Public int constructor.
};
...
anInt myInt = 7;              //  Access-control violation. Attempt to
                              //   reference private copy constructor.
anInt myInt( 7 );             //  Correct; no copy constructor called.

When a function is called, class-type arguments passed by value and objects returned by value are conceptually initialized using the form:

type-name name = value

For example:

String s = "C++";

Therefore, it follows that the argument type must be a type that can be converted to the class type being passed as an argument. The class's copy constructor, as well as user-defined conversion operators or constructors that accept the type of the actual argument, must be public.

In expressions that use the new operator, the objects allocated on the free store are conceptually initialized using the form:

type-name name( initializer1, initializer2, ... initializern )

For example:

String *ps = new String( "C++" );

Initializers for base-class components and member objects of a class are also conceptually initialized this way. (For more information, see »Initializing Bases and Members«.)


  Initializing Arrays

If a class has a constructor, arrays of that class are initialized by a constructor. If there are fewer items in the initializer list than elements in the array, the default constructor is used for the remaining elements. If no default constructor is defined for the class, the initializer list must be complete — that is, there must be one initializer for each element in the array.

Consider the Point class that defines two constructors:

class Point
{
public:
    Point();           // Default constructor.
    Point( int, int ); // Construct from two ints.
    ...
};

An array of Point objects can be declared as follows:

Point aPoint[3] = {
    Point( 3, 3 )     // Use int, int constructor.
};

The first element of aPoint is constructed using the constructor Point( int, int ); the remaining two elements are constructed using the default constructor.

Static member arrays (whether const or not) can be initialized in their definitions (outside the class declaration). For example:

class WindowColors
{
public:
    static const char *rgszWindowPartList[7];
    ...
};
const char *WindowColors::rgszWindowPartList[7] = {
    "Active Title Bar", "Inactive Title Bar", "Title Bar Text",
    "Menu Bar", "Menu Bar Text", "Window Background", "Frame"   };


  Initializing Static Objects

Global static objects are initialized in the order they occur in the source. They are destroyed in the reverse order. Across translation units, however, the order of initialization is dependent on how the object files are arranged by the linker; the order of destruction still takes place in the reverse of that in which objects were constructed.

Local static objects are initialized when they are first encountered in the program flow, and they are destroyed in the reverse order at program termination. Destruction of local static objects occurs only if the object was encountered in the program flow and initialized.


  Initializing Bases and Members

An object of a derived class is made up of a component that represents each base class and a component that is unique to the particular class. Objects of classes that have member objects may also contain instances of other classes. This section describes how these component objects are initialized when an object of the class type is created.

To perform the initialization, the constructor-initializer, or ctor-initializer, syntax is used.

Syntax

ctor-initializer:
mem-initializer-list

mem-initializer-list:
mem-initializer
mem-initializer  ,  mem-initializer-list

mem-initializer:
complete-class-name  (  expression-list (opt)   )
identifier  (  expression-list (opt)   )

This syntax, used in constructors, is described more fully in the next section, »Initializing Member Objects,« and in »Initializing Base Classes«.


  Initializing Member Objects

Classes can contain member objects of class type, but to ensure that initialization requirements for the member objects are met, one of the following conditions must be met:

•	The contained object's class requires no constructor.

•	The contained object's class has an accessible default constructor.

•	The containing class's constructors all explicitly initialize the contained object.

The following example shows how to perform such an initialization:

// Declare a class Point.
class Point
{
public:
    Point( int x, int y ) { _x = x; _y = y; }
private:
    int _x, _y;
};

// Declare a rectangle class that contains objects of type Point.
class Rect
{
public:
    Rect( int x1, int y1, int x2, int y2 );
private:
    Point _topleft, _bottomright;
};

//  Define the constructor for class Rect. This constructor
//   explicitly initializes the objects of type Point.
Rect::Rect( int x1, int y1, int x2, int y2 ) :
_topleft( x1, y1 ), _bottomright( x2, y2 )
{
}

The Rect class, shown in the preceding example, contains two member objects of class Point. Its constructor explicitly initializes the objects _topleft and _bottomright. Note that a colon follows the closing parenthesis of the constructor (in the definition). The colon is followed by the member names and arguments with which to initialize the objects of type Point.

Warning  The order in which the member initializers are specified in the constructor does not affect the order in which the members are constructed; the members are constructed in the order in which they are declared in the class.

Reference and const member objects must be initialized using the member initialization syntax shown in "Syntax" in »Initializing Bases and Members«. There is no other way to initialize these objects.


  Initializing Base Classes

Direct base classes are initialized in much the same way as member objects. Consider the following example:

//  Declare class Window.
class Window
{
public:
    Window( Rect rSize );
    ...
};

//  Declare class DialogBox, derived from class Window.
class DialogBox : public Window
{
public:
    DialogBox( Rect rSize );
    ...
};

//  Define the constructor for DialogBox. This constructor
//   explicitly initializes the Window subobject.
DialogBox::DialogBox( Rect rSize ) : Window( rSize )
{
}

Note that in the constructor for DialogBox, the Window base class is initialized using the argument rSize. This initialization consists of the name of the base class to initialize, followed by a parenthesized list of arguments to the class's constructor.

In initialization of base classes, the object that is not the subobject representing a base class's component is considered a "complete object." The complete object's class is considered the "most derived" class for the object.

The subobjects representing virtual base classes are initialized by the constructor for the most derived class. That means that where virtual derivation is specified, the most derived class must explicitly initialize the virtual base class, or the virtual base class must have a default constructor. Initializations for virtual base classes that appear in constructors for classes other than the most derived class are ignored.

Although initialization of base classes is usually restricted to direct base classes, a class constructor can initialize an indirect virtual base class.


  Initialization Order of Bases and Members

Base classes and member objects are initialized in the following order:

1.	Virtual base classes are initialized in the order in which they appear in the directed acyclic graph. For information about using the directed acyclic graph to construct a list of unique subobjects, see »Virtual Base Classes« in Chapter 9. (Note that these subobjects are destroyed by walking the same list in reverse.) For more information about how the directed acyclic graph is traversed, see »Order of Destruction«.

2.	Nonvirtual base classes are initialized in the order in which they are declared in the class declaration.

3.	Member objects are initialized in the order in which the objects are declared in the class.

The order in which base classes and member objects are initialized is not affected by the order in which the member initializers or base-class initializers appear in the member-initializer-list of the constructor.


  Scope of Initializers

Initializers for base classes and member objects are evaluated in the scope of the constructor with which they are declared. Therefore, they can refer implicitly to class-member data.


  11.7  Copying Class Objects

Two operations cause objects to be copied:

•	Assignment. When one object's value is assigned to another object, the first object is copied to the second object. Therefore:

Point a, b;
...
a = b;

causes the value of b to be copied to a.

•	Initialization. Initialization occurs at the point of declaration of a new object, when arguments are passed to functions by value, and when values are returned from functions by value.

The programmer can define the semantics of "copy" for objects of class type. For example, consider the following code:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT," or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." The programmer is responsible for attaching appropriate copying semantics to each class.

Copying is done in one of two ways:

•	Assignment (using the assignment operator, operator=).

•	Initialization (using the copy constructor). (For more information about the copy constructor, see »Rules for Declaring Constructors«.)

Any given class can implement one or both copy methods. If neither method is implemented, assignment is handled as a member-by-member ("memberwise") assignment, and initialization is handled as a member-by-member initialization. Memberwise assignment is covered in more detail in »Memberwise Assignment and Initialization«.

The copy constructor takes a single argument of type class-name&, where class-name is the name of the class for which the constructor is defined. For example:

class Window
{
public:
    Window( const Window& ); // Declare copy constructor.
    ...
};

Note  The type of the copy constructor's argument should be const class-name& whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also allows copying from const objects.


  Compiler-Generated Copying

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name&. In such a case, the compiler-generated copy constructor's argument is also const.

When the argument type to the copy constructor is not const, initialization by copying a const object generates an error. The reverse is not true: If the argument is const, initialization by copying an object that is not const.

Compiler-generated assignment operators follow the same pattern with regard to const. They take a single argument of type class-name& unless the assignment operators in all base and member classes take arguments of type const class-name&. In this case, the class's generated assignment operator takes a const argument.

Note  When virtual base classes are initialized by copy constructors, compiler-generated or user-defined, they are initialized only once: at the point when they are constructed.

The implications are similar to those of the copy constructor. When the argument type is not const, assignment from a const object generates an error. The reverse is not true: If a const value is assigned to a value that is not const, the assignment succeeds.

For more information about overloaded assignment operators, see »Assignment« in Chapter 12.


  Memberwise Assignment and Initialization

The methods for default assignment and initialization are "memberwise assignment" and "memberwise initialization," respectively. Memberwise assignment consists of copying one object to the other, a member at a time, as if assigning each member individually. Memberwise initialization consists of copying one object to the other, a member at a time, as if initializing each member individually. The primary difference between the two is that memberwise assignment invokes each member's assignment operator (operator=), whereas memberwise initialization invokes each member's copy constructor.

Memberwise assignment is performed only by the assignment operator declared in the form:

type& type :: operator=( [const | volatile] type& )

Default assignment operators for memberwise assignment cannot be generated if any of the following conditions exist:

•	A member class has const members.

•	A member class has reference members.

•	A member class or its base class has a private assignment operator (operator=).

•	A base class or member class has no assignment operator (operator=).

Default copy constructors for memberwise initialization cannot be generated if the class or one of its base classes has a private copy constructor or if any of the following conditions exist:

•	A member class has const members.

•	A member class has reference members.

•	A member class or its base class has a private copy constructor.

•	A base class or member class has no copy constructor.

The default assignment operators and copy constructors for a given class are always declared, but they are not defined unless both of the following conditions are met:

•	The class does not provide a user-defined function for this copy.

•	The program requires that the function be present. This requirement exists if an assignment or initialization is encountered that requires memberwise copying or if the address of the class's operator= function is taken.

If both of the conditions in the preceding list are not met, the compiler is not required to generate code for the default assignment operator and copy constructor functions (elimination of such code is an optimization performed by the Microsoft C++ compiler). Specifically, if the class declares a user-defined operator= that takes an argument of type "reference to class-name," no default assignment operator is generated. If the class declares a copy constructor, no default copy constructor is generated.

Therefore, for a given class A, the following declarations are always present:

//  Implicit declarations of copy constructor
//   and assignment operator.
A::A( const A& );
A& A::operator=( const A& );

The definitions are supplied only if required (according to the preceding criteria). The copy constructor functions shown in the preceding example are considered public member functions of the class.

Default assignment operators allow objects of a given class to be assigned to objects of a public base-class type. Consider the following code:

class Account
{
public:
    // Public member functions
    ...
private:
    double _balance;
};

class Checking : public Account
{
private:
    int _fOverdraftProtect;
};

...

Account account;
Checking checking;

account = checking;

In the preceding example, the assignment operator chosen is Account::operator=. Because the default operator= function takes an argument of type Account& (reference to Account), the Account subobject of checking is copied to account; fOverdraftProtect is not copied.


Chapter 12: Overloading
  Chapter 12  Overloading

This chapter explains how to use C++ overloaded functions and overloaded operators.


  12.1  Overview

The C++ language allows you to overload functions and operators. Overloading is the practice of supplying more than one definition for a given function name in the same scope. The compiler is left to pick the appropriate version of the function or operator based on the arguments with which it is called. For example:

double max( double d1, double d2 )
{
    return ( d1 > d2 ) ? d1 : d2;
}

int max( int i1, int i2 )
{
    return ( i1 > i2 ) ? i1 : i2;
}

The function max is considered an overloaded function. It can be used in code such as the following:

main()
{
    int    i = max( 12, 8 );
    double d = max( 32.9, 17.4 );

    return i + (int)d;
}

In the first case, where the maximum value of two variables of type int is being requested, the function max( int, int ) is called. However, in the second case, the arguments are of type double, so the function max( double, double ) is called.


  Argument Type Differences

Overloaded functions differentiate between argument types that take different initializers. Therefore, an argument of a given type and a reference to that type are considered the same for the purposes of overloading. They are considered the same because they take the same initializers. For example, max( double, double ) is considered the same as max( double &, double & ). It is an error for overloaded functions to differ only in this manner.

For the same reason, function arguments of a type modified by const or volatile are not treated differently than the base type for the purposes of overloading.

However, the function overloading mechanism can distinguish between references that are qualified by const and volatile and references to the base type. This makes code such as the following possible:

#include <iostream.h>

class Over
{
public:
    Over() { cout << "Over default constructor\n"; }
    Over( Over &o ) { cout << "Over&\n"; }
    Over( const Over &co ) { cout << "const Over&\n"; }
    Over( volatile Over &vo ) { cout << "volatile Over&\n"; }
};

main()
{
    Over o1;            // Calls default constructor.
    Over o2( o1 );      // Calls Over( Over& ).
    const Over o3;      // Calls default constructor.
    Over o4( o3 );      // Calls Over( const Over& ).
    volatile Over o5;   // Calls default constructor.
    Over o6( o5 );      // Calls Over( volatile Over& ).

    return 0;
}

Pointers to const and volatile objects are also considered different from pointers to the base type for the purposes of overloading.


  Restrictions on Overloaded Functions

There are a number of restrictions that govern what makes up an acceptable set of overloaded functions:

•	Any two functions in a set of overloaded functions must have different argument lists.

•	Overloading functions with argument lists of the same types, based on return type alone, is an error.

Microsoft Specific

You can overload operator new solely on the basis of return type — specifically, on the basis of the memory-model modifier specified. ♦

•	Member functions cannot be overloaded solely on the basis of one being static and the other nonstatic.

•	typedef declarations do not define new types; they introduce synonyms for existing types. They do not affect the overloading mechanism. Consider the following code:

typedef char * PSTR;

void Print( char *szToPrint );
void Print( PSTR szToPrint );

The preceding two functions have identical argument lists. PSTR is a synonym for type char *. In member scope, this code generates an error.

•	Enumerated types are distinct types and can be used to distinguish between overloaded functions.

•	The types "array of" and "pointer to" are considered identical for the purposes of distinguishing between overloaded functions. This is true only for singly dimensioned arrays. Therefore, the following overloaded functions conflict and generate an error message:

void Print( char *szToPrint );
void Print( char szToPrint[] );

For multiply dimensioned arrays, the second and all succeeding dimensions are considered part of the type. Therefore, they are used in distinguishing between overloaded functions:

void Print( char szToPrint[] );
void Print( char szToPrint[][7] );
void Print( char szToPrint[][9][42] );


  12.2  Declaration Matching

Any two function declarations of the same name in the same scope can refer to two discrete functions that are overloaded or to the same function. If the argument lists of the declarations contain arguments of equivalent types (as described in the previous section), the function declarations refer to the same function. Otherwise, they refer to two different functions that are selected using overloading.

Class scope is strictly observed; therefore, a function declared in a base class is not in the same scope as a function declared in a derived class. If a function in a derived class is declared with the same name as a function in the base class, the derived-class function hides the base-class function instead of causing overloading.

Block scope is strictly observed; therefore, a function declared in file scope is not in the same scope as a function declared locally. If a locally declared function has the same name as a function declared in file scope, the locally declared function hides the file-scoped function instead of causing overloading. For example:

#include <iostream.h>

void func( int i )
{
    cout << "Called file-scoped func : " << i << endl;
}

void func( char *sz )
{
    cout << "Called locally declared func : " << sz << endl;
}

main()
{
    // Declare func local to main.
    extern void func( char *sz );

    func( 3 );    // Error. func( int ) is hidden.
    func( "s" );

    return 0;
}

The preceding code shows two definitions from the function func. The definition that takes an argument of type char * is local to main because of the extern statement. Therefore, the definition that takes an argument of type int is hidden, and the first call to func is in error.

For overloaded member functions, different versions of the function can be given different access privileges. They are still considered to be in the scope of the enclosing class and thus are overloaded functions. Consider the following code, in which the member function Deposit is overloaded; one version is public, the other, private:

class Account
{
public:
    Account();
    double Deposit( double dAmount, char *szPassword );
private:
    double Deposit( double dAmount );
    int    Validate( char *szPassword );
};

The intent of the preceding code is to provide an Account class in which a correct password is required to perform deposits. This is accomplished using overloading. The following code shows how this class can be used and also shows an erroneous call to the private member, Deposit:

main()
{
    // Allocate a new object of type Account.
    Account *pAcct = new Account;

    // Deposit $57.22. Error: calls a private function.
    pAcct->Deposit( 57.22 );

    // Deposit $57.22 and supply a password. OK: calls a
    //  public function.
    pAcct->Deposit( 52.77, "pswd" );

    return 0;
}

double Account::Deposit( double dAmount, char *szPassword )
{
    if( Validate( szPassword ) )
        return Deposit( dAmount );
    else
        return 0.0;
}

Note that the call to Deposit in Account::Deposit calls the private member function. This call is correct because Account::Deposit is a member function and therefore has access to the private members of the class.


  12.3  Argument Matching

Overloaded functions are selected on a best-match basis. That is, the set of overloaded functions is scanned to see which function declaration in the current scope best matches the arguments supplied in the function call. If a suitable function is found, that function is called. "Suitable" in this context means one of the following:

•	An exact match was found.

•	A trivial conversion was performed.

•	An integral promotion was performed.

•	A standard conversion to the desired argument type exists.

•	A user-defined conversion (either conversion operator or constructor) to the desired argument type exists.

•	Arguments represented by an ellipsis were found.

The compiler creates a set of candidate functions for each argument. Candidate functions are functions in which the actual argument in that position can be converted to the type of the formal argument.

A set of "best matching functions" is built for each argument, and the selected function is the intersection of all the sets. If the intersection contains more than one function, the overloading is ambiguous and generates an error. The function that is eventually selected is always a better match than every other function in the group for at least one argument. If this is not the case (if there is no clear winner), the function call generates an error.

Consider the following declarations (the functions are marked Variant 1, Variant 2, and Variant 3, for identification in the following discussion):

Fraction &Add( Fraction &f, long l );       // Variant 1
Fraction &Add( long l, Fraction &f );       // Variant 2
Fraction &Add( Fraction &f, Fraction &f );  // Variant 3

Fraction F1, F2;

Consider the following statement:

F1 = Add( F2, 23 );

The preceding statement builds two sets:

Set 1: Candidate Functions That Have First Argument of Type Fraction	Set 2: Candidate Functions Whose Second Argument Can Be Converted to Type int
Variant 1	Variant 1 (int can be converted to long using a standard conversion)
Variant 3
Functions in Set 2 are functions for which there are implicit conversions from actual parameter type to formal parameter type, and among such functions there is a function for which the "cost" of converting the actual parameter type to its formal parameter type is the smallest.

The intersection of these two sets is Variant 1. An example of an ambiguous function call is:

F1 = Add( 3, 6 );

The preceding function call builds the following sets:

Set 1: Candidate Functions That Have First Argument of Type int	Set 2: Candidate Functions That Have Second Argument of Type int
Variant 2 (int can be converted to long using a standard conversion)	Variant 1 (int can be converted to long using a standard conversion)
Note that the intersection between these two sets is empty. Therefore, the compiler generates an error message.

For argument matching, a function with n default arguments is treated as n+1 separate functions, each with a different number of arguments.

The ellipsis (...) acts as a wildcard; it matches any actual argument. This can lead to many ambiguous sets, if you do not design your overloaded function sets with extreme care.

Note  Ambiguity of overloaded functions cannot be determined until a function call is encountered. At that point, the sets are built for each argument in the function call, and it can be determined whether an unambiguous overload exists. This means that ambiguities can remain in your code until they are evoked by a particular function call.


  Argument Matching and the this Pointer

Class member functions are treated differently, depending on whether they are declared as static. Because nonstatic functions have an implicit argument that supplies the this pointer, nonstatic functions are considered to have one more argument than static functions; otherwise, they are declared identically.

These nonstatic member functions require that the implied this pointer match the object type through which the function is being called, or, for overloaded operators, they require that the first argument match the object on which the operator is being applied. (For more information about overloaded operators, see »Overloaded Operators«.)

Unlike other arguments in overloaded functions, no temporary objects are introduced and no conversions are attempted when trying to match the this pointer argument.

When the  − > member-selection operator is used to access a member function, the this pointer argument has a type of class-name * const. If the members are declared as const or volatile, the types are const class-name * const and volatile class-name * const, respectively.

The . member-selection operator works exactly the same way, except that an implicit & (address-of) operator is prefixed to the object name. The following example shows how this works:

// Expression encountered in code
obj.name

// How the compiler treats it
(&obj)->name

The left operand of the  − >* and .* (pointer to member) operators are treated the same way as the . and  − > (member-selection) operators with respect to argument matching.


  Argument Matching and Conversions

When the compiler tries to match actual arguments against the arguments in function declarations, it can supply standard or user-defined conversions to obtain the correct type if no exact match can be found. The application of conversions is subject to these rules:

•	Sequences of conversions that contain more than one user-defined conversion are not considered.

•	Sequences of conversions that can be shortened by removing intermediate conversions are not considered.

The resultant sequence of conversions, if any, is called the best matching sequence. There are several ways to convert an object of type int to type unsigned long using standard conversions (described in »Chapter 3, Standard Conversions«):

•	Convert from int to long and then from long to unsigned long.

•	Convert from int to unsigned long.

The first sequence, although it achieves the desired goal, is not the best matching sequence — a shorter sequence exists.

Table 12.1 shows a group of conversions, called trivial conversions, that have a limited effect on the determination of which sequence is the best matching. The instances in which trivial conversions affect choice of sequence are discussed in the list following the table.

Table 12.1    Trivial Conversions

Convert from Type	Convert to Type
type-name	type-name&
type-name&	type-name
type-name[ ]	type-name*
type-name( argument-list )	(*type-name) ( argument-list )
type-name	const type-name
type-name	volatile type-name
type-name*	const type-name*
type-name*	volatile type-name*
The sequence in which conversions are attempted is as follows:

1.	Exact match. An exact match between the types with which the function is called and the types declared in the function prototype is always the best match. Sequences of trivial conversions are classified as exact matches. However, sequences that do not make any of these conversions are considered better than sequences that convert:

•	From pointer, to pointer to const (type * to const type *).

•	From pointer, to pointer to volatile (type * to volatile type *).

•	From reference, to reference to const (type & to const type &).

•	From reference, to reference to volatile (type & to volatile type &).

2.	Match using promotions. Any sequence not classified as an exact match that contains only integral promotions, conversions from float to double, and trivial conversions is classified as a match using promotions. Although not as good a match as any exact match, a match using promotions is better than a match using standard conversions.

3.	Match using standard conversions. Any sequence not classified as an exact match or a match using promotions that contains only standard conversions and trivial conversions is classified as a match using standard conversions. Within this category, the following rules are applied:

•	Conversion from a pointer to a derived class, to a pointer to a direct or indirect base class is preferable to converting to void * or const void *.

•	Conversion from a pointer to a derived class, to a pointer to a base class produces a better match the closer the base class is to a direct base class. Suppose the class hierarchy is as shown in »Figure 12.1.«

Conversion from type D* to type C* is preferable to conversion from type D* to type B*. Similarly, conversion from type D* to type B* is preferable to conversion from type D* to type A*.

This same rule applies to reference conversions. Conversion from type D& to type C& is preferable to conversion from type D& to type B&, and so on.

This same rule applies to pointer-to-member conversions. Conversion from type T D::* to type T C::* is preferable to conversion from type T D::* to type T B::*, and so on (where T is the type of the member).

The preceding rule applies only along a given path of derivation. Consider the graph shown in »Figure 12.2.«

Conversion from type C* to type B* is preferable to conversion from type C* to type A*. The reason is that they are on the same path, and B* is closer. However, conversion from type C* to type D* is not preferable to conversion to type A*; there is no preference because the conversions follow different paths.

4.	Match with user-defined conversions. This sequence cannot be classified as an exact match, a match using promotions, or a match using standard conversions. The sequence must contain only user-defined conversions, standard conversions, or trivial conversions to be classified as a match with user-defined conversions. A match with user-defined conversions is considered a better match than a match with an ellipsis but not as good a match as a match with standard conversions.

5.	Match with an ellipsis. Any sequence that matches an ellipsis in the declaration is classified as a match with an ellipsis. This is considered the weakest match.

User-defined conversions are applied if no built-in promotion or conversion exists. These conversions are selected on the basis of the type of the argument being matched. Consider the following code:

class UDC
{
public:
    operator int();
    operator long();
};

void Print( int i );
...
UDC udc;
Print( udc );

The available user-defined conversions for class UDC are from type int and type long. Therefore, the compiler considers conversions for the type of the object being matched: UDC. A conversion to int exists, and it is selected.

During the process of matching arguments, standard conversions can be applied to both the argument and the result of a user-defined conversion. Therefore, the following code works:

void LogToFile( long l );
...
UDC udc;
LogToFile( udc );

In the preceding example, the user-defined conversion, operator long, is invoked to convert udc to type long. If no user-defined conversion to type long had been defined, the conversion would have proceeded as follows: Type UDC would have been converted to type int using the user-defined conversion. Then the standard conversion from type int to type long would have been applied to match the argument in the declaration.

If any user-defined conversions are required to match an argument, the standard conversions are not used when evaluating the best match. This is true even if more than one candidate function requires a user-defined conversion; in such a case, the functions are considered equal. For example:

class UDC1
{
public:
    UDC1( int );  // User-defined conversion from int.
};

class UDC2
{
public:
    UDC2( long ); // User-defined conversion from long.
};

...

void Func( UDC1 );
void Func( UDC2 );

...

Func( 1 );

Both versions of Func require a user-defined conversion to convert type int to the class type argument. The possible conversions are:

•	Convert from type int to type UDC1 (a user-defined conversion).

•	Convert from type int to type long; then convert to type UDC2 (a two-step conversion).

Even though the second of these requires a standard conversion, as well as the user-defined conversion, the two conversions are still considered equal.

Note  User-defined conversions are considered conversion by construction or conversion by initialization (conversion function). Both methods are considered equal when considering the best match.


  12.4  Address of Overloaded Functions

Use of a function name without arguments returns the address of that function. For example:

int Func( int i, int j );
int Func( long l );

...

int (*pFunc) ( int, int ) = Func;

In the preceding example, the first version of Func is selected, and its address is copied into pFunc.

The compiler determines which version of the function to select by finding a function with an argument list that exactly matches that of the target. The arguments in the overloaded function declarations are matched against one of the following:

•	An object being initialized (as shown in the preceding example)

•	The left side of an assignment statement

•	A formal argument to a function

•	A formal argument to a user-defined operator

•	A function return type

If no exact match is found, the expression that takes the address of the function is ambiguous and an error is generated.

Note that although a nonmember function, Func, was used in the preceding example, the same rules are applied when taking the address of overloaded member functions.


  12.5  Overloaded Operators

C++ allows the function of most built-in operators to be redefined. These operators can be redefined, or "overloaded," globally or on a class-by-class basis. Overloaded operators are implemented as functions and can be class-member or global functions.

The name of an overloaded operator is operatorx, where x is the operator as it appears in Table 12.2. For example, to overload the addition operator, you define a function called operator+. Similarly, to overload the addition/assignment operator, +=, define a function called operator+=.

Although these operators are usually called implicitly by the compiler when they are encountered in code, they can be invoked explicitly the same way as any member or nonmember function is called:

Point pt;

pt.operator+( 3 );  // Call addition operator to add 3 to pt.

Table 12.2 shows a list of operators that can be overloaded.

Table 12.2    Redefinable Operators

Operator	Name	Type
,	Comma	Binary
!	Logical NOT	Unary
!=	Inequality	Binary
%	Modulus	Binary
%=	Modulus/assignment	Binary
&	Bitwise AND	Binary
&	Address-of	Unary
&&	Logical AND	Binary
&=	Bitwise AND/assignment	Binary
( )	Function call	—
*	Multiplication	Binary
*	Pointer dereference	Unary
*=	Multiplication/assignment	Binary
+	Addition	Binary
+	Unary Plus	Unary
++	Increment (1)	Unary
+=	Addition/assignment	Binary
−	Subtraction	Binary
−	Unary negation	Unary
−−	Decrement (1)	Unary
−=	Subtraction/assignment	Binary
−>	Member selection	Binary
−>*	Pointer-to-member selection	Binary
/	Division	Binary
/=	Division/assignment	Binary
<	Less than	Binary
<<	Left shift	Binary
<<=	Left shift/assignment	Binary
<=	Less than or equal to	Binary
=	Assignment	Binary
==	Equality	Binary
>	Greater than	Binary
>=	Greater than or equal to	Binary
>>	Right shift	Binary
>>=	Right shift/assignment	Binary
[ ]	Array subscript	—
^	Exclusive OR	Binary
^=	Exclusive OR/assignment	Binary
|	Bitwise inclusive OR	Binary
|=	Bitwise inclusive OR/assignment	Binary
||	Logical OR	Binary
~	One's complement	Unary
delete	delete	—
new	new	—
(1)  Two versions of the unary increment and decrement operators exist: preincrement and postincrement.
The constraints on the various categories of overloaded operators are described in »Unary Operators«, »Binary Operators«, »Assignment«, »Function Call«, »Subscripting«, »Class-Member Access«, and »Increment and Decrement«.

The operators shown in Table 12.3 cannot be overloaded.

Table 12.3    Nonredefinable Operators

Operator	Name
.	Member selection
.*	Pointer-to-member selection
::	Scope resolution
:> (1)	Base operator
? :	Conditional
#	Preprocessor symbol
##	Preprocessor symbol
(1)  16-bit specific and Microsoft specific


  General Rules for Operator Overloading

The following rules constrain how overloaded operators are implemented. However, they do not apply to the »new« and »delete« operators, which are covered separately in Chapter 4.

•	Operators must either be class member functions or take an argument that is of class or enumerated type or arguments that are references to class or enumerated types. For example:

class Point
{
public:
    Point operator<( Point & );  // Declare a member operator
                                 //  overload.
    ...
    // Declare addition operators.
    friend Point operator+( Point&, int );
    friend Point operator+( int, Point& );
};

The preceding code sample declares the less-than operator as a member function; however, the addition operators are declared as global functions that have friend access. Note that more than one implementation can be provided for a given operator. In the case of the preceding addition operator, the two implementations are provided to facilitate commutativity. It is just as likely that operators that add a Point to a Point, int to a Point, and so on might be implemented.

•	Operators obey the precedence, grouping, and number of operands dictated by their typical use with built-in types. Therefore, there is no way to express the concept "add 2 and 3 to an object of type Point," expecting 2 to be added to the x coordinate and 3 to be added to the y coordinate.

•	Unary operators if declared as member functions take no arguments; if declared as global functions, they take one argument.

•	Binary operators if declared as member functions take one argument; if declared as global functions, they take two arguments.

•	Overloaded operators cannot have default arguments.

•	All overloaded operators except assignment (operator=) are inherited by derived classes.

•	The first argument for member-function overloaded operators is always of the class type of the object for which the operator is invoked (the class in which the operator is declared, or a class derived from that class). No conversions are supplied for the first argument.

Note that the meaning of any of the operators can be changed completely. That includes the meaning of the address-of (&), assignment (=), and function-call operators. Also, identities that can be relied upon for built-in types can be changed using operator overloading. For example, the following four statements are usually equivalent when completely evaluated:

var = var + 1;
var += 1;
var++;
++var;

This identity cannot be relied upon for class types that overload operators. Moreover, some of the requirements implicit in the use of these operators for basic types are relaxed for overloaded operators. For example, the addition/assignment operator, +=, requires the left operand to be an l-value when applied to basic types; there is no such requirement when the operator is overloaded.

Note  For consistency, it is often best to follow the model of the built-in types when defining overloaded operators. If the semantics of an overloaded operator differ wildly from its meaning in other contexts, it can be more confusing than useful.


  Unary Operators

The unary operators are shown in Table 12.4.

Table 12.4    Redefinable Unary Operators

Operator	Name
!	Logical NOT
&	Address-of
~	One's complement
*	Pointer dereference
+	Unary plus
++	Increment
−	Unary negation
−−	Decrement
Of the operators shown in Table 12.4, the postfix increment and decrement operators (++ and −−) are treated separately in »Increment and Decrement«.

To declare a unary operator function as a nonstatic member, you must declare it in the form:

ret-type operatorop()

where ret-type is the return type and op is one of the operators listed in Table 12.4.

To declare a unary operator function as a global function, you must declare it in the form:

ret-type operatorop( arg )

where ret-type and op are as described for member operator functions and the arg is an argument of class type on which to operate.

Note  There is no restriction on the return types of the unary operators. For example, it makes sense for logical NOT (!) to return an integral value, but this is not enforced.


  Increment and Decrement

The increment and decrement operators fall into a special category because there are two variants of each:

•	Preincrement and postincrement

•	Predecrement and postdecrement

When you write overloaded operator functions, it can be useful to implement separate versions for the prefix and postfix versions of these operators. To distinguish between the two, the following rule is observed: The prefix form of the operator is declared exactly the same way as any other unary operator; the postfix form accepts an additional argument of type int.

Important  When specifying an overloaded operator for the postfix form of the increment or decrement operator, the additional argument must be of type int; specifying any other type generates an error.

The following example shows how to define prefix and postfix increment and decrement operators for the Point class:

class Point
{
public:
// Declare prefix and postfix increment operators.
Point& operator++();       // Prefix increment operator.
Point operator++(int);     // Postfix increment operator.

// Declare prefix and postfix decrement operators.
Point& operator--();       // Prefix decrement operator.
Point operator--(int);     // Postfix decrement operator.

// Define default constructor.
Point() { _x = _y = 0; }

// Define accessor functions.
int x() { return _x; }
int y() { return _y; }
private:
int _x, _y;
};

// Define prefix increment operator.
Point& Point::operator++()
{
_x++;
_y++;
return *this;
}

// Define postfix increment operator.
Point Point::operator++(int)
{
Point temp = *this;
++*this;
return temp;
}

// Define prefix decrement operator.
Point& Point::operator--()
{
_x--;
_y--;
return *this;
}

// Define postfix decrement operator.
Point Point::operator--(int)
{
Point temp = *this;
--*this;
return temp;
}

The same operators can be defined in file scope (globally) using the following function heads:

friend Point& operator++( Point& )      // Prefix increment
friend Point& operator++( Point&, int ) // Postfix increment
friend Point& operator--( Point& )      // Prefix decrement
friend Point& operator--( Point&, int ) // Postfix decrement

The argument of type int that denotes the postfix form of the increment or decrement operator is not commonly used to pass arguments. It usually contains the value 0. However, it can be used as follows:

class Int
{
public:
    Int &operator++( int n );
private:
    int _i;
};

Int& Int::operator++( int n )
{
    if( n != 0 )    // Handle case where an argument is passed.
        _i += n;
    else
        _i++;       // Handle case where no argument is passed.
    return *this;
}
...

Int i;
i.operator++( 25 ); // Increment by 25.

No syntax exists for using the increment or decrement operators to pass these values other than explicit invocation, as shown in the preceding code. A more straightforward way to implement this functionality is to overload the
addition/assignment operator (+=).


  Binary Operators

Table 12.5 shows a list of operators that can be overloaded.

Table 12.5    Redefinable Binary Operators

Operator	Name
,	Comma
!=	Inequality
%	Modulus
%=	Modulus/assignment
&	Bitwise AND
&&	Logical AND
&=	Bitwise AND/assignment
*	Multiplication
*=	Multiplication/assignment
+	Addition
+=	Addition/assignment
−	Subtraction
−=	Subtraction/assignment
−>	Member selection
−>*	Pointer-to-member selection
/	Division
/=	Division/assignment
<	Less than
<<	Left shift
<<=	Left shift/assignment
<=	Less than or equal to
=	Assignment
==	Equality
>	Greater than
>=	Greater than or equal to
>>	Right shift
>>=	Right shift/assignment
^	Exclusive OR
^=	Exclusive OR/assignment
|	Bitwise inclusive OR
|=	Bitwise inclusive OR/assignment
||	Logical OR
To declare a binary operator function as a nonstatic member, you must declare it in the form:

ret-type operatorop( arg )

where ret-type is the return type, op is one of the operators listed in Table 12.5, and arg is an argument of any type.

To declare a binary operator function as a global function, you must declare it in the form:

ret-type operatorop( arg1, arg2 )

where ret-type and op are as described for member operator functions and arg1 and arg2 are arguments. At least one of the arguments must be of class type.

Note  There is no restriction on the return types of the binary operators; however, most user-defined binary operators return either a class type or a reference to a class type.


  Assignment

The assignment operator (=) is, strictly speaking, a binary operator. Its declaration is identical to any other binary operator, with the following exceptions:

•	It must be a nonstatic member function. No operator= can be declared as a nonmember function.

•	It is not inherited by derived classes.

•	A default operator= function can be generated by the compiler for class types if none exists. (For more information about default operator= functions, see »Memberwise Assignment and Initialization« in Chapter 11.)

The following example illustrates how to declare an assignment operator:

class Point
{
public:
    Point &operator=( Point & );  // Right side is the argument.
    ...
};

// Define assignment operator.
Point &Point::operator=( Point &ptRHS )
{
    _x = ptRHS._x;
    _y = ptRHS._y;

    return *this;  // Assignment operator returns left side.
}

Note that the supplied argument is the right side of the expression. The operator returns the object to preserve the behavior of the assignment operator, which returns the value of the left side after the assignment is complete. This allows writing statements such as:

pt1 = pt2 = pt3;


  Function Call

The function-call operator, invoked using parentheses, is a binary operator. The syntax for a function call is:

Syntax

primary-expression  (  expression-list (opt)   )

In this context, primary-expression is the first operand, and expression-list, a possibly empty list of arguments, is the second operand. The function-call operator is used for operations that require a number of parameters. This works because expression-list is a list instead of a single operand. The function-call operator must be a nonstatic member function.

The function-call operator, when overloaded, does not modify how functions are called; rather, it modifies how the operator is to be interpreted when applied to objects of a given class type. For example, the following code would usually be meaningless:

Point pt;
pt( 3, 2 );

Given an appropriate overloaded function-call operator, however, this syntax can be used to offset the x coordinate 3 units and the y coordinate 2 units. The following code shows such a definition:

class Point
{
public:
    Point() { _x = _y = 0; }
    Point &operator()( int dx, int dy )
        { _x += dx; _y += dy; return *this; }
private:
    int _x, _y;
};

...

Point pt;
pt( 3, 2 );

Note that the function-call operator is applied to the name of an object, not the name of a function.


  Subscripting

The subscript operator ([ ]), like the function-call operator, is considered a binary operator. The subscript operator must be a nonstatic member function that takes a single argument. This argument can be of any type and designates the desired array subscript.

The following example demonstrates how to create a vector of type int that implements bounds checking:

#include <iostream.h>

class IntVector
{
public:
IntVector( int cElements );
~IntVector() { delete _iElements; }
int& operator[]( int nSubscript );
private:
int *_iElements;
int _iUpperBound;
};

// Construct an IntVector.
IntVector::IntVector( int cElements )
{
_iElements = new int[cElements];
_iUpperBound = cElements;
}

// Subscript operator for IntVector.
int& IntVector::operator[]( int nSubscript )
{
static int iErr = -1;

if( nSubscript >= 0 && nSubscript < _iUpperBound )
return _iElements[nSubscript];
else
{
clog << "Array bounds violation." << endl;
return iErr;
}
}

// Test the IntVector class.
main()
{
IntVector v( 10 );

for( int i = 0; i <= 10; ++i )
v[i] = i;

v[3] = v[9];

for( i = 0; i <= 10; ++i )
cout << "Element: [" << i << "] = " << v[i]
                << endl;

return v[0];
}

When i reaches 10 in the preceding program, operator[] detects that an out-of-bounds subscript is being used and issues an error message.

Note that the function operator[] returns a reference type. This causes it to be an l-value, allowing you to use subscripted expressions on either side of assignment operators.


  Class-Member Access

Class-member access can be controlled by overloading the member-selection operator (−>). This operator is considered a unary operator in this usage, and the overloaded operator function must be a class member function. Therefore, the declaration for such a function is:

class-type *operator−>()

where class-type is the name of the class to which this operator belongs. The member-selection operator function must be a nonstatic member function.

This operator is used (often in conjunction with the pointer-dereference operator) to implement "smart pointers" that validate pointers prior to dereference or count usage.

The . member-selector operator cannot be overloaded.


Appendix A: Grammar Summary
  Appendix A  Grammar Summary

This appendix describes the formal grammar of the C++ language, as implemented in the Microsoft C++ compiler. It is loosely organized around the chapter organization of this book as follows:

•	The »Keywords« section describes keywords, covered in »Chapter 1, Lexical Conventions.«

•	The »Expressions« section describes the syntax of expressions, described in »Chapter 4, Expressions.«

•	The »Declarations« section describes the syntax of declarations, described in »Chapter 6, Declarations.«

•	The »Declarators« section describes the syntax of declarators, covered in »Chapter 7, Declarators.«

•	The »Classes« section covers the syntax used in declaring classes, as covered in »Chapter 8, Classes.«

•	The »Statements« section covers the syntax used in writing statements, as covered in »Chapter 5, Statements.«

•	The »Microsoft Extensions« section covers the syntax of features unique to Microsoft C++. Many of these features are covered in »Appendix B, Microsoft-Specific Modifiers.«


  A.1  Keywords

class-name:
identifier

enum-name:
identifier

typedef-name:
identifier

identifier: one of
nondigit
identifier nondigit
identifier digit

nondigit: one of
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

digit: one of
0 1 2 3 4 5 6 7 8 9


  A.2  Expressions

expression:
assignment-expression
expression  ,  assignment-expression

assignment-expression:
conditional-expression
unary-expression  assignment-operator  assignment-expression

assignment-operator:  one of
=  *=  /=  %=  +=  −=  >=  <=  &=  ^=  |=

conditional-expression:
logical-or-expression
logical-or-expression  ?  expression  :  conditional-expression

logical-or-expression:
logical-and-expression
logical-or-expression    ||    logical-and-expression

logical-and-expression:
inclusive-or-expression
logical-and-expression    &&    inclusive-or-expression

inclusive-or-expression:
exclusive-or-expression
inclusive-or-expression  |  exclusive-or-expression

exclusive-or-expression:
and-expression
exclusive-or-expression  ^  and-expression

and-expression:
equality-expression
and-expression  &  equality-expression

equality-expression:
relational-expression
equality-expression  ==  relational-expression
equality-expression  !=  relational-expression

relational-expression:
shift-expression
relational-expression  <  shift-expression
relational-expression  >  shift-expression
relational-expression  <=  shift-expression
relational-expression  =>  shift-expression

shift-expression:
additive-expression
shift-expression  <<  additive-expression
shift-expression  >>  additive-expression

additive-expression:
multiplicative-expression
additive-expression  +  multiplicative-expression
additive-expression  −  multiplicative-expression

multiplicative-expression:
segment-expression
multiplicative-expression  *  segment-expression
multiplicative-expression  /  segment-expression
multiplicative-expression  %  segment-expression

segment-expression:
pm-expression
segment-expression  :>  pm-expression

pm-expression:
cast-expression
pm-expression  .*  cast-expression
pm-expression  −>*  cast-expression

cast-expression:
unary-expression
(  type-name  )  cast-expression

unary-expression:
postfix-expression
++  unary-expression
−−  unary-expression
unary-operator  cast-expression
sizeof  unary-expression
sizeof  (  type-name  )
allocation-expression
deallocation-expression

unary-operator:  one of
*  &  +  −  !  ~

allocation-expression:
:: (opt)   new nmodel (opt ) placement (opt)   new-type-name  new-initializer (opt)
:: (opt)   new nmodel (opt)  placement (opt)  (  type-name  )   new-initializer (opt)

placement:
(  expression-list  )

new-type-name:
type-specifier-list  new-declarator (opt)

new-declarator:
ms-modifier-list  (opt)     *  cv-qualifier-list  (opt)  new-declarator (opt)
ms-modifier-list  (opt)    complete-class-name  ::  *cv-qualifier-list (opt)
new-declarator (opt)
new-declarator (opt)   [  expression  ]

new-initializer:
(  initializer-list  )

deallocation-expression:
:: (opt)   delete cast-expression
:: (opt)   delete  [  ] cast-expression

postfix-expression:
primary-expression
postfix-expression  [  expression  ]
postfix-expression   (  expression-list  )
simple-type-name  (  expression-list  )
postfix-expression  .  name
postfix-expression  −>   name
postfix-expression  ++
postfix-expression  −−

expression-list:
assignment-expression
expression-list  ,  assignment-expression

primary-expression:
literal
this
::  identifier
::  operator-function-name
::  qualified-name (  expression  )
name

name:
identifier
operator-function-name
conversion-function-name
   ~  class-name
qualified-name

qualified-name:
ms-modifier-list (opt)  qualified-class-name  ::  name

literal:
integer-constant
character-constant
floating-constant
string-literal

integer-constant:
decimal-constant integer-suffix (opt)
octal-constant integer-suffix (opt)
hexadecimal-constant integer-suffix (opt)
'c-char-sequence'

decimal-constant:
nonzero-digit
decimal-constant digit

octal-constant:
0
octal-constant octal-digit

hexadecimal-constant:
0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit:  one of
1 2 3 4 5 6 7 8 9

octal-digit:  one of
0 1 2 3 4 5 6 7

hexadecimal-digit:  one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

integer-suffix:
unsigned-suffix long-suffix (opt)
long-suffix unsigned-suffix (opt)

unsigned-suffix:  one of
u U

long-suffix:  one of
l L

character-constant:
'c-char-sequence'
L'c-char-sequence'

c-char-sequence:
c-char
c-char-sequence c-char

c-char:
any member of the source character set except the single quote ('),
   backslash (\), or newline character
escape-sequence

escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence:  one of
\'  \"  \?  \\
\a  \b  \f  \n  \r  \t  \v

octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit

hexadecimal-escape-sequence:
\xhexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit

floating-constant:
fractional-constant exponent-part (opt)  floating-suffix (opt)
digit-sequence exponent-part floating-suffix (opt)

fractional-constant:
digit-sequence (opt)  . digit-sequence
digit-sequence  .

exponent-part:
e sign (opt)  digit-sequence
E sign (opt)  digit-sequence

sign:  one of
+ −

digit-sequence:
digit
digit-sequence digit

floating-suffix:  one of
f l F L

string literal:
''s-char-sequence  (opt) ''
L ''s-char-sequence  (opt) ''

s-char-sequence:
s-char
s-char-sequence s-char

s-char:
any member of the source character set except double quotation marks ( (") ),
   backslash (\), or newline character
escape-sequence


  A.3  Declarations

declaration:
decl-specifiers (opt ) declarator-list (opt)   ;
asm-declaration
function-definition
linkage-specification

asm-declaration:
__asm(string-literal);

decl-specifiers:
decl-specifiers (opt)   decl-specifier

decl-specifier:
storage-class-specifier
type-specifier
fct-specifier
friend
typedef
__declspec ( extended-decl-modifier-seq )  // Microsoft Specific

storage-class-specifier:
auto
register
static
extern

fct-specifier:
inline
virtual

type-specifier:
simple-type-name
class-specifier
enum-specifier
elaborated-type-specifier
const
volatile

extended-decl-modifier-seq:  // Microsoft Specific
extended-decl-modifier (opt)
extended-decl-modifier extended-decl-modifier-seq

extended-decl-modifier:  // Microsoft Specific
thread
naked
dllimport
dllexport

simple-type-name:
complete-class-name
qualified-type-name
char
short
int
long
signed
unsigned
float
double
void
__segment  // 16-Bit Specific

elaborated-type-specifier:
class-key  rmodel (opt)    identifier
class-key  rmodel (opt )   class-name
enum-name

class-key:
class
struct
union

qualified-type-name:
typedef-name
class-name  ::  qualified-type-name

complete-class-name:
qualified-class-name
::  qualified-class-name

qualified-class-name:
class-name
class-name  ::  qualified-class-name

enum-specifier:
enum identifier (opt)   {  enum-list (opt)   }

enum-list:
enumerator
enum-list  ,  enumerator

enumerator:
identifier
identifier  =  constant-expression

constant-expression:
conditional-expression

linkage-specification:
extern string-literal  {  declaration-list (opt )  }
extern string-literal declaration

declaration-list:
declaration
declaration-list  declaration


  A.4  Declarators

declarator-list:
init-declarator
declarator-list  ,   init-declarator

init-declarator:
ms-modifier-list (opt)   declarator  initializer (opt)

declarator:
dname
ptr-operator  declarator
declarator  (  argument-declaration-list  )  cv-mod-list (opt)
declarator  [  constant-expression (opt )  ]
( declarator  )

cv-mod-list:
cv-qualifier  cv-mod-list (opt)
rmodel  cv-mod-list (opt)

ptr-operator:
ms-modifier-list (opt )  *  cv-qualifier-list (opt)
ms-modifier-list (opt)   &  cv-qualifier-list (opt)
ms-modifier-list (opt)   complete-class-name  ::  *  cv-qualifier-list (opt)

cv-qualifier-list:
cv-qualifier  cv-qualifier-list (opt

) cv-qualifier:
const
volatile

dname:
name
class-name
~  class-name
typedef-name
qualified-type-name

type-name:
type-specifier-list  ms-modifier-list (opt )  abstract-declarator (opt)

type-specifier-list:
type-specifier  type-specifier-list (opt

) abstract-declarator:
ptr-operator  ms-modifier-list (opt)   abstract-declarator (opt)
abstract-declarator (opt )  (  argument-declaration-list  )  cv-qualifier-list (opt)
abstract-declarator (opt)   [  constant-expression (opt)   ]
(  ms-modifier-list (opt)   abstract-declarator  )

argument-declaration-list:
arg-declaration-list (opt)   . . . (opt )
arg-declaration-list  ,  . . .

arg-declaration-list:
argument-declaration
arg-declaration-list  ,  argument-declaration

argument-declaration:
decl-specifiers  ms-modifier-list (opt )  declarator
decl-specifiers  ms-modifier-list (opt)   declarator  =  expression
decl-specifiers  ms-modifier-list (opt)   abstract-declarator (opt)
decl-specifiers  ms-modifier-list (opt)   abstract-declarator (opt)   =  expression

function-definition:
decl-specifiers (opt)   ms-modifier-list (opt )  declarator  ctor-initializer (opt)   fct-body

fct-body:
compound-statement

initializer:
=  expression
=  {  initializer-list  , (opt)   }
(  expression-list  )

initializer-list:
expression
initializer-list  ,  expression
{  initializer-list  , (opt)   }


  A.5  Classes

class-specifier:
class-head  {  member-list (opt)   }

class-head:
class-key ambient-model (opt)  identifier (opt)   base-spec (opt)
class-key  ambient-model (opt)  class-name  base-spec (opt)

member-list:
member-declaration  member-list (opt)
access-specifier  :  member-list (opt)

member-declaration:
decl-specifiers (opt )  member-declarator-list (opt)   ;
function-definition  ; (opt)
qualified-name  ;

member-declarator-list:
member-declarator
member-declarator-list  ,  member-declarator

member-declarator:
ms-modifier-list (opt )  declarator pure-specifier (opt)
identifier (opt)   :  constant-expression

pure-specifier:
=  0

base-spec:
:  base-list

base-list:
base-specifier
base-list  ,   base-specifier

base-specifier:
complete-class-name
virtual access-specifier (opt)   complete-class-name
access-specifier virtual (opt)   complete-class-name

access-specifier:
private
protected
public

conversion-function-name:
operator  conversion-type-name

conversion-type-name:
type-specifier-list  ptr-operator (opt)

ctor-initializer:
:  mem-initializer-list

mem-initializer-list:
mem-initializer
mem-initializer  ,  mem-initializer-list

mem-initializer:
complete-class-name  ( expression-list (opt)   )
identifier  ( expression-list (opt)   )

operator-function-name:
operator  operator

operator:  one of
new	delete
+        −        *        /         %       ^       &       |          ~
!         =        <       >         +=      −=      *=      /=       %=
^=     &=      |=      <<       >>      >>=    <<=    ==       !=
<=     >=      &&    ||         ++      −−      ,        −>*       −>
()       []


  A.6  Statements

statement:
labeled-statement
expression-statement
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
asm-statement
try-except-statement  // Microsoft Specific
try-finally-statement  // Microsoft Specific

labeled-statement:
identifier  :  statement
case  constant-expression  :  statement
default  :  statement

expression-statement:
expression (opt )  ;

compound-statement:
{  statement-list (opt)   }

statement-list:
statement
statement-list  statement

selection-statement:
if  (  expression  )  statement
if  (  expression  )  statement else statement
switch  (  expression  ) statement

iteration-statement:
while  (  expression  )  statement
do  statement  while  (  expression  )  ;
for  (  for-init-statement  expression (opt)   ;  expression (opt)   )  statement

for-init-statement:
expression-statement
declaration-statement

jump-statement:
break  ;
continue  ;
return  expression (opt)   ;
goto  identifier  ;

declaration-statement:
declaration

try-except-statement:  // Microsoft Specific
__try compound-statement
__except ( expression ) compound-statement

try-finally-statement:  // Microsoft Specific
__try compound-statement
__finally ( expression ) compound-statement


  A.7  Microsoft Extensions

asm-statement:
__asm assembly-instruction ; (opt)
__asm { assembly-instruction-list } ; (opt)

Note  The definition of assembly-instruction and more information about inline assembly can be found in Chapter 11, "Using the Inline Assembler," of Programming Techniques.

assembly-instruction-list:
assembly-instruction ; (opt)
assembly-instruction ; assembly-instruction-list ; (opt)

amodel:  // 16-Bit Specific
__near
__far

rmodel:  // 16-Bit Specific
amodel
__huge

nmodel:
rmodel
__based  (  expression  )

ambient-model:  // 16-Bit Specific
amb-export
amb-model

amb-model:
amodel amb-model (opt)
__novtordisp amb-model (opt)  (reserved for future implementations)

amb-export:
__export amb-export (opt)
__novtordisp amb-export (opt )  (reserved for future implementations)

ms-modifier-list:
ms-modifier ms-modifier-list (opt)

Note  Many combinations of these modifiers, while syntactically legal, are invalid because of the context in which they appear. For example, __fastcall is not permitted when declaring data.

ms-modifier:
__cdecl
__fortran  // 16-Bit Specific
__pascal  // 16-Bit Specific
__fastcall
__interrupt  // 16-Bit Specific
__export  // 16-Bit Specific
__saveregs  // 16-Bit Specific
__loadds  // 16-Bit Specific
__stdcall
__syscall (reserved for future implementations)
__oldcall (reserved for future implementations)
__unaligned (reserved for future implementations)
__novtordisp (reserved for future 16-bit-specific implementations)
rmodel
based-modifier

based-modifier:
__based ( based-type )

based-type:
void
__self
__segname ( string-literal )  // 16-Bit Specific
( __segment ) expression  // 16-Bit Specific
__segment ( expression )  // 16-Bit Specific
name


Appendix B: Microsoft-Specific Modifiers
  Appendix B  Microsoft-Specific Modifiers

Many of the Microsoft-specific keywords can be used to modify declarators to form derived types. Keywords valid for 16-bit targets only are shown in Table B.1. Keywords valid for 16-bit or 32-bit targets are shown in Table B.2. Table B.3 shows keywords valid for 32-bit targets only. (For more information about declarators, see »Chapter 7, Declarators.«)

16-Bit Specific

Table B.1    Microsoft-Specific Keywords for 16-Bit Targets

Keyword	Meaning	Used to Form Derived Types?
__export	The name that follows is marked with the EXPORT attribute.	Yes
__far	The name that follows declares an object or function that uses segmented addressing.	Yes
__fortran	The name that follows uses the FORTRAN/Pascal naming and calling conventions.	Yes
__huge	The name that follows declares an object or function that uses segmented addressing.	Yes
__interrupt	The name that follows declares a function that is an interrupt service routine.	Yes
__loadds	The name that follows declares a function that must load the DS register as part of the entry sequence.	Yes
__near	The name that follows declares a name that represents a 16-bit offset into DGROUP.	Yes
__pascal	The name that follows uses the FORTRAN/Pascal naming and calling conventions.	Yes
__saveregs	The name that follows declares a function. The function entry sequence saves the values in all registers.	Yes
__segment	The name that follows specifies a segment value — for use with based pointers and objects.	Yes
__segname	Built-in conversion function that takes the name of a segment and returns a value of type __segment — for use with based pointers and objects.	Yes
__self	Specifies the name of the segment in which a based pointer is stored — for use with based pointers and objects. ♦	Yes
Table B.2    Microsoft-Specific Keywords for 16-Bit or 32-Bit Targets

Keyword	Meaning	Used to Form Derived Types?
__asm	Insert the following assembly-language code.	No
__based	The name that follows declares a 16-bit offset to the base contained in the declaration. (1)	Yes
__cdecl	The name that follows uses the C naming and calling conventions.	Yes
__fastcall	The name that follows declares a function that uses registers, when available, instead of the stack for argument passing.	Yes
(1)  Only based-on-pointer form allowed in 32-bit target compilations. In such compilations, they represent a 32-bit offset to a 32-bit base.
32-Bit Specific

Table B.3    Microsoft-Specific Keywords for 32-Bit Targets

Keyword	Meaning	Used to Form Derived Types?
__declspec	The name that follows (thread, naked, dllimport, or dllexport) specifies a Microsoft-specific storage-class attribute.	No
__stdcall	The name that follows specifies a function that observes the standard calling convention. ♦	Yes
The following sections discuss the syntactic usage and semantic meaning of the Microsoft-specific modifiers.


  B.1  Memory-Model Modifiers

16-Bit Specific

Microsoft C++ supports explicit modification of addressing of an object or function. This permits more flexibility in writing code for Intel 80x86 and 80x87 based computers. You can specify a memory model at compile time; this explicit specification overrides the compile-time memory model. Classes can also have an "ambient" memory model — the memory model used if none is explicitly specified. Explicit specification overrides the ambient memory model as well.♦


  Memory-Model Modifiers and Objects

16-Bit Specific

Memory-model modifiers can be used when declaring objects to explicitly specify addressing. A memory-model modifier affects the token immediately to its right. The declaration of pointers provides a good example of how this works. Consider the following declarations:

char __far *lpchObject;                // Declaration 1
char * __far pchlFarPointer;           // Declaration 2
char __far * __far lpchlFarObject;     // Declaration 3

In the first declaration, the keyword __far modifies the token *, making lpchObject a pointer in the default data segment to a "far" object — an object accessed with a 32-bit address.

In the second declaration, the keyword __far modifies the pchlFarPointer token. This modification makes pchlFarPointer a pointer that is not necessarily in the default data segment that refers to an object of type char in the default data segment. It declares a far-allocated pointer to a near object.

In the third declaration, the keyword __far is used twice: once to modify the pointer and once to modify the object. Therefore, it declares a far-allocated pointer to a far object.♦


  Memory-Model Modifiers and Nonmember Functions

16-Bit Specific

The memory-model modifiers can also be used to declare functions. In that context, they specify whether the function call is a far (intersegment) or a near (intrasegment) call. Consider the following declaration:

char __far * __far _fstrcpy( char __far *dst, char __far *src );

The preceding code declares a far function (_fstrcpy) that takes two arguments of type "far pointer to char" and returns type "far pointer to char." The declaration can be broken down as follows:

•	Function returning.

•	Accepting two arguments of type far pointer to char.

•	Making a far (intersegment) call to the function named _fstrcpy.

•	Returning a far pointer to type char. ♦


  Memory-Model Modifiers and Member Functions

16-Bit Specific

Memory-model modifiers can be used with nonstatic class-member functions to specify:

•	Calling of the function (intersegment or intrasegment).

•	Addressing for the this pointer.

The following example declares a class that illustrates how these options work:

class String
{
public:
  char * __far GetStringPointer1();
  char * GetStringPointer2() __far;
};

In the preceding class declaration, GetStringPointer1 is always called with an intersegment (far) call. The this pointer passed to GetStringPointer1 is dependent on the ambient memory model (if any) and the compilation options. The function GetStringPointer2 is invoked with the call implied by the compilation options. The this pointer passed to GetStringPointer2 is always far.

The declaration syntax shown for GetStringPointer2 uses the cv-mod-list part of the syntax (see »Overview« in Chapter 7) and is illegal for nonmember functions or static member functions. Using this syntax, only the memory-model specifiers __near, __far, and __huge can be used.

By using different modifiers for the this pointer, you can create functions that behave properly with respect to the address space in which their objects are located. This is particularly useful for any class that does its own memory management. ♦


  Memory-Model Modifiers and Classes

16-Bit Specific

Memory-model modifiers can be used in the declaration of an ambient memory model for classes. This "ambient memory model" overrides the addressing specified in compilation options for a given class.

Syntax

class-head:
class-key rmodel (opt)  identifier (opt)  base-spec (opt)
class-key rmodel (opt)  class-name (opt)  base-spec (opt )

Consider this example:

class __far CollectionOfCustomers
{
public:
       CollectionOfCustomers();
  int    CCAdd( Customer *CNewCustomer );
  Customer& CCFindName( char *Name );
};

The preceding example declares a class called CollectionOfCustomers. No matter what memory model is specified in the compilation options, objects of type CollectionOfCustomers, along with this pointers for member functions, are far unless specifically declared as near. Consider the following example:

CollectionOfCustomers *pBestCustomers;

The preceding example declares a pointer to an object whose data is addressed far (not necessarily in the default data segment). The this pointer, which is used for the member functions CollectionOfCustomers (the constructor), CCAdd, and CCFindName, is a far pointer.

The ambient memory model can be overridden in explicit declarations as follows:

CollectionOfCustomers __near *npBestCustomers;

In the preceding declaration, npBestCustomers stores its member data in the default data segment (near) even though the ambient memory model calls for far addressing. The this pointer, however, is still far, as specified by the ambient memory model. ♦

Warning  If a class has an ambient memory model that is specifically overridden in an object declaration, only methods where there is an implicit conversion from a pointer to an object to the formal this type are guaranteed to work.

32-Bit Specific

The __near keyword is not supported in 32-bit compilations. ♦


  Memory-Model Specifiers and Overloading

16-Bit Specific

The Microsoft memory-model specifiers for function arguments and for the this pointer are used for disambiguation between overloaded functions. The following two functions are considered different because the arguments use different addressing:

char *strchr( char *szString, char chTarget );
char *strchr( char __far *szString, char chTarget );

This functionality enables different implementations, depending on the addressing specified. Similarly, the member functions in the following class fragment are different because the this pointer is overloaded:

class __far List
{
public:
  List() __far;   // This class is intended to be far.
  List() __huge;  // The near and huge constructors simply
  List() __near;  //  issue run-time error messages.
...
protected:
  void AddressingError( char *szModel );
};

List::List() __far // Correct instantiation.
{
  // Set up the list.
}

List::List() __near // Incorrect addressing.
{
  AddressingError( "__near" );
}

List::List() __huge // Incorrect addressing.
{
  AddressingError( "__huge" );
}

// Issue error message.
inline void AddressingError( char *szModel )
{
  cerr << "Cannot create a "<< szModel
     << " instance of a List.\n"
}

In the preceding example, the functions List::List() __far, List::List() __near, and List::List() __huge are considered different because of the overloaded this pointer. ♦


  __near

16-Bit Specific

The __near keyword specifies that a name is to have 16-bit addressing. For functions, this 16-bit offset is assumed to be from the default code segment, _TEXT; for objects, it is assumed to be from the default data segment, _DATA. Functions declared as __near can be allocated in other segments by declaring them as __based or using the /NT compilation option.

Class-type objects declared as near have:

•	Near addressing for member data.

•	Near this pointer.

•	Function calling determined by the compilation options.

For information about converting near addresses to far and huge, see »Pointer Conversions« in Chapter 3. ♦

32-Bit Specific

The __near keyword is not supported in 32-bit compilations. ♦


  __far

16-Bit Specific

The __far keyword specifies that a name is to have 32-bit addressing. For functions, this 32-bit address contains the segment and offset of the called function; for objects, it contains the segment and offset of the object.

Functions in the same compilation unit reside in the same segment unless the alloc_text, code_seg, or same_seg pragmas are used or unless the function is declared as based. The default naming convention for functions specified as __far is source-filename_TEXT. The default naming convention for objects specified as __far is source-filename_DATA.

Class-type objects declared as far have:

•	Far addressing for member data.

•	Far this pointer.

•	Function calling determined by the compilation options.

•	Limit on object or array size; the practical limit on the size of a single far object is 64K− data-threshold-size. The data-threshold-size defaults to 32,767, but it can be set using the /Gt compilation option.

Objects declared as __far must reside within the segment in which they start. Therefore, they must be smaller than 64K. This restriction allows pointer arithmetic to be done on 16-bit values while still retaining the ability to address data in multiple segments.

The alloc_text pragma affects where segment functions declared as __far reside; the same_seg pragma affects assumptions the compiler makes regarding where segment functions and objects declared as __far reside. For more information about the alloc_text and same_seg pragmas, see Chapter 2 of the Preprocessor Reference. ♦

32-Bit Specific

The __far keyword is not supported in 32-bit compilations. ♦


  __huge

16-Bit Specific

The __huge keyword specifies that a name is to have 32-bit addressing. For objects, this 32-bit address contains the segment and offset of the object; for functions, it is illegal.

The default naming convention for objects specified as __huge is source-filename_DATA. (This is identical to the naming convention described for objects declared as __far.)

Class-type objects declared as __huge have:

•	Far addressing for member data.

•	Far this pointer.

•	Function calling determined by the compilation options.

•	Relaxed limit on object and array size. Objects and arrays can be greater than 64K in size; however, if an array exceeds 128K bytes in size, the individual elements must be of a length that is a power of two.

Objects declared as __huge trade efficiency in pointer arithmetic for relaxed limits on array and object size.

Declaring an object of automatic storage class as __huge generates an error. Only static arrays and memory allocated using the new operator can be declared as huge, as in the following example:

struct Customer
{
  char szName[40];   // An object of type Customer
  char szAddr1[30];  //  requires 149 bytes of
  char szAddr2[30];  //  memory.
  char szCity[30];
  char szZip[9];
  char szPhone[10];
};

int main()
{
  // Allocate a static array that occupies 447,000 bytes.
  static Customer __huge GiantArray[3000];

  // Allocate a dynamic array that occupies 447,000 bytes.
  Customer __huge *pCustList = new Customer[3000];

  Customer __huge GiantAutoArray[3000]; // Error. Automatic.
} ♦

Note  Some, but not all, of the run-time library functions support huge types. Check Chapter 1 of the Run-Time Library Reference to see if a particular function will work with objects declared as __huge.

32-Bit Specific

The __huge keyword is not supported in 32-bit compilations. ♦


  __based

Based addressing is useful when you need to:

•	Exercise precise control over the segment in which objects are allocated (static and dynamic based data).

•	Reference far objects using a 16- rather than a 32-bit address. This can decrease the size of an executable file while increasing its speed.  (16-Bit Specific)

•	Store pointers to memory not allocated by your program — for example, ROM data.  (16-Bit Specific)

32-Bit Specific

The only form of based addressing acceptable in 32-bit compilations is "based on a pointer" that defines a type that contains a 32-bit displacement to a 32-bit base or based on void. ♦

Syntax

based-range-modifier:
__based ( base-expression )

base-expression:
base-constant	// 16-Bit Specific
based-variable
based-abstract-declarator
__self	// 16-Bit Specific

base-constant:	// 16-Bit Specific
segment-name
segment-cast

based-variable:
identifier

based-abstract-declarator:
abstract-declarator

base-type:
type-name

segment-name:	// 16-Bit Specific
__segment ( string-literal )

segment-cast:	// 16-Bit Specific
( __segment ) pointer-id
( __segment ) & identifier

The keywords and operators in the following list have been added to the language to support based addressing:

Keyword or Operator	Use
__segment	A type that contains a segment value. (16-Bit Specific)
__segname	A built-in function that returns type __segment. The __segment function can be used in declarations to initialize variables of type __segment, or it can be used in declarations of based objects or pointers. (16-Bit Specific)
__self	The result of the __self keyword is a far pointer to the segment where a pointer is stored. Basing a pointer on __self avoids the segment-register reloads implicit in storing the pointer and object in different segments. (16-Bit Specific)
:>	Base operator. The base operator combines a segment and an address that can be dereferenced using the * operator. (16-Bit Specific)


  Based Pointers

Based pointers are short (16-bit) offsets from a segment base. The effective address is calculated using the formula:

effective address = base + pointer value

32-Bit Specific

Pointers based on pointer addresses are the only form of the __based keyword valid in 32-bit compilations. In such compilations, based pointers are 32-bit offsets from a 32-bit base. ♦

When dereferencing a based pointer, the base must be either explicitly specified or implicitly known through the declaration. The following code shows some example declarations of based pointers:

16-Bit Specific

// Binary tree
struct BTree
{
  char *szSymbolName;
  BTree *btLeft;
  BTree *btRight;
};

// Declare a pointer to data that resides in segment SYM_DATA.
BTree __based( __segname( "SYM_DATA" ) ) *btSymTable1;

// Declare a pointer to data that resides in segment 0x7000.
const __segment SegVar = (const __segment)0x7000;
BTree __based( SegVar ) *btSymTable2;

// Declare a pointer to data that resides in the same segment
//  as the pointer btSymTable3.
BTree __based( (__segment)__self ) *btSymTable3;

A based pointer can be based on the following:

•	A constant. A pointer can be based on an expression that evaluates to a constant. These constants can be supplied as segment names using the __segname operator.

•	A variable segment. A pointer based on a variable segment is specified using an expression that evaluates type to __segment but that does not evaluate to a constant.

•	Self. A pointer based on self is specified using the __self function. It causes the pointer to refer only to objects in its own segment.

•	Void. A pointer based on void has no implicit base; the base must be supplied at the point of dereference.

•	A pointer. A pointer based on a pointer allows the base to be manipulated at run time. ♦


  Pointers Based on a Constant

16-Bit Specific

Pointers based on a constant are specified in several ways:

In the following example, sgConst is explicitly declared as a constant. The pointer bp1, therefore, is based on a constant.

const __segment sgConst = (const __segment)0x3000;
char __based( sgConst ) *bp1;

In the following example, the __segname function returns a constant value of type __segment. The pointer bp3, therefore, is based on a constant.

char __based( __segname( "INFO_SEg" ) ) *bp3; ♦


  Pointers Based on a Segment Variable

16-Bit Specific

Pointers based on a segment variable require that a variable of type __segment be declared. This variable determines what segment the based pointer refers to and can be changed at run time. The following uses a pointer, pbv, based on a segment variable, sgVar:

#include <iostream.h>

__segment sgVar;

void __based( sgVar ) *pbv;

int main()
{
  static __segment sgList[] =  // Initialize a static array
  {                            //  with the CODE, DATA, and
    __segname( "_CODE" ),      //  STACK segment values.
    __segname( "_DATA" ),
    __segname( "_STACK" )
  };
  static char *aszSegNames[] = // Initialize an array of
  {                            //  strings with the names
    "_CODE",                   //  of the above segments.
    "_DATA",
    "_STACK"
  };

  // Calculate the size of the array.
  int cSegments = sizeof( sgList ) / sizeof ( __segment );

  // Dump the first 256 bytes of each segment.
  for( int i = 0; i < cSegments; ++i )
  {
    cout << "Segment: " << aszSegNames[i] << "\n\n";

    // Set the variable on which pbv is based to point to
    //  the ith segment in the list.
    sgVar = sgList[i];
    // Initialize pbv to point to the
    //  initial byte of the current
    //  segment (sgList[i]:0000).
    for( int row = 0, pbv = 0; row < 16; ++row )
    {
      for( int col = 0; col < 16; ++col, pbv++ )
        cout << hex << *(unsigned*)pbv << " ";
      for( col = 0, pbv -= 16; col < 16; ++col, pbv++ )
        cout << isprint(*(char*)pbv) ? *(char*)pbv : '.';
      cout << "\n";
    }
  }
  return 0;
} ♦


  Pointers Based on Self

16-Bit Specific

Pointers based on self can access data anywhere in the segment in which the pointer resides. They are declared using the __self function cast to the __segment type as the base-expression. You can base a pointer only on (__segment)__self. You cannot base a pointer on __self alone. Basing a pointer on self can improve program performance by requiring that the segment register be the same for addressing both the pointer and the data it addresses.

Note  While both the pointer and the data are in the same segment, some segment-register reloads can be forced by such operations as conversions, references to other data, and function calls.

Functions cannot return pointers based on self. Also, register variables cannot be based on self. Only addressable l-values can be converted to pointers based on self.

Since only l-values can be converted to pointer types based on self, you cannot assign a constant to a pointer based on self. Consider the following code:

int __based((__segment)__self) *piself;
piself = 1;

Before performing the assignment, the compiler attempts to convert 1, which is of type const int, to type int __based(void) *, which is an illegal conversion. To put the value 1 in the pointer piself, you first must cast 1 to a pointer based on void, as follows:

piself = (int __based(void)*)1; ♦

32-Bit Specific

Pointers based on self are not supported in 32-bit target compilations. ♦


  Pointers Based on void

16-Bit Specific

Pointers based on void defer address calculation until the pointer is dereferenced. Unlike most other forms of based pointers, a pointer that is based on void has no implied segment as its base.

The segment specified at the point of dereference can be a constant or a segment variable. It is combined with the offset using the base operator (:>) to form an address that can be dereferenced using the indirection operator (*).

The following example shows how to declare and dereference a pointer based on void.

struct BiosEquipList  // Structure for the BIOS Equipment List
{                     //  that starts at 0000:0410 (hex).

...

};

// Declare ROM data as const and supply the offset, hex 410.
const BiosEquipList __based( void ) *bpelROM = \
(const BiosEquipList __based( void ) *)0x410;

int main()
{
  BiosEquipList elLocal;  // Local copy of equipment list.

  // Make a local "shadow" copy of the BIOS equipment list.
  elLocal = *((__segment)0x0000 :> bpelROM);

  return 0;
} ♦


  Pointers Based on Pointers

The "based on pointer" variant of based addressing enables specification of a pointer as a base-expression. The based pointer, then, is an offset into the segment starting at the beginning of the pointer on which it is based.

One use for pointers based on pointers is for persistent objects that contain pointers. A linked list that consists of pointers based on pointers can be saved to disk and reloaded to another place in memory, and the pointers will still be valid. The following example declares such a linked list:

void *vpBuffer;

struct llist_t
{
  void __based( vpBuffer ) *vpData;
  llist_t __based( vpBuffer ) *llNext;
};

The pointer, vpBuffer, is assigned the address of memory allocated at some later point in the program; the linked list is then relocated relative to the value of vpBuffer.

32-Bit Specific

Pointers based on pointer addresses are the only forms of __based valid in 32-bit compilations. In such compilations, they are 32-bit displacements from a 32-bit base. ♦


  Based Objects

16-Bit Specific

Static and external objects can be declared using the __based keyword. In this context, the __based specification causes the object to be allocated in the specified segment. The following example shows how to declare a based object:

class Symbol
{
...
};

Symbol __based( __segname( "SYM_DATA" ) ) Symbol;

The preceding declaration allocates one object of type Symbol in segment  SYM_DATA. Similarly, arrays of objects can be declared as based:

Symbol __based( __segname( "SYM_DATA" ) ) Symbol[3000]; ♦


  Based Functions

16-Bit Specific

If a function is to be allocated in a given segment, it can be declared as based on a segment constant. No other forms of based declarations are accepted for functions. Consider the following example:

char __based(__segname("STRING_TEXT")) \
  __near *StringCompare( char __near *String1, char __near *String2 );
char __based(__segname("STRING_TEXT")) \
  __far *FStringCompare( char __far *String1, char __far *String2 );

In the preceding declaration, both StringCompare and FStringCompare are allocated in the segment STRING_TEXT. However, the segment in which the functions are allocated does not affect the calling protocol specified by the __near and __far keywords. In the preceding example, StringCompare can be called only by other functions in the same segment, and it is accessed using a near (intrasegment) call. The FStringCompare function, however, is declared as __far and can be accessed from any function in the program using a far call.

Note  Declaring functions as __based replaces the alloc_text pragma. However, the alloc_text pragma is retained for backward compatibility.

This application of __based is not used for disambiguation of overloaded functions. Therefore, the following two function declarations conflict:

char __based(__segname("FAR_TEXT")) Print( int iValue );
char __based(__segname("NEAR_TEXT")) Print( int iValue );

The compiler recognizes the suffix _TEXT as a code segment designation. Therefore, any function based on a segment that has the _TEXT suffix is placed in a code segment. If you choose a segment name that does not have the _TEXT suffix, however, the segment chosen is a data segment. ♦


  __segment Keyword

16-Bit Specific

The __segment type is used either at the point of declaration of a based type or at the point of a based dereference to specify the segment in which the based object resides. If specified at the point of declaration, the segment value is implicit and need not be respecified at the point of dereference (based pointers). Otherwise, the segment must be explicitly specified.

The following example shows specification of a segment in a declaration and at the point of dereference:

// Dump the first 256 bytes of the data segment (DS)
//  using based pointers.

#include <iostream.h>
#include <iomanip.h>

int main()
{
  // Segment specified at point of declaration.
  unsigned char __based( __segname( "_DATA" ) ) *puc = 0;

  // Segment specification deferred until point of dereference.
  // pv is a generic pointer to type unsigned char.
  unsigned char __based( void ) *pv = 0;

  int i, j;
  for( i = 0; i < 16; ++i )
  {
    // Specify the segment at point of dereference.
    for( j = 0; j < 16; ++j )
      cout << hex << setw( 2 )
         << (unsigned)*(__segname("_DATA"):>pv++) << " ";
    // Because the segment for puc was specified at the point
    // of declaration, it can be used like a normal pointer.
    for( j = 0, pv += 16; j < 16; ++j )
      cout << *puc++;

    cout << "\n";
  }

  return 0;
}

Type __segment behaves like any other C++ type — derivative types can be formed using the pointer-to, array-of, and function-returning operators (*, [ ], and (), respectively).

An object of type __segment can be initialized with the following three items:

•	The result of the built-in function __segname. This allows specification of a segment by name, causing the linker to insert segment fixups in the executable file, to be resolved at load time.

•	Another expression of type __segment. For example:

__segment sgCustomerData = (__segment)0x7000;
__segment sgCurrent = sgCustomerData;

•	Another expression explicitly cast to type __segment. The following list shows how various expressions are converted in explicit casts to type __segment:

Expression	Base
Cast from pointer not explicitly declared with a memory-model modifier	Segment value for that pointer
Cast from near pointer	Segment value of the default data segment
Cast from far pointer	Segment portion of the far pointer
Cast from based pointer	Base segment of based pointer
Cast from address value obtained using the address-of operator (&) on an object	Segment in which the object is located ♦
32-Bit Specific

The __segment type is not supported in 32-bit compilations. ♦


  __segname Function

16-Bit Specific

The built-in function __segname accepts a quoted string and returns a value of type __segment. A __segname declaration is not an l-value and its address cannot be taken.

The primary use for the __segname function is in initializing objects of type __segment or in declarations of pointers or objects of based type. It enables specification of a segment name instead of a segment value when declaring a based type. Consider the following example:

// Keep all message strings for the File.Open dialog box
//  in the same segment.
char __based(__segname("ERR_STRINGS")) *szErrStr[] =
{
  "Cannot find file: %s",
  "Cannot open file: %s",
  "Invalid path: %s",
  "Drive %c: does not exist or is not ready",
  ...
};

Collecting like data into the same segment is beneficial in Windows programming because users are commonly performing a task — such as opening a file — that requires only a certain subset of the application's data. Microsoft Windows manages segment swapping; however, the way data is organized in those segments can greatly affect how often these disk-intensive swaps occur.

The following list shows the predefined segment-name constants you can use as arguments to the __segname function:

Name	Refers To
_CODE	The default code segment
_DATA	The default data segment
_CONST	The default CONST segment    ♦
32-Bit Specific

The __segname keyword is not supported in 32-bit compilations. ♦


  __self Function

16-Bit Specific

Pointers can be declared as based on __self. This form of declaration defers calculation of the pointer value until the point of dereference. It also ensures that the object the pointer references is in the same segment as the pointer itself. For example:

char __based( (__segment)__self ) *pszMessage;

...

pszMessage = new char __based( __self )[1024];
if( pszMessage == NULL )
  cerr << "Cannot allocate 1K buffer.\n";
else
  // 1K buffer allocated in same segment as pointer.

In the preceding example, the pointer is initialized using the new operator. ♦

32-Bit Specific

The __self keyword is not supported in 32-bit compilations. ♦


  B.2  Calling and Naming Convention Modifiers

The modifiers described in this section affect function "calling conventions" and "naming conventions." Calling conventions determine how functions are called; naming conventions determine how external names are treated. Calling and naming conventions are composed of the following elements:

Element	Description
Argument-passing order	For 16-bit targets, some conventions pass arguments to functions from right to left, others from left to right. For 32-bit targets, all conventions pass arguments right to left.
Stack-maintenance responsibility	Because arguments are pushed on the stack for communication with the function, either the called function or the calling function must pop the arguments from the stack.
Name-decoration convention	Some calling conventions add characters to the name as it is declared in the program. This is called "name decoration."
Case-translation convention	Some calling conventions require case translation to uppercase.
Return-value convention	Some calling conventions return values in registers; others return values on the stack. Most return values both ways, depending on the size of the value to be returned.
Note  Functions with variable argument lists must be prototyped, or a linker error occurs. In addition, such functions use the __cdecl calling convention, even if another calling convention has been specified.


  __cdecl

The default calling convention for C and most C++ functions is __cdecl. In addition, functions that have a variable number of arguments use the __cdecl calling convention, whether or not any other calling convention has been specified. Explicit use of the __fastcall or __stdcall convention overrides __cdecl.

The following list shows the implementation of the __cdecl calling convention:

Element	Implementation
Argument-passing order	Right to left
Stack-maintenance responsibility	Calling function pops the arguments from the stack
Name-decoration convention	Underscore character (_) is prefixed to names
Case-translation convention	No case translation performed
32-Bit Specific

The default calling convention for C++ member functions is "thiscall." In the thiscall convention, the this pointer is passed in the ECX register and all other parameters are pushed on the stack right to left. There is no way to specify the thiscall calling convention. Note that member functions that take a variable number of parameters use the __cdecl convention.♦

To declare a function as __cdecl, use a declaration of the form

char * __cdecl stricmp( char *szString1,
            char *szString2 );

The modifier __cdecl modifies the name immediately to its right, stricmp.


  __fastcall

The __fastcall convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention:

Element	Implementation
Argument-passing order	For 16-bit targets, the arguments are passed left to right. For 32-bit targets, the first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
Stack-maintenance responsibility	Called function pops the arguments from the stack.
Name-decoration convention	At sign (@) is prefixed to names; an at sign @ followed by the number of bytes in the parameter list is suffixed to names.
Case-translation convention	No case translation performed.
Return-value conventions	Identical to __cdecl.
To declare a function as __fastcall, use a declaration of the form:

char * __fastcall parsechar( char *szString, char chTarget );

Note that, in the preceding declaration, the modifier __fastcall modifies the name immediately to its right, parsechar.

16-Bit Specific

The compiler allocates registers for the arguments according to the type of the argument and availability of an appropriate register. If no appropriate register is available, the argument is pushed on the stack, much as in the __pascal calling convention. The following list shows the register candidates for various types:

Type	Register Candidate
char, unsigned char	AL, DL, BL
int, unsigned int	AX, DX, BX
long, unsigned long	DX:AX
"pointer to near"	BX, AX, DX
"pointer to far," "pointer to huge"	Passed on the stack
All far and huge pointers, structures, unions, and floating types are passed on the stack. ♦


  __fortran, __pascal

16-Bit Specific

The __fortran and __pascal conventions specify argument passing that is compatible with Microsoft FORTRAN and Microsoft Pascal. The following list shows the implementation of this calling convention:

Element	Implementation
Argument-passing order	Left to right
Stack-maintenance responsibility	Called function adjusts the stack
Name-decoration convention	None
Case-translation convention	Names translated to uppercase
To declare a function as __fortran or __pascal, use a declaration of the form:

void __fortran regress( double series[],
            double *slope,
            double *intercept );

Note that, in the preceding declaration, the modifier __fortran modifies the name immediately to its right, regress. Functions declared using the __fortran or __pascal modifiers return values the same way as those declared using __cdecl. ♦

32-Bit Specific

The __fortran and __pascal keywords are not supported in 32-bit compilations. ♦


  __stdcall

32-Bit Specific

The __stdcall calling convention is a faster, more type-safe version of __cdecl. In addition, __stdcall produces less code than other calling conventions because the code to pop arguments from the stack exists only in the calling function definition. The following list shows the implementation of this calling convention:

Element	Implementation
Argument-passing order	Right to left
Argument-passing convention	By value, unless a pointer or reference type is passed
Stack-maintenance responsibility	Called function pops its own arguments from the stack
Name-decoration convention	An underscore (_) is prefixed to the name. The name is followed by the at-sign (@) character, followed by the number of bytes in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12
Case-translation convention	None
Functions declared using the __stdcall modifier return values the same way as functions declared using __cdecl.

Note  Functions declared using __stdcall must be prototyped or a linker error occurs. ♦


  B.3  Special Modifiers

The Microsoft-specific keywords __export, __interrupt, and __loadds do not necessarily modify the calling or naming convention of a function or object. They can, however, modify other behavior.


  __export

16-Bit Specific

The __export keyword specifies that the named function or object is to be marked for export from a DLL or to Windows. If an object file contains this export definition (known as an EXPDEF record), LINK creates a segmented executable. Applying the __export attribute to a function or object is the same as specifying the name in the EXPORTS section of a module-definition file. See reference information on the /GA command-line option in Chapter 2 of the Build Tools User's Guide for more information.

It is not possible to use the __export keyword to specify any of the following additional information that can be provided in a module-definition file for exported functions or objects:

•	Name aliasing (internal versus external)

•	Tagging functions with ordinal values

•	Keeping names resident in memory

•	Tagging exported real-mode Windows functions as having no data

In most cases, the defaults provided by the __export keyword are sufficient, especially for call-back functions exported to Windows.

The __export keyword can be used with any of the calling-convention modifiers discussed in the previous section, but it should be used only with functions declared as __far. ♦

32-Bit Specific

The __export keyword is not supported for 32-bit compilations. To import and export items in DLLs, use the extended attributes dllimport and dllexport. For more information, see »The dllexport and dllimport Attributes«. ♦


  __interrupt

16-Bit Specific

The __interrupt keyword indicates that the function is an interrupt handler. The compiler generates appropriate entry and exit sequences for the interrupt-handling function, including saving and restoring all registers and executing an IRET instruction to return.

When an interrupt function is entered, the DS register is initialized to the default (near) data segment. This allows access to global variables from within an interrupt function.

In addition, all registers (except SS) are saved on the stack. These registers can be accessed within the function by declaring a function-parameter list containing a formal parameter for each saved register. The following example illustrates such a declaration:

void __interrupt __far int_handler(
  unsigned _es, unsigned _ds,
  unsigned _di, unsigned _si,
  unsigned _bp, unsigned _sp,
  unsigned _bx, unsigned _dx,
  unsigned _cx, unsigned _ax,
  unsigned _ip, unsigned _cs,
  unsigned flags )


  Restrictions on Interrupt Functions

An interrupt function must use the far memory model. Programs compiled with the small or compact memory model must explicitly declare interrupt functions with the __far keyword.

Interrupt functions must observe the __cdecl calling convention. Therefore, the only calling convention keyword that can be used in combination with __interrupt is __cdecl.

Functions declared with the __interrupt keyword cannot be declared with the __saveregs keyword.


  Considerations When Using __interrupt

When an interrupt function is called by an INT instruction, the interrupt enable flag is cleared. This means that no further interrupts (including keyboard, time-of-day, and other crucial interrupts) are processed until the interrupt function returns.

If an interrupt function needs to do significant processing, it should call the _enable function to reset the interrupt-enable flag.

Interrupt functions must obey special rules because they are potentially reentrant (that is, the function can be entered more than once before the first return is executed). When designing an interrupt-handling function, consider the following guidelines:

•	If the function does not use the _enable function to set the interrupt flag, important interrupts may be ignored. This can result in such undesirable effects as lost keystrokes and inaccurate real-time clocks.

•	If the function uses the _enable function to set the interrupt flag, another interrupt of the same sort may take place. To make sure that the interrupt handler takes this into account, serialize access to all objects that are not automatic or accessed on the free store using an automatic pointer. ♦

32-Bit Specific

Neither the __interrupt nor the __saveregs keyword is supported in 32-bit compilations. For 32-bit compilations, use the naked storage-class attribute. For more information about this attribute, see »Extended Storage-Class Attributes«. ♦


  __loadds

16-Bit Specific

The __loadds keyword causes the compiler to generate a function-entry sequence to load the data-segment (DS) register with the segment value of the most recently specified data segment. The compiler also generates code to restore the previous DS value when the function terminates.

Loading the DS register is essential for Windows call-back functions and Windows DLL entry points. Because there is no requirement for Windows or clients of a DLL to "know" about the entry function's use of memory, these functions cannot depend on DS pointing to their data segment at entry unless they are declared as loadds or compiled with the /Au compilation option.

Note  The __loadds keyword does not imply any change in calling convention; it can be specified with any calling-convention modifier that is compatible with 16-bit compilations.

When loading the DS register, the compiler uses the segment specified by the /ND (name-data-segment) option or, if no segment has been specified, the default group DGROUP. Note that this function modifier has the same effect as the /Au option, but on a function-by-function basis. ♦

32-Bit Specific

The __loadds keyword is not supported in 32-bit compilations. ♦


  __saveregs

16-Bit Specific

The __saveregs keyword causes the compiler to generate a function entry sequence that saves all CPU registers and an exit sequence that restores the registers. Note that __saveregs does not restore registers used for a return value (the AX register, or AX and DX).

The __saveregs keyword is useful when the register conventions of the caller are not known. For instance, __saveregs can be used for a general-purpose function in a dynamic-link library. Because such a function can be called from any language, it is unsafe to assume any particular calling convention. Using the __saveregs attribute on functions that are intended to be interfaced with assembly-language code can protect the caller against undesirable side effects.

It is illegal to declare a function with both the __saveregs and the __interrupt attributes. ♦

32-Bit Specific

The __saveregs keyword is not supported in 32-bit compilations. For 32-bit compilations, use the naked storage-class attribute. For more information about this attribute, see the next section, »Extended Storage-Class Attributes.« ♦


  B.4  Extended Storage-Class Attributes (32-Bit Specific)

This section describes extended attribute syntax, which simplifies and standardizes extensions to the Microsoft C and C++ languages. The storage-class attributes that use extended attribute syntax include thread, naked, dllimport, and dllexport. Use of these attributes is described later in this section.


  Extended Attribute Syntax

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute (thread, naked, dllimport, or dllexport). Examples of other storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by extended attribute syntax.

This is the extended attribute syntax for C++:

Syntax

decl-specifier :
__declspec ( extended-decl-modifier-seq )   // Microsoft Specific

extended-decl-modifier-seq :   // Microsoft Specific
extended-decl-modifier (opt)
extended-decl-modifier extended-decl-modifier-seq

extended-decl-modifier :   // Microsoft Specific
thread
naked
dllimport
dllexport

White space separates the declaration modifier sequence. Examples of the syntax appear in later sections.

The thread, naked, dllimport, and dllexport storage-class attributes are a property only of the declaration of the object or function to which they are applied. Unlike the __near and __far keywords, which actually affect the type of object or function (in this case, 2- and 4-byte addresses), these storage-class attributes do not redefine the type attributes of the object itself. The thread attribute affects data and objects only. The naked attribute affects functions only. The dllimport and dllexport attributes affect functions, data, and objects.


  The thread Attribute

Thread Local Storage (TLS) is the mechanism by which each thread in a given multithreaded process allocates storage for thread-specific data. In standard multithreaded programs, data is shared among all threads of a given process, whereas thread local storage is the mechanism for allocating per-thread data. For a complete discussion of threads, see the API Programmer's Reference in the Microsoft Win32™ Software Development Kit for Windows NT™.

The C and C++ languages include the extended storage-class attribute, thread. The thread attribute must be used with the __declspec keyword to declare a thread variable. For example, the following code declares an integer thread local variable and initializes it with a value:

__declspec( thread ) int tls_i = 1;

These guidelines must be observed when you are declaring thread local objects and variables:

1.	You can apply the thread attribute only to data declarations and definitions. It cannot be used on function declarations or definitions. For example, the following code generates a compiler error:

#define Thread	__declspec( thread )
Thread void func();	       // Error

2.	You can specify the thread attribute only on data items with static storage duration. This includes global data objects (both static and extern), local static objects, and static data members of classes. You cannot declare automatic data objects with the thread attribute. For example, the following code generates compiler errors:

#define Thread	__declspec( thread )
void func1()
{
    Thread int tls_i;            // Error
}

int func2( Thread int tls_i )    // Error
{
    return tls_i;
}

3.	You must use the thread attribute for the declaration and the definition of a thread local object, whether the declaration and definition occur in the same file or separate files. For example, the following code generates an error:

#define Thread	__declspec( thread )
extern int tls_i;      // This generates an error, because the
int Thread tls_i;      // declaration and the definition differ.

4.	You cannot use the thread attribute as a type modifier. For example, the following code generates a compiler error:

char __declspec( thread ) *ch;	    // Error

5.	Classes cannot use the thread attribute. However, you can instantiate class objects with the thread attribute, as long as the objects do not need to be constructed or destructed. For example, the following code generates a compiler error:

#define Thread __declspec( thread )
class Thread C	// Error: classes can't be declared Thread.
{
// Code
};
C CObject;

Because the declaration of objects that use the thread attribute is permitted, these two examples are semantically equivalent:

#define Thread	__declspec( thread )
Thread class B
{
// Code
} BObject;            // Okay--BObject declared thread local.

class B
{
// Code
}
Thread B BObject;     // Okay--BObject declared thread local.

6.	Standard C permits initialization of an object or variable with an expression involving a reference to itself, but only for objects of nonstatic extent. Although C++ normally permits such dynamic initialization of an object with an expression involving a reference to itself, this type of initialization is not permitted with thread local objects. For example:

#define Thread	__declspec( thread )
Thread int tls_i = tls_i;            // C and C++ error
int j = j;                           // Okay in C++; C error
Thread int tls_i = sizeof( tls_i )   // Okay in C and C++

Note that a sizeof expression that includes the object being initialized does not constitute a reference to itself and is allowed in C and C++.


  The naked Attribute

For functions declared with the naked attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked functions are particularly useful in writing virtual device drivers.

Because the naked attribute is only relevant to the definition of a function and is not a type modifier, naked functions use the extended attribute syntax, described previously. For example, this code defines a function with the naked attribute:

__declspec( naked ) int func( formal_parameters )
{
// Function body
}

Or, alternatively:

#define Naked	__declspec( naked )
Naked int func( formal_parameters )
{
// Function body
}

The naked attribute affects only the nature of the compiler's code generation for the function's prolog and epilog sequences. It does not affect the code that is generated for calling such functions. Thus, the naked attribute is not considered part of the function's type, and function pointers cannot have the naked attribute. Furthermore, the naked attribute cannot be applied to a data definition. For example, this code sample generates an error:

__declspec( naked ) int i;       // Error--naked attribute not
                                 // permitted on data declarations.

The naked attribute is relevant only to the definition of the function and cannot be specified in the function's prototype. For example, this declaration generates a compiler error:

__declspec( naked ) int func();  // Error--naked attribute not
                                 // permitted on function declarations


Rules and Limitations

1.	The return statement is not permitted in a naked function. However, you can return an int by moving the return value into the EAX register before the RET instruction.

2.	Structured exception handling constructs are not permitted in a naked function, because the constructs must unwind across the stack frame.

3.	Any use of the setjmp run-time function is not permitted in a naked function, because it too must unwind across the stack frame. However, use of the longjmp run-time function is permitted.

4.	Use of the _alloca function is not permitted in a naked function.

5.	To ensure that no initialization code for local variables appears before the prolog sequence, initialized local variables are not permitted at function scope. In particular, the declaration of C++ objects is not permitted at function scope. There can, however, be initialized data in a nested scope.

6.	Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically suppressed for a naked function.


  Considerations for Writing Prolog/Epilog Code

Before writing your own prolog and epilog code sequences, it is important to understand how the stack frame is laid out. It is also useful to know how to use the __LOCAL_SIZE symbol.

Stack Frame Layout

A few minor differences exist between 16- and 32-bit stack frame layout. This example shows the standard prolog code that might appear in a 32-bit function:

push        ebp                ; Save ebp
mov         ebp, esp	           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

The localbytes variable represents the number of bytes needed on the stack for local variables, and the <registers> variable is a placeholder that represents the list of registers to be saved on the stack. After pushing the registers, you can place any other appropriate data on the stack. The following is the corresponding epilog code:

pop         <registers>   ; Restore registers
mov         esp, ebp	      ; Restore stack pointer
pop         ebp           ; Restore ebp
ret                       ; Return from function

The stack always grows down (from high to low memory addresses). The base pointer (ebp) points to the pushed value of ebp. The locals area begins at ebp-2. To access local variables, calculate an offset from ebp by subtracting the appropriate value from ebp.

__LOCAL_SIZE

The compiler provides a symbol, __LOCAL_SIZE, for use in the inline assembler block of function prolog code. This symbol is used to allocate space for local variables on the stack frame in custom prolog code.

The compiler determines the value of __LOCAL_SIZE. Its value is the total number of bytes of all user-defined local variables and compiler-generated temporary variables. __LOCAL_SIZE can be used only as an immediate operand; it cannot be used in an expression. You must not change or redefine the value of this symbol. For example:

mov        eax, __LOCAL_SIZE           ;Immediate operand--Okay
mov        eax, [ebp - __LOCAL_SIZE]   ;Error

The following example of a naked function containing custom prolog and epilog sequences uses the __LOCAL_SIZE symbol in the prolog sequence:

__declspec ( naked ) func()
{
int i;
int j;

__asm	/* prolog */
{
push	ebp
mov	ebp, esp
sub	esp, __LOCAL_SIZE
}

/* Function body */

__asm	/* epilog */
{
mov	esp, ebp
pop	ebp
ret
}
}


  The dllexport and dllimport Attributes

The dllexport and dllimport storage-class modifiers export and import functions, data, and objects to and from a DLL. These modifiers, or attributes, explicitly define the DLL's interface to its client, which can be the executable file or another DLL. Declaring functions as dllexport eliminates the need for a module-definition (.DEF) file, at least with respect to the specification of exported functions. Note that dllexport replaces the __export keyword.

The declaration of dllexport and dllimport uses extended attribute syntax:

__declspec( dllexport ) void func();

Alternatively, to make your code more readable, you can use macro definitions:

#define DllImport	__declspec( dllimport )
#define DllExport	__declspec( dllexport )

DllExport void func();
DllExport int i = 10;
DllImport int j;
DllExport int n;


  Definitions and Declarations

The DLL interface refers to all items (functions and data) that are known to be exported by some program in the system; that is, all items that are declared as dllimport or dllexport. All declarations included in the DLL interface must specify either the dllimport or dllexport attribute. However, the definition must specify only the dllexport attribute. For example, the following function definition generates a compiler error:

__declspec( dllimport ) int func()  // Error; dllimport
                                    // prohibited on definition.
{
return 1;
}

This code also generates an error:

#define DllImport	__declspec( dllimport )

__declspec( dllimport ) int i = 10;  // Error; this is a
                                     // definition.

However, this is correct syntax:

__declspec( dllexport ) int i = 10;	  // Okay--export definition

The use of dllexport implies a definition, while dllimport implies a declaration. You must use the extern keyword with dllexport to force a declaration; otherwise, a definition is implied. Thus, the following examples are correct:

#define DllImport	__declspec( dllimport )
#define DllExport	__declspec( dllexport )

extern DllImport int k; // These are both correct and imply a
DllImport int j;        // declaration.

The following examples help to further clarify the above:

static __declspec( dllimport ) int l; // Error; not declared extern.

void func()
{
    static __declspec( dllimport ) int s;  // Error; not declared
                                           // extern.
    __declspec( dllimport ) int m;         // Okay; this is a
                                           // declaration.
    __declspec( dllexport ) int n;         // Error; implies external
                                           // definition in local scope.
    extern __declspec( dllimport ) int i;  // Okay; this is a
                                           // declaration.
    extern __declspec( dllexport ) int k;  // Okay; extern implies
                                           // declaration.
    __declspec( dllexport ) int x = 5;     // Error; implies external
                                           // definition in local scope.
}


  Defining Inline Functions with dllexport and dllimport

You can define as inline a function with the dllexport attribute. In this case, the function is always instantiated and exported, whether or not any module in the program references the function. The function is presumed to be imported by another program.

You can also define as inline a function declared with the dllimport attribute. In this case, the function can be expanded (subject to /Ob specifications), but never instantiated. In particular, if the address of an inline imported function is taken, the address of the function residing in the DLL is returned. This behavior is the same as taking the address of a non-inline imported function.

These rules apply to inline functions whose definitions appear within a class definition. In addition, static local data and strings in inline functions maintain the same identities between the DLL and client as they would in a single program (that is, an executable file without a DLL interface).

Exercise care when providing imported inline functions. For example, if you update the DLL, don't assume that the client will use the changed version of the DLL. To ensure that you are loading the proper version of the DLL, rebuild the DLL's client as well.


  General Rules and Limitations

1.	If you declare a function or object without the dllimport or dllexport attribute, the function or object is not considered part of the DLL interface. Therefore, the definition of the function or object must be present in that module or in another module of the same program. To make the function or object part of the DLL interface, you must declare the definition of the function or object in the other module as dllexport. Otherwise, a linker error is generated.

If you declare a function or object with the dllexport attribute, its definition must appear in some module of the same program. Otherwise, a linker error is generated.

2.	If a single module in your program contains both dllimport and dllexport declarations for the same function or object, the dllexport attribute takes precedence over the dllimport attribute. However, a compiler warning is generated. For example:

__declspec( dllimport ) int i;
__declspec( dllexport ) int i;   // Warning; inconsistent;
                                 // dllexport takes precedence.

3.	In C, if you initialize a globally declared pointer with the address of a data object declared with the dllimport attribute, a compiler error is generated. Similarly, you cannot initialize a static local function pointer with the address of a function declared with the dllimport attribute, or initialize a static local data pointer with the address of a data object declared with the dllimport attribute. The C++ compiler does not enforce this restriction, because C++ supports dynamic initialization of local and global static objects. For example, the following code generates errors when compiled with the C compiler, but not with the C++ compiler.

__declspec( dllimport ) void func1( void );
__declspec( dllimport ) int i;

int *pi = &i;                             // Error in C
static void ( *pf )( void ) = &func1;     // Error in C

void func2()
{
static int *pi = &i;                  // Error in C
static void ( *pf )( void ) = &func1; // Error in C
}

However, because a program that includes the dllexport attribute in the declaration of an object must provide the definition for that object somewhere in the program, you can initialize a global or local static function pointer with the address of a dllexport function. Similarly, you can initialize a global or local static data pointer with the address of a dllexport data object. For example, the following code does not generate errors in C or C++:

__declspec( dllexport ) void func1( void );
__declspec( dllexport ) int i;

int *pi = &i;                              // Okay
static void ( *pf )( void ) = &func1;      // Okay

void func2()
{
    static int *pi = &i;                   // Okay
    static void ( *pf )( void ) = &func1;  // Okay
}


  Using dllimport and dllexport in C++

You can declare C++ classes with the dllimport or dllexport attribute. These forms imply that the entire class is imported or exported. Classes exported in this manner are referred to as exportable classes.

The following example defines an exportable class. All its member functions and static data are exported:

#define DllExport	__declspec( dllexport )

class DllExport C
{
int i;
virtual int func( void )
{ return 1; }
};

Note that explicit use of the dllimport and dllexport attributes on members of an exportable class is prohibited.


  dllexport Classes

When you declare a class dllexport, all its member functions and static data members are exported. You must provide the definitions of all such members in the same program. Otherwise, a linker error is generated. The one exception to this rule applies to pure virtual functions, for which you need not provide explicit definitions. However, because a destructor for an abstract class is always called by the destructor for the base class, pure virtual destructors must always provide a definition. Note that these rules are the same for nonexportable classes.

If you export data of class type or functions that return classes, be sure to export the class.


  dllimport Classes

When you declare a class dllimport, all its member functions and static data members are imported. Unlike the behavior of dllimport and dllexport on nonclass types, static data members cannot specify a definition in the same program in which a dllimport class is defined.


  Inheritance and Exportable Classes

All base classes of an exportable class must be exportable. If not, a compiler warning is generated. Moreover, all accessible members that are also classes must be exportable. This rule permits a dllexport class to inherit from a dllimport class, and a dllimport class to inherit from a dllexport class (though the latter is not recommended). As a rule, everything that is accessible to the DLL's client (according to C++ access rules) should be part of the exportable interface. This includes private data members referenced in inline functions.


  Selective Member Import/Export

Because member functions and static data within a class implicitly have external linkage, you can declare them with the dllimport or dllexport attribute, unless the entire class is exported. If the entire class is imported or exported, the explicit declaration of member functions and data as dllimport or dllexport is prohibited. If you declare a static data member within a class definition as dllexport, a definition must occur somewhere within the same program (as with nonclass external linkage).

Similarly, you can declare member functions with the dllimport or dllexport attributes. In this case, you must provide a dllexport definition somewhere within the same program.

It is worthwhile to note several important points regarding selective member import and export:

1.	Selective member import/export is best used for providing a version of the exported class interface that is more restrictive; that is, one for which you can design a DLL that exposes fewer public and private features than the language would otherwise allow. It is also useful for fine-tuning the exportable interface: when you know that the client, by definition, is unable to access some private data, you need not export the entire class.

2.	If you export one virtual function in a class, you must export all of them, or at least provide versions that the client can use directly.

If you have a class in which you are using selective member import/export with virtual functions, the functions must be in the exportable interface or defined inline (visible to the client).

3.	If you define a member as dllexport but do not include it in the class definition, a compiler error is generated. You must define the member in the class header.

4.	Although the definition of class members as dllimport or dllexport is permitted, you cannot override the interface specified in the class definition.

5.	If you define a member function in a place other than the body of the class definition in which you declared it, a warning is generated if the function is defined as dllexport or dllimport (if this definition differs from that specified in the class declaration).


Appendix C: Decorated Names
  Appendix C  Decorated Names

This appendix discusses decorated names for functions in C++ programs. You must use a decorated name when you need to specify a C++ function name as it is known internally by the linker.


  C.1  Overview

Functions in C++ programs are known internally by their decorated names. A decorated name is created by the compiler during compilation of the function definition or prototype. In most circumstances, you do not need to know the decorated name of a function. However, some uses of function names require that you specify the decorated name of a C++ function. For example, the EXPORTS, IMPORTS, and FUNCTIONS statements in a module-definition (.DEF) file require decorated names for C++ functions. These and other .DEF file statements are described in Chapter 4 of the Build Tools User's Guide.


  Format of a Decorated Name

A decorated name is a string generated by the compiler. It contains the following information:

•	The function name.

•	The class that the function is a member of, if it is a member function. This may include the class that encloses the function's class, and so on.

•	The types of the function's parameters.

•	The calling convention.

•	The return type of the function.

The function and class names are expressed literally in the string. The rest of the string is a code that has internal meaning only for the compiler and linker.

Note  The decoration for a C identifier, in contrast to a C++ identifier, consists only of a leading underscore.


  Viewing Decorated Names

The decorated name of a function is not generated until compilation. After the program is compiled, the linker uses the decorated form of the name. Use the LINK /MAP option to create a map file that shows decorated names. You can control the map output as follows:

•	Specify /MAP with no qualifier to get a map file that contains public symbols listed by name and by address. The map file gives the decorated form of C++ function names in each of these lists.

•	Specify /MAP:ADDRESS to get the same map file that /MAP creates but without the list of symbols sorted by name.

•	Specify /MAP:FULL to add the undecorated form of each name to the map file produced by /MAP. The undecorated form is given after the decorated name. This option also adds the contributions of object files to segments.

To see the undecorated form of the decorated name, you must use /MAP:FULL. Note that inline functions do not generate entries in a map file. For more information on LINK and the /MAP option, see Chapter 4 of the Build Tools User's Guide.


  Examples

The following are examples of decorated names and their undecorated versions:

?calc@@YAHH@Z
   int __near __cdecl calc(int)

?getMonth@Date@@QACHXZ
   public: int __near __pascal Date::getMonth(void)__near

These names are from the map file that is produced when /MAP:FULL is specified to the linker.


  C.2  Getting and Specifying a Decorated Name

Some uses of C++ function names require that you specify the name in its decorated form. Decorated names are required in the FUNCTIONS, EXPORTS, and IMPORTS statements in a .DEF file. This section describes how to get and use a decorated name.

For example, the FUNCTIONS statement in a .DEF file accepts one or more names of functions that are to be placed in a specified order or assigned to a segment or an overlay. To assign a C++ function using the FUNCTIONS statement, you must give the function's decorated name. However, the decorated name is not known until after compilation. Therefore, you must use the following procedure to get and use decorated names in a .DEF file:

1.	Compile the object files for your program.

2.	Create a .DEF file that does not yet specify the C++ functions.

3.	Link your program using a form of the /MAP option.

4.	Examine the map file to learn the decorated names of the functions.

5.	Specify the decorated names in the places where you want to use the functions in the .DEF file.

6.	Relink your program.

Warning  If you change the function name, class, calling convention, any parameter, or the return type, the old decorated name is no longer valid. You must repeat this procedure and use the new version of the decorated name everywhere it is specified.


Appendix D: Charts
  Appendix D  Charts

This appendix contains the following charts:

•	»ASCII Character Codes«

•	»ASCII Multilingual Codes«

•	»ANSI Character Codes«

•	»Key Codes«


  ASCII Character Codes Chart

This table contains the decimal and hexadecimal values of the extended ASCII (American Standards Committee for Information Interchange) character set. The extended character set includes the ASCII character set and 128 other characters for graphics and line drawing, often called the "IBM® character set."


  ASCII Multilingual Codes Chart

There are a number of variants on the IBM character set, called "code pages." Systems sold in some European countries use the multilingual character set known as Code Page 850, which contains fewer graphics symbols and more accented letters and special characters.


  ANSI Character Codes Chart

This is the extended character set of most of the programs used by Windows. The codes of the ANSI (American National Standards Institute) character set from 32 through 126 are displayable characters from the ASCII character set. The ANSI characters displayed as solid blocks are undefined characters and may appear differently on output devices.


  Key Codes Chart

Some keys, such as function keys, cursor keys, and Alt+key combinations, have no ASCII code. When a key is pressed, a microprocessor within the keyboard generates an "extended scan code" of two bytes. The first (low-order) byte contains the ASCII code, if any. The second (high-order) byte has the scan code—a unique code generated by the keyboard when a key is either pressed or released. Because the extended scan code is more extensive than the standard ASCII code, programs can use it to identify keys lacking an ASCII code.


Figure 1.1 Escapes and String Concatenation


Figure 2.1 Block Scope and Name Hiding


Figure 3.1 Inheritance Graph for Illustration of Base-Class Accessibility


Figure 4.1 Expression-Evaluation Order


Figure 4.2 Expression-Evaluation Order with Parentheses


Figure 7.1 Specifiers, Modifiers, and Declarators


Figure 7.2 Conceptual Layout of Multidimensional Array


Figure 7.3 Parts of a Function Definition


Figure 7.4 Decision Graph for Initialization of Reference Types


Figure 8.1 Storage of Data in NumericType Union


Figure 8.2 Memory Layout of Date Object (16-Bit Specific)


Figure 8.3 Layout of Date Object with Zero-Length Bit Field (16-Bit Specific)


Figure 9.1 Simple Single-Inheritance Graph


Figure 9.2 Sample of Directed Acyclic Graph


Figure 9.3 Simple Multiple-Inheritance Graph


Figure 9.4 Multiple Instances of a Single Base Class


Figure 9.5 Simulated Lunch-Line Graph


Figure 9.6 Simulated Lunch-Line Object


Figure 9.7 Simulated Lunch-Line Object with Virtual Base Classes


Figure 9.8 Virtual and Nonvirtual Components of the Same Class


Figure 9.9 Object Layout with Virtual and Nonvirtual Inheritance


Figure 9.10 Virtual vs. Nonvirtual Derivation


Figure 9.11 Ambiguous Conversion of Pointers to Base Classes


Figure 10.1 Access Control in Classes


Figure 10.2 Implications of friend Relationship


Figure 10.3 Access Along Paths of an Inheritance Graph


Figure 11.1 Inheritance Graph Showing Virtual Base Classes


Figure 12.1 Graph Illustrating Preferred Conversions


Figure 12.2 Multiple-Inheritance Graph Illustrating Preferred Conversions


Introduction to the Class Library Reference
Class Library Reference

Introduction

The Class Library Reference covers the classes, global functions, global variables, and macros that make up the Microsoft® Foundation Class Library for Windows NT, which is included with Microsoft Visual C++™ Development System for Windows™ and Windows NT™, 32-bit edition. The »class hierarchy charts« detail the class relationships in the class library. Immediately following this introduction is the »Microsoft Foundation Class Library Update«, which covers programming issues specific to use of the 32-bit version of the Microsoft Foundation Class Library.

This book is divided into two parts:

Part 1    Introduction to the Microsoft Foundation Class Library

Part 2    The Microsoft Foundation Class Reference

Part 1 contains overview material designed to help you learn about and use the Microsoft Foundation Class Library. »Chapter 1« lists the classes in helpful categories. Use these lists to help locate a class that contains the functionality you are interested in. »Chapters 2« through 6 describe the Microsoft Foundation Class Library and the "application framework" that it provides to help you program for the Microsoft Windows and Windows NT operating systems. Use these chapters to learn how the framework operates and how your code fits into the framework. Practical examples and techniques are provided in the Class Library User's Guide.

Material applicable to programs for MS-DOS® as well as to programs for Windows is covered in »Chapter 6«. This includes diagnostics, file handling, exception handling, and collection classes.

Part 2 contains the following components:

•	An alphabetical listing of the classes

•	A section that explains the global functions, global variables, and macros used with the class library

The hierarchy chart and the subset charts included with each class are useful for locating base classes. Be aware that the class documentation does not include repeated descriptions of inherited member functions, inherited operators, and overridden virtual member functions. You must always refer to the base classes depicted in the hierarchy diagrams.

In the alphabetical listing, each class description includes a member summary by category followed by alphabetical listings of member functions (public, protected, and private intermixed), overloaded operators, and data members.

Public and protected class members are documented only when they are normally used in application programs or derived classes. Occasionally, private members are listed because they override a public or protected member in the base class. See the class header files for a complete listing of class members.

Many member functions of the Microsoft Foundation classes encapsulate calls to Windows API functions that are specific to Microsoft Windows version 3.1. (Note that these functions can also be used with Win32s, the application programming interface that runs with either Windows NT or in a 32-bit segment with Windows 3.1.) These functions (and other material) are marked as "Windows 3.1 Only" in the alphabetical reference. To clearly distinguish Windows 3.1−specific material, each such section begins with the heading "Windows 3.1 Only" and ends with a diamond icon (♦).

Some C-language structures defined by Windows are so widely applicable that their descriptions have been reproduced completely in pertinent places in the alphabetical reference. Similarly, styles, such as window styles, are listed in appropriate places in the alphabetical reference.

In Part 2, please note that the "See Also" sections refer to Windows functions by prefacing them with the scope resolution operator (::). For example, ::EqualRect. More information on these functions can be found in the Programmer's Reference in the Windows Software Development Kit, other Windows references, and Help.

The »Macros and Globals« section at the end of the alphabetical class reference details the global functions, global variables, and macros supplied with the Microsoft Foundation Class Library. The section lists data types used with the class library, diagnostic and exception-handling services available, and message-map information. Macros, global functions, and global variables are listed alphabetically. See the beginning of the "Macros and Globals" section for a list of the topics covered.


Book Location
Class Library Reference


  Document Conventions

This book uses the following typographic conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
char, CObject, GetTime, TRACE, MF_STRING, CREATESTRUCT, _setcolor, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. This includes the classes and member functions of the Microsoft Foundation Class Library, macros, flags, data structures and their members, and enumerators. Within discussions of syntax, bold type indicates that the text must be entered exactly as shown.
	Many constants, functions, and keywords begin with either a single or double underscore. These are required as part of the name. For example, the compiler recognizes the __cplusplus manifest constant only when the leading double underscore is included. It may be difficult at first glance to distinguish a single underscore from a double underscore because the two run together on the screen. Therefore, the width of the character(s) is your guide. The sample term setcolor, in the left column above, has one underscore in front of it, while the term far has two underscores in front of it.
expression	Words in italics indicate placeholders for information you must supply, such as a filename. Italic type is also used occasionally for emphasis in the text.
[option]	Items inside square brackets are optional.
#pragma pack {1 | 2}	Braces and a vertical bar indicate a choice among two or more items. You must choose one of these items unless square brackets ([ ] ) surround the braces.
#include <io.h>, MyObject	This font is used for examples, user input, program output, and error messages in text.
CL [option...]  file...	Three dots (an ellipsis) following an item indicate that more items having the same form may appear.
while() {  .  .  . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second.
	The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
"argument"	Quotation marks enclose a new term the first time it is defined in text.
"C string"	Some C constructs, such as strings, require quotation marks.
dynamic-link library (DLL)	The first time an acronym is used, it is usually spelled out.
♦	This symbol denotes the end of a section of "Windows 3.1 Only" material (which also relates to Win32s) or a "Protected" or "Private" class member.
see »Using Projects«.	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to display the referenced information.
CEnterDlg;	The blue box adjoining the blue code indicates that it has been altered from a previous example, usually because you are being instructed to edit it.


Hierarchy Charts

»Application Architecture Hierarchy«

»Visual Object Hierarchy«

»General-Purpose Hierarchy«

»OLE Hierarchy«


General-Purpose Hierarchy


Visual Object Hierarchy


OLE Hierarchy


Application Architecture Hierarchy


The class CBEdit is not available when building with NT.


The class CHEdit is not available when building with NT.


The class CVBControl is not available when building with NT.


  Microsoft Foundation Class Library Update

This update addresses the creation of applications using the Microsoft Foundation Class Library for Windows NT. It focuses on the differences you'll encounter when using the 32-bit version of the Microsoft Foundation Class Library application framework instead of the 16-bit version. This material assumes some familiarity with the application framework and with programming for Windows. For a more complete discussion of 32-bit programming in C and for Windows, see "Porting 16-Bit Code to 32-Bit Windows" in Programming Techniques.

The last two sections of this update, "»Steps for Porting Framework Applications to 32 Bits«" and "»Tips for Porting to Win32«," cover porting an existing 16-bit application to the 32-bit environment. You will want to read this material even if you don't have an application to port because much of it also applies when you write a 32-bit application from scratch.

The following list summarizes issues that arise when programming in the 32-bit environment:

•	Applications created with the 32-bit version of the Microsoft Foundation Class Library version 2.0 run with both Windows NT and Windows version 3.1.

•	The 32-bit version of the Microsoft Foundation Class Library does not support threads.

•	App Studio for Windows NT cannot load and save executable (.EXE) files, compiled resource script (.RES) files, or dynamic-link libraries that were created with Windows NT, and it does not directly support Win32 resource types. For more information about App Studio for Windows NT, see "App Studio Update" in the App Studio User's Guide.

•	The only differences between the application programming interfaces (API) of the two libraries are:

•	The packing of lParam and wParam in the CWnd members OnCommand and OnParentNotify has changed. For more information, see "»Changing Message Handlers«."

•	The CTime class has constructors that accept system and file times from Win32. For more information, see "»Using the CTime Class«."

•	The 32-bit object-code libraries have new names.

•	Some underlying Windows function calls employed by the framework have changed. (These changes are listed for reference only; in each case, the calling class member function has remained unchanged.)

If you are porting a 16-bit Microsoft Foundation Class Library application to 32 bits, you should be aware that the following features are not supported:

•	VBX controls.

•	Microsoft Windows for Pen Computing classes.

•	AFXDLL (MFC200.DLL and MFC200D.DLL).

•	The DLLHUSK, VBCHART, and VBCIRCLE sample applications.


Writing Applications Using the Class Library for Windows NT
  Writing Applications Using the Microsoft Foundation Class Library for Windows NT

This may be your first experience with a 32-bit environment, and even if you are expert in 16-bit programming, you may be uncertain how to proceed. When you finish this material you should have a clear idea of what it means to move from the 16-bit to the 32-bit class library.


Running with Windows NT and Windows 3.1
  Running with Windows NT and Windows Version 3.1

The Microsoft Foundation Class Library for Windows NT uses the Win32s API, which is a subset of the Windows NT API; the library does not use any API functions that are specific to Windows NT. This was done to ensure that your applications will run with either Windows NT or with Windows version 3.1 when using the Win32s dynamic-link libraries (DLL).

One of the fundamental tenets of programming with the Microsoft Foundation Class Library is that a programmer can always make direct calls to the Windows API. If your own code directly calls any Windows NT functions that lie outside Win32s, you need to allow those functions to fail gracefully if you intend your application to run with Windows version 3.1.


  Using Threads

The main thread of an application for Windows NT can use the framework, but subthreads cannot because the library is not reentrant or thread-safe. See Technical Note 37 in MSVCNT\HELP\MFCNOTES.HLP if you intend to implement multithreading within your application.


  Using the New Run-Time Libraries

This section provides information on building versions of the Microsoft Foundation Class Library for Windows NT. This material supersedes Appendix B of the Class Library User's Guide.

Object-code libraries for the class library for Windows NT use the following naming conventions. The library names have the form

NAFXcwd.LIB

where the letters shown in italic lowercase are placeholders for specifiers whose meanings are shown in the following table:

Specifier	Values and Meanings
c	Type of program to create: C=EXE, D=USRDLL
w	Target: W=Windows, R=Console
d	Debug or Release: D=Debug; omit specifier for Release
The following libraries are included prebuilt. If you need to build any of the libraries, do so with the NMAKE commands given in the second column of Table U.1:

Table U.1    Commands for Building Library Versions

Library	Commands to Build the Library
NAFXCWD.LIB	NMAKE
NAFXCW.LIB	NMAKE DEBUG=0
NAFXCRD.LIB	NMAKE TARGET=R
NAFXCR.LIB	NMAKE TARGET=R DEBUG=0
NAFXDWD.LIB	NMAKE DLL=1
NAFXDW.LIB	NMAKE DLL=1 DEBUG=0


  Dynamic-Link Library Support

The NAFXDWD.LIB and NAFXDW.LIB libraries create your application as a dynamic-link library (called a USRDLL) that can be used with applications not built with the class library. Don't confuse this DLL support with MFC200.DLL and MFC200D.DLL (known as AFXDLL), which contain the entire 16-bit class library in a DLL and are not supported in this product.


  Selecting a Library

By default, AppWizard creates an application that uses the NAFXCWD.LIB library, which builds a Windows debug application.

To change the current object-code library used by Visual Workbench

1.	In Visual Workbench, choose Project from the Options menu.

The Project Options dialog box appears.

2.	In the Project Type box, select the project type.

3.	Under Build Mode, select the Debug or Release option button.


  Underlying Windows Function Calls

Some member functions in the 32-bit version of the Microsoft Foundation Class Library call different Windows functions than the corresponding member functions in the 16-bit version. For example, in the 16-bit framework, CDC::SetViewportExt calls the Windows function SetViewportExt, whereas the 32-bit version calls the new Win32 function SetViewportExtEx.

In each of the cases shown in Table U.2, the framework member function is identical in both environments. The change in the underlying Windows call is provided for reference only.

Table U.2    Underlying Windows Function Calls

Framework Member Function	Windows 3.x Function	32-Bit Windows Function
CBitmap::GetBitmapDimension	GetBitmapDimension	GetBitmapDimensionEx
CBitmap::SetBitmapDimension	SetBitmapDimension	SetBitmapDimensionEx
CDC::GetAspectRatioFilter	GetAspectRatioFilter	GetAspectRatioFilterEx
CDC::GetBrushOrg	GetBrushOrg	GetBrushOrgEx
CDC::GetCurrentPosition	GetCurrentPosition	GetCurrentPositionEx
CDC::GetOutputTextExtent	GetTextExtent	GetTextExtentPoint
CDC::GetTextExtent	GetTextExtent	GetTextExtentPoint
CDC::GetViewportExt	GetViewportExt	GetViewportExtEx
CDC::GetViewportOrg	GetViewportOrg	GetViewportOrgEx
CDC::GetWindowExt	GetWindowExt	GetWindowExtEx
CDC::GetWindowOrg	GetWindowOrg	GetWindowOrgEx
CDC::MoveTo	MoveTo	MoveToEx
CDC::OffsetViewportOrg	OffsetViewportOrg	OffsetViewportOrgEx
CDC::OffsetWindowOrg	OffsetWindowOrg	OffsetWindowOrgEx
CDC::ScaleViewportExt	ScaleViewportExt	ScaleViewportExtEx
CDC::ScaleWindowExt	ScaleWindowExt	ScaleWindowExtEx
CDC::SetBrushOrg	SetBrushOrg	SetBrushOrgEx
CDC::SetViewportExt	SetViewportExt	SetViewportExtEx
CDC::SetViewportOrg	SetViewportOrg	SetViewportOrgEx
CDC::SetWindowExt	SetWindowExt	SetWindowExtEx
CDC::SetWindowOrg	SetWindowOrg	SetWindowOrgEx
CGdiObject::UnrealizeObject	UnrealizeObject	None
CWnd::DlgDirSelect	DlgDirSelect	DlgDirSelectEx
CWnd::DlgDirSelectComboBox	DlgDirSelectComboBox	DlgDirSelectComboBoxEx
The UnrealizeObject function has been deleted in Win32. Since calls to »CGdiObject::UnrealizeObject« are common in programs written for Windows version 3.x, yet are now unnecessary, this member function is retained for backward compatibility. It now always returns a nonzero value, without making an underlying Win32 function call. Calls to CGdiObject::UnrealizeObject should not be made in new Win32 programs and should be removed from existing programs eventually.

The QueryAbort function has been deleted in Win32; the CDC::QueryAbort member function has also been deleted. If your program needs this functionality, you should create a member function that calls your AbortProc callback function directly.


  Steps for Porting Framework Applications to 32 Bits

This section describes how to port a 16-bit Microsoft Foundation Class Library application to 32 bits. However, much of this information also applies to writing applications for the 32-bit environment from scratch. For more general information on writing 32-bit applications, see the first section of this update, "»Writing Applications Using the Microsoft Foundation Class Library for Windows NT«."

To port a 16-bit framework application to 32 bits

This procedure uses the same top-down approach advocated in Programming Techniques.

1.	Import your application files into a new Visual Workbench project.

The quickest and easiest way to port an application to the new framework is to create a new project in Visual Workbench and then import your files. (For detailed information, see the Visual Workbench User's Guide.) You can import your files into a new project regardless of whether your original application was created within Visual Workbench. If you want to use an external makefile, you must make the necessary changes manually.

2.	Remove VBX controls.

Because Visual Basic does not support 32-bit programming, VBX controls are not supported in a 32-bit application. Thus, the CVBControl class, the AfxRegisterVBEvent, AfxGetPict, AfxSetPict, and AfxReferencePict global functions, and the ON_VBXEVENT macro are unavailable with Windows NT. If you use VBX controls in your application, you must replace them with standard Windows controls, redesigning your application as necessary.

3.	Remove Windows for Pens extensions.

The Microsoft Foundation Class Library for Windows NT does not include the CHEdit and CBEdit classes, which implement 16-bit extensions for Windows for Pens. Thus, if your existing application supports pen extensions, it will not compile as a 32-bit application. If you want to run with Win32, you will need to substitute another form of user input, most likely keyboard input, for the pen class input.

4.	Remove AFXDLL.

AFXDLL (which consists of MFC200.DLL and the debug version MFC200D.DLL) contains the entire 16-bit Microsoft Foundation Class Library in a DLL and is not supported in the 32-bit version of the class library. If you wrote your 16-bit application to use AFXDLL, remove "\D_AFXDLL" from your compiler options and "MFC200.DLL" or "MFC200D.DLL" from your linker options.

5.	Change VER.H to WINVER.H.

If you generated your 16-bit application with AppWizard, you must change "VER.H" in the RC2 file to "WINVER.H". You must also change any other instances of "VER.H" in your code.

6.	Replace difficult-to-port code, such as assembly language functions and MS-DOS calls, with stubs.

Windows NT is designed to be portable, and your applications should follow suit. If your 16-bit application makes calls to an assembly-language module, you should rewrite it in C or C++ if possible. Otherwise, you will be faced with rewriting the assembly-language portion for each hardware platform that can run Windows NT.

If you've used any MS-DOS services for file I/O, including those used by Windows version 3.x, you will have to rewrite the code using the new Windows NT file I/O set that replaces these services. If you've used the »CFile« class for file I/O, you are shielded from this change because CFile uses the new function calls even though its member function interface remains unchanged.

If you need to write custom file I/O functions, see the Windows NT Software Development Kit documentation for more information.

7.	Build your 16-bit application with Visual C++ for Windows NT and note any 32-bit related problems.

8.	Use the information in the next section, "»Tips for Porting to Win32«," to fix any problems. Rebuild until the main body of your program is running correctly.

9.	Implement each stubbed function with portable code until the entire application runs correctly.


  Tips for Porting to Win32

Moving to 32 bits means changing from a 16-bit segmented architecture to a 32-bit unsegmented address space. What will this change in architecture mean when you port your existing 16-bit application? Memory models, near and far pointers, and 64K segments are an integral part of your existing 16-bit code, but this will change under Win32.

Certain fundamental Windows parameters also change in Win32:

•	Handles to windows and to objects such as pens, brushes, and menus are now 32 bits wide.

•	System metrics have changed (screen dimensions and colors are now 32 bits wide), and thus many graphics and other functions have changed.

•	A WPARAM is now 32 bits wide, which means that message packing and window procedures change.

•	The WinMain function has changed.


  Porting and the Framework

Although most of the changes in Windows parameters are handled for you within the framework, there are some changes you will have to make manually. They are described in the next sections: »Changing Message Handlers«, »Using the CTime Class«, »Using the Collection Classes«, and »Porting from Version 1.0 to Version 2.0 for Windows NT«.


  Changing Message Handlers

Window handles in the Win32 API are now 32 bits wide; consequently, the WPARAM type has been widened from 16 to 32 bits to accommodate this change. This widening often necessitates repacking the values carried by the wParam and lParam parameters.

Programmers who created a 16-bit application for Windows without using the framework and want to port that application to 32 bits must rework a considerable amount of code to account for these changes. Each window procedure declaration must be modified, as well as the message-handling code within the procedure.

The class library accommodates most of these changes internally. The framework hides the window procedure from you, unpacks wParam and lParam, and passes the properly unpacked values to you in message handlers. The only two instances that require your attention are functions that override the »CWnd::OnCommand« and »CWnd::OnParentNotify« message handlers, where the framework passes wParam or lParam directly from Windows to you.

CWnd::OnCommand

If your application overrides OnCommand, check the code carefully and modify it so that it unpacks wParam and lParam correctly. Your 16-bit override of OnCommand will compile successfully, but will not execute correctly.

When the framework receives a WM_COMMAND message, it calls the »CWnd::OnCommand« member function with the following arguments:

virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam );

A command ID, a control handle, and a notification message can be packed in wParam and lParam, depending on the circumstances of the call.

You don't need to change the way you extract the command ID; it is packed the same way in both environments. You can extract it this way:

UINT nID = LOWORD(wParam);

You extract the remaining two values in this way in the 16-bit framework:

HWND hWndCtrl = (HWND)LOWORD(lParam);    	//Control handle

int nCode = HIWORD(lParam);	    //Notification code

You extract them this way in the 32-bit framework:

HWND hWndCtrl = (HWND)lParam;	    //Control handle

int nCode = HIWORD(wParam);	    //Notification code

In both the 16-bit and 32-bit versions, if the »OnCommand« message is from an accelerator, the value retrieved in nCode is 1. If the message is from a menu, the value in nCode is 0.

Beyond the packing change, the 16-bit and 32-bit versions of OnCommand are identical.

The framework also unpacks the wParam and lParam values associated with a WM_COMMAND message to implement message-map entries. The framework properly unpacks the values as appropriate for Windows version 3.x or Win32 with no attention from the programmer.

For example, when an edit control sends a WM_COMMAND message with the EN_UPDATE notification code, the framework unpacks wParam and lParam and then routes the notification to the edit control's parent through the following entry in the parent's message map:

BEGIN_MESSAGE_MAP

ON_EN_UPDATE( ID_MYEDIT, OnMyEditUpdate );

END_MESSAGE_MAP

CWnd::OnParentNotify

As with OnCommand, carefully check any code in your application that overrides OnParentNotify and modify it so that it unpacks values from lParam correctly. Your 16-bit override of OnParentNotify will compile successfully, but will not execute correctly.

The framework calls the »CWnd::OnParentNotify« member function with the following arguments:

afx_msg void OnParentNotify( UINT message, LPARAM lParam );

The OnParentNotify member function is called for the parent of a child window in two cases: when the mouse is clicked over a child window, and when a child window is created or destroyed.

When the message parameter is equal to WM_CREATE or WM_DESTROY  the framework's 16-bit packing of lParam puts the child window handle in the low-order word and the identifier of the child window in the high-order word. For the 32-bit framework, the child window handle has been widened and now takes up all of lParam; the child window identifier is unavailable.

If your Win32 code in OnParentNotify requires the child ID, retrieve it like this:

CWnd* pChild = FromHandle( (HWND)lParam );

int nID = pChild->GetDlgCtrlID();

In this example, FromHandle returns the CWnd object attached to the child window handle. The GetDlgCtrlID member function returns the child window ID. You could also retrieve the child ID by passing the child handle directly to the Windows GetDlgCtrlID function, but the code above also retrieves a pointer to the child CWnd object.

The pointer returned in pChild is temporary and should not be stored for use beyond the scope of OnParentNotify.


  Using the CTime Class

The »CTime« class has constructors that accept system and file times from Win32. If you use CTime objects for these purposes, you must modify their initialization accordingly.

The original CTime 16-bit constructors are still present in the 32-bit framework, but the CTime class now contains a constructor that takes a Windows NT SYSTEMTIME structure and another that takes a Windows NT FILETIME structure.

The two new CTime constructors are:

CTime( const SYSTEMTIME& sysTime );

CTime( const FILETIME& fileTime );

The sysTime parameter is a reference to a Windows NT SYSTEMTIME structure, which has the following form:

typedef struct _SYSTEMTIME {

WORD wYear;

WORD wMonth;

    WORD wDayOfWeek;

    WORD wDay;

    WORD wHour;

    WORD wMinute;

    WORD wSecond;

    WORD wMilliseconds;

} SYSTEMTIME;

The SYSTEMTIME members are as follows:

wYear    The current year

wMonth    The current month; January is 1

wDayOfWeek    The current day of the week; Sunday is 0, Monday is 1, etc.

wDay    The current day of the month

wHour    The current hour

wMinute    The current minute

wSecond    The current second

wMilliseconds    The current millisecond

The fileTime parameter is a reference to a Windows NT FILETIME structure, which represents time as a 64-bit value, a more convenient format for internal storage than a SYSTEMTIME structure and the format used by Windows NT to represent the time of file creation.

A FILETIME structure has the following form:

typedef struct _FILETIME {

    DWORD dwLowDateTime;   /* low 32 bits  */

    DWORD dwHighDateTime;  /* high 32 bits */

} FILETIME, *PFILETIME, *LPFILETIME;

The FILETIME members are as follows:

dwLowDateTime    Specifies the low 32 bits of the file time.

dwHighDateTime    Specifies the high 32 bits of the file time.

If your code contains a CTime initialized with the system time, you should use the SYSTEMTIME constructor in Windows NT.

You most likely will not use CTime FILETIME initialization directly. If you use a CFile object to manipulate a file, »CFile::GetStatus« retrieves the file time stamp for you via a CTime object initialized with a FILETIME structure.


  Using the Collection Classes

With Windows version 3.x, a CObArray and all related array collection classes are constrained by 16-bit memory models and must fit within a single 64K segment.

With Win32, the number of elements that can fit within a framework array collection is limited essentially by available memory. The maximum number of collection elements is the largest possible value of a UINT, which is much larger than a typical computer's memory. The increase in maximum collection size should have little effect upon your code because a framework collection simply throws a »CMemoryException« when it reaches its memory limit in both the 16-bit framework and the 32-bit framework.


Porting from Version 1.0 of the Library to 2.0
  Porting from Version 1.0 of the Class Library to Version 2.0 for Windows NT

In version 2.0 of the Microsoft Foundation Class Library for Windows NT, the »ExitInstance« member function of your WinApp-derived class will be called from a _WEP function provided by the framework (which in turn is called by the C++ run-time library when Windows calls the Windows exit procedure [WEP] of the DLL). If you implemented a DLL using version 1.0 of the class library, you had to explicitly implement the _WEP function. To migrate your DLL from version 1.0 to version 2.0 for Windows NT, you need to move your code from the old _WEP function to an override of the CWinApp::ExitInstance function and remove the old _WEP.


  Porting Application-Specific Code

To successfully complete the port to 32 bits, you have to examine your application-specific code to eliminate any part of it that relies on the 16-bit architecture. For more detail than that provided here, see "Porting 16-Bit Code to 32-Bit Windows" in the Programming Techniques manual and Porting 16-Bit Windows Applications to Win32 and Description of the Win32s API on the Microsoft Developer's Network CD.


  Check Segment and Pointer References in Your Code

You must be certain that your application code makes no specific references to a segmented architecture. And since all pointers are now 32 bits, be sure that you make no assumptions about the size of a pointer and examine any code that copies parts of a pointer. In the 16-bit architecture, a far pointer consists of a base and an offset. Code that accesses the LOWORD of a pointer no longer retrieves an offset.


  Be Careful of Stray Pointers

In Win32, your code and data now reside in one contiguous space, and you will need to be more careful about stray pointers because the segmented architecture won't create convenient pointer boundaries for you.


  Check near and far Declarations

For convenience, Visual C++ for Windows NT merely ignores the following declarations in your code:

•	NEAR and FAR

•	_near and _far

•	near and far

However, _ _near and _ _far declarations will cause a compiler error and should be removed.


  Check 32-Bit Integers

With Win32, integers are 32 bits rather than 16 bits wide. From a programmer's point of view, the framework remains unchanged. However, if your application-specific code makes any assumptions about the size of an integer, that code most likely will break. You need to rework such code to make it independent of data size.

You also should be aware that the change in the size of integers and near pointers will ripple through your application's code and data structures; in particular, structures that contain integers and near pointers will be enlarged. If you, for example, maintain a binary data file format that is based on a structure that contains integers, the code you use to access the file format might break.


  Optimize Data Access

With Win32, data is accessed most efficiently in 32-bit chunks. While you're examining structure changes, consider whether you need to redesign your data structures for greater efficiency of access.


  Realign Data

The 80386 and many 32-bit RISC processors pay a performance penalty for data that is not optimally aligned for 32 bits. Align data on 32-byte boundaries for greatest efficiency. Alignment considerations might also necessitate redesigning the data structure of your program.


  CHAPTER 1  The Microsoft Foundation Class Library

This chapter categorizes and describes the classes in the Microsoft Foundation Class Library for Windows NT, which is based on version 2.0 of the library. These classes support application development for Microsoft Windows version 3.1 and Windows NT.

Because the class library supports programming for Windows, its Windows classes are the largest and most important group of classes. Taken together, they constitute an "application framework" — the framework of an application written for Windows. Your programming task is to fill in the code that is unique to your application.

The library's classes are presented here in the following categories:

•	Root Class

•	Application Architecture Classes

•	Windows Application Class

•	Command-Related Classes

•	Document/View Classes

•	Visual Object Classes

•	Window Classes

•	View Classes

•	Dialog Classes

•	Control Classes

•	Menu Class

•	Drawing Object Classes

•	General-Purpose Classes

•	File Classes

•	Diagnostics

•	Exceptions

•	Collections

•	Miscellaneous Support Classes

•	Object Linking and Embedding (OLE) Classes

•	OLE Base Classes

•	OLE Client Classes

•	OLE Server Classes

•	OLE Exception Class

•	Macros and Globals

The section »General Class Design Philosophy« at the end of this chapter explains how the Microsoft Foundation Class Library was designed.

The framework is explained in detail in »Chapters 2« through 6.

Some of the classes listed above are general-purpose classes that can be used either with the framework or in MS-DOS programs. »Chapter 6« details these classes, which provide useful abstractions such as collections, exceptions, files, and strings. The Object Linking and Embedding (OLE) classes support programming for OLE. See Chapter 18 in the Class Library User's Guide for more information about the OLE classes.


  Class Summary

The following is a brief summary of the classes in the Microsoft Foundation Class Library, divided by category to help you locate what you need. In some cases, a class is listed in more than one category. To see a class's inheritance, use the class »hierarchy diagram«.


  Root Class

Most of the classes in the Microsoft Foundation Class Library are derived from a single base class at the root of the class hierarchy. CObject provides a number of useful capabilities to all classes derived from it, with very low overhead. For more information about CObject and its capabilities, see »CObject Services« in Chapter 6.

CObject

The ultimate base class of nearly all other classes. Supports serializing data and obtaining run-time information about a class.


  Application Architecture Classes

Classes in this category contribute to the architecture of a framework application. They supply functionality common to most applications written for Windows. You fill in the framework to add application-specific functionality. Typically, you do so by deriving new classes from the architecture classes, sometimes adding new members or overriding existing member functions.

The framework consists of a group of class objects that cooperate at run time to function as an application for Windows. The principal objects are:

•	An application object derived from class CWinApp.

•	One or more document objects derived from class CDocument and associated with a window.

•	One or more view objects derived from class CView, each attached to a document and associated with a window.


  Windows Application Class

Each application has one and only one application object; this object coordinates other objects in the running program and is derived from CWinApp.

CWinApp

Encapsulates the code to initialize, run, and terminate the application.


  Command-Related Classes

As the user interacts with the application by choosing menus or control-bar buttons with the mouse, the application sends messages from the affected user-interface object to an appropriate command-target object, which is of class CCmdTarget. Command-target classes derived from CCmdTarget include CWinApp, CWnd, CDocTemplate, CDocument, CView, and the classes derived from them. Class CCmdUI represents a command user-interface object, such as a menu or button, for updating the object's state.

CCmdTarget

Serves as the base class for all classes of objects that can receive and respond to messages.

CCmdUI

Provides a programmatic interface for updating user-interface objects such as menu items or control-bar buttons. The command-target object enables, disables, checks, and/or unchecks the user-interface object via this proxy object.


  Document/View Classes

Document objects, created by document template objects, manage the application's data. View objects, which represent the client area of a window, display a document's data and allow users to interact with it.

CDocTemplate

The base class for document templates. A document template coordinates the creation of document, view, and frame window objects.

CSingleDocTemplate

A template for documents in the single document interface (SDI). SDI applications have only one document open at a time.

CMultiDocTemplate

A template for documents in the multiple document interface (MDI). MDI applications can have multiple documents open at a time.

CDocument

The base class for application-specific documents. Derive your document class(es) from CDocument.

CView

The base class for application-specific views of a document's data. Views display data and take user input to edit or select the data. Derive your view class(es) from CView. See the description of CView and its derived classes under »View Classes«.CPrintInfo

A structure containing information about a print or print preview job. Used by CView's printing architecture.

CCreateContext

A structure passed by a document template to window-creation functions to coordinate the creation of document, view, and frame window objects.


  Visual Object Classes

Classes in this category represent visual user-interface objects: windows, dialog boxes, controls, and menus. Also included are associated objects employed in rendering the contents of a window: device contexts and drawing objects such as pens and brushes.


  Window Classes

Class CWnd and its derived classes encapsulate an HWND, a handle to a Windows window. CWnd can be used by itself or as a base for deriving new classes. The derived classes supplied by the class library represent various kinds of windows.

CWnd

The base class for all windows. Use the derived classes below, or derive your own classes directly from CWnd.

CFrameWnd

The base class for an SDI application's main frame window.

CMDIFrameWnd

The base class for an MDI application's main frame window.

CMDIChildWnd

The base class for an MDI application's document frame windows.


  View Classes

Class CView and its derived classes are child windows that represent the client area of a frame window and that show and accept input for a document.

CView

The base class for application-specific views of a document's data. Views display data and take user input to edit or select the data. Derive your view classes from CView or use CScrollView for automatic scrolling.

CScrollView

The base class for views with scrolling capabilities. Derive your view class from CScrollView for automatic scrolling.

CFormView

A scroll view whose layout is defined in a dialog resource. Derive classes from CFormView to quickly implement user interfaces based on dialog resources.

CEditView

A view with text-editing, searching, replacing, and scrolling capabilities. Use this class to provide a text-based user interface to a document.


  Dialog Classes

Class CDialog and its derived classes encapsulate dialog-box functionality. Since a dialog box is a special kind of window, CDialog is derived from CWnd. Derive your dialog classes from CDialog or use one of the common dialog classes for standard dialog boxes such as opening or saving a file, printing, selecting a font or color, or initiating a search-and-replace operation.

CDialog

The base class for all dialog boxes — both modal and modeless.

CDataExchange

Supplies initialization and validation information for dialog boxes.

CFileDialog

Provides a standard dialog box for opening or saving a file.

CPrintDialog

Provides a standard dialog box for printing a file.

CFontDialog

Provides a standard dialog box for selecting a font.

CColorDialog

Provides a standard dialog box for selecting a color.

CFindReplaceDialog

Provides a standard dialog box for a search-and-replace operation.


  Control Classes

Control classes encapsulate standard Windows controls such as buttons, list boxes, and combo boxes, as well as new controls, including buttons with bitmaps and control bars. The Visual C++ class provides a programmatic interface to the Windows control.

CStatic

A static-text control window. Static controls are used to label, box, or separate other controls in a dialog box or window.

CButton

A button control window. The class provides a programmatic interface to a pushbutton, check box, or radio button in a dialog box or window.

CEdit

An editable-text control window. Edit controls are used to take textual input from the user.

CScrollBar

A scroll-bar control window. The class provides the functionality of a scroll bar for use as a control in a dialog box or window through which the user can specify a position within a range.

CListBox

A list-box control window. A list box displays a list of items that the user can view and select.

CComboBox

A combo-box control window. A combo box consists of an edit control plus a list box.

CControlBar

A window aligned to the top or bottom of a frame window that contains HWND-based child controls or controls not based on an HWND, such as toolbar buttons. The base class for control bars such as toolbars and status bars.

CStatusBar

The base class for status-bar control windows.

CToolBar

Toolbar control windows that contain bitmap command buttons not based on an HWND.

CDialogBar

A modeless dialog box in the form of a control bar.

CBitmapButton

A button with a bitmap rather than a text caption.

CSplitterWnd

A window that the user can split into multiple panes.


  Menu Class

Class CMenu provides an interface through which to access your application's menus. It's useful for manipulating menus dynamically at run time; for example, you may want to add or delete menu items according to context.

CMenu

Encapsulates an HMENU handle to the application's menu bar and pop-up menus.


  Device-Context Classes

Most of the following classes encapsulate a handle to a Windows device context. A device context is a Windows object that contains information about the drawing attributes of a device such as a display or a printer. All drawing calls are made through a device-context object. Additional classes derived from CDC encapsulate specialized device-context functionality, including support for Windows metafiles.

CDC

The base class for device contexts; used directly for accessing the whole display and for accessing nondisplay contexts such as printers.

CPaintDC

A display context used in OnPaint member functions of windows and OnDraw member functions of views. Automatically calls BeginPaint on construction and EndPaint on destruction.

CClientDC

A display context for client areas of windows. Used, for example, to draw in an immediate response to mouse events.

CWindowDC

A display context for entire windows, including both the client and frame areas.

CMetaFileDC

A device context for Windows metafiles. A Windows metafile contains a sequence of graphics device interface (GDI) commands that can be replayed to create an image. Calls made to the member functions of a CMetaFileDC are recorded in a metafile.


  Drawing Object Classes

The following classes encapsulate handle-based GDI objects. They allow you to manipulate common GDI drawing objects with C++ syntax.

CGdiObject

The base class for GDI drawing tools.

CBitmap

Encapsulates a GDI bitmap, providing an interface for manipulating bitmaps.

CBrush

Encapsulates a GDI brush that can be selected as the current brush in a device context.

CFont

Encapsulates a GDI font that can be selected as the current font in a device context.

CPalette

Encapsulates a GDI color palette for use as an interface between the application and a color output device such as a display.

CPen

Encapsulates a GDI pen that can be selected as the current pen in a device context.

CRgn

Encapsulates a GDI region for manipulating an elliptical or polygonal area within a window. Used in conjunction with the clipping member functions in class CDC.


  General-Purpose Classes

Classes in this category provide a variety of general-purpose services such as file I/O, diagnostics, and exception handling. Also included are classes such as arrays and lists for storing aggregates of data.


  File Classes

Use the following classes, particularly CArchive and CFile, if you write your own input/output processing. Normally you don't need to derive from these classes. If you use the application framework, the default implementations of the Open and Save commands on the File menu handle file I/O (using class CArchive), provided you supply details about how a document "serializes" its contents. For more information about the file classes and serialization, see »The File Classes« and Chapter 14, "Files and Serialization," in the Class Library User's Guide.

CFile

Provides a programmatic interface to binary disk files.

CMemFile

Provides a programmatic interface to in-memory files.

CStdioFile

Provides a programmatic interface to buffered stream disk files, usually in text mode.

CArchive

Cooperates with a CFile object to implement persistent storage for objects through serialization (see »CObject::Serialize«).


  Diagnostics

Use classes CDumpContext and CMemoryState during development to assist with debugging, as described in Chapter 15, "Diagnostics," in the Class Library User's Guide. Use CRuntimeClass to determine the class of any object at run time, as described in Chapter 12, "The CObject Class," in the Class Library User's Guide. The framework uses CRuntimeClass to dynamically create objects of a particular class.

CDumpContext

Provides a destination for diagnostic dumps.

CMemoryState

Provides snapshots of memory use. The class is also used to compare earlier and later snapshots.

CRuntimeClass

Used to determine the exact class of an object at run time.


  Exceptions

The class library provides an exception-handling mechanism based on class CException. The application framework uses exceptions in its code; you can also use them in yours. For more information, see »Exception Handling«. You can derive your own exception types from CException.

CException

The base class for exceptions.

CArchiveException

An archive exception.

CFileException

A file-oriented exception.

CMemoryException

An out-of-memory exception.

CNotSupportedException

An exception resulting from the invocation of an unsupported feature.

CResourceException

An exception resulting from a failure to load a Windows resource.

COleException

An exception resulting from failures in OLE processing. This class is used by both clients and servers.

CUserException

An exception used to stop a user-initiated operation. The user has typically been notified of the problem before this exception is thrown.


  Collections

For handling aggregates of data, the class library provides a group of collection classes — arrays, lists, and "maps" — that can hold a variety of object and predefined types. The collections are dynamically sized. These classes can be used in any program, whether written for Windows or not. However, they are most useful for implementing the data structures that define your document classes in the application framework. You can readily derive specialized collection classes from these, or you can create them with a template tool supplied with the class library. For more information about these approaches, see »The Collection Classes«.

CByteArray

Stores elements of type BYTE in an array.

CDWordArray

Stores elements of type doubleword in an array.

CObArray

Stores pointers to objects of class CObject or to objects of classes derived from CObject in an array.

CPtrArray

Stores pointers to void (generic pointers) in an array.

CStringArray

Stores CString objects in an array.

CWordArray

Stores elements of type WORD in an array.

CUIntArray

Stores elements of type UINT in an array.

CObList

Stores pointers to objects of class CObject or to objects of classes derived from CObject in a linked list.

CPtrList

Stores pointers to void (generic pointers) in a linked list.

CStringList

Stores CString objects in a linked list.

CMapPtrToWord

Maps void pointers to data of type WORD. Uses void pointers as keys for finding data of type WORD.

CMapPtrToPtr

Maps void pointers to void pointers. Uses void pointers as keys for finding other void pointers.

CMapStringToOb

Maps CString objects to CObject pointers. Uses CString objects as keys for finding CObject pointers.

CMapStringToPtr

Maps CString objects to void pointers. Uses CString objects as keys for finding void pointers.

CMapStringToString

Maps CString objects to CString objects. Uses CString objects as keys for finding other CString objects.

CMapWordToOb

Maps data of type WORD to CObject pointers. Uses data of type WORD to find CObject pointers.

CMapWordToPtr

Maps data of type WORD to void pointers. Uses data of type WORD to find void pointers.


  Miscellaneous Support Classes

The following classes encapsulate drawing coordinates, character strings, and time and date information, allowing convenient use of C++ syntax. These objects are used widely as parameters to the member functions of Windows classes in the Microsoft Foundation Class Library. Because CPoint, CSize, and CRect correspond to the POINT, SIZE, and RECT structures, respectively, in the Windows Software Development Kit (SDK), you can use objects of these C++ classes wherever you can use these C-language structures. The classes provide useful interfaces through their member functions. CString provides very flexible dynamic character strings. CTime and CTimeSpan represent time and date values. For more information about these classes, see »Other Support Classes«.

CPoint

Holds coordinate (x, y) pairs.

CSize

Holds distance, relative positions, or paired values.

CRect

Holds rectangular areas.

CString

Holds character strings.

CTime

Holds absolute time and date values.

CTimeSpan

Holds relative time and date values.


  Object Linking and Embedding (OLE) Classes

The class library supplies four categories of classes to support Object Linking and Embedding: OLE base classes, OLE client classes, OLE server classes, and an OLE exception class. For more about using the OLE classes, see Chapter 18 in the Class Library User's Guide.


  OLE Base Classes

The classes listed in this category serve as base classes for more specialized OLE classes in the other categories. These classes are listed here for completeness; you will not use them directly.

COleDocument

The abstract base class of the COleClientDoc and COleServerDoc classes. A COleDocument is the container for items of type CDocItem. A COleClientDoc contains items of type COleClientItem while a COleServerDoc contains items of type COleServerItem.

CDocItem

An item that is part of a document. Abstract base class of COleClientItem and COleServerItem.


  OLE Client Classes

The class library supplies two classes for use in OLE client applications. COleClientDoc represents client documents, which maintain a collection of items of type COleClientItem. A COleClientItem represents the client view of an embedded or linked OLE item. These classes are derived from abstract base classes, as shown.

COleClientDoc

A client document class that manages client items. You must derive your documents from this class instead of CDocument to implement OLE client functionality.

COleClientItem

A client item class that represents the client's side of the connection to an embedded or linked OLE item. You must derive your client items from this class.


  OLE Server Classes

An OLE server application has server objects for each of the document types it supports. A server creates and maintains server documents in much the same way that CDocTemplate objects create and maintain documents. For OLE objects embedded in a client application, the OLE server maintains one server document and one server item for each active item embedded in a client. For OLE objects linked to this server application, the OLE server maintains an OLE server document for each document that contains links. Each of these documents can be linked to multiple server items.

COleServer

A server application class that creates and manages server documents. You must derive a class from this class for each server type your application supports.

COleServerDoc

A server document class that creates and manages server items. You must derive your server documents from this class instead of CDocument.

COleServerItem

A server item class that represents the server's side of the connection to an embedded or linked OLE item. You must derive your server items from this class.

COleTemplateServer

An OLE server implementation class that manages server documents using a document template. This class can be used directly as an alternative to deriving from COleServer.


  OLE Exception Class

The class library provides an exception class, derived from CException, for exceptional conditions that occur during OLE processing. For more information, see Chapter 3, »Working with Messages and Commands«. For details about exception handling, see Chapter 16, "Exceptions," in the Class Library User's Guide.

COleException

An exception resulting from a failure in OLE processing. This class is used by both clients and servers.


  Macros and Globals

The »Macros and Globals« section in Part 2 of this manual documents the elements of the Microsoft Foundation Class Library that are not defined as members of specific classes. These include macros and global functions and variables in the following general categories:

•	Data types

•	Run-time object model services

•	Diagnostic services

•	Exception processing

•	CString formatting and message-box display

•	Message maps

•	Dialog data exchange and validation

•	Application information and management

•	OLE support

•	Standard commands and window IDs


  General Class Design Philosophy

Microsoft Windows was designed long before the C++ language became popular. Because thousands of applications use the C-language Windows application programming interface (API), that interface will be maintained for the foreseeable future. Any C++ Windows interface must therefore be built on top of the procedural C-language API. This guarantees that C++ applications will be able to coexist with C applications.


  Design Goals

The Microsoft Foundation Class Library is truly an object-oriented interface to Windows that meets the following design goals:

•	Significantly reduce the effort of programming an application for Windows

•	Execution speed comparable to that of the C-language API

•	Minimum code size overhead

•	The ability to call any Windows C function directly

•	Easier conversion of existing C applications to C++

•	The ability to leverage from the existing base of C-language Windows programming experience

•	Easier use of the Windows API with C++ than with C

•	True Windows API for C++ that effectively uses C++ language features


  The Application Framework

The core of the Microsoft Foundation Class Library is an encapsulation of a large portion of the Windows API in C++ form. Library classes represent windows, dialog boxes, device contexts, common GDI objects such as brushes and pens, controls, and other standard Windows items. These classes provide a convenient C++ member function interface to the structures in Windows that they encapsulate. For more information about these core classes, see »Window Objects« in Chapter 2.

But 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. Chapter 2, »Using the Classes to Write Applications for Windows«, explains the framework in detail, and the Class Library User's Guide provides a tutorial that teaches application-framework programming.


  Relationship to the C-Language API

The single characteristic that sets the Microsoft Foundation classes for Windows apart from other class libraries for Windows is the very close mapping to the Windows API written in the C language. Further, you can generally freely mix calls to the class library with direct calls to the Windows API. This direct access does not, however, imply that the classes are 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 if there is a clear advantage to doing so.

Because you sometimes need to make native Windows function calls, you should have access to the C-language Windows API documentation. This is included with Microsoft Visual C++ as Help. One useful book is Programming Windows 3.1, third edition, by Charles Petzold, from Microsoft Press. Many of that book's examples can be easily converted to the Microsoft Foundation classes. For examples and additional information about programming with the Microsoft Foundation Class Library version 2.0, see Microsoft Visual C/C++ Programming for Windows by David J. Kruglinski from Microsoft Press. Both of these books are specific to programming for Windows version 3.1.


  In Chapters to Come

Chapters 2 through 6 provide an overview of the framework and how it functions. Table 1.1 shows the topics covered by each chapter.

Table 1.1    Reference Overview Chapters

Chapter	Contents
»2«	The application object; creation of document templates, documents, views, and frame windows. How to initialize these objects.
»3«	Messages and commands; command routing; updating user-interface objects such as menus and toolbar buttons.
»4«	Documents and views; drawing in a view; working with multiple views; printing and print preview.
»5«	Dialog boxes and controls; control bars, including toolbars and status bars; using context-sensitive help.
»6«	Diagnostics; exception handling; files and serialization; collection classes.
The alphabetical reference for the classes in the Microsoft Foundation Class Library begins with »CArchive«.


  CHAPTER 2  Using the Classes to Write Applications for Windows

Taken together, the classes in the Microsoft Foundation Class Library make up an "application framework" — the framework on which you build an application for Windows. At a very general level, the framework defines the skeleton of an application and supplies standard user-interface implementations that can be placed onto the skeleton. Your job as programmer is to fill in the rest of the skeleton — those things that are specific to your application. You can get a head start by using AppWizard to create the files for a very thorough starter application. You use App Studio to design your user-interface elements visually, ClassWizard to connect those elements to code, and the class library to implement your application-specific logic.

This chapter presents a broad overview of the application framework. It also explores the major objects that make up your application and how they are created. Among the topics covered in this chapter are the following:

•	The major objects in a running application

•	Division of labor between the framework and your code

•	The application class, which encapsulates application-level functionality

•	How document templates create and manage documents and their associated views and frame windows

•	Class CWnd, the root base class of all windows

•	Graphic objects, such as pens and brushes

•	The Windows Clipboard

Subsequent chapters continue the framework story, covering:

•	Messages and commands (»Chapter 3«)

•	Documents, views, and frame windows (»Chapter 4«)

•	Dialog boxes, controls, control bars, and context-sensitive help (»Chapter 5«)

For a step-by-step tutorial in which you build an application with the framework, read the Class Library User's Guide, Chapters 1 through 10. Table 2.1 directs you to other documents:

Table 2.1    Where to Find More Information

Topic	Manual	Chapters
Classes mentioned in this chapter	Class Library Reference	Alphabetic reference
App Studio	App Studio User's Guide
ClassWizard	App Studio User's Guide	9
	Class Library User's Guide	6, 7
	Visual Workbench User's Guide	7
AppWizard	Visual Workbench User's Guide	7
	Class Library User's Guide	2
Visual Workbench	Visual Workbench User's Guide
Diagnostics, exceptions	Class Library User's Guide	15 − 16
Macros and globals	Class Library Reference	Alphabetic reference
Resources	App Studio User's Guide


  The Framework

This section introduces the major classes of the framework and three tools that simplify your work with the framework. Some of the classes encapsulate a large portion of the Microsoft Windows application programming interface (API). Other classes encapsulate application concepts such as documents, views, and the application itself.


  SDI and MDI

The Microsoft Foundation Class Library makes it easy to work with both single document interface (SDI) and multiple document interface (MDI) applications.

SDI applications allow only one open document frame window at a time. MDI applications allow multiple document frame windows to be open in the same instance of an application. An MDI application has a window within which multiple MDI child windows, which are frame windows themselves, can be opened, each containing a separate document. In some applications, the child windows may be of different types, such as chart windows and spreadsheet windows. In that case, the menu bar may change as MDI child windows of different types are activated.


  Documents, Views, and the Framework

At the heart of the framework are the concepts of document and view. A document is a data object with which the user interacts in an editing session. It is created by the New or Open commands on the File menu and is typically saved in a file. A view is a window object through which the user interacts with a document.

The key objects in a running application are:

•	The document(s)

Your document class (derived from CDocument) specifies your application's data.

•	The view(s)

Your view class (derived from CView) is the user's "window on the data." The view class specifies how the user sees your document's data and interacts with it. In some cases, you may want a document to have multiple views of the data.

If you need scrolling, derive from CScrollView. If your view has a user interface that is laid out in a dialog-template resource, derive from CFormView. For simple text data, use or derive from CEditView.

•	The frame windows

Views are displayed inside "document frame windows." In an SDI application, the document frame window is also the "main frame window" for the application. In an MDI application, document windows are child windows displayed inside a main frame window. Your derived main frame-window class specifies the styles and other characteristics of the frame windows that contain your views. Derive from CFrameWnd to customize the document frame window for SDI applications. Derive from CMDIFrameWnd to customize the main frame window for MDI applications. Also derive a class from CMDIChildWnd to customize each of the distinct kinds of MDI document frame windows that your application supports.

•	The document template(s)

A document template orchestrates the creation of documents, views, and frame windows. A particular document-template class creates and manages all open documents of one type. Applications that support more than one type of document have multiple document templates. Use class CSingleDocTemplate for SDI applications, or use class CMultiDocTemplate for MDI applications.

•	The application object

Your application class (derived from CWinApp) controls all of the objects above and specifies application behavior such as initialization and cleanup. The application's one and only application object creates and manages the document templates for any document types the application supports.

In a running application, these objects cooperatively respond to user actions, bound together by commands and other messages. A single application object manages one or more document templates. Each document template creates and manages one or more documents (depending on whether the application is SDI or MDI). The user views and manipulates a document through a view contained inside a frame window. »Figure 2.1« shows the relationships among these objects for an SDI application.

The rest of this chapter explains how the framework creates these objects, how they work together, and how you use them in your programming. Documents, views, and frame windows are discussed in more detail in »Chapter 4«.


  AppWizard

AppWizard creates a skeleton application upon which you can build your application-specific code.

You begin your application by invoking AppWizard from Visual Workbench. By default, AppWizard creates an MDI application, but you can change this through the Options dialog box. AppWizard then creates all of the necessary files and classes for the application type you have chosen.

An MDI application created by AppWizard already supports creating new MDI child windows when the user opens a document with the New or Open commands on the File menu. It handles changing the menu bar when an MDI child window of a different type receives the focus. It manages tiling or cascading open MDI child windows in response to the Tile and Cascade commands on the Window menu.

AppWizard also offers numerous options that let you incorporate support for toolbars, printing and print preview, context-sensitive help, and Object Linking and Embedding (OLE) in the files that AppWizard creates.

For more information about AppWizard, see Chapter 7 in the Visual Workbench User's Guide and Chapter 2 in the Class Library User's Guide.


  App Studio

Use App Studio to design your application's user interface and create the application's resources: menus, dialog boxes, custom controls, accelerator keys, bitmaps, icons, cursors, and strings.

After creating a skeletal application with AppWizard, run App Studio from Visual Workbench. Select the type of resource you want to create or edit and open an editor for that type. App Studio lets you work easily and intuitively, operating visually upon visual objects. For example, to add controls to a dialog box, simply select a control icon on the Control Palette, drag it into the dialog box, and drop it in place. Editor functions make it easy to align and organize controls in a dialog box.

To help you even more, the Microsoft Foundation Class Library provides a file called COMMON.RC, which contains "clip art" resources that you can copy from COMMON.RC and paste into your own resource file. COMMON.RC includes toolbar buttons, common cursors, icons, and more. You can use, modify, and redistribute these resources in your application.

For more information about App Studio and COMMON.RC, see the App Studio User's Guide.


  ClassWizard

Applications running under Windows are "message driven." User actions and other events that occur in the running program cause Windows to send messages to the windows in the program. For example, if the user clicks the mouse in a window, Windows sends a WM_LBUTTONDOWN message when the left mouse button is pressed and a WM_LBUTTONUP message when the button is released. Windows also sends WM_COMMAND messages when the user selects commands from the menu bar.

In the framework, various objects — documents, views, frame windows, document templates, the application object — can "handle" messages. Such an object provides a "handler function" as one of its member functions, and the framework maps the incoming message to its handler.

A large part of your programming task is choosing which messages to map to which objects and then implementing that mapping. To do so, you use the ClassWizard tool.

You can invoke ClassWizard from App Studio or from Visual Workbench. ClassWizard will create empty message-handler member functions and you use the Visual Workbench editor to implement the body of the handler.

For more information about messages, see Chapter 3, »Working with Messages and Commands«. For more information about ClassWizard, see Chapter 9 in the App Studio User's Guide.


  Building on the Framework

Your role in configuring an application with the framework is to supply the application-specific source code and to connect the components by defining what messages and commands they respond to. You use the C++ language and standard C++ techniques to derive your own application-specific classes from those supplied by the class library and to override and augment the base class's behavior.

Table 2.2 shows what you do in relation to what the framework does.

Table 2.2    Sequence in Building an Application with the Framework

Task	You Do	The Framework Does
Create a skeleton application.	Run AppWizard. Specify the options you want in the Options dialog box.	AppWizard creates the files for a skeleton application, including source files for your application, document, view, and frame windows; a resource file; a project file (.MAK); and others — all tailored to your specifications.
See what it offers without adding a line of your own code.	Build the skeleton application and run it in Visual Workbench.	The running skeleton application derives many standard File, Edit, View, and Help menu commands from the framework. For MDI applications, you also get a fully functional Window menu, and the framework manages creation, arrangement, and destruction of MDI child windows.
Construct your application's user interface.	Use App Studio to visually edit the application's user interface: • Create menus. • Define accelerators. • Create dialog boxes. • Create and edit bitmaps, icons, and cursors. • Edit the toolbar bitmap created for you by AppWizard. • Create and edit other resources. You can also test the dialog boxes in App Studio.	The default resource file created by AppWizard supplies many of the resources you need. App Studio lets you edit existing resources and add new resources, easily and visually.
Map menus to handler functions.	Use ClassWizard to connect menus and accelerators to handler functions in your code.	ClassWizard inserts message-map entries and empty function templates in the source files you specify and manages many manual coding tasks.
Write your handler code.	Use ClassWizard to jump directly to the code in the Visual Workbench editor. Fill in the code for your handler functions.	ClassWizard brings up the editor, scrolls to the empty function template, and positions the cursor for you.
Map toolbar buttons to commands.	Map each button on your toolbar to a menu or accelerator command by assigning the button the appropriate command ID.	The framework controls the drawing, enabling, disabling, checking, and other visual aspects of the toolbar buttons.
Test your handler functions.	Rebuild the program and use Visual Workbench's built-in debugging tools to test that your handlers work correctly.	You can step or trace through the code to see how your handlers are called. If you've filled out the handler code, the handlers carry out commands. The framework will automatically disable menu items and toolbar buttons that are not handled.
Create additional classes.	Use ClassWizard to create additional document, view, and frame-window classes beyond those created automatically by AppWizard.	ClassWizard adds these classes to your source files and helps you define their connections to any commands they handle.
Implement your document class.	Implement your application-specific document class(es). Add member variables to hold data structures. Add member functions to provide an interface to the data.	The framework already knows how to interact with document data files. It can open and close document files, read and write the document's data, and handle other user interfaces. You can focus on how the document's data is manipulated.
Implement Open, Save, and Save As commands.	Write code for the document's Serialize member function.	The framework displays dialog boxes for the Open, Save, and Save As commands on the File menu. It writes and reads back a document using the data format specified in your Serialize member function.
Implement your view class.	Implement one or more view classes corresponding to your documents. Implement the view's member functions that you mapped to the user interface with ClassWizard.	The framework manages most of the relationship between a document and its view. The view's member functions access the view's document to render its image on the screen or printed page and to update the document's data structures in response to user editing commands.
Enhance default printing.	If you need to support multipage printing, override view member functions.	The framework supports the Print, Print Setup, and Print Preview commands on the File menu. You must tell it how to break your document into multiple pages.
Add scrolling.	If you need to support scrolling, derive your view class(es) from CScrollView.	The view automatically adds scroll bars when the view window becomes too small.
Create form views.	If you want to base your views on dialog-template resources, derive your view class(es) from CFormView.	The view uses the dialog-template resource to display controls. The user can tab from control to control in the view.
Create a simple text editor.	If you want your view to be a simple text editor, derive your view class(es) from CEditView.	The view provides editing functions, Clipboard support, and file input/output.
Add splitter windows.	If you want to support window splitting, add a CSplitterWnd object to your SDI frame window or MDI child window and hook it up in the window's OnCreateClient member function.	The framework supplies splitter-box controls next to the scroll bars and manages splitting your view into multiple panes. If the user splits a window, the framework creates and attaches additional view objects to the document.
Add dialog boxes.	Design dialog-template resources with App Studio. Then use ClassWizard to create a dialog class and the code that handles the dialog box.	The framework manages the dialog box and facilitates retrieving information entered by the user.
Initialize, validate, and retrieve dialog-box data.	You can also define how the dialog box's controls are to be initialized and validated. Use ClassWizard to add member variables to the dialog class and map them to dialog controls. Specify validation rules to be applied to each control as the user enters data. Provide your own custom validations if you wish.	The framework manages dialog-box initialization and validation. If the user enters invalid information, the framework puts up a message box and lets the user reenter the data.
Build, test, and debug your application.	Use the facilities of Visual Workbench to build, test, and debug your application.	Visual Workbench is closely coupled with AppWizard, App Studio, and ClassWizard. It lets you adjust compile, link, and other options. And it lets you browse your source code and class structure.
As you can see, AppWizard, App Studio, and ClassWizard do a lot of work for you and make managing your code much easier. The bulk of your application-specific code is in your document and view classes. For a tour of this process with a real application, see Chapters 1 through 10 in the Class Library User's Guide.

While it is possible to do these tasks by hand or using other tools, your savings in time, energy, and errors suggest that using the tools is greatly to your benefit.

You will learn more about these tools in the rest of this chapter. For more information about AppWizard, see Chapter 7 in the Visual Workbench User's Guide and Chapter 3 in the Class Library User's Guide. For more information about App Studio, see the App Studio User's Guide. For more information about ClassWizard, see Chapter 9 in the App Studio User's Guide, Chapter 7 in the Visual Workbench User's Guide, and Chapters 6 and 7 in the Class Library User's Guide. For information about resources and resource files, see the App Studio User's Guide.


  How the Framework Calls Your Code

It is crucial to understand the relationship between your source code and the code in the framework. When your application runs, most of the flow of control resides in the framework's code. The framework manages the message loop that gets messages from Windows as the user chooses commands and edits data in a view. Events that the framework can handle by itself don't rely on your code at all. For example, the framework knows how to close windows and how to exit the application in response to user commands. As it handles these tasks, the framework uses message handlers and C++ virtual functions to give you opportunities to respond to these events as well. But your code is not in the driver's seat.

Your code is called by the framework for application-specific events. For example, when the user chooses a menu command, the framework routes the command along a sequence of C++ objects: the current view and frame window, the document associated with the view, the document's document template, and the application object. If one of these objects can handle the command, it does so, calling the appropriate message-handler function. For any given command, the code called may be yours or it may be the framework's.

This arrangement is somewhat familiar to programmers experienced with traditional programming for Windows or event-driven programming.

In the next several sections, you'll see what the framework does as it initializes and runs the application and then cleans up as the application terminates. You'll also get a clearer picture of where the code you write fits in.


  CWinApp: The Application Class

The main application class encapsulates the initialization, running, and termination of an application for Windows. An application built on the framework must have one (and only one) object of a class derived from CWinApp. This object is constructed before windows are created.

Like any program for Windows, your framework application has a WinMain function. In a framework application, however, you don't write WinMain. It is supplied by the class library and is called when the application starts up. WinMain performs standard services such as registering window classes. Then it calls member functions of the application object to initialize and run the application.

To initialize the application, WinMain calls your application object's InitApplication and InitInstance member functions. To run the application's message loop, WinMain calls the Run member function. On termination, WinMain calls the application object's ExitInstance member function. »Figure 2.2« shows the sequence of execution in a framework application.

Note  Names shown in bold type indicate elements supplied by the Microsoft Foundation Class Library. Names shown in monospaced type indicate elements that you create or override.


  CWinApp and AppWizard

When it creates a skeleton application, AppWizard declares an application class derived from CWinApp. AppWizard also generates an implementation file that contains the following items:

•	A message map for the application class

•	An empty class constructor

•	A variable that declares the one and only object of the class

•	A standard implementation of your InitInstance member function

The application class is placed in the project header and main source files. The names of the class and files created are based on the project name you supply in the AppWizard dialog box.

The standard implementations and message map supplied are adequate for many purposes, but you can modify them as needed. The most interesting of these implementations is the InitInstance member function. Typically you will add code to the skeletal implementation of InitInstance.


  Overridable CWinApp Member Functions

CWinApp provides several key overridable member functions. The only CWinApp member function that you must override is InitInstance.


  InitInstance

Windows allows you to run more than one copy, or "instance," of the same application. WinMain calls InitInstance every time a new instance of the application starts.

The standard InitInstance implementation created by AppWizard performs the following tasks:

•	Loads standard file options from an .INI file, including the names of the most recently used files.

•	Registers one or more document templates.

•	For an MDI application, creates a main frame window.

•	Processes the command line to open a document specified on the command line or to open a new, empty document.

The central action of InitInstance is to create the document templates that, in turn, create documents, views, and frame windows. For a description of this process, see »Document Templates«.


  ExitInstance

The ExitInstance member function of class CWinApp is called each time a copy of your application terminates, usually as a result of the user quitting the application. Override ExitInstance if you need special cleanup processing, such as freeing graphics device interface (GDI) resources or deallocating memory used during program execution. Cleanup of standard items such as documents and views, however, is provided by the framework, with other overridable functions for doing special cleanup specific to those objects.


  OnIdle

When no Windows messages are being processed, the framework calls the CWinApp member function OnIdle. Override OnIdle to perform background tasks. The default version updates the state of user-interface objects such as toolbar buttons and performs cleanup of temporary objects created by the framework in the course of its operations. »Figure 2.3« illustrates how the message loop calls OnIdle when there are no messages in the queue.


  The Run Function

A framework application spends most of its time in the Run member function of class CWinApp. After initialization, WinMain calls Run to process the message loop.

Run cycles through a message loop, checking the message queue for available messages. If a message is available, Run dispatches it for action. If no messages are available — often the case — Run calls OnIdle to do any idle-time processing that you or the framework may need done. If there are no messages and no idle processing to do, the application waits until something happens. When the application terminates, Run calls ExitInstance. »Figure 2.3« above shows the sequence of actions in the message loop.

Message dispatching depends on the kind of message. For more information, see Chapter 3, »Working with Messages and Commands«.


  Other CWinApp Services

Besides running the message loop and giving you an opportunity to initialize the application and clean up after it, CWinApp provides several other services.


  Shell Registration

By default, AppWizard makes it possible for the user to open data files that your application has created by double-clicking them in the Windows File Manager. If your application is an MDI application and you specify an extension for the files your application creates, AppWizard adds calls to the EnableShellOpen and RegisterShellFileTypes member functions of CWinApp to the InitInstance override that it writes for you.

RegisterShellFileTypes registers your application's document types with File Manager. The function adds entries to the registration database that Windows maintains. The entries register each document type, associate a file extension with the file type, specify a command line to open the application, and specify a dynamic data exchange (DDE) command to open a document of that type.

EnableShellOpen completes the process by allowing your application to receive DDE commands from File Manager to open the file chosen by the user.

This automatic registration support in CWinApp eliminates the need to ship an .REG file with your application or to do special installation work.


  File Manager Drag and Drop

Windows versions 3.1 and later allow the user to drag filenames from the file view window in the File Manager and drop them into a window in your application. You might, for example, allow the user to drag one or more filenames into an MDI application's main window, where the application could retrieve the filenames and open MDI child windows for those files.

To enable file drag and drop in your application, AppWizard writes a call to the CWnd member function DragAcceptFiles for your main frame window in your InitInstance. You can remove that call if you do not want to implement the drag-and-drop feature.


  Keeping Track of the Most Recently Used Documents

As the user opens and closes files, the application object keeps track of the four most recently used files. The names of these files are added to the File menu and updated when they change. The framework stores these filenames in an .INI file with the same name as your project and reads them from the file when your application starts up. The InitInstance override that AppWizard creates for you includes a call to the CWinApp member function LoadStdProfileSettings, which loads information from the .INI file, including the most recently used filenames.


  Document Templates

To manage the complex process of creating documents with their associated views and frame windows, the framework uses two document template classes: CSingleDocTemplate for SDI applications and CMultiDocTemplate for MDI applications. A CSingleDocTemplate can create and store one document of one type at a time. A CMultiDocTemplate keeps a list of many open documents of one type.

Some applications support multiple document types. For example, an application might support text documents and graphics documents. In such an application, when the user chooses the New command on the File menu, a dialog box shows a list of possible new document types to open. For each supported document type, the application uses a distinct document template object. »Figure 2.4« illustrates the configuration of an MDI application that supports two document types. The figure shows several open documents.

Document templates are created and maintained by the application object. One of the key tasks performed during your application's InitInstance function is to construct one or more document templates of the appropriate kind. This feature is described in »Document Template Creation«. The application object stores a pointer to each document template in its template list and provides an interface for adding and removing document templates.

If you need to support two or more document types, you must add an extra call to AddDocTemplate for each document type.


  Document Template Creation

While creating a new document in response to a New or Open command from the File menu, the document template also creates a new frame window through which to view the document.

The document-template constructor specifies what types of documents, windows, and views the template will be able to create. This is determined by the arguments you pass to the document-template constructor. The following code illustrates creation of a CMultiDocTemplate for a sample application:

AddDocTemplate( new CMultiDocTemplate( IDR_SCRIBTYPE,

          RUNTIME_CLASS( CScribDoc ),

          RUNTIME_CLASS( CMDIChildWnd ),

          RUNTIME_CLASS( CScribView ) ) );

The pointer to a new CMultiDocTemplate object is used as an argument to AddDocTemplate. Arguments to the CMultiDocTemplate constructor include the resource ID associated with the document type's menus and accelerators, and three uses of the RUNTIME_CLASS macro. RUNTIME_CLASS returns the CRuntimeClass object for the C++ class named as its argument. The three CRuntimeClass objects passed to the document-template constructor supply the information needed to create new objects of the specified classes during the document creation process. The example shows creation of a document template that creates CScribDoc objects with CScribView objects attached. The views are framed by standard MDI child frame windows.


  Document/View Creation

The framework supplies implementations of the New and Open commands (among others) on the File menu. Creation of a new document and its associated view and frame window is a cooperative effort among the application object, a document template, the newly created document, and the newly created frame window. Table 2.3 summarizes which objects create what.

Table 2.3    Object Creators

Creator	Creates
Application object	Document template
Document template	Document
Document template	Frame window
Frame window	View


  Relationships Among Documents, Views, Frame Windows, Templates, and the Application

To help put the document/view creation process in perspective, first consider a running program: a document, the frame window used to contain the view, and the view associated with the document.

•	A document keeps a list of the views of that document and a pointer to the document template that created the document.

•	A view keeps a pointer to its document and is a child of its parent frame window.

•	A document frame window keeps a pointer to its current active view.

•	A document template keeps a list of its open documents.

•	The application keeps a list of its document templates.

•	Windows keeps track of all open windows so it can send messages to them.

These relationships are established during document/view creation. Table 2.4 shows how objects in a running program can access other objects. Any object can obtain a pointer to the application object by calling the global function AfxGetApp.

Table 2.4    How to Access Other Objects

From Object	How to Access Other Objects
Document	Use GetFirstViewPosition and GetNextView to access the document's view list.  Call GetDocTemplate to get the document template.
View	Call GetDocument to get the document.  Call GetParentFrame to get the frame window.
Document frame window	Call GetActiveView to get the current view.
MDI frame window	Call MDIGetActive to get the currently active CMDIChildWnd.
Typically, a frame window has one view, but sometimes, as in splitter windows, the same frame window contains multiple views. The frame window keeps a pointer to the currently active view; the pointer is updated any time another view is activated.

Note  A pointer to the main frame window is stored in the m_pMainWnd member variable of the application object. You must set the value of this variable in your override of CWinApp's InitInstance member function.

Creating New Documents, Windows, and Views

»Figures 2.5«, »2.6«, and »2.7« give an overview of the creation process for documents, views, and frame windows. Later chapters that focus on the participating objects provide further details.

Upon completion of this process, the cooperating objects exist and store pointers to each other. »Figures 2.5«, »2.6«, and »2.7« show the sequence in which objects are created. You can follow the sequence from figure to figure.

Initializing the New Objects

For information about how the framework initializes the new document, view, and frame window objects, see classes »CDocument«, »CView«, »CFrameWnd«, »CMDIFrameWnd«, and »CMDIChildWnd« in the alphabetic reference. Also see Technical Note 22 in MSVCNT\HELP\MFCNOTES.HLP, which explains the creation and initialization processes further under its discussion of the framework's standard commands for the New and Open items on the File menu.

Initializing Your Own Additions to These Classes

»Figures 2.5«, »2.6«, and »2.7« also suggest the points at which you can override member functions to initialize your application's objects. An override of OnInitialUpdate in your view class is the best place to initialize the view. The OnInitialUpdate call occurs immediately after the frame window is created and the view within the frame window is attached to its document. For example, if your view is a scroll view (derived from CScrollView rather than CView), you should set the view size based on the document size in your OnInitialUpdate override. (This process is described in the description of class CScrollView.) You can override the CDocument member functions OnNewDocument and OnOpenDocument to provide application-specific initialization of the document. Typically, you must override both since a document can be created in two ways.

In most cases, your override should call the base class version. For more information, see the named member functions of classes »CDocument«, »CView«, »CFrameWnd«, and »CWinApp«.


  Windows of Your Own

Although the framework provides windows on your documents, you may at times want to create your own windows, particularly child windows. Keeping in mind how much the framework does for you, this section discusses windows in a more general way, with particular emphasis on creating windows of your own. For more information about the frame windows that the framework creates, see Chapter 4, »Working with Frame Windows, Documents, and Views«.


  Class CWnd

In the Microsoft Foundation Class Library, all windows are ultimately derived from class CWnd. This includes dialog boxes, controls, control bars, and views as well as frame windows and your own child windows, as shown in the Microsoft Foundation Class Library »hierarchy diagram«.


  Window Objects

A C++ window object (whether for a frame window or some other kind of window) is distinct from its corresponding Windows window (the HWND), but the two are tightly linked. A good understanding of this relationship is crucial for effective programming with the Microsoft Foundation Class Library.

The window object is an object of the C++ CWnd class (or a derived class) that your program creates directly. It comes and goes in response to your program's constructor and destructor calls. The Windows window, on the other hand, is an opaque handle to an internal Windows data structure that corresponds to a window and consumes system resources when present. A Windows window is identified by a "window handle" (HWND) and is created after the CWnd object is created by a call to the Create member function of class CWnd. The window may be destroyed either by a program call or by a user's action. The window handle is stored in the window object's m_hWnd member variable. »Figure 2.8« shows the relationship between the C++ window object and the Windows window. Creating windows is discussed in »Creating Windows«. Destroying windows is discussed in »Destroying Windows«.


  CWnd Member Functions

CWnd and its derived classes provide constructors, destructors, and member functions to initialize the object, create the underlying Windows structures, and access the encapsulated HWND. CWnd also provides member functions that encapsulate Windows APIs for sending messages, accessing the window's state, converting coordinates, updating, scrolling, accessing the Clipboard, and many other tasks. Most Windows window-management APIs that take an HWND argument are encapsulated as member functions of CWnd. The names of the functions and their parameters are preserved in the CWnd member function. For details about the Windows APIs encapsulated by CWnd, see class »CWnd« in the alphabetic reference.

The general literature on programming for Windows is a good resource for learning how to use the CWnd member functions, which typically encapsulate the HWND APIs. For example, see Charles Petzold's Programming Windows 3.1, third edition.


  Message Handling

One of the primary purposes of CWnd is to provide an interface for handling Windows messages, such as WM_PAINT or WM_MOUSEMOVE. Many of the member functions of CWnd are handlers for standard messages — those beginning with the identifier afx_msg and the prefix "On," such as OnPaint and OnMouseMove. Chapter 3, »Working with Messages and Commands«, covers messages and message handling in detail. The information there applies equally to the framework's windows and those that you create yourself for special purposes.


  Derived Window Classes

Although you can create windows directly from CWnd, or derive new window classes from CWnd, most windows used in a framework program are instead created from one of the CWnd-derived frame-window classes supplied by the Microsoft Foundation Class Library:

CFrameWnd

Used for SDI frame windows that frame a single document and its view. The frame window is both the main frame window for the application and the frame window for the current document.

CMDIFrameWnd

Used as the main frame window for MDI applications. The main frame window is a container for all MDI document windows and shares its menu bar with them. An MDI frame window is a top-level window that appears on the desktop.

CMDIChildWnd

Used for individual documents opened in an MDI main frame window. Each document and its view are framed by an MDI child frame window contained by the MDI main frame window. An MDI child window looks much like a typical frame window but is contained inside an MDI frame window instead of sitting on the desktop. However, the MDI child window lacks a menu bar of its own and must share the menu bar of the MDI frame window that contains it. »Figure 2.9« shows an MDI application whose main frame window contains two MDI document windows. Each document window contains a document and its view.

In addition to frame windows, several other major categories of windows are derived from CWnd:

Views

Views are created using the CWnd-derived class CView (or one of its derived classes). A view is attached to a document and acts as an intermediary between the document and the user. A view is a child window (not an MDI child) that typically fills the client area of an SDI frame window or an MDI child frame window.

Dialog Boxes

Dialog boxes are created using the CWnd-derived class CDialog.

Controls

Controls such as buttons, list boxes, and combo boxes are created using other classes derived from CWnd.

Control Bars

Child windows that contain controls. Examples include toolbars and status bars.

Refer again to the Microsoft Foundation Class Library hierarchy diagram. Views are explained in Chapter 4, »Working with Frame Windows, Documents, and Views«. Dialog boxes, controls, and control bars are explained in »Chapter 5«.

In addition to the window classes provided by the class library, you may need special-purpose child windows. To create such a window, write your own CWnd-derived class and make it a child window of a frame window or view.

Bear in mind that the framework manages the client area of a document frame window. Most of the client area is managed by a view, but other windows, such as control bars or your own custom windows, may share the space with the view. You may need to interact with the mechanisms in classes CView and CControlBar for positioning child windows in a frame window's client area.

The next section, »Creating Windows«, discusses creation of window objects and the Windows windows they manage.


  Creating Windows

Most of the windows you need in a framework program are created automatically by the framework. You have already seen, in this chapter, how the framework creates the frame windows associated with documents and views. This section discusses window creation at a more general level. The material presented here is especially useful if you need to create your own windows — in addition to the windows supplied by the framework — for special purposes.


Registering Window Classes
  Registering Window "Classes"

In a traditional Windows program, you process all messages to a window in its "window procedure" or "WndProc." A WndProc is associated with a window by means of a "window class registration" process. The main window is registered in the WinMain function, but other classes of windows can be registered anywhere in the application. Registration depends on a structure that contains a pointer to the WndProc function together with specifications for the cursor, background brush, and so forth. The structure is passed as a parameter, along with the string name of the class, in a prior call to the RegisterClass function. Thus a registration class can be shared by multiple windows.

In contrast, most window class registration activity is done automatically in a framework program. If you are using the Microsoft Foundation Class Library, you typically derive a C++ window class from an existing library class using the normal C++ syntax for class inheritance. The framework still uses traditional "registration classes," and it provides several standard ones, registered for you in the standard application initialization function. You can register additional registration classes by calling the AfxRegisterWndClass global function and then pass the registered class to the Create member function of CWnd. As described here, the traditional Windows "registration class" is not to be confused with a C++ class.

For more information, see Technical Note 1 in MSVCNT\HELP\MFCNOTES.HLP.


  General Creation Sequence

If you are creating a window of your own, such as a child window, this section describes what you need to know. The framework uses much the same process to create windows for your documents as that described earlier in the chapter.

All the window classes provided by the Microsoft Foundation Class Library employ two-phase construction. That is, during an invocation of the C++ new operator, the constructor allocates and initializes a C++ object but does not create a corresponding Windows window. That is done afterwards by calling the Create member function of the window object.

The Create member function makes the Windows window and stores its HWND in the C++ object's public data member m_hWnd. Create gives complete flexibility over the creation parameters. Before calling Create, you may want to register a window class with AfxRegisterWndClass in order to set the icon and class styles for the frame.

For frame windows, the LoadFrame member function can be used instead of Create. LoadFrame makes the Windows window using fewer parameters. It gets many default values from resources, including the frame's caption, icon, accelerator table, and menu.

Note  Your icon, accelerator table, and menu resources must have a common resource ID, such as IDR_MAINFRAME.


  Destroying Windows

Care must be taken with your own child windows to destroy the C++ window object when the user is finished with the window. If these objects are not destroyed, your application will not recover their memory. Fortunately, the framework manages window destruction as well as creation for frame windows, views, and dialog boxes. If you create additional windows, you are responsible for destroying them.

In the framework, when the user closes the frame window, the window's default OnClose handler calls DestroyWindow. The last member function called when the Windows window is destroyed is OnNcDestroy, which does some cleanup, calls the Default member function to perform Windows cleanup, and lastly calls the virtual member function PostNcDestroy. The CFrameWnd implementation of PostNcDestroy deletes the C++ window object.

Do not use the C++ delete operator to destroy a frame window or view. Instead, call the CWnd member function DestroyWindow. Frame windows, therefore, should be allocated on the heap with operator new. Care must be taken when allocating frame windows on the stack frame or globally. Other windows should be allocated on the stack frame whenever possible.

If you need to circumvent the object-HWND relationship, the Microsoft Foundation Class Library provides another CWnd member function, Detach, which disconnects the C++ window object from the Windows window. This prevents the destructor from destroying the Windows window when the object is destroyed.


  Working With Windows

Working with windows calls for two kinds of activity:

•	Handling Windows messages

•	Drawing in the window

To handle Windows messages in any window, including your own child windows, use ClassWizard to map the messages to your window class. Then write message-handler member functions in your class. Chapter 3, »Working with Messages and Commands«, details message handling.

Most drawing in a framework application occurs in the view, whose OnDraw member function is called whenever the window's contents must be drawn. If your window is a child of the view, you might delegate some of the view's drawing to your child window by having OnDraw call one of your window's member functions.

In any case, you will need a device context for drawing.


  Device Contexts

A device context is a Windows data structure that contains information about the drawing attributes of a device such as a display or a printer. All drawing calls are made through a device-context object, which encapsulates the Windows APIs for drawing lines, shapes, and text. Device contexts allow device-independent Windows drawing. Device contexts can be used to draw to the screen, to the printer, or to a metafile.

Special Device-Context Classes

CPaintDC objects encapsulate the common Windows idiom of calling the BeginPaint function, then drawing in the device context, then calling the EndPaint function. The CPaintDC constructor calls BeginPaint for you, and the destructor calls EndPaint. The simplified process is to create the CDC object, draw, and destroy the CDC object. In the framework, much of even this process is automated. In particular, your OnDraw function is passed a CPaintDC already prepared (via OnPrepareDC), and you simply draw into it. It is destroyed by the framework and the underlying Windows device context is released to Windows upon return from the call to your OnDraw function.

CClientDC objects encapsulate working with a device context that represents only the client area of a window. The CClientDC constructor calls the GetDC function, and the destructor calls the ReleaseDC function. CWindowDC objects encapsulate a device context that represents the whole window, including its frame.

CMetaFileDC objects encapsulate drawing into a Windows metafile. In contrast to the CPaintDC passed to OnDraw, you must in this case call OnPrepareDC yourself. For more information about these classes, see the alphabetic reference.

Drawing is discussed in greater detail in Chapter 4, »Working with Frame Windows, Documents, and Views«.

Other Device-Context Uses

Although most drawing — and thus most device-context work — in a framework program is done in the view's OnDraw member function, as described in Chapter 4, »Working with Frame Windows, Documents, and Views«, you can still use device-context objects for other purposes. For example, to provide tracking feedback for mouse movement in a view, you need to draw directly into the view without waiting for OnDraw to be called.

In such a case, you can use a CClientDC device-context object to draw directly into the view. For more information about mouse drawing, see »Interpreting User Input Through a View« in Chapter 4.


  Graphic Objects

Windows provides a variety of drawing tools to use in device contexts. It provides pens to draw lines, brushes to fill interiors, and fonts to draw text. The Microsoft Foundation Class Library provides graphic-object classes equivalent to the drawing tools in Windows. Table 2.5 shows the available classes and the equivalent Windows GDI handle types.

The general literature on programming for the Windows GDI applies to the Microsoft Foundation classes that encapsulate GDI graphic objects. This section explains the use of the graphic-object classes.

Table 2.5    Graphic Objects

Classes	Windows Handle Types
CPen	HPEN
CBrush	HBRUSH
CFont	HFONT
CBitmap	HBITMAP
CPalette	HPALETTE
CRgn	HRGN
Each of the graphic-object classes in the class library has a constructor that allows you to create graphic objects of that class, which you must then initialize with the appropriate create function, such as CreatePen.

The following four steps are typically used when you need a graphic object for a drawing operation:

1.	Define a graphic object on the stack frame. Initialize the object with the type-specific create function, such as CreatePen. Alternatively, initialize the object in the constructor. See the discussion of one-stage and two-stage creation below.

2.	Select the object into the current device context, saving the old graphic object that was selected before.

3.	When done with the current graphic object, select the old graphic object back into the device context to restore its state.

4.	Allow the frame-allocated graphic object to be deleted automatically when the scope is exited.

Note  If you will be using a graphic object repeatedly, you can allocate it once and select it into a device context each time it is needed. Be sure to delete such an object when you no longer need it.

You have a choice between two techniques for creating graphic objects:

•	One-stage construction: Construct and initialize the object in one stage, all with the constructor.

•	Two-stage construction: Construct and initialize the object in two separate stages. The constructor creates the object and an initialization function initializes it.

Two-stage construction is always safer. In one-stage construction, the constructor could throw an exception if you provide incorrect arguments or memory allocation fails. That problem is avoided by two-stage construction, although you do have to check for failure. In either case, destroying the object is the same process.

The following brief example shows both methods of constructing a pen object:

void CMyView::OnDraw( CDC* pDC )

{

    CPen myPen1( PS_DOT, 5, RGB(0,0,0) );   // One-stage

    // Two-stage: first construct the pen

    CPen myPen2;

    // Then initialize it

    if( myPen2.CreatePen( PS_DOT, 5, RGB(0,0,0) ) )

        // Use the pen

}

After you create a drawing object, you must select it into the device context in place of the default pen stored there:

void CMyView::OnDraw( CDC* pDC )

{

    CPen penBlack;  // Construct it, then initialize

    if( newPen.CreatePen( PS_SOLID, 2, RGB(0,0,0) ) )

    {

        // Select it into the device context

        // Save the old pen at the same time

        CPen* pOldPen = pDC->SelectObject( &penBlack );

        // Draw with the pen

        pDC->MoveTo(...);

        pDC->LineTo(...);

        // Restore the old pen to the device context

        pDC->SelectObject( pOldPen );

    }

    else

    {

        // Alert the user that resources are low

    }

}

The graphic object returned by SelectObject is a "temporary" object. That is, it will be deleted by the OnIdle member function of class CWinApp the next time the program gets idle time. As long as you use the object returned by SelectObject in a single function without returning control to the main message loop, you will have no problem.


  How to Use the Clipboard

Most applications for Windows support cutting or copying data to the Windows Clipboard and pasting data from the Clipboard. The Clipboard data formats vary among applications. The framework supports only a limited number of Clipboard formats for a limited number of classes. You will normally implement the Clipboard-related commands — Cut, Copy, and Paste — on the Edit menu for your view. The class library defines the command IDs for these commands: ID_EDIT_CUT, ID_EDIT_COPY, and ID_EDIT_PASTE. Their message-line prompts are also defined.

The Clipboard is a system service shared by the entire Windows session, so it does not have a handle or class of its own. You manage the Clipboard through member functions of class CWnd.

Chapter 3, »Working with Messages and Commands«, explains how to handle menu commands in your application by mapping the menu command to a handler function. As long as your application does not define handler functions for the Clipboard commands on the Edit menu, they remain disabled. To write handler functions for the Cut and Copy commands, implement selection in your application. To write a handler function for the Paste command, query the Clipboard to see whether it contains data in a format your application can accept. For example, to enable the Copy command, you might write a handler something like the following:

void CMyView::OnEditCopy()

{

   if(!OpenClipboard())

   {

      AfxMessageBox("Cannot open the Clipboard");

      return;

   }

   // ...

   // Get the currently selected data

   // ...

   // For the appropriate data formats...

   SetClipboardData(CF_??, hData);

   // ...

   CloseClipboard();

}

The Cut, Copy, and Paste commands are only meaningful in certain contexts. The Cut and Copy commands should be enabled only when something is selected, and the Paste command only when something is in the Clipboard. You can provide this behavior by defining update handler functions that enable or disable these commands depending on the context. For more information, see »How to Update User-Interface Objects« in Chapter 3.

The Microsoft Foundation Class Library does provide Clipboard support for text editing with the CEdit and CEditView classes. The Object Linking and Embedding (OLE) classes also simplify implementing Clipboard operations that involve OLE items. For more information on the OLE classes, see Chapter 18 in the Class Library User's Guide.

Implementing other Edit menu commands, such as Undo (ID_EDIT_UNDO) and Redo (ID_EDIT_REDO), is also left to you. If your application does not support these commands, you can easily delete them from your resource file using App Studio.


  In the Next Chapter

So far you have seen how the framework creates its major component objects. In »Chapter 3«, you will see how the framework dispatches Windows messages — including "commands," a new category of messages introduced by the Microsoft Foundation Class Library — to those objects and how the objects "handle" the messages and commands to do the application's work.


  CHAPTER 3  Working with Messages and Commands

Chapter 2 introduced the major objects in a running framework application written with the Microsoft Foundation Class Library. This chapter describes how messages and commands are processed by the framework and how you connect them to their handler functions using the ClassWizard tool. Topics covered include:

•	Messages and commands

•	Message categories

•	How the framework calls a message handler

•	Message maps

•	Managing messages and commands with ClassWizard

•	Dynamic update of user-interface objects

•	Dynamic display of command information in the status bar


  Messages and Commands in the Framework

Applications written for Microsoft Windows are "message driven." In response to events such as mouse clicks, keystrokes, window movements, and so on, Windows sends messages to the proper window. Framework applications process Windows messages like any other application for Windows. But the framework also provides some enhancements that make processing messages easier, more maintainable, and better encapsulated.

The following sections introduce the key terms used in the rest of the chapter to discuss messages and commands.


  Messages

The message loop in the Run member function of class CWinApp retrieves queued messages generated by various events. For example, when the user clicks the mouse, Windows sends several mouse-related messages, such as WM_LBUTTONDOWN when the left mouse button is pressed and WM_LBUTTONUP when the left mouse button is released. The framework's implementation of the application message loop dispatches the message to the appropriate window.

The important categories of messages are described in Message Categories.


  Message Handlers

In the Microsoft Foundation Class Library, a dedicated "handler" function processes each separate message. Message-handler functions are member functions of a class. This manual uses the terms "message-handler member function," "message-handler function," "message handler," and "handler" interchangeably.

Writing message handlers accounts for a large proportion of your work in writing a framework application. This chapter describes how the message-processing mechanism works.

What does the handler for a message do? The answer is that it does whatever you want done in response to that message. ClassWizard will create the handlers for you and allow you to implement them. You can jump directly from the ClassWizard dialog box to the handler function's definition in your source files and fill in the handler's code using the Visual Workbench editor. Or you can create all of your handlers with ClassWizard, then move to the editor to fill in all functions at once. You will learn more about using ClassWizard in How to Manage Commands and Messages with ClassWizard.

You can use all of the facilities of Microsoft Visual C++ and the Microsoft Foundation Class Library to write your handlers. For a list of all classes, see Chapter 1, »The Microsoft Foundation Class Library«.


  Message Categories

What kinds of messages do you write handlers for? There are three main categories:

1.	Windows messages

This includes primarily those messages beginning with the WM_ prefix, except for WM_COMMAND. Windows messages are handled by windows and views. These messages often have parameters that are used in determining how to handle the message.

2.	Control notifications

This includes WM_COMMAND notification messages from controls and other child windows to their parent windows. For example, an edit control sends its parent a WM_COMMAND message containing the EN_CHANGE control-notification code when the user has taken an action that may have altered text in the edit control. The window's handler for the message responds to the notification message in some appropriate way, such as retrieving the text in the control.

The framework routes control-notification messages like other WM_ messages. One exception, however, is the BN_CLICKED control-notification message sent by buttons when the user clicks them. This message is treated specially as a command message and routed like other commands.

3.	Command messages

This includes WM_COMMAND notification messages from user-interface objects: menus, toolbar buttons, and accelerator keys. The framework processes commands differently from other messages, and they can be handled by more kinds of objects, as explained in the next section, "»Windows Messages and Control-Notification Messages«."


  Windows Messages and Control-Notification Messages

Messages in categories 1 and 2 are handled by windows: objects of classes derived from class CWnd. This includes CFrameWnd, CMDIFrameWnd, CMDIChildWnd, CView, CDialog, and your own classes derived from these base classes. Such objects encapsulate an HWND, a handle to a Windows window.


  Command Messages

Messages in category 3 — commands — can be handled by a wider variety of objects: documents, document templates, and the application object itself in addition to windows and views. When a command directly affects some particular object, it makes sense to have that object handle the command. For example, the Open command on the File menu is logically associated with the application: the application opens a specified document upon receiving the command. So the handler for the Open command is a member function of the application class. You will learn more about commands and how they are routed to objects in »How the Framework Calls a Handler«.


  Message Maps

Each framework class that can receive messages or commands has its own "message map." The framework uses message maps to connect messages and commands to their handler functions. Any class derived from class CCmdTarget can have a message map. Later sections of this chapter explain message maps in detail and describe how to use them.

In spite of the name "message map," message maps handle both messages and commands — all three categories of messages listed in »Message Categories«.


  User-Interface Objects and Command IDs

Menu items, toolbar buttons, and accelerator keys are "user-interface objects" capable of generating commands. Each such user-interface object has an ID. You associate a user-interface object with a command by assigning the same ID to the object and the command. As you have seen, commands are implemented as special messages. »Figure 3.1« shows how the framework manages commands.


  Command IDs

A command is fully described by its command ID alone (encoded in the WM_COMMAND message). This ID is assigned to the user-interface object that generates the command. Typically, IDs are named for the functionality of the user-interface object they are assigned to.

For example, a Clear All item in the Edit menu might be assigned an ID such as ID_EDIT_CLEAR_ALL. The class library predefines some IDs, particularly for commands that the framework handles itself, such as ID_EDIT_CLEAR_ALL or ID_FILE_OPEN. You will create other command IDs yourself.

When you create your own menus in App Studio, it is a good idea to follow the class library's naming convention as illustrated by ID_FILE_OPEN. The next section, »Standard Commands«, explains the standard commands defined by the class library.


  Standard Commands

The framework defines many standard command messages. The IDs for these commands typically take the form:

ID_Source_Item

where Source is usually a menu name and Item is a menu item. For example, the command ID for the New command on the File menu is ID_FILE_NEW. Standard command IDs are shown in bold type in the documentation. Programmer-defined IDs are shown in monotype.

The following is a list of some of the most important commands supported:

File Menu Commands

New, Open, Close, Save, Save As, Page Setup, Print Setup, Print, Print Preview, Exit, and most-recently-used files.

Edit Menu Commands

Clear, Clear All, Copy, Cut, Find, Paste, Repeat, Replace, Select All, Undo, and Redo.

View Menu Commands

Toolbar and Status Bar.

Window Menu Commands

New, Arrange, Cascade, Tile Horizontal, Tile Vertical, and Split.

Help Menu Commands

Index, Using Help, and About.

Object Linking and Embedding (OLE) Commands (Edit Menu)

Insert New Object, Edit Links, Paste Link, Paste Special, and typename Object (verb commands).

The framework provides varying levels of support for these commands. Some commands are supported only as defined command IDs, while others are supported with thorough implementations. For example, the framework implements the Open command on the File menu by creating a new document object, displaying an Open dialog box, and opening and reading the file. In contrast, you must implement commands on the Edit menu yourself, since commands like ID_EDIT_COPY depend on the nature of the data you are copying.

For more information about the commands supported and the level of implementation provided, see Technical Note 22 in MSVCNT\HELP\MFCNOTES.HLP. The standard commands are defined in file AFXRES.H.


  Command Targets

»Figure 3.1« shows the connection between a user-interface object, such as a menu item, and the handler function that the framework calls to carry out the resulting command when the object is clicked.

Windows sends messages that are not command messages directly to a window whose handler for the message is then called. However, the framework routes commands to a number of candidate objects — called "command targets" — one of which normally invokes a handler for the command. The handler functions work the same way for both commands and standard Windows messages, but the mechanism by which they are called is different, as explained in the next section, »How the Framework Calls a Handler«.


  How the Framework Calls a Handler

This section first examines how the framework routes commands, then examines how other messages and control notifications are sent to windows.


  Message Sending and Receiving

Consider the sending part of the process and how the framework responds.

Most messages result from user interaction with the program. Commands are generated by mouse clicks in menu items or toolbar buttons or by accelerator keystrokes. The user also generates Windows messages by, for example, moving or resizing a window. Other Windows messages are sent when events such as program startup or termination occur, as windows get or lose the focus, and so on. Control-notification messages are generated by mouse clicks or other user interactions with a control, such as a button or list-box control in a dialog box.

The Run member function of class CWinApp retrieves messages and dispatches them to the appropriate window. Most command messages are sent to the main frame window of the application. The WindowProc predefined by the class library gets the messages and routes them differently, depending on the category of message received.

Now consider the receiving part of the process.

The initial receiver of a message must be a window object. Windows messages are usually handled directly by that window object. Command messages, usually originating in the application's main frame window, get routed to the command-target chain described in »Command Routing«.

Each object capable of receiving messages or commands has its own message map that pairs a message or command with the name of its handler.

When a command-target object receives a message or command, it searches its message map for a match. If it finds a handler for the message, it calls the handler. For more information about how message maps are searched, see »How the Framework Searches Message Maps«. Refer again to »Figure 3.1«.


  How Noncommand Messages Reach Their Handlers

Unlike commands, standard Windows messages do not get routed through a chain of command targets but are usually handled by the window to which Windows sends the message. The window might be a main frame window, an MDI child window, a standard control, a dialog box, a view, or some other kind of child window.

At run time, each Windows window is attached to a window object (derived from CWnd) that has its own associated message map and handler functions. The framework uses the message map — as for a command — to map incoming messages to handlers.


  Command Routing

Your responsibility in working with commands is limited to making message-map connections between commands and their handler functions, a task for which you use ClassWizard. You must also write most command handlers.

All messages are usually sent to the main frame window, but command messages are then routed on to other objects. The framework routes commands through a standard sequence of command-target objects, one of which is expected to have a handler for the command. Each command-target object checks its message map to see if it can handle the incoming message.

Different command-target classes check their own message maps at different times. Typically, a class routes the command to certain other objects to give them first chance at the command. If none of those objects handles the command, the original class checks its own message map. Then, if it can't supply a handler itself, it may route the command to yet more command targets. »Table 3.1«, below, shows how each of the classes structures this sequence. The general order in which a command target routes a command is:

1.	To its currently active child command-target object

2.	To itself

3.	To other command targets

How expensive is this routing mechanism? Compared to what your handler does in response to a command, the cost of the routing is low. Bear in mind that the framework generates commands only when the user interacts with a user-interface object.

Table 3.1    Standard Command Route

When an object of this type  receives a command . . .	. . . it gives itself and other command-target objects a chance to handle the command in  this order:
MDI frame window (CMDIFrameWnd)	1. Active CMDIChildWnd 2. This frame window 3. Application (CWinApp object)
Document frame window (CFrameWnd, CMDIChildWnd)	1. Active view 2. This frame window 3. Application (CWinApp object)
View	1. This view 2. Document attached to the view
Document	1. This document 2. Document template attached to the document
Dialog box	1. This dialog box 2. Window that owns the dialog box 3. Application (CWinApp object)
Where numbered entries in the second column of Table 3.1 mention other objects, such as a document, see the corresponding item in the first column. For instance, when you read in the second column that the view forwards a command to its document, see the "Document" entry in the first column to follow the routing further.


  An Example

To illustrate, consider a command message from a Clear All menu item in an MDI application's Edit menu. Suppose the handler function for this command happens to be a member function of the application's document class. Here's how that command reaches its handler after the user chooses the menu item:

1.	The main frame window receives the command message first.

2.	The main MDI frame window gives the currently active MDI child window a chance to handle the command.

3.	The standard routing of an MDI child frame window gives its view a chance at the command before checking its own message map.

4.	The view checks its own message map first, but, finding no handler, the view next routes the command to its associated document.

5.	The document checks its message map and finds a handler. This document member function is called and the routing stops.

If the document did not have a handler, it would next route the command to its document template. Then the command would return to the view and then the frame window. Finally, the frame window would check its message map. If that check failed as well, the command would be routed back to the main MDI frame window and then to the application object — the ultimate destination of unhandled commands.


  OnCmdMsg

To accomplish this routing of commands, each command target calls the OnCmdMsg member function of the next command target in the sequence. Command targets use OnCmdMsg to determine whether they can handle a command and to route it to another command target if they cannot handle it.

Each command-target class may override the OnCmdMsg member function. The overrides let each class route commands to a particular next target. A frame window, for example, always routes commands to its current child window or view, as shown in »Table 3.1«.

The default CCmdTarget implementation of OnCmdMsg uses the message map of the command-target class to search for a handler function for each command message it receives — in the same way that standard messages are searched. If it finds a match, it calls the handler. Message-map searching is explained in the section »How the Framework Searches Message Maps«.


  Overriding the Standard Routing

In rare cases when you must implement some variation of the standard framework routing, you can override it. The idea is to change the routing in one or more classes by overriding OnCmdMsg in those classes. Do so:

•	In the class that breaks the order to pass to a nondefault object.

•	In the new nondefault object or in command targets it might in turn pass commands to.

If you insert some new object into the routing, its class must be a command-target class. In your overriding versions of OnCmdMsg, be sure to call the version that you're overriding. See the »OnCmdMsg« member function of class CCmdTarget and the versions in such classes as CView and CDocument in the supplied source code for examples.


  How the Framework Searches Message Maps

The framework searches the message-map table for matches with incoming messages. Once you use ClassWizard to write a message-map entry for each message you want a class to handle and to write the corresponding handlers, the framework calls your handlers automatically.


  Where to Find Message Maps

When you create a new skeleton application with AppWizard, AppWizard writes a message map for each command-target class it creates for you. This includes your derived application, document, view, and frame-window classes. Some of these message maps already have AppWizard-supplied entries for certain messages and predefined commands, and some are just placeholders for handlers that you will add.

A class's message map is located in the .CPP file for the class. Working with the basic message maps that AppWizard creates, you use ClassWizard to add entries for the messages and commands that each class will handle. A typical message map might look like the following after you add some entries:

BEGIN_MESSAGE_MAP(CMyView, CView)

   //{{AFX_MSG_MAP(CMyView)

   ON_WM_MOUSEACTIVATE()

   ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)

   ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)

   ON_BN_CLICKED(ID_MY_BUTTON, OnMyButton)

   //}}AFX_MSG_MAP

END_MESSAGE_MAP()

The message map consists of a collection of macros. Two macros, BEGIN_MESSAGE_MAP and END_MESSAGE_MAP, bracket the message map. Other macros, such as ON_COMMAND, fill in the message map's contents. You will learn more about these macros in the sections to come.

Note  The message-map macros are not followed by semicolons.

The message map also includes comments of the form

//{{AFX_MSG_MAP(CMyView)

//}}AFX_MSG_MAP

that bracket many of the entries (not necessarily all). ClassWizard uses these special comments when it writes entries for you. All ClassWizard entries go between the comment lines.

When you use ClassWizard to create a new class, it provides a message map for the class. Alternatively, you can create a message map manually using the Visual Workbench editor.


  Derived Message Maps

During message handling, checking a class's own message map is not the end of the message-map story. What happens if class CMyView (derived from CView) has no matching entry for a message?

Keep in mind that CView, the base class of CMyView, is derived in turn from CWnd. Thus CMyView is a CView and is a CWnd. Each of those classes has its own message map. »Figure 3.2« shows the hierarchical relationship of the classes, but keep in mind that a CMyView object is a single object that has the characteristics of all three classes.

So if a message can't be matched in class CMyView's message map, the framework also searches the message map of its immediate base class. The BEGIN_MESSAGE_MAP macro at the start of the message map specifies two class names as its arguments:

BEGIN_MESSAGE_MAP(CMyView, CView)

The first argument names the class to which the message map belongs. The second argument provides a connection with the immediate base class — CView here — so the framework can search its message map too.

The message handlers provided in a base class are thus inherited by the derived class. This is very similar to normal virtual member functions without needing to make all handler member functions virtual.

If no handler is found in any of the base-class message maps, default processing of the message is performed. If the message is a command, the framework routes it to the next command target. If it is a standard Windows message, the message is passed to the appropriate default window procedure.

To speed message-map matching, the framework caches recent matches on the likelihood that it will receive the same message again. One consequence of this is that the framework processes unhandled messages quite efficiently. Message maps are also more space-efficient than implementations that use virtual functions.


  Message-Map Entries

In your source files, a message map consists of a sequence of predefined macros. The macros inside the message map are called "entry macros." The entry macros used in a message map depend upon the category of the message to be handled. The following sample shows a message map with several common entries (given in the same order as the items in »Table 3.2«):

BEGIN_MESSAGE_MAP(CMyView, CView)

   //{{AFX_MSG_MAP(CMyView)

   ON_WM_MOUSEACTIVATE()

   ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)

   ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)

   ON_BN_CLICKED(ID_MY_BUTTON, OnMyButton)

   ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)

   ON_REGISTERED_MESSAGE(WM_FIND, OnFind)

   //}}AFX_MSG_MAP

END_MESSAGE_MAP()

Table 3.2 summarizes the various kinds of entries. Each entry consists of a macro with zero or more arguments. The macros are predefined by the class library. For examples of the macros, see the message map above.

Table 3.2    Message-Map Entry Macros

Message Type	Macro Form	Arguments
Predefined Windows messages	ON_WM_XXXX	None
Commands	ON_COMMAND	Command ID, Handler name
Update commands	ON_UPDATE_COMMAND_UI	Command ID, Handler name
Control notifications	ON_XXXX	Control ID, Handler name
User-defined message	ON_MESSAGE	User-defined message ID, Handler name (see Technical Note 6 in MSVCNT\HELP\MFCNOTES.HLP)
Registered Windows message	ON_REGISTERED_MESSAGE	Registered message ID variable, Handler name (see Technical Note 6 in MSVCNT\HELP\MFCNOTES.HLP)
Names in the table with the notation _XXX represent groups of messages whose names are based on standard message names or control-notification codes in Windows. For example: ON_WM_PAINT, ON_WM_LBUTTONDOWN, ON_EN_CHANGE, ON_LB_GETSEL. Even though the ON_WM_XXX macros take no arguments, the corresponding handler functions often do take arguments, passed to them by the framework.


  Declaring Handler Functions

Certain rules and conventions govern the names of your message-handler functions. These depend on the message category.


  Standard Windows Messages

Default handlers for standard Windows messages (WM_) are predefined in class CWnd. The class library bases names for these handlers on the message name. For example, the handler for the WM_PAINT message is declared in CWnd as:

afx_msg void OnPaint();

The afx_msg keyword suggests the effect of the C++ virtual keyword by distinguishing the handlers from other CWnd member functions. Note, however, that these functions are not actually virtual; they are instead implemented through message maps. Message maps depend solely on standard preprocessor macros, not on any extensions to the C++ language. The afx_msg keyword resolves to white space after preprocessing.

To override a handler defined in a base class, simply use ClassWizard to define a function with the same prototype in your derived class and to make a message-map entry for the handler. Your handler "overrides" any handler of the same name in any of your class's base classes.

In some cases, your handler should call the overridden handler in the base class so the base class(es) and Windows can operate on the message. Where you call the base-class handler in your override depends on the circumstances. Sometimes you must call the base-class handler first and sometimes last. Sometimes you call the base-class handler conditionally, if you choose not to handle the message yourself. Sometimes you should call the base-class handler, then conditionally execute your own handler code, depending on the value or state returned by the base-class handler.

Important  It is not safe to modify the arguments passed into a handler if you intend to pass them to a base-class handler. For example, you might be tempted to modify the nChar argument of the OnChar handler (to convert to uppercase, for example). This behavior is fairly obscure, but if you need to accomplish this effect, use the CWnd member function SendMessage instead.

How do you determine the proper way to override a given message? ClassWizard helps with this decision. When ClassWizard writes the skeleton of the handler function for a given message — an OnCreate handler for WM_CREATE, for example — it sketches in the form of the recommended overridden member function. The following example recommends that the handler first call the base-class handler and proceed only on condition that it does not return −1.

int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

    if (CView::OnCreate(lpCreateStruct) == -1)

        return -1;

    // TODO: Add your specialized creation code here

    return 0;

}

By convention the names of these handlers begin with the prefix "On." Some of these handlers take no arguments, while others take several. Some also have a return type other than void. The default handlers for all WM_ messages are documented in the reference as member functions of class CWnd whose names begin with "On." The member function declarations in CWnd are prefixed with afx_msg.


  Commands and Control Notifications

There are no default handlers for commands or control-notification messages. Therefore, you are bound only by convention in naming your handlers for these categories of messages. When you map the command or control notification to a handler, ClassWizard proposes a name based on the command ID or control-notification code. You can accept the proposed name, change it, or replace it.

Convention suggests that you name handlers in both categories for the user-interface object they represent. Thus a handler for the Cut command on the Edit menu might be named

afx_msg void OnEditCut();

Because the Cut command is so commonly implemented in applications, the framework predefines the command ID for the Cut command as ID_EDIT_CUT. For a list of all predefined command IDs, see the file AFXRES.H. For more information, see »Standard Commands«.

In addition, convention suggests a handler for the BN_CLICKED notification message from a button labeled "Use As Default" might be named

afx_msg void OnClickedUseAsDefault();

You might assign this command an ID of IDC_USE_AS_DEFAULT since it is equivalent to an application-specific user-interface object.

Both categories of messages take no arguments and return no value.


  How to Manage Commands and Messages with ClassWizard

Now that you have seen how messages and commands work, it is time to see how easy it is to manage them with ClassWizard. This section briefly describes the process.

Since a framework application must handle many messages — with the handlers distributed among numerous windows and views, and even documents and other objects — the job of making and maintaining all the connections is demanding.

For that reason, Visual C++ provides ClassWizard, a tool designed specifically to connect Windows messages and user-interface objects such as menus to their handlers. »Figure 3.3« shows ClassWizard being used to map a message to a handler.

The typical development scenarios are as follows:

•	You determine that one of your classes must handle a certain Windows message, so you invoke ClassWizard and make the connection.

•	You create a menu or accelerator resource in App Studio, then invoke ClassWizard to connect the command associated with that object to a handler.

As you work with the framework, you'll find that ClassWizard greatly simplifies your message-management tasks.

ClassWizard writes the following information to your source files:

•	The appropriate message-map entry for the connection

•	A declaration of the handler as a member function of the class

•	An empty function template for you to fill in with the handler's code

You can invoke ClassWizard from App Studio while you're editing menus, accelerators, toolbars, or dialog boxes. Or you can invoke it from Visual Workbench while you're working on source code files with the editor. For detailed information about using ClassWizard to connect messages to handlers, see Chapter 7 in the Visual Workbench User's Guide and Chapter 9 in the App Studio User's Guide. For examples, see Chapters 6 and 7 in the Class Library User's Guide.

Important  Use ClassWizard to create and edit all message-map entries. If you add them manually, you may not be able to edit them with ClassWizard later. If you add them outside the bracketing comments, //{{AFX_MSG_MAP(classname) and //}}AFX_MSG_MAP, ClassWizard cannot edit them at all. Note that by the same token ClassWizard will not touch any entries you add outside the comments, so feel free to add messages outside the comments if you do not want them to be modified.


  How to Update User-Interface Objects

Typically, menu items and toolbar buttons have more than one state. For example, a menu item is grayed (dimmed) if it is unavailable in the present context. Menu items can also be checked or unchecked. A toolbar button can also be disabled if unavailable, or be checked.

Who updates the state of these items as program conditions change? Logically, if a menu item generates a command that is handled by, say, a document, it makes sense to have the document update the menu item. The document probably contains the information on which the update is based.

If a command has multiple user-interface objects (perhaps a menu item and a toolbar button), both are routed to the same handler function. This encapsulates your user-interface update code for all of the equivalent user-interface objects in a single place.

The framework provides a convenient interface for automatically updating user-interface objects. You can choose to do the updating in some other way, but the interface provided is efficient and easy to use.


  When Update Handlers are Called

Suppose the user clicks the mouse in the File menu, which generates a WM_INITMENUPOPUP message. The framework's update mechanism collectively updates all items on the File menu before the menu drops down so the user can see it.

To do this, the framework routes update commands for all menu items in the pop-up menu along the standard command routing. Command targets on the routing have an opportunity to update any menu items by matching the update command with an appropriate message-map entry (of the form ON_UPDATE_COMMAND_UI) and calling an "update handler" function. Thus, for a menu with six menu items, six update commands are sent out. If an update handler exists for the command ID of

the menu item, it is called to do the updating. If not, the framework checks for the existence of a handler for that command ID and enables or disables the menu item as appropriate.

If the framework does not find an ON_UPDATE_COMMAND_UI entry during command routing, it automatically enables the user-interface object if there is an ON_COMMAND entry somewhere with the same command ID. Otherwise, it disables the user-interface object. Therefore, to ensure that a user-interface object is enabled, supply a handler for the command the object generates or supply an update handler for it. See »Figure 3.1«.

It is possible to disable the default disabling of user-interface objects. For more information, see the »m_bAutoMenuEnable« member of class CFrameWnd.

Menu initialization is automatic in the framework, occurring when the application receives a WM_INITMENUPOPUP message. During the idle loop, the framework searches the command routing for button update handlers in much the same way as it does for menus.


  The ON_UPDATE_COMMAND_UI Macro

Use ClassWizard to connect a user-interface object to a command-update handler in a command-target object. It will automatically connect the user-interface object's ID to the ON_UPDATE_COMMAND_UI macro and create a handler in the object that will handle the update.

For example, the Scribble tutorial in the Class Library User's Guide updates a Clear All command in its Edit menu. In the tutorial, ClassWizard adds a message-map entry in the chosen class, a function declaration for a command-update handler called OnUpdateEditClearAll in the class declaration, and an empty function template in the class's implementation file. The function prototype looks like this:

afx_msg void OnUpdateEditClearAll( CCmdUI* pCmdUI );

Like all handlers, the function shows the afx_msg keyword. Like all update handlers, it takes one argument, a pointer to a CCmdUI object.


  The CCmdUI Class

When it routes the update command to the handler, the framework passes the handler a pointer to a CCmdUI object (or to an object of a CCmdUI-derived class). This object represents the menu item or toolbar button or other user-interface object that generated the command. The update handler calls member functions of

the CCmdUI structure through the pointer to update the user-interface object. For example, here is an update handler for the Clear All menu item:

void CMyClass::OnUpdateToolsMyTool( CCmdUI* pCmdUI )

{

    if( ToolAvailable() )

        pCmdUI->Enable( TRUE );

}

This handler calls the Enable member function of an object with access to the menu item. Enable makes the item available for use.


  How to Display Command Information In the Status Bar

When you run AppWizard to create the skeleton of your application, you can easily support a toolbar and a status bar. A single option in AppWizard supports both together. When a status bar is present, the framework automatically gives helpful feedback as the user of your application moves the mouse through items in the menus. The framework automatically displays a prompt string in the status bar when the menu item is being selected. For example, when the user drags the mouse over the Cut item in the Edit menu, the framework might display "Cut the selection and put it on the Clipboard" in the message area of the status bar. The prompt helps the user grasp the menu item's purpose. This also works when the user clicks on a toolbar button. »Figure 3.4« shows a status bar displaying a command prompt string.

You can easily add to this status-bar help by defining prompt strings for the menu items that you add to the program. To do so, provide the prompt strings when you edit the properties of the menu item in App Studio. The strings you define this way are stored in your application's resource file; they have the same IDs as the commands they explain.

By default, AppWizard adds the ID for a standard prompt, "Ready," which is displayed when the program is waiting for new messages. If you specify the Context-Sensitive Help option in AppWizard, the ID for a help prompt, "For Help, press F1," is added to your application. This ID is AFX_IDS_IDLEMESSAGE.


  In the Next Chapter

So far you have seen how the framework creates its major component objects and how those objects communicate through Windows messages and user-initiated commands. In »Chapter 4«, you will learn more about documents, views, frame windows, drawing, and printing.


  CHAPTER 4  Working with Frame Windows, Documents, and Views

Previous chapters introduced the primary objects in an application built upon the framework of the Microsoft Foundation Class Library and showed how these objects communicate via messages and commands.

This chapter takes you deeper into three of the most important objects in a framework application:

•	Frame windows, which contain and manage your views

•	Documents, which define your application's data

•	Views, which display your documents and manage user interaction with them

The chapter also explains how the framework manages printing and print preview since printing functionality is intimately tied to the view.

One of the most important features of the framework is the division of labor among frame windows, documents, and views. The document manages your data. The view displays it and takes user input. And the frame window puts a frame around the view. Code that defines and manipulates data resides in the document class. Code that displays the data and interprets user input resides in the view class.


  Frame Windows

When an application runs under Microsoft Windows, the user interacts with documents displayed in frame windows. A document frame window has two major components: the frame and the contents that it frames. A document frame window can be a single document interface (SDI) frame window or a multiple document interface (MDI) child window. Windows manages most of the user's interaction with the frame window: moving and resizing the window, closing it, minimizing and maximizing it. You manage the contents inside the frame.

The framework uses frame windows to contain views. The two components — frame and contents — are represented and managed by two different classes in the Microsoft Foundation Class Library. A frame window class manages the frame, and a view class manages the contents. The view window is a child of the frame window. Drawing and other user interaction with the document take place in the view's client area, not the frame window's client area. The frame window provides a visible frame around a view, complete with a caption bar and standard window controls such as a control menu, buttons to minimize and maximize the window, and controls for resizing the window. The "contents" consist of the window's client area, which is fully occupied by a child window — the view. »Figure 4.1« shows the relationship between a frame window and a view.

Later, the chapter discusses splitter windows. In a splitter window, the frame window's client area is occupied by a splitter window, which in turn has multiple child windows, called panes, which are views.

This section explains what you need to know about frame windows. Topics covered include:

•	The frame window classes created by AppWizard

•	Managing child windows

•	Managing the current view

•	Managing menus, control bars, and accelerators

•	Working with the File Manager

•	Orchestrating other window actions


  Window Classes

Each application has one "main frame window," a desktop window that usually has the application name in its caption. Each document usually has one "document frame window." A document frame window contains at least one view, which presents the document's data. For an SDI application, there is one frame window derived from class CFrameWnd. This window is both the main frame window and the document frame window. For an MDI application, the main frame window is derived from class CMDIFrameWnd, and the document frame windows, which are MDI child windows, are derived from class CMDIChildWnd.

These classes provide most of the frame window functionality you will need for your applications. Under normal circumstances, the default behavior and appearance they provide will suit your needs. If you need additional functionality, derive from these classes.


  The Frame Window Classes Created by AppWizard

When you use AppWizard to create a skeleton application, in addition to application, document, and view classes, AppWizard creates a derived frame-window class for your application's main frame window. The class is called CMainFrame by default, and the files that contain it are named MAINFRM.H and MAINFRM.CPP.

If your application is SDI, your CMainFrame class is derived from class CFrameWnd. If your application is MDI, CMainFrame is derived from class CMDIFrameWnd. If you choose to support a toolbar, the class also has member variables of type CToolBar and CStatusBar and an OnCreate message-handler function to initialize the two control bars.

If your application is MDI, AppWizard does not derive a new document frame window class for you. Instead, it uses the default implementation in CMDIChildWnd. Later on, if you find you need to customize your document frame window, you can use ClassWizard to create a new document frame window class.

These frame window classes work as created, but to enhance their functionality, you must add member variables and member functions. You may also want to have your window classes handle other Windows messages.


  Using Frame Windows

The framework creates document frame windows — and their views and documents — as part of its implementation of the New and Open commands on the File menu. Because the framework does most of the frame window work for you, you play only a small role in creating, using, and destroying those windows. You can, however, explicitly create your own frame windows and child windows for special purposes.


  Creating Document Frame Windows

As you saw earlier, in »Document/View Creation« in Chapter 2, the CDocTemplate object orchestrates creating the frame window, document, and view and connecting them all together. Three CRuntimeClass arguments to the CDocTemplate constructor specify the frame window, document, and view classes that the document template creates dynamically in response to user commands such as the New command on the File menu or the New Window command on an MDI Window menu. The document template stores this information for later use when it creates a frame window for a view and document.

In order for the RUNTIME_CLASS mechanism to work correctly, your derived frame-window classes must be declared with the DECLARE_DYNCREATE macro. This is because the framework needs to create document frame windows using the dynamic construction mechanism of class CObject. For details about DECLARE_DYNCREATE, see the »Macros and Globals« section in Part 2 and Chapter 12 in the Class Library User's Guide.

When the user chooses a command that creates a document, the framework calls upon the document template to create the document object, its view, and the frame window that will display the view. Chapter 2, »Using the Classes to Write Applications for Windows«, described this creation process. When it creates the document frame window, the document template creates an object of the appropriate class — a class derived from CFrameWnd for an SDI application or from CMDIChildWnd for an MDI application. The framework then calls the frame window object's LoadFrame member function to get creation information from resources and to create the Windows window. The framework attaches the window handle to the frame-window object. Then it creates the view as a child window of the document frame window.

Note  You cannot create your own child windows or call any Windows application programming interface (API) functions in the constructor of a CWnd-derived object. This is because the HWND for the CWnd object has not been created yet. Most Windows-specific initialization, such as adding child windows, must be done in an OnCreate message handler.


  Destroying Frame Windows

The framework manages window destruction as well as creation for those windows associated with framework documents and views. If you create additional windows, you are responsible for destroying them.

In the framework, when the user closes the frame window, the window's default OnClose handler calls DestroyWindow. The last member function called when the Windows window is destroyed is OnNcDestroy, which does some cleanup, calls the Default member function to perform Windows cleanup, and lastly calls the virtual member function PostNcDestroy. The CFrameWnd implementation of PostNcDestroy deletes the C++ window object. You should never use the C++ delete operator on a frame window. Use DestroyWindow instead.

When the main window closes, the application closes. If there are modified unsaved documents, the framework puts up a message box to ask if the documents should be saved and ensures that the appropriate documents are saved if necessary.


  What Frame Windows Do

Besides simply framing a view, frame windows are responsible for numerous tasks involved in coordinating the frame with its view and with the application. CMDIFrameWnd and CMDIChildWnd inherit from CFrameWnd, so they have CFrameWnd capabilities as well as new capabilities that they add. Examples of child windows include views, controls such as buttons and list boxes, and control bars, including toolbars, status bars, and dialog bars. The frame window is responsible for managing the layout of its child windows. In the framework, a frame window positions any control bars, views, and other child windows inside its client area. The frame window also forwards commands to its views and can respond to notification messages from control windows. Chapter 2, »Using the Classes to Write Applications for Windows«, showed how commands are routed from the frame window to its view and other command targets.

Managing Child Windows

MDI main frame windows (one per application) contain a special child window called the MDICLIENT window. The MDICLIENT window manages the client area of the main frame window, and itself has child windows: the document windows, derived from CMDIChildWnd. Because the document windows are frame windows themselves (MDI child windows), they can also have their own children. In all of these cases, the parent window manages its child windows and forwards some commands to them.

In an MDI frame window, the frame window manages the MDICLIENT window, repositioning it in conjunction with control bars. The MDICLIENT window, in turn, manages all MDI child frame windows. »Figure 4.2« shows the relationship between an MDI frame window, its MDICLIENT window, and its child document frame windows.

An MDI frame window also works in conjunction with the current MDI child window, if there is one. The MDI frame window delegates command messages to the MDI child before it tries to handle them itself.

Managing the Current View

As part of the default implementation of frame windows, a frame window keeps track of a currently active view. If the frame window contains more than one view, as for example in a splitter window, the current view is the most recent view in use. The active view is independent of the active window in Windows or the current input focus.

When the active view changes, the framework notifies the current view by calling its OnActivateView member function. You can tell whether the view is being activated or deactivated by examining OnActivateView's bActivate parameter. By default, OnActivateView sets the focus to the current view on activation. You can override OnActivateView to perform any special processing when the view is deactivated or reactivated. For example, you might want to provide special visual cues to distinguish the active view from other, inactive views. For more information, see the »OnActivateView« member function of class CView.

A frame window forwards commands to its current (active) view, as described in »Chapter 2«, as part of the standard command routing.

Managing Menus, Control Bars, and Accelerators

The frame window manages updating user-interface objects, including menus, toolbar buttons, and the status bar. It also manages sharing the menu bar in MDI applications.

The frame window participates in updating user-interface items using the ON_UPDATE_COMMAND_UI mechanism described in Chapter 3, »Working with Messages and Commands«. Buttons on toolbars and other control bars are updated during the idle loop. Menu items in drop-down menus on the menu bar are updated just before the menu drops down.

The frame window also positions the status bar within its client area and manages the status bar's indicators. The frame window clears and updates the message area in the status bar as needed and displays prompt strings as the user selects menu items or toolbar buttons, as described in »Chapter 3«.

For MDI applications, the MDI frame window manages the menu bar and caption. An MDI frame window owns one default menu that is used as the menu bar when there are no active MDI child windows. When there are active children, the MDI frame window's menu bar is taken over by the menu for the active MDI child window. If an MDI application supports multiple document types, such as chart and worksheet documents, each type puts its own menus into the menu bar and changes the main frame window's caption.

CMDIFrameWnd provides default implementations for the standard commands on the Window menu that appears for MDI applications. In particular, the New Window command (ID_WINDOW_NEW) is implemented to create a new frame window and view on the current document. You need to override these implementations only if you need advanced customization.

Multiple MDI child windows of the same document type share menu resources. If several MDI child windows are created by the same document template, they can all use the same menu resource, saving on Windows system resources.

Each frame window maintains an optional accelerator table that does keyboard accelerator translation for you automatically. This mechanism makes it easy to define accelerator keys (also called shortcut keys) that invoke menu commands.

Frame Window Styles

The frame windows that you get with the framework are suitable for most programs, but you can gain additional flexibility by using the advanced functions PreCreateWindow and AfxRegisterWindowClass. PreCreateWindow is a member function of CWnd. AfxRegisterWindowClass is a global function documented in "Macros and Globals" in the alphabetic reference.

If you apply the WS_HSCROLL and WS_VSCROLL styles to the main frame window, they are instead applied to the MDICLIENT window so users can scroll the MDICLIENT area.

If the window's FWS_ADDTOTITLE style bit is set (which it is by default), the view tells the frame window what title to display in the window's title bar based on the view's document name.

Working with the File Manager

The frame window manages a relationship with the Windows File Manager.

By adding a few initializing calls in your override of the CWinApp member function InitInstance, as described in Chapter 2, you can have your frame window indirectly open files dragged from the Windows File Manager and dropped in the frame window. See »File Manager Drag and Drop« in Chapter 2.

The frame window can also respond to dynamic data exchange (DDE) requests to open files from the File Manager (if the file extension is registered or associated with the application). See »Shell Registration« in Chapter 2.

Orchestrating Other Window Actions

The frame window orchestrates semimodal states such as context-sensitive help and print preview. The framework's role in managing context-sensitive help is described in Chapter 5, »Working with Dialog Boxes, Controls, Control Bars, and Context-Sensitive Help«. For a description of the frame window's role in print preview, see »Printing and Print Preview«.


  Documents and Views

The parts of the framework most visible both to the user and to you, the programmer, are the document and view. Most of your work in developing an application with the framework goes into writing your document and view classes. This section describes:

•	The purposes of documents and views and how they interact in the framework.

•	What you must do to implement them.

The CDocument class provides the basic functionality for programmer-defined document classes. A document represents the unit of data that the user typically opens with the File Open command and saves with the File Save command.

The CView class provides the basic functionality for programmer-defined view classes. A view is attached to a document and acts as an intermediary between the document and the user: the view renders an image of the document on the screen and interprets user input as operations upon the document. The view also renders the image for both printing and print preview.

»Figure 4.3« shows the relationship between a document and its view.

The document/view implementation in the class library separates the data itself from its display and from user operations on the data. All changes to the data are managed through the document class. The view calls this interface to access and update the data.

Documents, their associated views, and the frame windows that frame the views are created by a document template, as described in »Document/View Creation« in Chapter 2. The document template is responsible for creating and managing all documents of one document type.


  Document and View Classes Created by AppWizard

AppWizard gives you a head start on your program development by creating skeletal document and view classes for you. You can then use ClassWizard to map commands and messages to these classes and the Visual Workbench editor to write their member functions.

The document class created by AppWizard is derived from class CDocument. The view class is derived from CView. The names that AppWizard gives these classes and the files that contain them are based on the project name you supply in the AppWizard dialog box. From AppWizard, you can use the Classes dialog box to alter the default names.

Some applications might need more than one document class, view class, or frame window class. For more information, see »Multiple Document Types, Views, and Frame Windows«.


  Using Documents and Views

Working together, documents and views:

•	Contain, manage, and display your application-specific data.

•	Provide an interface for manipulating the data.

•	Participate in writing and reading files.

•	Participate in printing.

•	Handle most of your application's commands and messages.


  Managing Data

Documents contain and manage your application's data. To use the AppWizard-supplied document class, you must do the following:

•	Derive a class from CDocument for each type of document.

•	Add member variables to store each document's data.

•	Override CDocument's Serialize member function in your document class. Serialize writes and reads the document's data to and from disk.

You may also want to override other CDocument member functions. In particular, you will often need to override OnNewDocument and OnOpenDocument to initialize the document's data members and DeleteContents to destroy dynamically allocated data. For information about overridable members, see class »CDocument«.

Document Data Variables

Implement your document's data as member variables of your document class. For example, the Scribble tutorial program declares a data member of type CObList — a linked list that stores pointers to CObject objects. This list is used to store arrays of points that make up a freehand line drawing.

How you implement your document's member data depends on the nature of your application. To help you out, the Microsoft Foundation Class Library supplies a group of "collection classes" — arrays, lists, and maps (dictionaries) — along with classes that encapsulate a variety of common data types such as CString, CRect, CPoint, CSize, and CTime. For more information about these classes, see Chapter 1, »The Microsoft Foundation Class Library«.

When you define your document's member data, you will usually add member functions to the document class to set and get data items and perform other useful operations on them.

Your views access the document object by using the view's pointer to the document, installed in the view at creation time. You can retrieve this pointer in a view's member functions by calling the CView member function GetDocument. Be sure to cast this pointer to your own document type. Then you can access public document members through the pointer.

If frequent data transfer requires direct access, or you wish to use the nonpublic members of the document class, you may want to make your view class a friend of the document class.


  Serializing Data to and from Files

The basic idea of persistence is that an object should be able to write its current state, indicated by the values of its member variables, to persistent storage. Later, the object can be recreated by reading, or "deserializing," the object's state from persistent storage. A key point here is that the object itself is responsible for reading and writing its own state. Thus, for a class to be persistent, it must implement the basic serialization operations.

The framework provides a default implementation for saving documents to disk files in response to the Save and Save As commands on the File menu and for loading documents from disk files in response to the Open command. With very little work, you can implement a document's ability to write and read its data to and from a file. The main thing you must do is override CDocument's Serialize member function in your document class.

AppWizard places a skeletal override of the CDocument member function Serialize in the document class it creates for you. After you have implemented your application's member variables, you can fill in your Serialize override with code that sends the data to an "archive object" connected to a file. A CArchive object is similar to the cin and cout input/output objects from the C++ iostream library. However, CArchive writes and reads binary format, not formatted text.

The Document's Role

The framework responds automatically to the File menu's Open, Save, and Save As commands by calling the document's Serialize member function if it is implemented. An ID_FILE_OPEN command, for example, calls a handler function in the application object. During this process, the user sees and responds to the File Open dialog box and the framework obtains the filename the user chooses. The framework creates a CArchive object set up for loading data into the document and passes the archive to Serialize. The framework has already opened the file. The code in your document's Serialize member function reads the data in through the archive, reconstructing data objects as needed. For more information about serialization, see Chapter 14 in the Class Library User's Guide.

The Data's Role

In general, class-type data should be able to serialize itself. That is, when you pass an object to an archive, the object should know how to write itself to the archive and how to read itself from the archive. The Microsoft Foundation Class Library provides support for making classes serializable in this way. If you design a class to define a data type and you intend to serialize data of that type, design for serialization.

Instructions for defining a serializable class are given in Chapter 14 of the Class Library User's Guide.

Bypassing the Archive Mechanism

As you have seen, the framework provides a default way to read and write data to and from files. Serializing through an archive object suits the needs of a great many applications. Such an application reads a file entirely into memory, lets the user update the file, and then writes the updated version to disk again.

However, some applications operate on data very differently, and for these applications serialization through an archive is not suitable. Examples include database programs, programs that edit only parts of large files, and programs that share data files.

In these cases, you can override the Serialize member function of CDocument in a different way to mediate file actions through a CFile object rather than a CArchive object.

You can use the Open, Read, Write, Close, and Seek member functions of class CFile to open a file, move the file pointer (seek) to a specific point in the file, read a record (a specified number of bytes) at that point, let the user update the record, then seek to the same point again and write the record back to the file. The framework will open the file for you, and you can use the GetFile member function of class CArchive to obtain a pointer to the CFile object. For even more sophisticated and flexible use, you can override the OnOpenDocument and OnSaveDocument member functions of class CWinApp. For more information, see class »CFile« in the alphabetic reference.

In this scenario, your Serialize override does nothing, unless, for example, you want to have it read and write a file header to keep it up to date when the document closes.

For an example of such nonarchived processing, see the CHKBOOK sample program.


  Handling Commands in the Document

Your document class may also handle certain commands generated by menu items, toolbar buttons, or accelerator keys. By default, CDocument handles the File Save and Save As commands, using serialization. Other commands that affect the data may also be handled by member functions of your document. For example, in the Scribble tutorial program, class CScribDoc provides a handler for the Edit Clear All command, which deletes all of the data currently stored in the document. Unlike views, documents cannot handle standard Windows messages.


  Displaying Data in a View and Interacting with the User

The view's responsibilities are to display the document's data graphically to the user and to accept and interpret user input as operations on the document. Your tasks in writing your view class are to:

•	Write your view class's OnDraw member function, which renders the document's data.

•	Connect appropriate Windows messages and user-interface objects such as menu items to message-handler member functions in the view class.

•	Implement those handlers to interpret user input.

In addition, you may need to override other CView member functions in your derived view class. In particular, you may want to override OnInitialUpdate to perform special initialization for the view and OnUpdate to do any special processing needed just before the view redraws itself. For multipage documents, you also must override OnPreparePrinting to initialize the Print dialog box with the number of pages to print and other information. For more information on overriding CView member functions, see class »CView«.

The Microsoft Foundation Class Library also provides several derived view classes for special purposes:

•	CScrollView, which provides automatic scrolling and view scaling.

•	CFormView, which provides a scrollable view useful for displaying a form made up of dialog controls. A CFormView object is created from a dialog-template resource.

•	CEditView, which provides a view with the characteristics of an editable-text control with enhanced editing features. You can use a CEditView object to implement a simple text editor.

To take advantage of these special classes, derive your view classes from them. For more information, see »Scrolling« and »Special View Classes«.

Drawing in a View

Nearly all drawing in your application occurs in the view's OnDraw member function, which you must override in your view class. (The exception is mouse drawing, discussed in the next section, »Interpreting User Input Through a View«.) Your OnDraw override:

1.	Gets data by calling the document member functions you provide.

2.	Displays the data by calling member functions of a device-context object that the framework passes to OnDraw.

When a document's data changes in some way, the view must be redrawn to reflect the changes. Typically, this happens when the user makes a change through a view on the document. In this case, the view calls the document's UpdateAllViews member function to notify all views on the same document to update themselves. UpdateAllViews calls each view's OnUpdate member function. The default implementation of OnUpdate invalidates the view's entire client area. You can override it to invalidate only those regions of the client area that map to the modified portions of the document.

The UpdateAllViews member function of class CDocument and the OnUpdate member function of class CView let you pass information describing what parts of the document were modified. This "hint" mechanism lets you limit the area that the view must redraw. OnUpdate takes two "hint" arguments. The first, lHint, of type LPARAM, lets you pass any data you like, while the second, pHint, of type CObject*, lets you pass a pointer to any object derived from CObject.

When a view becomes invalid, Windows sends it a WM_PAINT message. The view's OnPaint handler function responds to the message by creating a device-context object of class CPaintDC and calls your view's OnDraw member function. You do not normally have to write an overriding OnPaint handler function.

Recall from »Chapter 2« that a device context is a Windows data structure that contains information about the drawing attributes of a device such as a display or a printer. All drawing calls are made through a device-context object. For drawing on the screen, OnDraw is passed a CPaintDC object. For drawing on a printer, it is passed a CDC object set up for the current printer.

Your code for drawing in the view first retrieves a pointer to the document, then makes drawing calls through the device context. The following simple OnDraw example illustrates the process:

void CMyView::OnDraw( CDC* pDC )

{

    CMyDoc* pDoc = GetDocument();

    CString s = pDoc->GetData();   // Returns a CString

    CRect rect;

    GetClientRect( &rect );

    pDC->SetTextAlign( TA_BASELINE | TA_CENTER );

    pDC->TextOut( rect.right / 2, rect.bottom / 2,

                  s, s.GetLength() );

}

In this example, you would define the GetData function as a member of your derived document class.

The example prints whatever string it gets from the document, centered in the view. If the OnDraw call is for screen drawing, the CDC object passed in pDC is a CPaintDC whose constructor has already called BeginPaint. Calls to drawing functions are made through the device-context pointer. For information about device contexts and drawing calls, see class »CDC« and »Working with Windows« in Chapter 2.

For more examples of how to write OnDraw, see MFCSAMP.HLP.

Interpreting User Input Through a View

Other member functions of the view handle and interpret all user input. You will usually define message-handler member functions in your view class to:

•	Process Windows messages generated by mouse and keyboard actions.

•	Process commands from menus, toolbar buttons, and accelerator keys.

These message-handler member functions interpret mouse clicks, drags, double-clicks, and mouse movements; keystrokes; and menu commands as data input, selection, dragging, or other editing operations, including moving data to and from the Clipboard. Which Windows messages your view handles depends on your application's needs.

You saw earlier, in »Messages and Commands in the Framework« in Chapter 3, how to assign menu items and other user-interface objects to commands and how to bind the commands to handler functions with ClassWizard. You have also seen how the framework routes such commands and sends standard Windows messages to the objects that contain handlers for them.

For example, your application might need to implement direct mouse drawing in the view. The Scribble tutorial example shows how to handle the WM_LBUTTONDOWN, WM_MOUSEMOVE, and WM_LBUTTONUP messages respectively to begin, continue, and end the drawing of a line segment. On the other hand, you might sometimes need to interpret a mouse click in your view as a selection. Your view's OnLButtonDown handler function would determine whether the user was drawing or selecting. If selecting, the handler would determine whether the click was within the bounds of some object in the view and, if so, alter the display to show the object as selected.

Your view might also handle certain menu commands, such as those from the Edit menu to cut, copy, paste, or delete selected data using the Clipboard. Such a handler would call some of the Clipboard-related member functions of class CWnd to transfer a selected data item to or from the Clipboard.


  Printing and the View

Your view also plays two important roles in printing its associated document.
The view:

•	Uses the same OnDraw code to draw on the printer as to draw on the screen.

•	Manages dividing the document into pages for printing.

For more information about printing and about the view's role in printing, see »Printing and Print Preview«.


  Scrolling and Scaling Views

The Microsoft Foundation Class Library supports views that scroll and views that are automatically scaled to the size of the frame window that displays them. Class CScrollView supports both kinds of views.

For more information about scrolling and scaling, see class »CScrollView«. For a scrolling example, see Chapter 8, "Enhancing Views," in the Class Library User's Guide.

Scrolling

Frequently the size of a document is greater than the size that its view can display. This may occur because the document's data increases or the user shrinks the window that frames the view. In such cases, the view must support scrolling.

Any view can handle scroll-bar messages in its OnHScroll and OnVScroll member functions. You can either implement scroll-bar message handling in these functions, doing all the work yourself, or you can use the CScrollView class to handle scrolling for you.

CScrollView does the following:

•	Manages window and viewport sizes and mapping modes

•	Scrolls automatically in response to scroll-bar messages

You can specify how much to scroll for a "page" (when the user clicks in a scroll-bar shaft) and a "line" (when the user clicks in a scroll arrow). Plan these values to suit the nature of your view. For example, you might want to scroll in 1-pixel increments for a graphics view but in increments based on the line height in text documents.

Scaling

When you want the view to automatically fit the size of its frame window, you can use CScrollView for scaling instead of scrolling. The logical view is stretched or shrunk to fit the window's client area exactly. A scaled view has no scroll bars.


  Multiple Document Types, Views, and Frame Windows

The standard relationship among a document, its view, and its frame window was described earlier in »Document/View Creation« in Chapter 2. Many applications support a single document type (but possibly multiple open documents of that type) with a single view on the document and only one frame window per document. But some applications may need to alter one or more of those defaults.

Multiple Document Types

AppWizard creates a single document class for you. In some cases, though, you may need to support more than one document type. For example, your application may need worksheet and chart documents. Each document type is represented by its own document class and probably by its own view class as well. When the user chooses the File New command, the framework puts up a dialog box that lists the supported document types. Then it creates a document of the type that the user chooses. Each document type is managed by its own document-template object.

To create extra document classes, use the Add Class button in the ClassWizard dialog box. Choose CDocument as the Class Type to derive from and supply the requested document information. Then implement the new class's data.

To let the framework know about your extra document class, you must add a second call to AddDocTemplate in your application class's InitInstance override. For more information, see »Document Templates« in Chapter 2.

Multiple Views

Many documents require only a single view, but it is possible to support more than one view of a single document. To help you implement multiple views, a document object keeps a list of its views, provides member functions for adding and removing views, and supplies the UpdateAllViews member function for letting multiple views know when the document's data has changed.

The Microsoft Foundation Class Library supports three common user interfaces requiring multiple views on the same document. These models are:

•	View objects of the same class, each in a separate MDI document frame window.

You might want to support creating a second frame window on a document. The user could choose a New Window command to open a second frame with a view of the same document and then use the two frames to view different portions of the document simultaneously. The framework supports the New Window command on the Window menu for MDI applications by duplicating the initial frame window and view attached to the document.

•	View objects of the same class in the same document frame window.

•	View objects of different classes in a single frame window.

In this model, a variation of the splitter window, multiple views share a single frame window. The views are constructed from different classes, each view providing a different way to view the same document. For example, one view might show a word-processing document in normal mode while the other view shows it in outline mode. A splitter control allows the user to adjust the relative sizes of the views.

»Figure 4.4« shows the three user-interface models in the order presented above.

The framework provides these models by implementing the New Window command and by providing class CSplitterWnd, as discussed in the next section, »Splitter Windows«. You can implement other models using these as your starting point. For sample programs that illustrate different configurations of views, frame windows, and splitters, see MFCSAMP.HLP.

For more information about UpdateAllViews, see class »CView« in this manual and Chapter 8 in the Class Library User's Guide.

Splitter Windows

In a splitter window, the window is, or can be, split into two or more scrollable panes. A splitter control (or "split box") in the window frame next to the scroll bars allows the user to adjust the relative sizes of the panes. Each pane is a view on the same document. In "dynamic" splitters, the views are of the same class, as shown in »Figure 4.4«(b). In "static" splitters, the views can be of different classes. Splitter windows of both kinds are supported by class CSplitterWnd.

Dynamic splitter windows, with views of the same class, allow the user to split a window into multiple panes at will and then scroll different panes to see different parts of the document. The user can also unsplit the window to remove the additional views. The splitter windows added to the Scribble application in Chapter 8 of the Class Library User's Guide are an example. That chapter describes the technique for creating dynamic splitter windows. A dynamic splitter window is shown in »Figure 4.4«(b).

Static splitter windows, with views of different classes, start with the window split into multiple panes, each with a different purpose. For example, in App Studio's bitmap editor, the image window shows two panes side by side. The left-hand pane displays a life-sized image of the bitmap. The right-hand pane displays a zoomed or magnified image of the same bitmap. The panes are separated by a "splitter bar" that the user can drag to change the relative sizes of the panes. A static splitter window is shown in »Figure 4.4«(c).

For more information, see class »CSplitterWnd« in the alphabetical reference and MFCSAMP.HLP.


  Initializing and Cleaning Up Documents and Views

Use the following guidelines for initializing and cleaning up after your documents and views:

•	The framework initializes documents and views; you initialize any data that you add to them.

•	The framework cleans up as documents and views close; you must deallocate any memory that you allocated on the heap from within the member functions of those documents and views.

Note  Recall that initialization for the whole application is best done in your override of the InitInstance member function of class CWinApp, and cleanup for the whole application is best done in your override of the CWinApp member function ExitInstance.

The life cycle of a document (and its frame window and view or views) in an MDI application is as follows:

1.	During dynamic creation, the document constructor is called.

2.	For each new document, the document's OnNewDocument or OnOpenDocument is called.

3.	The user interacts with the document throughout its lifetime.

4.	The framework calls DeleteContents to delete data specific to a document.

5.	The document's destructor is called.

In an SDI application, step 1 is performed once, when the document is first created. Then steps 2 through 4 are performed repeatedly each time a new document is opened. The new document reuses the existing document object. Finally, step 5 is performed when the application ends.

Initializing

Documents are created in two different ways, so your document class must support both ways. First, the user can create a new, empty document with the File New command. In that case, initialize the document in your override of the OnNewDocument member function of class CDocument. Second, the user can use the File Open command to create a new document whose contents are read from a file. In that case, initialize the document in your override of the OnOpenDocument member function of class CDocument. If both initializations are the same, you can call a common member function from both overrides, or OnOpenDocument can call OnNewDocument to initialize a clean document and then finish the open operation.

Views are created after their documents are created. The best time to initialize a view is after the framework has finished creating the document, frame window, and view. You can initialize your view by overriding the OnInitialUpdate member function of CView. If you need to reinitialize or adjust anything each time the document changes, you can override OnUpdate.

Cleaning Up

When a document is closing, the framework first calls its DeleteContents member function. If you allocated any memory on the heap during the course of the document's operation, DeleteContents is the best place to deallocate it.

Note  You should not deallocate document data in the document's destructor. In the case of an SDI application, the document object may be reused.

You can override a view's destructor to deallocate any memory you allocated on the heap.


  Special View Classes

Besides CScrollView, the Microsoft Foundation Class Library provides two other classes derived from CView:

•	CFormView, a view with attributes of a dialog box and a scrolling view. A CFormView is created from a dialog-template resource. You can create the dialog-template resource with App Studio.

•	CEditView, a view that uses the Windows edit control as a simple multiline text editor. You can use a CEditView as the view on a document.


  CFormView

CFormView provides a view based on a dialog-template resource. You can use it to create formlike views with edit boxes and other dialog controls. The user can scroll the form view and tab among its controls. Form views support scrolling using the CScrollView functionality. For more information, see class »CFormView« in the alphabetical reference.


  CEditView

CEditView provides the functionality of a CEdit control with enhanced editing features: printing; find and replace; cut, copy, paste, clear, and undo commands; and File Save and File Open commands. You can use a CEditView to implement a simple text-editor view. See classes »CEditView« and »CEdit« in the alphabetical reference.


  Printing and Print Preview

Microsoft Windows implements device-independent display. This means that the same drawing calls, made through a device context passed to your view's OnDraw member function, are used to draw on the screen and on other devices, such as printers. You use the device context to call graphics device interface (GDI) functions, and the device driver associated with the particular device translates the calls into calls that the device can understand.

When your framework document prints, OnDraw receives a different kind of device-context object as its argument; instead of a CPaintDC object, it gets a CDC object associated with the current printer. OnDraw makes exactly the same calls through the device context as it does for rendering your document on the screen.

The framework also provides an implementation of the File Print Preview command as described below.

Chapter 9 in the Class Library User's Guide describes the partnership between you and the framework during printing and print preview and provides an example. In particular, see Figure 9.1 in that chapter.


  Printing the Document

To print, the framework calls member functions of the view object to set up the Print dialog box, allocate fonts and other resources needed, set the printer mode for a given page, print a given page, and deallocate resources. Once the document as a whole is set up, the process iteratively prints each page. When all pages have been printed, the framework cleans up and deallocates resources. You can, and sometimes must, override some view member functions to facilitate printing. For information, see class »CView«.

When the view's OnPrint member function is called, it must calculate what part of the document image to draw for the given page number. Typically, OnPrint adjusts the viewport origin or the clipping region of the device context to specify what should be drawn. Then OnPrint calls the view's OnDraw member function to draw that portion of the image.


  Print Preview

The framework also implements print-preview functionality and makes it easy for you to use this functionality in your applications. Print preview shows a reduced image of either one or two pages of the document as it would appear when printed. The implementation also provides controls for printing the displayed page(s), moving to the next or the previous page, toggling the display between one and two pages, zooming the display in and out to view it at different sizes, and closing the display. If the framework knows how long the document is, it can also display a scroll bar for moving from page to page.

To implement print preview, instead of directly drawing an image on a device, the framework must simulate the printer using the screen. To do this, the Microsoft Foundation Class Library implements the CPreviewDC class, which is used in conjunction with the implementation class CPreviewView. All CDC objects contain two device contexts. In a CPreviewDC object, the first device context represents the printer being simulated; the second represents the screen on which output is actually displayed.

In response to a Print Preview command from the File menu, the framework creates a CPreviewDC object. Then when your application performs an operation that sets a characteristic of the printer device context, the framework performs a similar operation on the screen device context. For example, if your application selects a font for printing, the framework selects a font for screen display that simulates the printer font. When your application sends output that would go to the printer, the framework instead sends it to the screen.

The order and manner in which pages of a document are displayed are also different for print preview. Instead of printing a range of pages from start to finish, print preview displays one or two pages at a time and waits for a cue from the user before it displays different pages.

You are not required to do anything to provide print preview, other than to make sure the Print Preview command is in the File menu for your application. However, if you choose, you can modify the behavior of print preview in a number of ways. For more information about making such modifications to print preview in your application, see Technical Note 30 in MSVCNT\HELP\MFCNOTES.HLP.


  In the Next Chapter

In this and previous chapters, you have seen how the framework's application, frame window, document, and view classes work, bound together by messages and commands mapped to handler functions in the program's run-time objects. In »Chapter 5«, you will learn about dialog boxes and the controls that appear in them and about control bars, such as toolbars, status bars, and dialog bars. You will also learn how to incorporate context-sensitive Windows help in your application.


  CHAPTER 5  Working with Dialog Boxes, Controls, Control Bars, and Context-Sensitive Help

The previous chapter explained windows, particularly the frame windows used to display views of documents. As you saw briefly in that chapter, class CWnd is the base class of many other window classes besides the frame windows.

This chapter covers the following topics, including several additional categories of window classes:

•	Dialog boxes

•	Control windows

•	Control bars

•	Context-sensitive Windows Help

Dialog boxes are used to take user input. Inside a dialog box, the user interacts with controls, such as buttons, list boxes, combo boxes, and edit boxes. You can also place controls in a frame window, a view, or a control bar.

A toolbar is a control bar that contains bitmapped buttons; these buttons can be configured to appear and behave as pushbuttons, radio buttons, or check boxes. A status bar is a control bar that contains text-output panes, or "indicators." A dialog bar is a control bar based on a dialog-template resource; as in a dialog box, the user can tab among the controls.

This chapter also explains how to implement context-sensitive Windows Help in your application. The Microsoft Foundation Class Library simplifies the process. If you choose the Context-Sensitive Help option in AppWizard, AppWizard creates basic .RTF files and supplies other code needed to invoke Help.


  Dialog Boxes

Applications for Windows frequently communicate with the user through dialog boxes. Class CDialog provides an interface for managing dialog boxes, App Studio makes it easy to design dialog boxes and create their dialog-template resources, and ClassWizard simplifies the process of initializing and validating the controls in a dialog box and of gathering the values entered by the user.

This section explains:

•	Modal and modeless dialog boxes.

•	The roles of AppWizard, App Studio, and ClassWizard in creating dialog resources and dialog classes for dialog boxes.

•	Controls in dialog boxes.

•	How dialog boxes are invoked and displayed on the screen.

•	Initializing and gathering data from the controls in a dialog box: dialog data exchange (DDX).

•	Validating data entered in a dialog box: dialog data validation (DDV).

•	Dialog classes supplied by the class library.


  Dialog-Box Components in the Framework

In the framework, a dialog box has two components:

•	A dialog-template resource that specifies the dialog box's controls and their placement.

The dialog resource stores a dialog template from which Windows creates the dialog window and displays it. The template specifies the dialog box's characteristics, including its size, location, style, and the types and positions of the dialog box's controls. You will usually use a dialog template stored as a resource, but you can also create your own template in memory.

•	A dialog class, derived from CDialog, to provide a programmatic interface for managing the dialog box.

A dialog box is a window and will be attached to a Windows window when visible. When the dialog window is created, the dialog-template resource is used as a template for creating child window controls for the dialog box.


  Modal and Modeless Dialog Boxes

You can use class CDialog to manage two kinds of dialog boxes:

•	Modal dialog boxes, which require the user to respond before continuing the program

•	Modeless dialog boxes, which stay on the screen and are available for use at any time but permit other user activities

The App Studio and ClassWizard procedures for creating a dialog template are the same for modal and modeless dialog boxes.

Creating a dialog box for your program requires the following steps:

1.	Use App Studio to design the dialog box and create its dialog-template resource.

2.	Use ClassWizard to create a dialog class.

3.	Connect its controls to message handlers in the dialog class.

4.	Use ClassWizard to add data members associated with the dialog box's controls and to specify dialog data exchange and dialog data validations for the controls.


  Creating the Dialog Resource with App Studio

To design the dialog box and create the dialog resource, you use App Studio. In the App Studio dialog editor, you can:

•	Adjust the size and location your dialog will have when it appears.

•	Drag various kinds of controls from a controls palette and drop them where you want them in the dialog box.

•	Position the controls with alignment buttons on the App Studio toolbar.

•	Test your dialog box by simulating the appearance and behavior it will have in your program. In Test mode, you can manipulate the dialog box's controls by typing text in text boxes, clicking pushbuttons, and so on.

When you finish, your dialog-template resource is stored in your application's resource script file. You can edit it later if needed. For a full description of how to create and edit dialog resources in App Studio, see the App Studio User's Guide.

When the dialog box's appearance suits you, use ClassWizard to create a dialog class and map its messages, as discussed in the next section, »Creating a Dialog Class with ClassWizard«.


  Creating a Dialog Class with ClassWizard

ClassWizard helps you manage the dialog-related tasks shown in Table 5.1.

Table 5.1    Dialog-Related Tasks

Task	Apply to . . .
Create a new CDialog-derived class to manage your dialog box.	Each dialog box.
Map Windows messages to your dialog class.	Each message you want handled.
Declare class member variables to represent the controls in the dialog box.	Each control that yields a text or numeric value you want to access from your program.
Specify validation rules for the member variables.	Each control that yields a text or numeric value, if desired.
Mapping Windows messages to your dialog class is explained in »Handling Windows Messages«. Mapping dialog class member variables to dialog-box controls and specifying data exchange and validation are explained in »Dialog Data Exchange and Validation«.


  Creating Your Dialog Class

For each dialog box in your program, create a new dialog class to work with the dialog resource.

Chapter 9 in the App Studio User's Guide explains how to create a new dialog class. When you create a dialog class with ClassWizard, ClassWizard writes the following items in the .H and .CPP files you specify:

In the .H file:

•	A class declaration for the dialog class. The class is derived from CDialog.

In the .CPP file:

•	A message map for the class.

•	A standard constructor for the dialog box.

•	An override of the DoDataExchange member function. Edit this function with ClassWizard. It is used for dialog data exchange and validation capabilities as described later in this chapter.


  Life Cycle of a Dialog Box

During the life cycle of a dialog box, the user invokes the dialog box, typically inside a command handler that creates and intializes the dialog object; the user interacts with the dialog box; and the dialog box closes.

For modal dialog boxes, your handler gathers any data the user entered once the dialog box closes. Since the dialog object exists after its dialog window has closed, you can simply use the member variables of your dialog class to extract the data.

For modeless dialog boxes, you may often extract data from the dialog object while the dialog box is still visible. At some point, the dialog object is destroyed; when this happens depends on your code.


  Creating and Displaying Dialog Boxes

Creating a dialog object is a two-phase operation. First, construct the dialog object. Then create the dialog window. Modal and modeless dialog boxes differ somewhat in the process used to create and display them. Table 5.2 lists how modal and modeless dialog boxes are normally constructed and displayed.

Table 5.2    Dialog Creation

Dialog Type	How to Create It
Modeless	Construct CDialog, then call Create member function.
Modal	Construct CDialog, then call DoModal member function.
Creating Modal Dialog Boxes

To create a modal dialog box, you call either of the two public constructors declared in CDialog and then call the dialog object's DoModal member function to display the dialog box and manage interaction with it until the user chooses OK or Cancel. This management by DoModal is what makes the dialog box "modal." For modal dialog boxes, DoModal loads the dialog resource.

Creating Modeless Dialog Boxes

For a modeless dialog box, you must provide your own public constructor in your dialog class. To create a modeless dialog box, call your public constructor and then call the dialog object's Create member function to load the dialog resource. You can call Create either during or after the constructor call. If the dialog resource has the property WS_VISIBLE, the dialog box appears immediately. If not, you must call its ShowWindow member function.

Using a Dialog Template in Memory

Instead of using the methods given in »Table 5.2«, you can create either kind of dialog box indirectly from a dialog template in memory. For more information, see class »CDialog« in the alphabetic reference.

Setting the Dialog Box's Background Color

You can set the background color of your dialog boxes by calling the CWinApp member function SetDialogBkColor in your InitInstance override. The color you set is used for all dialog boxes and message boxes.

Initializing the Dialog Box

After the dialog box and all of its controls are created but just before the dialog box (of either type) appears on the screen, the dialog object's OnInitDialog member function is called. For a modal dialog box, this occurs during the DoModal call. You typically override this function to initialize the dialog box's controls, such as setting the initial text of an edit box. You must call the OnInitDialog member function of the base class, CDialog, from your OnInitDialog override.

Handling Windows Messages

Dialog boxes are Windows, so they can handle Windows messages if you supply the appropriate handler functions.


  Exchanging Data Between Dialog Box and Dialog Object

The framework provides an easy way to initialize the values of controls in a dialog box and to retrieve values from the controls. The more laborious manual approach is to call functions such as the SetDlgItemText and GetDlgItemText member functions of class CWnd, which apply to control windows. With these functions, you access each control individually to set or get its value, calling functions such as SetWindowText and GetWindowText. The framework's approach automates both initialization and retrieval.

Dialog data exchange (DDX) lets you automatically exchange data between the dialog box and member variables in the dialog object. This exchange works both ways. To initialize the controls in the dialog box, you can set the values of data members in the dialog object, and the values will be transferred automatically to the controls before the dialog box is displayed. Then you can at any time update the dialog data members with data entered by the user. At that point, you can use the data by referring to the data member variables.

You can also arrange for the values of dialog controls to be validated automatically with dialog data validation (DDV).

Use ClassWizard to add DDX and DDV capabilities to a dialog class. DDX and DDV are explained in more detail in »Dialog Data Exchange and Validation«.


  Retrieving Data from the Dialog Object

DDX exchanges data between the dialog box and a dialog object. Once the dialog object's data members have been updated from the dialog box's controls, other objects in your program, such as a view, can access the data through those data members.

For a modal dialog box, you can retrieve any data the user entered when DoModal returns IDOK but before the dialog object is destroyed. For a modeless dialog box, you can retrieve data from the dialog object at any time by calling UpdateData with the argument TRUE and then accessing dialog class member variables. This subject is discussed in more detail in »Dialog Data Exchange and Validation«.


  Closing the Dialog Box

A modal dialog box closes when the user chooses one of its buttons, typically the OK button or the Cancel button. Choosing the OK or Cancel button causes Windows to send the dialog object a BN_CLICKED control-notification message with the button's ID, either IDOK or IDCANCEL. CDialog provides default handler functions for these messages: OnOK and OnCancel. The default handlers call the EndDialog member function to close the dialog window. You can also call EndDialog from your own code. For more information, see the »EndDialog« member function of class CDialog.

To arrange for closing and deleting a modeless dialog box, override PostNcDestroy and invoke the delete operator on the this pointer. The next section, »Destroying the Dialog Box«, explains what happens next.


  Destroying the Dialog Box

Modal dialog boxes are normally created on the stack frame and destroyed when the function that created them ends. The dialog object's destructor is called when the object goes out of scope.

Modeless dialog boxes are normally created and "owned" by a parent view or frame window — the application's main frame window or a document frame window. The default OnClose handler calls DestroyWindow, which destroys the dialog-box window. The PostNcDestroy handler destroys the C++ dialog object. You should also override OnCancel and call DestroyWindow from within it.


  Dialog Data Exchange and Validation

Dialog data exchange (DDX) is an easy way to initialize the controls in your dialog box and to gather data input by the user. Dialog data validation (DDV) is an easy way to validate data entry in a dialog box. To take advantage of DDX and DDV in your dialog boxes, use ClassWizard to create the data members and set their data types and specify validation rules. For additional information about DDX/DDV and for examples, see Chapter 9 in the App Studio User's Guide and Chapter 7 in the Class Library User's Guide.


  Data Exchange

If you use the DDX mechanism, you set the initial values of the dialog object's member variables, typically in your OnInitDialog handler or the dialog constructor. The framework's DDX mechanism then transfers the values of the member variables to the controls in the dialog box, where they appear when the dialog box itself appears. The default implementation of OnInitDialog in CDialog calls the UpdateData member function of class CWnd to initialize the controls in the dialog box.

The same mechanism transfers values from the controls to the member variables when the user clicks the OK button (or whenever you call the UpdateData member function with the argument TRUE). The dialog data validation mechanism validates any data items for which you specified validation rules.

»Figure 5.1« illustrates dialog data exchange.

UpdateData works in both directions, as specified by the BOOL parameter passed to it. To carry out the exchange, UpdateData sets up a CDataExchange object and calls your dialog class's override of CDialog's DoDataExchange member function. DoDataExchange takes an argument of type CDataExchange. The CDataExchange object passed to UpdateData represents the context of the exchange, defining such information as the direction of the exchange.

When you (or ClassWizard) override DoDataExchange, you specify a call to one DDX function per data member (control). Each DDX function knows how to exchange data in both directions based on the context supplied by the CDataExchange argument passed to your DoDataExchange by UpdateData.

The Microsoft Foundation Class Library provides many DDX functions for different kinds of exchange. The following example shows a DoDataExchange override in which two DDX functions and one DDV function are called:

void CMyDialog::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);    // Call base class version

    //{{AFX_DATA_MAP(CMyDialog)

    DDX_Check(pDX, IDC_MY_CHECKBOX, m_bVar);

    DDX_Text(pDX, IDC_MY_TEXTBOX, m_strName);

    DDV_MaxChars(pDX, IDC_MY_TEXTBOX, m_strName, 20);

    //}}AFX_DATA_MAP

}

The DDX_ and DDV_ lines between the //{{AFX_DATA_MAP and //}}AFX_DATA_MAP delimiters are a "data map." The sample DDX and DDV functions shown are for a check-box control and an edit-box control, respectively.

If the user cancels a modal dialog box, the OnCancel member function terminates the dialog box and DoModal returns the value IDCANCEL. In that case, no data is exchanged between the dialog box and the dialog object.


  Data Validation

You can specify validation in addition to data exchange by calling DDV functions, as shown in the example above. The DDV_MaxChars call in the example above validates that the string entered in the text-box control is not longer than 20 characters. The DDV function typically alerts the user with a message box if the validation fails and puts the focus on the offending control so the user can reenter the data. A DDV function for a given control must be called immediately after the DDX function for the same control.

You can also define your own custom DDX and DDV routines. For details on this and other aspects of DDX and DDV, see Technical Note 26 in MSVCNT\HELP\MFCNOTES.HLP.

ClassWizard will write all of the DDX and DDV calls in the data map for you. Do not manually edit the lines in the data map between the delimiting comments.


  Type-Safe Access to Controls in a Dialog Box

The controls in a dialog box can use the interfaces of the Microsoft Foundation Class Library control classes such as CListBox and CEdit. You can create a control object and attach it to a dialog control. Then you can access the control through its class interface, calling member functions to operate on the control, as shown below. The methods described here are designed to give you type-safe access to a control. This is especially useful for controls such as edit boxes and list boxes.

The connection between a control in a dialog box and a C++ control member variable in a CDialog-derived class can be done in two different ways.


  Without ClassWizard

The first approach uses an inline member function to cast the return type of class CWnd's GetDlgItem member function to the appropriate C++ control type, as in this example:

// Declared inline in class CMyDialog

CButton* GetMyCheckbox()

{

    return (CButton*)GetDlgItem(ID_MYCHECKBOX);

}

You can then use this member function to access the control in a type-safe manner with code similar to the following:

GetMyCheckbox()->SetState(TRUE);


  With ClassWizard

However, there is a much easier way to accomplish the same effect if you are familiar with the DDX features, using the Control property in ClassWizard.

If you simply want access to a control's value, DDX provides it. If you want to do more than access a control's value, use ClassWizard to add a member variable of the appropriate class to your dialog class. Attach this member variable to the Control property.

Member variables can have a Control property instead of a Value property. The Value property refers to the type of data returned from the control, such as CString or int. The Control property enables direct access to the control through a data member whose type is one of the control classes in the Microsoft Foundation Class Library, such as CButton or CEdit.

You can use this object to call any member functions for the control object. Such calls affect the control in the dialog box. For example, for a check-box control represented by a variable m_checkboxDefault, of type CButton, you could call:

m_checkboxDefault.SetState(TRUE);

Here the member variable m_checkboxDefault serves the same purpose as the member function GetMyCheckbox shown above. If the check box is not an auto check box, you would still need a handler in your dialog class for the BN_CLICKED control-notification message when the button is clicked.

For more information about controls, see »Controls«.


  Mapping Windows Messages to Your Class

If you need your dialog box to handle Windows messages, override the appropriate handler functions. To do so, use ClassWizard to map the messages to the dialog class. This writes a message-map entry for each message and adds the message-handler member functions to the class. Use the Visual Workbench editor to write code in the message handlers. Chapter 3, »Working with Messages and Commands«, describes message maps and message-handler functions in detail.


  Commonly Overridden Member Functions

The most likely member functions to override in your CDialog-derived class are listed in Table 5.3.

Table 5.3    Commonly Overridden Member Functions of Class CDialog

Member Function	Message It Responds To	Purpose of the Override
OnInitDialog	WM_INITDIALOG	Initialize the dialog box's controls
OnOK	BN_CLICKED for button IDOK	Respond when the user clicks the OK button
OnCancel	BN_CLICKED for button IDCANCEL	Respond when the user clicks the Cancel button
OnInitDialog, OnOK, and OnCancel are virtual functions. To override them, you declare an overriding function in your derived dialog class using ClassWizard; in these cases, ClassWizard will not add any message-map entries because they are not necessary.

OnInitDialog is called just before the dialog box is displayed. You must call the default OnInitDialog handler from your override — usually as the first action in the handler. By default, OnInitDialog returns TRUE to indicate that the focus should be set to the first control in the dialog box.

OnOK is typically overridden for modeless but not modal dialog boxes. If you override this handler for a modal dialog box, call the base class version from your override — to ensure that EndDialog is called — or call EndDialog yourself.

OnCancel is usually overridden for modeless dialog boxes.

For more information about these member functions, see class »CDialog« and the discussion on »Life Cycle of a Dialog Box«.


  Commonly Added Member Functions

If your dialog box contains pushbuttons other than OK or Cancel, you need to write message-handler member functions in your dialog class to respond to the control-notification messages they generate. For an example, see Chapter 7, "Adding A Dialog Box," in the Class Library User's Guide. You can also handle control-notification messages from other controls in your dialog box.


  Common Dialog Classes

In addition to class CDialog, the Microsoft Foundation Class Library supplies several classes derived from CDialog that encapsulate commonly used dialog boxes, as shown in Table 5.4. The dialog boxes encapsulated are called the "common dialog boxes" and are part of the Windows common dialog library. The dialog-template resources and code for these classes is provided in the Windows common dialog boxes that are part of Windows versions 3.1 and later.

Table 5.4    Common Dialog Classes

Derived Dialog Class	Purpose
CColorDialog	Lets user select colors
CFileDialog	Lets user select a filename to open or to save
CFindReplaceDialog	Lets user initiate a find or replace operation in a text file
CFontDialog	Lets user specify a font
CPrintDialog	Lets user specify information for a print job
For more information about the common dialog classes, see the individual class names in the alphabetic reference.

Two other classes in the Microsoft Foundation Class Library have dialog-like characteristics. For information about class CFormView, see »CFormView« in Chapter 4. For information about class CDialogBar, see »Control Bars«.


  Controls

The Microsoft Foundation Class Library supplies a set of classes that correspond to the standard control windows provided by Microsoft Windows. These include buttons of several kinds, static- and editable-text controls, scroll bars, list boxes, and combo boxes. Table 5.5 lists the classes and the corresponding standard controls. The next section, »New Controls«, describes new kinds of controls.

Table 5.5    Standard Control Window Classes

Class	Windows Control
CStatic	Static-text control
CButton	Button control: pushbutton, check box, radio button, or group-box control
CListBox	List-box control
CComboBox	Combo-box control
CEdit	Edit control
CScrollBar	Scroll-bar control
Each control class encapsulates a Windows control and provides a member function user interface to the underlying control. Using a control object's member functions, you can get and set the value or state of the control and respond to various standard messages sent by the control to its parent window (usually a dialog box). For additional control classes, see »New Controls«, which follows.

You can create control objects in a window or dialog box. You can also use a control class as an interface to a control created in a dialog box from a dialog-template resource.


  New Controls

In addition to the standard Windows controls discussed above, the Microsoft Foundation Class Library provides several new control classes. These provide buttons labeled with bitmaps instead of text, control bars, and splitter-window controls. Splitter windows were discussed in »Chapter 4«.

Table 5.6 shows the new classes and their purposes.

Table 5.6    New Control Classes

Class	Purpose
CBitmapButton	Button labeled with a bitmap instead of text
CToolBar	Toolbar arranged along a border of a frame window and containing other controls
CStatusBar	Status bar arranged along a border of a frame window and containing panes, or indicators
CDialogBar	Control bar created from a dialog-template resource and arranged along a border of a frame window
Control bars, including toolbars, status bars, and dialog bars, are discussed in »Control Bars«.


  Bitmap Buttons

Class CBitmapButton allows you to have button controls labeled with bitmaps instead of text. An object of this class stores four CBitmap objects that represent various states of the button: up (active), down (pushed), focused, and disabled. Bitmap buttons can be used in dialog boxes. For more information, see class »CBitmapButton«. »Figure 5.2« shows bitmap buttons in a dialog box.


  Controls and Dialog Boxes

Normally the controls in a dialog box are created from the dialog template at the time the dialog box is created. Use ClassWizard to manage the controls in your dialog box. For details, see »Dialog Data Exchange and Validation«, »Type-Safe Access to Controls in a Dialog Box«, and »Mapping Windows Messages to Your Class«.


  Making and Using Controls

You make most controls for dialog boxes in the App Studio dialog editor. But you can also create controls in any dialog box or window.


  Using App Studio

When you create your dialog-template resource with App Studio, you drag controls from a controls palette and drop them into the dialog box. This adds the specifications for that control type to the dialog-template resource. When you construct a dialog object and call its Create or DoModal member function, the framework creates a Windows control and places it in the dialog window on screen.


  Doing It By Hand

To create a control object yourself, you will usually embed the C++ control object in a C++ dialog or frame window object. Like many other objects in the framework, controls require two-stage construction. You should call the control's Create member function as part of the parent dialog box or frame window creation. For dialog boxes, this is usually done in OnInitDialog, and for frame windows, in OnCreate.

The following example shows how you might declare a CEdit object in the class declaration of a derived dialog class and then call the Create member function in OnInitDialog. Because the CEdit object is declared as an embedded object, it is automatically constructed when the dialog object is constructed, but it must still be initialized with its own Create member function.

class CMyDialog : public CDialog

{

protected:

    CEdit m_edit;   // Embedded edit object

public:

    virtual BOOL OnInitDialog();

};

The following OnInitDialog function sets up a rectangle, then calls Create to create the Windows edit control and attach it to the uninitialized CEdit object.

BOOL CMyDialog::OnInitDialog()

{

    CDialog::OnInitDialog();

    CRect rect(85, 110, 180, 210);

    m_edit.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP |

             ES_AUTOSCROLL | WS_BORDER, rect, this, ID_EXTRA_EDIT);

    m_edit.SetFocus();

    return FALSE;

}

After creating the edit object, you can also set the input focus to the control by calling the SetFocus member function. Finally, you return 0 from OnInitDialog to show that you set the focus. If you return nonzero, the dialog manager sets the focus to the first control item in the dialog item list.


  Deriving Controls from a Standard Control

As with any CWnd-derived class, you can modify a control's behavior by deriving a new class from an existing control class.

To create a derived control class, follow these steps:

1.	Derive your class from an existing control class and optionally override the Create member function so that it provides the necessary arguments to the base-class Create function.

2.	Use ClassWizard to provide message-handler member functions and message-map entries to modify the control's behavior in response to specific Windows messages.

3.	Provide new member functions to extend the functionality of the control (optional).

Using a derived control in a dialog box requires extra work. The types and positions of controls in a dialog box are normally specified in a dialog-template resource. If you create a derived control class, you cannot specify it in a dialog template since the resource compiler knows nothing about your derived class. To place your derived control in a dialog box, follow these steps:

1.	Embed an object of the derived control class in the declaration of your derived dialog class.

2.	Override the OnInitDialog member function in your dialog class to call the SubclassDlgItem member function for the derived control.

SubclassDlgItem "dynamically subclasses" a control created from a dialog template. When a control is dynamically subclassed, you hook into Windows, process some messages within your own application, then pass the remaining messages on to Windows. For more information, see the »SubclassDlgItem« member function of class CWnd. The following example shows how you might write an override of OnInitDialog to call SubclassDlgItem:

BOOL CMyDialog::OnInitDialog()

{

    CDialog::OnInitDialog();

    m_wndMyBtn.SubclassDlgItem(IDC_MYBTN, this);

    return TRUE;

}

Because the derived control is embedded in the dialog class, it will be constructed when the dialog box is constructed, and it will be destroyed when the dialog box is destroyed. Compare this code to the previous example in »Doing It By Hand«.


  Control Bars

Control bars greatly enhance a program's usability by providing quick, one-step command actions. Control bars include toolbars, status bars, and dialog bars. The base class of all control bars is CControlBar.

•	A toolbar is a control bar that displays a row of bitmapped buttons that activate commands similarly to menu items. The buttons can act like pushbuttons, check boxes, or radio buttons. Toolbars are usually aligned to the top of a frame window.

•	A status bar is a control bar with a row of text output panes, or "indicators." The output panes are commonly used as message lines and as status indicators. Examples include the command help-message lines that briefly explain the selected menu or toolbar command and the indicators that indicate the status of the Scroll Lock, Num Lock, and other keys. Status bars are usually aligned to the bottom of a frame window.

•	A dialog bar is a control bar with the functionality of a modeless dialog box. Dialog bars are created from dialog templates and can contain any Windows control. Dialog bars support tabbing among controls and can be aligned to the top, bottom, left, or right sides of a frame window.

This section explains how control bars of all three types work. The base class, CControlBar, provides the functionality for positioning the control bar in its parent frame window. Because a control bar is usually a child window of a parent frame window, it is a "sibling" to the client view or MDI client of the frame

window. A control-bar object uses information about its parent window's client rectangle to position itself. Then it alters the parent's remaining client-window rectangle so that the client view or MDI client window will fill the rest of the client window.


  Toolbars

The buttons in a toolbar are analogous to the items in a menu. Both kinds of user-interface objects generate commands, which your program handles by providing handler functions. Often toolbar buttons duplicate the functionality of menu commands, providing an alternative user interface to the same functionality. Such duplication is arranged by giving the button and the menu item the same ID.

Once constructed, a CToolBar object creates the toolbar image by loading a single bitmap that contains one image for each button. AppWizard creates a standard toolbar bitmap, in file TOOLBAR.BMP, that you can customize with App Studio. »Figure 5.3« shows that bitmap as it appears in the App Studio bitmap editor.

»Figure 5.4« shows a toolbar as it appears in a running application, including separators between groups of buttons.

The buttons in a toolbar are only bitmaps, but the toolbar object processes mouse clicks in the toolbar and generates the appropriate command based on the clicked button's position in the toolbar.

Buttons are correlated with the commands they generate by an array of command IDs, in which the position of an ID in the array is the same as the position of a button image in the toolbar bitmap. If you choose the Initial Toolbar option in AppWizard, AppWizard adds a "buttons" array to the source file for your main frame window class. The array also contains ID_SEPARATOR elements used to space the buttons into groups. The separators are ignored in determining button positions. For an example of using App Studio and the array to modify the default toolbar provided by AppWizard, see Chapter 5 in the Class Library User's Guide.

You can make the buttons in a toolbar appear and behave as pushbuttons, check boxes, or radio buttons.

For more information, see class »CToolBar« in the alphabetic reference.


  Status Bars

As with toolbars, a CStatusBar object is based on an array of IDs for its indicator panes. If you select the Initial Toolbar option in AppWizard, AppWizard creates the array for a status bar as well as the array for a toolbar in the source file for your main frame window class. The array looks like this:

static UINT BASED_CODE indicators[] =

{

    ID_SEPARATOR,        // message line indicator

    ID_INDICATOR_CAPS,

    ID_INDICATOR_NUM,

    ID_INDICATOR_SCRL,

};

These indicators are arranged horizontally along the status bar from left to right. You can add more indicators by adding more IDs to the array. You can size these indicators as needed. You can also add separators by adding ID_SEPARATOR elements. The leftmost indicator, at position 0, takes up all space remaining after the other panes are placed. This indicator is most often used as a message area in which to display text strings such as command prompts. »Figure 5.5« shows a status bar that displays several indicators.

Like the toolbar, the status-bar object is embedded in its parent frame window and is constructed automatically when the frame window is constructed. During creation, a call to the SetIndicators member function of class CStatusBar associates an ID from the array with each indicator. The status bar, like all control bars, is destroyed automatically as well.

For an example of using a status bar, see the Scribble tutorial program in the Class Library User's Guide. For more information, see class »CStatusBar«.


  Dialog Bars

Because it has the characteristics of a modeless dialog box, a CDialogBar provides a more powerful toolbar. There are several key differences between a toolbar and a CDialogBar. A CDialogBar is created from a dialog-template resource, which you can create with App Studio and which can contain any kind of Windows control. The user can tab from control to control. And you can specify an alignment style to align the dialog bar with any part of the parent frame window or even to leave it in place if the parent is resized. »Figure 5.6« shows a dialog bar with a variety of controls.

In other respects, working with a CDialogBar is like working with a modeless dialog box. Use App Studio to design and create the dialog resource.

One of the virtues of dialog bars is that they can include controls other than buttons.

While it is normal to derive your own dialog classes from CDialog, you do not typically derive your own class for a dialog bar. Dialog bars are extensions to a main window and any dialog-bar control-notification messages, such as BN_CLICKED or EN_CHANGE, will be sent to the parent of the dialog bar — the main window.

For more information about dialog bars, see class »CDialogBar«.


  Context-Sensitive Help

Applications written for Windows usually provide context-sensitive Help, allowing the user to get Help on a particular window, dialog box, command, or toolbar button. The Microsoft Foundation Class Library makes it simple to add context-sensitive Help to your application.

The user can access Help in three ways:

•	Getting Help from the Help menu.

•	Getting Help on the task at hand by pressing the F1 key. This kind of help is called "F1 Help."

•	Getting Help by invoking a "help mode" with SHIFT+F1 and then selecting a user-interface object to get help about. This kind of help is called "SHIFT+F1 Help."

This section explains how the framework manages the three kinds of Help support. It also explains the tools you use to add Help support. For a detailed example, see Chapter 10 in the Class Library User's Guide. For additional technical information, see Technical Note 28 in MSVCNT\HELP\MFCNOTES.HLP.


  Components of Help

The Help subsystem in the framework has the following components, many of which are supplied by AppWizard when you choose its Context-Sensitive Help option:

•	A Help drop-down menu with several commands. For a new MDI application, there are two copies of this drop-down menu: one for an application with no open documents and one for each type of document that uses its own menu structure. AppWizard supplies these menus.

•	Several message-map entries in your CWinApp-derived application class. AppWizard supplies these entries.

•	Message handlers corresponding to the message-map entries. Class CWinApp supplies these handlers and AppWizard supplies the message-map entries for them.

•	The CWinApp::WinHelp member function, which calls WINHELP.EXE, the Windows Help program.

•	Additional AppWizard support for Help, including several Help-related files. The files include skeleton .RTF files that contain Help entries for the common elements of the Windows user interface such as the File and Edit menus. You can edit these files to revise the supplied text and add your own application-specific Help information.

•	A mechanism and tool for mapping resource and command IDs in your application to "help contexts" in Windows Help. The MAKEHM tool is described later.


  Help-Menu Support

The framework implements two Help menu commands:

•	Help Index launches Windows Help with the Help index. The user can browse Help topics or search for a specific topic. The command ID for Help Index is ID_HELP_INDEX.

•	Using Help launches Windows Help with general information about using Windows Help. The command ID is ID_HELP_USING.

Each of these menu items is implemented with commands. The following partial message map for a main frame window class contains mappings for the Help commands:

BEGIN_MESSAGE_MAP(CMyApp, CWinApp)

   //{{AFX_MSG_MAP(CMyApp)

   // ...

   //}}AFX_MSG_MAP

   // Standard file based document commands

   // ...

   // Global help commands

   ON_COMMAND(ID_HELP_INDEX, CWinApp::OnHelpIndex)

   ON_COMMAND(ID_HELP_USING, CWinApp::OnHelpUsing)

   ON_COMMAND(ID_HELP, CWinApp::OnHelp)

   ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp)

   ON_COMMAND(ID_DEFAULT_HELP, CWinApp::OnHelpIndex)

END_MESSAGE_MAP()

The first two entries under the // Global help commands comment specify handlers for the two menu commands. The remaining three entries are for F1 Help, Shift+F1 Help, and default Help, respectively. All you have to do to enable these menu items is choose the Context-Sensitive Help option in AppWizard. AppWizard writes the message-map entries.

When the user chooses a Help menu command (or uses one of the context-sensitive Help techniques described in the next two sections, »F1 Help Support« and »SHIFT+F1 Help Support«), the framework calls CWinApp's WinHelp member function, which in turn starts the program WINHELP.EXE, passing context information to it.


  F1 Help Support

The framework implements F1 Help for windows, dialog boxes, message boxes, menus, and toolbar buttons. If the cursor is over a window, dialog box, or message box when the user presses the F1 key, the framework opens Windows Help for that window. If a menu item is highlighted, the framework opens Windows Help for that menu item. And if a toolbar button has been pressed (but the mouse not released yet), the framework opens Windows Help for that toolbar button.

When the user presses the F1 key, the framework processes the keystroke as a Help request, as follows, using a variation on the normal command routing. Pressing F1 causes a WM_COMMAND message to be sent for the ID_HELP command. If the application supports Help, this command is mapped to the OnHelp message handler of class CWinApp and is routed directly there. OnHelp uses the ID of the current frame window or dialog box to determine the appropriate Help topic

to display to the user. If no specific Help topic is found, OnHelp displays default Help, which is usually mapped to CWinApp member function OnHelpIndex in the application object's message map — the same handler as for the Help Index menu command.


  SHIFT+F1 Help Support

If the user presses SHIFT+F1 at any time the application is active, the framework puts the application into Help mode and changes the cursor to a Help cursor. The next thing the user clicks determines what Help context the framework opens in Windows Help.

If the user presses SHIFT+F1, the framework routes the command ID_CONTEXT_HELP through the normal command routing. The command is mapped to the CWinApp member function OnContextHelp, which captures the mouse, changes the cursor to a Help cursor (arrow + question mark), and puts the application into Help mode. The Help cursor is maintained as long as the application is in Help mode but reverts to a normal arrow cursor if it is not over the application that is in Help mode. Activating a different application cancels Help mode in the original application. While in Help mode, the application determines what object the user clicks on and calls the CWinApp member function WinHelp with the appropriate context, determined from the object clicked upon. Once an object has been selected, Help mode ends and the cursor is restored to the normal arrow.

For more information, see Technical Note 28 in MSVCNT\HELP\MFCNOTES.HLP.


  More Precise Context-Sensitivity

The standard Help implementation in the framework can obtain a Help context from a window, dialog box, message box, menu item, or toolbar button. If you need more precise control over this mechanism, you can override parts of the mechanism.

For additional information, see Technical Note 28 in MSVCNT\HELP\MFCNOTES.HLP.


  Help Support Tools

You will use three main tools to develop your application's Help system: AppWizard, MAKEHM, and the Windows Help Compiler. You also need an editor, such as Microsoft Word for Windows, that can edit .RTF files. You can use App Studio to create bitmaps to include in your Help files.


  AppWizard

As you have seen, AppWizard is your first tool for implementing context-sensitive Help. Set the Context-Sensitive Help option in AppWizard's Options dialog box. AppWizard then provides the message-map entries in your CWinApp-derived class that connect up the whole help mechanism. AppWizard also creates a set of skeletal starter files, as shown in Table 5.7. The bitmap and .RTF files are in an HLP subdirectory that AppWizard creates in your project directory.

Table 5.7    AppWizard-Supplied Help Files

File	Description
[Yourproject].HPJ	A Windows Help project file that the Windows Help Compiler uses to compile your Help.
MAKEHELP.BAT	A batch file that manages Help ID mapping and calls the Help Compiler.
HLP\*.BMP	Various bitmap files used with the supplied Help files.
HLP\*.RTF	Skeleton Help files in .RTF format that contain starter Help for the application components supplied by the framework.
The help project file (.HPJ) and MAKEHELP.BAT are in your project directory. The other files are in an HLP subdirectory of your project directory.

You can edit these files as described in »Authoring and Compiling Help« to fill in application-specific Help information.


  MAKEHM and MAKEHELP.BAT

Once you've created the Help support files with AppWizard and are ready to prepare context-sensitive Help files, run the MAKEHELP.BAT tool from the MSDOS command line to create a "Help mapping" file (.HM extension) and to compile your Help file. MAKEHELP.BAT calls the MAKEHM tool, which translates the contents of your RESOURCE.H file to a Help mapping file, which is then included in the [MAP] section of your .HPJ file. The [MAP] section associates context strings (or aliases) with context numbers used by the Help Compiler. Then MAKEHELP.BAT calls the Windows Help Compiler to compile your Help file.

When you create a new resource or object within a resource, App Studio assigns it an identifier, or symbol, consisting of a C preprocessor macro name mapped to an integer value. App Studio writes these symbols as #define statements in a file called RESOURCE.H.

MAKEHM reads your RESOURCE.H file, locates all applicable #define statements (defining various IDs, including those for dialog boxes, menus, and toolbar buttons), and adds an appropriate number to each ID number, using certain rules that depend on the kind of ID (dialog box, menu, etc.). The rules are defined by MAKEHELP.BAT; the MAKEHM tool is actually more flexible than needed for MAKEHELP.BAT. The new "Help IDs" are written to an .HM file, which the Help Compiler uses to define contexts. For example, the following IDs defined in RESOURCE.H

#define IDD_MY_DIALOG   2000

#define ID_MY_COMMAND    150

would be translated by MAKEHM into

HIDD_MY_DIALOG    0x207d0

HID_MY_COMMAND    0x10096

Dialog-box IDs are translated to values beginning at 0x20000. Command and resource IDs are translated to values beginning at 0x10000. That is, the framework reserves specific ranges of values for different kinds of objects. For details, see the contents of MAKEHELP.BAT and Technical Note 28 in MSVCNT\HELP\MFCNOTES.HLP.

This format is compatible with the Help Compiler, which maps context IDs (the numbers on the right side) to topic names (the symbols on the left). Use these topic names in the .RTF Help files to identify contexts.


  Preferred Resource ID Prefixes

To facilitate using MAKEHELP.BAT and MAKEHM, observe the conventions in specifying IDs for your resource objects, as shown in Table 5.8. It is important that different kinds of resource objects have different ID prefixes.

Table 5.8    Preferred Resource ID Naming Conventions

Predefined ID	Object
IDP_	Message-box prompt
IDD_	Dialog-box ID
ID_	Toolbar or menu command (IDM_ is okay too)
IDR_	Frame-related resources
IDW_	Control bar
Use the IDS_ prefix for normal string resources, and do not write Help topics for them. For string resources used in message boxes, use the IDP_ prefix and write Help topics for them so the user can get context-sensitive Help by pressing F1 while the message box is displayed.


  Authoring and Compiling Help

For details about authoring and compiling Windows Help, see Help Compiler User's Guide.

The preferred way to build Help for your framework application is to run MAKEHELP.BAT. You must have the Microsoft Windows 3.1 Help Compiler in your path.

»Figure 5.7« shows the general process for creating a Help system for your application.

For an example of preparing Help files, see Chapter 10 in the Class Library User's Guide.


  In the Next Chapter

Chapters 2 through 5 have explained how the framework functions and given you some insight into its use. The next chapter, »Chapter 6«, explains the "general-purpose" classes and facilities of the Microsoft Foundation Class Library. These classes, global functions, and macros Help you diagnose problems with your application, manage file input/output, handle exceptional conditions, use collection classes, and more.


  CHAPTER 6  Using the General-Purpose Classes

This chapter summarizes the use of the general-purpose classes in the Microsoft Foundation Class Library. These classes provide useful services such as diagnostics, exception handling, and collections.


  CObject Services

The CObject base class provides the following services to objects of its derived classes:

•	Object diagnostics

•	Run-time class information

•	Object persistence

Some of these services are available only if you use certain macros in derived class declarations and implementations. In order to make use of the services listed above, you should seriously consider deriving most of your nontrivial classes from CObject. Many of the Microsoft Foundation classes are so derived, including almost all of the application architecture classes that make up the framework.


  Object Diagnostics

The Microsoft Foundation library provides many diagnostic features, including diagnostic dump context and object validity checking supplied by the CObject class. For global diagnostic features, see »Memory Diagnostics« later in this chapter.


  Diagnostic Dump Context

The CDumpContext class works in conjunction with the Dump member function of the CObject class to provide formatted diagnostic printing of internal object data. CDumpContext provides an insertion (<<) operator that accepts not only CObject pointers; standard types, such as BYTE and WORD; and CString and CTime objects.

A predefined CDumpContext object, afxDump, is available in the Debug version of the Microsoft Foundation classes (#define_DEBUG is required in your source code). For more information about afxDump, see »Macros and Globals«, and Technical Note 12, which can be found in MSVCNT\HELP\MFCNOTES.HLP.


  Object Validity Checking

You override the base class AssertValid member function in your derived class to perform a specific test of your object's internal consistency. Call the ASSERT_VALID macro, passing it a pointer to any CObject, to call that object's AssertValid function. The implementation of an AssertValid function usually includes calls to the ASSERT macro. For more information about AssertValid, see Chapter 15, "Diagnostics," in the Class Library User's Guide.


  Run-Time Class Information

The Microsoft Foundation classes offer the developer some optional features that make it possible to do run-time type checking. If you derive a class from CObject and implement one of three macros (IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, or IMPLEMENT_SERIAL), you can use member functions to:

•	Access the class name at run time.

•	Safely cast a generic CObject pointer to a derived class pointer.

Run-time class information is particularly valuable in the Debug environment because it can be used to detect incorrect casts and to produce object dumps with class names included.

Note  In order to access run-time type information, you must use the DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL macro in your class declaration, and you must use the corresponding IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, or IMPLEMENT_SERIAL macro in your class implementation.

Run-time class information is, of course, available in the Release environment. During serialization, the run-time class information is used to store the object's type with the object data.

Run-time class testing is not meant to be a substitute for using virtual functions added in a common base class. Use the run-time type information only when virtual functions are not appropriate.


  Object Persistence

Class CObject, in conjunction with class CArchive, supports "object persistence" through a process called serialization. Object persistence allows you to save a complex network of objects in a permanent binary form (usually disk storage) that persists after those objects are deleted from memory. Later you can load the objects from persistent storage and reconstitute them in memory.

To create your own serializable CObject-derived class, you must use the DECLARE_SERIAL macro in the class declaration, and you must use the corresponding IMPLEMENT_SERIAL macro in the class implementation. If you have added new data members in your derived class, you must override the base class Serialize member function to store object data to the archive object and load object data from it. Once you have a serializable class, you can serialize objects of that class to and from a file via a CArchive object.

A CArchive object provides a type-safe buffering mechanism for writing or reading serializable objects to or from a CFile object. Usually the CFile object represents a disk file; however, it can be also be a memory file (CMemFile object), perhaps representing the Clipboard. A given CArchive object either stores (writes, serializes) data or loads (reads, deserializes) data, but never both. Thus two successively created CArchive objects are required to serialize data to a file and then deserialize it back from the file. The life of a CArchive object is limited to one pass — either writing an object to a file or reading an object from a file.

When storing an object to a file, an archive attaches the CRuntimeClass name to the object. Then, when another archive loads the object from a file, the archive uses the CRuntimeClass name of the object to dynamically reconstruct the object in memory. A given object may be referenced more than once as it is written to the file by the storing archive. The loading archive, however, will reconstruct the object only once. The details about how an archive attaches CRuntimeClass information to objects and reconstructs objects, taking into account possible multiple references, are described in Technical Note 2 in MSVCNT\HELP\MFCNOTES.HLP.

As you serialize data to an archive, the archive accumulates the data until its buffer is full. When the buffer is full, the archive then writes its buffer to the CFile object pointed to by the CArchive object. Similarly, as you read data from an archive, the archive reads data from the file to its buffer, and then from the buffer to your deserialized object. This buffering reduces the number of times a hard disk is physically read, thus improving your application's performance.

There are two ways to create a CArchive object. The most common way, and the easiest way, is to let the framework create one for your document on behalf of the Save, Save As, and Open commands on the File menu. The other way is to explicitly create the CArchive object yourself.

To let the framework create the CArchive object for your document, simply implement the document's Serialize function, which writes and reads to and from the archive. You also have to implement Serialize for any CObject-derived objects that the document's Serialize function in turn serializes directly or indirectly.

There are other occasions besides serializing a document via the framework when you may need a CArchive object. For example, you might want to serialize data to and from the Clipboard, represented by a CMemFile object. Or, you might want to develop a user interface for saving files that is different from the one offered by the framework. In this case, you can explicitly create a CArchive object. You do this the same way the framework does. For more detailed information, see Chapter 14, "Files and Serialization" in the Class Library User's Guide.


  The File Classes

The CFile family of classes provides a C++ programming interface to operating-system files. The CFile class itself gives access to low-level binary files, and the CStdioFile class gives access to buffered "standard I/O" files. CStdioFile files are often processed in "text mode," which means that newline characters are converted to carriage return − linefeed pairs on output.

CMemFile supports "in-memory files." The files behave like disk files except that bytes are stored in RAM. An in-memory file is a useful means of transferring raw bytes or serialized objects between independent processes.

Because CFile is the base class for all file classes, it provides a polymorphic programming interface. If a CStdioFile file is opened, for example, its object pointer can be used by the virtual Read and Write member functions defined for the CFile class. The CDumpContext and CArchive classes, described previously, depend on the CFile class for input and output.


  The Collection Classes

The Microsoft Foundation Class Library contains a number of ready-to-use lists, arrays, and maps that are referred to as "collection classes." A collection is an extremely useful programming idiom for holding and processing groups of class objects or groups of standard types. A collection object appears as a single object. Class member functions can operate on all elements of the collection.

Most collections may be archived or sent to a dump context. The Dump and Serialize member functions for CObject pointer collections call the corresponding functions for each of their elements. Some collections may not be archived — for example, pointer collections.

If you need a list, array, or map that is not included among the standard collections provided with the Microsoft Foundation classes, you can use the Templdef template tool that is included in the \MSVCNT\MFC\SAMPLES directory. Technical Note 4, found in MSVCNT\HELP\MFCNOTES.HLP, describes how to the use this tool.

Note  The collection classes CObArray, CObList, CMapStringToOb, and CMapWordToOb accept CObject pointer elements and thus are useful for storing collections of objects of CObject-derived classes. If such a collection is archived or sent to a diagnostic dump context, then the element objects are automatically archived or dumped as well. For more about collection classes, see Chapter 13, "Collections," in the Class Library User's Guide.

When you program with the application framework, the collection classes will be especially useful for implementing data structures in your document class. For an example, see the document implementation in the tutorial contained in the Class Library User's Guide.


  Lists

There are "list" classes for CString objects, CObject pointers, and void pointers. A list is an ordered grouping of elements. New elements can be added at the head or tail of the list, or before or after a specified element. The list can be traversed in forward or reverse sequence, and elements may be retrieved or removed during the traversal.


  Arrays

The Microsoft Foundation Class Library contains "array" classes for bytes, words, doublewords, CString objects, CObject pointers, and void pointers. An array implemented this way is a dynamically sized grouping of elements that is directly accessible through a zero-based integer subscript. The subscript ([]) operator can be used to set or retrieve array elements. If an element above the current array bound is to be set, then the programmer can specify whether the array is to grow automatically. When growing is not required, array collection access is as fast as standard C array access.


  Maps

A "map" is a dictionary that maps keys to values. The map classes support CString objects, words, CObject pointers, and void pointers. Consider the CMapWordToOb class as an example. A WORD variable is used as a key to find the corresponding CObject pointer. Duplicate key values are not allowed. A key-pointer pair can be inserted only if the key is not already contained in the map. Key lookups are fast because they rely on a hashing technique.


  Other Support Classes

The Microsoft Foundation CString, CTime, and CTimeSpan classes are not derived from CObject. They are discussed below.


  The CString Class

The CString class supports dynamic character strings. CString objects can grow and shrink automatically, and they can be serialized. Member functions and overloaded operators add Basic-like string-processing capability. These features make CString objects easier to use than C-style fixed-length character arrays. Conversion functions allow CString objects to be used interchangeably with C-style strings. Thus a CString object can be passed to a function that expects a pointer to a constant string (const char*) parameter.

Like other Microsoft Foundation classes, the CString class allocates memory on the heap. You must be sure that CString destructors are called at appropriate times to free unneeded memory. There is no automatic "garbage collection" as there is in Basic.


  The CTime and CTimeSpan Classes

The CTime class encapsulates the run-time time_t data type. Thus it represents absolute time values in the range 1970 to 2038, approximately. There are member functions that convert a time value to years, months, days, hours, minutes, and seconds. The class has overloaded insertion and extraction operators for archiving and for diagnostic dumping.

The CTimeSpan class extends time_t by representing relative time values. When one CTime object is subtracted from another one, the result is a CTimeSpan object. A CTimeSpan object can be added to or subtracted from a CTime object. A CTimeSpan value is limited to the range of ± 68 years, approximately.


  Diagnostic Services

The Microsoft Foundation Class Library provides diagnostic services that make it easier to debug your programs. These services include macros and global functions that allow you to trace your program's memory allocations, dump the contents of objects during run time, and print debugging messages during run time. Most of these services require the Debug version of the library and thus should not be used in released applications. For a detailed description of the functions and macros available, see Chapter 15, "Diagnostics," in the Class Library User's Guide and the overview of »Macros and Globals« in this book.


   Memory Diagnostics

Many applications use the C++ new operator to allocate memory on the heap. The Microsoft Foundation classes provide a special Debug version of new that inserts extra control bytes in allocated memory blocks. These control bytes, together with the run-time class information that results from CObject derivation, allow you to analyze memory-allocation statistics and detect memory-block bounds violations. A memory dump can include the source filename and the line number of the allocated memory and, in the case of objects from CObject-derived classes, the name of the class and the output from its Dump function.


  Diagnostic Output

Many programmers want diagnostic output statements in their programs, particularly during the early stages of development. The TRACE statement acts like printf except that the TRACE code is not generated by the compiler with the Release version of the library. In the Windows environment, debugging output goes to the debugger if it is present.

Important  For important information on using TRACE, see the »Macros and Globals« section of this book and Technical Note 7 found in MSVCNT\HELP\MFCNOTES.HLP.

You can use the afxDump dump context object for stream-style dumping of standard types as well as Microsoft Foundation class objects. If you use afxDump, be sure to bracket references with #ifdef _DEBUG and #endif statements.


  Assertions

In the Debug environment, the ASSERT macro evaluates a specified condition. If the condition is false, the macro displays a message in a message box that gives the source filename and the line number and then terminates the program. In the Release environment, the ASSERT statement has no effect.

VERIFY, a companion macro, evaluates the condition in both the Debug and Release environments. It prints and terminates only in the Debug environment.

Classes derived from CObject, directly or indirectly, can also override the AssertValid member function to test the internal validity of objects of the class. For an example, see »Object Validity Checking«.


  Exception Handling

The Microsoft Foundation Class Library includes an exception-handling mechanism, similar to, and upwardly compatible with, the one in the proposed ANSI C++ standard, for handling "abnormal conditions." An abnormal condition is defined as a condition outside the program's control that influences the outcome of a function. Abnormal conditions include low memory, I/O errors, and attempted use of an unsupported feature. They do not include programming errors or normally expected conditions such as an end-of-file condition. In general, you can consider an exception to be a bug that remains in your program after shipping.

Exception handling in the Microsoft Foundation classes relies on "exception objects" and a group of macros. The process starts with the interruption of normal program execution in response to a THROW statement (macro invocation). Execution resumes at the appropriate CATCH statement leading into code that presumably deals with the abnormal condition. The exception objects, which are instances of classes derived from CException, differentiate the various kinds of exceptions and are used for communication.

This exception-handling scheme eliminates the need for extensive error testing after every library function call. If, for example, you enclose your entire program in an exception-handling block, then you don't have to test for low memory after each statement that contains the new operator.

If you don't provide THROW and CATCH exception-processing code in your classes, then exceptions will be caught in the Microsoft Foundation code. This results in termination of the program through the global function AfxTerminate, which normally calls the run-time function abort. However, if you use the AfxSetTerminate function, the effect of AfxTerminate is changed. When programming for Windows, it is important to remember that exceptions cannot cross the boundary of a "callback." In other words, if an exception occurs within the scope of a message handler, it must be caught there, before the next message is processed. If you do not catch an exception, the CWinApp member function ProcessWndProcException is called as a last resort. This function displays an error message and then continues processing.

For exception-processing examples and a more detailed explanation of error categories, see Chapter 16, "Exceptions," in the Class Library User's Guide. For a detailed description of the functions and macros available, see the »Macros and Globals« section in Part 2 of this book.


CArchive
  class CArchive

The CArchive class allows you to save a complex network of objects in a permanent binary form (usually disk storage) that persists after those objects are deleted. Later you can load the objects from persistent storage, reconstituting them in memory. This process of making data persistent is called "serialization."

You can think of an archive object as a kind of binary stream. Like an input/output stream, an archive is associated with a file and permits the buffered writing and reading of data to and from storage. An input/output stream processes sequences of ASCII characters, but an archive processes binary object data in an efficient, nonredundant format.

You must create a CFile object before you can create a CArchive object. In addition, you must ensure that the archive's load/store status is compatible with the file's open mode. You are limited to one active archive per file.

When you construct a CArchive object, you attach it to an object of class CFile (or a derived class) that represents an open file. You also specify whether the archive will be used for loading or storing. A CArchive object can process not only primitive types but also objects of CObject-derived classes designed for serialization. A serializable class must have a Serialize member function, and it must use the DECLARE_SERIAL and IMPLEMENT_SERIAL macros, as described under class CObject.

The overloaded extraction (>>) and insertion (<<) operators are convenient archive programming interfaces that support both primitive types and CObject-derived classes.

#include <afx.h>

See Also

»CFile«, »CObject«


CArchive Class Members
   Class Members

Construction/Destruction — Public Members

»CArchive«	Creates a CArchive object.
»~CArchive«	Destroys a CArchive object and flushes unwritten data.
»Close«	Flushes unwritten data and disconnects from the CFile.
Basic Input/Output — Public Members

»Flush«	Flushes unwritten data from the archive buffer.
»operator >>«	Loads objects and primitive types from the archive.
»operator <<«	Stores objects and primitive types to the archive.
»Read«	Reads raw bytes.
»Write«	Writes raw bytes.
Status — Public Members

»GetFile«	Gets the CFile object pointer for this archive.
»IsLoading«	Determines if the archive is loading.
»IsStoring«	Determines if the archive is storing.
Object Input/Output — Public Members

»ReadObject«	Calls an object's Serialize function for loading.
»WriteObject«	Calls an object's Serialize function for storing.


CArchive Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CArchive::CArchive

CArchive( CFile* pFile, UINT nMode, int nBufSize = 512,
void FAR* lpBuf = NULL )
throw( CMemoryException, CArchiveException, CFileException );

pFile    A pointer to the CFile object that is the ultimate source or destination of the persistent data.

nMode    A flag that specifies whether objects will be loaded from or stored to the archive. The nMode parameter must have one of the following values, with the meaning as given:

•	CArchive::load    Loads data from the archive. Requires only CFile read permission.

•	CArchive::store    Saves data to the archive. Requires CFile write permission.

•	CArchive::bNoFlushOnDelete    Prevents the archive from automatically calling Flush when the archive destructor is invoked. If you set this flag, you are responsible for explicitly calling Close before the destructor is invoked. If you do not, your data will be corrupted.

nBufSize    An integer that specifies the size of the internal file buffer, in bytes. Note that the default buffer size is 512 bytes. If you routinely archive large objects, you will improve performance if you use a larger buffer size that is a multiple of the file buffer size.

lpBuf    An optional FAR pointer to a user-supplied buffer of size nBufSize. If you do not specify this parameter, the archive allocates a buffer from the local heap and frees it when the object is destroyed. The archive does not free a user-supplied buffer.

Remarks

Constructs a CArchive object and specifies whether it will be used for loading or storing objects. You cannot change this specification after you have created the archive.

You may not use CFile operations to alter the state of the file until you have closed the archive. Any such operation will damage the integrity of the archive. You may access the position of the file pointer at any time during serialization by (1) obtaining the archive's file object from the GetFile member function and then (2) using the »CFile::GetPosition« function. You should call CArchive::Flush before obtaining the position of the file pointer.

See Also

»CArchive::Close«, »CArchive::Flush«, »CFile::Close«

Example

extern char* pFileName;
CFile f;
char buf[512];
if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite ) ) {
   #ifdef _DEBUG
      afxDump << "Unable to open file" << "\n";
      exit( 1 );
   #endif
}
CArchive ar( &f, CArchive::store, 512, buf );


  CArchive::~CArchive

~CArchive();

Remarks

The CArchive destructor closes the archive if it is not closed already. However, you should call the member function »Close« before calling the destructor. After you have used the CFile object for archiving, you must close and destroy it as you usually would.

See Also

»CArchive::Flush«, »CFile::Close«


  CArchive::Close

void Close()
throw( CArchiveException, CFileException );

Remarks

Flushes any data remaining in the buffer, closes the archive, and disconnects the archive from the file. No further operations on the archive are permitted. After you close an archive, you can create another archive for the same file or you can close the file.

The member function Close ensures that all data is transferred from the archive to the file, and it makes the archive unavailable. To complete the transfer from the file to the storage medium, you must first use CFile::Close and then destroy the CFile object.

See Also

»CArchive::Flush«


  CArchive::Flush

void Flush()
throw( CFileException );

Remarks

Forces any data remaining in the archive buffer to be written to the file.

The member function Flush ensures that all data is transferred from the archive to the file. You must call CFile::Close to complete the transfer from the file to the storage medium.

See Also

»CArchive::Close«, »CFile::Flush«, »CFile::Close«


  CArchive::GetFile

CFile* GetFile() const;

Remarks

Gets the CFile object pointer for this archive. You must flush the archive before using GetFile.

Return Value

A constant pointer to the CFile object in use.

Example

extern CArchive ar;
const CFile* fp = ar.GetFile();


  CArchive::IsLoading

BOOL IsLoading() const;

Remarks

Determines if the archive is loading data. This member function is called by the Serialize functions of the archived classes.

Return Value

Nonzero if the archive is currently being used for loading; otherwise 0.

See Also

»CArchive::IsStoring«

Example

int i;
extern CArchive ar;
if( ar.IsLoading() )
  ar >> i;
else
  ar << i;


  CArchive::IsStoring

BOOL IsStoring() const;

Remarks

Determines if the archive is storing data. This member function is called by the Serialize functions of the archived classes.

If the IsStoring status of an archive is nonzero, then its IsLoading status is 0, and vice versa.

Return Value

Nonzero if the archive is currently being used for storing; otherwise 0.

See Also

»CArchive::IsLoading«

Example

int i;
extern CArchive ar;
if( ar.IsStoring() )
  ar << i;
else
  ar >> i;


  CArchive::Read

UINT Read( void FAR* lpBuf, UINT nMax )
throw( CFileException );

lpBuf    A FAR pointer to a user-supplied buffer that is to receive the data read from the archive.

nMax    An unsigned integer specifying the number of bytes to be read from the archive.

Remarks

Reads a specified number of bytes from the archive. The archive does not interpret the bytes.

You can use the Read member function within your Serialize function for reading ordinary structures that are contained in your objects.

Return Value

An unsigned integer containing the number of bytes actually read. If the return value is less than the number requested, the end of file has been reached. No exception is thrown on the end-of-file condition.

Example

extern CArchive ar;
char pb[100];
UINT nr = ar.Read( pb, 100 );


  CArchive::ReadObject

CObject* ReadObject( const CRuntimeClass* pClass )
throw( CFileException, CArchiveException, CMemoryException );

pClass    A constant pointer to the CRuntimeClass structure that corresponds to the object you expect to read.

Remarks

Reads object data from the archive and constructs an object of the appropriate type. If the object contains pointers to other objects, those objects are constructed automatically.

This function is normally called by the CArchive extraction (>>) operator overloaded for a CObject pointer. ReadObject, in turn, calls the Serialize function of the archived class.

If you supply a nonzero pClass parameter, which is obtained by the »RUNTIME_CLASS macro«, then the function verifies the run-time class of the archived object. This assumes you have used the IMPLEMENT_SERIAL macro in the implementation of the class.

Return Value

A CObject pointer that must be safely cast to the correct derived class by using CObject::IsKindOf.

See Also

»CArchive::WriteObject«, »CObject::IsKindOf«


  CArchive::Write

void Write( const void FAR* lpBuf, UINT nMax )
throw( CFileException );

lpBuf    A pointer to a user-supplied buffer that contains the data to be written to the archive.

nMax    An integer that specifies the number of bytes to be written to the archive.

Remarks

Writes a specified number of bytes to the archive. The archive does not format the bytes.

You can use the Write member function within your Serialize function to write ordinary structures that are contained in your objects.

See Also

»CArchive::Read«

Example

extern CArchive ar;
char pb[100];
ar.Write( pb, 100 );


  CArchive::WriteObject

void WriteObject( const CObject* pOb )
throw( CFileException, CArchiveException );

pOb    A constant pointer to the object being stored.

Remarks

Stores the specified CObject to the archive. If the object contains pointers to other objects, they are serialized in turn.

This function is normally called by the CArchive insertion (<<) operator overloaded for CObject. WriteObject, in turn, calls the Serialize function of the archived class.

You must use the IMPLEMENT_SERIAL macro to enable archiving. WriteObject writes the ASCII class name to the archive. This class name is validated later during the load process. A special encoding scheme prevents unnecessary duplication of the class name for multiple objects of the class. This scheme also prevents redundant storage of objects that are targets of more than one pointer.

The exact object encoding method (including the presence of the ASCII class name) is an implementation detail and could change in future versions of the library.

Note  Finish creating, deleting, and updating all your objects before you begin to archive them. Your archive will be corrupted if you mix archiving with object modification.

See Also

»CArchive::ReadObject«


CArchive Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CArchive::operator <<

friend CArchive& operator <<( CArchive& ar, const CObject* pOb )
throw( CArchiveException, CFileException );

CArchive& operator <<( BYTE by )
throw( CArchiveException, CFileException );

CArchive& operator <<( WORD w )
throw( CArchiveException, CFileException );

CArchive& operator <<( LONG l )
throw( CArchiveException, CFileException );

CArchive& operator <<( DWORD dw )
throw( CArchiveException, CFileException );

CArchive& operator <<( float f )
throw( CArchiveException, CFileException );

CArchive& operator <<( double d )
throw( CArchiveException, CFileException );

Remarks

Stores the indicated object or primitive type to the archive.

If you used the IMPLEMENT_SERIAL macro in your class implementation, then the insertion operator overloaded for CObject calls the protected WriteObject. This function, in turn, calls the Serialize function of the class.

Return Value

A CArchive reference that enables multiple extraction operators on a single line.

See Also

»CArchive::WriteObject«, »CObject::Serialize«

Example

long l;
int i;
extern CArchive ar;
if( ar.IsStoring() )

  ar << l << i;


  CArchive::operator >>

friend CArchive& operator >>( CArchive& ar, CObject *& pOb )
throw( CArchiveException, CFileException, CMemoryException );

friend CArchive& operator >>( CArchive& ar, const CObject *& pOb )
throw( CArchiveException, CFileException, CMemoryException );

CArchive& operator >>( BYTE& by )
throw( CArchiveException, CFileException );

CArchive& operator >>( WORD& w )
throw( CArchiveException, CFileException );

CArchive& operator >>( LONG& l )
throw( CArchiveException, CFileException );

CArchive& operator >>( DWORD& dw )
throw( CArchiveException, CFileException );

CArchive& operator >>( float& f )
throw( CArchiveException, CFileException );

CArchive& operator >>( double& d )
throw( CArchiveException, CFileException );

Remarks

Loads the indicated object or primitive type from the archive.

If you used the IMPLEMENT_SERIAL macro in your class implementation, then the extraction operators overloaded for CObject call the protected ReadObject function (with a nonzero run-time class pointer). This function, in turn, calls the Serialize function of the class.

Return Value

A CArchive reference that enables multiple insertion operators on a single line.

See Also

»CArchive::ReadObject«, »CObject::Serialize«

Example

int i;
extern CArchive ar;
if( ar.IsLoading() )
  ar >> i;


CArchiveException
   class CArchiveException : public CException

A CArchiveException object represents a serialization exception condition. The CArchiveException class includes a public data member that indicates the cause of the exception.

CArchiveException objects are constructed and thrown inside CArchive member functions. You can access these objects within the scope of a CATCH expression. The cause code is independent of the operating system. For more information about exception processing, see Chapter 16, "Exceptions," in the Class Library User's Guide.

#include <afx.h>

See Also

»CArchive«, »AfxThrowArchiveException«

»Exception Processing«


CArchiveException Class Members
   Class Members

Data Members — Public Members

»m_cause«	Indicates the exception cause.
Construction/Destruction — Public Members

»CArchiveException«	Constructs a CArchiveException object.


CArchiveException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CArchiveException::CArchiveException

CArchiveException( int cause = CArchiveException::none );

cause    An enumerated type variable that indicates the reason for the exception. For a list of the enumerators, see the »m_cause« data member.

Remarks

Constructs a CArchiveException object, storing the value of cause in the object. You can create a CArchiveException object on the heap and throw it yourself or let the global function »AfxThrowArchiveException« handle it for you.

Do not use this constructor directly; instead, call the global function AfxThrowArchiveException.


CArchiveException Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CArchiveException::m_cause

Remarks

Specifies the cause of the exception. This data member is a public variable of type int. Its values are defined by a CArchiveException enumerated type. The enumerators and their meanings are as follows:

•	CArchiveException::none    No error occurred.

•	CArchiveException::generic    Unspecified error.

•	CArchiveException::readOnly    Tried to write into an archive opened for loading.

•	CArchiveException::endOfFile    Reached end of file while reading an object.

•	CArchiveException::writeOnly    Tried to read from an archive opened for storing.

•	CArchiveException::badIndex    Invalid file format.

•	CArchiveException::badClass    Tried to read an object into an object of the wrong type.

•	CArchiveException::badSchema    Tried to read an object with a different version of the class.

Note  These CArchiveException cause enumerators are distinct from the CFileException cause enumerators.


CBitmap
  class CBitmap : public CGdiObject

The CBitmap class encapsulates a Windows graphics device interface (GDI) bitmap and provides member functions to manipulate the bitmap. To use a CBitmap object, construct the object, install a bitmap handle in it with one of the initialization member functions, and then call the object's member functions.

#include <afxwin.h>


CBitmap Class Members
   Class Members

Construction/Destruction — Public Members

»CBitmap«	Constructs a CBitmap object.
Initialization — Public Members

»LoadBitmap«	Initializes the object by loading a named bitmap resource from the application's executable file and attaching the bitmap to the object.
»LoadOEMBitmap«	Initializes the object by loading a predefined Windows bitmap and attaching the bitmap to the object.
»CreateBitmap«	Initializes the object with a device-dependent memory bitmap that has a specified width, height, and bit pattern.
»CreateBitmapIndirect«	Initializes the object with a bitmap with the width, height, and bit pattern (if one is specified) given in a BITMAP structure.
»CreateCompatibleBitmap«	Initializes the object with a bitmap so that it is compatible with a specified device.
»CreateDiscardableBitmap«	Initializes the object with a discardable bitmap that is compatible with a specified device.
Operations — Public Members

»FromHandle«	Returns a pointer to a CBitmap object when given a handle to a Windows HBITMAP bitmap.
»SetBitmapBits«	Sets the bits of a bitmap to the specified bit values.
»GetBitmapBits«	Copies the bits of the specified bitmap into the specified buffer.
»SetBitmapDimension«	Assigns a width and height to a bitmap in 0.1-millimeter units.
»GetBitmapDimension«	Returns the width and height of the bitmap. The height and width are assumed to have been set previously by the »SetBitmapDimension« member function.


CBitmap Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CBitmap::CBitmap

CBitmap();

Remarks

Constructs a CBitmap object. The resulting object must be initialized with one of the initialization member functions.

See Also

»CBitmap::LoadBitmap«, »CBitmap::LoadOEMBitmap«, »CBitmap::CreateBitmap«, »CBitmap::CreateBitmapIndirect«, »CBitmap::CreateCompatibleBitmap«, »CBitmap::CreateDiscardableBitmap«


  CBitmap::CreateBitmap

BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void FAR* lpBits );

nWidth    Specifies the width (in pixels) of the bitmap.

nHeight    Specifies the height (in pixels) of the bitmap.

nPlanes    Specifies the number of color planes in the bitmap.

nBitcount    Specifies the number of color bits per display pixel.

lpBits    Points to a short-integer array that contains the initial bitmap bit values. If it is NULL, the new bitmap is left uninitialized.

For more information, see the description of the bmBits field in the BITMAP structure. In this manual, the »BITMAP« structure is described under the »CBitmap::CreateBitmapIndirect« member function.

Remarks

Initializes a device-dependent memory bitmap that has the specified width, height, and bit pattern.

For a color bitmap, either the nPlanes or nBitcount parameter should be set to 1. If both of these parameters are set to 1, CreateBitmap creates a monochrome bitmap.

Although a bitmap cannot be directly selected for a display device, it can be selected as the current bitmap for a "memory device context" by using »CDC::SelectObject« and copied to any compatible device context by using the »CDC::BitBlt« function.

When you finish with the CBitmap object created by the CreateBitmap function, first select the bitmap out of the device context, then delete the CBitmap object.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CDC::SelectObject«, »CGdiObject::DeleteObject«, »CDC::BitBlt«, ::CreateBitmap


  CBitmap::CreateBitmapIndirect

BOOL CreateBitmapIndirect( LPBITMAP lpBitmap );

lpBitmap    Points to a »BITMAP« structure that contains information about the bitmap.

Remarks

Initializes a bitmap that has the width, height, and bit pattern (if one is specified) given in the structure pointed to by lpBitmap. Although a bitmap cannot be directly selected for a display device, it can be selected as the current bitmap for a memory device context by using »CDC::SelectObject« and copied to any compatible device context by using the »CDC::BitBlt« or »CDC::StretchBlt« function. (The »CDC::PatBlt« function can copy the bitmap for the current brush directly to the display device context.)

If the BITMAP structure pointed to by the lpBitmap parameter has been filled in by using the GetObject function, the bits of the bitmap are not specified and the bitmap is uninitialized. To initialize the bitmap, an application can use a function such as »CDC::BitBlt« or ::SetDIBits to copy the bits from the bitmap identified by the first parameter of CGdiObject::GetObject to the bitmap created by CreateBitmapIndirect.

When you finish with the CBitmap object created with CreateBitmapIndirect function, first select the bitmap out of the device context, then delete the CBitmap object.

Return Value

Nonzero if successful; otherwise 0.

BITMAP Structure

A BITMAP structure has this form:

typedef struct tagBITMAP {  /* bm */
    int     bmType;
    int     bmWidth;
    int     bmHeight;
    int     bmWidthBytes;
    BYTE    bmPlanes;
    BYTE    bmBitsPixel;
    void FAR* bmBits;
} BITMAP;

The BITMAP structure defines the height, width, color format, and bit values of a logical bitmap.

Members

bmType    Specifies the bitmap type. For logical bitmaps, this member must be 0.

bmWidth    Specifies the width of the bitmap in pixels. The width must be greater than 0.

bmHeight    Specifies the height of the bitmap in raster lines. The height must be greater than 0.

bmWidthBytes    Specifies the number of bytes in each raster line. This value must be an even number since the graphics device interface (GDI) assumes that the bit values of a bitmap form an array of integer (2-byte) values. In other words, bmWidthBytes * 8 must be the next multiple of 16 greater than or equal to the value obtained when the bmWidth member is multiplied by the bmBitsPixel member.

bmPlanes    Specifies the number of color planes in the bitmap.

bmBitsPixel    Specifies the number of adjacent color bits on each plane needed to define a pixel.

bmBits    Points to the location of the bit values for the bitmap. The bmBits member must be a long pointer to an array of 1-byte values.

Comments

The currently used bitmap formats are monochrome and color. The monochrome bitmap uses a 1-bit, 1-plane format. Each scan is a multiple of 16 bits.

Scans are organized as follows for a monochrome bitmap of height n:

Scan 0
Scan 1
.
.
.
Scan n-2
Scan n-1

The pixels on a monochrome device are either black or white. If the corresponding bit in the bitmap is 1, the pixel is turned on (white). If the corresponding bit in the bitmap is 0, the pixel is turned off (black).

All devices support bitmaps that have the RC_BITBLT bit set in the RASTERCAPS index of the GetDeviceCaps member function.

Each device has its own unique color format. In order to transfer a bitmap from one device to another, use the GetDIBits and SetDIBits Windows functions.

See Also

»CDC::SelectObject«, »CDC::BitBlt«, »CGdiObject::DeleteObject«, »CGdiObject::GetObject«, ::CreateBitmapIndirect


  CBitmap::CreateCompatibleBitmap

BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth, int nHeight );

pDC    Specifies the device context.

nWidth    Specifies the width (in bits) of the bitmap.

nHeight    Specifies the height (in bits) of the bitmap.

Remarks

Initializes a bitmap that is compatible with the device specified by pDC. The bitmap has the same number of color planes or the same bits-per-pixel format as the specified device context. It can be selected as the current bitmap for any memory device that is compatible with the one specified by pDC.

If pDC is a memory device context, the bitmap returned has the same format as the currently selected bitmap in that device context. A "memory device context" is a block of memory that represents a display surface. It can be used to prepare images in memory before copying them to the actual display surface of the compatible device.

When a memory device context is created, GDI automatically selects a monochrome stock bitmap for it.

Since a color memory device context can have either color or monochrome bitmaps selected, the format of the bitmap returned by the CreateCompatibleBitmap function is not always the same; however, the format of a compatible bitmap for a nonmemory device context is always in the format of the device.

When you finish with the CBitmap object created with the CreateCompatibleBitmap function, first select the bitmap out of the device context, then delete the CBitmap object.

Return Value

Nonzero if successful; otherwise 0.

See Also

::CreateCompatibleBitmap, »CGdiObject::DeleteObject«


  CBitmap::CreateDiscardableBitmap

BOOL CreateDiscardableBitmap( CDC* pDC, int nWidth, int nHeight );

pDC    Specifies a device context.

nWidth    Specifies the width (in bits) of the bitmap.

nHeight    Specifies the height (in bits) of the bitmap.

Remarks

Initializes a discardable bitmap that is compatible with the device context identified by pDC. The bitmap has the same number of color planes or the same bits-per-pixel format as the specified device context. An application can select this bitmap as the current bitmap for a memory device that is compatible with the one specified by pDC.

Windows can discard a bitmap created by this function only if an application has not selected it into a display context. If Windows discards the bitmap when it is not selected and the application later attempts to select it, the »CDC::SelectObject« function will return NULL.

When you finish with the CBitmap object created with the CreateDiscardableBitmap function, first select the bitmap out of the device context, then delete the CBitmap object.

Return Value

Nonzero if successful; otherwise 0.

See Also

::CreateDiscardableBitmap, »CGdiObject::DeleteObject«


  CBitmap::FromHandle

static CBitmap* PASCAL FromHandle( HBITMAP hBitmap );

hBitmap    Specifies a Windows GDI bitmap.

Remarks

Returns a pointer to a CBitmap object when given a handle to a Windows GDI bitmap. If a CBitmap object is not already attached to the handle, a temporary CBitmap object is created and attached. This temporary CBitmap object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CBitmap object if successful; otherwise NULL.


  CBitmap::GetBitmapBits

DWORD GetBitmapBits( DWORD dwCount, LPVOID lpBits ) const;

dwCount    Specifies the number of bytes to be copied.

lpBits    Points to the buffer that is to receive the bitmap. The bitmap is an array of bytes. The bitmap byte array conforms to a structure where horizontal scan lines are multiples of 16 bits.

Remarks

Copies the bit pattern of the CBitmap object into the buffer that is pointed to by lpBits. The dwCount parameter specifies the number of bytes to be copied to the buffer. Use »GetObject« to determine the correct dwCount value for the given bitmap.

Return Value

The actual number of bytes in the bitmap, or 0 if there is an error.

See Also

»CGdiObject::GetObject«, ::GetBitmapBits


  CBitmap::GetBitmapDimension

CSize GetBitmapDimension() const;

Remarks

Returns the width and height of the bitmap. The height and width are assumed to have been set previously by using the »SetBitmapDimension« member function.

Return Value

The width and height of the bitmap, measured in 0.1-millimeter units. The height is in the cy member of the CSize object, and the width is in the cx member. If the bitmap width and height have not been set by using SetBitmapDimension, the return value is 0.

See Also

»CBitmap::SetBitmapDimension«, ::GetBitmapDimension


  CBitmap::LoadBitmap

BOOL LoadBitmap( LPCSTR lpszResourceName );

BOOL LoadBitmap( UINT nIDResource );

lpszResourceName    Points to a null-terminated string that contains the name of the bitmap resource.

nIDResource     Specifies the resource ID number of the bitmap resource.

Remarks

Loads the bitmap resource named by lpszResourceName or identified by the ID number in nIDResource from the application's executable file. The loaded bitmap is attached to the CBitmap object.

If the bitmap identified by lpszResourceName does not exist or if there is insufficient memory to load the bitmap, the function returns 0.

An application must call the CGdiObject::DeleteObject function to delete any bitmap loaded by the LoadBitmap function.

Windows 3.1 only

The following new bitmaps have been added:

OBM_UPARRROWI
OBM_DNARROWI
OBM_RGARROWI
OBM_LFARROWI

These bitmaps are not found in device drivers for Windows versions 3.0 and earlier. For a complete list of bitmaps and a display of their appearance, see the Programmer's Reference in the Windows Software Development Kit. ♦

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBitmap::LoadOEMBitmap«, ::LoadBitmap, »CGdiObject::DeleteObject«


  CBitmap::LoadOEMBitmap

BOOL LoadOEMBitmap( UINT nIDBitmap );

nIDBitmap    ID number of the predefined Windows bitmap. The possible values are listed below from WINDOWS.H:

OBM_BTNCORNERS
OBM_BTSIZE
OBM_CHECK
OBM_CHECKBOXES
OBM_CLOSE
OBM_COMBO
OBM_DNARROW
OBM_DNARROWD
OBM_DNARROWI
OBM_LFARROW
OBM_LFARROWD
OBM_LFARROWI
OBM_MNARROW
OBM_OLD_CLOSE
OBM_OLD_DNARROW
OBM_OLD_LFARROW
OBM_OLD_REDUCE
OBM_OLD_RESTORE
OBM_OLD_RGARROW
OBM_OLD_UPARROW
OBM_OLD_ZOOM
OBM_REDUCE
OBM_REDUCED
OBM_RESTORE
OBM_RESTORED
OBM_RGARROW
OBM_RGARROWD
OBM_RGARROWI
OBM_SIZE
OBM_UPARROW
OBM_UPARROWD
OBM_UPARROWI
OBM_ZOOM
OBM_ZOOMD

Remarks

Loads a predefined bitmap used by Windows.

Bitmap names that begin with OBM_OLD represent bitmaps used by Windows versions prior to 3.0.

Note that the constant OEMRESOURCE must be defined before including WINDOWS.H in order to use any of the OBM_ constants.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBitmap::LoadBitmap«, ::LoadBitmap


  CBitmap::SetBitmapBits

DWORD SetBitmapBits( DWORD dwCount, const void FAR* lpBits );

dwCount    Specifies the number of bytes pointed to by lpBits.

lpBits    Points to the BYTE array that contains the bit values to be copied to the CBitmap object.

Remarks

Sets the bits of a bitmap to the bit values given by lpBits.

Return Value

The number of bytes used in setting the bitmap bits; 0 if the function fails.

See Also

::SetBitmapBits


  CBitmap::SetBitmapDimension

CSize SetBitmapDimension( int nWidth, int nHeight );

nWidth    Specifies the width of the bitmap (in 0.1-millimeter units).

nHeight    Specifies the height of the bitmap (in 0.1-millimeter units).

Remarks

Assigns a width and height to a bitmap in 0.1-millimeter units. The GDI does not use these values except to return them when an application calls the »GetBitmapDimension« member function.

Return Value

The previous bitmap dimensions. Height is in the cy member variable of the CSize object, and width is in the cx member variable.

See Also

»CBitmap::GetBitmapDimension«, ::SetBitmapDimension


CBitmapButton
  class CBitmapButton : public CButton

Use the CBitmapButton class to create pushbutton controls labeled with bitmapped images instead of text. CBitmapButton objects contain up to four bitmaps, which contain images for the different states a button can assume: up (or normal), down (or selected), focused, and disabled. Only the first bitmap is required; the others are optional.

Bitmap-button images include the border around the image as well as the image itself. The border typically plays a part in showing the state of the button. For example, the bitmap for the focused state usually is like the one for the up state but with a dashed rectangle inset from the border or a thick solid line at the border. The bitmap for the disabled state usually resembles the one for the up state but has lower contrast (like a dimmed or grayed menu selection).

These bitmaps can be of any size, but all are treated as if they were the same size as the bitmap for the up state.

Various applications demand different combinations of bitmap images:

Up	Down	Focused	Disabled	Application
×				Bitmap
×	×			Button without WS_TABSTOP style
×	×	×	×	Dialog button with all states
×	×	×		Dialog button with WS_TABSTOP style
When creating a bitmap-button control, set the BS_OWNERDRAW style to specify that the button is owner-drawn.  This causes Windows to send the WM_MEASUREITEM and WM_DRAWITEM messages for the button; the framework handles these messages and manages the appearance of the button for you.

To create a bitmap-button control in a window's client area, follow these steps:

1.	Create one to four bitmap images for the button.

2.	Construct the »CBitmapButton« object.

3.	Call the »Create« function to create the Windows button control and attach it to the CBitmapButton object.

4.	Call the »LoadBitmaps« member function to load the bitmap resources after the bitmap button is constructed.

To include a bitmap-button control in a dialog box, follow these steps:

1.	Create one to four bitmap images for the button.

2.	Create a dialog template with an owner-draw button positioned where you want the bitmap button. The size of the button in the template does not matter.

3.	Set the button's caption to a value such as "MYIMAGE" and define a symbol for the button such as IDC_MYIMAGE.

4.	In your application's resource script, give each of the images created for the button an ID constructed by appending one of the letters "U," "D," "F," or "X" (for up, down, focused, and disabled) to the string used for the button caption in step 3. For the button caption "MYIMAGE," for example, the IDs would be "MYIMAGEU," "MYIMAGED," "MYIMAGEF," and "MYIMAGEX."

5.	In your application's dialog class (derived from CDialog), add a CBitmapButton member object.

6.	In the CDialog object's »OnInitDialog« routine, call the CBitmapButton object's »AutoLoad« function, using as parameters the button's control ID and the CDialog object's this pointer.

If you want to handle Windows notification messages, such as BN_CLICKED, sent by a bitmap-button control to its parent (usually a class derived from CDialog), add to the CDialog-derived object a message-map entry and message-handler member function for each message. The notifications sent by a CBitmapButton object are the same as those sent by a CButton object.

The class CToolBar takes a different approach to bitmap buttons. See »CToolBar« for more information.

#include <afxext.h>

See Also

»CButton«, »CBitmapButton::AutoLoad«, »CToolBar«


CBitmapButton  Class Members
   Class Members

Construction/Destruction — Public Members

»CBitmapButton«	Constructs a CBitmapButton object.
»LoadBitmaps«	Initializes the object by loading one or more named bitmap resources from the application's resource file and attaching the bitmaps to the object.
»AutoLoad«	Associates a button in a dialog with an object of the CBitmapButton class, loads the bitmap(s) by name, and sizes the button to fit the bitmap.
Operations — Public Members

»SizeToContent«	Sizes the button to accommodate the bitmap.


CBitmapButton Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CBitmapButton::AutoLoad

BOOL AutoLoad( UINT nID, CWnd* pParent );

nID    The button's control ID.

pParent    Pointer to the object that owns the button.

Remarks

Associates a button in a dialog box with an object of the CBitmapButton class, loads the bitmap(s) by name, and sizes the button to fit the bitmap.

Use the AutoLoad function to initialize an owner-draw button in a dialog box as a bitmap button. Instructions for using this function are in the remarks for the »CBitmapButton« class.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBitmapButton«, »CBitmapButton::LoadBitmaps«, »CBitmapButton::SizeToContent«


  CBitmapButton::CBitmapButton

CBitmapButton();

Remarks

Creates a CBitmapButton object.

See Also

»CBitmapButton::LoadBitmaps«, »CBitmapButton::AutoLoad«, »CBitmapButton::SizeToContent«, »CButton::Create«


  CBitmapButton::LoadBitmaps

BOOL LoadBitmaps( LPCSTR lpszBitmapResource, LPCSTR lpszBitmapResourceSel = NULL, LPCSTR lpszBitmapResourceFocus = NULL, LPCSTR lpszBitmapResourceDisabled = NULL );

lpszBitmapResource    Resource name of the bitmap for a bitmap button's normal or "up" state. Required.

lpszBitmapResourceSel    Resource name of the bitmap for a bitmap button's selected or "down" state. May be NULL.

lpszBitmapResourceFocus    Resource name of the bitmap for a bitmap button's focused state. May be NULL.

lpszBitmapResourceDisabled    Resource name of the bitmap for a bitmap button's disabled state. May be NULL.

Remarks

Use this function when you want to load bitmap images identified by their resource names or when you cannot use the AutoLoad function because, for example, you are creating a bitmap button that is not part of a dialog box.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBitmapButton«, »CBitmapButton::AutoLoad«, »CBitmapButton::SizeToContent«, »CButton::Create«, »CBitmap::LoadBitmap«


  CBitmapButton::SizeToContent

void SizeToContent();

Remarks

Call this function to resize a bitmap button to the size of the bitmap.

See Also

»CBitmapButton«, »CBitmapButton::LoadBitmaps«, »CBitmapButton::AutoLoad«


CBrush
  class CBrush : public CGdiObject

The CBrush class encapsulates a Windows graphics device interface (GDI) brush. To use a CBrush object, construct a CBrush object and pass it to any CDC member function that requires a brush.

Brushes can be solid, hatched, or patterned.

#include <afxwin.h>

See Also

»CBitmap«, »CDC«


CBrush Class Members
   Class Members

Construction/Destruction — Public Members

»CBrush«	Constructs a CBrush object.
Initialization — Public Members

»CreateSolidBrush«	Initializes a brush with the specified solid color.
»CreateHatchBrush«	Initializes a brush with the specified hatched pattern and color.
»CreateBrushIndirect«	Initializes a brush with the style, color, and pattern specified in a LOGBRUSHstructure.
»CreatePatternBrush«	Initializes a brush with a pattern specified by a bitmap.
»CreateDIBPatternBrush«	Initializes a brush with a pattern specified by a device-independent bitmap (DIB).
Operations — Public Members

»FromHandle«	Returns a pointer to a CBrush object when given a handle to a Windows HBRUSH object.


CBrush Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CBrush::CBrush

CBrush();

CBrush( COLORREF crColor )
throw( CResourceException );

CBrush( int nIndex, COLORREF crColor )
throw( CResourceException );

CBrush( CBitmap* pBitmap )
throw( CResourceException );

crColor    Specifies the foreground color of the brush as an RGB color. If the brush is hatched, this parameter specifies the color of the hatching.

nIndex    Specifies the hatch style of the brush. It can be any one of the following values, with the meaning as given:

•	HS_BDIAGONAL    Downward hatch (left to right) at 45 degrees

•	HS_CROSS    Horizontal and vertical crosshatch

•	HS_DIAGCROSS    Crosshatch at 45 degrees

•	HS_FDIAGONAL    Upward hatch (left to right) at 45 degrees

•	HS_HORIZONTAL    Horizontal hatch

•	HS_VERTICAL    Vertical hatch

pBitmap    Points to a CBitmap object that specifies a bitmap with which the brush paints.

Remarks

Has four overloaded constructors. The constructor with no arguments constructs an uninitialized CBrush object that must be initialized before it can be used.

If you use the constructor with no arguments, you must initialize the resulting CBrush object with CreateSolidBrush, CreateHatchBrush, CreateBrushIndirect, CreatePatternBrush, or CreateDIBPatternBrush. If you use one of the constructors that takes arguments, then no further initialization is necessary. The constructors with arguments can throw an exception if errors are encountered, while the constructor with no arguments will always succeed.

The constructor with a single COLORREF parameter constructs a solid brush with the specified color. The color specifies an RGB value and can be constructed with the RGB macro in WINDOWS.H.

The constructor with two parameters constructs a hatch brush. The nIndex parameter specifies the index of a hatched pattern. The crColor parameter specifies the color.

The constructor with a CBitmap parameter constructs a patterned brush. The parameter identifies a bitmap. The bitmap is assumed to have been created by using »CBitmap::CreateBitmap«, »CBitmap::CreateBitmapIndirect«, »CBitmap::LoadBitmap«, or »CBitmap::CreateCompatibleBitmap«. The minimum size for a bitmap to be used in a fill pattern is 8 pixels by 8 pixels.

See Also

»CBitmap::CreateBitmap«, »CBitmap::CreateBitmapIndirect«, »CBitmap::LoadBitmap«, »CBitmap::CreateCompatibleBitmap«, »CBrush::CreateSolidBrush«, »CBrush::CreateHatchBrush«, »CBrush::CreateBrushIndirect«, »CBrush::CreatePatternBrush«, »CBrush::CreateDIBPatternBrush«, »CGdiObject::CreateStockObject«


  CBrush::CreateBrushIndirect

BOOL CreateBrushIndirect( LPLOGBRUSH lpLogBrush );

lpLogBrush    Points to a LOGBRUSH structure that contains information about the brush.

The LOGBRUSH structure has the following form:

typedef struct tagLOGBRUSH {
    UINT      lbStyle;
    COLORREF  lbColor;
    int lbHatch;
} LOGBRUSH;

Remarks

Initializes a brush with a style, color, and pattern specified in a LOGBRUSHstructure. The brush can subsequently be selected as the current brush for any device context.

A brush created using a monochrome (1 plane, 1 bit per pixel) bitmap is drawn using the current text and background colors. Pixels represented by a bit set to 0 will be drawn with the current text color. Pixels represented by a bit set to 1 will be drawn with the current background color.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CBrush::CreateDIBPatternBrush«, »CBrush::CreatePatternBrush«, »CBrush::CreateSolidBrush«, »CBrush::CreateHatchBrush«, »CGdiObject::CreateStockObject«, »CGdiObject::DeleteObject«, ::CreateBrushIndirect


  CBrush::CreateDIBPatternBrush

BOOL CreateDIBPatternBrush( HGLOBAL hPackedDIB, UINT nUsage );

hPackedDIB    Identifies a global-memory object containing a packed device-independent bitmap (DIB).

nUsage    Specifies whether the bmiColors[] fields of the BITMAPINFO data structure contain explicit RGB values or indexes into the currently realized logical palette. The parameter must be one of the following values, with the meaning as given:

•	DIB_PAL_COLORS    The color table consists of an array of 16-bit indexes.

•	DIB_RGB_COLORS    The color table contains literal RGB values.

Remarks

Initializes a brush with the pattern specified by a device-independent bitmap (DIB). The brush can subsequently be selected for any device context that supports raster operations.

To obtain a handle to the DIB, call the Windows GlobalAlloc function to allocate a block of global memory and then fill the memory with the packed DIB. A packed DIB consists of a BITMAPINFO data structure immediately followed by the array of bytes that define the pixels of the bitmap.

The BITMAPINFO structure has the following form:

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER    bmiHeader;
    RGBQUAD             bmiColors[1];
} BITMAPINFO;

Bitmaps used as fill patterns should be 8 pixels by 8 pixels. If the bitmap is larger, Windows creates a fill pattern using only the bits corresponding to the first 8 rows and 8 columns of pixels in the upper-left corner of the bitmap.

When an application selects a two-color DIB pattern brush into a monochrome device context, Windows ignores the colors specified in the DIB and instead displays the pattern brush using the current text and background colors of the device context. Pixels mapped to the first color (at offset 0 in the DIB color table) of the DIB are displayed using the text color. Pixels mapped to the second color (at offset 1 in the color table) are displayed using the background color.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBrush::CreatePatternBrush«, »CBrush::CreateBrushIndirect«, »CBrush::CreateSolidBrush«, »CBrush::CreateHatchBrush«, »CGdiObject::CreateStockObject«, ::CreateDIBPatternBrush, ::GlobalAlloc


  CBrush::CreateHatchBrush

BOOL CreateHatchBrush( int nIndex, COLORREF crColor );

nIndex    Specifies the hatch style of the brush. It can be one of the following values, with the meaning as given:

•	HS_BDIAGONAL    Downward hatch (left to right) at 45 degrees

•	HS_CROSS    Horizontal and vertical crosshatch

•	HS_DIAGCROSS    Crosshatch at 45 degrees

•	HS_FDIAGONAL    Upward hatch (left to right) at 45 degrees

•	HS_HORIZONTAL    Horizontal hatch

•	HS_VERTICAL    Vertical hatch

crColor    Specifies the foreground color of the brush as an RGB color (the color of the hatches).

Remarks

Initializes a brush with the specified hatched pattern and color. The brush can subsequently be selected as the current brush for any device context.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBrush::CreateBrushIndirect«, »CBrush::CreateDIBPatternBrush«, »CBrush::CreatePatternBrush«, »CBrush::CreateSolidBrush«, »CGdiObject::CreateStockObject«, ::CreateHatchBrush


  CBrush::CreatePatternBrush

BOOL CreatePatternBrush( CBitmap* pBitmap );

pBitmap    Identifies a bitmap.

Remarks

Initializes a brush with a pattern specified by a bitmap. The brush can subsequently be selected for any device context that supports raster operations. The bitmap identified by pBitmap is typically initialized by using the »CBitmap::CreateBitmap«, »CBitmap::CreateBitmapIndirect«, »CBitmap::LoadBitmap«, or »CBitmap::CreateCompatibleBitmap« function.

Bitmaps used as fill patterns should be 8 pixels by 8 pixels. If the bitmap is larger, the Windows operating system will only use the bits corresponding to the first 8 rows and columns of pixels in the upper-left corner of the bitmap.

A pattern brush can be deleted without affecting the associated bitmap. This means the bitmap can be used to create any number of pattern brushes.

A brush created using a monochrome bitmap (1 color plane, 1 bit per pixel) is drawn using the current text and background colors. Pixels represented by a bit set to 0 are drawn with the current text color. Pixels represented by a bit set to 1 are drawn with the current background color.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBrush::CreateBrushIndirect«, »CBrush::CreateDIBPatternBrush«, »CBrush::CreateHatchBrush«, »CBrush::CreateSolidBrush«, »CGdiObject::CreateStockObject«, »CBitmap::CreateBitmap«, »CBitmap::CreateBitmapIndirect«, »CBitmap::CreateCompatibleBitmap«, »CBitmap::LoadBitmap«, ::CreatePatternBrush


  CBrush::CreateSolidBrush

BOOL CreateSolidBrush( COLORREF crColor );

crColor    Specifies the color of the brush. The color specifies an RGB value and can be constructed with the RGB macro in WINDOWS.H.

Remarks

Initializes a brush with a specified solid color. The brush can subsequently be selected as the current brush for any device context.

When an application has finished using the brush created by CreateSolidBrush, it should select the brush out of the device context.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CBrush::CreateBrushIndirect«, »CBrush::CreateDIBPatternBrush«, »CBrush::CreateHatchBrush«, »CBrush::CreatePatternBrush«, ::CreateSolidBrush, »CGdiObject::DeleteObject«


  CBrush::FromHandle

static CBrush* PASCAL FromHandle( HBRUSH hBrush );

hBrush    HANDLE to a Windows GDI brush.

Remarks

Returns a pointer to a CBrush object when given a handle to a Windows HBRUSH object. If a CBrush object is not already attached to the handle, a temporary CBrush object is created and attached. This temporary CBrush object is valid only until the next time the application has idle time in its event loop. At this time, all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CBrush object if successful; NULL if not.


CButton
  class CButton : public CWnd

The CButton class provides the functionality of Windows button controls.
A button control is a small, rectangular child window that can be clicked on and off. Buttons can be used alone or in groups and can either be labeled or appear without text. A button typically changes appearance when the user clicks it.

Typical buttons are the check box, radio button, and pushbutton. A CButton object can become any of these, according to the »style« specified at its initialization by the »Create« member function.

In addition, the CBitmapButton class derived from CButton supports creation of button controls labeled with bitmap images instead of text. A CBitmapButton can have separate bitmaps for a button's up, down, focused, and disabled states.

You can create a button control either from a dialog template or directly in your code. In both cases, first call the constructor CButton to construct the CButton object; then call the Create member function to create the Windows button control and attach it to the CButton object.

Construction can be a one-step process in a class derived from CButton. Write a constructor for the derived class and call Create from within the constructor.

If you want to handle Windows notification messages sent by a button control to its parent (usually a class derived from CDialog), add a message-map entry and message-handler member function to the parent class for each message.

Each message-map entry takes the following form:

ON_Notification( id, memberFxn )

Where id specifies the child window ID of the control sending the notification and memberFxn is the name of the parent member function you have written to handle the notification.

The parent's function prototype is as follows:

afx_msg void memberFxn();

Potential message-map entries are:

Map Entry	Sent To Parent When...
ON_BN_CLICKED	The user clicks a button.
ON_BN_DOUBLECLICKED	The user double-clicks a button.
If you create a CButton object from a dialog resource using App Studio, the CButton object is automatically destroyed when the user closes the dialog box.

If you create a CButton object within a window, you may need to destroy it. If you create the CButton object on the heap by using the new function, you must call delete on the object to destroy it when the user closes the Windows button control. If you create the CButton object on the stack, or it is embedded in the parent dialog object, it is destroyed automatically.

#include <afxwin.h>

See Also

»CWnd«, »CComboBox«, »CEdit«, »CListBox«, »CScrollBar«, »CStatic«, »CBitmapButton«, »CDialog«


CButton Class Members
   Class Members

Construction/Destruction — Public Members

»CButton«	Constructs a CButton object.
Initialization — Public Members

»Create«	Creates the Windows button control and attaches it to the CButton object.
Operations — Public Members

»GetState«	Retrieves the check state, highlight state, and focus state of a button control.
»SetState«	Sets the highlighting state of a button control.
»GetCheck«	Retrieves the check state of a button control.
»SetCheck«	Sets the check state of a button control.
»GetButtonStyle«	Retrieves information about the button control style.
»SetButtonStyle«	Changes the style of a button.
Overridables — Public Members

»DrawItem«	Override to draw an owner-drawn CButton object.


CButton Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CButton::CButton

CButton();

Remarks

Constructs a CButton object.

See Also

»CButton::Create«


  CButton::Create

BOOL Create( LPCSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

lpszCaption    Specifies the button control's text.

dwStyle    Specifies the button control's style.

rect    Specifies the button control's size and position. It can be either a CRect object or a RECT structure.

pParentWnd    Specifies the button control's parent window, usually a CDialog or CModalDialog. It must not be NULL.

nID    Specifies the button control's ID.

Remarks

You construct a CButton object in two steps. First call the constructor, then call Create, which creates the Windows button control and attaches it to the CButton object.

If the WS_VISIBLE style is given, Windows sends the button control all the messages required to activate and show the button.

Apply the following window styleswindowstyles to a button control:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

•	WS_GROUP    To group controls

•	WS_TABSTOP    To include the button in the tabbing order

Return Value

Nonzero if successful; otherwise 0.

Apply any combination of »button styles« to the button.

 Button Styles

You can use any combination of the following button styles for dwStyle:

•	BS_AUTOCHECKBOX    Same as a check box, except that an X appears in the check box when the user selects the box; the X disappears the next time the user selects the box.

•	BS_AUTORADIOBUTTON    Same as a radio button, except that when the user selects it, the button automatically highlights itself and removes the selection from any other radio buttons with the same style in the same group.

•	BS_AUTO3STATE    Same as a three-state check box, except that the box changes its state when the user selects it.

•	BS_CHECKBOX    Creates a small square that has text displayed to its right (unless this style is combined with the BS_LEFTTEXT style).

•	BS_DEFPUSHBUTTON    Creates a button that has a heavy black border. The user can select this button by pressing the ENTER key. This style enables the user to quickly select the most likely option (the default option).

•	BS_GROUPBOX    Creates a rectangle in which other buttons can be grouped. Any text associated with this style is displayed in the rectangle's upper-left corner.

•	BS_LEFTTEXT    When combined with a radio-button or check-box style, the text appears on the left side of the radio button or check box.

•	BS_OWNERDRAW    Creates an owner-drawn button. The framework calls the DrawItem member function when a visual aspect of the button has changed.  This style must be set when using the CBitmapButton class.

•	BS_PUSHBUTTON    Creates a pushbutton that posts a WM_COMMAND message to the owner window when the user selects the button.

•	BS_RADIOBUTTON    Creates a small circle that has text displayed to its right (unless this style is combined with the BS_LEFTTEXT style). Radio buttons are usually used in groups of related but mutually exclusive choices.

•	BS_3STATE    Same as a check box, except that the box can be dimmed as well as checked. The dimmed state typically is used to show that a check box has been disabled.

See Also

»CButton::CButton«


  CButton::DrawItem

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

lpDrawItemStruct    A long pointer to a DrawItemStruct structure. The structure contains information about the item to be drawn and the type of drawing required.

Remarks

Called by the framework when a visual aspect of an owner-drawn button has changed. An owner-drawn button has the BS_OWNERDRAW style set. Override this member function to implement drawing for an owner-drawn CButton object. The application should restore all graphics device interface (GDI) objects selected for the display context supplied in lpDrawItemStruct before the member function terminates.

Also see the »BS_« style values.

See Also

»CButton::SetButtonStyle«, WM_DRAWITEM


  CButton::GetButtonStyle

UINT GetButtonStyle() const;

Remarks

Retrieves the window style of CButton. It only returns the »BS_« style values, not any of the other window styles.

See Also

»CButton::SetButtonStyle«, ::GetWindowLong


  CButton::GetCheck

int GetCheck() const;

Remarks

Retrieves the check state of a radio button or check box.

Return Value

The return value from a button control created with the BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON, BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, or BS_3STATE style is one of the following values:

Value	Meaning
0	Button state is unchecked.
1	Button state is checked.
2	Button state is indeterminate (only applies if the button has the BS_3STATE or BS_AUTO3STATE style).
If the button has any other style, the return value is 0.

See Also

»CButton::GetState«, »CButton::SetState«, »CButton::SetCheck«, BM_GETCHECK


  CButton::GetState

UINT GetState() const;

Return Value

Specifies the current state of the button control. You can use the following masks against the return value to extract information about the state:

Mask	Meaning
0x0003	Specifies the check state (radio buttons and check boxes only). A 0 indicates the button is unchecked. A 1 indicates the button is checked. A radio button is checked when it contains a bullet (•). A check box is checked when it contains an X. A 2 indicates the check state is indeterminate (three-state check boxes only). The state of a three-state check box is indeterminate when it contains a halftone pattern.
0x0004	Specifies the highlight state. A nonzero value indicates that the button is highlighted. A button is highlighted when the user clicks and holds the left mouse button. The highlighting is removed when the user releases the mouse button.
0x0008	Specifies the focus state. A nonzero value indicates that the button has the focus.
See Also

»CButton::GetCheck«, »CButton::SetCheck«, »CButton::SetState«, BM_GETSTATE


  CButton::SetButtonStyle

void SetButtonStyle( UINT nStyle, BOOL bRedraw = TRUE );

nStyle    Specifies the button style.

bRedraw    Specifies whether the button is to be redrawn. A nonzero value redraws the button. A 0 value does not redraw the button. The button is redrawn by default.

Remarks

Changes the style of a button.

Use the GetButtonStyle member function to retrieve the button style. The low-order word of the complete button style is the button-specific style.

See Also

»CButton::GetButtonStyle«, BM_SETSTYLE


  CButton::SetCheck

void SetCheck( int nCheck );

nCheck    Specifies the check state. This parameter can be one of the following:

Value	Meaning
0	Set the button state to unchecked.
1	Set the button state to checked.
2	Set the button state to indeterminate. This value can be used only if the button has the BS_3STATE or BS_AUTO3STATE style.
Remarks

Sets or resets the check state of a radio button or check box. This member function has no effect on a pushbutton.

See Also

»CButton::GetCheck«, »CButton::GetState«, »CButton::SetState«,  BM_SETCHECK


  CButton::SetState

void SetState( BOOL bHighlight );

bHighlight    Specifies whether the button is to be highlighted. A nonzero value highlights the button; a 0 value removes any highlighting.

Remarks

Sets the highlighting state of a button control.

Highlighting affects the exterior of a button control. It has no effect on the check state of a radio button or check box.

A button control is automatically highlighted when the user clicks and holds the left mouse button. The highlighting is removed when the user releases the mouse button.

See Also

»CButton::GetState«, »CButton::SetCheck«, »CButton::GetCheck«, BM_SETSTATE


CByteArray
  class CByteArray : public CObject

The CByteArray class supports dynamic arrays of bytes.

The member functions of CByteArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a BYTE.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

BYTE CByteArray::GetAt( int <nIndex> ) const;

CByteArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of bytes is stored to an archive, either with the overloaded insertion (<<) operator or with the Serialize member function, each element is, in turn, serialized.

If you need debug output from individual elements in the array, you must set the depth of the CDumpContext object to 1 or greater.

#include <afxcoll.h>

See Also

»CObArray«


CByteArray Class Members
   Class Members

Construction/Destruction — Public Members

»CByteArray«	Constructs an empty array for bytes.
»~CByteArray«	Destroys a CByteArray object.
Bounds — Public Members

»GetSize«	Gets the number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array not allowed to grow.
»ElementAt«	Returns a temporary reference to the byte within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CClientDC
  class CClientDC : public CDC

The CClientDC class is derived from CDC and takes care of calling the Windows functions GetDC at construction time and ReleaseDC at destruction time. This means that the device context associated with a CClientDC object is the client area of a window.

#include <afxwin.h>

See Also

»CDC«


CClientDC Class Members
   Class Members

Construction/Destruction — Public Members

»CClientDC«	Constructs a CClientDC object connected to the CWnd.
Data Members — Protected Members

»m_hWnd«	The HWND of the window for which this CClientDC is valid.


CClientDC Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CClientDC::CClientDC

CClientDC( CWnd* pWnd )
throw( CResourceException );

pWnd    The window whose client area the device context object will access.

Remarks

Constructs a CClientDC object that accesses the client area of the »CWnd« pointed to by pWnd. The constructor calls the Windows function GetDC.

An exception (of type CResourceException) is thrown if the Windows GetDC call fails. A device context may not be available if Windows has already allocated all of its available device contexts. Your application competes for the five common display contexts available at any given time under Windows.


CClientDC Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CClientDC::m_hWnd

Remarks

The HWND of the CWnd pointer used to construct the CClientDC object. m_hWnd is a protected variable.


CCmdTarget
  class CCmdTarget : public CObject

CCmdTarget is the base class for the Microsoft Foundation Class Library message-map architecture. A message map routes commands or messages to the member functions you write to handle them. (A command is a message from a menu item, command button, or accelerator key.)

Key framework classes derived from CCmdTarget include »CView«, »CWinApp«, »CDocument«, »CWnd«, and »CFrameWnd«. If you intend for a new class to handle messages, derive the class from one of these CCmdTarget-derived classes. You will rarely derive a class from CCmdTarget directly.

For an overview of command targets and OnCmdMsg routing, see Chapter 3, "»Working with Messages and Commands«," in this manual.CCmdTarget includes member functions that handle the display of an hourglass cursor. Display the hourglass cursor when you expect a command to take a noticeable time interval to execute.

include <afxwin.h>

See Also

»CCmdUI«, »CDocument«, »CDocTemplate«, »CWinApp«, »CWnd«, »CView«, »CFrameWnd«


CCmdTarget Class Members
   Class Members

Operations — Public Members

»BeginWaitCursor«	Displays the cursor as an hourglass cursor.
»EndWaitCursor«	Returns to the previous cursor.
»RestoreWaitCursor«	Restores the hourglass cursor.
Overridables — Public Members

»OnCmdMsg«	Routes and dispatches command messages.


CCmdTarget Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CCmdTarget::BeginWaitCursor

void BeginWaitCursor();

Remarks

Call this function to display the cursor as an hourglass when you expect a command to take a noticeable time interval to execute. The framework calls this function to show the user that it is busy, such as when a CDocument object loads or saves itself to a file.

Call EndWaitCursor to restore the previous cursor.

See Also

»CCmdTarget::EndWaitCursor«, »CCmdTarget::RestoreWaitCursor«, »CWinApp::DoWaitCursor«


  CCmdTarget::EndWaitCursor

void EndWaitCursor();

Remarks

Call this function after you have called the BeginWaitCursor member function to return from the hourglass cursor to the previous cursor. The framework also calls this member function after it has invoked the hourglass cursor.

See Also

»CCmdTarget::BeginWaitCursor«, »CCmdTarget::RestoreWaitCursor«, »CWinApp::DoWaitCursor«


  CCmdTarget::OnCmdMsg

virtual BOOL OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo );

nID    Contains the command ID.

nCode    Identifies the command notification code.

pExtra    Used according to the value of nCode.

pHandlerInfo    If not NULL, OnCmdMsg fills in the pHandlerInfo structure with the pTarget and pmf members of the CMDHANDLERINFO structure instead of dispatching the command. Typically, this parameter should be NULL.

Remarks

Called by the framework to route and dispatch command messages and to handle the update of command user-interface objects. This is the main implementation routine of the framework command architecture.

At run time, OnCmdMsg dispatches a command to other objects or handles the command itself by calling the root class CCmdTarget::OnCmdMsg, which does the actual message-map lookup. For a complete description of the default command routing, see Chapter 6 in the Class Library User's Guide.

On rare occasions, you may want to override this member function to extend the framework's standard command routing. Please refer to Technical Note 21 in MSVCNT\HELP\MFCNOTES.HLP for advanced details of the command-routing architecture.

Return Value

Nonzero if the message is handled; otherwise 0.

See Also

»CCmdUI«


  CCmdTarget::RestoreWaitCursor

void RestoreWaitCursor();

Remarks

Call this function to restore the appropriate hourglass cursor after the system cursor has changed (for example, after a message box has opened and then closed while in the middle of a lengthy operation).

See Also

»CCmdTarget::EndWaitCursor«, »CCmdTarget::BeginWaitCursor«, »CWinApp::DoWaitCursor«


CCmdUI
  class CCmdUI

The CCmdUI class is used only within an ON_UPDATE_COMMAND_UI handler in a CCmdTarget-derived class.

When a user of your application pulls down a menu, each menu item needs to know whether it should be displayed as enabled or disabled (dimmed). The target of a menu command provides this information by implementing an ON_UPDATE_COMMAND_UI handler. Use ClassWizard to browse the command user-interface objects in your application and create a message-map entry and function prototype for each handler.

When the menu is pulled down, the framework searches for and calls each ON_UPDATE_COMMAND_UI handler, each handler calls CCmdUI member functions such as Enable and Check, and the framework then appropriately displays each menu item.

A menu item can be replaced with a control-bar button or other command user-interface object without changing the code within the ON_UPDATE_COMMAND_UI handler.

Table R.1 summarizes the effect CCmdUI's member functions have on various command user-interface items.

 Table R.1    Using CCmdUI Member Functions

User-Interface Item	Enable	SetCheck	SetRadio	SetText
Menu item	Enables or disables	Checks (×) or unchecks	Checks using dot (•)	Sets item text
Toolbar button	Enables or disables	Selects,  unselects, or indeterminate	Same as SetCheck	(Not applicable)
Status-bar pane	Makes text visible or invisible	Sets pop-out or normal border	Same as SetCheck	Sets pane text
Normal button in CDialogBar	Enables or disables	Checks or unchecks check box	Same as SetCheck	Sets button text
Normal control in CDialogBar	Enables or disables	(Not applicable)	(Not applicable)	Sets window text
For more on the use of this class, see Chapter 6 in the Class Library User's Guide and Chapter 3, »Working with Messages and Commands«, in this manual.

#include <afxwin.h>

See Also

»CCmdTarget«


CCmdUI Class Members
  Class Members

Operations — Public Members

»Enable«	Enables or disables the user-interface item for this command.
»SetCheck«	Sets the check state of the user-interface item for this command.
»SetRadio«	Like the SetCheck member function, but operates on radio groups.
»SetText«	Sets the text for the user-interface item for this command.
»ContinueRouting«	Tells the command-routing mechanism to continue routing the current message down the chain of handlers.


CCmdUI Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CCmdUI::ContinueRouting

void ContinueRouting();

Remarks

Call this member function to tell the command-routing mechanism to continue routing the current message down the chain of handlers.

This is an advanced member function that should be used in conjunction with an ON_COMMAND_EX handler that returns FALSE. For more information, see Technical Note 21 in MSVCNT\HELP\MFCNOTES.HLP.


  CCmdUI::Enable

virtual void Enable( BOOL bOn = TRUE );

bOn    TRUE to enable the item, FALSE to disable it.

Remarks

Call this member function to enable or disable the user-interface item for this command.

See Also

»CCmdUI::SetCheck«


  CCmdUI::SetCheck

virtual void SetCheck( int nCheck = 1 );

nCheck    Specifies the check state to set. If 0, unchecks; if 1, checks; and if 2, sets indeterminate.

Remarks

Call this member function to set the user-interface item for this command to the appropriate check state. This member function works for menu items and toolbar buttons. The indeterminate state applies only to toolbar buttons.

See Also

»CCmdUI::SetRadio«


  CCmdUI::SetRadio

virtual void SetRadio( BOOL bOn = TRUE );

bOn    TRUE to enable the item; otherwise FALSE.

Remarks

Call this member function to set the user-interface item for this command to the appropriate check state. This member function operates like SetCheck, except that it operates on user-interface items acting as part of a radio group. Unchecking the other items in the group is not automatic unless the items themselves maintain the radio-group behavior.

See Also

»CCmdUI::SetCheck«


  CCmdUI::SetText

virtual void SetText( LPCSTR lpszText );

lpszText    A pointer to a text string.

Remarks

Call this member function to set the text of the user-interface item for this command.

See Also

»CCmdUI::Enable«


CColorDialog
  class CColorDialog : public CDialog

The CColorDialog class allows you to incorporate a color-selection dialog box into your application. A CColorDialog object is a dialog box with a list of colors that are defined for the display system. The user can select or create a particular color from the list, which is then reported back to the application when the dialog box exits.

To construct a CColorDialog object, use the provided constructor or derive a new class and use your own custom constructor.

Once the dialog box has been constructed, you can set or modify any values in the m_cc structure to initialize the values of the dialog box's controls. The m_cc structure is of type CHOOSECOLOR. For more information on this structure, see the Windows Software Development Kit (SDK) documentation.

After initializing the dialog box's controls, call the DoModal member function to display the dialog box and allow the user to select a color. DoModal returns the user's selection of either the dialog box's OK (IDOK) or Cancel (IDCANCEL) button.

If DoModal returns IDOK, you can use one of CColorDialog's member functions to retrieve the information input by the user.

You can use the Windows CommDlgExtendedError function to determine if an error occurred during initialization of the dialog box and to learn more about the error. For more information on this function, see the Windows SDK documentation.

CColorDialog relies on the COMMDLG.DLL file that ships with Windows versions 3.1 and later. For details about redistributing COMMDLG.DLL to Windows version 3.0 users, see the Getting Started manual for the Windows version 3.1 SDK.

To customize the dialog box, derive a class from CColorDialog, provide a custom dialog template, and add a message map to process the notifiction messages from the extended controls. Any unprocessed messages should be passed to the base class.

Customizing the hook function is not required.

Note  On some installations the CColorDialog object will not display with a gray background if you have used the framework to make other CDialog objects gray.

#include <afxdlgs.h>


CColorDialog Class Members
   Class Members

Data Members — Public Members

»clrSavedCustom«	An array of RGB values used to store custom colors.
»m_cc«	A structure used to customize the settings of the dialog box.
Construction/Destruction — Public Members

»CColorDialog«	Constructs a CColorDialog object.
Operations — Public Members

»DoModal«	Displays a color dialog box and allows the user to make a selection.
»GetColor«	Returns a COLORREF structure containing the values of the selected color.
»SetCurrentColor«	Forces the current color selection to the specified color.
Overridables— Protected Members

»OnColorOK«	Override to validate the color entered into the dialog box.


CColorDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CColorDialog::CColorDialog

CColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd* pParentWnd = NULL );

clrInit    The default color selection. If no value is specified, the default is RGB(0,0,0) (black).

dwFlags    A set of flags that customize the function and appearance of the dialog box. For more information, see the CHOOSECOLOR structure in the Windows SDK documentation.

pParentWnd    A pointer to the dialog box's parent or owner window.

Remarks

Constructs a CColorDialog object.

See Also

»CDialog::DoModal«, ::ChooseColor


  CColorDialog::DoModal

virtual int DoModal();

Remarks

Call this function to display the Windows common color dialog box and allow the user to select a color.

If you want to initialize the various color dialog-box options by setting members of the m_cc structure, you should do this before calling DoModal but after the dialog-box object is constructed.

After calling DoModal, you can call other member functions to retrieve the settings or information input by the user into the dialog box.

Return Value

IDOK or IDCANCEL if the function is successful; otherwise 0. IDOK and IDCANCEL are constants that indicate whether the user selected the OK or Cancel button.

If IDCANCEL is returned, you can call the Windows CommDlgExtendedError function to determine if an error occurred.

See Also

»CDialog::DoModal«, »CColorDialog::CColorDialog«


  CColorDialog::GetColor

COLORREF GetColor() const;

Remarks

Call this function after calling DoModal to retrieve the information about the color the user selected.

Return Value

A COLORREF value that contains the RGB information for the color selected in the color dialog box.

See Also

»CColorDialog::SetCurrentColor«


  CColorDialog::OnColorOK

Protected

virtual BOOL OnColorOK(); ♦

Remarks

Override this function only if you want to provide custom validation of the color entered into the dialog box. This function allows you to reject a color entered by a user into a common color dialog box for any application-specific reason. Normally, you do not need to use this function because the framework provides default validation of colors and displays a message box if an invalid color is entered.

Use the GetColor member function to get the RGB value of the color.

If 0 is returned, the dialog box will remain displayed in order for the user to enter another filename.

Return Value

Nonzero if the dialog box should not be dismissed; otherwise 0 to accept the color that was entered.


  CColorDialog::SetCurrentColor

void SetCurrentColor( COLORREF clr );

clr    An RGB color value.

Remarks

Call this function after calling DoModal to force the current color selection to the color value specified in clr. This function is called from within a message handler or OnColorOK. The dialog box will automatically update the user's selection based on the value of the clr parameter.

See Also

»CColorDialog::GetColor«


CColorDialog Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CColorDialog::clrSavedCustom

static COLORREF clrSavedCustom[16];

Remarks

In addition to choosing colors, CColorDialog objects permit the user to define up to 16 custom colors. The clrSavedCustom member is an array of 16 RGB color values that stores these custom colors between invocations of the CColorDialog object. These colors can be retrieved after DoModal returns IDOK.

Each of the 16 RGB values in clrSavedCustom is initialized to  RGB(255,255,255) (white). The clrSavedCustom member only allows you to save custom colors between dialog box invocations within the application. If you wish to save these colors between invocations of the application, you must save them in some other manner, such as in an initialization (.INI) file. Typically, this saving is done in your application's ExitInstance function.


  CColorDialog::m_cc

CHOOSECOLOR m_cc;

Remarks

A structure of type CHOOSECOLOR, whose members store the characteristics and values of the dialog box. After constructing a CColorDialog object, you can use m_cc to set various aspects of the dialog box before calling the DoModal member function.


CComboBox
  class CComboBox : public CWnd

The CComboBox class provides the functionality of a Windows combo box.

A combo box consists of a list box combined with either a static control or edit control. The list-box portion of the control may be displayed at all times or may only drop down when the user selects the drop-down arrow next to the control.

The currently selected item (if any) in the list box is displayed in the static or edit control. In addition, if the combo box has an edit control, the user can type text in the edit control and the list box, if it is visible, will highlight the first selection that matches the typed entry.

The following table compares the three combo-box »styles«:

Style	When Is List Box Visible?	Static or Edit Control?
Simple	Always	Edit
Drop-down	When dropped down	Edit
Drop-down list	When dropped down	Static
You can create a CComboBox object from either a dialog template or directly in your code. In both cases, first call the constructor CComboBox to construct the CComboBox object; then call the »Create« member function to create the control and attach it to the CComboBox object.

If you want to handle Windows notification messages sent by a combo box to its parent (usually a class derived from CDialog), add a message-map entry and message-handler member function to the parent class for each message.

Each message-map entry takes the following form:

ON_Notification( id, memberFxn )

where id specifies the child-window ID of the combo-box control sending the notification and memberFxn is the name of the parent member function you have written to handle the notification.

The parent's function prototype is as follows:

afx_msg void memberFxn();

The order in which certain notifications will be sent cannot be predicted. In particular, a CBN_SELCHANGE notification may occur either before or after a CBN_CLOSEUP notification.

Potential message-map entries are:

Windows 3.1 Only

•	ON_CBN_CLOSEUP    The list box of a combo box has closed. This notification message is not sent for a combo box that has the »CBS_SIMPLE« style. »

•	ON_CBN_DBLCLK    The user double-clicks a string in the list box of a combo box. This notification message is only sent for a combo box with the »CBS_SIMPLE« style. For a combo box with the CBS_DROPDOWN or CBS_DROPDOWNLIST style, a double-click cannot occur because a single click hides the list box.

•	ON_CBN_DROPDOWN    The list box of a combo box is about to drop down (be made visible). This notification message can occur only for a combo box with the »CBS_DROPDOWN« or »CBS_DROPDOWNLIST« style.

•	ON_CBN_EDITCHANGE    The user has taken an action that may have altered the text in the edit-control portion of a combo box. Unlike the CBN_EDITUPDATE message, this message is sent after Windows updates the screen. It is not sent if the combo box has the »CBS_DROPDOWNLIST« style.

•	ON_CBN_EDITUPDATE    The edit-control portion of a combo box is about to display altered text. This notification message is sent after the control has formatted the text but before it displays the text. It is not sent if the combo box has the CBS_DROPDOWNLIST style.

•	ON_CBN_ERRSPACE    The combo box cannot allocate enough memory to meet a specific request.

Windows 3.1 Only

•	ON_CBN_SELENDCANCEL    Indicates the user's selection should be canceled. The user clicks an item and then clicks another window or control to hide the list box of a combo box. This notification message is sent before the CBN_CLOSEUP notification message to indicate that the user's selection should be ignored. The CBN_SELENDCANCEL or CBN_SELENDOK notification message is sent even if the CBN_CLOSEUP notification message is not sent (as in the case of a combo box with the »CBS_SIMPLE« style).

•	ON_CBN_SELENDOK    The user selects an item and then either presses the ENTER key or clicks the DOWN ARROW key to hide the list box of a combo box. This notification message is sent before the CBN_CLOSEUP message to indicate that the user's selection should be considered valid. The CBN_SELENDCANCEL or CBN_SELENDOK notification message is sent even if the CBN_CLOSEUP notification message is not sent (as in the case of a combo box with the »CBS_SIMPLE« style). »

•	ON_CBN_KILLFOCUS    The combo box is losing the input focus.

•	ON_CBN_SELCHANGE    The selection in the list box of a combo box is about to be changed as a result of the user either clicking in the list box or changing the selection by using the arrow keys.

•	ON_CBN_SETFOCUS    The combo box receives the input focus.

If you create a CComboBox object within a dialog box (through a dialog resource with App Studio), the CComboBox object is automatically destroyed when the user closes the dialog box.

If you embed a CComboBox object within another window object, you do not need to destroy it. If you create the CComboBox object on the stack, it is destroyed automatically. If you create the CComboBox object on the heap by using the new function, you must call delete on the object to destroy it when the Windows combo box is destroyed.

#include <afxwin.h>

See Also

»CWnd«, »CButton«, »CEdit«, »CListBox«, »CScrollBar«, »CStatic«, »CDialog«


CComboBox Class Members
   Class Members

Construction/Destruction — Public Members

»CComboBox«	Constructs a CComboBox object.
Initialization — Public Members

»Create«	Creates the combo box and attaches it to the CComboBox object.
General Operations — Public Members

»GetCount«	Retrieves the number of items in the list box of a combo box.
»GetCurSel«	Retrieves the index of the currently selected item, if any, in the list box of a combo box.
»SetCurSel«	Selects a string in the list box of a combo box.
»GetEditSel«	Gets the starting and ending character positions of the current selection in the edit control of a combo box.
»SetEditSel«	Selects characters in the edit control of a combo box.
»SetItemData«	Sets the 32-bit value associated with the specified item in a combo box.
»SetItemDataPtr«	Sets the 32-bit value associated with the specified item in a combo box to the specified pointer (void*).
»GetItemData«	Retrieves the application-supplied 32-bit value associated with the specified combo-box item.
»GetItemDataPtr«	Retrieves the application-supplied 32-bit value associated with the specified combo-box item as a pointer (void*).
»Clear«	Deletes (clears) the current selection (if any) in the edit control.
»Copy«	Copies the current selection (if any) onto the Clipboard in CF_TEXT format.
»Cut«	Deletes (cuts) the current selection, if any, in the edit control and copies the deleted text onto the Clipboard in CF_TEXT format.
»Paste«	Inserts the data from the Clipboard into the edit control at the current cursor position. Data is inserted only if the Clipboard contains data in CF_TEXT format.
»LimitText«	Limits the length of the text that the user may enter into the edit control of a combo box.
»SetItemHeight«	Sets the height of list items in a combo box or the height of the edit-control (or static-text) portion of a combo box.
»GetItemHeight«	Retrieves the height of list items in a combo box.
»GetLBText«	Gets a string from the list box of a combo box.
»GetLBTextLen«	Gets the length of a string in the list box of a combo box.
»ShowDropDown«	Shows or hides the list box of a combo box that has the CBS_DROPDOWN or CBS_DROPDOWNLIST »style«.
»GetDroppedControlRect«	Retrieves the screen coordinates of the visible (dropped-down) list box of a drop-down combo box.
»GetDroppedState«	Determines whether the list box of a drop-down combo box is visible (dropped down).
»SetExtendedUI«	Selects either the default user interface or the extended user interface for a combo box that has the »CBS_DROPDOWN« or »CBS_DROPDOWNLIST« style.
»GetExtendedUI«	Determines whether a combo box has the default user interface or the extended user interface.
String Operations — Public Members

»AddString«	Adds a string to the end of the list in the list box of a combo box or at the sorted position for list boxes with the CBS_SORT style.
»DeleteString«	Deletes a string from the list box of a combo box.
»InsertString«	Inserts a string into the list box of a combo box.
»ResetContent«	Removes all items from the list box and edit control of a combo box.
»Dir«	Adds a list of filenames to the list box of a combo box.
»FindString«	Finds the first string that contains the specified prefix in the list box of a combo box.
»FindStringExact«	Finds the first list-box string (in a combo box) that matches the specified string.
»SelectString«	Searches for a string in the list box of a combo box and, if the string is found, selects the string in the list box and copies the string to the edit control.
Overridables — Public Members

»DrawItem«	Called by the framework when a visual aspect of an owner-draw combo box changes.
»MeasureItem«	Called by the framework to determine combo box dimensions when an owner-draw combo box is created.
»CompareItem«	Called by the framework to determine the relative position of a new list item in a sorted owner-draw combo box.
»DeleteItem«	Called by the framework when a list item is deleted from an owner-draw combo box.


CComboBox Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CComboBox::AddString

int AddString( LPCSTR lpszString );

lpszString    Points to the null-terminated string that is to be added.

Remarks

Adds a string to the list box of a combo box. If the list box was not created with the »CBS_SORT« style, the string is added to the end of the list. Otherwise, the string is inserted into the list, and the list is sorted.

To insert a string into a specific location within the list, use the »InsertString« member function.

Return Value

If the return value is greater than or equal to 0, it is the zero-based index to the string in the list box. The return value is CB_ERR if an error occurs; the return value is CB_ERRSPACE if insufficient space is available to store the new string.

See Also

»CComboBox::InsertString«, »CComboBox::DeleteString«, CB_ADDSTRING


  CComboBox::CComboBox

CComboBox();

Remarks

Constructs a CComboBox object.

See Also

»CComboBox::Create«


  CComboBox::Clear

void Clear();

Remarks

Deletes (clears) the current selection, if any, in the edit control of the combo box.

To delete the current selection and place the deleted contents onto the Clipboard, use the »Cut« member function.

See Also

»CComboBox::Copy«, »CComboBox::Cut«, »CComboBox::Paste«, WM_CLEAR


  CComboBox::CompareItem

virtual int CompareItem( LPCOMPAREITEMSTRUCT lpCompareItemStruct );

lpCompareItemStruct    A long pointer to a COMPAREITEMSTRUCT structure.

Remarks

Called by the framework to determine the relative position of a new item in the list-box portion of a sorted owner-draw combo box. By default, this member function does nothing. If you create an owner-draw combo box with the LBS_SORT style, you must override this member function to assist the framework in sorting new items added to the list box.

Return Value

Indicates the relative position of the two items described in the COMPAREITEMSTRUCT structure. It may be any of the following values:

Value	Meaning
− 1	Item 1 sorts before item 2.
0	Item 1 and item 2 sort the same.
1	Item 1 sorts after item 2.
See »CWnd::OnCompareItem« for a description of COMPAREITEMSTRUCT.

See Also

WM_COMPAREITEM, »CComboBox::DrawItem«, »CComboBox::MeasureItem«, »CComboBox::DeleteItem«


  CComboBox::Copy

void Copy();

Remarks

Copies the current selection, if any, in the edit control of the combo box onto the Clipboard in CF_TEXT format.

See Also

»CComboBox::Clear«, »CComboBox::Cut«, »CComboBox::Paste«, WM_COPY


  CComboBox::Create

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle    Specifies the »style« of the combo box.

rect    Points to the position and size of the combo box. Can be a RECT structure or a CRect object.

pParentWnd    Specifies the combo box's parent window (usually a CDialog). It must not be NULL.

nID    Specifies the combo box's control ID.

Remarks

You construct a CComboBox object in two steps. First call the constructor, then call Create, which creates the Windows combo box and attaches it to the CComboBox object.

When Create executes, Windows sends the »WM_NCCREATE«, »WM_CREATE«, »WM_NCCALCSIZE«, and »WM_GETMINMAXINFO« messages to the combo box.

These messages are handled by default by the »OnNcCreate«, »OnCreate«, »OnNcCalcSize«, and »OnGetMinMaxInfo« member functions in the CWnd base class. To extend the default message handling, derive a class from CComboBox, add a message map to the new class, and override the preceding message-handler member functions. Override OnCreate, for example, to perform needed initialization for a new class.

Apply the following »window styles« to a combo-box control:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

•	WS_VSCROLL    To add vertical scrolling for the list box in the combo box

•	WS_HSCROLL    To add horizontal scrolling for the list box in the combo box

•	WS_GROUP    To group controls

•	WS_TABSTOP    To include the combo box in the tabbing order

Return Value

Nonzero if successful; otherwise 0.

Apply any combination of »combo-box styles« to the combo box.

 Combo-Box Styles

You can use any combination of the following combo-box styles for dwStyle:

•	CBS_AUTOHSCROLL    Automatically scrolls the text in the edit control to the right when the user types a character at the end of the line. If this style is not set, only text that fits within the rectangular boundary is allowed.

•	CBS_DROPDOWN    Similar to CBS_SIMPLE, except that the list box is not displayed unless the user selects an icon next to the edit control.

•	CBS_DROPDOWNLIST    Similar to CBS_DROPDOWN, except that the edit control is replaced by a static-text item that displays the current selection in the list box.

•	CBS_HASSTRINGS    An owner-draw combo box contains items consisting of strings. The combo box maintains the memory and pointers for the strings so the application can use the GetText member function to retrieve the text for a particular item.

•	CBS_OEMCONVERT    Text entered in the combo-box edit control is converted from the ANSI character set to the OEM character set and then back to ANSI. This ensures proper character conversion when the application calls the AnsiToOem Windows function to convert an ANSI string in the combo box to OEM characters. This style is most useful for combo boxes that contain filenames and applies only to combo boxes created with the CBS_SIMPLE or CBS_DROPDOWN styles.

•	CBS_OWNERDRAWFIXED    The owner of the list box is responsible for drawing its contents; the items in the list box are all the same height.

•	CBS_OWNERDRAWVARIABLE    The owner of the list box is responsible for drawing its contents; the items in the list box are variable in height.

•	CBS_SIMPLE    The list box is displayed at all times. The current selection in the list box is displayed in the edit control.

•	CBS_SORT    Automatically sorts strings entered into the list box.

Windows 3.1 Only

•	CBS_DISABLENOSCROLL    The list box shows a disabled vertical scroll bar when the list box does not contain enough items to scroll. Without this style, the scroll bar is hidden when the list box does not contain enough items.

•	CBS_NOINTEGRALHEIGHT    Specifies that the size of the combo box is exactly the size specified by the application when it created the combo box. Normally, Windows sizes a combo box so that the combo box does not display partial items. ♦

See Also

»CComboBox::CComboBox«


  CComboBox::Cut

void Cut();

Remarks

Deletes (cuts) the current selection, if any, in the combo-box edit control and copies the deleted text onto the Clipboard in CF_TEXT format.

To delete the current selection without placing the deleted text onto the Clipboard, call the »Clear« member function.

See Also

»CComboBox::Clear«, »CComboBox::Copy«, »CComboBox::Paste«, WM_CUT


  CComboBox::DeleteItem

virtual void DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct );

lpDeleteItemStruct    A long pointer to a Windows DELETEITEMSTRUCT structure that contains information about the deleted item.

See »CWnd::OnDeleteItem« for a description of this structure.

Remarks

Called by the framework when the user deletes an item from an owner-draw CComboBox object or destroys the combo box. The default implementation of this function does nothing. Override this function to redraw the combo box as needed.

See Also

»CComboBox::CompareItem«, »CComboBox::DrawItem«, »CComboBox::MeasureItem«, WM_DELETEITEM


  CComboBox::DeleteString

int DeleteString( UINT nIndex );

nIndex    Specifies the index to the string that is to be deleted.

Remarks

Deletes a string in the list box of a combo box.

Return Value

If the return value is greater than or equal to 0, then it is a count of the strings remaining in the list. The return value is CB_ERR if nIndex specifies an index greater then the number of items in the list.

See Also

»CComboBox::InsertString«, »CComboBox::AddString«, CB_DELETESTRING


  CComboBox::Dir

int Dir( UINT attr, LPCSTR lpszWildCard );

attr    Can be any combination of the enum values described in »CFile::GetStatus« or any combination of the following values:

•	DDL_READWRITE    File can be read from or written to.

•	DDL_READONLY    File can be read from but not written to.

•	DDL_HIDDEN    File is hidden and does not appear in a directory listing.

•	DDL_SYSTEM    File is a system file.

•	DDL_DIRECTORY    The name specified by lpszWildCard specifies a directory.

•	DDL_ARCHIVE    File has been archived.

•	DDL_DRIVES    Include all drives that match the name specified by lpszWildCard.

•	DDL_EXCLUSIVE    Exclusive flag. If the exclusive flag is set, only files of the specified type are listed. Otherwise, files of the specified type are listed in addition to "normal" files.

lpszWildCard    Points to a file-specification string. The string can contain wildcards (for example, *.*).

Remarks

Adds a list of filenames and/or drives to the list box of a combo box.

Return Value

If the return value is greater than or equal to 0, it is the zero-based index of the last filename added to the list. The return value is CB_ERR if an error occurs; the return value is CB_ERRSPACE if insufficient space is available to store the new strings.

See Also

»CWnd::DlgDirList«, CB_DIR, »CFile::GetStatus«


  CComboBox::DrawItem

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

lpDrawItemStruct    A pointer to a DRAWITEMSTRUCT structure that contains information about the type of drawing required.

Remarks

Called by the framework when a visual aspect of an owner-draw combo box changes. The itemAction member of the DRAWITEMSTRUCT structure defines the drawing action that is to be performed.

See »CWnd::OnDrawItem« for a description of this structure.

By default, this member function does nothing. Override this member function to implement drawing for an owner-draw CComboBox object. Before this member function terminates, the application should restore all graphics device interface (GDI) objects selected for the display context supplied in lpDrawItemStruct.

See Also

»CComboBox::CompareItem«, ::DrawItem, »CComboBox::MeasureItem«, »CComboBox::DeleteItem«


  CComboBox::FindString

int FindString( int nStartAfter, LPCSTR lpszString ) const;

nStartAfter    Contains the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nStartAfter. If −1, the entire list box is searched from the beginning.

lpszString    Points to the null-terminated string that contains the prefix to search for. The search is case independent, so this string may contain any combination of uppercase and lowercase letters.

Remarks

Finds, but doesn't select, the first string that contains the specified prefix in the list box of a combo box.

Return Value

If the return value is greater than or equal to 0, it is the zero-based index of the matching item. It is CB_ERR if the search was unsuccessful.

See Also

»CComboBox::SelectString«, »CComboBox::SetCurSel«, CB_FINDSTRING


  CComboBox::FindStringExact

Windows 3.1 Only

int FindStringExact( int nIndexStart, LPCSTR lpszFind ) const; ♦

nIndexStart    Specifies the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nIndexStart. If nIndexStart is −1, the entire list box is searched from the beginning.

lpszFind    Points to the null-terminated string to search for. This string can contain a complete filename, including the extension. The search is not case sensitive, so this string can contain any combination of uppercase and lowercase letters.

Remarks

Call the FindStringExact member function to find the first list-box string (in a combo box) that matches the string specified in lpszFind.

If the combo box was created with an owner-draw style but without the »CBS_HASSTRINGS« style, FindStringExact attempts to match the doubleword value against the value of lpszFind.

Return Value

The zero-based index of the matching item, or CB_ERR if the search was unsuccessful.

See Also

»CComboBox::FindString«, CB_FINDSTRINGEXACT


  CComboBox::GetCount

int GetCount() const;

Return Value

The number of items in the list box of a combo box. The returned count is one greater then the index value of the last item (the index is zero-based). It is CB_ERR if an error occurs.

See Also

CB_GETCOUNT


  CComboBox::GetCurSel

int GetCurSel() const;

Return Value

The zero-based index of the currently selected item in the list box of a combo box, or CB_ERR if no item is selected.

See Also

»CComboBox::SetCurSel«, CB_GETCURSEL


  CComboBox::GetDroppedControlRect

Windows 3.1 Only

void GetDroppedControlRect( LPRECT lprect ) const; ♦

lprect    Points to the RECT structure that is to receive the coordinates.

Remarks

Call the GetDroppedControlRect member function to retrieve the screen coordinates of the visible (dropped-down) list box of a drop-down combo box.

See Also

CB_GETDROPPEDCONTROLRECT


  CComboBox::GetDroppedState

Windows 3.1 Only

BOOL GetDroppedState() const; ♦

Remarks

Call the GetDroppedState member function to determine whether the list box of a drop-down combo box is visible (dropped down).

Return Value

Nonzero if the listbox is visible; otherwise 0.

See Also

CB_SHOWDROPDOWN, CB_SHOWDROPDOWN, CB_GETDROPPEDSTATE


  CComboBox::GetEditSel

DWORD GetEditSel() const;

Remarks

Gets the starting and ending character positions of the current selection in the edit control of a combo box.

Return Value

A 32-bit value that contains the starting position in the low-order word and the position of the first nonselected character after the end of the selection in the high-order word. If this function is used on a combo box without an edit control, CB_ERR is returned.

See Also

»CComboBox::SetEditSel«, CB_GETEDITSEL


  CComboBox::GetExtendedUI

Windows 3.1 Only

BOOL GetExtendedUI() const; ♦

Remarks

Call the GetExtendedUI member function to determine whether a combo box has the default user interface or the extended user interface. The extended user interface can be identified in the following ways:

•	Clicking the static control displays the list box only for combo boxes with the »CBS_DROPDOWNLIST« style.

•	Pressing the DOWN ARROW key displays the list box (F4 is disabled).

•	Scrolling in the static control is disabled when the item list is not visible (arrow keys are disabled).

Return Value

Nonzero if the combo box has the extended user interface; otherwise 0.

See Also

»CComboBox::SetExtendedUI«, CB_GETEXTENDEDUI


  CComboBox::GetItemData

DWORD GetItemData( int nIndex ) const;

nIndex    Contains the zero-based index of an item in the combo box's list box.

Remarks

Retrieves the application-supplied 32-bit value associated with the specified combo-box item. The 32-bit value can be set with the dwItemData parameter of a »SetItemData« member function call. Use the GetItemDataPtr member function if the 32-bit value to be retrieved is a pointer (void*).

Return Value

The 32-bit value associated with the item, or CB_ERR if an error occurs.

See Also

»CComboBox::SetItemData«, »CComboBox::GetItemDataPtr«, »CComboBox::SetItemDataPtr«, CB_GETITEMDATA


  CComboBox::GetItemDataPtr

void* GetItemDataPtr( int nIndex ) const;

nIndex    Contains the zero-based index of an item in the combo box's list box.

Remarks

Retrieves the application-supplied 32-bit value associated with the specified combo-box item as a pointer (void*).

Return Value

Retrieves a pointer, or −1 if an error occurs.

See Also

»CComboBox::SetItemDataPtr«, »CComboBox::GetItemData«, »CComboBox::SetItemData«, CB_GETITEMDATA


  CComboBox::GetItemHeight

Windows 3.1 Only

int GetItemHeight( int nIndex ) const; ♦

nIndex    Specifies the component of the combo box whose height is to be retrieved. If the nIndex parameter is −1, the height of the edit-control (or static-text) portion of the combo box is retrieved. If the combo box has the CBS_OWNERDRAWVARIABLE style, nIndex specifies the zero-based index of the list item whose height is to be retrieved. Otherwise, nIndex should be set to 0.

Remarks

Call the GetItemHeight member function to retrieve the height of list items in a combo box.

Return Value

The height, in pixels, of the specified item in a combo box. The return value is CB_ERR if an error occurs.

See Also

»CComboBox::SetItemHeight«, WM_MEASUREITEM, CB_GETITEMHEIGHT


  CComboBox::GetLBText

int GetLBText( int nIndex, LPSTR lpszText ) const;

void GetLBText( int nIndex, CString& rString ) const;

nIndex    Contains the zero-based index of the list-box string to be copied.

lpszText    Points to a buffer that is to receive the string. The buffer must have sufficient space for the string and a terminating null character.

rString    A reference to a CString.

Remarks

Gets a string from the list box of a combo box. The second form of this member function fills a CString object with the item's text.

Return Value

The length (in bytes) of the string, excluding the terminating null character. If nIndex does not specify a valid index, the return value is CB_ERR.

See Also

»CComboBox::GetLBTextLen«, CB_GETLBTEXT


  CComboBox::GetLBTextLen

int GetLBTextLen( int nIndex ) const;

nIndex    Contains the zero-based index of the list-box string.

Remarks

Gets the length of a string in the list box of a combo box.

Return Value

The length of the string in bytes, excluding the terminating null character. If nIndex does not specify a valid index, the return value is CB_ERR.

See Also

»CComboBox::GetLBText«, CB_GETLBTEXTLEN


  CComboBox::InsertString

int InsertString( int nIndex, LPCSTR lpszString );

nIndex    Contains the zero-based index to the position in the list box that will receive the string. If this parameter is −1, the string is added to the end of the list.

lpszString    Points to the null-terminated string that is to be inserted.

Remarks

Inserts a string into the list box of a combo box. Unlike the »AddString« member function, the InsertString member function does not cause a list with the »CBS_SORT« style to be sorted.

Return Value

The zero-based index of the position at which the string was inserted. The return value is CB_ERR if an error occurs. The return value is CB_ERRSPACE if insufficient space is available to store the new string.

See Also

»CComboBox::AddString«, »CComboBox::DeleteString«, »CComboBox::ResetContent«, CB_INSERTSTRING


  CComboBox::LimitText

BOOL LimitText( int nMaxChars );

nMaxChars    Specifies the length (in bytes) of the text that the user can enter. If this parameter is 0, the text length is set to 65,535 bytes.

Remarks

Limits the length in bytes of the text that the user can enter into the edit control of a combo box.

If the combo box does not have the style »CBS_AUTOHSCROLL«, setting the text limit to be larger than the size of the edit control will have no effect.

LimitText only limits the text the user can enter. It has no effect on any text already in the edit control when the message is sent, nor does it affect the length of the text copied to the edit control when a string in the list box is selected.

Return Value

Nonzero if successful. If called for a combo box with the style »CBS_DROPDOWNLIST« or for a combo box without an edit control, the return value is CB_ERR.

See Also

CB_LIMITTEXT


  CComboBox::MeasureItem

virtual void MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct );

lpMeasureItemStruct    A long pointer to a MEASUREITEMSTRUCT structure.

Remarks

Called by the framework when a combo box with an owner-draw style is created.

By default, this member function does nothing. Override this member function and fill in the MEASUREITEM structure to inform Windows of the dimensions of the list box in the combo box. If the combo box is created with the CBS_OWNERDRAWVARIABLE style, the framework calls this member function for each item in the list box. Otherwise, this member is called only once.

Using the CBS_OWNERDRAWFIXED style in an owner-draw combo box created with the SubclassDlgItem member function of CWnd involves further programming considerations. See the discussion in Technical Note 14 in MSVCNT\HELP\MFCNOTES.HLP.

See »CWnd::OnMeasureItem« for a description of the MEASUREITEMSTRUCT structure.

See Also

»CComboBox::CompareItem«, »CComboBox::DrawItem«, ::MeasureItem, »CComboBox::DeleteItem«


  CComboBox::Paste

void Paste();

Remarks

Inserts the data from the Clipboard into the edit control of the combo box at the current cursor position. Data is inserted only if the Clipboard contains data in CF_TEXT format.

See Also

»CComboBox::Clear«, »CComboBox::Copy«, »CComboBox::Cut«, WM_PASTE


  CComboBox::ResetContent

void ResetContent();

Remarks

Removes all items from the list box and edit control of a combo box.

See Also

CB_RESETCONTENT


  CComboBox::SelectString

int SelectString( int nStartAfter, LPCSTR lpszString );

nStartAfter    Contains the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nStartAfter. If −1, the entire list box is searched from the beginning.

lpszString    Points to the null-terminated string that contains the prefix to search for. The search is case independent, so this string may contain any combination of uppercase and lowercase letters.

Remarks

Searches for a string in the list box of a combo box, and if the string is found, selects the string in the list box and copies it to the edit control.

A string is selected only if its initial characters (from the starting point) match the characters in the prefix string.

Note that the SelectString and FindString member functions both find a string, but the SelectString member function also selects the string.

Return Value

The zero-based index of the selected item if the string was found. If the search was unsuccessful, the return value is CB_ERR and the current selection is not changed.

See Also

»CComboBox::FindString«, CB_SELECTSTRING


  CComboBox::SetCurSel

int SetCurSel( int nSelect );

nSelect    Specifies the zero-based index of the string to select. If −1, any current selection in the list box is removed and the edit control is cleared.

Remarks

Selects a string in the list box of a combo box. If necessary, the list box scrolls the string into view (if the list box is visible). The text in the edit control of the combo box is changed to reflect the new selection. Any previous selection in the list box is removed.

Return Value

The zero-based index of the item selected if the message is successful. The return value is CB_ERR if nSelect is greater than the number of items in the list or if nSelect is set to −1, which clears the selection.

See Also

»CComboBox::GetCurSel«, CB_SETCURSEL


  CComboBox::SetEditSel

BOOL SetEditSel( int nStartChar, int nEndChar );

nStartChar    Specifies the starting position. If the starting position is set to −1, then any existing selection is removed.

nEndChar    Specifies the ending position. If the ending position is set to −1, then all text from the starting position to the last character in the edit control is selected.

Remarks

Selects characters in the edit control of a combo box.

The positions are zero-based. To select the first character of the edit control, you specify a starting position of 0. The ending position is for the character just after the last character to select. For example, to select the first four characters of the edit control, you would use a starting position of 0 and an ending position of 4.

Return Value

Nonzero if the member function is successful; otherwise 0. It is CB_ERR if CComboBox has the »CBS_DROPDOWNLIST« style or doesn't have a list box.

See Also

»CComboBox::GetEditSel«, CB_SETEDITSEL


  CComboBox::SetExtendedUI

Windows 3.1 Only

int SetExtendedUI( BOOL bExtended = TRUE ); ♦

bExtended    Specifies whether the combo box should use the extended user interface or the default user interface. A value of TRUE selects the extended user interface; a value of FALSE selects the standard user interface.

Remarks

Call the SetExtendedUI member function to select either the default user interface or the extended user interface for a combo box that has the »CBS_DROPDOWN« or »CBS_DROPDOWNLIST« style.

The extended user interface can be identified in the following ways:

•	Clicking the static control displays the list box only for combo boxes with the CBS_DROPDOWNLIST style.

•	Pressing the DOWN ARROW key displays the list box (F4 is disabled).

•	Scrolling in the static control is disabled when the item list is not visible (the arrow keys are disabled).

Return Value

CB_OKAY if the operation is successful, or CB_ERR if an error occurs.

See Also

»CComboBox::GetExtendedUI«, CB_SETEXTENDEDUI


  CComboBox::SetItemData

int SetItemData( int nIndex, DWORD dwItemData );

nIndex    Contains a zero-based index to the item to set.

dwItemData    Contains the new value to associate with the item.

Remarks

Sets the 32-bit value associated with the specified item in a combo box. Use the SetItemDataPtr member function if the 32-bit item is to be a pointer.

Return Value

CB_ERR if an error occurs.

See Also

»CComboBox::GetItemData«, »CComboBox::GetItemDataPtr«, »CComboBox::SetItemDataPtr«, CB_SETITEMDATA, »CComboBox::AddString«, »CComboBox::InsertString«


  CComboBox::SetItemDataPtr

int SetItemDataPtr( int nIndex, void* pData );

nIndex    Contains a zero-based index to the item.

pData    Contains the pointer to associate with the item.

Remarks

Sets the 32-bit value associated with the specified item in a combo box to be the specified pointer (void*).

Return Value

CB_ERR if an error occurs.

See Also

»CComboBox::GetItemData«, »CComboBox::GetItemDataPtr«, »CComboBox::SetItemData«, CB_SETITEMDATA, »CComboBox::AddString«, »CComboBox::InsertString«


  CComboBox::SetItemHeight

Windows 3.1 Only

int SetItemHeight( int nIndex, UINT cyItemHeight ); ♦

nIndex    Specifies whether the height of list items or the height of the edit-control (or static-text) portion of the combo box is set.

If the combo box has the CBS_OWNERDRAWVARIABLE style, nIndex specifies the zero-based index of the list item whose height is to be set; otherwise, nIndex must be 0 and the height of all list items will be set.

If nIndex is −1, the height of the edit-control or static-text portion of the combo box is to be set.

cyItemHeight    Specifies the height, in pixels, of the combo-box component identified by nIndex.

Remarks

Call the SetItemHeight member function to set the height of list items in a combo box or the height of the edit-control (or static-text) portion of a combo box.

The height of the edit-control (or static-text) portion of the combo box is set independently of the height of the list items. An application must ensure that the height of the edit-control (or static-text) portion isn't smaller than the height of a particular list-box item.

Return Value

CB_ERR if the index or height is invalid; otherwise 0.

See Also

»CComboBox::GetItemHeight«, WM_MEASUREITEM, CB_SETITEMHEIGHT


  CComboBox::ShowDropDown

void ShowDropDown( BOOL bShowIt = TRUE );

bShowIt    Specifies whether the drop-down list box is to be shown or hidden. A value of TRUE shows the list box. A value of FALSE hides the list box.

Remarks

Shows or hides the list box of a combo box that has the »CBS_DROPDOWN« or »CBS_DROPDOWNLIST« style. By default, a combo box of this style will show the list box.

This member function has no effect on a combo box created with the »CBS_SIMPLE« style.

See Also

CB_SHOWDROPDOWN


CControlBar
  class CControlBar : public CWnd

CControlBar is the base class for the control-bar classes CStatusBar, CToolBar, and CDialogBar. A control bar is a window that is usually aligned to the top or bottom of a frame window. It may contain child items that are either HWND-based controls, which are Windows windows that generate and respond to Windows messages, or non-HWND-based items, which are not windows and are managed by application code or framework code. List boxes and edit controls are examples of HWND-based controls; status-bar panes and bitmap buttons are examples of non-HWND-based controls.

Control-bar windows are usually child windows of a parent frame window and are usually "siblings" to the client view or MDI client of the frame window. A CControlBar object uses information about the parent window's client rectangle to position itself. It then informs the parent window as to how much space remains unallocated in the parent window's client area.

#include <afxext.h>

See Also

»CStatusBar«, »CToolBar«, »CDialogBar«


CControlBar  Class Members
   Class Members

Data Members— Public Members

»m_bAutoDelete«	If nonzero, the CControlBar object is deleted when the Windows control bar is destroyed.
Attributes — Public Members

»GetCount«	Returns the number of non-HWND elements in the control bar.


CControlBar Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CControlBar::GetCount

int GetCount();

Remarks

Returns the number of non-HWND items on the CControlBar object. The type of the item depends on the derived object: panes for CStatusBar objects, and buttons and separators for CToolBar objects.

Return Value

The number of non-HWND items on the CControlBar object. This function returns 0 for a CDialogBar object.

See Also

»CToolBar::SetButtons«, »CStatusBar::SetIndicators«


CControlBar Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CControlBar::m_bAutoDelete

Remarks

m_bAutoDelete is a public variable of type BOOL. If it is nonzero when the Windows control-bar object is destroyed, the CControlBar object is deleted.

A control-bar object is usually embedded in a frame-window object. In this case, m_bAutoDelete is 0 because the embedded control-bar object is destroyed when the frame window is destroyed.

Set this variable to a nonzero value if you allocate a CControlBar object on the heap and you do not plan to call delete.

See Also

»CWnd::DestroyWindow«


CCreateContext
  struct CCreateContext

The framework uses the CCreateContext structure when it creates the frame windows and views associated with a document. When creating a window, the values in this structure provide information used to connect the components that make up a document and the view of its data. You will only need to use CCreateContext if you are overriding parts of the creation process.

A CCreateContext structure contains pointers to the document, the frame window, the view, and the document template. It also contains a pointer to a CRuntimeClass that identifies the type of view to create. The run-time class information and the current document pointer are used to create a new view dynamically. The following table suggests how and when each CCreateContext member might be used:

Member	What It Is For
m_pNewViewClass	CRuntimeClass of the new view to create.
m_pCurrentDoc	The existing document to be associated with the new view.
m_pNewDocTemplate	The document template associated with the creation of a new MDI frame window.
m_pLastView	The original view upon which additional views are modeled, as in the creation of a splitter window's views or the creation of a second view on a document.
m_pCurrentFrame	The frame window upon which additional frame windows are modeled, as in the creation of a second frame window on a document.
When a document template creates a document and its associated components, it validates the information stored in the CCreateContext structure. For example, a view should not be created for a nonexistent document.

Note  All of the pointers in CCreateContext are optional and may be NULL if unspecified or unknown.

CCreateContext is used by the member functions listed under "See Also." Consult the descriptions of these functions for specific information if you plan to override them.

Here are a few general guidelines:

•	When passed as an argument for window creation, as in CWnd::Create, CFrameWnd::Create, and CFrameWnd::LoadFrame, the create context specifies what the new window should be connected to. For most windows, the entire structure is optional and a NULL pointer may be passed.

•	For overridable member functions, such as CFrameWnd::OnCreateClient, the CCreateContext argument is optional.

•	For member functions involved in view creation, you must provide enough information to create the view. For example, for the first view in a splitter window, you must supply the view class information and the current document.

In general, if you use the framework defaults, you can ignore CCreateContext. If you attempt more advanced modifications, the Microsoft Foundation Class Library source code or the sample programs, such as VIEWEX, will guide you.  If you do forget a required parameter, a framework assertion will tell you what you forgot.

#include <afxext.h>

See Also

»CFrameWnd::Create«, »CFrameWnd::LoadFrame«, »CFrameWnd::OnCreateClient«, »CSplitterWnd::Create«, »CSplitterWnd::CreateView«, »CWnd::Create«


CDataExchange
  class CDataExchange

The CDataExchange class supports the dialog data exchange (DDX) and dialog data validation (DDV) routines used by the Microsoft Foundation classes. Use this class if you are writing data exchange routines for custom data types or controls, or if you are writing your own data validation routines. For more information on writing your own DDX and DDV routines, see Technical Note 26 in MSVCNT\HELP\MFCNOTES.HLP. For an overview of DDX and DDV, see the App Studio User's Guide.

A CDataExchange object provides the context information needed for DDX and DDV to take place. The flag m_bSaveAndValidate is FALSE when DDX is used to fill the initial values of dialog controls from data members. The flag m_bSaveAndValidate is TRUE when DDX is used to set the current values of dialog controls into data members and when DDV is used to validate the data values. If the DDV validation fails, the DDV procedure will display a message box explaining the input error. The DDV procedure will then call Fail to reset the focus to the offending control and throw an exception to stop the validation process.

See Also

»CWnd::DoDataExchange«, »CWnd::UpdateData«


CDataExchange Class Members
   Class Members

Data Members

m_bSaveAndValidate	Flag for the direction of DDX and DDV.
m_pDlgWnd	The dialog box or window where the data exchange takes place.
Operations — Public Members

PrepareCtrl	Prepares the specified control for data exchange or validation. Use for nonedit controls.
PrepareEditCtrl	Prepares the specified edit control for data exchange or validation.
Fail	Called when validation fails. Resets focus to the previous control and throws an exception.


CDC
  class CDC : public CObject

The CDC class defines a class of device-context objects. The CDC object provides member functions for working with a device context, such as a display or printer, as well as members for working with a display context associated with the client area of a window.

Do all drawing through the member functions of a CDC object. The class provides member functions for device-context operations, working with drawing tools, type-safe graphics device interface (GDI) object selection, and working with colors and palettes. It also provides member functions for getting and setting drawing attributes, mapping, working with the viewport, working with the window extent, converting coordinates, working with regions, clipping, drawing lines, and drawing simple shapes, ellipses, and polygons. Member functions are also provided for drawing text, working with fonts, using printer escapes, scrolling, and playing metafiles.

To use a CDC object, construct it, and then call its member functions, which parallel Windows functions that use device contexts or display contexts.

For specific uses, the Microsoft Foundation Class Library provides several classes derived from CDC . CPaintDC encapsulates calls to BeginPaint and EndPaint. CClientDC manages a display context associated with a window's client area. CWindowDC manages a display context associated with an entire window, including its frame and controls. CMetaFileDC associates a device context with a metafile.

CDC contains two device contexts, »m_hDC« and »m_hAttribDC«, which, on creation of a CDC object, refer to the same device. CDC directs all output GDI calls to m_hDC and most attribute GDI calls to m_hAttribDC. (An example of an attribute call is GetTextColor, while SetTextColor is an output call.)

 The framework uses these two device contexts to, for example, implement a CMetaFileDC object that will send output to a metafile while reading attributes from a physical device. Print preview is implemented in the framework in a similar fashion. You can also use the two device contexts in a similar way in your application-specific code.

There are times when you may need text-metric information from both the m_hDC and m_hAttribDC device contexts. The following pairs of functions provide this capability:

Uses m_hAttribDC	Uses m_hDC
»GetTextExtent«	»GetOutputTextExtent«
»GetTabbedTextExtent«	»GetOutputTabbedTextExtent«
»GetTextMetrics«	»GetOutputTextMetrics«
»GetCharWidth«	»GetOutputCharWidth«
See Also

»CPaintDC«, »CWindowDC«, »CClientDC«, »CMetaFileDC«


CDC Class Members
Class Members

Data Members — Public Members

»m_hDC«	The output-device context used by this CDC object.
»m_hAttribDC«	The attribute-device context used by this CDC object.
Construction/Destruction — Public Members

»CDC«	Constructs a CDC object.
Initialization — Public Members

»CreateDC«	Creates a device context for a specific device.
»CreateIC«	Creates an information context for a specific device. This provides a fast way to get information about the device without creating a device context.
»CreateCompatibleDC«	Creates a memory-device context that is compatible with another device context. You can use it to prepare images in memory.
»DeleteDC«	Deletes the Windows device context associated with this CDC object.
»FromHandle«	Returns a pointer to a CDC object when given a handle to a device context. If a CDC object is not attached to the handle, a temporary CDC object is created and attached.
»DeleteTempMap«	Called by the CWinApp idle-time handler to delete any temporary CDC object created by FromHandle. Also detaches the device context.
»Attach«	Attaches a Windows device context to this CDC object.
»Detach«	Detaches the Windows device context from this CDC object.
»SetAttribDC«	Sets m_hAttribDC, the attribute device context.
»SetOutputDC«	Sets m_hDC, the output device context.
»ReleaseAttribDC«	Releases m_hAttribDC, the attribute device context.
»ReleaseOutputDC«	Releases m_hDC, the output device context.
Device-Context Functions — Public Members

»GetSafeHdc«	Returns »m_hDC«, the output device context.
»SaveDC«	Saves the current state of the device context.
»RestoreDC«	Restores the device context to a previous state saved with SaveDC.
»ResetDC«	Updates the m_hAttribDC device context.
»GetDeviceCaps«	Retrieves a specified kind of device-specific information about a given display device's capabilities.
»IsPrinting«	Determines if the device context is being used for printing.
Drawing-Tool Functions — Public Members

»GetBrushOrg«	Retrieves the origin of the current brush.
»SetBrushOrg«	Specifies the origin for the next brush selected into a device context.
»EnumObjects«	Enumerates the pens and brushes available in a device context.
Type-Safe Selection Helpers — Public Members

»SelectObject«	Selects a GDI drawing object such as a pen.
»SelectStockObject«	Selects one of the predefined stock pens, brushes, or fonts provided by Windows.
Color and Color Palette Functions — Public Members

»GetNearestColor«	Retrieves the closest logical color to a specified logical color that the given device can represent.
»SelectPalette«	Selects the logical palette.
»RealizePalette«	Maps palette entries in the current logical palette to the system palette.
»UpdateColors«	Updates the client area of the device context by matching the current colors in the client area to the system palette on a pixel-by-pixel basis.
Drawing-Attribute Functions — Public Members

»GetBkColor«	Retrieves the current background color.
»SetBkColor«	Sets the current background color.
»GetBkMode«	Retrieves the background mode.
»SetBkMode«	Sets the background mode.
»GetPolyFillMode«	Retrieves the current polygon-filling mode.
»SetPolyFillMode«	Sets the polygon-filling mode.
»GetROP2«	Retrieves the current drawing mode.
»SetROP2«	Sets the current drawing mode.
»GetStretchBltMode«	Retrieves the current bitmap-stretching mode.
»SetStretchBltMode«	Sets the bitmap-stretching mode.
»GetTextColor«	Retrieves the current text color.
»SetTextColor«	Sets the text color.
Mapping Functions — Public Members

»GetMapMode«	Retrieves the current mapping mode.
»SetMapMode«	Sets the current mapping mode.
»GetViewportOrg«	Retrieves the x- and y-coordinates of the viewport origin.
»SetViewportOrg«	Sets the viewport origin.
»OffsetViewportOrg«	Modifies the viewport origin relative to the coordinates of the current viewport origin.
»GetViewportExt«	Retrieves the x- and y-extents of the viewport.
»SetViewportExt«	Sets the x- and y-extents of the viewport.
»ScaleViewportExt«	Modifies the viewport extent relative to the current values.
»GetWindowOrg«	Retrieves the x- and y-coordinates of the origin of the associated window.
»SetWindowOrg«	Sets the window origin of the device context.
»OffsetWindowOrg«	Modifies the window origin relative to the coordinates of the current window origin.
»GetWindowExt«	Retrieves the x- and y-extents of the associated window.
»SetWindowExt«	Sets the x- and y-extents of the associated window.
»ScaleWindowExt«	Modifies the window extents relative to the current values.
Coordinate Functions — Public Members

»DPtoLP«	Converts device points or rectangles into logical points or rectangles.
»LPtoDP«	Converts logical points or rectangles into device points or rectangles.
Region Functions — Public Members

»FillRgn«	Fills a specific region with the specified brush.
»FrameRgn«	Draws a border around a specific region using a brush.
»InvertRgn«	Inverts the colors in a region.
»PaintRgn«	Fills a region with the selected brush.
Clipping Functions — Public Members

»SetBoundsRect«	Controls the accumulation of bounding-rectangle information for the specified device context.
»GetBoundsRect«	Returns the current accumulated bounding rectangle for the specified device context.
»GetClipBox«	Retrieves the dimensions of the tightest bounding rectangle around the current clipping boundary.
»SelectClipRgn«	Selects the given region as the current clipping region.
»ExcludeClipRect«	Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.
»ExcludeUpdateRgn«	Prevents drawing within invalid areas of a window by excluding an updated region in the window from a clipping region.
»IntersectClipRect«	Creates a new clipping region by forming the intersection of the current region and a rectangle.
»OffsetClipRgn«	Moves the clipping region of the given device.
»PtVisible«	Specifies whether the given point is within the clipping region.
»RectVisible«	Determines whether any part of the given rectangle lies within the clipping region.
Line-Output Functions — Public Members

»GetCurrentPosition«	Retrieves the current position of the pen (in logical coordinates).
»MoveTo«	Moves the current position.
»LineTo«	Draws a line from the current position up to, but not including, a point.
»Arc«	Draws an elliptical arc.
»Polyline«	Draws a set of line segments connecting the specified points.
Simple Drawing Functions — Public Members

»FillRect«	Fills a given rectangle by using a specific brush.
»FrameRect«	Draws a border around a rectangle.
»InvertRect«	Inverts the contents of a rectangle.
»DrawIcon«	Draws an icon.
Ellipse and Polygon Functions — Public Members

»Chord«	Draws a chord (a closed figure bounded by the intersection of an ellipse and a line segment).
»DrawFocusRect«	Draws a rectangle in the style used to indicate focus.
»Ellipse«	Draws an ellipse.
»Pie«	Draws a pie-shaped wedge.
»Polygon«	Draws a polygon consisting of two or more points (vertices) connected by lines.
»PolyPolygon«	Creates two or more polygons that are filled using the current polygon-filling mode. The polygons may be disjoint or they may overlap.
»Rectangle«	Draws a rectangle using the current pen and fills it using the current brush.
»RoundRect«	Draws a rectangle with rounded corners using the current pen and filled using the current brush.
Bitmap Functions — Public Members

»PatBlt«	Creates a bit pattern.
»BitBlt«	Copies a bitmap from a specified device context.
»StretchBlt«	Moves a bitmap from a source rectangle and device into a destination rectangle, stretching or compressing the bitmap if necessary to fit the dimensions of the destination rectangle.
»GetPixel«	Retrieves the RGB color value of the pixel at the specified point.
»SetPixel«	Sets the pixel at the specified point to the closest approximation of the specified color.
»FloodFill«	Fills an area with the current brush.
»ExtFloodFill«	Fills an area with the current brush. Provides more flexibility than the »FloodFill« member function.
Text Functions — Public Members

»TextOut«	Writes a character string at a specified location using the currently selected font.
»ExtTextOut«	Writes a character string within a rectangular region using the currently selected font.
»TabbedTextOut«	Writes a character string at a specified location, expanding tabs to the values specified in an array of tab-stop positions.
»DrawText«	Draws formatted text in the specified rectangle.
»GetTextExtent«	Computes the width and height of a line of text on the attribute device context using the current font to determine the dimensions.
»GetOutputTextExtent«	Computes the width and height of a line of text on the output device context using the current font to determine the dimensions.
»GetTabbedTextExtent«	Computes the width and height of a character string on the attribute device context.
»GetOutputTabbedTextExtent«	Computes the width and height of a character string on the output device context.
»GrayString«	Draws dimmed (grayed) text at the given location.
»GetTextAlign«	Retrieves the text-alignment flags.
»SetTextAlign«	Sets the text-alignment flags.
»GetTextFace«	Copies the typeface name of the current font into a buffer as a null-terminated string.
»GetTextMetrics«	Retrieves the metrics for the current font from the attribute device context.
»GetOutputTextMetrics«	Retrieves the metrics for the current font from the output device context.
»SetTextJustification«	Adds space to the break characters in a string.
»GetTextCharacterExtra«	Retrieves the current setting for the amount of intercharacter spacing.
»SetTextCharacterExtra«	Sets the amount of intercharacter spacing.
Font Functions — Public Members

»GetFontData«	Retrieves font metric information from a scalable font file. The information to retrieve is identified by specifying an offset into the font file and the length of the information to return.
»GetKerningPairs«	Retrieves the character kerning pairs for the font that is currently selected in the specified device context.
»GetOutlineTextMetrics«	Retrieves font metric information for TrueType fonts.
»GetGlyphOutline«	Retrieves the outline curve or bitmap for an outline character in the current font.
»GetCharABCWidths«	Retrieves the widths of consecutive characters in a specified range from the current TrueType font. The widths are returned in logical units. This function succeeds only with TrueType fonts.
»GetCharWidth«	Retrieves the widths of individual characters in a consecutive group of characters from the current font using the attribute device context.
»GetOutputCharWidth«	Retrieves the widths of individual characters in a consecutive group of characters from the current font using the output device context.
»SetMapperFlags«	Alters the algorithm that the font mapper uses when it maps logical fonts to physical fonts.
»GetAspectRatioFilter«	Retrieves the setting for the current aspect-ratio filter.
Printer Escape Functions — Public Members

»QueryAbort«	Calls the AbortProc callback function for a printing application and queries whether the printing should be terminated.
»Escape«	Allows applications to access facilities that are not directly available from a particular device through GDI. Escape calls made by an application are translated and sent to the device driver.
»StartDoc«	Informs the device driver that a new print job is starting.
»StartPage«	Informs the device driver that a new page is starting.
»EndPage«	Informs the device driver that a page is ending.
»SetAbortProc«	Sets a programmer-supplied callback function that Windows calls if a print job must be aborted.
»AbortDoc«	Terminates the current print job, erasing everything the application has written to the device since the last call of the StartDoc member function.
»EndDoc«	Ends a print job started by the StartDoc member function.
Scrolling Functions — Public Members

»ScrollDC«	Scrolls a rectangle of bits horizontally and vertically.
Metafile Functions — Public Members

»PlayMetaFile«	Plays the contents of the specified metafile on the given device. The metafile can be played any number of times.


CDC Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDC::AbortDoc

int AbortDoc();

Remarks

Terminates the current print job and erases everything the application has written to the device since the last call to the »StartDoc« member function.

This member function replaces the ABORTDOC printer escape.

AbortDoc should be used to terminate:

•	Printing operations that do not specify an abort function using »SetAbortProc«.

•	Printing operations that have not yet reached their first NEWFRAME or NEXTBAND escape call.

If an application encounters a printing error or a canceled print operation, it must not attempt to terminate the operation by using either the EndDoc or AbortDoc member functions of class CDC. GDI automatically terminates the operation before returning the error value.

If the application displays a dialog box to allow the user to cancel the print operation, it must call AbortDoc before destroying the dialog box.

If Print Manager was used to start the print job, calling AbortDoc erases the entire spool job — the printer receives nothing. If Print Manager was not used to start the print job, the data may have been sent to the printer before AbortDoc was called. In this case, the printer driver would have reset the printer (when possible) and closed the print job.

When running under Windows version 3.0, this member function sends an ABORTDOC printer escape.

Return Value

A value greater than or equal to 0 if successful, or a negative value if an error has occurred. The following list shows common error values and their meanings:

•	SP_ERROR    General error.

•	SP_OUTOFDISK    Not enough disk space is currently available for spooling, and no more space will become available.

•	SP_OUTOFMEMORY    Not enough memory is available for spooling.

•	SP_USERABORT    User terminated the job through the Print Manager.

See Also

»CDC::StartDoc«, »CDC::EndDoc«, »CDC::SetAbortProc«


  CDC::Arc

BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Arc( LPCRECT lpRect, POINT ptStart, POINT ptEnd );

x1    Specifies the x-coordinate of the upper-left corner of the bounding rectangle (in logical units).

y1    Specifies the y-coordinate of the upper-left corner of the bounding rectangle (in logical units).

x2    Specifies the x-coordinate of the lower-right corner of the bounding rectangle (in logical units).

y2    Specifies the y-coordinate of the lower-right corner of the bounding rectangle (in logical units).

x3    Specifies the x-coordinate of the point that defines the arc's starting point (in logical units). This point does not have to lie exactly on the arc.

y3    Specifies the y-coordinate of the point that defines the arc's starting point (in logical units). This point does not have to lie exactly on the arc.

x4    Specifies the x-coordinate of the point that defines the arc's endpoint (in logical units). This point does not have to lie exactly on the arc.

y4    Specifies the y-coordinate of the point that defines the arc's endpoint (in logical units). This point does not have to lie exactly on the arc.

lpRect    Specifies the bounding rectangle (in logical units). You can pass either an LPRECT or a »CRect« object for this parameter.

ptStart    Specifies the x- and y-coordinates of the point that defines the arc's starting point (in logical units). This point does not have to lie exactly on the arc. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

ptEnd    Specifies the x- and y-coordinates of the point that defines the arc's ending point (in logical units). This point does not have to lie exactly on the arc. You can pass either a POINT structure or a CPoint object for this parameter.

Remarks

Draws an elliptical arc. The arc drawn by using the function is a segment of the ellipse defined by the specified bounding rectangle.

The actual starting point of the arc is the point at which a ray drawn from the center of the bounding rectangle through the specified starting point intersects the ellipse. The actual ending point of the arc is the point at which a ray drawn from the center of the bounding rectangle through the specified ending point intersects the ellipse. The arc is drawn in a counterclockwise direction. Since an arc is not a closed figure, it is not filled. Both the width and height of the rectangle must be greater than 2 units and less than 32767 units.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Chord«, ::Arc, »POINT«, »RECT«


  CDC::Attach

BOOL Attach( HDC hDC );

hDC     A Windows device context.

Remarks

Use this member function to attach an hDC to the CDC object. The hDC is stored in both m_hDC, the output device context, and in m_hAttribDC, the attribute device context.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Detach«, »CDC::m_hDC«, »CDC::m_hAttribDC«


  CDC::BitBlt

BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );

x    Specifies the logical x-coordinate of the upper-left corner of the destination rectangle.

y    Specifies the logical y-coordinate of the upper-left corner of the destination rectangle.

nWidth    Specifies the width (in logical units) of the destination rectangle and source bitmap.

nHeight    Specifies the height (in logical units) of the destination rectangle and source bitmap.

pSrcDC    Pointer to a CDC object that identifies the device context from which the bitmap will be copied. It must be NULL if dwRop specifies a raster operation that does not include a source.

xSrc    Specifies the logical x-coordinate of the upper-left corner of the source bitmap.

ySrc    Specifies the logical y-coordinate of the upper-left corner of the source bitmap.

dwRop    Specifies the raster operation to be performed. Raster-operation codes define how the GDI combines colors in output operations that involve a current brush, a possible source bitmap, and a destination bitmap. The following lists raster-operation codes for dwRop and their descriptions:

•	BLACKNESS    Turns all output black.

•	DSTINVERT    Inverts the destination bitmap.

•	MERGECOPY    Combines the pattern and the source bitmap using the Boolean AND operator.

•	MERGEPAINT    Combines the inverted source bitmap with the destination bitmap using the Boolean OR operator.

•	NOTSRCCOPY    Copies the inverted source bitmap to the destination.

•	NOTSRCERASE    Inverts the result of combining the destination and source bitmaps using the Boolean OR operator.

•	PATCOPY    Copies the pattern to the destination bitmap.

•	PATINVERT    Combines the destination bitmap with the pattern using the Boolean XOR operator.

•	PATPAINT    Combines the inverted source bitmap with the pattern using the Boolean OR operator. Combines the result of this operation with the destination bitmap using the Boolean OR operator.

•	SRCAND    Combines pixels of the destination and source bitmaps using the Boolean AND operator.

•	SRCCOPY    Copies the source bitmap to the destination bitmap.

•	SRCERASE    Inverts the desination bitmap and combines the result with the source bitmap using the Boolean AND operator.

•	SRCINVERT    Combines pixels of the destination and source bitmaps using the Boolean XOR operator.

•	SRCPAINT    Combines pixels of the destination and source bitmaps using the Boolean OR operator.

•	WHITENESS    Turns all output white.

For a complete list of raster-operation codes, see the Windows Software Development Kit (SDK) documentation.

Remarks

Copies a bitmap from the source device context to this current device context.

The application can align the windows or client areas on byte boundaries to ensure that the BitBlt operations occur on byte-aligned rectangles. (Set the CS_BYTEALIGNWINDOW or CS_BYTEALIGNCLIENT flags when you register the window classes.)

BitBlt operations on byte-aligned rectangles are considerably faster than BitBlt operations on rectangles that are not byte aligned. If you want to specify class styles such as byte-alignment for your own device context, you will have to register a window class rather than relying on the Microsoft Foundation classes to do it for you. Use the global function »AfxRegisterWndClass«.

GDI transforms nWidth and nHeight, once by using the destination device context, and once by using the source device context. If the resulting extents do not match, GDI uses the Windows StretchBlt function to compress or stretch the source bitmap as necessary.

If destination, source, and pattern bitmaps do not have the same color format, the BitBlt function converts the source and pattern bitmaps to match the destination. The foreground and background colors of the destination bitmap are used in the conversion.

When the BitBlt function converts a monochrome bitmap to color, it sets white bits (1) to the background color and black bits (0) to the foreground color. The foreground and background colors of the destination device context are used. To convert color to monochrome, BitBlt sets pixels that match the background color to white and sets all other pixels to black. BitBlt uses the foreground and background colors of the color device context to convert from color to monochrome.

Note that not all device contexts support BitBlt. To check whether a given device context does support BitBlt, use the GetDeviceCaps member function and specify the RASTERCAPS index.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetDeviceCaps«, »CDC::PatBlt«, »CDC::SetTextColor«, »CDC::StretchBlt«, ::StretchDIBits, ::BitBlt


  CDC::CDC

CDC();

Remarks

Constructs a CDC object.

See Also

»CDC::CreateDC«, »CDC::CreateIC«, »CDC::CreateCompatibleDC«


  CDC::Chord

BOOL Chord( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Chord( LPCRECT lpRect, POINT ptStart, POINT ptEnd );

x1    Specifies the x-coordinate of the upper-left corner of the chord's bounding rectangle (in logical units).

y1    Specifies the y-coordinate of the upper-left corner of the chord's bounding rectangle (in logical units).

x2    Specifies the x-coordinate of the lower-right corner of the chord's bounding rectangle (in logical units).

y2    Specifies the y-coordinate of the lower-right corner of the chord's bounding rectangle (in logical units).

x3    Specifies the x-coordinate of the point that defines the chord's starting point (in logical units).

y3    Specifies the y-coordinate of the point that defines the chord's starting point (in logical units).

x4    Specifies the x-coordinate of the point that defines the chord's endpoint (in logical units).

y4    Specifies the y-coordinate of the point that defines the chord's endpoint (in logical units).

lpRect    Specifies the bounding rectangle (in logical units). You can pass either a LPRECT or a »CRect« object for this parameter.

ptStart    Specifies the x- and y-coordinates of the point that defines the chord's starting point (in logical units). This point does not have to lie exactly on the chord. You can pass either a POINT structure or a CPoint object for this parameter.

ptEnd    Specifies the x- and y-coordinates of the point that defines the chord's ending point (in logical units). This point does not have to lie exactly on the chord. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Draws a chord (a closed figure bounded by the intersection of an ellipse and a line segment). The (x1, y1) and (x2, y2) parameters specify the upper-left and lower-right corners, respectively, of a rectangle bounding the ellipse that is part of the chord. The (x3, y3) and (x4, y4) parameters specify the endpoints of a line that intersects the ellipse. The chord is drawn by using the selected pen and filled by using the selected brush.

The figure drawn by the Chord function extends up to, but does not include the right and bottom coordinates. This means that the height of the figure is y2 − y1 and the width of the figure is x2 − x1.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Arc«,  ::Chord, »POINT«


  CDC::CreateCompatibleDC

virtual BOOL CreateCompatibleDC( CDC* pDC );

pDC    A pointer to a device context. If pDC is NULL, the function creates a memory device context that is compatible with the system display.

Remarks

Creates a memory device context that is compatible with the device specified by pDC. A memory device context is a block of memory that represents a display surface. It can be used to prepare images in memory before copying them to the actual device surface of the compatible device.

When a memory device context is created, GDI automatically selects a 1-by-1 monochrome stock bitmap for it. GDI output functions can be used with a memory device context only if a bitmap has been created and selected into that context.

This function can only be used to create compatible device contexts for devices that support raster operations. See the »CDC::BitBlt« member function for information regarding bit-block transfers between device contexts. To determine if a device context supports raster operations, see the RC_BITBLT raster capability in the member function CDC::GetDeviceCaps.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::CDC«, »CDC::GetDeviceCaps«, ::CreateCompatibleDC, »CDC::BitBlt«, »CDC::CreateDC«, »CDC::CreateIC«, »CDC::DeleteDC«


  CDC::CreateDC

virtual BOOL CreateDC( LPCSTR lpszDriverName, LPCSTR lpszDeviceName, LPCSTR lpszOutput, const void FAR* lpInitData );

lpszDriverName    Points to a null-terminated string that specifies the MS-DOS filename (without extension) of the device driver (for example, "EPSON"). You can also pass a CString object for this parameter.

lpszDeviceName    Points to a null-terminated string that specifies the name of the specific device to be supported (for example, "EPSON FX-80"). The lpszDeviceName parameter is used if the module supports more than one device. You can also pass a CString object for this parameter.

lpszOutput    Points to a null-terminated string that specifies the MS-DOS file or device name for the physical output medium (file or output port). You can also pass a CString object for this parameter.

lpInitData    Points to a DEVMODE structure containing device-specific initialization data for the device driver. The Windows ExtDeviceMode function retrieves this structure filled in for a given device. The lpInitData parameter must be NULL if the device driver is to use the default initialization (if any) specified by the user through the Control Panel.

A DEVMODE structure has this form:

#include <print.h>

typedef struct tagDEVMODE {   /* dm */
    char  dmDeviceName[CCHDEVICENAME];
    UINT  dmSpecVersion;
    UINT  dmDriverVersion;
    UINT  dmSize;
    UINT  dmDriverExtra;
    DWORD dmFields;
    int   dmOrientation;
    int   dmPaperSize;
    int   dmPaperLength;
    int   dmPaperWidth;
    int   dmScale;
    int   dmCopies;
    int   dmDefaultSource;
    int   dmPrintQuality;
    int   dmColor;
    int   dmDuplex;
    int   dmYResolution;
    int   dmTTOption;
} DEVMODE;

For more information about this structure, see DEVMODE in the Windows SDK documentation.

Remarks

Creates a device context for the specified device.

The PRINT.H header file is required if the »DEVMODE« structure is used.

MS-DOS device names follow MS-DOS conventions; an ending colon (:) is recommended, but optional. Windows strips the terminating colon so that a device name ending with a colon is mapped to the same port as the same name without a colon. The driver and port names must not contain leading or trailing spaces. GDI output functions cannot be used with information contexts.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::ExtDeviceMode, ::CreateDC, »CDC::DeleteDC«, »CDC::CreateIC«


  CDC::CreateIC

virtual BOOL CreateIC( LPCSTR lpszDriverName, LPCSTR lpszDeviceName, LPCSTR lpszOutput, const void FAR* lpInitData );

lpszDriverName    Points to a null-terminated string that specifies the MS-DOS filename (without extension) of the device driver (for example, "EPSON"). You can pass a CString object for this parameter.

lpszDeviceName    Points to a null-terminated string that specifies the name of the specific device to be supported (for example, "EPSON FX-80"). The lpszDeviceName parameter is used if the module supports more than one device. You can pass a CString object for this parameter.

lpszOutput    Points to a null-terminated string that specifies the MS-DOS file or device name for the physical output medium (file or port). You can pass a CString object for this parameter.

lpInitData    Points to device-specific initialization data for the device driver. The lpInitData parameter must be NULL if the device driver is to use the default initialization (if any) specified by the user through the Control Panel. See CreateDC for the data format for device-specific initialization.

Remarks

Creates an information context for the specified device. The information context provides a fast way to get information about the device without creating a device context.

MS-DOS device names follow MS-DOS conventions; an ending colon (:) is recommended, but optional. Windows strips the terminating colon so that a device name ending with a colon is mapped to the same port as the same name without a colon. The driver and port names must not contain leading or trailing spaces. GDI output functions cannot be used with information contexts.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CDC::CreateDC«, ::CreateIC, »CDC::DeleteDC«


  CDC::DeleteDC

virtual BOOL DeleteDC();

Remarks

In general, do not call this function; the destructor will do it for you. The DeleteDC member function deletes the Windows device contexts that are associated with m_hDC in the current CDC object. If this CDC object is the last active device context for a given device, the device is notified and all storage and system resources used by the device are released.

An application should not call DeleteDC if objects have been selected into the device context. Objects must first be selected out of the device context before it it is deleted.

An application must not delete a device context whose handle was obtained by calling »CWnd::GetDC«. Instead, it must call »CWnd::ReleaseDC« to free the device context. The »CClientDC« and »CWindowDC« classes are provided to wrap this functionality.

The DeleteDC function is generally used to delete device contexts created with »CreateDC«, »CreateIC«, or »CreateCompatibleDC«.

Return Value

Nonzero if the function completed successfully; otherwise 0.

See Also

»CDC::CDC«, ::DeleteDC, »CDC::CreateDC«, »CDC::CreateIC«, »CDC::CreateCompatibleDC«, »CWnd::GetDC«, »CWnd::ReleaseDC«


  CDC::DeleteTempMap

static void PASCAL DeleteTempMap();

Remarks

Called automatically by the CWinApp idle-time handler, DeleteTempMap deletes any temporary CDC objects created by FromHandle, but does not destroy the device context handles (HDCs) temporarily associated with the CDC objects.

See Also

»CDC::Detach«, »CDC::FromHandle«, »CWinApp::OnIdle«


  CDC::Detach

HDC Detach();

Remarks

Call this function to detach m_hDC (the output device context) from the CDC object and set both m_hDC and m_hAttribDC to NULL.

Return Value

A Windows device context.

See Also

»CDC::Attach«, »CDC::m_hDC«, »CDC::m_hAttribDC«


  CDC::DPtoLP

void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;

void DPtoLP( LPRECT lpRect ) const;

lpPoints    Points to an array of »POINT« structures or »CPoint« objects.

nCount    Specifies the number of points in the array.

lpRect    Points to a »RECT« structure or »CRect« object. This parameter is used for the simple case of converting one rectangle from device points to logical points.

Remarks

Converts device points into logical points. The function maps the coordinates of each point from the device coordinate system into the GDI's logical coordinate system. The conversion depends on the current mapping mode and the settings of the origins and extents for the device's window and viewport.

See Also

»CDC::LPtoDP«, ::DPtoLP, »POINT«, »RECT«


  CDC::DrawFocusRect

void DrawFocusRect( LPCRECT lpRect );

lpRect    Points to a »RECT« structure or a »CRect« object that specifies the logical coordinates of the rectangle to be drawn.

Remarks

Draws a rectangle in the style used to indicate that the rectangle has the focus.

Since this is a Boolean XOR function, calling this function a second time with the same rectangle removes the rectangle from the display. The rectangle drawn by this function cannot be scrolled. To scroll an area containing a rectangle drawn by this function, first call DrawFocusRect to remove the rectangle from the display, then scroll the area, and then call DrawFocusRect again to draw the rectangle in the new position.

See Also

»CDC::FrameRect«,  ::DrawFocusRect, »RECT«


  CDC::DrawIcon

BOOL DrawIcon( int x, int y, HICON hIcon );

BOOL DrawIcon( POINT point, HICON hIcon );

x    Specifies the logical x-coordinate of the upper-left corner of the icon.

y    Specifies the logical y-coordinate of the upper-left corner of the icon.

hIcon    Identifies the handle of the icon to be drawn.

point    Specifies the logical x- and y-coordinates of the upper-left corner of the icon. You can pass a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Draws an icon on the device represented by the current CDC object. The function places the icon's upper-left corner at the location specified by x and y. The location is subject to the current mapping mode of the device context.

The icon resource must have been previously loaded by using the functions CWinApp::LoadIcon, CWinApp::LoadStandardIcon, or CWinApp::LoadOEMIcon. The MM_TEXT mapping mode must be selected prior to using this function.

Return Value

Nonzero if the function completed successfully; otherwise 0.

See Also

»CWinApp::LoadIcon«, »CWinApp::LoadStandardIcon«, »CWinApp::LoadOEMIcon«, »CDC::GetMapMode«, »CDC::SetMapMode«, ::DrawIcon, »POINT«


  CDC::DrawText

virtual int DrawText( LPCSTR lpszString, int nCount, LPRECT lpRect, UINT nFormat );

lpszString    Points to the string to be drawn. If nCount is −1, the string must be null-terminated.

nCount    Specifies the number of bytes in the string. If nCount is −1, then lpszString is assumed to be a long pointer to a null-terminated string and DrawText computes the character count automatically.

lpRect    Points to a »RECT« structure or »CRect« object that contains the rectangle (in logical coordinates) in which the text is to be formatted.

nFormat    Specifies the method of formatting the text. It can be any combination of the following values (combine using the bitwise-OR operator), with the meanings as given:

•	DT_BOTTOM    Specifies bottom-justified text. This value must be combined with DT_SINGLELINE.

•	DT_CALCRECT    Determines the width and height of the rectangle. If there are multiple lines of text, DrawText will use the width of the rectangle pointed to by lpRect and extend the base of the rectangle to bound the last line of text. If there is only one line of text, DrawText will modify the right side of the rectangle so that it bounds the last character in the line. In either case, DrawText returns the height of the formatted text but does not draw the text.

•	DT_CENTER    Centers text horizontally.

•	DT_EXPANDTABS    Expands tab characters. The default number of characters per tab is eight.

•	DT_EXTERNALLEADING    Includes the font's external leading in the line height. Normally, external leading is not included in the height of a line of text.

•	DT_LEFT    Aligns text flush-left.

•	DT_NOCLIP    Draws without clipping. DrawText is somewhat faster when DT_NOCLIP is used.

•	DT_NOPREFIX    Turns off processing of prefix characters. Normally, DrawText interprets the ampersand (&) mnemonic-prefix character as a directive to underscore the character that follows, and the two-ampersand (&&) mnemonic-prefix characters as a directive to print a single ampersand. By specifiying DT_NOPREFIX this processing is turned off.

•	DT_RIGHT    Aligns text flush-right.

•	DT_SINGLELINE    Specifies single line only. Carriage returns and linefeeds do not break the line.

•	DT_TABSTOP    Sets tab stops. The high-order byte of nFormat is the number of characters for each tab. The default number of characters per tab is eight.

•	DT_TOP    Specifies top-justified text (single line only).

•	DT_VCENTER    Specifies vertically centered text (single line only).

•	DT_WORDBREAK    Specifies word-breaking. Lines are automatically broken between words if a word would extend past the edge of the rectangle specified by lpRect. A carriage return−linefeed sequence will also break the line.

Note that the values DT_CALCRECT, DT_EXTERNALLEADING, DT_INTERNAL, DT_NOCLIP, and DT_NOPREFIX cannot be used with the DT_TABSTOP value.

Remarks

Draws formatted text in the rectangle specified by lpRect. It formats text by expanding tabs into appropriate spaces, aligning text to the left, right, or center of the given rectangle, and breaking text into lines that fit within the given rectangle. The type of formatting is specified by nFormat.

This member function uses the device context's selected font, text color, and background color to draw the text. Unless the DT_NOCLIP format is used, DrawText clips the text so that the text does not appear outside the given rectangle. All formatting is assumed to have multiple lines unless the DT_SINGLELINE format is given.

If the selected font is too large for the specified rectangle, the DrawText member function does not attempt to substitute a smaller font.

If the DT_CALCRECT flag is specified, the rectangle specified by lpRect will be updated to reflect the width and height needed to draw the text.

If the TA_UPDATECP text-alignment flag has been set (see »CDC::SetTextAlign«), DrawText will display text starting at the current position, rather than at the left of the given rectangle. DrawText will not wrap text when the TA_UPDATECP flag has been set (that is, the DT_WORDBREAK flag will have no effect).

The text color may be set by »CDC::SetTextColor«.

Return Value

The height of the text if the function is successful.

See Also

»CDC::SetTextColor«, »CDC::ExtTextOut«, »CDC::TabbedTextOut«, »CDC::TextOut«, ::DrawText, »RECT«, »CDC::SetTextAlign«


  CDC::Ellipse

BOOL Ellipse( int x1, int y1, int x2, int y2 );

BOOL Ellipse( LPCRECT lpRect );

x1    Specifies the logical x-coordinate of the upper-left corner of the ellipse's bounding rectangle.

y1    Specifies the logical y-coordinate of the upper-left corner of the ellipse's bounding rectangle.

x2    Specifies the logical x-coordinate of the lower-right corner of the ellipse's bounding rectangle.

y2    Specifies the logical y-coordinate of the lower-right corner of the ellipse's bounding rectangle.

lpRect    Specifies the ellipse's bounding rectangle. You can also pass a »CRect« object for this parameter.

Remarks

Draws an ellipse. The center of the ellipse is the center of the bounding rectangle specified by x1, y1, x2, and y2, or lpRect. The ellipse is drawn with the current pen and its interior is filled with the current brush.

The figure drawn by this function extends up to but does not include the right and bottom coordinates. This means that the height of the figure is y2 − y1 and the width of the figure is x2 − x1.

If either the width or the height of the bounding rectangle is 0, no ellipse is drawn.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Arc«, »CDC::Chord«, ::Ellipse


  CDC::EndDoc

int EndDoc();

Remarks

Ends a print job started by a call to the »StartDoc« member function. This member function replaces the ENDDOC printer escape, and should be called immediately after finishing a successful print job.

If an application encounters a printing error or a canceled print operation, it must not attempt to terminate the operation by using either EndDoc or »AbortDoc«. GDI automatically terminates the operation before returning the error value.

This function should not be used inside metafiles.

When used with Windows version 3.0, this member function sends the ENDDOC escape.

Return Value

Greater than or equal to 0 if the function is successful, or a negative value if an error occurred. The following list shows common error values and their meanings:

•	SP_ERROR    General error.

•	SP_OUTOFDISK    Not enough disk space is currently available for spooling, and no more space will become available.

•	SP_OUTOFMEMORY    Not enough memory is available for spooling.

•	SP_USERABORT    User ended the job through the Print Manager.

See Also

»CDC::AbortDoc«, »CDC::Escape«, »CDC::StartDoc«


  CDC::EndPage

int EndPage();

Remarks

Informs the device that the application has finished writing to a page. This member function is typically used to direct the device driver to advance to a new page.

This member function replaces the NEWFRAME printer escape. Unlike NEWFRAME, this function is always called after printing a page.

When used with Windows version 3.0, this member function sends the NEWFRAME escape.

Return Value

Greater than or equal to 0 if successful; otherwise it is an error value, which can be one of the following, with its meaning as given:

•	SP_ERROR    General error.

•	SP_APPABORT    Job was ended because the application's abort function returned 0.

•	SP_USERABORT    User ended the job through Print Manager.

•	SP_OUTOFDISK    Not enough disk space is currently available for spooling, and no more space will become available.

•	SP_OUTOFMEMORY    Not enough memory is available for spooling.

See Also

»CDC::StartPage«, »CDC::StartDoc«, »CDC::Escape«


  CDC::EnumObjects

int EnumObjects( int nObjectType, int ( CALLBACK EXPORT* lpfn )( LPVOID, LPARAM ), LPARAM lpData );

nObjectType    Specifies the object type. It can have the values OBJ_BRUSH or OBJ_PEN.

lpfn    Is the procedure-instance address of the application-supplied callback function. See the "Remarks" section below.

lpData    Points to the application-supplied data. The data is passed to the callback function along with the object information.

Remarks

Enumerates the pens and brushes available in a device context. For each object of a given type, the callback function that you pass is called with the information for that object. The system calls the callback function until there are no more objects or the callback function returns 0.

Note that new features of Microsoft C/C++ let you use an ordinary function as the function passed to EnumObjects. The address passed to EnumObjects is a FAR pointer to a function exported with __export and with the Pascal calling convention. In protect-mode applications, you do not have to create this function with the Windows MakeProcInstancefunction or free the function after use with the FreeProcInstanceWindows function.

You also do not have to export the function name in an EXPORTS statement in your application's module-definition file. You can instead use the __export function modifier, as in

int FAR PASCAL __export AFunction( LPSTR, LPSTR );

to cause the compiler to emit the proper export record for export by name without aliasing. This works for most needs. For some special cases, such as exporting a function by ordinal or aliasing the export, you still need to use an EXPORTS statement in a module-definition file.

For compiling Microsoft Foundation programs, you will normally use the /GA and /GEs compiler options. The /Gw compiler option is not used with the Microsoft Foundation classes. (If you do use the Windows function MakeProcInstance, you will need to explicitly cast the returned function pointer from FARPROC to the type needed in this API.) Callback registration interfaces are now type-safe (you must pass in a function pointer that points to the right kind of function for the specific callback).

Also note that all callback functions must trap Microsoft Foundation exceptions before returning to Windows, since exceptions cannot be thrown across callback boundaries. For more information about exceptions, see Chapter 16 in the Class Library User's Guide.

Callback Function

The callback function passed to EnumObjects must use the Pascal calling convention and must be declared FAR.

int CALLBACK EXPORT ObjectFunc( LPSTR lpszLogObject, LPSTR* lpData );

The ObjectFunc name is a placeholder for the application-supplied function name. The actual name must be exported as described in the "Remarks" section above. The parameters are described below:

•	lpszLogObject    Points to a »LOGPEN« or LOGBRUSHdata structure that contains information about the logical attributes of the object.

•	lpData    Points to the application-supplied data passed to the EnumObjects function.

Return Value

The callback function returns an int. The value of this return is user-defined. If the callback function returns 0, EnumObjects stops enumeration early.

Return Value

Specifies the last value returned by the callback function. Its meaning is user-defined.

See Also

::EnumObjects


  CDC::Escape

virtual int Escape( int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData );

nEscape    Specifies the escape function to be performed.

nCount    Specifies the number of bytes of data pointed to by lpszInData.

lpszInData    Points to the input data structure required for this escape.

lpOutData    Points to the structure that is to receive output from this escape. The lpOutData parameter is NULL if no data is returned.

Remarks

Allows applications to access facilities of a particular device that are not directly available through GDI. Escape calls made by an application are translated and sent to the device driver.

The nEscape parameter specifies the escape function to be performed. For possible values, see the information on printer escapes in the Windows SDK documentation.

Windows versions 3.1 and later substitute function calls for some escapes. The following CDC member functions call the Windows functions if running with Windows versions 3.1 and later, and otherwise send the printer escapes:

•	AbortDoc    Terminates a print job. Supersedes the ABORTDOC escape.

•	EndDoc    Ends a print job. Supersedes the ENDDOC escape.

•	EndPage    Ends a page. Supersedes the NEWFRAME escape. Unlike NEWFRAME, this function is always called after printing a page.

•	SetAbortProc    Sets the abort function for a print job. Supersedes the SETABORTPROC escape.

•	StartDoc    Starts a print job. Supersedes the STARTDOC escape.

•	StartPage    Prepares printer driver to receive data. Supercedes the NEWFRAME and BANDINFO escapes.

Return Value

Positive if the function is successful, except for the QUERYESCSUPPORT escape, which only checks for implementation. Zero is returned if the escape is not implemented, and a negative value is returned if an error occurred. The following list shows common error values and their meanings:

•	SP_ERROR    General error.

•	SP_OUTOFDISK    Not enough disk space is currently available for spooling, and no more space will become available.

•	SP_OUTOFMEMORY    Not enough memory is available for spooling.

•	SP_USERABORT    User ended the job through the Print Manager.

See Also

»CDC::StartDoc«, »CDC::StartPage«, »CDC::EndPage«, »CDC::SetAbortProc«, »CDC::AbortDoc«, »CDC::EndDoc«, ::Escape


  CDC::ExcludeClipRect

virtual int ExcludeClipRect( int x1, int y1, int x2, int y2 );

virtual int ExcludeClipRect( LPCRECT lpRect );

x1    Specifies the logical x-coordinate of the upper-left corner of the rectangle.

y1    Specifies the logical y-coordinate of the upper-left corner of the rectangle.

x2    Specifies the logical x-coordinate of the lower-right corner of the rectangle.

y2    Specifies the logical y-coordinate of the lower-right corner of the rectangle.

lpRect    Specifies the rectangle. Can also be a CRect object.

Remarks

Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.

The width of the rectangle, specified by the absolute value of x2 − x1, must not exceed 32,767 units. This limit applies to the height of the rectangle as well.

Return Value

Specifies the new clipping region's type. It can be any one of the following values, with meaning as given:

•	COMPLEXREGION    The region has overlapping borders.

•	ERROR    No region was created.

•	NULLREGION    The region is empty.

•	SIMPLEREGION    The region has no overlapping borders.

See Also

»CDC::ExcludeUpdateRgn«, ::ExcludeClipRect


  CDC::ExcludeUpdateRgn

int ExcludeUpdateRgn( CWnd* pWnd );

pWnd    Points to the window object whose window is being updated.

Remarks

Prevents drawing within invalid areas of a window by excluding an updated region in the window from the clipping region associated with the CDC object.

Return Value

The type of excluded region. It can be any one of the following values, with the meaning as given:

•	COMPLEXREGION    The region has overlapping borders.

•	ERROR    No region was created.

•	NULLREGION    The region is empty.

•	SIMPLEREGION    The region has no overlapping borders.

See Also

»CDC::ExcludeClipRect«, ::ExcludeUpdateRgn


  CDC::ExtFloodFill

BOOL ExtFloodFill( int x, int y, COLORREF crColor, UINT nFillType );

x    Specifies the logical x-coordinate of the point where filling begins.

y    Specifies the logical y-coordinate of the point where filling begins.

crColor    Specifies the color of the boundary or of the area to be filled. The interpretation of crColor depends on the value of nFillType.

nFillType    Specifies the type of flood fill to be performed. It must be one of the following values, with the meaning as given:

•	FLOODFILLBORDER    The fill area is bounded by the color specified by crColor. This style is identical to the filling performed by FloodFill.

•	FLOODFILLSURFACE    The fill area is defined by the color specified by crColor. Filling continues outward in all directions as long as the color is encountered. This style is useful for filling areas with multicolored boundaries.

Remarks

Fills an area of the display surface with the current brush. This member function provides more flexibility than FloodFill because you can specify a fill type in nFillType.

If nFillType is set to FLOODFILLBORDER, the area is assumed to be completely bounded by the color specified by crColor. The function begins at the point specified by x and y and fills in all directions to the color boundary.

If nFillType is set to FLOODFILLSURFACE, the function begins at the point specified by x and y and continues in all directions, filling all adjacent areas containing the color specified by crColor.

Only memory-device contexts and devices that support raster-display technology support ExtFloodFill. For more information, see the »GetDeviceCaps« member function.

Return Value

Nonzero if the function is successful; otherwise 0 if the filling could not be completed, if the given point has the boundary color specified by crColor (if FLOODFILLBORDER was requested), if the given point does not have the color specified by crColor (if FLOODFILLSURFACE was requested), or if the point is outside the clipping region.

See Also

»CDC::FloodFill«, »CDC::GetDeviceCaps«, ::ExtFloodFill


  CDC::ExtTextOut

virtual BOOL ExtTextOut( int x, int y, UINT nOptions, LPCRECT lpRect, LPCSTR lpszString, UINT nCount, LPINT lpDxWidths );

x    Specifies the logical x-coordinate of the character cell for the first character in the specified string.

y    Specifies the logical y-coordinate of the character cell for the first character in the specified string.

nOptions    Specifies the rectangle type. This parameter can be one, both, or neither of the following values:

•	ETO_CLIPPED    Specifies that text is clipped to the rectangle.

•	ETO_OPAQUE    Specifies that the current background color fills the rectangle. (You can set and query the current background color with the SetBkColor and GetBkColor member functions).

lpRect    Points to a »RECT« structure that determines the dimensions of the rectangle. This parameter can be NULL. You can also pass a »CRect« object for this parameter.

lpszString    Points to the specified character string. You can also pass a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

lpDxWidths    Points to an array of values that indicate the distance between origins of adjacent character cells. For instance, lpDxWidths[i] logical units will separate the origins of character cell i and character cell i + 1. If lpDxWidths is NULL, ExtTextOut uses the default spacing between characters.

Remarks

Writes a character string within a rectangular region using the currently selected font. The rectangular region can be opaque (filled with the current background color) and it can be a clipping region.

If nOptions is 0 and lpRect is NULL, the function writes text to the device context without using a rectangular region. By default, the current position is not used or updated by the function. If an application needs to update the current position when it calls ExtTextOut, the application can call the CDC member function SetTextAlign with nFlags set to TA_UPDATECP. When this flag is set, Windows ignores x and y on subsequent calls to ExtTextOut and uses the current position instead. When an application uses TA_UPDATECP to update the current position, ExtTextOut sets the current position either to the end of the previous line of text or to the position specified by the last element of the array pointed to by lpDxWidths, whichever is greater.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::SetTextAlign«, »CDC::TabbedTextOut«, »CDC::TextOut«, »CDC::GetBkColor«, »CDC::SetBkColor«, »CDC::SetTextColor«, ::ExtTextOut, »RECT«


  CDC::FillRect

void FillRect( LPCRECT lpRect, CBrush* pBrush );

lpRect    Points to a »RECT« structure that contains the logical coordinates of the rectangle to be filled. You can also pass a CRect object for this parameter.

pBrush    Identifies the brush used to fill the rectangle.

Remarks

Fills a given rectangle using the specified brush. The function fills the complete rectangle, including the left and top borders, but it does not fill the right and bottom borders.

The brush needs to either be created using the CBrush member functions CreateHatchBrush, CreatePatternBrush, and CreateSolidBrush, or retrieved by the GetStockObject Windows function.

When filling the specified rectangle, FillRect does not include the rectangle's right and bottom sides. GDI fills a rectangle up to, but does not include, the right column and bottom row, regardless of the current mapping mode. FillRect compares the values of the top, bottom, left, and right members of the specified rectangle. If bottom is less than or equal to top, or if right is less than or equal to left, the rectangle is not drawn.

See Also

»CBrush::CreateHatchBrush«, »CBrush::CreatePatternBrush«, »CBrush::CreateSolidBrush«, ::FillRect, ::GetStockObject, »RECT«, »CBrush«


  CDC::FillRgn

BOOL FillRgn( CRgn* pRgn, CBrush* pBrush );

pRgn    A pointer to the region to be filled. The coordinates for the given region are specified in device units.

pBrush    Identifies the brush to be used to fill the region.

Remarks

Fills the region specified by pRgn with the brush specified by pBrush.

The brush needs to either be created using the CBrush member functions CreateHatchBrush, CreatePatternBrush, CreateSolidBrush, or retrieved by GetStockObject.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::PaintRgn«, »CDC::FillRect«, »CBrush«, »CRgn«, ::FillRgn


  CDC::FloodFill

BOOL FloodFill( int x, int y, COLORREF crColor );

x    Specifies the logical x-coordinate of the point where filling begins.

y    Specifies the logical y-coordinate of the point where filling begins.

crColor    Specifies the color of the boundary.

Remarks

Fills an area of the display surface with the current brush. The area is assumed to be bounded as specified by crColor. The FloodFill function begins at the point specified by x and y and continues in all directions to the color boundary.

Only memory-device contexts and devices that support raster-display technology support the FloodFill member function. For information about RC_BITBLT capability, see the GetDeviceCaps member function.

The ExtFloodFill function provides similar capability but greater flexibility.

Return Value

Nonzero if the function is successful; otherwise 0 is returned if the filling could not be completed, the given point has the boundary color specified by crColor, or the point is outside the clipping region.

See Also

»CDC::ExtFloodFill«, »CDC::GetDeviceCaps«, ::FloodFill


  CDC::FrameRect

void FrameRect( LPCRECT lpRect, CBrush* pBrush );

lpRect    Points to a »RECT« structure or »CRect« object that contains the logical coordinates of the upper-left and lower-right corners of the rectangle. You can also pass a CRect object for this parameter.

pBrush    Identifies the brush to be used for framing the rectangle.

Remarks

Draws a border around the rectangle specified by lpRect. The function uses the given brush to draw the border. The width and height of the border is always 1 logical unit.

If the rectangle's bottom coordinate is less than or equal to top, or if right is less than or equal to left, the rectangle is not drawn.

The border drawn by FrameRect is in the same position as a border drawn by the Rectangle member function using the same coordinates (if Rectangle uses a pen that is 1 logical unit wide). The interior of the rectangle is not filled by FrameRect.

See Also

»CBrush«, »CDC::Rectangle«, »CDC::FrameRgn«, ::FrameRect, »RECT«


  CDC::FrameRgn

BOOL FrameRgn( CRgn* pRgn, CBrush* pBrush, int nWidth, int nHeight );

pRgn    Points to the CRgn object that identifies the region to be enclosed in a border. The coordinates for the given region are specified in device units.

pBrush    Points to the CBrush object that identifies the brush to be used to draw the border.

nWidth    Specifies the width of the border in vertical brush strokes (in logical units, or device units if running with Windows versions 3.1 and later).

nHeight    Specifies the height of the border in horizontal brush strokes (in logical units, or device units if running with Windows versions 3.1 and later).

Remarks

Draws a border around the region specified by pRgn using the brush specified by pBrush.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Rectangle«, »CDC::FrameRect«, »CBrush«, »CRgn«, ::FrameRgn


  CDC::FromHandle

static CDC* PASCAL FromHandle( HDC hDC );

hDC   Contains a handle to a Windows device context.

Remarks

Returns a pointer to a CDC object when given a handle to a device context. If a CDC object is not attached to the handle, a temporary CDC object is created and attached.

Return Value

The pointer may be temporary and should not be stored beyond immediate use.

See Also

»CDC::DeleteTempMap«


  CDC::GetAspectRatioFilter

CSize GetAspectRatioFilter() const;

Remarks

Retrieves the setting for the current aspect-ratio filter. The aspect ratio is the ratio formed by a device's pixel width and height. Information about a device's aspect ratio is used in the creation, selection, and display of fonts. Windows provides a special filter, the aspect-ratio filter, to select fonts designed for a particular aspect ratio from all of the available fonts. The filter uses the aspect ratio specified by the SetMapperFlags member function.

Return Value

A CSize object representing the aspect ratio used by the current aspect ratio filter.

See Also

»CDC::SetMapperFlags«, ::GetAspectRatioFilter, »CSize«


  CDC::GetBkColor

COLORREF GetBkColor() const;

Remarks

Returns the current background color. If the background mode is OPAQUE, the system uses the background color to fill the gaps in styled lines, the gaps between hatched lines in brushes, and the background in character cells. The system also uses the background color when converting bitmaps between color and monochrome device contexts.

Return Value

An RGB color value.

See Also

»CDC::GetBkMode«, »CDC::SetBkColor«, »CDC::SetBkMode«, ::GetBkColor


  CDC::GetBkMode

int GetBkMode() const;

Remarks

Returns the background mode. The background mode defines whether the system removes existing background colors on the drawing surface before drawing text, hatched brushes, or any pen style that is not a solid line.

Return Value

The current background mode, which can be OPAQUE, TRANSPARENT, or TRANSPARENT1.

See Also

»CDC::GetBkColor«, »CDC::SetBkColor«, »CDC::SetBkMode«, ::GetBkMode


  CDC::GetBoundsRect

Windows 3.1 Only

UINT GetBoundsRect( LPRECT lpRectBounds, UINT flags ); ♦

lpRectBounds    Points to a buffer that will receive the current bounding rectangle. The rectangle is returned in logical coordinates.

flags    Specifies whether the bounding rectangle is to be cleared after it is returned. This parameter can be one of the following values, with the meaning as given:

•	DCB_RESET    Forces the bounding rectangle to be cleared after it is returned.

•	DCB_WINDOWMGR    Queries the Windows bounding rectangle instead of the application's.

Remarks

Returns the current accumulated bounding rectangle for the specified device context.

Return Value

Specifies the current state of the bounding rectangle if the function is successful. It can be a combination of the following values, with the meaning as given:

•	DCB_ACCUMULATE    Bounding rectangle accumulation is occuring.

•	DCB_RESET    Bounding rectangle is empty.

•	DCB_SET    Bounding rectangle is not empty.

•	DCB_ENABLE    Bounding accumulation is on.

•	DCB_DISABLE    Bounding accumulation is off.

See Also

»CDC::SetBoundsRect«, ::GetBoundsRect


  CDC::GetBrushOrg

CPoint GetBrushOrg() const;

Remarks

Retrieves the origin (in device units) of the brush currently selected for the device context.

The initial brush origin is at (0,0) of the client area. The return value specifies this point in device units relative to the origin of the desktop window.

Return Value

The current origin of the brush (in device units) as a »CPoint« object.

See Also

»CDC::SetBrushOrg«, ::GetBrushOrg, »CPoint«


  CDC::GetCharABCWidths

Windows 3.1 Only

BOOL GetCharABCWidths( UINT nFirst, UINT nLast, LPABC lpabc ) const; ♦

nFirst    Specifies the first character in the range of characters from the current font for which character widths are returned.

nLast    Specifies the last character in the range of characters from the current font for which character widths are returned.

lpabc    Points to an array of ABC structures that receive the character widths when the function returns. This array must contain at least as many ABC structures as there are characters in the range specified by the nFirst and nLast parameters.

Remarks

Retrieves the widths of consecutive characters in a specified range from the current TrueType font. The widths are returned in logical units. This function succeeds only with TrueType fonts.

The TrueType rasterizer provides "ABC" character spacing after a specific point size has been selected. "A" spacing is the distance that is added to the current position before placing the glyph. "B" spacing is the width of the black part of the glyph. "C" spacing is added to the current position to account for the white space to the right of the glyph. The total advanced width is given by A + B + C.

When the GetCharABCWidths member function retrieves negative "A" or "C" widths for a character, that character includes underhangs or overhangs.

To convert the ABC widths to font design units, an application should create a font whose height (as specified in the lfHeight member of the »LOGFONT« structure) is equal to the value stored in the ntmSizeEM member of the NEWTEXTMETRICstructure. (The value of the ntmSizeEM member can be retrieved by calling the EnumFontFamiliesWindows function.)

The ABC widths of the default character are used for characters that are outside the range of the currently selected font.

To retrieve the widths of characters in non-TrueType fonts, applications should use the GetCharWidthmember function.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::EnumFontFamilies, »CDC::GetCharWidth«, ::GetCharABCWidths, ABC


  CDC::GetCharWidth

BOOL GetCharWidth( UINT nFirstChar, UINT nLastChar, LPINT lpBuffer ) const;

nFirstChar    Specifies the first character in a consecutive group of characters in the current font.

nLastChar    Specifies the last character in a consecutive group of characters in the current font.

lpBuffer    Points to a buffer that will receive the width values for a consecutive group of characters in the current font.

Remarks

Retrieves the widths of individual characters in a consecutive group of characters from the current font, using m_hAttribDC, the input device context. For example, if nFirstChar identifies the letter 'a' and nLastChar identifies the letter 'z', the function retrieves the widths of all lowercase characters.

The function stores the values in the buffer pointed to by lpBuffer. This buffer must be large enough to hold all of the widths. That is, there must be at least 26 entries in the example given.

If a character in the consecutive group of characters does not exist in a particular font, it will be assigned the width value of the default character.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetOutputCharWidth«, »CDC::m_hAttribDC«, »CDC::m_hDC«, ::GetCharWidth, ::GetCharABCWidths, »CDC::GetCharABCWidths«


  CDC::GetClipBox

virtual int GetClipBox( LPRECT lpRect ) const;

lpRect    Points to the »RECT« structure or »CRect« object that is to receive the rectangle dimensions.

Remarks

Retrieves the dimensions of the tightest bounding rectangle around the current clipping boundary. The dimensions are copied to the buffer pointed to by lpRect.

Return Value

The clipping region's type. It can be any one of the following values, with the meaning as given:

•	COMPLEXREGION    Clipping region has overlapping borders.

•	ERROR    Device context is not valid.

•	NULLREGION    Clipping region is empty.

•	SIMPLEREGION    Clipping region has no overlapping borders.

See Also

»CDC::SelectClipRgn«, ::GetClipBox, »RECT«


  CDC::GetCurrentPosition

CPoint GetCurrentPosition() const;

Remarks

Retrieves the current position (in logical coordinates). The current position can be set with the MoveTo member function.

Return Value

The current position as a CPoint object.

See Also

»CDC::MoveTo«, »CPoint«, ::GetCurrentPosition


  CDC::GetDeviceCaps

int GetDeviceCaps( int nIndex ) const;

nIndex    Specifies the type of information to return. It can be any one of the following values:

•	DRIVERVERSION    Version number; for example, 0x100 for 1.0.

•	TECHNOLOGY    Device technology. It can be any one of the following:

Value	Meaning
DT_PLOTTER	Vector plotter
DT_RASDISPLAY	Raster display
DT_RASPRINTER	Raster printer
DT_RASCAMERA	Raster camera
DT_CHARSTREAM	Character stream
DT_METAFILE	Metafile
DT_DISPFILE	Display file
•	HORZSIZE    Width of the physical display (in millimeters).

•	VERTSIZE    Height of the physical display (in millimeters).

•	HORZRES    Width of the display (in pixels).

•	VERTRES    Height of the display (in raster lines).

•	LOGPIXELSX    Number of pixels per logical inch along the display width.

•	LOGPIXELSY    Number of pixels per logical inch along the display height.

•	BITSPIXEL    Number of adjacent color bits for each pixel.

•	PLANES    Number of color planes.

•	NUMBRUSHES    Number of device-specific brushes.

•	NUMPENS    Number of device-specific pens.

•	NUMFONTS    Number of device-specific fonts.

•	NUMCOLORS    Number of entries in the device's color table.

•	ASPECTX    Relative width of a device pixel as used for line drawing.

•	ASPECTY    Relative height of a device pixel as used for line drawing.

•	ASPECTXY    Diagonal width of the device pixel as used for line drawing.

•	PDEVICESIZE    Size of the PDEVICE internal data structure.

•	CLIPCAPS    Clipping capabilities of the device. It can be one of the following:

Value	Meaning
CP_NONE	Output is not clipped.
CP_RECTANGLE	Output is clipped to rectangles.
CP_REGION	Output is clipped to regions.
•	SIZEPALETTE    Number of entries in the system palette. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index. It is available only if the driver is written for Windows version 3.0 or later.

•	NUMRESERVED    Number of reserved entries in the system palette. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is written for Windows version 3.0 or higher.

•	COLORRES    Actual color resolution of the device in bits per pixel. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is written for Windows version 3.0 or later.

•	RASTERCAPS    Value that indicates the raster capabilities of the device. It can be a combination of the following:

Capability	Meaning
RC_BANDING	Requires banding support.
RC_BIGFONT	Supports fonts larger than 64K.
RC_BITBLT	Capable of transferring bitmaps.
RC_BITMAP64	Spports bitmaps larger than 64K.
RC_DEVBITS	Supports device bitmaps.
RC_DI_BITMAP	Capable of supporting the SetDIBits and GetDIBits Windows functions.
RC_DIBTODEV	Capable of supporting the SetDIBitsToDevice Windows function.
RC_FLOODFILL	Capable of performing flood fills.
RC_GDI20_OUTPUT	Capable of supporting Windows version 2.0 features.
RC_GDI20_STATE	Includes a state block in the device context.
RC_NONE	Supports no raster operations.
RC_OP_DX_OUTPUT	Supports dev opaque and DX array.
RC_PALETTE	Specifies a palette-based device.
RC_SAVEBITMAP	Capable of saving bitmaps locally.
RC_SCALING	Capable of scaling.
RC_STRETCHBLT	Capable of performing the StretchBlt member function.
RC_STRETCHDIB	Capable of performing the StretchDIBits Windows function.
•	CURVECAPS    The curve capabilities of the device. It can be a combination of the following:

Value	Meaning
CC_NONE	Supports curves.
CC_CIRCLES	Supports circles.
CC_PIE	Supports pie wedges.
CC_CHORD	Supports chords.
CC_ELLIPSES	Supports ellipses.
CC_WIDE	Supports wide borders.
CC_STYLED	Supports styled borders.
CC_WIDESTYLED	Supports wide, styled borders.
CC_INTERIORS	Supports interiors.
CC_ROUNDRECT	Supports rectangles with rounded corners.
•	LINECAPS    Line capabilities the device supports. It can be a combination of the following:

Value	Meaning
LC_NONE	Supports no lines.
LC_POLYLINE	Supports polylines.
LC_MARKER	Supports markers.
LC_POLYMARKER	Supports polymarkers.
LC_WIDE	Supports wide lines.
LC_STYLED	Supports styled lines.
LC_WIDESTYLED	Supports wide, styled lines.
LC_INTERIORS	Supports interiors.
•	POLYGONALCAPS    Polygonal capabilities the device supports. It can be a combination of the following:

Value	Meaning
PC_NONE	Supports no polygons.
PC_POLYGON	Supports alternate fill polygons.
PC_RECTANGLE	Supports rectangles.
PC_WINDPOLYGON	Supports winding number fill polygons.
PC_SCANLINE	Supports scan lines.
PC_WIDE	Supports wide borders.
PC_STYLED	Supports styled borders.
PC_WIDESTYLED	Supports wide, styled borders.
PC_INTERIORS	Supports interiors.
•	TEXTCAPS    Text capabilities the device supports. It can be a combination of the following:

Value	Meaning
TC_OP_CHARACTER	Supports character output precision, which indicates the device can place device fonts at any pixel location. This is required for any device with device fonts.
TC_OP_STROKE	Supports stroke output precision, which indicates the device can omit any stroke of a device font.
TC_CP_STROKE	Supports stroke clip precision, which indicates the device can clip device fonts to a pixel boundary.
TC_CR_90	Supports 90-degree character rotation, which indicates the device can rotate characters only 90 degrees at a time.
TC_CR_ANY	Supports character rotation at any degree, which indicates the device can rotate device fonts through any angle.
TC_SF_X_YINDEP	Supports scaling independent of x and y directions, which indicates the device can scale device fonts separately in x and y directions.
TC_SA_DOUBLE	Supports doubled characters for scaling, which indicates the device can double the size of device fonts.
TC_SA_INTEGER	Supports integer multiples for scaling, which indicates the device can scale the size of device fonts in any integer multiple.
TC_SA_CONTIN	Supports any multiples for exact scaling, which indicates the device can scale device fonts by any amount but still preserve the x and y ratios.
TC_EA_DOUBLE	Supports double-weight characters, which indicates the device can make device fonts bold. If this bit is not set for printer drivers, GDI attempts to create bold device fonts by printing them twice.
TC_IA_ABLE	Supports italics, which indicates the device can make device fonts italic. If this bit is not set, GDI assumes italics are not available.
TC_UA_ABLE	Supports underlining, which indicates the device can underline device fonts. If this bit is not set, GDI creates underlines for device fonts.
TC_SO_ABLE	Supports strikeouts, which indicates the device can strikeout device fonts. If this bit is not set, GDI creates strikeouts for device fonts.
TC_RA_ABLE	Supports raster fonts, which indicates that GDI should enumerate any raster or TrueType fonts available for this device in response to a call to the EnumFonts or EnumFontFamilies Windows functions. If this bit is not set, GDI-supplied raster or TrueType fonts are not enumerated when these functions are called.
TC_VA_ABLE	Supports vector fonts, which indicates that GDI should enumerate any vector fonts available for this device in response to a call to the EnumFonts or EnumFontFamilies Windows functions. This is significant for vector devices only (that is, for plotters). Display drivers (which must be able to use raster fonts) and raster printer drivers always enumerate vector fonts, because GDI rasterizes vector fonts before sending them to the driver.
TC_RESERVED	Reserved; must be 0.
Remarks

Retrieves a wide range of device-specific information about the display device.

Return Value

The value of the requested capability if the function is successful.

See Also

::GetDeviceCaps


  CDC::GetFontData

Windows 3.1 Only

DWORD GetFontData( DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData ) const; ♦

dwTable    Specifies the name of the metric table to be returned. This parameter can be one of the metric tables documented in the TrueType Font Files specification published by Microsoft Corporation. If this parameter is 0, the information is retrieved starting at the beginning of the font file.

dwOffset    Specifies the offset from the beginning of the table at which to begin retrieving information. If this parameter is 0, the information is retrieved starting at the beginning of the table specified by the dwTable parameter. If this value is greater than or equal to the size of the table, GetFontData returns 0.

lpData    Points to a buffer that will receive the font information. If this value is NULL, the function returns the size of the buffer required for the font data specified in the dwTable parameter.

cbData    Specifies the length, in bytes, of the information to be retrieved. If this parameter is 0, GetFontData returns the size of the data specified in the dwTable parameter.

Remarks

Retrieves font-metric information from a scalable font file. The information to retrieve is identified by specifying an offset into the font file and the length of the information to return.

An application can sometimes use the GetFontData member function to save a TrueType font with a document. To do this, the application determines whether the font can be embedded and then retrieves the entire font file, specifying 0 for the dwTable, dwOffset, and cbData parameters.

Applications can determine whether a font can be embedded by checking the otmfsType member of the OUTLINETEXTMETRICstructure. If bit 1 of otmfsType is set, embedding is not permitted for the font. If bit 1 is clear, the font can be embedded. If bit 2 is set, the embedding is read only.

If an application attempts to use this function to retrieve information for a non-TrueType font, the GetFontData member function returns −1.

Return Value

Specifies the number of bytes returned in the buffer pointed to by lpData if the function is successful; otherwise −1.

See Also

»CDC::GetOutlineTextMetrics«, ::GetFontData, OUTLINETEXTMETRIC


  CDC::GetGlyphOutline

Windows 3.1 Only

DWORD GetGlyphOutline( UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 FAR* lpmat2 ) const; ♦

nChar    Specifies the character for which information is to be returned.

nFormat    Specifies the format in which the function is to return information. It can be one of the following values, or 0:

Value	Meaning
GGO_BITMAP	Returns the glyph bitmap. When the function returns, the buffer pointed to by lpBuffer contains a 1-bit-per-pixel bitmap whose rows start on doubleword boundaries.
GGO_NATIVE	Returns the curve data points in the rasterizer's native format, using device units. When this value is specified, any transformation specified in lpmat2 is ignored.
When the value of nFormat is 0, the function fills in a GLYPHMETRICSstructure but does not return glyph-outline data.

lpgm    Points to a GLYPHMETRICS structure that describes the placement of the glyph in the character cell.

cbBuffer    Specifies the size of the buffer into which the function copies information about the outline character. If this value is 0 and the nFormat parameter is either the GGO_BITMAP or GGO_NATIVE values, the function returns the required size of the buffer.

lpBuffer    Points to a buffer into which the function copies information about the outline character. If nFormat specifies the GGO_NATIVE value, the information is copied in the form of TTPOLYGONHEADER and TTPOLYCURVE structures. If this value is NULL and nFormat is either the GGO_BITMAP or GGO_NATIVE value, the function returns the required size of the buffer.

lpmat2    Points to a MAT2structure that contains a transformation matrix for the character. This parameter cannot be NULL, even when the GGO_NATIVE value is specified for nFormat.

Remarks

Retrieves the outline curve or bitmap for an outline character in the current font.

An application can rotate characters retrieved in bitmap format by specifying a 2-by-2 transformation matrix in the structure pointed to by lpmat2.

A glyph outline is returned as a series of contours. Each contour is defined by a TTPOLYGONHEADERstructure followed by as many TTPOLYCURVE structures as are required to describe it. All points are returned as POINTFXstructures and represent absolute positions, not relative moves. The starting point given by the pfxStart member of the TTPOLYGONHEADERstructure is the point at which the outline for a contour begins. The TTPOLYCURVEstructures that follow can be either polyline records or spline records. Polyline records are a series of points; lines drawn between the points describe the outline of the character. Spline records represent the quadratic curves used by TrueType (that is, quadratic b-splines).

Return Value

The size, in bytes, of the buffer required for the retrieved information if cbBuffer is 0 or lpBuffer is NULL. Otherwise, it is a positive value if the function is successful, or −1 if there is an error.

See Also

»CDC::GetOutlineTextMetrics«, ::GetGlyphOutline, GLYPHMETRICS, TTPOLYGONHEADER, TTPOLYCURVE


  CDC::GetKerningPairs

Windows 3.1 Only

int GetKerningPairs( int nPairs, LPKERNINGPAIR lpkrnpair ) const; ♦

nPairs    Specifies the number of KERNINGPAIRstructures pointed to by lpkrnpair. The function will not copy more kerning pairs than specified by nPairs.

lpkrnpair    Points to an array of KERNINGPAIR structures that receive the kerning pairs when the function returns. This array must contain at least as many structures as specified by nPairs. If this parameter is NULL, the function returns the total number of kerning pairs for the font.

Remarks

Retrieves the character kerning pairs for the font that is currently selected in the specified device context.

Return Value

Specifies the number of kerning pairs retrieved or the total number of kerning pairs in the font, if the function is successful. Zero is returned if the function fails or there are no kerning pairs for the font.

See Also

::GetKerningPairs, KERNINGPAIR


  CDC::GetMapMode

int GetMapMode() const;

Remarks

Retrieves the current mapping mode.

See the SetMapMode member function for a description of the mapping modes.

Return Value

The mapping mode.

See Also

»CDC::SetMapMode«, ::GetMapMode


  CDC::GetNearestColor

COLORREF GetNearestColor( COLORREF crColor ) const;

crColor    Specifies the color to be matched.

Remarks

Returns the solid color that best matches a specified logical color. The given device must be able to represent this color.

Return Value

An RGB (red, green, blue) color value that defines the solid color closest to the crColor value that the device can represent.

See Also

::GetNearestColor, »CPalette::GetNearestPaletteIndex«


  CDC::GetOutlineTextMetrics

Windows 3.1 Only

UINT GetOutlineTextMetrics( UINT cbData, LPOUTLINETEXTMETRIC lpotm ) const; ♦

cbData    Specifies the size, in bytes, of the buffer to which information is returned.

lpotm    Points to an OUTLINETEXTMETRIC structure. If this parameter is NULL, the function returns the size of the buffer required for the retrieved metric information.

Remarks

Retrieves metric information for TrueType fonts.

The OUTLINETEXTMETRIC structure contains most of the font metric information provided with the TrueType format, including a »TEXTMETRIC« structure. The last four members of the OUTLINETEXTMETRIC structure are pointers to strings. Applications should allocate space for these strings in addition to the space required for the other members. Because there is no system-imposed limit to the size of the strings, the simplest method for allocating memory is to retrieve the required size by specifying NULL for lpotm in the first call to the GetOutlineTextMetrics function.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::GetTextMetrics, ::GetOutlineTextMetrics, »CDC::GetTextMetrics«


  CDC::GetOutputCharWidth

BOOL GetOutputCharWidth( UINT nFirstChar, UINT nLastChar, LPINT lpBuffer ) const;

nFirstChar    Specifies the first character in a consecutive group of characters in the current font.

nLastChar    Specifies the last character in a consecutive group of characters in the current font.

lpBuffer    Points to a buffer that will receive the width values for a consecutive group of characters in the current font.

Remarks

Uses the output device context, m_hDC, and retrieves the widths of individual characters in a consecutive group of characters from the current font. For example, if nFirstChar identifies the letter 'a' and nLastChar identifies the letter 'z', the function retrieves the widths of all lowercase characters.

The function stores the values in the buffer pointed to by lpBuffer. This buffer must be large enough to hold all of the widths; that is, there must be at least 26 entries in the example given.

If a character in the consecutive group of characters does not exist in a particular font, it will be assigned the width value of the default character.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetCharWidth«, »CDC::m_hAttribDC«, »CDC::m_hDC«, ::GetCharWidth


  CDC::GetOutputTextExtent

CSize GetOutputTextExtent( LPCSTR lpszString, int nCount ) const;

lpszString    Points to a string of characters. You can also pass a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

Remarks

This member function uses the output device context, m_hDC, and computes the width and height of a line of text, using the current font.

The current clipping region does not affect the width and height returned by GetOutputTextExtent.

Since some devices do not place characters in regular cell arrays (that is, they carry out kerning), the sum of the extents of the characters in a string may not be equal to the extent of the string.

Return Value

The dimensions of the string (in logical units) returned in a CSize object

See Also

»CDC::GetTabbedTextExtent«, »CDC::m_hAttribDC«, »CDC::m_hDC«, »CDC::GetTextExtent«, ::GetTextExtent, »CDC::SetTextJustification«, »CSize«


  CDC::GetPixel

COLORREF GetPixel( int x, int y ) const;

COLORREF GetPixel( POINT point ) const;

x    Specifies the logical x-coordinate of the point to be examined.

y    Specifies the logical y-coordinate of the point to be examined.

point    Specifies the logical x- and y-coordinates of the point to be examined.

Remarks

Retrieves the RGB color value of the pixel at the point specified by x and y. The point must be in the clipping region. If the point is not in the clipping region, the function has no effect and returns −1.

Not all devices support the GetPixel function. For more information, see the RC_BITBLT raster capability under the »GetDeviceCaps« member function.

The GetPixel member function has two forms. The first takes two coordinate values; the second takes either a »POINT« structure or a »CPoint« object.

Return Value

For either version of the function, an RGB color value for the color of the given point. It is −1 if the coordinates do not specify a point in the clipping region.

See Also

»CDC::GetDeviceCaps«, »CDC::SetPixel«, ::GetPixel, »POINT«, »CPoint«


  CDC::GetPolyFillMode

int GetPolyFillMode() const;

Remarks

Retrieves the current polygon-filling mode.

See the SetPolyFillMode member function for a description of the polygon-filling modes.

Return Value

The current polygon-filled mode, ALTERNATE or WINDING, if the function is successful.

See Also

»CDC::SetPolyFillMode«, ::GetPolyFillMode


  CDC::GetROP2

int GetROP2() const;

Remarks

Retrieves the current drawing mode. The drawing mode specifies how the colors of the pen and the interior of filled objects are combined with the color already on the display surface.

Return Value

The drawing mode. For a list of the drawing mode values, see the SetROP2 member function.

See Also

»CDC::GetDeviceCaps«, »CDC::SetROP2«, ::GetROP2


  CDC::GetSafeHdc

HDC GetSafeHdc() const;

Remarks

Call this member function to get »m_hDC«, the output device context. This member function also works with null pointers.

Return Value

A device context handle.


  CDC::GetStretchBltMode

int GetStretchBltMode() const;

Remarks

Retrieves the current bitmap-stretching mode. The bitmap-stretching mode defines how information is removed from bitmaps that are stretched or compressed by the StretchBlt member function.

The STRETCH_ANDSCANS and STRETCH_ORSCANS modes are typically used to preserve foreground pixels in monochrome bitmaps. The STRETCH_DELETESCANS mode is typically used to preserve color in color bitmaps.

Return Value

The return value specifies the current bitmap-stretching mode — STRETCH_ANDSCANS, STRETCH_DELETESCANS, or STRETCH_ORSCANS — if the function is successful.

See Also

»CDC::StretchBlt«, »CDC::SetStretchBltMode«, ::GetStretchBltMode


  CDC::GetOutputTabbedTextExtent

CSize GetOutputTabbedTextExtent( LPCSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions ) const;

lpszString    Points to a character string. You can also pass a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

nTabPositions    Specifies the number of tab-stop positions in the array pointed to by lpnTabStopPositions.

lpnTabStopPositions    Points to an array of integers containing the tab-stop positions in logical units. The tab stops must be sorted in increasing order; the smallest x-value should be the first item in the array. Back tabs are not allowed.

Remarks

Computes the width and height of a character string using m_hDC, the output device context. If the string contains one or more tab characters, the width of the string is based upon the tab stops specified by lpnTabStopPositions. The function uses the currently selected font to compute the dimensions of the string.

The current clipping region does not offset the width and height returned by the GetOutputTabbedTextExtent function.

Since some devices do not place characters in regular cell arrays (that is, they kern the characters), the sum of the extents of the characters in a string may not be equal to the extent of the string.

If nTabPositions is 0 and lpnTabStopPositions is NULL, tabs are expanded to eight average character widths.

If nTabPositions is 1, the tab stops will be separated by the distance specified by the first value in the array to which lpnTabStopPositions points.

If lpnTabStopPositions points to more than a single value, a tab stop is set for each value in the array, up to the number specified by nTabPositions.

Return Value

The dimensions of the string (in logical units).

See Also

»CDC::GetTextExtent«, »CDC::m_hAttribDC«, »CDC::m_hDC«, »CDC::GetTabbedTextExtent«, »CDC::GetOutputTextExtent«, »CDC::TabbedTextOut«, ::GetTabbedTextExtent, »CSize«


  CDC::GetOutputTextMetrics

BOOL GetOutputTextMetrics( LPTEXTMETRIC lpMetrics ) const;

lpMetrics    Points to the TEXTMETRIC structure that receives the metrics.

Remarks

Retrieves the metrics for the current font using m_hDC, the output device context.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetTextAlign«, »CDC::m_hAttribDC«, »CDC::m_hDC«, »CDC::GetTextMetrics«, »CDC::GetTextExtent«, »CDC::GetTextFace«, »CDC::SetTextJustification«, ::GetTextMetrics


  CDC::GetTabbedTextExtent

CSize GetTabbedTextExtent( LPCSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions ) const;

lpszString    Points to a character string. You can also pass a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

nTabPositions    Specifies the number of tab-stop positions in the array pointed to by lpnTabStopPositions.

lpnTabStopPositions    Points to an array of integers containing the tab-stop positions in logical units. The tab stops must be sorted in increasing order; the smallest x-value should be the first item in the array. Back tabs are not allowed.

Remarks

Computes the width and height of a character string using m_hAttribDC, the attribute device context. If the string contains one or more tab characters, the width of the string is based upon the tab stops specified by lpnTabStopPositions. The function uses the currently selected font to compute the dimensions of the string.

The current clipping region does not offset the width and height returned by the GetTabbedTextExtent function.

Since some devices do not place characters in regular cell arrays (that is, they kern the characters), the sum of the extents of the characters in a string may not be equal to the extent of the string.

If nTabPositions is 0 and lpnTabStopPositions is NULL, tabs are expanded to eight times the average character width.

If nTabPositions is 1, the tab stops will be separated by the distance specified by the first value in the array to which lpnTabStopPositions points.

If lpnTabStopPositions points to more than a single value, a tab stop is set for each value in the array, up to the number specified by nTabPositions.

Return Value

The dimensions of the string (in logical units).

See Also

»CDC::GetTextExtent«, »CDC::GetOutputTabbedTextExtent«, »CDC::GetOutputTextExtent«, »CDC::TabbedTextOut«, ::GetTabbedTextExtent, »CSize«


  CDC::GetTextAlign

UINT GetTextAlign() const;

Remarks

Retrieves the status of the text-alignment flags for the device context.

The text-alignment flags determine how the TextOut and ExtTextOut member functions align a string of text in relation to the string's starting point. The text-alignment flags are not necessarily single-bit flags and may be equal to 0. To test whether a flag is set, an application should follow these steps:

1.	Apply the bitwise-OR operator to the flag and its related flags. The following list shows the groups of related flags:

•	TA_LEFT, TA_CENTER, and TA_RIGHT

•	TA_BASELINE, TA_BOTTOM, and TA_TOP

•	TA_NOUPDATECP and TA_UPDATECP

2.	Apply the bitwise-AND operator to the result and the return value of GetTextAlign.

3.	Test for the equality of this result and the flag.

Return Value

The status of the text-alignment flags. The return value is one or more of the following values, with the meaning as given:

•	TA_BASELINE    Specifies alignment of the x-axis and the baseline of the chosen font within the bounding rectangle.

•	TA_BOTTOM    Specifies alignment of the x-axis and the bottom of the bounding rectangle.

•	TA_CENTER    Specifies alignment of the y-axis and the center of the bounding rectangle.

•	TA_LEFT    Specifies alignment of the y-axis and the left side of the bounding rectangle.

•	TA_NOUPDATECP    Specifies that the current position is not updated.

•	TA_RIGHT    Specifies alignment of the y-axis and the right side of the bounding rectangle.

•	TA_TOP    Specifies alignment of the x-axis and the top of the bounding rectangle.

•	TA_UPDATECP    Specifies that the current position is updated.

See Also

»CDC::ExtTextOut«, »CDC::SetTextAlign«, »CDC::TextOut«, ::GetTextAlign


  CDC::GetTextCharacterExtra

int GetTextCharacterExtra() const;

Remarks

Retrieves the current setting for the amount of intercharacter spacing. GDI adds this spacing to each character, including break characters, when it writes a line of text to the device context.

The default value for the amount of intercharacter spacing is 0.

Return Value

The amount of the intercharacter spacing.

See Also

»CDC::SetTextCharacterExtra«, ::GetTextCharacterExtra


  CDC::GetTextColor

COLORREF GetTextColor() const;

Remarks

Retrieves the current text color. The text color is the foreground color of characters drawn by using the GDI text-output member functions »TextOut«, »ExtTextOut«, and »TabbedTextOut«.

Return Value

The current text color as an RGB color value.

See Also

»CDC::GetBkColor«, »CDC::GetBkMode«, »CDC::SetBkMode«, »CDC::SetTextColor«, ::GetTextColor


  CDC::GetTextExtent

CSize GetTextExtent( LPCSTR lpszString, int nCount ) const;

lpszString    Points to a string of characters. You can also pass a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

Remarks

Computes the width and height of a line of text using the current font to determine the dimensions. The information is retrieved from m_hAttribDC, the attribute device context.

The current clipping region does not affect the width and height returned by GetTextExtent.

Since some devices do not place characters in regular cell arrays (that is, they carry out kerning), the sum of the extents of the characters in a string may not be equal to the extent of the string.

Return Value

The dimensions of the string (in logical units) in a CSize object.

See Also

»CDC::GetTabbedTextExtent«, »CDC::m_hAttribDC«, »CDC::m_hDC«, »CDC::GetOutputTextExtent«, ::GetTextExtent, »CDC::SetTextJustification«, »CSize«


  CDC::GetTextFace

int GetTextFace( int nCount, LPSTR lpszFacename ) const;

nCount    Specifies the size of the buffer (in bytes). If the typeface name is longer than the number of bytes specified by this parameter, the name is truncated.

lpszFacename    Points to the buffer for the typeface name.

Remarks

Copies the typeface name of the current font into a buffer. The typeface name is copied as a null-terminated string.

Return Value

The number of bytes copied to the buffer, not including the terminating null character. It is 0 if an error occurs.

See Also

»CDC::GetTextMetrics«, »CDC::SetTextAlign«, »CDC::TextOut«, ::GetTextFace


  CDC::GetTextMetrics

BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics ) const;

lpMetrics    Points to the »TEXTMETRIC« structure that receives the metrics.

Remarks

Retrieves the metrics for the current font using the attribute device context.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetTextAlign«, »CDC::m_hAttribDC«, »CDC::m_hDC«, »CDC::GetOutputTextMetrics«, »CDC::GetTextExtent«, »CDC::GetTextFace«, »CDC::SetTextJustification«, ::GetTextMetrics

A TEXTMETRIC structure has this form:

typedef struct tagTEXTMETRIC {  /* tm */

    int  tmHeight;

    int  tmAscent;

    int  tmDescent;

    int  tmInternalLeading;

    int  tmExternalLeading;

    int  tmAveCharWidth;

    int  tmMaxCharWidth;

    int  tmWeight;

    BYTE tmItalic;

    BYTE tmUnderlined;

    BYTE tmStruckOut;

    BYTE tmFirstChar;

    BYTE tmLastChar;

    BYTE tmDefaultChar;

    BYTE tmBreakChar;

    BYTE tmPitchAndFamily;

    BYTE tmCharSet;

    int  tmOverhang;

    int  tmDigitizedAspectX;

    int  tmDigitizedAspectY;

} TEXTMETRIC;

For more complete information about this structure, see TEXTMETRICin the Windows SDK.


  CDC::GetViewportExt

CSize GetViewportExt() const;

Remarks

Retrieves the x- and y-extents of the device context's viewport.

Return Value

The x- and y-extents (in device units) as a CSize object.

See Also

»CDC::SetViewportExt«, »CSize«, ::GetViewportExt, »CDC::SetWindowExt«


  CDC::GetViewportOrg

CPoint GetViewportOrg() const;

Remarks

Retrieves the x- and y-coordinates of the origin of the viewport associated with the device context.

Return Value

The origin of the viewport (in device coordinates) as a CPoint object.

See Also

»CDC::GetWindowOrg«, »CPoint«, ::GetViewportOrg, »CDC::SetViewportOrg«


  CDC::GetWindowExt

CSize GetWindowExt() const;

Remarks

Retrieves the x- and y-extents of the window associated with the device context.

Return Value

The x- and y-extents (in logical units) as a CSize object.

See Also

»CDC::SetWindowExt«, »CSize«, ::GetWindowExt, »CDC::GetViewportExt«


  CDC::GetWindowOrg

CPoint GetWindowOrg() const;

Remarks

Retrieves the x- and y-coordinates of the origin of the window associated with the device context.

Return Value

The origin of the window (in logical coordinates) as a CPoint object.

See Also

»CDC::GetViewportOrg«, »CDC::SetWindowOrg«, »CPoint«, ::GetWindowOrg


  CDC::GrayString

virtual BOOL GrayString( CBrush* pBrush, BOOL ( CALLBACK EXPORT* lpfnOutput )( HDC, LPARAM, int ), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight );

pBrush    Identifies the brush to be used for dimming (graying).

lpfnOutput    Specifies the procedure-instance address of the application-supplied callback function that will draw the string. For more information, see the description of the Windows OutputFunc »callback function« below. If this parameter is NULL, the system uses the Windows TextOut function to draw the string, and lpData is assumed to be a long pointer to the character string to be output.

lpData    Specifies a far pointer to data to be passed to the output function. If lpfnOutput is NULL, lpData must be a long pointer to the string to be output.

nCount    Specifies the number of characters to be output. If this parameter is 0, GrayString calculates the length of the string (assuming that lpData is a pointer to the string). If nCount is −1 and the function pointed to by lpfnOutput returns 0, the image is shown but not dimmed.

x    Specifies the logical x-coordinate of the starting position of the rectangle that encloses the string.

y    Specifies the logical y-coordinate of the starting position of the rectangle that encloses the string.

nWidth    Specifies the width (in logical units) of the rectangle that encloses the string. If nWidth is 0, GrayString calculates the width of the area, assuming lpData is a pointer to the string.

nHeight    Specifies the height (in logical units) of the rectangle that encloses the string. If nHeight is 0, GrayString calculates the height of the area, assuming lpData is a pointer to the string.

Remarks

Draws dimmed (gray) text at the given location by writing the text in a memory bitmap, dimming the bitmap, and then copying the bitmap to the display. The function dims the text regardless of the selected brush and background. The GrayString member function uses the currently selected font. The MM_TEXT mapping mode must be selected before using this function.

An application can draw dimmed (grayed) strings on devices that support a solid gray color without calling the GrayString member function. The system color COLOR_GRAYTEXT is the solid-gray system color used to draw disabled text. The application can call the GetSysColor Windows function to retrieve the color value of COLOR_GRAYTEXT. If the color is other than 0 (black), the application can call the SetTextColor member function to set the text color to the color value and then draw the string directly. If the retrieved color is black, the application must call GrayString to dim (gray) the text.

If lpfnOutput is NULL, GDI uses the Windows TextOutfunction, and lpData is assumed to be a far pointer to the character to be output. If the characters to be output cannot be handled by the TextOut member function (for example, the string is stored as a bitmap), the application must supply its own output function.

Also note that all callback functions must trap Microsoft Foundation exceptions before returning to Windows, since exceptions cannot be thrown across callback boundaries. For more information about exceptions, see Chapter 16 in the Class Library User's Guide.

The callback function passed to GrayString must use the Pascal calling convention, must be exported with __export, and must be declared FAR.

When the framework is in preview mode, a call to the GrayString member function is translated to a TextOut call, and the callback function is not called.

Callback Function

BOOL CALLBACK EXPORT OutputFunc( HDC hDC, LPARAM lpData, int nCount );

OutputFunc is a placeholder for the application-supplied callback function name. The callback function (OutputFunc) must draw an image relative to the coordinates (0,0) rather than (x, y). The parameters are described below:

hDC    Identifies a memory device context with a bitmap of at least the width and height specified by nWidth and nHeight to GrayString.

lpData    Points to the character string to be drawn.

nCount    Specifies the number of characters to output.

Return Value

The callback function's return value must be TRUE to indicate success; otherwise it is FALSE.

Return Value

Nonzero if the string is drawn, or 0 if either the TextOut function or the application-supplied output function returned 0, or there was insufficient memory to create a memory bitmap for dimming.

See Also

::GetSysColor, »CDC::SetTextColor«, »CDC::TextOut«, ::GrayString


  CDC::IntersectClipRect

virtual int IntersectClipRect( int x1, int y1, int x2, int y2 );

virtual int IntersectClipRect( LPCRECT lpRect );

x1    Specifies the logical x-coordinate of the upper-left corner of the rectangle.

y1    Specifies the logical y-coordinate of the upper-left corner of the rectangle.

x2    Specifies the logical x-coordinate of the lower-right corner of the rectangle.

y2    Specifies the logical y-coordinate of the lower-right corner of the rectangle.

lpRect    Specifies the rectangle. You can pass either a »CRect« object or a pointer to a »RECT« structure for this parameter.

Remarks

Creates a new clipping region by forming the intersection of the current region and the rectangle specified by x1, y1, x2, and y2. GDI clips all subsequent output to fit within the new boundary. The width and height must not exceed 32,767.

Return Value

The new clipping region's type. It can be any one of the following values, with the meaning as given:

•	COMPLEXREGION    New clipping region has overlapping borders.

•	ERROR    Device context is not valid.

•	NULLREGION    New clipping region is empty.

•	SIMPLEREGION    New clipping region has no overlapping borders.

See Also

::IntersectClipRect, »CRect«, »RECT«


  CDC::InvertRect

void InvertRect( LPCRECT lpRect );

lpRect    Points to a »RECT« that contains the logical coordinates of the rectangle to be inverted. You can also pass a CRect object for this parameter.

Remarks

Inverts the contents of the given rectangle. Inversion is a logical NOT operation and flips the bits of each pixel. On monochrome displays, the function makes white pixels black and black pixels white. On color displays, the inversion depends on how colors are generated for the display. Calling InvertRect twice with the same rectangle restores the display to its previous colors.

If the rectangle is empty, nothing is drawn.

See Also

»CDC::FillRect«, ::InvertRect, »CRect«, »RECT struct«


  CDC::InvertRgn

BOOL InvertRgn( CRgn* pRgn );

pRgn    Identifies the region to be inverted. The coordinates for the region are specified in device units.

Remarks

Inverts the colors in the region specified by pRgn. On monochrome displays, the function makes white pixels black and black pixels white. On color displays, the inversion depends on how the colors are generated for the display.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::FillRgn«, »CDC::PaintRgn«, »CRgn«, ::InvertRgn


  CDC::IsPrinting

BOOL IsPrinting() const;

Return Value

Nonzero if the CDC object is currently printing; otherwise 0.


  CDC::LineTo

BOOL LineTo( int x, int y );

BOOL LineTo( POINT point );

x    Specifies the logical x-coordinate of the endpoint for the line.

y    Specifies the logical y-coordinate of the endpoint for the line.

point    Specifies the endpoint for the line. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Draws a line from the current position up to, but not including, the point specified by x and y (or point). The line is drawn with the selected pen. The current position is set to x,y or to point.

Return Value

Nonzero if the line is drawn; otherwise 0.

See Also

»CDC::MoveTo«, »CDC::GetCurrentPosition«, ::LineTo, »CPoint«, »POINT«


  CDC::LPtoDP

void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;

void LPtoDP( LPRECT lpRect ) const;

lpPoints    Points to an array of points. Each point in the array is a »POINT« structure or a »CPoint« object.

nCount    Specifies the number of points in the array.

lpRect    Points to a »RECT« structure or a »CRect« object. This parameter is used for the common case of mapping a rectangle from logical to device units.

Remarks

Converts logical points into device points. The function maps the coordinates of each point from GDI's logical coordinate system into a device coordinate system. The conversion depends on the current mapping mode and the settings of the origins and extents of the device's window and viewport.

The x- and y-coordinates of points are 2-byte signed integers in the range −32,768 through 32,767. In cases where the mapping mode would result in values larger than these limits, the system sets the values to −32,768 and 32,767, respectively.

See Also

»CDC::DPtoLP«, ::LPtoDP, »CPoint«, »POINT«, »RECT«, »CRect«


  CDC::MoveTo

CPoint MoveTo( int x, int y );

CPoint MoveTo( POINT point );

x    Specifies the logical x-coordinate of the new position.

y    Specifies the logical y-coordinate of the new position.

point    Specifies the new position. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Moves the current position to the point specified by x and y (or by point).

Return Value

The x- and y-coordinates of the previous position as a CPoint object.

See Also

»CDC::GetCurrentPosition«, »CDC::LineTo«, ::MoveTo, »CPoint«, »POINT«


  CDC::OffsetClipRgn

virtual int OffsetClipRgn( int x, int y );

virtual int OffsetClipRgn( SIZE size );

x    Specifies the number of logical units to move left or right.

y    Specifies the number of logical units to move up or down.

size    Specifies the amount to offset.

Remarks

Moves the clipping region of the device context by the specified offsets. The function moves the region x units along the x-axis and y units along the y-axis.

Return Value

The new region's type. It can be any one of the following values, with the meanings as given:

•	COMPLEXREGION    Clipping region has overlapping borders.

•	ERROR    Device context is not valid.

•	NULLREGION    Clipping region is empty.

•	SIMPLEREGION    Clipping region has no overlapping borders.

See Also

»CDC::SelectClipRgn«, ::OffsetClipRgn


  CDC::OffsetViewportOrg

virtual CPoint OffsetViewportOrg( int nWidth, int nHeight );

nWidth    Specifies the number of device units to add to the current origin's x-coordinate.

nHeight    Specifies the number of device units to add to the current origin's y-coordinate.

Remarks

Modifies the coordinates of the viewport origin relative to the coordinates of the current viewport origin.

Return Value

The previous viewport origin (in device coordinates) as a »CPoint« object.

See Also

»CDC::GetViewportOrg«, »CDC::OffsetWindowOrg«, »CDC::SetViewportOrg«, ::OffsetViewportOrg, »CPoint«


  CDC::OffsetWindowOrg

CPoint OffsetWindowOrg( int nWidth, int nHeight );

nWidth    Specifies the number of logical units to add to the current origin's x-coordinate.

nHeight    Specifies the number of logical units to add to the current origin's y-coordinate.

Remarks

Modifies the coordinates of the window origin relative to the coordinates of the current window origin.

Return Value

The previous window origin (in logical coordinates) as a »CPoint« object.

See Also

»CDC::GetWindowOrg«, »CDC::OffsetViewportOrg«, »CDC::SetWindowOrg«, ::OffsetWindowOrg, »CPoint«


  CDC::PaintRgn

BOOL PaintRgn( CRgn* pRgn );

pRgn    Identifies the region to be filled. The coordinates for the given region are specified in device units.

Remarks

Fills the region specified by pRgn using the current brush.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CBrush«, »CDC::SelectObject«, »CDC::FillRgn«, ::PaintRgn, »CRgn«


  CDC::PatBlt

BOOL PatBlt( int x, int y, int nWidth, int nHeight, DWORD
dwRop );

x    Specifies the logical x-coordinate of the upper-left corner of the rectangle that is to receive the pattern.

y    Specifies the logical y-coordinate of the upper-left corner of the rectangle that is to receive the pattern.

nWidth    Specifies the width (in logical units) of the rectangle that is to receive the pattern.

nHeight    Specifies the height (in logical units) of the rectangle that is to receive the pattern.

dwRop    Specifies the raster-operation code. Raster-operation codes (ROPs) define how GDI combines colors in output operations that involve a current brush, a possible source bitmap, and a destination bitmap. This parameter may be one of the following values, with the meanings as given:

•	PATCOPY    Copies pattern to destination bitmap.

•	PATINVERT    Combines destination bitmap with pattern using the Boolean XOR operator.

•	DSTINVERT    Inverts the destination bitmap.

•	BLACKNESS    Turns all output black.

•	WHITENESS    Turns all output white.

Windows 3.1 Only

•	PATPAINT    Paints the destination bitmap. ♦

Remarks

Creates a bit pattern on the device. The pattern is a combination of the selected brush and the pattern already on the device. The raster-operation code specified by dwRop defines how the patterns are to be combined. The raster operations listed for this function are a limited subset of the full 256 ternary raster-operation codes; in particular, a raster-operation code that refers to a source cannot be used.

Not all device contexts support the PatBlt function. To determine whether a device context supports PatBlt, call the GetDeviceCaps member function with the RASTERCAPS index and check the return value for the RC_BITBLT flag.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetDeviceCaps«, ::PatBlt


  CDC::Pie

BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );

x1    Specifies the x-coordinate of the upper-left corner of the bounding rectangle (in logical units).

y1    Specifies the y-coordinate of the upper-left corner of the bounding rectangle (in logical units).

x2    Specifies the x-coordinate of the lower-right corner of the bounding rectangle (in logical units).

y2    Specifies the y-coordinate of the lower-right corner of the bounding rectangle (in logical units).

x3    Specifies the x-coordinate of the arc's starting point (in logical units). This point does not have to lie exactly on the arc.

y3    Specifies the y-coordinate of the arc's starting point (in logical units). This point does not have to lie exactly on the arc.

x4    Specifies the x-coordinate of the arc's endpoint (in logical units). This point does not have to lie exactly on the arc.

y4    Specifies the y-coordinate of the arc's endpoint (in logical units). This point does not have to lie exactly on the arc.

lpRect    Specifies the bounding rectangle. You can pass either a »CRect« object or a pointer to a »RECT« structure for this parameter.

ptStart    Specifies the starting point of the arc. This point does not have to lie exactly on the arc. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

ptEnd    Specifies the endpoint of the arc. This point does not have to lie exactly on the arc. You can pass either a POINT structure or a CPoint object for this parameter.

Remarks

Draws a pie-shaped wedge by drawing an elliptical arc whose center and two endpoints are joined by lines. The center of the arc is the center of the bounding rectangle specified by x1, y1, x2, and y2 (or by lpRect). The starting and ending points of the arc are specified by x3, y3, x4, and y4 (or by ptStart and ptEnd).

The arc is drawn with the selected pen, moving in a counterclockwise direction. Two additional lines are drawn from each endpoint to the arc's center. The pie-shaped area is filled with the current brush. If x3 equals x4 and y3 equals y4, the result is an ellipse with a single line from the center of the ellipse to the point (x3, y3) or (x4, y4).

The figure drawn by this function extends up to but does not include the right and bottom coordinates. This means that the height of the figure is y2 − y1 and the width of the figure is x2 − x1. Both the width and the height of the bounding rectangle must be greater than 2 units and less than 32,767 units.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Chord«, ::Pie, »RECT«, »POINT«, »CRect«, »CPoint«


  CDC::PlayMetaFile

BOOL PlayMetaFile( HMETAFILE hMF );

hMF    Identifies the metafile to be played.

Remarks

Plays the contents of the specified metafile on the device context. The metafile can be played any number of times.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::PlayMetaFile


  CDC::Polygon

BOOL Polygon( LPPOINT lpPoints, int nCount );

lpPoints    Points to an array of points that specify the vertices of the polygon. Each point in the array is a »POINT« structure or a »CPoint« object.

nCount    Specifies the number of vertices in the array.

Remarks

Draws a polygon consisting of two or more points (vertices) connected by lines, using the current pen. The system closes the polygon automatically, if necessary, by drawing a line from the last vertex to the first.

The current polygon-filling mode can be retrieved or set by using the GetPolyFillMode and SetPolyFillMode member functions.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetPolyFillMode«, CDC::PolyLine, »CDC::PolyPolygon«, »CDC::SetPolyFillMode«, ::Polygon, »CPoint«


  CDC::Polyline

BOOL Polyline( LPPOINT lpPoints, int nCount );

lpPoints    Points to an array of POINT structures or CPoint objects to be connected.

nCount    Specifies the number of points in the array. This value must be at least 2.

Remarks

Draws a set of line segments connecting the points specified by lpPoints. The lines are drawn from the first point through subsequent points using the current pen. Unlike the LineTo member function, the Polyline function neither uses nor updates the current position.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::LineTo«, »CDC::Polygon«, ::PolyLine, »POINT«, »CPoint«


  CDC::PolyPolygon

BOOL PolyPolygon( LPPOINT lpPoints, LPINT lpPolyCounts, int nCount );

lpPoints    Points to an array of »POINT« structures or »CPoint« objects that define the vertices of the polygons.

lpPolyCounts    Points to an array of integers, each of which specifies the number of points in one of the polygons in the lpPoints array.

nCount    The number of entries in the lpPolyCounts array. This number specifies the number of polygons to be drawn. This value must be at least 2.

Remarks

Creates two or more polygons that are filled using the current polygon-filling mode. The polygons may be disjoint or overlapping.

Each polygon specified in a call to the PolyPolygon function must be closed. Unlike polygons created by the Polygon member function, the polygons created by PolyPolygon are not closed automatically.

The function creates two or more polygons. To create a single polygon, an application should use the Polygon member function.

The current polygon-filling mode can be retrieved or set by using the GetPolyFillMode and SetPolyFillMode member functions.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::GetPolyFillMode«, »CDC::Polygon«, »CDC::Polyline«, »CDC::SetPolyFillMode«, ::PolyPolygon, »POINT«, »CPoint«


  CDC::PtVisible

virtual BOOL PtVisible( int x, int y ) const;

virtual BOOL PtVisible( POINT point ) const;

x    Specifies the logical x-coordinate of the point.

y    Specifies the logical y-coordinate of the point.

point    Specifies the point to check in logical coordinates. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Determines whether the given point is within the clipping region of the device context.

Return Value

Nonzero if the specified point is within the clipping region; otherwise 0.

See Also

»CDC::RectVisible«, »CDC::SelectClipRgn«, »CPoint«, ::PtVisible, »POINT«


  CDC::QueryAbort

Windows 3.1 Only

BOOL QueryAbort() const; ♦

Remarks

Calls the abort function installed by the »SetAbortProc« member function for a printing application and queries whether the printing should be terminated.

Return Value

The return value is nonzero if printing should continue or if there is no abort procedure. It is 0 if the print job should be terminated. The return value is supplied by the abort function.

See Also

»CDC::SetAbortProc«,


  CDC::RealizePalette

UINT RealizePalette();

Remarks

Maps entries from the current logical palette to the system palette.

A logical color palette acts as a buffer between color-intensive applications and the system, allowing an application to use as many colors as needed without interfering with its own displayed colors or with colors displayed by other windows.

When a window has the input focus and calls RealizePalette, Windows ensures that the window will display all the requested colors, up to the maximum number simultaneously available on the screen. Windows also displays colors not found in the window's palette by matching them to available colors.

In addition, Windows matches the colors requested by inactive windows that call the function as closely as possible to the available colors. This significantly reduces undesirable changes in the colors displayed in inactive windows.

Return Value

Indicates how many entries in the logical palette were mapped to different entries in the system palette. This represents the number of entries that this function remapped to accommodate changes in the system palette since the logical palette was last realized.

See Also

»CDC::SelectPalette«, »CPalette«, ::RealizePalette


  CDC::Rectangle

BOOL Rectangle( int x1, int y1, int x2, int y2 );

BOOL Rectangle( LPCRECT lpRect );

x1    Specifies the x-coordinate of the upper-left corner of the rectangle (in logical units).

y1    Specifies the y-coordinate of the upper-left corner of the rectangle (in logical units).

x2    Specifies the x-coordinate of the lower-right corner of the rectangle (in logical units).

y2    Specifies the y-coordinate of the lower-right corner of the rectangle (in logical units).

lpRect    Specifies the rectangle in logical units. You can pass either a »CRect« object or a pointer to a »RECT« structure for this parameter.

Remarks

Draws a rectangle using the current pen. The interior of the rectangle is filled using the current brush.

The rectangle extends up to, but does not include, the right and bottom coordinates. This means that the height of the rectangle is y2 − y1 and the width of the rectangle is x2 − x1. Both the width and the height of a rectangle must be greater than 2 units and less than 32,767 units.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::Rectangle, »CDC::PolyLine«, »CDC::RoundRect«, »RECT«, »CRect«


  CDC::RectVisible

virtual BOOL RectVisible( LPCRECT lpRect ) const;

lpRect    Points to a »RECT« structure or a »CRect« object that contains the logical coordinates of the specified rectangle.

Remarks

Determines whether any part of the given rectangle lies within the clipping region of the display context.

Return Value

Nonzero if some portion of the given rectangle lies within the clipping region; otherwise 0.

See Also

»CDC::PtVisible«, »CDC::SelectClipRgn«, »CRect«, ::RectVisible, »RECT«


  CDC::ReleaseAttribDC

virtual void ReleaseAttribDC();

Remarks

Call this member function to set m_hAttribDC to NULL. This does not cause a Detach to occur. Only the output device context is attached to the CDC object, and only it can be detached.

See Also

»CDC::SetOutputDC«, »CDC::SetAttribDC«, »CDC::ReleaseOutputDC«, »CDC::m_hAttribDC«


  CDC::ReleaseOutputDC

virtual void ReleaseOutputDC();

Remarks

Call this member function to set the m_hDC member to NULL. This member function cannot be called when the output device context is attached to the CDC object. Use the Detach member function to detach the output device context.

See Also

»CDC::SetAttribDC«, »CDC::SetOutputDC«, »CDC::ReleaseAttribDC«, »CDC::m_hDC«


  CDC::ResetDC

Windows 3.1 Only

BOOL ResetDC( const DEVMODE FAR* lpDevMode ); ♦

lpDevMode    A pointer to a Windows »DEVMODE« structure.

Remarks

Call this member function to update the device context wrapped by the CDC object. The device context is updated from the information specified in the Windows DEVMODE structure.  This member function only resets the attribute device context.

An application will typically use the ResetDC member function when a window handles a WM_DEVMODECHANGE message. You can also use this member function to change the paper orientation or paper bins while printing a document.

You cannot use this member function to change the driver name, device name or the output port. When the user changes the port connection or device name, you must delete the original device context and create a new device context with the new information.

Before you call this member function, you must ensure that all objects (other than stock objects) that had been selected into the device context have been selected out.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::m_hAttribDC«, ::ResetDC, WM_DEVMODECHANGE, »DEVMODE«


  CDC::RestoreDC

virtual BOOL RestoreDC( int nSavedDC );

nSavedDC    Specifies the device context to be restored. It can be a value returned by a previous SaveDC function call. If nSavedDC is −1, the most recently saved device context is restored.

Remarks

Restores the device context to the previous state identified by nSavedDC. RestoreDC restores the device context by popping state information off a stack created by earlier calls to the SaveDC member function.

The stack can contain the state information for several device contexts. If the context specified by nSavedDC is not at the top of the stack, RestoreDC deletes all state information between the device context specified by nSavedDC and the top of the stack. The deleted information is lost.

Return Value

Nonzero if the specified context was restored; otherwise 0.

See Also

»CDC::SaveDC«, ::RestoreDC


  CDC::RoundRect

BOOL RoundRect( int x1, int y1, int x2, int y2, int x3, int y3 );

BOOL RoundRect( LPCRECT lpRect, POINT point );

x1    Specifies the x-coordinate of the upper-left corner of the rectangle (in logical units).

y1    Specifies the y-coordinate of the upper-left corner of the rectangle (in logical units).

x2    Specifies the x-coordinate of the lower-right corner of the rectangle (in logical units).

y2    Specifies the y-coordinate of the lower-right corner of the rectangle (in logical units).

x3    Specifies the width of the ellipse used to draw the rounded corners (in logical units).

y3    Specifies the height of the ellipse used to draw the rounded corners (in logical units).

lpRect    Specifies the bounding rectangle in logical units. You can pass either a »CRect« object or a pointer to a »RECT« structure for this parameter.

point    The x-coordinate of point specifies the width of the ellipse to draw the rounded corners (in logical units). The y-coordinate of point specifies the height of the ellipse to draw the rounded corners (in logical units). You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Draws a rectangle with rounded corners using the current pen. The interior of the rectangle is filled using the current brush.

The figure this function draws extends up to but does not include the right and bottom coordinates. This means that the height of the figure is y2 − y1 and the width of the figure is x2 − x1. Both the height and the width of the bounding rectangle must be greater than 2 units and less than 32,767 units.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::Rectangle«, ::RoundRect, »CRect«, »RECT«, »POINT«, »CPoint«


  CDC::SaveDC

virtual int SaveDC();

Remarks

Saves the current state of the device context by copying state information (such as clipping region, selected objects, and mapping mode) to a context stack maintained by Windows. The saved device context can later be restored by using RestoreDC.

SaveDC can be used any number of times to save any number of device-context states.

Return Value

An integer identifying the saved device context. It is 0 if an error occurs. This return value can be used to restore the device context by calling RestoreDC.

See Also

»CDC::RestoreDC«, ::SaveDC


  CDC::ScaleViewportExt

virtual CSize ScaleViewportExt( int xNum, int xDenom, int yNum, int yDenom );

xNum    Specifies the amount by which to multiply the current x-extent.

xDenom    Specifies the amount by which to divide the result of multiplying the current x-extent by the value of the xNum parameter.

yNum    Specifies the amount by which to multiply the current y-extent.

yDenom    Specifies the amount by which to divide the result of multiplying the current y-extent by the value of the yNum parameter.

Remarks

Modifies the viewport extents relative to the current values. The formulas are written as follows:

xNewVE = ( xOldVE * xNum ) / xDenom
yNewVE = ( yOldVE * yNum ) / yDenom

The new viewport extents are calculated by multiplying the current extents by the given numerator and then dividing by the given denominator.

Return Value

The previous viewport extents (in device units) as a »CSize« object.

See Also

»CDC::GetViewportExt«, ::ScaleViewportExt, »CSize«


  CDC::ScaleWindowExt

virtual CSize ScaleWindowExt( int xNum, int xDenom, int yNum, int
yDenom );

xNum    Specifies the amount by which to multiply the current x-extent.

xDenom    Specifies the amount by which to divide the result of multiplying the current x-extent by the value of the xNum parameter.

yNum    Specifies the amount by which to multiply the current y-extent.

yDenom    Specifies the amount by which to divide the result of multiplying the current y-extent by the value of the yNum parameter.

Remarks

Modifies the window extents relative to the current values. The formulas are written as follows:

xNewWE = ( xOldWE * xNum ) / xDenom
yNewWE = ( yOldWE * yNum ) / yDenom

The new window extents are calculated by multiplying the current extents by the given numerator and then dividing by the given denominator.

Return Value

The previous window extents (in logical units) as a »CSize« object.

See Also

»CDC::GetWindowExt«, ::ScaleWindowExt, »CSize«


  CDC::ScrollDC

BOOL ScrollDC( int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, CRgn* pRgnUpdate, LPRECT lpRectUpdate );

dx    Specifies the number of horizontal scroll units.

dy    Specifies the number of vertical scroll units.

lpRectScroll    Points to the »RECT« structure or »CRect« object that contains the coordinates of the scrolling rectangle.

lpRectClip    Points to the RECT structure or CRect object that contains the coordinates of the clipping rectangle. When this rectangle is smaller than the original one pointed to by lpRectScroll, scrolling occurs only in the smaller rectangle.

pRgnUpdate    Identifies the region uncovered by the scrolling process. The ScrollDC function defines this region; it is not necessarily a rectangle.

lpRectUpdate    Points to the RECT structure or CRect object that receives the coordinates of the rectangle that bounds the scrolling update region. This is the largest rectangular area that requires repainting. The values in the structure or object when the function returns are in client coordinates, regardless of the mapping mode for the given device context.

Remarks

Scrolls a rectangle of bits horizontally and vertically.

If lpRectUpdate is NULL, Windows does not compute the update rectangle. If both pRgnUpdate and lpRectUpdate are NULL, Windows does not compute the update region. If pRgnUpdate is not NULL, Windows assumes that it contains a valid pointer to the region uncovered by the scrolling process (defined by the ScrollDC member function). The update region returned in lpRectUpdate can be passed to CWnd::InvalidateRgn if required.

An application should use the ScrollWindow member function of class CWnd when it is necessary to scroll the entire client area of a window. Otherwise it should use ScrollDC.

Return Value

Nonzero if scrolling is executed; otherwise 0.

See Also

»CWnd::InvalidateRgn«, »CWnd::ScrollWindow«, ::ScrollDC, »CRgn«, »RECT«, »CRect«


  CDC::SelectClipRgn

virtual int SelectClipRgn( CRgn* pRgn );

pRgn    Identifies the region to be selected. If this value is NULL, the entire client area is selected and output is still clipped to the window.

Remarks

Selects the given region as the current clipping region for the device context. Only a copy of the selected region is used. The region itself can be selected for any number of other device contexts, or it can be deleted.

The function assumes that the coordinates for the given region are specified in device units. Some printer devices support text output at a higher resolution than graphics output in order to retain the precision needed to express text metrics. These devices report device units at the higher resolution, that is, in text units. These devices then scale coordinates for graphics so that several reported device units map to only 1 graphic unit. You should always call the SelectClipRgn function using text units.

Applications that must take the scaling of graphics objects in the GDI can use the GETSCALINGFACTOR printer escape to determine the scaling factor. This scaling factor affects clipping. If a region is used to clip graphics, GDI divides the coordinates by the scaling factor. If the region is used to clip text, GDI makes no scaling adjustment. A scaling factor of 1 causes the coordinates to be divided by 2; a scaling factor of 2 causes the coordinates to be divided by 4; and so on.

Return Value

The region's type. It can be any one of the following values, with the meanings as given:

•	COMPLEXREGION    New clipping region has overlapping borders.

•	ERROR    Device context or region is not valid.

•	NULLREGION    New clipping region is empty.

•	SIMPLEREGION    New clipping region has no overlapping borders.

See Also

»CDC::GetClipBox«, »CDC::Escape«, »CRgn«, ::SelectClipRgn::SelectClipRgn


  CDC::SelectObject

CPen* SelectObject( CPen* pPen );

CBrush* SelectObject( CBrush* pBrush );

virtual CFont* SelectObject( CFont* pFont );

CBitmap* SelectObject( CBitmap* pBitmap );

int SelectObject( CRgn* pRgn );

pPen    A pointer to a »CPen« object to be selected.

pBrush    A pointer to a »CBrush« object to be selected.

pFont    A pointer to a »CFont« object to be selected.

pBitmap    A pointer to a »CBitmap« object to be selected.

pRgn    A pointer to a »CRgn« object to be selected.

Remarks

Selects an object into the device context. Class CDC provides five versions specialized for particular kinds of GDI objects, including pens, brushes, fonts, bitmaps, and regions. The newly selected object replaces the previous object of the same type. For example, if pObject of the general version of SelectObject points to a »CPen« object, the function replaces the current pen with the pen specified by pObject.

An application can select a bitmap into memory device contexts only and into only one memory device context at a time. The format of the bitmap must either be monochrome or compatible with the device context; if it is not, SelectObject returns an error.

Windows 3.1 Only

For Windows 3.1, the SelectObject function returns the same value whether or not it is used in a metafile. Under previous versions of Windows, SelectObject returned a nonzero value for success and 0 for failure when it was used in a metafile. ♦

Return Value

A pointer to the object being replaced. This is a pointer to an object of one of the classes derived from CGdiObject, such as CPen, depending on which version of the function is used. The return value is NULL if there is an error.

The version of the member function that takes a region parameter performs the same task as the SelectClipRgn member function. Its return value can be any one of the following, with the meanings as given:

•	COMPLEXREGION    New clipping region has overlapping borders.

•	ERROR    Device context or region is not valid.

•	NULLREGION    New clipping region is empty.

•	SIMPLEREGION    New clipping region has no overlapping borders.

See Also

»CGdiObject::DeleteObject«, »CDC::SelectClipRgn«, »CDC::SelectPalette«,  ::SelectObject


  CDC::SelectPalette

CPalette* SelectPalette( CPalette* pPalette, BOOL bForceBackground );

pPalette    Identifies the logical palette to be selected. This palette must already have been created with the CPalette member function »CreatePalette«.

bForceBackground    Specifies whether the logical palette is forced to be a background palette. If bForceBackground is nonzero, the selected palette is always a background palette, regardless of whether the window has the input focus. If bForceBackground is 0 and the device context is attached to a window, the logical palette is a foreground palette when the window has the input focus.

Remarks

Selects the logical palette that is specified by pPalette as the selected palette object of the device context. The new palette becomes the palette object used by GDI to control colors displayed in the device context and replaces the previous palette.

An application can select a logical palette into more than one device context. However, changes to a logical palette will affect all device contexts for which it is selected. If an application selects a palette into more than one device context, the device contexts must all belong to the same physical device.

Return Value

A pointer to a CPalette object identifying the logical palette replaced by the palette specified by pPalette. It is NULL if there is an error.

See Also

»CDC::RealizePalette«, »CPalette«, ::SelectPalette


  CDC::SelectStockObject

virtual CGdiObject* SelectStockObject( int nIndex );

nIndex    Specifies the kind of stock object desired. It can be one of the following values, with meanings as given:

•	BLACK_BRUSH    Black brush.

•	DKGRAY_BRUSH    Dark gray brush.

•	GRAY_BRUSH    Gray brush.

•	HOLLOW_BRUSH    Hollow brush.

•	LTGRAY_BRUSH    Light gray brush.

•	NULL_BRUSH    Null brush.

•	WHITE_BRUSH    White brush.

•	BLACK_PEN    Black pen.

•	NULL_PEN    Null pen.

•	WHITE_PEN    White pen.

•	ANSI_FIXED_FONT    ANSI fixed system font.

•	ANSI_VAR_FONT    ANSI variable system font.

•	DEVICE_DEFAULT_FONT    Device-dependent font.

•	OEM_FIXED_FONT    OEM-dependent fixed font.

•	SYSTEM_FONT    The system font. By default, Windows uses the system font to draw menus, dialog-box controls, and other text. In Windows versions 3.0 and later, the system font is proportional width; earlier versions of Windows use a fixed-width system font.

•	SYSTEM_FIXED_FONT    The fixed-width system font used in Windows prior to version 3.0. This object is available for compatibility with earlier versions of Windows.

•	DEFAULT_PALETTE    Default color palette. This palette consists of the 20 static colors in the system palette.

Remarks

Selects a »CGdiObject« object that corresponds to one of the predefined stock pens, brushes, or fonts.

Return Value

A pointer to the CGdiObject object that was replaced if the function is successful. The actual object pointed to is a »CPen«, »CBrush«, or »CFont« object. If the call is unsuccessful, the return value is NULL.

See Also

»CGdiObject::GetObject«


  CDC::SetAbortProc

int SetAbortProc( BOOL ( CALLBACK EXPORT* lpfn )( HDC, int ) );

lpfn    A pointer to the abort function to install as the abort procedure. For more about this callback function, see the »Callback Function« section below.

Remarks

Installs the abort procedure for the print job.

If an application is to allow the print job to be canceled during spooling, it must set the abort function before the print job is started with the »StartDoc« member function. The Print Manager calls the abort function during spooling to allow the application to cancel the print job or to process out-of-disk-space conditions. If no abort function is set, the print job will fail if there is not enough disk space for spooling.

Note that new features of Microsoft C/C++ simplify the creation of the callback function passed to SetAbortProc. The address passed to the EnumObjects member function is a FAR pointer to a function exported with __export and with the Pascal calling convention. In protect-mode applications, you do not have to create this function with the Windows MakeProcInstancefunction or free the function after use with the Windows function  FreeProcInstance

You also do not have to export the function name in an EXPORTS statement in your application's module-definition file. You can instead use  the __export function modifier, as in

BOOL CALLBACK __export AFunction( HDC, int );

to cause the compiler to emit the proper export record for export by name without aliasing. This works for most needs. For some special cases, such as exporting a function by ordinal or aliasing the export, you still need to use an EXPORTS statement in a module-definition file.

For compiling Microsoft Foundation programs, you'll normally use the /GA and /GEs compiler options. The /Gw compiler option is not used with the Microsoft Foundation classes. (If you do use the Windows function MakeProcInstance, you will need to explicitly cast the returned function pointer from FARPROC to the type needed by this member function.) Callback registration interfaces are now type-safe (you must pass in a function pointer that points to the right kind of function for the specific callback).

Also note that all callback functions must trap Microsoft Foundation exceptions before returning to Windows, since exceptions cannot be thrown across callback boundaries. For more information about exceptions, see Chapter 16 in the Class Library User's Guide.

Callback Function

The callback function must use the Pascal calling convention, must be exported with __export, and must be declared FAR.

BOOL FAR PASCAL __export AbortFunc( HDC hPr, int code );

The name AbortFunc is a placeholder for the application-supplied function name. The actual name must be exported as described in the "Remarks" section above. The parameters are described below:

•	hPr    Identifies the device context.

•	code    Specifies whether an error has occurred. It is 0 if no error has occurred. It is SP_OUTOFDISK if the Print Manager is currently out of disk space and more disk space will become available if the application waits. If code is SP_OUTOFDISK, the application does not have to abort the print job. If it does not, it must yield to the Print Manager by calling the PeekMessage or GetMessage Windows function.

Return Value

The return value of the abort-handler function is nonzero if the print job is to continue, and 0 if it is canceled.

Return Value

Specifies the outcome of the SetAbortProc function. Some of the following values are more probable than others, but all are possible.

•	SP_ERROR    General error.

•	SP_OUTOFDISK    Not enough disk space is currently available for spooling, and no more space will become available.

•	SP_OUTOFMEMORY    Not enough memory is available for spooling.

•	SP_USERABORT    User ended the job through the Print Manager.


  CDC::SetAttribDC

virtual void SetAttribDC( HDC hDC );

hDC    A Windows device context.

Remarks

Call this function to set the attribute device context, m_hAttribDC. This member function does not attach the device context to the CDC object. Only the output device context is attached to a CDC object.

See Also

»CDC::SetOutputDC«, »CDC::ReleaseAttribDC«, »CDC::ReleaseOutputDC«


  CDC::SetBkColor

virtual COLORREF SetBkColor( COLORREF crColor );

crColor    Specifies the new background color.

Remarks

Sets the current background color to the specified color. If the background mode is OPAQUE, the system uses the background color to fill the gaps in styled lines, the gaps between hatched lines in brushes, and the background in character cells. The system also uses the background color when converting bitmaps between color and monochrome device contexts.

If the device cannot display the specified color, the system sets the background color to the nearest physical color.

Return Value

The previous background color as an RGB color value. If an error occurs, the return value is 0x80000000.

See Also

»CDC::BitBlt«, »CDC::GetBkColor«, »CDC::GetBkMode«, »CDC::SetBkMode«, »CDC::StretchBlt«, ::SetBkColor


  CDC::SetBkMode

int SetBkMode( int nBkMode );

nBkMode    Specifies the mode to be set. This parameter can be either of the following values, with the meanings as given:

•	OPAQUE    Background is filled with the current background color before the text, hatched brush, or pen is drawn. This is the default background mode.

•	TRANSPARENT    Background is not changed before drawing.

Remarks

Sets the background mode. The background mode defines whether the system removes existing background colors on the drawing surface before drawing text, hatched brushes, or any pen style that is not a solid line.

Return Value

The previous background mode.

See Also

»CDC::GetBkColor«, »CDC::GetBkMode«, »CDC::SetBkColor«, ::SetBkMode


  CDC::SetBoundsRect

Windows 3.1 Only

UINT SetBoundsRect( LPCRECT lpRectBounds, UINT flags ); ♦

lpRectBounds    Points to a RECT structure or CRect object that is used to set the bounding rectangle. Rectangle dimensions are given in logical coordinates. This parameter can be NULL.

flags    Specifies how the new rectangle will be combined with the accumulated rectangle. This parameter may be a combination of the following values:

•	DCB_ACCUMULATE    Add the rectangle specified by lpRectBounds to the bounding rectangle (using a rectangle-union operation).

•	DCB_DISABLE    Turn off bounds accumulation.

•	DCB_ENABLE    Turn on bounds accumulation. (The default setting for bounds accumulation is disabled.)

Remarks

Controls the accumulation of bounding-rectangle information for the specified device context.

Windows can maintain a bounding rectangle for all drawing operations. This rectangle can be queried and reset by the application. The drawing bounds are useful for invalidating bitmap caches.

Return Value

The current state of the bounding rectangle, if the function is successful. Like flags, the return value can be a combination of DCB_ values, as shown in the following list:

•	DCB_ACCUMULATE    The bounding rectangle is not empty. This value will always be set.

•	DCB_DISABLE    Bounds accumulation is off.

•	DCB_ENABLE    Bounds accumulation is on.

See Also

»CDC::GetBoundsRect«, ::SetBoundsRect, »RECT«, »CRect«


  CDC::SetBrushOrg

CPoint SetBrushOrg( int x, int y );

CPoint SetBrushOrg( POINT point );

x    Specifies the x-coordinate (in device units) of the new origin. This value must be in the range 0−7.

y    Specifies the y-coordinate (in device units) of the new origin. This value must be in the range 0−7.

point    Specifies the x- and y-coordinates of the new origin. Each value must be in the range 0−7. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Specifies the origin that GDI will assign to the next brush that the application selects into the device context.

The default coordinates for the brush origin are (0, 0). To alter the origin of a brush, call the UnrealizeObject function for the CBrush object, call SetBrushOrg, and then call the SelectObject member function to select the brush into the device context.

Do not use SetBrushOrg with stock »CBrush« objects.

Return Value

The previous origin of the brush in device units.

See Also

»CBrush«, »CDC::GetBrushOrg«, »CDC::SelectObject«, »CGdiObject::UnrealizeObject«, ::SetBrushOrg, »POINT«, »CPoint«


  CDC::SetMapMode

virtual int SetMapMode( int nMapMode );

nMapMode    Specifies the new mapping mode. It can be any one of the following values, with the meanings as given:

•	MM_ANISOTROPIC    Logical units are converted to arbitrary units with arbitrarily scaled axes. Setting the mapping mode to MM_ANISOTROPIC does not change the current window or viewport settings. To change the units, orientation, and scaling, call the »SetWindowExt« and »SetViewportExt« member functions.

•	MM_HIENGLISH    Each logical unit is converted to 0.001 inch. Positive x is to the right; positive y is up.

•	MM_HIMETRIC    Each logical unit is converted to 0.01 millimeter. Positive x is to the right; positive y is up.

•	MM_ISOTROPIC    Logical units are converted to arbitrary units with equally scaled axes; that is, 1 unit along the x-axis is equal to 1 unit along the y-axis. Use the SetWindowExt and SetViewportExt member functions to specify the desired units and the orientation of the axes. GDI makes adjustments as necessary to ensure that the x and y units remain the same size.

•	MM_LOENGLISH    Each logical unit is converted to 0.01 inch. Positive x is to the right; positive y is up.

•	MM_LOMETRIC    Each logical unit is converted to 0.1 millimeter. Positive x is to the right; positive y is up.

•	MM_TEXT    Each logical unit is converted to 1 device pixel. Positive x is to the right; positive y is down.

•	MM_TWIPS    Each logical unit is converted to 1/20 of a point. (Because a point is 1/72 inch, a twip is 1/1440 inch.) Positive x is to the right; positive y is up.

Remarks

Sets the mapping mode. The mapping mode defines the unit of measure used to convert logical units to device units; it also defines the orientation of the device's x- and y-axes. GDI uses the mapping mode to convert logical coordinates into the appropriate device coordinates. The MM_TEXT mode allows applications to work in device pixels, where 1 unit is equal to 1 pixel. The physical size of a pixel varies from device to device.

The MM_HIENGLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRIC, and MM_TWIPS modes are useful for applications that must draw in physically meaningful units (such as inches or millimeters). The MM_ISOTROPIC mode ensures a 1:1 aspect ratio, which is useful when it is important to preserve the exact shape of an image. The MM_ANISOTROPIC mode allows the x- and y-coordinates to be adjusted independently.

Return Value

The previous mapping mode.

See Also

»CDC::SetViewportExt«, »CDC::SetWindowExt«, ::SetMapMode


  CDC::SetMapperFlags

DWORD SetMapperFlags( DWORD dwFlag );

dwFlag    Specifies whether the font mapper attempts to match a font's aspect height and width to the device. When this value is ASPECT_FILTERING, the mapper selects only fonts whose x-aspect and y-aspect exactly match those of the specified device.

Remarks

Changes the method used by the font mapper when it converts a logical font to a physical font. An application can use SetMapperFlags to cause the font mapper to attempt to choose only a physical font that exactly matches the aspect ratio of the specified device.

An application that uses only raster fonts can use the SetMapperFlags function to ensure that the font selected by the font mapper is attractive and readable on the specified device. Applications that use scalable (TrueType) fonts typically do not use SetMapperFlags.

If no physical font has an aspect ratio that matches the specification in the logical font, GDI chooses a new aspect ratio and selects a font that matches this new aspect ratio.

Return Value

The previous value of the font-mapper flag.

See Also

::SetMapperFlags


  CDC::SetOutputDC

virtual void SetOutputDC( HDC hDC );

hDC    A Windows device context.

Remarks

Call this member function to set the output device context, m_hDC. This member function can only be called when a device context has not been attached to the CDC object. This member function sets m_hDC but does not attach the device context to the CDC object.

See Also

»CDC::SetAttribDC«, »CDC::ReleaseAttribDC«, »CDC::ReleaseOutputDC«, »CDC::m_hDC«


  CDC::SetPixel

COLORREF SetPixel( int x, int y, COLORREF crColor );

COLORREF SetPixel( POINT point, COLORREF crColor );

x    Specifies the logical x-coordinate of the point to be set.

y    Specifies the logical y-coordinate of the point to be set.

crColor    Specifies the color used to paint the point.

point    Specifies the logical x- and y-coordinates of the point to be set. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Sets the pixel at the point specified to the closest approximation of the color specified by crColor. The point must be in the clipping region. If the point is not in the clipping region, the function does nothing.

Not all devices support the SetPixel function. To determine whether a device supports SetPixel, call the GetDeviceCaps member function with the RASTERCAPS index and check the return value for the RC_BITBLT flag.

Return Value

An RGB value for the color that the point is actually painted. This value can be different from that specified by crColor if an approximation of that color is used. If the function fails (if the point is outside the clipping region), the return value is −1.

See Also

»CDC::GetDeviceCaps«, »CDC::GetPixel«, ::SetPixel, »POINT«, »CPoint«


  CDC::SetPolyFillMode

int SetPolyFillMode( int nPolyFillMode );

nPolyFillMode    Specifies the new filling mode. This value may be either ALTERNATE or WINDING. The default mode set in Windows is ALTERNATE.

Remarks

Sets the polygon-filling mode.

When the polygon-filling mode is ALTERNATE, the system fills the area between odd-numbered and even-numbered polygon sides on each scan line. That is, the system fills the area between the first and second side, between the third and fourth side, and so on. This mode is the default.

When the polygon-filling mode is WINDING, the system uses the direction in which a figure was drawn to determine whether to fill an area. Each line segment in a polygon is drawn in either a clockwise or a counterclockwise direction. Whenever an imaginary line drawn from an enclosed area to the outside of a figure passes through a clockwise line segment, a count is incremented. When the line passes through a counterclockwise line segment, the count is decremented. The area is filled if the count is nonzero when the line reaches the outside of the figure.

Return Value

The previous filling mode, if successful; otherwise 0.

See Also

»CDC::GetPolyFillMode«, »CDC::PolyPolygon«, ::SetPolyFillMode


  CDC::SetROP2

int SetROP2( int nDrawMode );

nDrawMode    Specifies the new drawing mode. It can be any one of the following values, with the meanings as given:

•	R2_BLACK    Pixel is always black.

•	R2_WHITE    Pixel is always white.

•	R2_NOP    Pixel remains unchanged.

•	R2_NOT    Pixel is the inverse of the screen color.

•	R2_COPYPEN    Pixel is the pen color.

•	R2_NOTCOPYPEN    Pixel is the inverse of the pen color.

•	R2_MERGEPENNOT    Pixel is a combination of the pen color and the inverse of the screen color (final pixel = (NOT screen pixel) OR pen).

•	R2_MASKPENNOT    Pixel is a combination of the colors common to both the pen and the inverse of the screen (final pixel = (NOT screen pixel) AND pen).

•	R2_MERGENOTPEN    Pixel is a combination of the screen color and the inverse of the pen color (final pixel = (NOT pen) OR screen pixel).

•	R2_MASKNOTPEN    Pixel is a combination of the colors common to both the screen and the inverse of the pen (final pixel = (NOT pen) AND screen pixel).

•	R2_MERGEPEN    Pixel is a combination of the pen color and the screen color (final pixel = pen OR screen pixel).

•	R2_NOTMERGEPEN    Pixel is the inverse of the R2_MERGEPEN color (final pixel = NOT(pen OR screen pixel)).

•	R2_MASKPEN    Pixel is a combination of the colors common to both the pen and the screen (final pixel = pen AND screen pixel).

•	R2_NOTMASKPEN    Pixel is the inverse of the R2_MASKPEN color (final pixel = NOT(pen AND screen pixel)).

•	R2_XORPEN    Pixel is a combination of the colors that are in the pen or in the screen, but not in both (final pixel = pen XOR screen pixel).

•	R2_NOTXORPEN    Pixel is the inverse of the R2_XORPEN color (final pixel = NOT(pen XOR screen pixel)).

Remarks

Sets the current drawing mode. The drawing mode specifies how the colors of the pen and the interior of filled objects are combined with the color already on the display surface.

The drawing mode is for raster devices only; it does not apply to vector devices. Drawing modes are binary raster-operation codes representing all possible Boolean combinations of two variables, using the binary operators AND, OR, and XOR (exclusive OR), and the unary operation NOT.

Return Value

The previous drawing mode.

See Also

»CDC::GetDeviceCaps«, »CDC::GetROP2«, ::SetROP2


  CDC::SetStretchBltMode

int SetStretchBltMode( int nStretchMode );

nStretchMode    Specifies the new bitmap-stretching mode. It can be one of the following values, with the meaning as given:

•	STRETCH_ANDSCANS    Uses the AND operator to combine eliminated lines with the remaining lines. This mode preserves black pixels at the expense of colored or white pixels.

•	STRETCH_DELETESCANS    Deletes the eliminated lines. Information in the eliminated lines is not preserved.

•	STRETCH_ORSCANS    Uses the OR operator to combine eliminated lines with the remaining lines. This mode preserves colored or white pixels at the expense of black pixels.

Remarks

Sets the bitmap-stretching mode for the StretchBlt member function. The bitmap-stretching mode defines how information is removed from bitmaps that are compressed by using the function. The default mode is STRETCH_ANDSCANS.

The STRETCH_ANDSCANS and STRETCH_ORSCANS modes are typically used to preserve foreground pixels in monochrome bitmaps. The STRETCH_DELETESCANS mode is typically used to preserve color in color bitmaps.

Return Value

The previous stretching mode. It can be STRETCH_ANDSCANS, STRETCH_DELETESCANS, or STRETCH_ORSCRANS.

See Also

»CDC::GetStretchBltMode«, »CDC::StretchBlt«, ::SetStretchBltMode


  CDC::SetTextAlign

UINT SetTextAlign( UINT nFlags );

nFlags    Specifies text-alignment flags. The flags specify the relationship between a point and a rectangle that bounds the text. The point can be either the current position or coordinates specified by a text-output function. The rectangle that bounds the text is defined by the adjacent character cells in the text string. The nFlags parameter can be one or more flags from the following three categories. Choose only one flag from each category. The first category affects text alignment in the x-direction:

•	TA_CENTER    Aligns the point with the horizontal center of the bounding rectangle.

•	TA_LEFT    Aligns the point with the left side of the bounding rectangle. This is the default setting.

•	TA_RIGHT    Aligns the point with the right side of the bounding rectangle.

The second category affects text alignment in the y-direction:

•	TA_BASELINE    Aligns the point with the baseline of the chosen font.

•	TA_BOTTOM    Aligns the point with the bottom of the bounding rectangle.

•	TA_TOP    Aligns the point with the top of the bounding rectangle. This is the default setting.

The third category determines whether the current position is updated when text is written:

•	TA_NOUPDATECP    Does not update the current position after each call to a text-output function. This is the default setting.

•	TA_UPDATECP    Updates the current x-position after each call to a text-output function. The new position is at the right side of the bounding rectangle for the text. When this flag is set, the coordinates specified in calls to the TextOut member function are ignored.

Remarks

Sets the text-alignment flags.

The TextOut and ExtTextOut member functions use these flags when positioning a string of text on a display or device. The flags specify the relationship between a specific point and a rectangle that bounds the text. The coordinates of this point are passed as parameters to the TextOut member function. The rectangle that bounds the text is formed by the adjacent character cells in the text string.

Return Value

The previous text-alignment setting, if successful. The low-order byte contains the horizontal setting and the high-order byte contains the vertical setting; otherwise 0.

See Also

»CDC::ExtTextOut«, »CDC::GetTextAlign«, »CDC::TabbedTextOut«, »CDC::TextOut«, ::SetTextAlign


  CDC::SetTextCharacterExtra

int SetTextCharacterExtra( int nCharExtra );

nCharExtra    Specifies the amount of extra space (in logical units) to be added to each character. If the current mapping mode is not MM_TEXT, nCharExtra is transformed and rounded to the nearest pixel.

Remarks

Sets the amount of intercharacter spacing. GDI adds this spacing to each character, including break characters, when it writes a line of text to the device context. The default value for the amount of intercharacter spacing is 0.

Return Value

The amount of the previous intercharacter spacing.

See Also

»CDC::GetTextCharacterExtra«, ::SetTextCharacterExtra


  CDC::SetTextColor

virtual COLORREF SetTextColor( COLORREF crColor );

crColor    Specifies the color of the text as an RGB color value.

Remarks

Sets the text color to the specified color. The system will use this text color when writing text to this device context and also when converting bitmaps between color and monochrome device contexts.

If the device cannot represent the specified color, the system sets the text color to the nearest physical color. The background color for a character is specified by the SetBkColor and SetBkMode member functions.

Return Value

An RGB value for the previous text color.

See Also

»CDC::GetTextColor«, »CDC::BitBlt«, »CDC::SetBkColor«, »CDC::SetBkMode«, ::SetTextColor


  CDC::SetTextJustification

int SetTextJustification( int nBreakExtra, int nBreakCount );

nBreakExtra    Specifies the total extra space to be added to the line of text (in logical units). If the current mapping mode is not MM_TEXT, the value given by this parameter is converted to the current mapping mode and rounded to the nearest device unit.

nBreakCount    Specifies the number of break characters in the line.

Remarks

Adds space to the break characters in a string. An application can use the GetTextMetrics member functions to retrieve a font's break character.

After the SetTextJustification member function is called, a call to a text-output function (such as TextOut) distributes the specified extra space evenly among the specified number of break characters. The break character is usually the space character (ASCII 32), but may be defined by a font as some other character.

The member function GetTextExtent is typically used with SetTextJustification. GetTextExtent computes the width of a given line before alignment. An application can determine how much space to specify in the nBreakExtra parameter by subtracting the value returned by GetTextExtent from the width of the string after alignment.

The SetTextJustification function can be used to align a line that contains multiple runs in different fonts. In this case, the line must be created piecemeal by aligning and writing each run separately.

Because rounding errors can occur during alignment, the system keeps a running error term that defines the current error. When aligning a line that contains multiple runs, GetTextExtent automatically uses this error term when it computes the extent of the next run. This allows the text-output function to blend the error into the new run.

After each line has been aligned, this error term must be cleared to prevent it from being incorporated into the next line. The term can be cleared by calling SetTextJustification with nBreakExtra set to 0.

Return Value

One if the function is successful; otherwise 0.

See Also

»CDC::GetMapMode«, »CDC::GetTextExtent«, »CDC::GetTextMetrics«, »CDC::SetMapMode«, »CDC::TextOut«, ::SetTextJustification


  CDC::SetViewportExt

virtual CSize SetViewportExt( int cx, int cy );

virtual CSize SetViewportExt( SIZE size );

cx    Specifies the x-extent of the viewport (in device units).

cy    Specifies the y-extent of the viewport (in device units).

size    Specifies the x- and y-extents of the viewport (in device units).

Remarks

Sets the x- and y-extents of the viewport of the device context. The viewport, along with the device-context window, defines how GDI maps points in the logical coordinate system to points in the coordinate system of the actual device. In other words, they define how GDI converts logical coordinates into device coordinates.

When the following mapping modes are set, calls to SetWindowExt and SetViewportExt are ignored:

MM_HIENGLISH	MM_LOMETRIC
MM_HIMETRIC	MM_TEXT
MM_LOENGLISH	MM_TWIPS

When MM_ISOTROPIC mode is set, an application must call the SetWindowExt member function before it calls SetViewportExt.

Return Value

The previous extents of the viewport as a »CSize« object. When an error occurs, the x- and y-coordinates of the returned CSize object are both set to 0.

See Also

»CDC::SetWindowExt«, ::SetViewportExt, »CSize«, »CDC::GetViewportExt«


  CDC::SetViewportOrg

virtual CPoint SetViewportOrg( int x, int y );

virtual CPoint SetViewportOrg( POINT point );

x    Specifies the x-coordinate (in device units) of the origin of the viewport. The value must be within the range of the device coordinate system.

y    Specifies the y-coordinate (in device units) of the origin of the viewport. The value must be within the range of the device coordinate system.

point    Specifies the origin of the viewport. The values must be within the range of the device coordinate system. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Sets the viewport origin of the device context. The viewport, along with the device-context window, defines how GDI maps points in the logical coordinate system to points in the coordinate system of the actual device. In other words, they define how GDI converts logical coordinates into device coordinates.

The viewport origin marks the point in the device coordinate system to which GDI maps the window origin, a point in the logical coordinate system specified by the SetWindowOrg member function. GDI maps all other points by following the same process required to map the window origin to the viewport origin. For example, all points in a circle around the point at the window origin will be in a circle around the point at the viewport origin. Similarly, all points in a line that passes through the window origin will be in a line that passes through the viewport origin.

Return Value

The previous origin of the viewport (in device coordinates) as a CPoint object.

See Also

»CDC::SetWindowOrg«, ::SetViewportOrg, »CPoint«, »POINT«, »CDC::GetViewportOrg«


  CDC::SetWindowExt

virtual CSize SetWindowExt( int cx, int cy );

virtual CSize SetWindowExt( SIZE size );

cx    Specifies the x-extent (in logical units) of the window.

cy    Specifies the y-extent (in logical units) of the window.

size    Specifies the x- and y-extents (in logical units) of the window.

Remarks

Sets the x- and y-extents of the window associated with the device context. The window, along with the device-context viewport, defines how GDI maps points in the logical coordinate system to points in the device coordinate system.

When the following mapping modes are set, calls to SetWindowExt and SetViewportExt functions are ignored:

•	MM_HIENGLISH

•	MM_HIMETRIC

•	MM_LOENGLISH

•	MM_LOMETRIC

•	MM_TEXT

•	MM_TWIPS

When MM_ISOTROPIC mode is set, an application must call the SetWindowExt member function before calling SetViewportExt.

Return Value

The previous extents of the window (in logical units) as a »CSize« object. If an error occurs, the x- and y-coordinates of the returned CSize object are both set to 0.

See Also

»CDC::GetWindowExt«, »CDC::SetViewportExt«, ::SetWindowExt, »CSize«


  CDC::SetWindowOrg

CPoint SetWindowOrg( int x, int y );

CPoint SetWindowOrg( POINT point );

x    Specifies the logical x-coordinate of the new origin of the window.

y    Specifies the logical y-coordinate of the new origin of the window.

point    Specifies the logical coordinates of the new origin of the window. You can pass either a »POINT« structure or a »CPoint« object for this parameter.

Remarks

Sets the window origin of the device context. The window, along with the device-context viewport, defines how GDI maps points in the logical coordinate system to points in the device coordinate system.

The window origin marks the point in the logical coordinate system from which GDI maps the viewport origin, a point in the device coordinate system specified by the SetWindowOrg function. GDI maps all other points by following the same process required to map the window origin to the viewport origin. For example, all points in a circle around the point at the window origin will be in a circle around the point at the viewport origin. Similarly, all points in a line that passes through the window origin will be in a line that passes through the viewport origin.

Return Value

The previous origin of the window as a »CPoint« object.

See Also

::SetWindowOrg, ::SetViewportOrg, »CPoint«, »POINT«, »CDC::GetWindowOrg«


  CDC::StartDoc

int StartDoc( LPDOCINFO lpDocInfo );

lpDocInfo    Points to a »DOCINFO« structure containing the name of the document file and the name of the output file.

Remarks

Informs the device driver that a new print job is starting and that all subsequent StartPage and EndPage calls should be spooled under the same job until an EndDoc call occurs. This ensures that documents longer than one page will not be interspersed with other jobs.

For Windows version 3.1, this function replaces the STARTDOC printer escape. Using this function ensures that documents containing more than one page are not interspersed with other print jobs.

When running under Windows version 3.0, this member functions sends a STARTDOC printer escape.

StartDoc should not be used inside metafiles.

Return Value

The value −1 if there is an error such as insufficient memory or an invalid port specification occurs; otherwise a positive value.

DOCINFO Structure

Windows 3.1 only

A DOCINFO structure has this form:

typedef struct {    /* di */

    int     cbSize;

    LPCSTR  lpszDocName;

    LPCSTR  lpszOutput;

} DOCINFO;

The DOCINFO structure contains the input and output filenames used by the StartDoc function.

Members

cbSize    Specifies the size of the structure, in bytes.

lpszDocName    Points to a null-terminated string specifying the name of the document. This string must not be longer than 32 characters, including the null terminating character.

lpszOutput    Points to a null-terminated string specifying the name of an output file. This allows a print job to be redirected to a file. If this value is NULL, output goes to the device for the specified device context. ♦

See Also

»CDC::Escape«, »CDC::EndDoc«, »CDC::AbortDoc«


  CDC::StartPage

int StartPage();

Remarks

Call this member function to prepare the printer driver to receive data. StartPage supersedes the NEWFRAME and BANDINFO escapes.

For an overview of the sequence of printing calls, see the »StartDoc« member function.

The system disables the ResetDC member function between calls to StartPage and EndPage.

When running under Windows version 3.0, this member function does nothing.

See Also

»CDC::Escape«, »CDC::EndPage«


  CDC::StretchBlt

BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );

x    Specifies the x-coordinate (in logical units) of the upper-left corner of the destination rectangle.

y    Specifies the y-coordinate (in logical units) of the upper-left corner of the destination rectangle.

nWidth    Specifies the width (in logical units) of the destination rectangle.

nHeight    Specifies the height (in logical units) of the destination rectangle.

pSrcDC    Specifies the source device context.

xSrc    Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.

ySrc    Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.

nSrcWidth    Specifies the width (in logical units) of the source rectangle.

nSrcHeight    Specifies the height (in logical units) of the source rectangle.

dwRop    Specifies the raster operation to be performed. Raster operation codes define how GDI combines colors in output operations that involve a current brush, a possible source bitmap, and a destination bitmap. This parameter may be one of the following values, as described below:

•	BLACKNESS    Turns all output black.

•	DSTINVERT    Inverts the destination bitmap.

•	MERGECOPY    Combines the pattern and the source bitmap using the Boolean AND operator.

•	MERGEPAINT    Combines the inverted source bitmap with the destination bitmap using the Boolean OR operator.

•	NOTSRCCOPY    Copies the inverted source bitmap to the destination.

•	NOTSRCERASE    Inverts the result of combining the destination and source bitmaps using the Boolean OR operator.

•	PATCOPY    Copies the pattern to the destination bitmap.

•	PATINVERT    Combines the destination bitmap with the pattern using the Boolean XOR operator.

•	PATPAINT    Combines the inverted source bitmap with the pattern using the Boolean OR operator. Combines the result of this operation with the destination bitmap using the Boolean OR operator.

•	SRCAND    Combines pixels of the destination and source bitmaps using the Boolean AND operator.

•	SRCCOPY    Copies the source bitmap to the destination bitmap.

•	SRCERASE    Inverts the destination bitmap and combines the result with the source bitmap using the Boolean AND operator.

•	SRCINVERT    Combines pixels of the destination and source bitmaps using the Boolean XOR operator.

•	SRCPAINT    Combines pixels of the destination and source bitmaps using the Boolean OR operator.

•	WHITENESS    Turns all output white.

Remarks

Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap if necessary to fit the dimensions of the destination rectangle. The function uses the stretching mode of the destination device context (set by SetStretchBltMode) to determine how to stretch or compress the bitmap.

The StretchBlt function moves the bitmap from the source device given by pSrcDC to the destination device represented by the device-context object whose member function is being called. The xSrc, ySrc, nSrcWidth, and nSrcHeight parameters define the upper-left corner and dimensions of the source rectangle. The x, y, nWidth, and nHeight parameters give the upper-left corner and dimensions of the destination rectangle. The raster operation specified by dwRop defines how the source bitmap and the bits already on the destination device are combined.

The StretchBlt function creates a mirror image of a bitmap if the signs of the nSrcWidth and nWidth or nSrcHeight and nHeight parameters differ. If nSrcWidth and nWidth have different signs, the function creates a mirror image of the bitmap along the x-axis. If nSrcHeight and nHeight have different signs, the function creates a mirror image of the bitmap along the y-axis.

The StretchBlt function stretches or compresses the source bitmap in memory and then copies the result to the destination. If a pattern is to be merged with the result, it is not merged until the stretched source bitmap is copied to the destination. If a brush is used, it is the selected brush in the destination device context. The destination coordinates are transformed according to the destination device context; the source coordinates are transformed according to the source device context.

If the destination, source, and pattern bitmaps do not have the same color format, StretchBlt converts the source and pattern bitmaps to match the destination bitmaps. The foreground and background colors of the destination device context are used in the conversion.

If StretchBlt must convert a monochrome bitmap to color, it sets white bits (1) to the background color and black bits (0) to the foreground color. To convert color to monochrome, it sets pixels that match the background color to white (1) and sets all other pixels to black (0). The foreground and background colors of the device context with color are used.

Not all devices support the StretchBlt function. To determine whether a device supports StretchBlt, call the GetDeviceCaps member function with the RASTERCAPS index and check the return value for the RC_STRETCHBLT flag.

Return Value

Nonzero if the bitmap is drawn; otherwise 0.

See Also

»CDC::BitBlt«, »CDC::GetDeviceCaps«, »CDC::SetStretchBltMode«, ::StretchBlt


  CDC::TabbedTextOut

virtual CSize TabbedTextOut( int x, int y, LPCSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin );

x    Specifies the logical x-coordinate of the starting point of the string.

y    Specifies the logical y-coordinate of the starting point of the string.

lpszString    Points to the character string to draw. You can pass either a pointer to an array of characters or a »CString« object for this parameter.

nCount    Specifies the number of characters in the string.

nTabPositions    Specifies the number of values in the array of tab-stop positions.

lpnTabStopPositions    Points to an array containing the tab-stop positions (in logical units). The tab stops must be sorted in increasing order; the smallest x-value should be the first item in the array.

nTabOrigin    Specifies the x-coordinate of the starting position from which tabs are expanded (in logical units).

Remarks

Writes a character string at the specified location, expanding tabs to the values specified in the array of tab-stop positions. Text is written in the currently selected font. If nTabPositions is 0 and lpnTabStopPositions is NULL, tabs are expanded to eight times the average character width.

If nTabPositions is 1, the tab stops are separated by the distance specified by the first value in the lpnTabStopPositions array.

If the lpnTabStopPositions array contains more than one value, a tab stop is set for each value in the array, up to the number specified by nTabPositions.

The nTabOrigin parameter allows an application to call the TabbedTextOut function several times for a single line. If the application calls the function more than once with the nTabOrigin set to the same value each time, the function expands all tabs relative to the position specified by nTabOrigin.

By default, the current position is not used or updated by the function. If an application needs to update the current position when it calls the function, the application can call the SetTextAlign member function with nFlags set to TA_UPDATECP. When this flag is set, Windows ignores the x and y parameters on subsequent calls to TabbedTextOut, using the current position instead.

Return Value

The dimensions of the string (in logical units) as a CSize object.

See Also

»CDC::GetTabbedTextExtent«, »CDC::SetTextAlign«, »CDC::TextOut«, »CDC::SetTextColor«, ::TabbedTextOut, »CSize«


  CDC::TextOut

virtual BOOL TextOut( int x, int y, LPCSTR lpszString, int nCount );

virtual BOOL TextOut( int x, int y, const CString& str );

x    Specifies the logical x-coordinate of the starting point of the text.

y    Specifies the logical y-coordinate of the starting point of the text.

lpszString    Points to the character string to be drawn.

nCount    Specifies the number of bytes in the string.

str    A CString object that contains the characters to be drawn.

Remarks

Writes a character string at the specified location using the currently selected font.

Character origins are at the upper-left corner of the character cell. By default, the current position is not used or updated by the function.

If an application needs to update the current position when it calls TextOut, the application can call the SetTextAlign member function with nFlags set to TA_UPDATECP. When this flag is set, Windows ignores the x and y parameters on subsequent calls to TextOut, using the current position instead.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CDC::ExtTextOut«, »CDC::GetTextExtent«, »CDC::SetTextAlign«, »CDC::SetTextColor«, »CDC::TabbedTextOut«, ::TextOut


  CDC::UpdateColors

void UpdateColors();

Remarks

Updates the client area of the device context by matching the current colors in the client area to the system palette on a pixel-by-pixel basis. An inactive window with a realized logical palette may call UpdateColors as an alternative to redrawing its client area when the system palette changes.

For more information on using color palettes, see the Windows SDK documentation.

The UpdateColors member function typically updates a client area faster than redrawing the area. However, because the function performs the color translation based on the color of each pixel before the system palette changed, each call to this function results in the loss of some color accuracy.

See Also

»CDC::RealizePalette«, »CPalette«, ::UpdateColors


CDC Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CDC::m_hAttribDC

Remarks

The attribute device context for this CDC object. By default, this device context is equal to m_hDC. In general, CDC GDI calls that request information from the device context are directed to m_hAttribDC. See the »CDC« class description for more on the use of these two device contexts.

See Also

»CDC::m_hDC«, »CDC::SetAttribDC«, »CDC::ReleaseAttribDC«


  CDC::m_hDC

Remarks

The output device context for this CDC object. By default, m_hDC is equal to m_hAttribDC, the other device context wrapped by CDC. In general, CDC GDI calls that create output go to the m_hDC device context. You can initialize m_hDC and m_hAttribDC to point to different devices. See the »CDC« class description for more on the use of these two device contexts.

See Also

»CDC::m_hAttribDC«, »CDC::SetOutputDC«, »CDC::ReleaseOutputDC«


CDialog
  class CDialog : public CWnd

The CDialog class is the base class used for displaying dialog boxes on the screen. Dialog boxes are of two types: modal and modeless. A modal dialog box must be closed by the user before the application continues. A modeless dialog box allows the user to display the dialog box and return to another task without canceling or removing the dialog box.

A CDialog object is a combination of a dialog template and a CDialog-derived class. Use App Studio to create the dialog template and store it in a resource, then use ClassWizard to create a class derived from CDialog.

A dialog box, like any other window, receives messages from Windows. In a dialog box, you are particularly interested in handling notification messages from the dialog box's controls since that is how the user interacts with your dialog box. ClassWizard browses through the potential messages generated by each control in your dialog box, and you can select which messages you wish to handle. ClassWizard then adds the appropriate message-map entries and message-handler member functions to the new class for you. You only need to write application-specific code in the handler member functions.

If you prefer, you can always write message-map entries and member functions yourself instead of using ClassWizard.

In all but the most trivial dialog box, you add member variables to your derived dialog class to store data entered in the dialog box's controls by the user or to display data for the user. ClassWizard browses through those controls in your dialog box that can be mapped to data and prompts you to create a member variable for each control. At the same time, you choose a variable type and permissible range of values for each variable. ClassWizard adds the member variables to your derived dialog class.

ClassWizard then writes a data map to automatically handle the exchange of data between the member variables and the dialog box's controls. The data map provides functions that initialize the controls in the dialog box with the proper values, retrieve the data, and validate the data.

To create a modal dialog box, construct an object on the stack using the constructor for your derived dialog class and then call DoModal to create the dialog window and its controls. If you wish to create a modeless dialog, call Create in the constructor of your dialog class.

You can also create a template in memory by using a DialogBoxResource data structure as described in the Windows Software Development Kit documentation. After you construct a CDialog object, call CreateIndirect to create a modeless dialog box, or call InitModalIndirect and DoModal to create a modal dialog box.

ClassWizard writes the exchange and validation data map in an override of CWnd::DoDataExchange that ClassWizard adds to your new dialog class. See the »DoDataExchange« member function in CWnd for more on the exchange and validation functionality.

Both the programmer and the framework call DoDataExchange indirectly through a call to CWnd::UpdateData.

The framework calls UpdateData when the user clicks the OK button to close a modal dialog box. (The data is not retrieved if the Cancel button is clicked.) The default implementation of »OnInitDialog« also calls UpdateData to set the initial values of the controls. You typically override OnInitDialog to further initialize controls. OnInitDialog is called after all the dialog controls are created and just before the dialog box is displayed.

You can call CWnd::UpdateData at any time during the execution of a modal or modeless dialog box.

If you develop a dialog box by hand, you add the necessary member variables to the derived dialog-box class yourself, and you add member functions to set or get these values.

For more on App Studio, see the App Studio User's Guide. For more on ClassWizard, see the App Studio User's Guide, Chapter 9, and Chapters 6 and 7 of the Class Library User's Guide.

Call »CWinApp::SetDialogBkColor« to set the background color for dialog boxes in your application.

A modal dialog box closes automatically when the user presses the OK or Cancel buttons or when your code calls the EndDialog member function.

When you implement a modeless dialog box, always override the OnCancel member function and call DestroyWindow from within it. Don't call the base class CDialog::OnCancel, because it calls EndDialog, which will make the dialog box invisible but will not destroy it. You should also override PostNcDestroy for modeless dialog boxes in order to delete this, since modeless dialog boxes are usually allocated with new. Modal dialog boxes are usually constructed on the frame and do not need PostNcDestroy cleanup.

#include <afxwin.h>


CDialog Class Members
   Class Members

Construction/Destruction — Public Members

»CDialog«	Constructs a CDialog object.
Initialization — Public Members

»InitModalIndirect«	Creates a modal dialog box from a dialog-box template in memory (not resource-based). The parameters are stored until the function DoModal is called.
Operations — Public Members

»DoModal«	Invokes a modal dialog box and returns when done.
»MapDialogRect«	Converts the dialog-box units of a rectangle to screen units.
»IsDialogMessage«	Determines whether the given message is intended for the modeless dialog box and, if so, processes it.
»NextDlgCtrl«	Moves the focus to the next dialog-box control in the dialog box.
»PrevDlgCtrl«	Moves the focus to the previous dialog-box control in the dialog box.
»GotoDlgCtrl«	Moves the focus to a specified dialog-box control in the dialog box.
»SetDefID«	Changes the default pushbutton control for a dialog box to a specified pushbutton.
»GetDefID«	Gets the ID of the default pushbutton control for a dialog box.
»SetHelpID«	Sets a context-sensitive help ID for the dialog box.
»EndDialog«	Closes a modal dialog box.
Overridables — Public Members

»OnInitDialog«	Override to augment dialog-box initialization.
»OnSetFont«	Override to specify the font that a dialog-box control is to use when it draws text.
»OnOK«	Override to perform the OK button action in a modal dialog box. The default closes the dialog box and DoModal returns IDOK.
»OnCancel«	Override to perform the Cancel button or ESC key action. The default closes the dialog box and DoModal  returns IDCANCEL.
Construction/Destruction — Protected Members

»CDialog«	Constructs a CDialog object.
Initialization — Protected Members

»Create«	Initializes the CDialog object. Creates a modeless dialog box and attaches it to the CDialog object.
»CreateIndirect«	Creates a modeless dialog box from a dialog-box template in memory (not resource-based).


CDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDialog::CDialog

CDialog( LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL );

CDialog( UINT nIDTemplate, CWnd* pParentWnd = NULL );

Protected

CDialog(); ♦

lpszTemplateName    Contains a null-terminated string that is the name of a dialog-box template resource.

nIDTemplate    Contains the ID number of a dialog-box template resource.

pParentWnd    Points to the parent or owner window object (of type »CWnd«) to which the dialog object belongs. If it is NULL, the dialog object's parent window is set to the main application window.

Remarks

To construct a resource-based modal dialog box, invoke either public form of the constructor. One form of the constructor provides access to the dialog resource by template name. The other constructor provides access by template ID number, usually with an IDD_ prefix (for example, IDD_DIALOG1).

To construct a modal dialog box from a template in memory, first invoke the parameterless, protected constructor and then call InitModalIndirect.

After you construct a modal dialog box with one of the above methods, call DoModal.

To construct a modeless dialog box, use the protected form of the CDialog constructor. The constructor is protected because you must derive your own dialog-box class to implement a modeless dialog box. Construction of a modeless dialog box is a two-step process. First invoke the constructor; then call the Create member function to create a resource-based dialog box, or call CreateIndirect to create the dialog box from a template in memory.

See Also

»CDialog::Create«, »CWnd::DestroyWindow«, »CDialog::InitModalIndirect«, »CDialog::DoModal«, ::CreateDialog


  CDialog::Create

Protected

BOOL Create( LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL );

BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL ); ♦

lpszTemplateName    Contains a null-terminated string that is the name of a dialog-box template resource.

pParentWnd    Points to the parent window object (of type »CWnd«) to which the dialog object belongs. If it is NULL, the dialog object's parent window is set to the main application window.

nIDTemplate    Contains the ID number of a dialog-box template resource.

Remarks

Call Create to create a modeless dialog box using a dialog-box template from a resource. You can put the call to Create inside the constructor or call it after the constructor is invoked.

Two forms of the Create member function are provided for access to the dialog-box template resource by either template name or template ID number (for example, IDD_DIALOG1).

For either form, pass a pointer to the parent window object. If pParentWnd is NULL, the dialog box will be created with its parent or owner window set to the main application window.

The Create member function returns immediately after it creates the dialog box.

Use the WS_VISIBLE style in the dialog-box template if the dialog box should appear when the parent window is created. Otherwise, you must call ShowWindow. For further dialog-box styles and their application, see the Windows Software Development Kit documentation and App Studio documentation.

Use the CWnd::DestroyWindow function to destroy a dialog box created by the Create function.

Return Value

Both forms return nonzero if dialog box creation and initialization was successful; otherwise 0.

See Also

»CDialog::CDialog«, »CWnd::DestroyWindow«, »CDialog::InitModalIndirect«, »CDialog::DoModal«, ::CreateDialog


  CDialog::CreateIndirect

Protected

BOOL CreateIndirect( const void FAR* lpDialogTemplate, CWnd* pParentWnd = NULL ); ♦

lpDialogTemplate    Points to memory that contains a dialog-box template used to create the dialog box. This template is in the form of a DialogBoxHeader structure and control information. For more information on this structure, see the Windows SDK.

pParentWnd    Points to the dialog object's parent window object (of type »CWnd«). If it is NULL, the dialog object's parent window is set to the main application window.

Remarks

Call this member function to create a modeless dialog box from a dialog-box template in memory.

The CreateIndirect member function returns immediately after it creates the dialog box.

Use the WS_VISIBLE style in the dialog-box template if the dialog box should appear when the parent window is created. Otherwise, you must call ShowWindow to cause it to appear. For more information on how you can specify other dialog-box styles in the template, see the Windows Software Development Kit documentation and the App Studio User's Guide.

Use the CWnd::DestroyWindow function to destroy a dialog box created by the CreateIndirect function.

Return Value

Nonzero if the dialog was created and initialized successfully; otherwise 0.

See Also

»CDialog::CDialog«, »CWnd::DestroyWindow«, »CDialog::Create«, ::CreateDialogIndirect


  CDialog::DoModal

virtual int DoModal();

Remarks

Call this member function to invoke the modal dialog box and return the dialog box result when done. This member function handles all interaction with the user while the dialog box is active. This is what makes the dialog box modal; that is, the user cannot interact with other windows until the dialog box is closed.

If the user clicks one of the pushbuttons in the dialog box, such as OK or Cancel, a message-handler member function, such as »OnOK« or »OnCancel«, is called to attempt to close the dialog box. The default OnOK member function will validate and update the dialog-box data and close the dialog box with result IDOK, and the default OnCancel member function will close the dialog box with result IDCANCEL without validating or updating the dialog-box data. You can override these message-handler functions to alter their behavior.

Return Value

An int value that specifies the value of the nResult parameter that was passed to the »CDialog::EndDialog« member function, which is used to close the dialog box. The return value is −1 if the function could not create the dialog box, or IDABORT if some other error occurred.

See Also

::DialogBox


   CDialog::EndDialog

void EndDialog( int nResult );

nResult    Contains the value to be returned from the dialog box to the caller of DoModal.

Remarks

Call this member function to terminate a modal dialog box. This member function returns nResult as the return value of DoModal. You must use the EndDialog function to complete processing whenever a modal dialog box is created.

You can call EndDialog at any time, even in »OnInitDialog«, in which case you should close the dialog box before it is shown or before the input focus is set.

EndDialog does not close the dialog box immediately. Instead, it sets a flag that directs the dialog box to close as soon as the current message handler returns.

See Also

»CDialog::DoModal«, »CDialog::OnOK«, »CDialog::OnCancel«


  CDialog::GetDefID

DWORD GetDefID() const;

Remarks

Call the GetDefID member function to get the ID of the default pushbutton control for a dialog box. This is usually an OK button.

Return Value

A 32-bit value (DWORD). If the default pushbutton has an ID value, the high-order word contains DC_HASDEFID and the low-order word contains the ID value. If the default pushbutton does not have an ID value, the return value is 0.

See Also

»CDialog::SetDefID«, DM_GETDEFID


  CDialog::GotoDlgCtrl

void GotoDlgCtrl( CWnd* pWndCtrl );

pWndCtrl    Identifies the window (control) that is to receive the focus.

Remarks

Moves the focus to the specified control in the dialog box.

To get a pointer to the control (child window) to pass as pWndCtrl, call the CWnd::GetDlgItem member function, which returns a pointer to a »CWnd« object.

See Also

»CWnd::GetDlgItem«, »CDialog::PrevDlgCtrl«, »CDialog::NextDlgCtrl«


  CDialog::InitModalIndirect

BOOL InitModalIndirect( HGLOBAL hDialogTemplate );

hDialogTemplate    Contains a handle to global memory containing a dialog-box template. This template is in the form of a DialogBoxHeader structure and data for each control in the dialog box. For more information on this structure, see the Windows SDK.

Remarks

Call this member function to initialize a modal dialog object using a dialog-box template that you construct in memory.

To create a modal dialog indirectly, first allocate a global block of memory and fill it with the dialog box template. Then call the empty CDialog constructor to construct the dialog-box object. Next, call InitModalIndirect to store your handle to the in-memory dialog-box template. The Windows dialog box is created and displayed later, when the »DoModal« member function is called.

Return Value

Nonzero if the dialog object was created and initialized successfully; otherwise 0.

See Also

::DialogBoxIndirect, »CDialog::DoModal«, »CWnd::DestroyWindow«, DialogBoxResource, »CDialog::CDialog«, »CDialog::DoModal«


  CDialog::IsDialogMessage

BOOL IsDialogMessage( LPMSG lpMsg );

lpMsg    Points to an MSG structure that contains the message to be checked.

Remarks

Call this member function to determine whether the given message is intended for a modeless dialog box; if it is, this function processes the message. When the IsDialogMessage function processes a message, it checks for keyboard messages and converts them to selection commands for the corresponding dialog box. For example, the TAB key selects the next control or group of controls, and the DOWN ARROW key selects the next control in a group.

You must not pass a message processed by IsDialogMessage to the TranslateMessage or DispatchMessage Windows functions because it has already been processed.

Return Value

Specifies whether the member function has processed the given message. It is nonzero if the message has been processed; otherwise 0. If the return is 0, call the PreTranslateMessage member function of the base class to process the message. In an override of the CDialog::PreTranslateMessage member function the code looks like this :

BOOL CMyDlg::PreTranslateMessage( msg )
{
    if( IsDialogMessage( msg ) )
        return TRUE;
    else
        return CDialog::PreTranslateMessage( msg );
}

See Also

::DispatchMessage, ::TranslateMessage, ::GetMessage, »CWnd::PreTranslateMessage«, ::IsDialogMessage


  CDialog::MapDialogRect

void MapDialogRect( LPRECT lpRect ) const;

lpRect    Points to a RECT structure or CRect object that contains the dialog-box coordinates to be converted.

Remarks

Call to convert the dialog-box units of a rectangle to screen units. Dialog-box units are stated in terms of the current dialog-box base unit derived from the average width and height of characters in the font used for dialog-box text. One horizontal unit is one-fourth of the dialog-box base-width unit, and one vertical unit is one-eighth of the dialog-box base height unit.

The GetDialogBaseUnits Windows function returns size information for the system font, but you can specify a different font for each dialog box if you use the DS_SETFONT style in the resource-definition file. The MapDialogRect Windows function uses the appropriate font for this dialog box.

The MapDialogRect member function replaces the dialog-box units in lpRect with screen units (pixels) so that the rectangle can be used to create a dialog box or position a control within a box.

See Also

::GetDialogBaseUnits, ::MapDialogRect, WM_SETFONT


  CDialog::NextDlgCtrl

void NextDlgCtrl() const;

Remarks

Moves the focus to the next control in the dialog box. If the focus is at the last control in the dialog box, it moves to the first control.

See Also

»CDialog::PrevDlgCtrl«, »CDialog::GotoDlgCtrl«


  CDialog::OnCancel

Protected

virtual void OnCancel(); ♦

Remarks

The framework calls this member function when the user clicks the Cancel button or presses the ESC key in a modal or modeless dialog box.

Override this member function to perform Cancel button action. The default simply terminates a modal dialog box by calling EndDialog and causing DoModal to return IDCANCEL.

If you implement the Cancel button in a modeless dialog box, you must override the OnCancel member function and call DestroyWindow from within it. Don't call the base-class member function, because it calls EndDialog, which will make the dialog box invisible but not destroy it.

See Also

»CDialog::OnOK«, »CDialog::EndDialog«


  CDialog::OnInitDialog

virtual  BOOL OnInitDialog();

Remarks

This member function is called in response to the WM_INITDIALOG message. This message is sent to the dialog box during the Create, CreateIndirect, or DoModal calls, which occur immediately before the dialog box is displayed.

Override this member function if you need to perform special processing when the dialog box is initialized. In the overridden version, first call the base class OnInitDialog but disregard its return value. You will normally return TRUE from your overridden member function.

Windows calls the OnInitDialog function via the standard global dialog-box procedure common to all Microsoft Foundation Class Library dialog boxes, rather than through your message map, so you do not need a message-map entry for this member function.

Return Value

Specifies whether the application has set the input focus to one of the controls in the dialog box. If OnInitDialog returns nonzero, Windows sets the input focus to the first control in the dialog box. The application can return 0 only if it has explicitly set the input focus to one of the controls in the dialog box.

See Also

»CDialog::Create«, »CDialog::CreateIndirect«, WM_INITDIALOG


  CDialog::OnOK

Protected

virtual void OnOK(); ♦

Remarks

Called when the user clicks the OK button (the button with an ID of IDOK).

Override this member function to perform the OK button action. If the dialog box includes automatic data validation and exchange, the default implementation of this member function validates the dialog-box data and updates the appropriate variables in your application.

If you implement the OK button in a modeless dialog box, you must override the OnOK member function and call DestroyWindow from within it. Don't call the base-class member function, because it calls EndDialog, which makes the dialog box invisible but does not destroy it.

See Also

»CDialog::OnCancel«, »CDialog::EndDialog«


  CDialog::OnSetFont

virtual  void OnSetFont( CFont* pFont );

pFont    Specifies a pointer to the font. Used as the default font for all controls in this dialog box.

Remarks

Specifies the font a dialog-box control will use when drawing text. The dialog-box control will use the specified font as the default for all dialog-box controls.

App Studio typically sets the dialog-box font as part of the dialog-box template resource.

See Also

WM_SETFONT, »CWnd::SetFont«


  CDialog::PrevDlgCtrl

void PrevDlgCtrl() const;

Remarks

Sets the focus to the previous control in the dialog box. If the focus is at the first control in the dialog box, it moves to the last control in the box.

See Also

»CDialog::NextDlgCtrl«, »CDialog::GotoDlgCtrl«


  CDialog::SetDefID

void SetDefID( UINT nID );

nID    Specifies the ID of the pushbutton control that will become the default.

Remarks

Changes the default pushbutton control for a dialog box.

See Also

»CDialog::GetDefID«


  CDialog::SetHelpID

void SetHelpID( UINT nIDR );

nIDR    Specifies the context-sensitive help ID.

Remarks

Sets a context-sensitive help ID for the dialog box.


CDialogBar
  class CDialogBar : public CControlBar

The CDialogBar class provides the functionality of a Windows modeless dialog box in a control bar. A dialog bar resembles a dialog box in that it contains standard Windows controls that the user can tab between. Another similarity is that you create a dialog template to represent the dialog bar.

Creating and using a dialog bar is similar to creating and using a CFormView object. First, use App Studio to define a dialog template with the style WS_CHILD and no other style (see App Studio User's Guide, Chapter 3). The template must not have the style WS_VISIBLE. In your application code, call the constructor to construct the CDialogBar object, then call Create to create the dialog-bar window and attach it to the CDialogBar object.

#include <afxext.h>

See Also

»CControlBar«, »CFormView«


CDialogBar Class Members
   Class Members

Construction/Destruction — Public Members

»CDialogBar«	Constructs a CDialogBar object.
»Create«	Creates a Windows dialog bar and attaches it to the CDialogBar object.


CDialogBar Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDialogBar::CDialogBar

CDialogBar();

Remarks

Constructs a CDialogBar object.

See Also

»CControlBar«


  CDialogBar::Create

BOOL Create( CWnd* pParentWnd, LPCSTR lpszTemplateName, UINT nStyle, UINT nID );

BOOL Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID );

pParentWnd    A pointer to the parent CWnd object.

lpszTemplateName    A pointer to the name of the CDialogBar object's dialog-box resource template.

nStyle    The alignment style of the dialog bar. The styles supported and their meanings are as follows:

•	CBRS_TOP    Control bar is at the top of the frame window.

•	CBRS_BOTTOM    Control bar is at the bottom of the frame window.

•	CBRS_NOALIGN    Control bar is not repositioned when the parent is resized.

•	CBRS_LEFT    Control bar is at the left of the frame window.

•	CBRS_RIGHT    Control bar is at the right of the frame window.

nID    The control ID of the dialog bar.

nIDTemplate    The resource ID of the CDialogBar object's dialog-box template.

Remarks

Loads the dialog-box resource template specified by lpszTemplateName or nIDTemplate, creates the dialog-bar window, sets its style, and associates it with the CDialogBar object.

If you specify the CBRS_TOP or CBRS_BOTTOM alignment style, the dialog bar's width is that of the frame window and its height is that of the resource specified by nIDTemplate. If you specify the CBRS_LEFT or CBRS_RIGHT alignment style, the dialog bar's height is that of the frame window and its width is that of the resource specified by nIDTemplate.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CDialogBar::CDialogBar«


CDocItem
  class CDocItem : public CObject

CDocItem is the base class for document items, which are components of a document's data. CDocItem objects are used to represent Object Linking and Embedding (OLE) items in both client and server documents.

Typically you do not use the CDocItem class directly. Instead, you use its derived classes COleClientItem or COleServerItem.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»COleDocument«, »COleServerItem«, »COleClientItem«


CDocItem Class Members
   Class Members

Operations — Public Members

»GetDocument«	Returns the document that contains the item.


CDocItem Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDocItem::GetDocument

CDocument* GetDocument() const;

Remarks

Call this function to get the document that contains the item. This function is overridden in the derived classes COleClientItem and COleServerItem to return pointers to COleClientDoc and COleServerDoc, respectively.

Return Value

A pointer to the document that contains the item, or NULL if the item is not part of a document.

See Also

»COleDocument«, »COleServerDoc«, »COleClientDoc«


CDocTemplate
  class CDocTemplate : public CCmdTarget

CDocTemplate is an abstract base class that defines the basic functionality for document templates. A document template defines the relationship between three types of classes:

•	A document class, which you derive from CDocument.

•	A view class, which displays data from the document class listed above. You can derive this class from CView, CScrollView, CFormView, or CEditView. (You can also use CEditView directly.)

•	A frame window class, which contains the view. For a single document interface (SDI) application, you derive this class from CFrameWnd. For a multiple document interface (MDI) application, you derive this class from CMDIChildWnd. If you don't need to customize the behavior of the frame window, you can use CFrameWnd or CMDIChildWnd directly without deriving your own class.

Your application has one document template for each type of document that it supports. For example, if your application supports both spreadsheets and text documents, the application has two document template objects. Each document template is responsible for creating and managing all the documents of its type.

The document template stores pointers to the CRuntimeClass objects for the document, view, and frame window classes. These CRuntimeClass objects are specified when constructing a document template.

The document template contains the ID of the resources used with the document type (such as menu, icon, or accelerator table resources). The document template also has strings containing additional information about its document type. These include the name of the document type (for example, "Worksheet"), the file extension (for example, ".xls"), and, optionally, other strings used by the application's user interface, the Windows File Manager, and Object Linking and Embedding (OLE) support.

Since CDocTemplate is an abstract class, you cannot use the class directly. A typical application uses one of the two CDocTemplate-derived classes that the Microsoft Foundation Class Library provides: CSingleDocTemplate, which implements SDI, and CMultiDocTemplate, which implements MDI. See those classes for more information on using document templates.

If your application requires a user-interface paradigm that is fundamentally different from SDI or MDI, you can derive your own class from CDocTemplate.

See Also

»CSingleDocTemplate«, »CMultiDocTemplate«, »CDocument«, »CView«, »CScrollView«, »CEditView«, »CFormView«, »CFrameWnd«, »CMDIChildWnd«


CDocTemplate Class Members
   Class Members

Operations — Public Members

»GetDocString«	Retrieves a string describing the document type.


CDocTemplate Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDocTemplate::GetDocString

virtual BOOL GetDocString( CString& rString, enum DocStringIndex index ) const;

rString    A reference to a CString object that will contain the string when the function returns.

index    An index of the substring being retrieved from the string describing the document type. This parameter can have one of the following values:

•	CDocTemplate::windowTitle    Name that appears in the application window's title bar (for example, "Microsoft Excel"). Present only in the document template for SDI applications.

•	CDocTemplate::docName    Root for the default document name (for example, "Sheet"). This root, plus a number, is used for the default name of a new document of this type whenever the user chooses the New command from the File menu (for example, "Sheet1" or "Sheet2"). If not specified, "Untitled" is used as the default.

•	CDocTemplate::fileNewName    Name of this document type. If the application supports more than one type of document, this string is displayed in the File New dialog box (for example, "Worksheet"). If not specified, the document type is inaccessible using the File New command.

•	CDocTemplate::filterName    Description of the document type and a wildcard filter matching documents of this type. This string is displayed in the List Files Of Type drop-down list in the File Open dialog box (for example, "Worksheets (*.xls)"). If not specified, the document type is inaccessible using the File Open command.

•	CDocTemplate::filterExt    Extension for documents of this type (for example, ".xls"). If not specified, the document type is inaccessible using the File Open command.

•	CDocTemplate::regFileTypeId    Identifier for the document type to be stored in the registration database maintained by Windows. This string is for internal use only (for example, "ExcelWorksheet"). If not specified, the document type cannot be registered with the Windows File Manager.

•	CDocTemplate::regFileTypeName    Name of the document type to be stored in the registration database. This string may be displayed in dialog boxes of applications that access the registration database (for example, "Microsoft Excel Worksheet").

If you are using AppWizard to create a set of starter files, the last four substrings are present only if you specify a filename extension for your application's documents when running AppWizard.

Remarks

Call this function to retrieve a specific substring describing the document type. The string containing these substrings is stored in the document template and is derived from a string in the resource file for the application. The framework calls this function to get the strings it needs for the application's user interface. If you have specified a filename extension for your application's documents, the framework also calls this function when adding an entry to the Windows registration database; this allows documents to be opened from the Windows File Manager.

Call this function only if you are deriving your own class from CDocTemplate.

Return Value

Nonzero if the specified substring was found; otherwise 0.

See Also

»CMultiDocTemplate::CMultiDocTemplate«, »CSingleDocTemplate::CSingleDocTemplate«, »CWinApp::RegisterShellFileTypes«


CDocument
  class CDocument : public CCmdTarget

The CDocument class provides the basic functionality for user-defined document classes. A document represents the unit of data that the user typically opens with the File Open command and saves with the File Save command.

CDocument supports standard operations such as creating a document, loading it, and saving it. The framework manipulates documents using the interface defined by CDocument.

An application can support more than one type of document; for example, an application might support both spreadsheets and text documents. Each type of document has an associated document template; the document template specifies what resources (for example, menu, icon, or accelerator table) are used for that type of document. Each document contains a pointer to its associated CDocTemplate object.

Users interact with a document through the CView object(s) associated with it. A view renders an image of the document in a frame window and interprets user input as operations on the document. A document can have multiple views associated with it. When the user opens a window on a document, the framework creates a view and attaches it to the document. The document template specifies what type of view and frame window are used to display each type of document.

Documents are part of the framework's standard command routing and consequently receive commands from standard user-interface components (such as the File Save menu item). A document receives commands forwarded by the active view. If the document doesn't handle a given command, it forwards the command to the document template that manages it.

When a document's data is modified, each of its views must reflect those modifications. CDocument provides the UpdateAllViews member function for you to notify the views of such changes, so the views can repaint themselves as necessary. The framework also prompts the user to save a modified file before closing it.

To implement documents in a typical application, you must do the following:

•	Derive a class from CDocument for each type of document.

•	Add member variables to store each document's data.

•	Implement member functions for reading and modifying the document's data. The document's views are the most important users of these member functions.

•	Override the Serialize member function in your document class to write and read the document's data to and from disk.

#include <afxwin.h>

See Also

»CCmdTarget«, »CView«, »CDocTemplate«


CDocument Class Members
   Class Members

Construction/Destruction — Public Members

»CDocument«	Constructs a CDocument object.
Operations — Public Members

»AddView«	Attaches a view to the document.
»GetDocTemplate«	Returns a pointer to the document template that describes the type of the document.
»GetFirstViewPosition«	Returns the position of the first in the list of views; used to begin iteration.
»GetNextView«	Iterates through the list of views associated with the document.
»GetPathName«	Returns the path of the document's data file.
»GetTitle«	Returns the document's title.
»IsModified«	Indicates whether the document has been modified since it was last saved.
»RemoveView«	Detaches a view from the document.
»SetModifiedFlag«	Sets a flag indicating that you have modified the document since it was last saved.
»SetPathName«	Sets the path of the document's data file.
»SetTitle«	Sets the document's title.
»UpdateAllViews«	Notifies all views that document has been modified.
Overridables — Public Members

»CanCloseFrame«	Advanced overridable; called before closing a frame window viewing this document.
»DeleteContents«	Called to perform cleanup of the document.
»OnChangedViewList«	Called after a view is added to or removed from the document.
»OnCloseDocument«	Called to close the document.
»OnNewDocument«	Called to create a new document.
»OnOpenDocument«	Called to open an existing document.
»OnSaveDocument«	Called to save the document to disk.
»ReportSaveLoadException«	Advanced overridable; called when an open or save operation cannot be completed because of an exception.
»SaveModified«	Advanced overridable; called to ask the user whether the document should be saved.


CDocument Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDocument::AddView

void AddView( CView* pView );

pView    Points to the view being added.

Remarks

Call this function to attach a view to the document. This function adds the specified view to the list of views associated with the document; the function also sets the view's document pointer to this document. The framework calls this function when attaching a newly created view object to a document; this occurs in response to a File New, File Open, or New Window command or when a splitter window is split.

Call this function only if you are manually creating and attaching a view. Typically you will let the framework connect documents and views by defining a CDocTemplate object to associate a document class, view class, and frame window class.

See Also

»CDocTemplate«, »CDocument::GetFirstViewPosition«, »CDocument::GetNextView«, »CDocument::RemoveView«, »CView::GetDocument«


  CDocument::CanCloseFrame

virtual BOOL CanCloseFrame( CFrameWnd* pFrame );

pFrame    Points to the frame window of a view attached to the document.

Remarks

Called by the framework before a frame window displaying the document is closed. The default implementation checks if there are other frame windows displaying the document. If the specified frame window is the last one that displays the document, the function prompts the user to save the document if it has been modified. Override this function if you want to perform special processing when a frame window is closed. This is an advanced overridable.

Return Value

Nonzero if it is safe to close the frame window; otherwise 0.

See Also

»CDocument::SaveModified«


  CDocument::CDocument

CDocument();

Remarks

Constructs a CDocument object. The framework handles document creation for you. Override the OnNewDocument member function to perform initialization on a per-document basis; this is particularly important in single document interface (SDI) applications.

See Also

»CDocument::OnNewDocument«, »CDocument::OnOpenDocument«


  CDocument::DeleteContents

virtual void DeleteContents();

Remarks

Called by the framework to delete the document's data without destroying the document object itself. It is called just before the document is to be destroyed. It is also called to ensure that a document is empty before it is reused. This is particularly important for an SDI application, which uses only one document object; the document object is reused whenever the user creates or opens another document. Call this function to implement an "Edit Clear All" or similar command that deletes all of the document's data. The default implementation of this function does nothing. Override this function to delete the data in your document.

See Also

»CDocument::OnCloseDocument«, »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«


  CDocument::GetDocTemplate

CDocTemplate* GetDocTemplate() const;

Remarks

Call this function to get a pointer to the document template for this document type.

Return Value

A pointer to the document template for this document type, or NULL if the document is not managed by a document template.

See Also

»CDocTemplate«


  CDocument::GetFirstViewPosition

virtual POSITION GetFirstViewPosition() const;

Remarks

Call this function to get the position of the first view in the list of views associated with the document.

Return Value

A POSITION value that can be used for iteration with the GetNextView member function.

See Also

»CDocument::GetNextView«

 Example

To get the first view in the list of views:

POSITION pos = GetFirstViewPosition();
CView* pFirstView = GetNextView( pos );


  CDocument::GetNextView

virtual CView* GetNextView( POSITION& rPosition ) const;

rPosition    A reference to a POSITION value returned by a previous call to the GetNextView or GetFirstViewPosition member functions. This value must not be NULL.

Remarks

Call this function to iterate through all of the document's views. The function returns the view identified by rPosition and then sets rPosition to the POSITION value of the next view in the list. If the retrieved view is the last in the list, then rPosition is set to NULL.

Return Value

A pointer to the view identified by rPosition.

See Also

»CDocument::AddView«, »CDocument::GetFirstViewPosition«, »CDocument::RemoveView«, »CDocument::UpdateAllViews«


  CDocument::GetPathName

const CString& GetPathName() const;

Remarks

Call this function to get the fully qualified path of the document's disk file.

Return Value

The document's fully qualified path. This string is empty if the document has not been saved or does not have a disk file associated with it.

See Also

»CDocument::SetPathName«


  CDocument::GetTitle

const CString& GetTitle() const;

Remarks

Call this function to get the document's title, which is usually derived from the document's filename.

Return Value

The document's title.

See Also

»CDocument::SetTitle«


  CDocument::IsModified

BOOL IsModified();

Remarks

Call this function to determine whether the document has been modified since it was last saved.

Return Value

Nonzero if the document has been modified since it was last saved; otherwise 0.

See Also

»CDocument::SetModifiedFlag«, »CDocument::SaveModified«


  CDocument::OnChangedViewList

virtual void OnChangedViewList();

Remarks

Called by the framework after a view is added to or removed from the document. The default implementation of this function checks whether the last view is being removed and, if so, deletes the document. Override this function if you want to perform special processing when the framework adds or removes a view. For example, if you want a document to remain open even when there are no views attached to it, override this function.

See Also

»CDocument::AddView«, »CDocument::RemoveView«


  CDocument::OnCloseDocument

virtual void OnCloseDocument();

Remarks

Called by the framework when the document is closed, typically as part of the File Close command. The default implementation of this function calls the DeleteContents member function to delete the document's data and then closes the frame windows for all the views attached to the document.

Override this function if you want to perform special cleanup processing when the framework closes a document. For example, if the document represents a record in a database, you may want to override this function to close the database. You should call the base class version of this function from your override.

See Also

»CDocument::DeleteContents«, »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«


  CDocument::OnNewDocument

virtual BOOL OnNewDocument();

Remarks

Called by the framework as part of the File New command. The default implementation of this function calls the DeleteContents member function to ensure that the document is empty and then marks the new document as clean. Override this function to initialize the data structure for a new document. You should call the base class version of this function from your override.

If the user chooses the File New command in an SDI application, the framework uses this function to reinitialize the existing document object, rather than creating a new one. If the user chooses File New in a multiple document interface (MDI) application, the framework creates a new document object each time and then calls this function to initialize it. You must place your initialization code in this function instead of in the constructor for the File New command to be effective in SDI applications.

Return Value

Nonzero if the document was successfully initialized; otherwise 0.

See Also

»CDocument::CDocument«, »CDocument::DeleteContents«, »CDocument::OnCloseDocument«, »CDocument::OnOpenDocument«, »CDocument::OnSaveDocument«


  CDocument::OnOpenDocument

virtual BOOL OnOpenDocument( const char* pszPathName );

pszPathName    Points to the path of the document to be opened.

Remarks

Called by the framework as part of the File Open command. The default implementation of this function opens the specified file, calls the DeleteContents member function to ensure that the document is empty, calls Serialize to read the file's contents, and then marks the document as clean. Override this function if you want to use something other than the archive mechanism or the file mechanism. For example, you might write an application where documents represent records in a database rather than separate files.

If the user chooses the File Open command in an SDI application, the framework uses this function to reinitialize the existing document object, rather than creating a new one. If the user chooses File Open in an MDI application, the framework constructs a new document object each time and then calls this function to initialize it. You must place your initialization code in this function instead of in the constructor for the File Open command to be effective in SDI applications.

Return Value

Nonzero if the document was successfully loaded; otherwise 0.

See Also

»CDocument::DeleteContents«, »CDocument::OnCloseDocument«, »CDocument::OnNewDocument«, »CDocument::OnSaveDocument«, »CDocument::ReportSaveLoadException«, »CObject::Serialize«


  CDocument::OnSaveDocument

virtual BOOL OnSaveDocument( const char* pszPathName );

pszPathName    Points to the fully qualified path that the file should be saved to.

Remarks

Called by the framework as part of the File Save or File Save As command. The default implementation of this function opens the specified file, calls Serialize to write the document's data to the file, and then marks the document as clean. Override this function if you want to perform special processing when the framework saves a document. For example, you might write an application where documents represent records in a database rather than separate files.

Return Value

Nonzero if the document was successfully saved; otherwise 0.

See Also

»CDocument::OnCloseDocument«, »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«, »CDocument::ReportSaveLoadException«, »CObject::Serialize«


  CDocument::RemoveView

void RemoveView( CView* pView );

pView    Points to the view being removed.

Remarks

Call this function to detach a view from a document. This function removes the specified view from the list of views associated with the document; it also sets the view's document pointer to NULL. This function is called by the framework when a frame window is closed or a pane of a splitter window is closed.

Call this function only if you are manually detaching a view. Typically you will let the framework detach documents and views by defining a CDocTemplate object to associate a document class, view class, and frame window class.

See Also

»CDocument::AddView«, »CDocument::GetFirstViewPosition«, »CDocument::GetNextView«


  CDocument::ReportSaveLoadException

virtual void ReportSaveLoadException( const char* pszPathName, CException* e, BOOL bSaving, UINT nIDPDefault );

pszPathName    Points to name of document that was being saved or loaded.

e    Points to the exception that was thrown.

bSaving    Flag indicating what operation was in progress; nonzero if the document was being saved, 0 if the document was being loaded.

nIDPDefault    Identifier of the error message to be displayed if the function does not specify a more specific one.

Remarks

Called if an exception is thrown (typically a CFileException or CArchiveException) while saving or loading the document. The default implementation examines the exception object and looks for an error message that specifically describes the cause. If a specific message is not found, the general message specified by the nIDPDefault parameter is used. The function then displays a message box containing the error message. Override this function if you want to provide additional, customized failure messages. This is an advanced overridable.

See Also

»CDocument::OnOpenDocument«, »CDocument::OnSaveDocument«, »CFileException«, »CArchiveException«


  CDocument::SaveModified

virtual BOOL SaveModified();

Remarks

Called by the framework before a modified document is to be closed. The default implementation of this function displays a message box asking the user whether to save the changes to the document, if any have been made. Override this function if your program requires a different prompting procedure. This is an advanced overridable.

Return Value

Nonzero if it is safe to continue and close the document; 0 if the document should not be closed.

See Also

»CDocument::CanCloseFrame«, »CDocument::IsModified«, »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«, »CDocument::OnSaveDocument«


  CDocument::SetModifiedFlag

void SetModifiedFlag( BOOL bModified = TRUE );

bModified    Flag indicating whether the document has been modified.

Remarks

Call this function after you have made any modifications to the document. By calling this function consistently, you ensure that the framework prompts the user to save changes before closing a document. Typically you should use the default value of TRUE for the bModified parameter. To mark a document as clean (unmodified), call this function with a value of FALSE.

See Also

»CDocument::IsModified«, »CDocument::SaveModified«


  CDocument::SetPathName

virtual void SetPathName( const char* pszPathName );

pszPathName    Points to the string to be used as the document's path.

Remarks

Call this function to specify the fully qualified path of the document's disk file. The path is added to the most recently used (MRU) file list maintained by the application. Note that some documents are not associated with a disk file. Call this function only if you are overriding the framework's default implementation for opening and saving files.

See Also

»CDocument::GetPathName«, »CWinApp::AddToRecentFileList«


  CDocument::SetTitle

virtual void SetTitle( const char* pszTitle );

szTitle    Points to the string to be used as the document's title.

Remarks

Call this function to specify the document's title (the string displayed in the title bar of a frame window). Calling this function updates the titles of all frame windows that display the document.

See Also

»CDocument::GetTitle«


  CDocument::UpdateAllViews

void UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL );

pSender    Points to the view that modified the document, or NULL if all views are to be updated.

lHint    Contains information about the modification.

pHint    Points to an object storing information about the modification.

Remarks

Call this function after the document has been modified. You should call this function after you call the SetModifiedFlag member function. This function informs each view attached to the document, except for the view specified by pSender, that the document has been modified. You typically call this function from your view class after the user has changed the document through a view.

This function calls the OnUpdate member function for each of the document's views except the sending view, passing pHint and lHint. Use these parameters to pass information to the views about the modifications made to the document. You can encode information using lHint and/or you can define a CObject-derived class to store information about the modifications and pass an object of that class using pHint. Override the OnUpdate member function in your CView-derived class to optimize the updating of the view's display based on the information passed.

See Also

»CDocument::SetModifiedFlag«, »CDocument::GetFirstViewPosition«, »CDocument::GetNextView«, »CView::OnUpdate«


CDumpContext
  class CDumpContext

The CDumpContext class supports stream-oriented diagnostic output in the form of human-readable text. You can use afxDump, a predeclared CDumpContext object, for most of your dumping. The afxDump object is available only in the Debug version of the Microsoft Foundation Class Library.

Several of the »memory diagnostic functions« use afxDump for their output.

The predefined afxDump object, conceptually similar to the cerr stream, is connected to stderr under MS-DOS. Under the Windows environment, the output is routed to the debugger via the Windows function OutputDebugString.

The CDumpContext class has an overloaded insertion (<<) operator for CObject pointers that dumps the object's data. If you need a custom dump format for a derived object, override »CObject::Dump«. Most Microsoft Foundation classes implement an overridden Dump member function.

Classes that are not derived from CObject, such as CString, CTime, and CTimeSpan, have their own overloaded CDumpContext insertion operators, as do often-used structures such as CFileStatus, CPoint, and CRect.

If you use the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macros in the implementation of your class, then CObject::Dump will print the name of your CObject-derived class. Otherwise, it will print CObject.

The CDumpContext class is available with both the Debug and Release versions of the library, but the Dump member function is defined only in the Debug version. Use #ifdef _DEBUG / #endif statements to bracket your diagnostic code, including your custom Dump member functions.

Before you create your own CDumpContext object, you must create a CFile object that serves as the dump destination.

#define _DEBUG

#include <afx.h>

See Also

»CFile«, »CObject«


CDumpContext Class Members
  Class Members

Construction/Destruction — Public Members

»CDumpContext«	Constructs a CDumpContext object.
Basic Input/Output — Public Members

»Flush«	Flushes any data in the dump context buffer.
»operator <<«	Inserts variables and objects into the dump context.
»HexDump«	Dumps bytes in hexadecimal format.
Status — Public Members

»GetDepth«	Gets an integer corresponding to the depth of the dump.
»SetDepth«	Sets the depth of the dump.


CDumpContext Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CDumpContext::CDumpContext

CDumpContext( CFile* pFile )
throw( CMemoryException, CFileException );

pFile    A pointer to the CFile object that is the dump destination.

Remarks

Constructs an object of class CDumpContext.

The afxDump object is constructed automatically. The output from afxDump is sent to stderr in MS-DOS.

Do not write to the underlying CFile while the dump context is active; otherwise, you will interfere with the dump. Under the Windows environment, the output is routed to the debugger via the Windows function OutputDebugString.

Example

//example for CDumpContext::CDumpContext

extern char* pFileName;
CFile f;
if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite ) ) {
   afxDump << "Unable to open file" << "\n";
   exit( 1 );
}
CDumpContext dc( &f );


   CDumpContext::Flush

void Flush()
throw( CFileException );

Remarks

Forces any data remaining in buffers to be written to the file attached to the dump context.

Example

//example for CDumpContext::Flush

afxDump.Flush();


  CDumpContext::GetDepth

int GetDepth() const;

Remarks

Determines if a deep or shallow dump is in process.

Return Value

The depth of the dump as set by »SetDepth«.

See Also

»CDumpContext::SetDepth«

 Example

See the example for »SetDepth«.


  CDumpContext::HexDump

void HexDump( const char* pszLine, BYTE* pby, int nBytes, int nWidth )
throw( CFileException );

pszLine    A string to output at the start of a new line.

pby    A pointer to a buffer containing the bytes to dump.

nBytes    The number of bytes to dump.

nWidth    Maximum number of bytes dumped per line (not the width of the output line).

Remarks

Dumps an array of bytes formatted as hexadecimal numbers.

Example

//example for CDumpContext::HexDump

char test[] = "This is a test of CDumpContext::HexDump\n";
afxDump.HexDump( ".", (BYTE*) test, sizeof test, 20 );

The output from this program is:

    . 54 68 69 73 20 69 73 20 61 20 74 65 73 74 20 6F 66 20 43 44
    . 75 6D 70 43 6F 6E 74 65 78 74 3A 3A 48 65 78 44 75 6D 70 0A
    . 00


  CDumpContext::SetDepth

void SetDepth( int nNewDepth );

nNewDepth    The new depth value.

Remarks

Sets the depth for the dump. If you are dumping a primitive type or simple CObject that contains no pointers to other objects, then a value of 0 is sufficient. A value greater than 0 specifies a deep dump where all objects are dumped recursively. For example, a deep dump of a collection will dump all elements of the collection. You may use other specific depth values in your derived classes.

Note  Circular references are not detected in deep dumps and can result in infinite loops.

See Also

»CObject::Dump«

Example

//example for CDumpContext::SetDepth

afxDump.SetDepth( 1 );  // Specifies deep dump
ASSERT( afxDump.GetDepth() == 1 );


CDumpContext Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CDumpContext::operator <<

CDumpContext& operator <<( const CObject* pOb )
throw( CFileException );

CDumpContext& operator <<( const char FAR* lpsz )
throw( CFileException );

CDumpContext& operator <<( const void FAR* lp )
throw( CFileException );

CDumpContext& operator <<( const void NEAR* np )
throw( CFileException );

CDumpContext& operator <<( BYTE by )
throw( CFileException );

CDumpContext& operator <<( WORD w )
throw( CFileException );

CDumpContext& operator <<( DWORD dw )
throw( CFileException );

CDumpContext& operator <<( int n )
throw( CFileException );

CDumpContext& operator <<( LONG l )
throw( CFileException );

CDumpContext& operator <<( UINT n )
throw( CFileException );

Remarks

Outputs the specified data to the dump context.

The insertion operator is overloaded for CObject pointers as well as for most primitive types. A pointer to char results in a dump of string contents; a pointer to void results in a hexadecimal dump of the address only.

If you use the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macros in the implementation of your class, then the insertion operator, through CObject::Dump, will print the name of your CObject-derived class. Otherwise, it will print CObject. If you override the Dump function of the class, then you can provide a more meaningful output of the object's contents instead of a hexadecimal dump.

Return Value

A CDumpContext reference that enables multiple insertions on a single line.

Example

//example for CDumpContext::operator <<

extern CObList li;
CString s = "test";
int i = 7;
long lo = 1000000000L;
afxDump << "list=" << &li << "string="
        << s << "int=" << i << "long=" << lo << "\n";


CDWordArray
  class CDWordArray : public CObject

The CDWordArray class supports arrays of 32-bit doublewords.

The member functions of CDWordArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a DWORD.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

DWORD CDWordArray::GetAt( int <nIndex> ) const;

CDWordArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of doublewords is stored to an archive, either with the overloaded insertion (<<) operator or with the Serialize member function, each element is, in turn, serialized.

If you need debug output from individual elements in the array, you must set the depth of the CDumpContext object to 1 or greater.

#include <afxcoll.h>

See Also

»CObArray«


CDWordArray Class Members
  Class Members

Construction/Destruction — Public Members

»CDWordArray«	Constructs an empty array for doublewords.
»~CDWordArray«	Destroys a CDWordArray object.
Bounds — Public Members

»GetSize«	Gets the number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array not allowed to grow.
»ElementAt«	Returns a temporary reference to the doubleword within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CEdit
  class CEdit : public CWnd

The CEdit class provides the functionality of a Windows edit control. An edit control is a rectangular child window in which the user can enter text.

You can create an edit control either from a dialog template or directly in your code. In both cases, first call the constructor CEdit to construct the CEdit object, then call the »Create« member function to create the Windows edit control and attach it to the CEdit object.

Construction can be a one-step process in a class derived from CEdit. Write a constructor for the derived class and call Create from within the constructor.

CEdit inherits significant functionality from CWnd. To set and retrieve text from a CEdit object, use the CWnd member functions SetWindowText and GetWindowText, which set or get the entire contents of an edit control, even if  it is a multiline control.  Also, if an edit control is multiline, get and set part of the control's text by calling the CWnd member functions GetLine, SetSel, GetSel, and ReplaceSel.

If you want to handle Windows notification messages sent by an edit control to its parent (usually a class derived from CDialog), add a message-map entry and message-handler member function to the parent class for each message.

Each message-map entry takes the following form:

ON_Notification( id, memberFxn )

where id specifies the child window ID of the edit control sending the notification, and memberFxn is the name of the parent member function you have written to handle the notification.

The parent's function prototype is as follows:

afx_msg void memberFxn();

Following is a list of potential message-map entries and a description of the cases in which they would be sent to the parent:

•	ON_EN_CHANGE    The user has taken an action that may have altered text in an edit control. Unlike the EN_UPDATE notification message, this notification message is sent after Windows updates the display.

•	ON_EN_ERRSPACE    The edit control cannot allocate enough memory to meet a specific request.

•	ON_EN_HSCROLL    The user clicks an edit control's horizontal scroll bar. The parent window is notified before the screen is updated.

•	ON_EN_KILLFOCUS    The edit control loses the input focus.

•	ON_EN_MAXTEXT    The current insertion has exceeded the specified number of characters for the edit control and has been truncated. Also sent when an edit control does not have the ES_AUTOHSCROLL style and the number of characters to be inserted would exceed the width of the edit control. Also sent when an edit control does not have the ES_AUTOVSCROLL style and the total number of lines resulting from a text insertion would exceed the height of the edit control.

•	ON_EN_SETFOCUS    Sent when an edit control receives the input focus.

•	ON_EN_UPDATE    The edit control is about to display altered text. Sent after the control has formatted the text but before it screens the text so that the window size can be altered, if necessary.

•	ON_EN_VSCROLL    The user clicks an edit control's vertical scroll bar. The parent window is notified before the screen is updated.

If you create a CEdit object within a dialog box, the CEdit object is automatically destroyed when the user closes the dialog box.

If you create a CEdit object from a dialog resource using App Studio, the CEdit object is automatically destroyed when the user closes the dialog box.

If you create a CEdit object within a window, you may also need to destroy it. If you create the CEdit object on the stack, it is destroyed automatically. If you create the CEdit object on the heap by using the new function, you must call delete on the object to destroy it when the user terminates the Windows edit control. If you allocate any memory in the CEdit object, override the CEdit destructor to dispose of the allocations.

#include <afxwin.h>

See Also

»CWnd«, »CButton«, »CComboBox«, »CListBox«, »CScrollBar«, »CStatic«, »CDialog«


CEdit Class Members
  Class Members

Construction/Destruction — Public Members

»CEdit«	Constructs a CEdit control object.
Initialization — Public Members

»Create«	Creates the Windows edit control and attaches it to the CEdit object.
Multiple-Line Operations — Public Members

»GetLineCount«	Retrieves the number of lines in a multiple-line edit control.
»GetHandle«	Retrieves a handle to the memory currently allocated for a multiple-line edit control.
»SetHandle«	Sets the handle to the local memory that will be used by a multiple-line edit control.
»FmtLines«	Sets the inclusion of soft line-break characters on or off within a multiple-line edit control.
»LineIndex«	Retrieves the character index of a line within a multiple-line edit control.
»SetRect«	Sets the formatting rectangle of a multiple-line edit control and updates the control.
»SetRectNP«	Sets the formatting rectangle of a multiple-line edit control without redrawing the control window.
»SetTabStops«	Sets the tab stops in a multiple-line edit control.
General Operations — Public Members

»CanUndo«	Determines if an edit-control operation can be undone.
»GetModify«	Determines if the contents of an edit control have been modified.
»SetModify«	Sets or clears the modification flag for an edit control.
»SetReadOnly«	Sets the read-only state of an edit control.
»GetPasswordChar«	Retrieves the password character displayed in an edit control when the user enters text.
»GetRect«	Gets the formatting rectangle of an edit control.
»GetSel«	Gets the starting and ending character positions of the current selection in an edit control.
»GetLine«	Retrieves a line of text from an edit control.
»GetFirstVisibleLine«	Determines the topmost visible line in an edit control.
»EmptyUndoBuffer«	Resets (clears) the undo flag of an edit control.
»LimitText«	Limits the length of the text that the user may enter into an edit control.
»LineFromChar«	Retrieves the line number of the line that contains the specified character index.
»LineLength«	Retrieves the length of a line in an edit control.
»LineScroll«	Scrolls the text of a multiple-line edit control.
»ReplaceSel«	Replaces the current selection in an edit control with the specified text.
»SetPasswordChar«	Sets or removes a password character displayed in an edit control when the user enters text.
»SetSel«	Selects a range of characters in an edit control.
»Undo«	Reverses the last edit-control operation.
»Clear«	Deletes (clears) the current selection (if any) in the edit control.
»Copy«	Copies the current selection (if any) in the edit control to the Clipboard in CF_TEXT format.
»Cut«	Deletes (cuts) the current selection (if any) in the edit control and copies the deleted text to the Clipboard in CF_TEXT format.
»Paste«	Inserts the data from the Clipboard into the edit control at the current cursor position. Data is inserted only if the Clipboard contains data in CF_TEXT format.


CEdit Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CEdit::CanUndo

BOOL CanUndo() const;

Return Value

Nonzero if the last edit operation can be undone by a call to the Undo member function; 0 if it cannot be undone.

See Also

»CEdit::Undo«, EM_CANUNDO


  CEdit::CEdit

CEdit();

Remarks

Constructs a CEdit object.

See Also

»CEdit::Create«


  CEdit::Clear

void Clear();

Remarks

Deletes (clears) the current selection (if any) in the edit control.

The deletion performed by Clear can be undone by calling the Undo member function.

To delete the current selection and place the deleted contents into the Clipboard, call the »Cut« member function.

See Also

»CEdit::CanUndo«, »CEdit::Undo«, »CEdit::Copy«, »CEdit::Cut«, »CEdit::Paste«, WM_CLEAR


  CEdit::Copy

void Copy();

Remarks

Copies the current selection (if any) in the edit control to the Clipboard in CF_TEXT format.

See Also

»CEdit::Clear«, »CEdit::Cut«, »CEdit::Paste«, WM_COPY


  CEdit::Create

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle    Specifies the edit control's »style«.

rect    Specifies the edit control's size and position. Can be a CRect object or RECT structure.

pParentWnd    Specifies the edit control's parent window (usually a CDialog or CModalDialog). It must not be NULL.

nID    Specifies the edit control's ID.

Remarks

You construct a CEdit object in two steps. First, call the CEdit constructor, then call Create, which creates the Windows edit control and attaches it to the CEdit object.

When Create executes, Windows sends the »WM_NCCREATE«, »WM_NCCALCSIZE«, »WM_CREATE«, and »WM_GETMINMAXINFO« messages to the edit control.

These messages are handled by default by the »OnNcCreate«, »OnNcCalcSize«, »OnCreate«, and »OnGetMinMaxInfo« member functions in the CWnd base class. To extend the default message handling, derive a class from CEdit, add a message map to the new class, and override the above message-handler member functions. Override OnCreate, for example, to perform needed initialization for the new class.

Apply the following »window styles« to an edit control:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

•	WS_GROUP    To group controls

•	WS_TABSTOP    To include edit control in the tabbing order

Return Value

Create returns nonzero if initialization is successful; 0 if unsuccessful.

Apply any combination of »edit styles« to the edit control.

 Edit Styles

You can use any combination of the following edit-control styles for dwStyle:

•	ES_AUTOHSCROLL    Automatically scrolls text to the right by 10 characters when the user types a character at the end of the line. When the user presses the ENTER key, the control scrolls all text back to position 0.

•	ES_AUTOVSCROLL    Automatically scrolls text up one page when the user presses ENTER on the last line.

•	ES_CENTER    Centers text in a multiline edit control.

•	ES_LEFT    Aligns text flush left.

•	ES_LOWERCASE    Converts all characters to lowercase as they are typed into the edit control.

•	ES_MULTILINE    Designates a multiple-line edit control. (The default is single line.) If the ES_AUTOVSCROLL style is specified, the edit control shows as many lines as possible and scrolls vertically when the user presses the ENTER key. If ES_AUTOVSCROLL is not given, the edit control shows as many lines as possible and beeps if ENTER is pressed when no more lines can be displayed. If the ES_AUTOHSCROLL style is specified, the multiple-line edit control automatically scrolls horizontally when the caret goes past the right edge of the control. To start a new line, the user must press ENTER. If ES_AUTOHSCROLL is not given, the control automatically wraps words to the beginning of the next line when necessary; a new line is also started if ENTER is pressed. The position of the wordwrap is determined by the window size. If the window size changes, the wordwrap position changes and the text is redisplayed. Multiple-line edit controls can have scroll bars. An edit control with scroll bars processes its own scroll-bar messages. Edit controls without scroll bars scroll as described above and process any scroll messages sent by the parent window.

•	ES_NOHIDESEL    Normally, an edit control hides the selection when the control loses the input focus and inverts the selection when the control receives the input focus. Specifying ES_NOHIDESEL deletes this default action.

•	ES_OEMCONVERT    Text entered in the edit control is converted from the ANSI character set to the OEM character set and then back to ANSI. This ensures proper character conversion when the application calls the AnsiToOem Windows function to convert an ANSI string in the edit control to OEM characters. This style is most useful for edit controls that contain filenames.

•	ES_PASSWORD    Displays all characters as an asterisk (*) as they are typed into the edit control. An application can use the SetPasswordChar member function to change the character that is displayed.

•	ES_RIGHT    Aligns text flush right in a multiline edit control.

•	ES_UPPERCASE    Converts all characters to uppercase as they are typed into the edit control.

Windows 3.1 Only

•	ES_READONLY    Prevents the user from entering or editing text in the edit control.

•	ES_WANTRETURN    Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, pressing the ENTER key has the same effect as pressing the dialog box's default pushbutton. This style has no effect on a single-line edit control. ♦

See Also

»CEdit::CEdit«


  CEdit::Cut

void Cut();

Remarks

Deletes (cuts) the current selection (if any) in the edit control and copies the deleted text to the Clipboard in CF_TEXT format.

The deletion performed by Cut can be undone by calling the Undo member function.

To delete the current selection without placing the deleted text into the Clipboard, call the »Clear« member function.

See Also

»CEdit::Undo«, »CEdit::Clear«, »CEdit::Copy«, »CEdit::Paste«, WM_CUT


  CEdit::EmptyUndoBuffer

void EmptyUndoBuffer();

Remarks

Resets (clears) the undo flag of an edit control. The edit control will now be unable to undo the last operation. The undo flag is set whenever an operation within the edit control can be undone.

The undo flag is automatically cleared whenever the »SetWindowText« or SetHandle member function is called.

See Also

»CEdit::CanUndo«, »CEdit::SetHandle«, »CEdit::Undo«, »CWnd::SetWindowText«, EM_EMPTYUNDOBUFFER


  CEdit::FmtLines

BOOL FmtLines( BOOL bAddEOL );

bAddEOL    Specifies whether soft line-break characters are to be inserted. A value of TRUE inserts the characters; a value of FALSE removes them.

Remarks

Sets the inclusion of soft line-break characters on or off within a multiple-line edit control. A soft line break consists of two carriage returns and a linefeed inserted at the end of a line that is broken because of word wrapping. A hard line break consists of one carriage return and a linefeed. Lines that end with a hard line break are not affected by FmtLines.

Windows will only respond if the CEdit object is a multiple-line edit control.

FmtLines only affects the buffer returned by »GetHandle« and the text returned by WM_GETTEXT.It has no impact on the display of the text within the edit control.

Return Value

Nonzero if any formatting occurs; otherwise 0.

See Also

»CEdit::GetHandle«, »CWnd::GetWindowText«, EM_FMTLINES


  CEdit::GetFirstVisibleLine

Windows 3.1 Only

int GetFirstVisibleLine() const; ♦

Remarks

An application calls GetFirstVisibleLine to determine the topmost visible line in an edit control.

Return Value

The zero-based index of the topmost visible line. For single-line edit controls, the return value is 0.

See Also

EM_GETFIRSTVISIBLELINE


  CEdit::GetHandle

HLOCAL GetHandle() const;

Remarks

Retrieves a handle to the memory currently allocated for a multiple-line edit control. The handle is a local memory handle and may be used by any of the Local Windows memory functions that take a local memory handle as a parameter.

GetHandle is processed only by multiple-line edit controls.

Call GetHandle for a multiple-line edit control in a dialog box only if the dialog box was created with the DS_LOCALEDIT style flag set. If the DS_LOCALEDIT style is not set, you will still get a nonzero return value, but you will not be able to use the returned value.

Return Value

A local memory handle that identifies the buffer holding the contents of the edit control. If an error occurs, such as sending the message to a single-line edit control, the return value is 0.

See Also

»CEdit::SetHandle«, EM_GETHANDLE


  CEdit::GetLine

int GetLine( int nIndex, LPSTR lpszBuffer ) const;

int GetLine( int nIndex, LPSTR lpszBuffer, int nMaxLength ) const;

nIndex    Specifies the line number to retrieve from a multiple-line edit control. Line numbers are zero-based; a value of 0 specifies the first line. This parameter is ignored by a single-line edit control.

lpszBuffer    Points to the buffer that receives a copy of the line. The first word of the buffer must specify the maximum number of bytes that can be copied to the buffer.

nMaxLength    Specifies the maximum number of bytes that can be copied to the buffer. GetLine places this value in the first word of lpszBuffer before making the call to Windows.

Remarks

Retrieves a line of text from an edit control and places it in lpszBuffer. This call is not processed for a single-line edit control.

The copied line does not contain a null-termination character.

Return Value

The number of bytes actually copied. The return value is 0 if the line number specified by nIndex is greater then the number of lines in the edit control.

See Also

»CEdit::LineLength«, »CWnd::GetWindowText«, EM_GETLINE


  CEdit::GetLineCount

int GetLineCount() const;

Remarks

Retrieves the number of lines in a multiple-line edit control.

GetLineCount is only processed by multiple-line edit controls.

Return Value

An integer containing the number of lines in the multiple-line edit control. If no text has been entered into the edit control, the return value is 1.

See Also

EM_GETLINECOUNT


  CEdit::GetModify

BOOL GetModify() const;

Remarks

Determines if the contents of an edit control have been modified.

Windows maintains an internal flag indicating whether the contents of the edit control have been changed. This flag is cleared when the edit control is first created and may also be cleared by calling the »SetModify« member function.

Return Value

Nonzero if the edit-control contents have been modified; 0 if they have remained unchanged.

See Also

»CEdit::SetModify«, EM_GETMODIFY


  CEdit::GetPasswordChar

Windows 3.1 Only

char GetPasswordChar() const; ♦

Remarks

An application calls the GetPasswordChar member function to retrieve the password character displayed in an edit control when the user enters text.

If the edit control is created with the ES_PASSWORD style, the default password character is set to an asterisk (*).

Return Value

Specifies the character to be displayed in place of the character typed by the user. The return value is NULL if no password character exists.

See Also

EM_GETPASSWORDCHAR, »CEdit::SetPasswordChar«


  CEdit::GetRect

void GetRect( LPRECT lpRect ) const;

lpRect    Points to the RECT structure that receives the formatting rectangle.

Remarks

Gets the formatting rectangle of an edit control. The formatting rectangle is the limiting rectangle of the text, which is independent of the size of the edit-control window.

The formatting rectangle of a multiple-line edit control can be modified by the »SetRect« and »SetRectNP« member functions.

See Also

»CEdit::SetRect«, »CEdit::SetRectNP«, EM_GETRECT


  CEdit::GetSel

DWORD GetSel() const;

void GetSel( int& nStartChar, int& nEndChar ) const;

nStartChar    Reference to an integer that will receive the position of the first character in the current selection.

nEndChar     Reference to an integer that will receive the position of the first nonselected character past the end of the current selection.

Remarks

Gets the starting and ending character positions of the current selection (if any) in an edit control, using either the return value or the parameters.

Return Value

The version that returns a DWORD returns a value that contains the starting position in the low-order word and the position of the first nonselected character after the end of the selection in the high-order word.

See Also

»CEdit::SetSel«, EM_GETSEL


  CEdit::LimitText

void LimitText( int nChars = 0 );

nChars    Specifies the length (in bytes) of the text that the user can enter. If this parameter is 0, the text length is set to UINT_MAX bytes. This is the default behavior.

Remarks

Limits the length of the text that the user may enter into an edit control.

LimitText limits only the text the user can enter. It has no effect on any text already in the edit control when the message is sent, nor does it affect the length of the text copied to the edit control by the »SetWindowText« member function in CWnd. If an application uses the SetWindowText function to place more text into an edit control than is specified in the call to LimitText, the user can edit the entire contents of the edit control.

See Also

»CWnd::SetWindowText«, EM_LIMITTEXT


  CEdit::LineFromChar

int LineFromChar( int nIndex = −1 ) const;

nIndex    Contains the zero-based index value for the desired character in the text of the edit control, or contains −1. If nIndex is −1, it specifies the current line, that is, the line that contains the caret.

Remarks

Retrieves the line number of the line that contains the specified character index. A character index is the number of characters from the beginning of the edit control.

This member function is only used by multiple-line edit controls.

Return Value

The zero-based line number of the line containing the character index specified by nIndex. If nIndex is −1, the number of the line that contains the first character of the selection is returned. If there is no selection, the current line number is returned.

See Also

»CEdit::LineIndex«, EM_LINEFROMCHAR


  CEdit::LineIndex

int LineIndex( int nLine = −1 ) const;

nLine    Contains the index value for the desired line in the text of the edit control, or contains −1. If nLine is −1, it specifies the current line, that is, the line that contains the caret.

Remarks

Retrieves the character index of a line within a multiple-line edit control. The character index is the number of characters from the beginning of the edit control to the specified line.

This member function is only processed by multiple-line edit controls.

Return Value

The character index of the line specified in nLine or −1 if the specified line number is greater then the number of lines in the edit control.

See Also

»CEdit::LineFromChar«, EM_LINEINDEX


  CEdit::LineLength

int LineLength( int nLine = −1 ) const;

nLine    Specifies the character index of a character in the line whose length is to be retrieved. If this parameter is −1, the length of the current line (the line that contains the caret) is returned, not including the length of any selected text within the line. When LineLength is called for a single-line edit control, this parameter is ignored.

Remarks

Retrieves the length of a line in an edit control.

Use the »LineIndex« member function to retrieve a character index for a given line number within a multiple-line edit control.

Return Value

When LineLength is called for a multiple-line edit control, the return value is the length (in bytes) of the line specified by nLine. When LineLength is called for a single-line edit control, the return value is the length (in bytes) of the text in the edit control.

See Also

»CEdit::LineIndex«, EM_LINELENGTH


  CEdit::LineScroll

void LineScroll( int nLines, int nChars = 0 );

nLines    Specifies the number of lines to scroll vertically.

nChars    Specifies the number of character positions to scroll horizontally. This value is ignored if the edit control has either the ES_RIGHT or ES_CENTER style.

Remarks

Scrolls the text of a multiple-line edit control.

This member function is processed only by multiple-line edit controls.

The edit control does not scroll vertically past the last line of text in the edit control. If the current line plus the number of lines specified by nLines exceeds the total number of lines in the edit control, the value is adjusted so that the last line of the edit control is scrolled to the top of the edit-control window.

LineScroll can be used to scroll horizontally past the last character of any line.

See Also

EM_LINESCROLL


  CEdit::Paste

void Paste();

Remarks

Inserts the data from the Clipboard into the edit control at the current cursor position. Data is inserted only if the Clipboard contains data in CF_TEXT format.

See Also

»CEdit::Clear«, »CEdit::Copy«, »CEdit::Cut«, WM_PASTE


  CEdit::ReplaceSel

void ReplaceSel( LPCSTR lpszNewText );

lpszNewText    Points to a null-terminated string containing the replacement text.

Remarks

Replaces the current selection in an edit control with the text specified by lpszNewText.

Replaces only a portion of the text in an edit control. If you want to replace all of the text, use the »CWnd::SetWindowText« member function.

If there is no current selection, the replacement text is inserted at the current cursor location.

See Also

»CWnd::SetWindowText«, EM_REPLACESEL


  CEdit::SetHandle

void SetHandle( HLOCAL hBuffer );

hBuffer    Contains a handle to the local memory. This handle must have been created by a previous call to the LocalAllocWindows function using the LMEM_MOVEABLE flag. The memory is assumed to contain a null-terminated string. If this is not the case, the first byte of the allocated memory should be set to 0.

Remarks

Sets the handle to the local memory that will be used by a multiple-line edit control. The edit control will then use this buffer to store the currently displayed text instead of allocating its own buffer.

This member function is processed only by multiple-line edit controls.

Before an application sets a new memory handle, it should use the »GetHandle« member function to get the handle to the current memory buffer and free that memory using the LocalFreeWindows function.

SetHandle clears the undo buffer (the CanUndo member function then returns 0) and the internal modification flag (the GetModify member function then returns 0). The edit-control window is redrawn.

You can use this member function in a multiple-line edit control in a dialog box only if you have created the dialog box with the DS_LOCALEDIT style flag set.

See Also

»CEdit::CanUndo«, »CEdit::GetHandle«, »CEdit::GetModify«, ::LocalAlloc, ::LocalFree, EM_SETHANDLE


  CEdit::SetModify

void SetModify( BOOL bModified = TRUE );

bModified    A value of TRUE indicates that the text has been modified, and a value of FALSE indicates it is unmodified. By default, the modified flag is set.

Remarks

Sets or clears the modified flag for an edit control. The modified flag indicates whether or not the text within the edit control has been modified. It is automatically set whenever the user changes the text. Its value may be retrieved with the »GetModify« member function.

See Also

»CEdit::GetModify«, EM_SETMODIFY


  CEdit::SetPasswordChar

void SetPasswordChar( char ch );

ch    Specifies the character to be displayed in place of the character typed by the user. If ch is 0, the actual characters typed by the user are displayed.

Remarks

Sets or removes a password character displayed in an edit control when the user types text. When a password character is set, that character is displayed for each character the user types.

This member function has no effect on a multiple-line edit control.

When the SetPasswordChar member function is called, CEdit will redraw all visible characters using the character specified by ch.

If the edit control is created with the »ES_PASSWORD« style, the default password character is set to an asterisk (*). This style is removed if SetPasswordChar is called with ch set to 0.

See Also

»CEdit::GetPasswordChar«, EM_SETPASSWORDCHAR


  CEdit::SetReadOnly

Windows 3.1 Only

BOOL SetReadOnly( BOOL bReadOnly = TRUE ); ♦

bReadOnly    Specifies whether to set or remove the read-only state of the edit control. A value of TRUE sets the state to read-only; a value of FALSE sets the state to read/write.

Remarks

An application calls the SetReadOnly member function to set the read-only state of an edit control.

The current setting can be found by testing the »ES_READONLY« flag in the return value of »CWnd::GetStyle«.

Return Value

Nonzero if the operation is successful, or 0 if an error occurs.

See Also

EM_SETREADONLY, »CWnd::GetStyle«


  CEdit::SetRect

void SetRect( LPCRECT lpRect );

lpRect    Points to the RECT structure or CRect object that specifies the new dimensions of the formatting rectangle.

Remarks

Sets the dimensions of a rectangle using the specified coordinates. This member is processed only by multiple-line edit controls.

Use SetRect to set the formatting rectangle of a multiple-line edit control. The formatting rectangle is the limiting rectangle of the text, which is independent of the size of the edit-control window. When the edit control is first created, the formatting rectangle is the same as the client area of the edit-control window. By using the SetRect member function, an application can make the formatting rectangle larger or smaller than the edit-control window.

If the edit control has no scroll bar, text will be clipped, not wrapped, if the formatting rectangle is made larger than the window. If the edit control contains a border, the formatting rectangle is reduced by the size of the border. If you adjust the rectangle returned by the GetRect member function, you must remove the size of the border before you pass the rectangle to SetRect.

When SetRect is called, the edit control's text is also reformatted and redisplayed.

See Also

»CRect::CRect«, »CRect::CopyRect«, »CRect::operator =«, »CRect::SetRectEmpty«, »CEdit::GetRect«, »CEdit::SetRectNP«, EM_SETRECT


  CEdit::SetRectNP

void SetRectNP( LPCRECT lpRect );

lpRect    Points to a RECT structure or CRect object that specifies the new dimensions of the rectangle.

Remarks

Sets the formatting rectangle of a multiple-line edit control. The formatting rectangle is the limiting rectangle of the text, which is independent of the size of the edit-control window.

SetRectNP is identical to the SetRect member function except that the edit-control window is not redrawn.

When the edit control is first created, the formatting rectangle is the same as the client area of the edit-control window. By calling the SetRectNP member function, an application can make the formatting rectangle larger or smaller than the edit-control window.

If the edit control has no scroll bar, text will be clipped, not wrapped, if the formatting rectangle is made larger than the window.

This member is processed only by multiple-line edit controls.

See Also

»CRect::CRect«, »CRect::CopyRect«, »CRect::operator =«, »CRect::SetRectEmpty«, »CEdit::GetRect«, »CEdit::SetRect«, EM_SETRECTNP


  CEdit::SetSel

void SetSel( DWORD dwSelection, BOOL bNoScroll = FALSE );

void SetSel( int nStartChar, int nEndChar, BOOL bNoScroll = FALSE );

dwSelection    Specifies the starting position in the low-order word and the ending position in the high-order word. If the low-order word is 0 and the high-order word is −1, all the text in the edit control is selected. If the low-order word is −1, any current selection is removed.

Windows 3.1 Only

bNoScroll     Indicates whether the caret should be scrolled into view. If FALSE, the caret is scrolled into view. If TRUE, the caret is not scrolled into view. ♦

nStartChar    Specifies the starting position. If nStartChar is 0 and nEndChar is −1, all the text in the edit control is selected. If nStartChar is −1, any current selection is removed.

nEndChar    Specifies the ending position.

Remarks

Selects a range of characters in an edit control.

See Also

»CEdit::GetSel«, »CEdit::ReplaceSel«, EM_SETSEL


  CEdit::SetTabStops

void SetTabStops();

BOOL SetTabStops( const int& cxEachStop );

BOOL SetTabStops( int nTabStops, LPINT rgTabStops );

cxEachStop    Specifies that tab stops are to be set at every cxEachStop dialog units.

nTabStops    Specifies the number of tab stops contained in rgTabStops. This number must be greater than 1.

rgTabStops    Points to an array of unsigned integers specifying the tab stops in dialog units. A dialog unit is a horizontal or vertical distance. One horizontal dialog unit is equal to one-fourth of the current dialog base width unit, and 1 vertical dialog unit is equal to one-eighth of the current dialog base height unit. The dialog base units are computed based on the height and width of the current system font. The GetDialogBaseUnits Windows function returns the current dialog base units in pixels.

Remarks

Sets the tab stops in a multiple-line edit control. When text is copied to a multiple-line edit control, any tab character in the text will cause space to be generated up to the next tab stop.

To set tab stops to the default size of 32 dialog units, call the parameterless version of this member function. To set tab stops to a size other than 32, call the version with the cxEachStop parameter. To set tab stops to an array of sizes, use the  version with two parameters.

This member function is only processed by multiple-line edit controls.

SetTabStops does not automatically redraw the edit window. If you change the tab stops for text already in the edit control, call »CWnd::InvalidateRect« to redraw the edit window.

Return Value

Nonzero if the tabs were set; otherwise 0.

See Also

::GetDialogBaseUnits, »CWnd::InvalidateRect«, EM_SETTABSTOPS


  CEdit::Undo

BOOL Undo();

Remarks

Use to undo the last edit-control operation.

An undo operation can also be undone. For example, you can restore deleted text with the first call to Undo. As long as there is no intervening edit operation, you can remove the text again with a second call to Undo.

Return Value

For a single-line edit control, the return value is always nonzero. For a multiple-line edit control, the return value is nonzero if the undo operation is successful, or 0 if the undo operation fails.

See Also

»CEdit::CanUndo«, EM_UNDO


CEditView
  class CEditView : public CView

Like the CEdit class, the CEditView class provides the functionality of a Windows edit control. The CEditView class provides the following additional functions:

•	Printing

•	Find and replace

•	Cut, copy, paste, clear, and undo

Because class CEditView is derived from class CView, objects of class CEditView can be used with documents and document templates.

Each CEditView control's text is kept in its own global memory object. Your application can have any number of CEditView controls.

Create objects of type CEditView if you want an edit control with the added functionality listed above. Derive your own classes from CEditView to add or modify the basic functionality, or to declare classes that can be added to a document template.

The default implementation of class CEditView handles the following commands: ID_EDIT_CUT, ID_EDIT_COPY, ID_EDIT_PASTE, ID_EDIT_CLEAR, ID_EDIT_UNDO, ID_EDIT_SELECT_ALL, ID_EDIT_FIND, ID_EDIT_REPLACE, ID_EDIT_REPEAT, and ID_FILE_PRINT.

Objects of type CEditView (or of types derived from CEditView) have the following limitations:

•	CEditView does not implement true WYSIWYG (what you see is what you get) editing. Where there is a choice between readability on the screen and matching printed output, CEditView opts for screen readability.

•	CEditView can display text in only a single font. No special character formatting is supported.

•	The amount of text a CEditView can contain is limited. The limits are the same as for the CEdit control.

#include <afxext.h>

See Also

»CEdit«, »CDocument«, »CDocTemplate«, »CView«


CEditView Class Members
  Class Members

Data Members — Public Members

»dwStyleDefault«	Default style for objects of type CEditView.
Construction/Destruction — Public Members

»CEditView«	Constructs an object of type CEditView.
Attributes — Public Members

»GetEditCtrl«	Provides access to the CEdit portion of a CEditView object (the Windows edit control).
»GetPrinterFont«	Retrieves the current printer font.
»GetSelectedText«	Retrieves the current text selection.
»SetPrinterFont«	Sets a new printer font.
»SetTabStops«	Sets tab stops for both screen display and printing.
Operations — Public Members

»FindText«	Searches for a string within the text.
»PrintInsideRect«	Renders text inside a given rectangle.
»SerializeRaw«	Serializes a CEditView object to disk as raw text.
Overridables — Protected Members

»OnFindNext«	Finds next occurrence of a text string.
»OnReplaceAll«	Replaces all occurrences of a given string with a new string.
»OnReplaceSel«	Replaces current selection.
»OnTextNotFound«	Called when a find operation fails to match any further text.


CEditView Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CEditView::CEditView

CEditView();

Remarks

Constructs an object of type CEditView. After constructing the object, you must call the Create function before the edit control is used. If you derive a class from CEditView and add it to the template using CWinApp::AddDocTemplate, the framework calls both this constructor and the Create function.

See Also

»CWnd::Create«, »CWinApp::AddDocTemplate«


  CEditView::FindText

BOOL FindText( LPCSTR lpszFind, BOOL bNext = TRUE, BOOL bCase = TRUE );

lpszFind    The text to be found.

bNext    Specifies the direction of the search. If TRUE, the search direction is toward the end of the buffer. If FALSE, the search direction is toward the beginning of the buffer.

bCase    Specifies whether the search is case sensitive. If TRUE, the search is case sensitive. If FALSE, the search is not case sensitive.

Remarks

Call the FindText function to search the CEditView object's text buffer. This function searches the text in the buffer for the text specified by lpszFind, starting at the current selection, in the direction specified by bNext, and with case sensitivity specified by bCase. If the text is found, it sets the selection to the found text and returns a nonzero value. If the text is not found, the function returns 0.

You normally do not need to call the FindText function unless you override OnFindNext, which calls FindText.

Return Value

Nonzero if the search text is found; otherwise 0.

See Also

»CEditView::OnFindNext«, »CEditView::OnReplaceAll«, »CEditView::OnReplaceSel«, »CEditView::OnTextNotFound«


  CEditView::GetEditCtrl

CEdit& GetEditCtrl() const;

Remarks

Call GetEditCtrl to get a reference to the edit control used by the edit view. This control is of type »CEdit«, so you can manipulate the Windows edit control directly using the CEdit member functions.

Warning  Using the CEdit object can change the state of the underlying Windows edit control. For example, you should not change the tab settings using the »CEdit::SetTabStops« function because CEditView caches these settings for use both in the edit control and in printing. Instead, use »CEditView::SetTabStops«.

Return Value

A reference to a CEdit object.

See Also

»CEdit«, »CEditView::SetTabStops«


  CEditView::GetPrinterFont

CFont* GetPrinterFont() const;

Remarks

Call GetPrinterFont to get a pointer to a »CFont« object that describes the current printer font. If the printer font has not been set, the default printing behavior of the CEditView class is to print using the same font used for display.

Use this function to determine the current printer font. If it is not the desired printer font, use »CEditView::SetPrinterFont« to change it.

Return Value

A pointer to a CFont object that specifies the current printer font; NULL if the printer font has not been set. The pointer may be temporary and should not be stored for later use.

See Also

»CEditView::SetPrinterFont«


  CEditView::GetSelectedText

void GetSelectedText( CString& strResult ) const;

strResult    A reference to the CString object that is to receive the selected text.

Remarks

Call GetSelectedText to copy the selected text into a CString object, up to the end of the selection or the character preceding the first carriage-return character in the selection.

See Also

»CEditView::OnReplaceSel«


  CEditView::OnFindNext

Protected

virtual void OnFindNext( LPCSTR lpszFind, BOOL bNext, BOOL bCase ); ♦

lpszFind    The text to be found.

bNext    Specifies the direction of the search. If TRUE, the search direction is toward the end of the buffer. If FALSE, the search direction is toward the beginning of the buffer.

bCase    Specifies whether the search is case sensitive. If TRUE, the search is case sensitive. If FALSE, the search is not case sensitive.

Remarks

Searches the text in the buffer for the text specified by lpszFind, in the direction specified by bNext, with case sensitivity specified by bCase. The search starts at the beginning of the current selection and is accomplished through a call to »FindText«. In the default implementation, OnFindNext calls »OnTextNotFound« if the text is not found.

Override OnFindNext to change the way a CEditView-derived object searches text. CEditView calls OnFindNext when the user chooses the Find Next button in the standard Find dialog box.

See Also

»CEditView::OnTextNotFound«, »CEditView::FindText«, »CEditView::OnReplaceAll«, »CEditView::OnReplaceSel«


  CEditView::OnReplaceAll

Protected

virtual void OnReplaceAll( LPCSTR lpszFind, LPCSTR lpszReplace, BOOL bCase ); ♦

lpszFind    The text to be found.

lpszReplace    The text to replace the search text.

bCase    Specifies whether search is case sensitive. If TRUE, the search is case sensitive. If FALSE, the search is not case sensitive.

Remarks

CEditView calls OnReplaceAll when the user selects the Replace All button in the standard Replace dialog box. OnReplaceAll searches the text in the buffer for the text specified by lpszFind, with case sensitivity specified by bCase. The search starts at the beginning of the current selection. Each time the search text is found, this function replaces that occurrence of the text with the text specified by lpszReplace. The search is accomplished through a call to »FindText«. In the default implementation, »OnTextNotFound« is called if the text is not found.

Override OnReplaceAll to change the way a CEditView-derived object replaces text.

See Also

»CEditView::OnFindNext«, »CEditView::OnTextNotFound«, »CEditView::FindText«, »CEditView::OnReplaceSel«


  CEditView::OnReplaceSel

Protected

virtual void OnReplaceSel( LPCSTR lpszFind, BOOL bNext, BOOL bCase, LPCSTR lpszReplace ); ♦

lpszFind    The text to be found.

bNext    Specifies the direction of the search. If TRUE, the search direction is toward the end of the buffer. If FALSE, the search direction is toward the beginning of the buffer.

bCase    Specifies whether the search is case sensitive. If TRUE, the search is case sensitive. If FALSE, the search is not case sensitive.

lpszReplace    The text to replace the found text.

Remarks

CEditView calls OnReplaceSel when the user selects the Replace button in the standard Replace dialog box.

After replacing the selection, this function searches the text in the buffer for the next occurrence of the text specified by lpszFind, in the direction specified by bNext, with case sensitivity specified by bCase. The search is accomplished through a call to »FindText«. If the text is not found, »OnTextNotFound« is called.

Override OnReplaceSel to change the way a CEditView-derived object replaces the selected text.

See Also

»CEditView::OnFindNext«, »CEditView::OnTextNotFound«, »CEditView::FindText«, »CEditView::OnReplaceAll«


  CEditView::OnTextNotFound

Protected

virtual void OnTextNotFound( LPCSTR lpszFind ); ♦

lpszFind    The text to be found.

Remarks

Override this function to change the default implementation, which calls the Windows function MessageBeep.

See Also

»CEditView::FindText«, »CEditView::OnFindNext«, »CEditView::OnReplaceAll«, »CEditView::OnReplaceSel«


  CEditView::PrintInsideRect

UINT PrintInsideRect( CDC *pDC, RECT& rectLayout, UINT nIndexStart, UINT nIndexStop );

pDC    Pointer to the printer device context.

rectLayout    Reference to a CRect object or RECT structure specifying the rectangle in which the text is to be rendered.

nIndexStart    Index within the buffer of the first character to be rendered.

nIndexStop    Index within the buffer of the character following the last character to be rendered.

Remarks

Call PrintInsideRect to print text in the rectangle specified by rectLayout.

If the CEditView control does not have the style ES_AUTOHSCROLL, text is wrapped within the rendering rectangle. If the control does have the style ES_AUTOHSCROLL, the text is clipped at the right edge of the rectangle.

The rect.bottom element of the rectLayout object is changed so that the rectangle's dimensions define the part of the original rectangle that is occupied by the text.

Return Value

The index of the next character to be printed (i.e., the character following the last character rendered).

See Also

»CEditView::SetPrinterFont«, »CEditView::GetPrinterFont«


  CEditView::SerializeRaw

void SerializeRaw( CArchive& ar );

ar    Reference to the CArchive object that stores the serialized text.

Remarks

Call SerializeRaw to have a CArchive object read or write the text in the CEditView object to a text file. SerializeRaw differs from CEditView's internal implementation of Serialize in that it reads and writes only the text, without preceding object-description data.

See Also

»CArchive«, »CObject::Serialize«


  CEditView::SetPrinterFont

void SetPrinterFont( CFont* pFont );

pFont    A pointer to an object of type CFont. If NULL, the font used for printing is based on the display font.

Remarks

Call SetPrinterFont to set the printer font to the font specified by pFont.

If you want your view to always use a particular font for printing, include a call to SetPrinterFont in your class's OnPreparePrinting function. This virtual function is called before printing occurs, so the font change takes place before the view's contents are printed.

See Also

»CWnd::SetFont«, »CFont«, »CView::OnPreparePrinting«


  CEditView::SetTabStops

void SetTabStops( int nTabStops );

nTabStops    Width of each tab stop, in dialog units.

Remarks

Call this function to set the tab stops used for display and printing. Only a single tab-stop width is supported. (CEdit objects support multiple tab widths.) Widths are in dialog units, which equal one-fourth of the average character width (based on uppercase and lowercase alphabetic characters only) of the font used at the time of printing or displaying. You should not use CEdit::SetTabStops because CEditView must cache the tab-stop value.

This function modifies only the tabs of the object for which it is called. To change the tab stops for each CEditView object in your application, call each object's SetTabStops function. dwStyleDefault is a public member variable of type DWORD.

See Also

»CWnd::SetFont«, »CEditView::SetPrinterFont«


CEditView Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CEditView::dwStyleDefault

Remarks

Pass this static member as the dwStyle parameter of the Create function to obtain the default style for the CEditView object. dwStyleDefault is a public member of type DWORD.


CException
  class CException : public CObject

CException is the base class for all exceptions in the Microsoft Foundation Class Library. The derived classes and their descriptions are listed below:

»CNotSupportedException«	Request for an unsupported operation
»CArchiveException«	Archive-specific exceptions
»CFileException«	File-specific exceptions
»CResourceException«	Windows resource not found or not creatable
»COleException«	OLE (Object Linking and Embedding) exception
These exceptions are intended to be used with the »THROW«, »THROW_LAST«, »TRY«, »CATCH«, »AND_CATCH«, and »END_CATCH« macros. For more information on exceptions, see Chapter 16, "Exceptions," in the Class Library User's Guide.

For on-line information on exceptions, see »Exception Processing«.

Use the derived classes to catch specific exceptions. Use CException if you need to catch all types of exceptions (and then use CObject::IsKindOf to differentiate among CException-derived classes). All derived CException classes use the IMPLEMENT_DYNAMIC macro.

CException objects are deleted automatically. Do not delete them yourself.

Because CException is an abstract base class, you cannot create CException objects; you must create objects of derived classes. If you need to create your own CException type, use one of the derived classes listed above as a model.

#include <afx.h>

See Also

»Exception Processing«


CFile
  class CFile : public CObject

CFile is the base class for Microsoft Foundation file classes. It directly provides unbuffered, binary disk input/output services, and it indirectly supports text files and memory files through its derived classes. CFile works in conjunction with the CArchive class to support serialization of Microsoft Foundation objects.

The hierarchical relationship between this class and its derived classes allows your program to operate on all file objects through the polymorphic CFile interface. A memory file, for example, behaves like a disk file.

Use CFile and its derived classes for general-purpose disk I/O. Use ofstream or other Microsoft iostream classes for formatted text sent to a disk file.

Normally, a disk file is opened automatically on CFile construction and closed on destruction. Static member functions permit you to interrogate a file's status without opening the file.

#include <afx.h>

See Also

»CStdioFile«, »CMemFile«


CFile  Class Members
  Class Members

Data Members — Public Members

»m_hFile«	Usually contains the operating-system file handle.
Construction/Destruction — Public Members

»CFile«	Constructs a CFile object from a path or file handle.
»Duplicate«	Constructs a duplicate object based on this file.
»Open«	Safely opens a file with an error-testing option.
»Close«	Closes a file and deletes the object.
Input/Output — Public Members

»Read«	Reads (unbuffered) data from a file at the current file position.
»ReadHuge«	Can read more than 64K of (unbuffered) data from a file at the current file position.
»Write«	Writes (unbuffered) data in a file to the current file position.
»WriteHuge«	Can write more than 64K of (unbuffered) data in a file to the current file position.
»Flush«	Flushes any data yet to be written.
Position — Public Members

»Seek«	Positions the current file pointer.
»SeekToBegin«	Positions the current file pointer at the beginning of the file.
»SeekToEnd«	Positions the current file pointer at the end of the file.
»GetLength«	Obtains the length of the file.
»SetLength«	Changes the length of the file.
Locking — Public Members

»LockRange«	Locks a range of bytes in a file.
»UnlockRange«	Unlocks a range of bytes in a file.
Status — Public Members

»GetPosition«	Gets the current file pointer.
»GetStatus«	Obtains the status of this open file.
Static — Public Members

»Rename«	Renames the specified file (static function).
»Remove«	Deletes the specified file (static function).
»GetStatus«	Obtains the status of the specified file (static, virtual function).
»SetStatus«	Sets the status of the specified file (static, virtual function).


CFile Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFile::CFile

CFile();

CFile( int hFile );

CFile( const char* pszFileName, UINT nOpenFlags )
throw( CFileException );

hFile    The handle of a file that is already open.

pszFileName    A string that is the path to the desired file. The path may be relative or absolute.

nOpenFlags    Sharing and access mode. Specifies the action to take when opening the file. You can combine options listed below by using the bitwise-OR (|) operator. One access permission and one share option are required; the modeCreate and modeNoInherit modes are optional. The values and meanings are given below:

•	CFile::modeCreate    Directs the constructor to create a new file. If the file exists already, it is truncated to 0 length.

•	CFile::modeRead    Opens the file for reading only.

•	CFile::modeReadWrite    Opens the file for reading and writing.

•	CFile::modeWrite    Opens the file for writing only.

•	CFile::modeNoInherit    Prevents the file from being inherited by child processes.

•	CFile::shareDenyNone    Opens the file without denying other processes read or write access to the file. Create fails if the file has been opened in compatibility mode by any other process.

•	CFile::shareDenyRead    Opens the file and denies other processes read access to the file. Create fails if the file has been opened in compatibility mode or for read access by any other process.

•	CFile::shareDenyWrite    Opens the file and denies other processes write access to the file. Create fails if the file has been opened in compatibility mode or for write access by any other process.

•	CFile::shareExclusive    Opens the file with exclusive mode, denying other processes both read and write access to the file. Construction fails if the file has been opened in any other mode for read or write access, even by the current process.

•	CFile::shareCompat    Opens the file with compatibility mode, allowing any process on a given machine to open the file any number of times. Construction fails if the file has been opened with any of the other sharing modes.

•	CFile::typeText    Sets text mode with special processing for carriage return−linefeed pairs (used in derived classes only).

•	CFile::typeBinary    Sets binary mode (used in derived classes only).

Remarks

The default constructor does not open a file but rather sets m_hFile to CFile::hFileNull. Because this constructor does not throw an exception, it does not make sense to use TRY/CATCH logic. Use the Open member function, then test directly for exception conditions. For a discussion of exception-processing strategy, see Chapter 16 in the Class Library User's Guide.

The constructor with one argument creates a CFile object that corresponds to an existing operating-system file identified by hFile. No check is made on the access mode or file type. When the CFile object is destroyed the operating-system file will not be closed. You must close the file yourself.

The constructor with two arguments creates a CFile object and opens the corresponding operating-system file with the given path. This constructor combines the functions of the first constructor and the Open member function. It throws an exception if there is an error while opening the file. Generally, this means that the error is unrecoverable and that the user should be alerted.

 Example

//example for CFile::CFile

char* pFileName = "test.dat";
TRY
{
CFile f( pFileName, CFile::modeCreate | CFile::modeWrite );
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "\n";
#endif
}
END_CATCH


  CFile::Close

virtual void Close()
throw( CFileException );

Remarks

Closes the file associated with this object and makes the file unavailable for reading or writing. If you have not closed the file before destroying the object, the destructor closes it for you.

If you used new to allocate the CFile object on the heap, then you must delete it after closing the file. Close sets m_hFile to CFile::hFileNull.

See Also

»CFile::Open«


  CFile::Duplicate

virtual CFile* Duplicate() const
throw( CFileException );

Remarks

Constructs a duplicate CFile object for a given file. This is equivalent to the C run-time function _dup.


  CFile::Flush

virtual void Flush()
throw( CFileException );

Remarks

Forces any data remaining in the file buffer to be written to the file.

The use of Flush does not guarantee flushing of CArchive buffers. If you are using an archive, call CArchive::Flush first.


  CFile::GetLength

virtual DWORD GetLength() const
throw( CFileException );

Remarks

Obtains the current logical length of the file in bytes, not the amount physically allocated.

Return Value

The length of the file.

See Also

»CFile::SetLength«


  CFile::GetPosition

virtual DWORD GetPosition() const
throw( CFileException );

Remarks

Obtains the current value of the file pointer, which can be used in subsequent calls to Seek.

Return Value

The file pointer as a 32-bit doubleword.

 Example

//example for CFile::GetPosition

extern CFile cfile;
DWORD dwPosition = cfile.GetPosition();


  CFile::GetStatus

BOOL GetStatus( CFileStatus& rStatus ) const;

static BOOL PASCAL GetStatus( const char* pszFileName, CFileStatus& rStatus );

rStatus    A reference to a user-supplied CFileStatus structure that will receive the status information. The CFileStatus structure has the following fields with the meanings as given:

•	CTime m_ctime    The date and time the file was created

•	CTime m_mtime    The date and time the file was last modified

•	CTime m_atime    The date and time the file was last accessed for reading

•	LONG m_size    The logical size of the file in bytes, as reported by the MS-DOS command DIR

•	BYTE m_attribute    The MS-DOS attribute byte of the file

•	char m_szFullName[_MAX_PATH]    The absolute filename in the Windows character set. When running under MS-DOS only, m_szFullName in an OEM character string. (_MAX_PATH is defined in STDLIB.H.)

pszFileName    A string in the Windows character set that is the path to the desired file. When running under MS-DOS only, pszFileName is an OEM character string. The path may be relative or absolute, but may not contain a network name.

Remarks

The virtual version of GetStatus retrieves the status of the open file associated with this CFile object. It does not insert a value into the m_szFullName structure member.

The static version gets the status of the named file and copies the filename to m_szFullName. This function obtains the file status from the directory entry without actually opening the file. It is useful for testing the existence and access rights of a file.

The m_attribute is the MS-DOS file attribute. The Microsoft Foundation classes provide an enum type attribute so that you can specify attributes symbolically:

enum Attribute {
   normal =    0x00,
   readOnly =  0x01,
   hidden =    0x02,
   system =    0x04,
   volume =    0x08,
   directory = 0x10,
   archive =   0x20
   };

Return Value

Nonzero if no error, in which case rStatus is valid; otherwise 0. A value of 0 indicates that the file does not exist.

See Also

»CFile::SetStatus«, »CTime«

 Example

//example for CFile::GetStatus

CFileStatus status;
extern CFile cfile;
if( cfile.GetStatus( status ) )    // virtual member function
{
#ifdef _DEBUG
afxDump << "File size = " << status.m_size << "\n";
#endif
}
char* pFileName = "test.dat";
if( CFile::GetStatus( pFileName, status ) )   // static function
{
#ifdef _DEBUG
afxDump << "Full file name = " << status.m_szFullName << "\n";
#endif
}


  CFile::LockRange

virtual void LockRange( DWORD dwPos, DWORD dwCount )
throw( CFileException );

dwPos    The byte offset of the start of the byte range to lock.

dwCount    The number of bytes in the range to lock.

Remarks

Locks a range of bytes in an open file, throwing an exception if the file is already locked. Locking bytes in a file prevents access to those bytes by other processes. You can lock more than one region of a file, but no overlapping regions are allowed.

When you unlock the region, using the UnlockRange member function, the byte range must correspond exactly to the region that was previously locked. The LockRange function does not merge adjacent regions; if two locked regions are adjacent, you must unlock each region separately.

Under MS-DOS, you must enable file sharing by running SHARE.EXE before running an application using this member function.

Note  This function is not available for the CMemFile-derived class.

See Also

»CFile::UnlockRange«

 Example

//example for CFile::LockRange

extern DWORD dwPos;
extern DWORD dwCount;
extern CFile cfile;
cfile.LockRange( dwPos, dwCount );


  CFile::Open

virtual BOOL Open( const char* pszFileName, UINT nOpenFlags,
CFileException* pError = NULL );

pszFileName    A string that is the path to the desired file. The path may be relative or absolute but may not contain a network name.

nOpenFlags    A UINT that defines the file's sharing and access mode. It specifies the action to take when opening the file. You can combine options by using the bitwise-OR ( | ) operator. One access permission and one share option are required; the modeCreate and modeNoInherit modes are optional. See the »CFile« constructor for a list of mode options.

pError    A pointer to an existing file-exception object that indicates the completion status of the open operation.

Remarks

Open is designed for use with the default CFile constructor. The two functions form a "safe" method for opening a file where a failure is a normal, expected condition. The constructor is guaranteed to succeed, and Open returns a pointer to an exception object, bypassing the THROW/TRY/CATCH mechanism.

Return Value

Nonzero if the open was successful; otherwise 0. The pError parameter is meaningful only if 0 is returned.

See Also

»CFile::CFile«, »CFile::Close«

 Example

//example for CFile::Open

CFile f;
CFileException e;
char* pFileName = "test.dat";
if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, &e ) )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e.m_cause << "\n";
#endif
}


  CFile::Read

virtual UINT Read( void FAR* lpBuf, UINT nCount )
throw( CFileException );

lpBuf    Pointer to the user-supplied buffer that is to receive the data read from the file.

nCount    The maximum number of bytes to be read from the file. For text-mode files, carriage return−linefeed pairs are counted as single characters.

Remarks

Reads data into a buffer from the file associated with the CFile object.

Return Value

The number of bytes transferred to the buffer. Note that for all CFile classes, the return value may be less than nCount if the end of file was reached.

See Also

»CFile::Write«

 Example

//example for CFile::Read

extern CFile cfile;
char pbuf[100];
UINT nBytesRead = cfile.Read( pbuf, 100 );


  CFile::ReadHuge

virtual UINT ReadHuge( void FAR* lpBuf, DWORD dwCount )
throw( CFileException );

lpBuf    Pointer to the user-supplied buffer that is to receive the data read from the file.

dwCount    The maximum number of bytes to be read from the file. For text-mode files, carriage return−linefeed pairs are counted as single characters.

Remarks

Reads data into a buffer from the file associated with the CFile object.

This function differs from Read in that more than 64K−1 bytes of data can be read by ReadHuge. This function can be used by any object derived from CFile.

Return Value

The number of bytes transferred to the buffer. Note that for all CFile objects, the return value can be less than dwCount if the end of file was reached.

See Also

»CFile::Write«, »CFile::WriteHuge«, »CFile::Read«


  CFile::WriteHuge

virtual void WriteHuge( const void FAR* lpBuf, DWORD dwCount )
throw( CFileException );

lpBuf    A pointer to the user-supplied buffer that contains the data to be written to the file.

dwCount    The number of bytes to be transferred from the buffer. For text-mode files, carriage return−linefeed pairs are counted as single characters.

Remarks

Writes data from a buffer to the file associated with the CFile object. WriteHuge throws an exception in response to several conditions, including the disk-full condition.

This function differs from Write in that more than 64K−1 bytes of data can be written by WriteHuge. This function can be used by any object derived from CFile.

See Also

»CFile::Read«, »CFile::ReadHuge«, »CFile::Write«, »CStdioFile::WriteString«


  CFile::Remove

static void PASCAL Remove( const char* pszFileName )
throw( CFileException );

pszFileName    A string that is the path to the desired file. The path may be relative or absolute but may not contain a network name.

Remarks

This static function deletes the file specified by the path. It will not remove a directory.

The Remove member function throws an exception if the connected file is open or if the file cannot be removed. This is equivalent to the MS-DOS DEL command.

 Example

//example for CFile::Remove

char* pFileName = "test.dat";
TRY
{
CFile::Remove( pFileName );
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File " << pFileName << " cannot be removed\n";
#endif
}
END_CATCH


  CFile::Rename

static void PASCAL Rename( const char* pszOldName,
const char* pszNewName )
throw( CFileException );

pszOldName    The old path.

pszNewName    The new path.

Remarks

This static function renames the specified file. Directories cannot be renamed. This is equivalent to the MS-DOS REN command.

 Example

//example for CFile::Rename

extern char* pOldName;
extern char* pNewName;
TRY
{
CFile::Rename( pOldName, pNewName );
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File " << pOldName << " not found, cause = "
<< e->m_cause << "\n";
#endif
}
END_CATCH


  CFile::Seek

virtual LONG Seek( LONG lOff, UINT nFrom )
throw( CFileException );

lOff    Number of bytes to move the pointer.

nFrom    Pointer movement mode.  Must be one of the following values, with the meaning as given:

•	CFile::begin    Move the file pointer lOff  bytes forward from the beginning of the file.

•	CFile::current    Move the file pointer lOff  bytes from the current position in the file.

•	CFile::end    Move the file pointer backward lOff  bytes from the end of the file.

Remarks

Repositions the pointer in a previously opened file. The Seek function permits random access to a file's contents by moving the pointer a specified amount, absolutely or relatively. No data is actually read during the seek.

When a file is opened, the file pointer is positioned at offset 0, the beginning of the file.

Return Value

If the requested position is legal, Seek returns the new byte offset from the beginning of the file. Otherwise, the return value is undefined and a CFileException object is thrown.

 Example

//example for CFile::Seek

extern CFile cfile;
LONG lOffset = 1000, lActual;
lActual = cfile.Seek( lOffset, CFile::begin );


  CFile::SeekToBegin

void SeekToBegin()
throw( CFileException );

Remarks

Sets the value of the file pointer to the beginning of the file. SeekToBegin() is equivalent to Seek( 0L, CFile::begin ).

 Example

//example for CFile::SeekToBegin

extern CFile cfile;
cfile.SeekToBegin();


  CFile::SeekToEnd

DWORD SeekToEnd()
throw( CFileException );

Remarks

Sets the value of the file pointer to the logical end of the file. SeekToEnd() is equivalent to CFile::Seek( 0L, CFile::end ).

Return Value

The length of the file in bytes.

See Also

»CFile::GetLength«, »CFile::Seek«, »CFile::SeekToBegin«

 Example

//example for CFile::SeekToEnd

extern CFile cfile;
DWORD dwActual = cfile.SeekToEnd();


  CFile::SetLength

virtual void SetLength( const DWORD dwNewLen )
throw( CFileException );

dwNewLen    Desired length of the file in bytes. This value may be larger or smaller than the current length of the file. The file will be extended or truncated as appropriate.

Remarks

Changes the length of the file.

Note  With CMemFile, this function could throw a CMemoryException object.

 Example

//example for CFile::SetLength

extern CFile cfile;
DWORD dwNewLength = 10000;
cfile.SetLength( dwNewLength );


  CFile::SetStatus

static void SetStatus( const char* pszFileName, const CFileStatus& status )
throw( CFileException );

pszFileName    A string that is the path to the desired file. The path may be relative or absolute but may not contain a network name.

status    The buffer containing the new status information. Call the GetStatus member function to prefill the CFileStatus structure with current values, then make changes as required. If a value is 0, then the corresponding status item is not updated. See the »GetStatus« member function for a description of the CFileStatus structure.

Remarks

Sets the status of the file associated with this file location.

Under MS-DOS, all times in the CFileStatus structure, as described in the GetStatus member function, contain the same value.

To set the time, modify the m_mtime field of status.

The SetStatus function will throw an exception under MS-DOS if the file's read-only attribute is set.

See Also

»CFile::GetStatus«

 Example

//example for CFile::SetStatus

char* pFileName = "test.dat";
extern BYTE newAttribute;
CFileStatus status;
CFile::GetStatus( pFileName, status );
status.m_attribute = newAttribute;
CFile::SetStatus( pFileName, status );


  CFile::UnlockRange

virtual void UnlockRange( DWORD dwPos, DWORD dwCount )
throw( CFileException );

dwPos    The byte offset of the start of the byte range to unlock.

dwCount    The number of bytes in the range to unlock.

Remarks

Unlocks a range of bytes in an open file. See the description of the »LockRange« member function for details.

Under MS-DOS, you must load SHARE.EXE; otherwise the function throws a CFileException object.

Note  This function is not available for the CMemFile-derived class.

See Also

»CFile::LockRange«

 Example

//example for CFile::UnlockRange

extern DWORD dwPos;
extern DWORD dwCount;
extern CFile cfile;
cfile.UnlockRange( dwPos, dwCount );


  CFile::Write

virtual void Write( const void FAR* lpBuf, UINT nCount )
throw( CFileException );

lpBuf    A pointer to the user-supplied buffer that contains the data to be written to the file.

nCount    The number of bytes to be transferred from the buffer. For text-mode files, carriage return−linefeed pairs are counted as single characters.

Remarks

Writes data from a buffer to the file associated with the CFile object.

Write throws an exception in response to several conditions including the disk-full condition.

See Also

»CFile::Read«, »CStdioFile::WriteString«

 Example

//example for CFile::Write

extern CFile cfile;
char pbuf[100];
cfile.Write( pbuf, 100 );


CFile Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFile::m_hFile

Remarks

Contains the operating-system file handle for an open file. m_hFile is a public variable of type UINT. It contains CFile::hFileNull (an operating-system-independent empty file indicator) if the handle has not been assigned.

Use of m_hFile is not recommended because the member's meaning depends on the derived class. m_hFile is made a public member to conveniently support nonpolymorphic use of the class.


CFileDialog
  class CFileDialog : public CDialog

The CFileDialog class encapsulates the Windows common file dialog box. Common file dialog boxes provide an easy way to implement File Open and File Save As dialog boxes (as well as other file-selection dialog boxes) in a manner consistent with Windows standards.

You can use CFileDialog "as is" with the constructor provided, or you can derive your own dialog class from CFileDialog and write a constructor to suit your needs. In either case, these dialog boxes will behave like standard Microsoft Foundation class dialog boxes because they are derived from the CDialog class.

To use a CFileDialog object, first create the object using the CFileDialog constructor. Once the dialog has been constructed, you can set or modify any values in the m_ofn structure to initialize the values or states of the dialog box's controls. The m_ofn structure is of type OPENFILENAME. For more information on this structure, see the Windows Software Development Kit (SDK) documentation.

After initializing the dialog box's controls, call the DoModal member function to display the dialog box and allow the user to enter the path and file. DoModal returns whether the user selected the OK (IDOK) or the Cancel (IDCANCEL) button.

If DoModal returns IDOK, you can use one of CFileDialog's public member functions to retrieve the information input by the user.

CFileDialog includes several protected members that enable you to do custom handling of share violations, filename validation, and list-box change notification. These protected members are callback functions that most applications do not need to use, since default handling is done automatically. Message-map entries for these functions are not necessary because they are standard virtual functions.

You can use the Windows CommDlgExtendedError function to determine if an error occurred during initialization of the dialog box and to learn more about the error.

The destruction of CFileDialog objects is handled automatically. It is not necessary to call CDialog::EndDialog.

To allow the user to select multiple files, set the OFN.ALLOW_MULTISELECT flag before calling DoModal. You need to supply your own filename buffer to accommodate the returned list of multiple file names. Do this by replacing  m_ofn.lpstrFile with a pointer to a buffer you have allocated, after constructing the CFileDialog, but before calling DoModal.

CFileDialog relies on the COMMDLG.DLL file that ships with Windows versions 3.1 and later. For details about redistributing COMMDLG.DLL to Windows version 3.0 users, see the Getting Started manual in the Windows version 3.1 SDK.

If you derive a new class from CFileDialog, you can use a message map to handle any messages. To extend the default message handling, derive a class from CWnd, add a message map to the new class, and provide member functions for the new messages. You do not need to provide a hook function to customize the dialog.

To customize the dialog box, derive a class from CFileDialog, provide a custom dialog template, and add a message map to process the notification messages from the extended controls. Any unprocessed messages should be passed to the base class.

Customizing the hook function is not required.

#include <afxdlgs.h>


CFileDialog Class Members
  Class Members

Data Members— Public Members

»m_ofn«	The Windows OPENFILENAME structure. Provides access to basic file dialog box parameters.
Construction/Destruction — Public Members

»CFileDialog«	Constructs a CFileDialog object.
Overridables — Public Members

»DoModal«	Displays the dialog box and allows the user to make a selection.
»GetPathName«	Returns the full path of the selected file.
»GetFileName«	Returns the filename of the selected file.
»GetFileExt«	Returns the file extension of the selected file.
»GetFileTitle«	Returns the title of the selected file.
»GetReadOnlyPref«	Returns the read-only status of the selected file.
Operations — Protected Members

»OnShareViolation«	Called when a share violation occurs.
»OnFileNameOK«	Called to validate the filename entered in the dialog box.
»OnLBSelChangedNotify«	Called when the list box selection changes.


CFileDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFileDialog::CFileDialog

CFileDialog( BOOL bOpenFileDialog, LPCSTR lpszDefExt = NULL, LPCSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );

bOpenFileDialog    Set to TRUE to construct a File Open dialog box or FALSE to construct a File Save As dialog box.

lpszDefExt     The default filename extension. If the user does not include an extension in the Filename edit box, the extension specified by lpszDefExt is automatically appended to the filename. If this parameter is NULL, no file extension is appended.

lpszFileName    The initial filename that appears in the filename edit box. If NULL, no filename initially appears.

dwFlags    A combination of one or more flags that allow you to customize the dialog box. For a description of these flags, see the OPENFILENAME structure description in the Windows SDK documentation. If you modify the m_ofn.Flags structure member, use a bitwise -OR operator in your changes to keep the default behavior intact.

lpszFilter    A series of string pairs that specify filters you can apply to the file. If you specify file filters, only selected files will appear in the Files list box. See the Remarks section below for more information on how to work with file filters.

pParentWnd    A pointer to the file dialog-box object's parent or owner window.

Remarks

Call this function to construct a standard Windows file dialog box object. Either a File Open or File Save As dialog box is constructed, depending on the value of bOpenFileDialog.

The lpszFilter parameter is used to determine the type of filename a file must have to be displayed in the file list box. The first string in the string pair describes the filter; the second string indicates the file extension to use. Multiple extensions may be specified using ';' as the delimiter. The string ends with two '|' characters, followed by a NULL character. You can also use a CString object for this parameter.

For example, Microsoft Excel permits users to open files with extensions .XLC (chart) or .XLS (worksheet), among others. The filter for Excel could be written as:

static char BASED_CODE szFilter[] = "Chart Files (*.xlc) | *.xlc | Worksheet Files (*.xls) | *.xls | Data Files (*.xlc;*.xls) | *.xlc; *.xls | All Files (*.*) | *.* ||"

See Also

»CFileDialog::DoModal«, »::GetOpenFileName«, »::GetSaveFileName«


  CFileDialog::DoModal

virtual int DoModal();

Remarks

Call this function to display the Windows common file dialog box and allow the user to browse files and directories and enter a filename.

If you want to initialize the various file dialog-box options by setting members of the m_ofn structure, you should do this before calling DoModal, but after the dialog object is constructed.

When the user clicks the dialog box's OK or CANCEL buttons, or selects the CLOSE option from the dialog box's control menu, control is returned to your application. You can then call other member functions to retrieve the settings or information the user inputs into the dialog box.

DoModal is a virtual function derived from class CModalDialog.

Return Value

IDOK or IDCANCEL if the function is successful; otherwise 0. IDOK and IDCANCEL are constants that indicate whether the user selected the OK or Cancel button.

If IDCANCEL is returned, you can call the Windows CommDlgExtendedError function to determine if an error occurred.

See Also

»CDialog::DoModal«, »CFileDialog::CFileDialog«


  CFileDialog::GetFileExt

CString GetFileExt() const;

Remarks

Call this function to retrieve the extension of the filename entered into the dialog box. For example, if the name of the file entered is DATA.TXT, GetFileExt returns "TXT".

If m_ofn.Flags has the OFN_ALLOWMULTISELECT flag set, then this member function only applies to the first name.

Return Value

The extension of the filename.

See Also

»CFileDialog::GetPathName«, »CFileDialog::GetFileName«, »CFileDialog::GetFileTitle«


  CFileDialog::GetFileName

CString GetFileName() const;

Remarks

Call this function to retrieve the name of the file entered in the dialog box. The name of the file includes only its prefix, without the path or the extension. For example, GetFileName will return "TEXT" for the file C:\FILES\TEXT.DAT.

If m_ofn.Flags has the OFN_ALLOWMULTISELECT flag set, then this member function only applies to the first name.

Return Value

The name of the file.

See Also

»CFileDialog::GetPathName«, »CFileDialog::GetFileExt«, »CFileDialog::GetFileTitle«


  CFileDialog::GetFileTitle

CString GetFileTitle() const;

Remarks

Call this function to retrieve the title of the filename entered in the dialog box. The title of the filename includes both the name and the extension. For example, GetFileTitle will return "TEXT.DAT" for the file C:\FILES\TEXT.DAT.

If m_ofn.Flags has the OFN_ALLOWMULTISELECT flag set, then this member function only applies to the first name.

Return Value

The title of the file.

See Also

»CFileDialog::GetPathName«, »CFileDialog::GetFileName«, »CFileDialog::GetFileExt«, »::GetFileTitle«


  CFileDialog::GetPathName

CString GetPathName() const;

Remarks

Call this function to retrieve the full path of the file entered in the dialog box. The path of the filename includes the file's title plus the entire directory path. For example, GetPathName will return "C:\FILES\TEXT.DAT" for the file C:\FILES\TEXT.DAT.

If m_ofn.Flags has the OFN_ALLOWMULTISELECT flag set, then this member function only applies to the first name.

Return Value

The full path of the file.

See Also

»CFileDialog::GetFileName«, »CFileDialog::GetFileExt«, »CFileDialog::GetFileTitle«


  CFileDialog::GetReadOnlyPref

BOOL GetReadOnlyPref() const;

Remarks

Call this function to determine whether the Read Only check box has been selected in the Windows standard File Open and File Save As dialog boxes. The Read Only check box can be hidden by setting the OFN_HIDEREADONLY style in the CFileDialog constructor.

Return Value

Non-zero if the Read Only check box in the dialog box is selected; otherwise 0.

See Also

»CFileDialog::CFileDialog«, »CFileDialog::GetPathName«, »CFileDialog::GetFileExt«


  CFileDialog::OnFileNameOK

Protected

virtual BOOL OnFileNameOK(); ♦

Remarks

Override this function only if you want to provide custom validation of filenames that are entered into a common file dialog box. This function allows you to reject a filename for any application-specific reason. Normally, you do not need to use this function because the framework provides default validation of filenames and displays a message box if an invalid filename is entered.

If a nonzero value is returned, the dialog box will remain displayed for the user to enter another filename.

Return Value

Nonzero if the filename is a valid MS-DOS filename; otherwise 0.

See Also

»OPENFILENAME«


  CFileDialog::OnLBSelChangedNotify

Protected

virtual void OnLBSelChangedNotify( UINT nIDBox, UINT iCurSel, UINT nCode); ♦

nIDBox    The ID of the list box or combo box in which the selection occurred.

iCurSel    The index of the current selection.

nCode    The control notification code.

This parameter must have one of the following values, with the meaning as given:

•	CD_LBSELCHANGE    Specifies iCurSel is the selected item in a single-selection list box.

•	CD_LBSELSUB    Specifies that iCurSel is no longer selected in a multiselection list box.

•	CD_LBSELADD    Specifies that iCurSel was selected in a multiselection list box.

•	CD_LBSELNOITEMS    Specifies that no selection exists in a multiselection list box.

For more information, see "Filename Dialog Boxes" in the Windows version 3.1 SDK Help.

Remarks

This function is called whenever the current selection in a list box is about to change. Override this function to provide custom handling of selection changes in the list box. For example, you can use this function to display the access rights or date-last-modified of each file the user selects.


  CFileDialog::OnShareViolation

Protected

virtual UINT OnShareViolation( LPCSTR lpszPathName ); ♦

lpszPathName    The path of the file on which the share violation occurred.

Remarks

Override this function to provide custom handling of share violations. Normally, you do not need to use this function because the framework provides default checking of share violations and displays a message box if a share violation occurs.

If you want to disable share violation checking, use the bitwise -OR operator to combine the flag OFN_SHAREAWARE with m_ofn.Flags.

Return Value

One of the following values, with the meaning as given:

•	OFN_SHAREFALLTHROUGH    The filename is returned from the dialog box.

•	OFN_SHARENOWARN    No further action needs to be taken.

•	OFN_SHAREWARN    The user receives the standard warning message for this error.

See Also

»CFileDialog::OnFileNameOK«


CFileDialog Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFileDialog::m_ofn

Remarks

m_ofn is a structure of type OPENFILENAME. Use this structure to initialize the appearance of a File Open or File Save As dialog box after it is constructed but before it is displayed with the DoModal member function. For example, you can set the lpszTitle member of m_ofn to the caption you want the dialog box to have.

For more information on this structure, including a listing of its members, see OPENFILENAME in the Windows SDK documentation.


CFileException
  class CFileException : public CException

A CFileException object represents a file-related exception condition. The CFileException class includes public data members that hold the portable cause code and the operating-system-specific error number. The class also provides static member functions for throwing file exceptions and for returning cause codes for both operating-system errors and C run-time errors.

CFileException objects are constructed and thrown in CFile member functions and in member functions of derived classes. You can access these objects within the scope of a CATCH expression. For portability, use only the cause code to get the reason for an exception. For more information about exceptions, see Chapter 16, "Exceptions," in the Class Library User's Guide.

#include <afx.h>

See Also

»CFile«

»Exception Processing«


CFileException Class Members
  Class Members

Data Members — Public Members

»m_cause«	Contains portable code corresponding to the exception cause.
»m_lOsError«	Contains the related operating-system error number.
Construction/Destruction — Public Members

»CFileException«	Constructs a CFileException object.
Code Conversion — Public Members

»OsErrorToException«	Returns a cause code corresponding to an MS-DOS error code.
»ErrnoToException«	Returns cause code corresponding to a run-time error number.
Helper Functions — Public Members

»ThrowOsError«	Throws a file exception based on an operating-system error number.
»ThrowErrno«	Throws a file exception based on a run-time error number.


CFileException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFileException::CFileException

CFileException( int cause = CFileException::none, LONG lOsError = −1 );

cause    An enumerated type variable that indicates the reason for the exception. See »CFileException::m_cause« for a list of the possible values.

lOsError    An operating-system-specific reason for the exception, if available. The lOsError parameter provides more information than cause does.

Remarks

Constructs a CFileException object that stores the cause code and the operating-system code in the object.

Do not use this constructor directly, but rather call the global function »AfxThrowFileException«.

Note  The variable lOsError applies only to CFile and CStdioFile objects. The CMemFile class does not handle this error code. More information specifically about the operating system is available through the run-time function _dosexterr (MS-DOS only).

See Also

»AfxThrowFileException«


  CFileException::ErrnoToException

static int PASCAL ErrnoToException( int nErrno );

nErrno    An integer error code as defined in the run-time include file ERRNO.H.

Remarks

Converts a given run-time library error value to a CFileException enumerated error value. See »CFileException::m_cause« for a list of the possible enumerated values.

Return Value

Enumerated value that corresponds to a given run-time library error value.

See Also

»CFileException::OsErrorToException«

 Example

//example for CFileException::ErrnoToException

#include <errno.h>
ASSERT( CFileException::ErrnoToException( EACCES ) ==
                  CFileException::accessDenied );


  CFileException::OsErrorToException

static int PASCAL OsErrorToException( LONG lOsError );

lOsError    An operating-system-specific error code.

Remarks

Returns an enumerator that corresponds to a given lOsError value. If the error code is unknown, then the function returns CFileException::generic.

Return Value

Enumerated value that corresponds to a given operating-system error value.

See Also

»CFileException::ErrnoToException«

 Example

//example for CFileException::OsErrorToException

ASSERT( CFileException::OsErrorToException( 5 ) ==
                  CFileException::accessDenied );


  CFileException::ThrowErrno

static void PASCAL ThrowErrno( int nErrno );

nErrno    An integer error code as defined in the run-time include file ERRNO.H.

Remarks

Constructs a CFileException object corresponding to a given nErrno value, then throws the exception.

See Also

»CFileException::ThrowOsError«

 Example

//example for CFileException::ThrowErrno

#include <errno.h>
CFileException::ThrowErrno( EACCES );  // "access denied"


  CFileException::ThrowOsError

static void PASCAL ThrowOsError( LONG lOsError );

lOsError    An operating-system-specific error code.

Remarks

Throws a CFileException corresponding to a given lOsError value. If the error code is unknown, then the function throws an exception coded as CFileException::generic.

See Also

»CFileException::ThrowErrno«

 Example

//example for CFileException::ThrowOsError

FileException::ThrowOsError( 5 );  // "access denied"


CFileException Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFileException::m_cause

Remarks

Contains values defined by a CFileException enumerated type. This data member is a public variable of type int. The enumerators and their meanings are as follows:

•	CFileException::none    No error occurred.

•	CFileException::generic    An unspecified error occurred.

•	CFileException::fileNotFound    The file could not be located.

•	CFileException::badPath    All or part of the path is invalid.

•	CFileException::tooManyOpenFiles    The permitted number of open files was exceeded.

•	CFileException::accessDenied    The file could not be accessed.

•	CFileException::invalidFile    There was an attempt to use an invalid file handle.

•	CFileException::removeCurrentDir    The current working directory cannot be removed.

•	CFileException::directoryFull    There are no more directory entries.

•	CFileException::badSeek    There was an error trying to set the file pointer.

•	CFileException::hardIO    There was a hardware error.

•	CFileException::sharingViolation    SHARE.EXE was not loaded, or a shared region was locked.

•	CFileException::lockViolation    There was an attempt to lock a region that was already locked.

•	CFileException::diskFull    The disk is full.

•	CFileException::endOfFile    The end of file was reached.

Note  These CFileException cause enumerators are distinct from the CArchiveException cause enumerators.

 Example

//example for CFileException::m_cause

extern char* pFileName;
TRY
{
   CFile f( pFileName, CFile::modeCreate | CFile::modeWrite );
}
CATCH( CFileException, e)
{
    if( e->m_cause == CFileException::fileNotFound )
        printf( "ERROR: File not found\n");
}


  CFileException::m_lOsError

Remarks

Contains the operating-system error code for this exception. See your operating-system technical manual for a listing of error codes. This data member is a public variable of type LONG.


CFindReplaceDialog
  class CFindReplaceDialog : public CDialog

The CFindReplaceDialog class allows you to implement standard string Find/Replace dialog boxes in your application. Unlike the other Windows common dialog boxes, CFindReplaceDialog objects are modeless, allowing users to interact with other windows while they are on screen. There are two kinds of CFindReplaceDialog objects: Find dialog boxes and Find/Replace dialog boxes. Although the dialog boxes allow the user to input search and search/replace strings, they do not perform any of the searching or replacing functions. You must add these to the application.

To construct a CFindReplaceDialog object, use the provided constructor (which has no arguments). Since this is a modeless dialog box, allocate the object on the heap using the new operator, rather than on the stack.

Once a CFindReplaceDialog object has been constructed, you must call the Create member function to create and display the dialog box.

Use the m_fr structure to initialize the dialog box before calling Create. The m_fr structure is of type FINDREPLACE. For more information on this structure, see the Windows Software Development Kit (SDK) documentation.

In order for the parent window to be notified of find/replace requests, you must use the Windows RegisterMessage function and use the ON_REGISTERED_MESSAGE message-map macro in your frame window that handles this registered message. You can call any of the member functions listed in the following "Operations − Public Members" section from the frame window's callback function.

You can determine if the user has decided to terminate the dialog box with the IsTerminating member function.

CFindReplaceDialog relies on the COMMDLG.DLL file that ships with Windows versions 3.1 and later. For details about redistributing COMMDLG.DLL to Windows version 3.0 users, see the Getting Started manual in the Windows version 3.1 SDK.

To customize the dialog box, derive a class from CFindReplaceDialog, provide a custom dialog template, and add a message map to process the notifiction messages from the extended controls. Any unprocessed messages should be passed to the base class.

Customizing the hook function is not required.

#include <afxdlgs.h>


CFindReplaceDialog Class Members
  Class Members

Data Members — Public Members

»m_fr«	A structure used to customize a CFindReplaceDialog object.
Construction/Destruction — Public Members

»CFindReplaceDialog«	Call this function to construct a CFindReplaceDialog object.
»Create«	Creates and displays a CFindReplaceDialog dialog box.
Operations — Public Members

»FindNext«	Call this function to determine whether the user wants to find the next occurrence of the find string.
»GetNotifier«	Call this function to retrieve the FINDREPLACE structure in your registered message handler.
»GetFindString«	Call this function to retrieve the current find string.
»GetReplaceString«	Call this function to retrieve the current replace string.
»IsTerminating«	Call this function to determine whether the dialog box is terminating.
»MatchCase«	Call this function to determine if the user wants to match the case of the find string exactly.
»MatchWholeWord«	Call this function to determine whether the user wants to match entire words only.
»ReplaceAll«	Call this function to determine whether the user wants all occurrences of the string to be replaced.
»ReplaceCurrent«	Call this function to determine whether the user wants the current word to be replaced.
»SearchDown«	Call this function to determine whether the user wants the search to proceed in a downward direction.


CFindReplaceDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFindReplaceDialog::CFindReplaceDialog

CFindReplaceDialog();

Remarks

Constructs a CFindReplaceDialog object. CFindReplaceDialog objects are constructed on the heap with the new operator. See the »class description« for more information on the construction of CFindReplaceDialog objects. Use the Create member function to display the dialog box.

See Also

»CFindReplaceDialog::Create«


  CFindReplaceDialog::Create

BOOL Create( BOOL bFindDialogOnly, LPCSTR lpszFindWhat,
LPCSTR lpszReplaceWith = NULL, DWORD dwFlags = FR_DOWN,
CWnd* pParentWnd = NULL);

bFindDialogOnly    Set this parameter to TRUE to display the standard Windows Find dialog box. Set it to FALSE to display the Windows Find/Replace dialog box.

lpszFindWhat    Specifies the string to search for.

lpszReplaceWith    Specifies the default string to replace found strings with.

dwFlags    One or more flags you can use to customize the settings of the dialog box, combined using the bitwise-OR operator. The default value is FR_DOWN, which specifies that the search is to proceed in a downward direction. See the FINDREPLACE structure in the Windows SDK for more information on these flags.

pParentWnd    A pointer to the dialog box's parent or owner window. This is the window that will receive the special message indicating that a find/replace action is requested. If NULL, the application's main window is used.

Remarks

Creates and displays either a Find or Find/Replace dialog box object, depending on the value of bFindDialogOnly.

In order for the parent window to be notified of find/replace requests, you must use the Windows RegisterMessage function whose return value is a message number unique to the application's instance. Your frame window should have a message map entry that declares the callback function (OnFindReplace in the example that follows) that handles this registered message. The following code fragment is an example of how to do this for a frame window class named CMyFrameWnd:

    class CMyFrameWnd : public CFrameWnd
    {
    protected:
        afx_msg LONG LRESULT OnFindReplace(WPARAM wParam, LPARAM lParam);

        DECLARE_MESSAGE_MAP()
    };
    static UINT NEAR WM_FINREPLACE = ::RegisterMessage(FINDMSGSTRING);

    BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
       //Normal message map entries here.
       ON_REGISTERED_MESSAGE( WM_FINDREPLACE, OnFindReplace )
    END_MESSAGE_MAP

Within your OnFindReplace function, you interpret the intentions of the user and create the code for the find/replace operations.

See Also

»CFindReplaceDialog::CFindReplaceDialog«


  CFindReplaceDialog::FindNext

BOOL FindNext() const;

Remarks

Call this function from your callback function to determine whether the user wants to find the next occurrence of the search string.

Return Value

Nonzero if the user wants to find the next occurrence of the search string;
otherwise 0.

See Also

»CFindReplaceDialog::GetFindString«, »CFindReplaceDialog::SearchDown«


  CFindReplaceDialog::GetFindString

CString GetFindString() const;

Remarks

Call this function from your callback function to retrieve the default string to find.

Return Value

The default string to find.

See Also

»CFindReplaceDialog::FindNext«, »CFindReplaceDialog::GetReplaceString«


  CFindReplaceDialog::GetNotifier

static CFindReplaceDialog* PASCAL GetNotifier( LPARAM lParam );

lParam    The lparam value passed to the frame window's OnFindReplace member function.

Remarks

Call this function to retrieve a pointer to the current Find Replace dialog box. It should be used within your callback function to access the current dialog box, call its member functions, and access the m_fr structure.

Return Value

A pointer to the current dialog box.


  CFindReplaceDialog::GetReplaceString

CString GetReplaceString() const;

Return Value

The default string to replace found strings with.

See Also

»CFindReplaceDialog::GetFindString«


  CFindReplaceDialog::IsTerminating

BOOL IsTerminating() const;

Remarks

Call this function within your callback function to determine whether the user has decided to terminate the dialog box. If this function returns nonzero, you should call the DestroyWindow member function of the current dialog box and set any dialog box pointer variable to NULL. Optionally, you can also store the find/replace text last entered and use it to initialize the next find/replace dialog box.

Return Value

Nonzero if the user has decided to terminate the dialog box; otherwise 0.


  CFindReplaceDialog::MatchCase

BOOL MatchCase() const;

Return Value

Nonzero if the user wants to find occurrences of the search string that exactly match the case of the search string; otherwise 0.

See Also

»CFindReplaceDialog::MatchWholeWord«


  CFindReplaceDialog::MatchWholeWord

BOOL MatchWholeWord() const;

Return Value

Nonzero if the user wants to match only the entire words of the search string; otherwise 0.

See Also

»CFindReplaceDialog::MatchCase«


  CFindReplaceDialog::ReplaceAll

BOOL ReplaceAll() const;

Return Value

Nonzero if the user has requested that all strings matching the replace string be replaced; otherwise 0.

See Also

»CFindReplaceDialog::ReplaceCurrent«


  CFindReplaceDialog::ReplaceCurrent

BOOL ReplaceCurrent() const;

Return Value

Nonzero if the user has requested that the currently selected string be replaced with the replace string; otherwise 0.

See Also

»CFindReplaceDialog::ReplaceAll«


  CFindReplaceDialog::SearchDown

BOOL SearchDown() const;

Return Value

Nonzero if the user wants the search to proceed in a downward direction; 0 if the user wants the search to proceed in an upward direction.


CFindReplaceDialog Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFindReplaceDialog::m_fr

Remarks

m_fr is a structure of type FINDREPLACE. Its members store the characteristics of the dialog-box object. After constructing a CFindReplaceDialog object, you can use m_fr to initialize various values in the dialog box. You must initialize the dialog box's values before calling the Create member function. For more information on this structure, see the FINDREPLACE structure in the Windows SDK documentation.


CFont
  class CFont : public CGdiObject

The CFont class encapsulates a Windows graphics device interface (GDI) font and provides member functions for manipulating the font. To use a CFont object, construct a CFont object and attach a Windows font to it with CreateFont or CreateFontIndirect, and then use the object's member functions to manipulate the font.

#include <afxwin.h>


CFont Class Members
  Class Members

Construction/Destruction — Public Members

»CFont«	Constructs a CFont object.
Initialization — Public Members

»CreateFontIndirect«	Initializes a CFont object with the characteristics given in a LOGFONT structure.
»CreateFont«	Initializes a CFont with the specified characteristics.
Operations — Public Members

»FromHandle«	Returns a pointer to a CFont object when given a Windows HFONT.


CFont Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFont::CFont

CFont();

Remarks

Constructs a CFont object. The resulting object must be initialized with CreateFont or CreateFontIndirect before it can be used.

See Also

»CFont::CreateFontIndirect«, »CFont::CreateFont«, ::EnumFonts


  CFont::CreateFont

BOOL CreateFont( int nHeight, int nWidth, int nEscapement,
int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
LPCSTR lpszFacename );

nHeight    Specifies the desired height (in logical units) of the font. The font height can be specified in the following ways:

•	Greater than 0, in which case the height is transformed into device units and matched against the cell height of the available fonts.

•	Equal to 0, in which case a reasonable default size is used.

•	Less than 0, in which case the height is transformed into device units and the absolute value is matched against the character height of the available fonts.

The absolute value of nHeight must not exceed 16,384 device units after it is converted. For all height comparisons, the font mapper looks for the largest font that does not exceed the requested size or the smallest font if all the fonts exceed the requested size.

nWidth    Specifies the average width (in logical units) of characters in the font. If nWidth is 0, the aspect ratio of the device will be matched against the digitization aspect ratio of the available fonts to find the closest match, which is determined by the absolute value of the difference.

nEscapement    Specifies the angle (in 0.1-degree units) between the escapement vector and the x-axis of the display surface. The escapement vector is the line through the origins of the first and last characters on a line. The angle is measured counterclockwise from the x-axis.

nOrientation    Specifies the angle (in 0.1-degree units) between the baseline of a character and the x-axis. The angle is measured counterclockwise from the x-axis for coordinate systems in which the y-direction is down and clockwise from the x-axis for coordinate systems in which the y-direction is up.

nWeight    Specifies the font weight (in inked pixels per 1000). Although nWeight can be any integer value from 0 to 1000, the common constants and values are as follows:

Constant	Value
FW_DONTCARE	0
FW_THIN	100
FW_EXTRALIGHT	200
FW_ULTRALIGHT	200
FW_LIGHT	300
FW_NORMAL	400
FW_REGULAR	400
FW_MEDIUM	500
FW_SEMIBOLD	600
FW_DEMIBOLD	600
FW_BOLD	700
FW_EXTRABOLD	800
FW_ULTRABOLD	800
FW_BLACK	900
FW_HEAVY	900
These values are approximate; the actual appearance depends on the typeface. Some fonts have only FW_NORMAL, FW_REGULAR, and FW_BOLD weights. If FW_DONTCARE is specified, a default weight is used.

bItalic    Specifies whether the font is italic.

bUnderline    Specifies whether the font is underlined.

cStrikeOut    Specifies whether characters in the font are struck out. Specifies a strikeout font if set to a nonzero value.

nCharSet    Specifies the font's character set. The following constants and values are predefined:

Constant	Value
ANSI_CHARSET	0
DEFAULT_CHARSET	1
SYMBOL_CHARSET	2
SHIFTJIS_CHARSET	128
OEM_CHARSET	255
The OEM character set is system-dependent.

Fonts with other character sets may exist in the system. An application that uses a font with an unknown character set must not attempt to translate or interpret strings that are to be rendered with that font. Instead, the strings should be passed directly to the output device driver.

The font mapper does not use the DEFAULT_CHARSET value. An application can use this value to allow the name and size of a font to fully describe the logical font. If a font with the specified name does not exist, a font from any character set can be substituted for the specified font. To avoid unexpected results, applications should use the DEFAULT_CHARSET value sparingly.

nOutPrecision    Specifies the desired output precision. The output precision defines how closely the output must match the requested font's height, width, character orientation, escapement, and pitch. It can be any one of the following values:

OUT_CHARACTER_PRECIS
OUT_DEFAULT_PRECIS
OUT_DEVICE_PRECIS
OUT_RASTER_PRECIS
OUT_STRING_PRECIS
OUT_STROKE_PRECIS
OUT_TT_PRECIS

Applications can use the OUT_DEVICE_PRECIS, OUT_RASTER_PRECIS, and OUT_TT_PRECIS values to control how the font mapper chooses a font when the system contains more than one font with a given name. For example, if a system contains a font named Symbol in raster and TrueType form, specifying OUT_TT_PRECIS forces the font mapper to choose the TrueType version. (Specifying OUT_TT_PRECIS forces the font mapper to choose a TrueType font whenever the specified font name matches a device or raster font, even when there is no TrueType font of the same name.)

nClipPrecision    Specifies the desired clipping precision. The clipping precision defines how to clip characters that are partially outside the clipping region. It can be any one of the following values:

CLIP_CHARACTER_PRECIS
CLIP_DEFAULT_PRECIS
CLIP_ENCAPSULATE
CLIP_LH_ANGLES
CLIP_MASK
CLIP_STROKE_PRECIS
CLIP_TT_ALWAYS

To use an embedded read-only font, an application must specify CLIP_ENCAPSULATE.

To achieve consistent rotation of device, TrueType, and vector fonts, an application can use the OR operator to combine the CLIP_LH_ANGLES value with any of the other nClipPrecision values. If the CLIP_LH_ANGLES bit is set, the rotation for all fonts depends on whether the orientation of the coordinate system is left-handed or right-handed. (For more information about the orientation of coordinate systems, see the description of the »nOrientation« parameter.) If CLIP_LH_ANGLES is not set, device fonts always rotate counterclockwise, but the rotation of other fonts is dependent on the orientation of the coordinate system.

nQuality    Specifies the font's output quality, which defines how carefully the GDI must attempt to match the logical-font attributes to those of an actual physical font. It can be one of the following values, with the meaning as given:

•	DEFAULT_QUALITY    Appearance of the font does not matter.

•	DRAFT_QUALITY    Appearance of the font is less important than when PROOF_QUALITY is used. For GDI raster fonts, scaling is enabled. Bold, italic, underline, and strikeout fonts are synthesized if necessary.

•	PROOF_QUALITY    Character quality of the font is more important than exact matching of the logical-font attributes. For GDI raster fonts, scaling is disabled and the font closest in size is chosen. Bold, italic, underline, and strikeout fonts are synthesized if necessary.

nPitchAndFamily    Specifies the pitch and family of the font. The two low-order bits specify the pitch of the font and can be any one of the following values:

DEFAULT_PITCH	VARIABLE_PITCH
FIXED_PITCH

Applications can add TMPF_TRUETYPE to the nPitchAndFamily parameter to choose a TrueType font. The four high-order bits of the parameter specify the font family and can be one of the following values, with the meaning as given:

•	FF_DECORATIVE    Novelty fonts. Old English, for example.

•	FF_DONTCARE    Don't care or don't know.

•	FF_MODERN    Fonts with constant stroke width (fixed-pitch), with or without serifs. Fixed-pitch fonts are usually modern faces. Pica, Elite, and Courier New are examples.

•	FF_ROMAN    Fonts with variable stroke width (proportionally spaced) and with serifs. Times New Roman and Century Schoolbook are examples.

•	FF_SCRIPT    Fonts designed to look like handwriting. Script and Cursive are examples.

•	FF_SWISS    Fonts with variable stroke width (proportionally spaced) and without serifs. MS Sans Serif is an example.

An application can specify a value for nPitchAndFamily by using the Boolean OR operator to join a pitch constant with a family constant.

Font families describe the look of a font in a general way. They are intended for specifying fonts when the exact typeface desired is not available.

lpszFacename    A CString or pointer to a null-terminated string that specifies the typeface name of the font. The length of this string must not exceed 30 characters. The Windows EnumFontFamilies function can be used to enumerate all currently available fonts. If lpszFacename is NULL, the GDI uses a device-independent typeface.

Remarks

Initializes a CFont object with the specified characteristics. The font can subsequently be selected as the font for any device context.

The CreateFont function does not create a new Windows GDI font. It merely selects the closest match from the fonts available in the GDI's pool of physical fonts.

Applications can use the default settings for most of these parameters when creating a logical font. The parameters that should always be given specific values are nHeight and lpszFacename. If nHeight and lpszFacename are not set by the application, the logical font that is created is device-dependent.

When you finish with the CFont object created by the CreateFont function, first select the font out of the device context, then delete the CFont object.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CFont::CreateFontIndirect«, ::CreateFont, ::EnumFontFamilies, ::EnumFonts


  CFont::CreateFontIndirect

BOOL CreateFontIndirect( const LOGFONT FAR* lpLogFont );

lpLogFont    Points to a LOGFONT structure that defines the characteristics of the logical font.

Remarks

Initializes a CFont object with the characteristics given in a LOGFONT structure pointed to by lpLogFont. The font can subsequently be selected as the current font for any device.

This font has the characteristics specified in the »LOGFONT« structure. When the font is selected by using the »CDC::SelectObject« the GDI's font mapper attempts to match the logical font with an existing physical font. If it fails to find an exact match for the logical font, it provides an alternative whose characteristics match as many of the requested characteristics as possible.

When you finish with the CFont object created by the CreateFontIndirect function, first select the font out of the device context, then delete the CFont object.

Return Value

Nonzero if successful; otherwise 0.

 LOGFONT Structure

The LOGFONT structure has the following form:

typedef struct tagLOGFONT {
    int   lfHeight;
    int   lfWidth;
    int   lfEscapement;
    int   lfOrientation;
    int   lfWeight;
    BYTE  lfItalic;
    BYTE  lfUnderline;
    BYTE  lfStrikeOut;
    BYTE  lfCharSet;
    BYTE  lfOutPrecision;
    BYTE  lfClipPrecision;
    BYTE  lfQuality;
    BYTE  lfPitchAndFamily;
    BYTE  lfFaceName[LF_FACESIZE];
} LOGFONT;

For more complete information about this struct, see LOGFONTin the Windows SDK.

See Also

»CFont::CreateFont«, »CDC::SelectObject«, »CGdiObject::DeleteObject«, ::CreateFontIndirect


  CFont::FromHandle

static CFont* PASCAL FromHandle( HFONT hFont );

hFont    An HFONT handle to a Windows font.

Remarks

Returns a pointer to a CFont object when given an HFONT handle to a Windows GDI font object. If a CFont object is not already attached to the handle, a temporary CFont object is created and attached. This temporary CFont object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CFont object if successful; otherwise NULL.


CFontDialog
  class CFontDialog : public CDialog

The CFontDialog class allows you to incorporate a font-selection dialog box into your application. A CFontDialog object is a dialog box with a list of fonts that are currently installed in the system. The user can select a particular font from the list, and this selection is then reported back to the application.

To construct a CFontDialog object, use the provided constructor or derive a new subclass and use your own custom constructor.

Once a CFontDialog object has been constructed, you can use the m_cf structure to initialize the values or states of controls in the dialog box. The m_cf structure is of type CHOOSEFONT. For more information on this structure, see the Windows Software Development Kit (SDK) documentation.

After initializing the dialog object's controls, call the DoModal member function to display the dialog box and allow the user to select a font. DoModal returns whether the user selected the OK (IDOK) or Cancel (IDCANCEL) button.

If DoModal returns IDOK, you can use one of CFontDialog's member functions to retrieve the information input by the user.

You can use the Windows CommDlgExtendedError function to determine if an error occurred during initialization of the dialog box to and learn more about the error. For more information on this function, see the Windows SDK documentation.

CFontDialog relies on the COMMDLG.DLL file that ships with Windows versions 3.1 and later. For details about redistributing COMMDLG.DLL to Windows version 3.0 users, see the Getting Started manual for the Windows version 3.1 SDK.

To customize the dialog box, derive a class from CFontDialog, provide a custom dialog template, and add a message-map to process the notification messages from the extended controls. Any unprocessed messages should be passed to the base class.

Customizing the hook function is not required.

#include <afxdlgs.h>


CFontDialog  Class Members
  Class Members

Data Members — Public Members

»m_cf«	A structure used to customize a CFontDialog object.
Construction/Destruction — Public Members

»CFontDialog«	Constructs a CFontDialog object.
Operations — Public Members

»DoModal«	Displays the dialog and allows the user to make a selection.
»GetCurrentFont«	Retrieves the name of the currently selected font.
»GetFaceName«	Returns the face name of the selected font.
»GetStyleName«	Returns the style name of the selected font.
»GetSize«	Returns the point size of the selected font.
»GetColor«	Returns the color of the selected font.
»GetWeight«	Returns the weight of the selected font.
»IsStrikeOut«	Determines if the font is displayed with strikeout.
»IsUnderline«	Determines if the font is underlined.
»IsBold«	Determines if the font is bold.
»IsItalic«	Determines if the font is italic.


CFontDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFontDialog::CFontDialog

CFontDialog( LPLOGFONT lplfInitial = NULL,
DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
CDC* pdcPrinter = NULL,
CWnd* pParentWnd = NULL );

lplfInitial    A pointer to a LOGFONT data structure that allows you to set some of the font's characteristics. The LOGFONT type is defined in WINDOWS.H as follows:

typedef struct tagLOGFONT
  {
    int       lfHeight;
    int       lfWidth;
    int       lfEscapement;
    int       lfOrientation;
    int       lfWeight;
    BYTE      lfItalic;
    BYTE      lfUnderline;
    BYTE      lfStrikeOut;
    BYTE      lfCharSet;
    BYTE      lfOutPrecision;
    BYTE      lfClipPrecision;
    BYTE      lfQuality;
    BYTE      lfPitchAndFamily;
    BYTE      lfFaceName[LF_FACESIZE];
  } LOGFONT;

For more information on the LOGFONTstructure, see the Windows SDK documentation.

dwFlags    Specifies one or more choose-font flags. One or more preset values can be combined using the bitwise-OR operator. If you modify the m_ofn.Flags structure member, be sure to use a bitwise-OR operator in your changes to keep the default behavior intact. For details on each of these flags, see the description of the CHOOSEFONT structure in the Windows SDK documentation.

pdcPrinter    A pointer to a printer-device context. If supplied, this parameter points to a printer-device context for the printer on which the fonts are to be selected.

pParentWnd    A pointer to the font dialog box's parent or owner window.

Remarks

Constructs a CFontDialog object.

See Also

»CFontDialog::DoModal«


  CFontDialog::DoModal

virtual int DoModal();

Remarks

Call this function to display the Windows common font dialog box and allow the user to choose a font.

If you want to initialize the various font dialog controls by setting members of the m_cf structure, you should do this before calling DoModal, but after the dialog object is constructed.

If DoModal returns IDOK, you can call other member functions to retrieve the settings or information input by the user into the dialog box.

Return Value

IDOK or IDCANCEL if the function is successful; otherwise 0. IDOK and IDCANCEL are constants that indicate whether the user selected the OK or Cancel button.

If IDCANCEL is returned, you can call the Windows CommDlgExtendedError function to determine if an error occurred.

See Also

»CDialog::DoModal«, »CFontDialog::CFontDialog«


  CFontDialog::GetColor

COLORREF GetColor() const;

Return Value

The color of the selected font.

See Also

»CFontDialog::GetCurrentFont«


  CFontDialog::GetCurrentFont

void GetCurrentFont( LPLOGFONT lplf );

lplf    A pointer to a LOGFONT structure.

Remarks

Assigns the characteristics of the currently selected font to the members of a LOGFONT structure. For more information on the LOGFONT structure, see the Windows SDK documentation. Other CFontDialog member functions are provided to access individual characteristics of the current font.

See Also

»CFontDialog::GetFaceName«, »CFontDialog::GetStyleName«


  CFontDialog::GetFaceName

CString GetFaceName() const;

Return Value

The face name of the font selected in the CFontDialog dialog box.

See Also

»CFontDialog::GetCurrentFont«, »CFontDialog::GetStyleName«


  CFontDialog::GetSize

int GetSize() const;

Return Value

The font's point size.

See Also

»CFontDialog::GetWeight«, »CFontDialog::GetCurrentFont«


  CFontDialog::GetStyleName

CString GetStyleName() const;

Return Value

The style name of the font.

See Also

»CFontDialog::GetFaceName«, »CFontDialog::GetCurrentFont«


  CFontDialog::GetWeight

int GetWeight() const;

Return Value

The weight of the selected font.

See Also

»CFontDialog::GetCurrentFont«, »CFontDialog::IsBold«


  CFontDialog::IsBold

BOOL IsBold() const;

Return Value

Nonzero if the selected font has the Bold characteristic enabled; otherwise 0.

See Also

»CFontDialog::GetCurrentFont«


  CFontDialog::IsItalic

BOOL IsItalic() const;

Return Value

Nonzero if the selected font has the Italic characteristic enabled; otherwise 0.

See Also

»CFontDialog::GetCurrentFont«


  CFontDialog::IsStrikeOut

BOOL IsStrikeOut() const;

Return Value

Nonzero if the selected font has the Strikeout characteristic enabled; otherwise 0.

See Also

»CFontDialog::GetCurrentFont«


  CFontDialog::IsUnderline

BOOL IsUnderline() const;

Return Value

Nonzero if the selected font has the Underline characteristic enabled; otherwise 0.

See Also

»CFontDialog::GetCurrentFont«


CFontDialog Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFontDialog::m_cf

Remarks

A structure whose members store the characteristics of the dialog object. After constructing a CFontDialog object, you can use m_cf to initialize various values in the dialog box. You must initialize the dialog box's values before calling the Create member function. For more information on this structure, see CHOOSEFONT in the Windows SDK documentation.


CFormView
   class CFormView : public CScrollView

The CFormView class is the base class used for views containing controls. These controls are laid out based on a dialog-template resource. Use CFormView if you want form-based documents in your application. These views support scrolling, as needed, using the CScrollView functionality.

Creating a view based on CFormView is similar to creating a dialog box. For information on using AppWizard and ClassWizard with CFormView, see Technical Note 36 in \MSVCNT\HELP\MFCNOTES.HLP.

To use CFormView, take the following steps:

1.	Design a dialog template.

Use the App Studio dialog editor to design the dialog box. Then, in the Styles property page, set the following properties:

•	In the Style box, select Child (WS_CHILD on).

•	In the Border box, select None (WS_BORDER off).

•	Clear the Visible check box (WS_VISIBLE off).

•	Clear the Titlebar check box (WS_CAPTION off).

These steps are necessary because a form view is not a true dialog box. For more information about creating a dialog-box resource using App Studio, see Chapter 3, "Using the Dialog Editor," in the App Studio User's Guide.

2.	Create a view class.

With your dialog template open, invoke ClassWizard and choose CFormView as the class type when you are filling in the Add Class dialog box. ClassWizard creates a CFormView-derived class and connects it to the dialog template you just designed. This connection is established in the constructor for your class; ClassWizard generates a call to the base-class constructor, CFormView::CFormView, and passes the resource ID of your dialog template. For example:

CMyFormView::CMyFormView()
    : CFormView( CMyFormView::IDD )
{
    //{{AFX_DATA_INIT( CMyFormView )
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT

    // Other construction code, such as data initialization
}

Note  If you choose not to use ClassWizard, you must define the appropriate ID you supply to the CFormView constructor (that is, CMyFormView::IDD is not predefined). ClassWizard declares IDD as an enum value in the class it creates for you.

If you want to define member variables in your view class that correspond to the controls in your form view, use the Edit Variables button in the ClassWizard dialog box. This allows you to use the dialog data exchange (DDX) mechanism. If you want to define message handlers for control-notification messages, use the Add Function button in the ClassWizard dialog box. For more information on using ClassWizard, see Chapter 7 of the Class Library User's Guide or Chapter 9 of the App Studio User's Guide.

3.	Override the OnUpdate member function.

The OnUpdate member function is defined by CView and is called to update the form view's appearance. Override this function to update the member variables in your view class with the appropriate values from the current document. Then, if you are using DDX, use the UpdateData member function (defined by CWnd) with an argument of FALSE to update the controls in your form view.

The OnInitialUpdate member function (also defined by CView) is called to perform one-time initialization of the view. CFormView overrides this function to use DDX to set the initial values of the controls you have mapped using ClassWizard. Override OnInitialUpdate if you want to perform custom initialization.

4.	Implement a member function to move data from your view to your document.

This member function is typically a message handler for a control-notification message or for a menu command. If you are using DDX, call the UpdateData member function to update the member variables in your view class. Then move their values to the document associated with the form view.

5.	Override the OnPrint member function (optional).

The OnPrint member function is defined by CView and prints the view. By default, printing and print preview are not supported by the CFormView class. To add printing support, override the OnPrint function in your derived class. See the VIEWEX sample for more information about how to add printing capabilities to a view derived from CFormView.

6.	Associate your view class with a document class and a frame-window class using a document template.

Unlike ordinary views, form views do not require you to override the OnDraw member function defined by CView. This is because controls are able to paint themselves. Only if you want to customize the display of your form view (for example, to provide a background for your view) should you override OnDraw. If you do so, be careful that your updating does not conflict with the updating done by the controls.

If the view becomes smaller than the dialog template, scroll bars appear automatically. Views derived from CFormView support only the MM_TEXT mapping mode.

If you are not using DDX, use the CWnd dialog functions to move data between the member variables in your view class and the controls in your form view.

For more information about DDX, see Chapter 7 of the Class Library User's Guide or Chapter 5, »Working with Dialog Boxes, Controls, Control Bars, and Context-Sensitive Help«, in this manual.

#include <afxext.h>

See Also

»CDialog«, »CScrollView«, »CView::OnUpdate«, »CView::OnInitialUpdate«, »CView::OnPrint«, »CWnd::UpdateData«, »CScrollView::ResizeParentToFit«


CFormView Class Members
  Class Members

Construction/Destruction — Protected Members

»CFormView«	Constructs a CFormView object.


CFormView Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFormView::CFormView

Protected

CFormView( LPCSTR lpszTemplateName );

CFormView( UINT nIDTemplate ); ♦

lpszTemplateName    Contains a null-terminated string that is the name of a dialog-template resource.

nIDTemplate    Contains the ID number of a dialog-template resource.

Remarks

When you create an object of a type derived from CFormView, invoke one of the constructors to create the view object and identify the dialog resource on which the view is based. You can either identify the resource by name (pass a string as the argument to the constructor) or by its ID (pass an unsigned integer as the argument).

The form-view window and child controls are not created until CWnd::Create is called. CWnd::Create is called by the framework as part of the document and view creation process, which is driven by the document template.

Note  Your derived class must supply its own constructor. In the constructor, invoke the constructor, CFormView::CFormView, with the resource name or ID as an argument as shown in the preceding class overview.

See Also

»CWnd::Create«


CFrameWnd
  class CFrameWnd : public CWnd

The CFrameWnd class provides the functionality of a Windows single document interface (SDI) overlapped or pop-up frame window, along with members for managing the window.

To create a useful frame window for your application, derive a class from CFrameWnd. Add member variables to the derived class to store data specific to your application. Implement message-handler member functions and a message map in the derived class to specify what happens when messages are directed to the window.

There are three ways to construct a frame window:

•	Directly construct it using Create.

•	Directly construct it using LoadFrame.

•	Indirectly construct it using a document template.

Before you call either Create or LoadFrame, you must construct the frame-window object on the heap using the C++ new operator. Before calling Create, you may also register a window class with the AfxRegisterWndClass global function to set the icon and class styles for the frame.

Use the Create member function to pass the frame's creation parameters as immediate arguments.

LoadFrame requires fewer arguments than Create, and instead retrieves most of its default values from resources, including the frame's caption, icon, accelerator table, and menu. To be accessible by LoadFrame, all these resources must have the same resource ID (for example, IDR_MAINFRAME).

When a CFrameWnd object contains views and documents, they are created indirectly by the framework instead of directly by the programmer. The CDocTemplate object orchestrates the creation of the frame, the creation of the containing views, and the connection of the views to the appropriate document. The parameters of the CDocTemplate constructor specify the CRuntimeClass of the three classes involved (document, frame, and view). A CRuntimeClass object is used by the framework to dynamically create new frames when specified by the user (for example, by using the File New command or the multiple document interface [MDI] Window New command).

A frame-window class derived from CFrameWnd must be declared with DECLARE_DYNCREATE in order for the above RUNTIME_CLASS mechanism to work correctly.

A CFrameWnd contains default implementations to perform the following functions of a main window in a typical application for Windows:

•	A CFrameWnd frame window keeps track of a currently active view that is independent of the Windows active window or the current input focus. When the frame is reactivated, the active view is notified by calling CView::OnActivateView.

•	Command messages and many common frame-notification messages, including those handled by the OnSetFocus, OnHScroll, and OnVScroll functions of CWnd, are delegated by a CFrameWnd frame window to the currently active view.

•	The currently active view (or currently active MDI child frame window in the case of an MDI frame) can determine the caption of the frame window. This feature can be disabled by turning off the FWS_ADDTOTITLE style bit of the frame window.

•	A CFrameWnd frame window manages the positioning of the control bars, views, and other child windows inside the frame window's client area. A frame window also does idle-time updating of toolbar and other control-bar buttons. A CFrameWnd frame window also has default implementations of commands for toggling on and off the toolbar and status bar.

•	A CFrameWnd frame window manages the main menu bar. When a pop-up menu is displayed, the frame window uses the UPDATE_COMMAND_UI mechanism to determine which menu items should be enabled, disabled, or checked. When the user selects a menu item, the frame window updates the status bar with the message string for that command.

•	A CFrameWnd frame window has an optional accelerator table that automatically translates keyboard accelerators.

•	A CFrameWnd frame window has an optional help ID set with LoadFrame that is used for context-sensitive help. A frame window is the main orchestrator of semimodal states such as context-sensitive help (shift+F1) and print-preview modes.

•	A CFrameWnd frame window will open a file dragged from the File Manager and dropped on the frame window. If a file extension is registered and associated with the application, the frame window responds to the dynamic data exchange (DDE) open request that occurs when the user opens a data file in the File Manager or when the ShellExecute Windows function is called.

•	If the frame window is the main application window (that is, CWinApp::m_pMainWnd), when the user closes the application, the frame window prompts the user to save any modified documents (for OnClose and OnQueryEndSession).

•	If the frame window is the main application window, the frame window is the context for running WinHelp. Closing the frame window will shut down WINHELP.EXE if it was launched for help for this application.

Do not use the C++ delete operator to destroy a frame window. Use CWnd::DestroyWindow instead. The CFrameWnd implementation of PostNcDestroy will delete the C++ object when the window is destroyed. When the user closes the frame window, the default OnClose handler will call DestroyWindow.

#include <afxwin.h>

See Also

»CWnd«, »CMDIFrameWnd«, »CMDIChildWnd«


CFrameWnd Class Members
  Class Members

Data Members — Public Members

»m_bAutoMenuEnable«	Controls automatic enable and disable functionality for menu items.
»rectDefault«	Pass this static CRect as a parameter when creating a CFrameWnd object to allow Windows to choose the window's initial size and position.
Construction/Destruction — Public Members

»CFrameWnd«	Constructs a CFrameWnd object.
Initialization — Public Members

»Create«	Call to create and initialize the Windows frame window associated with the CFrameWnd object.
»LoadFrame«	Call to dynamically create a frame window from resource information.
»LoadAccelTable«	Call to load an accelerator table.
Operations — Public Members

»ActivateFrame«	Makes the frame visible and available to the user.
»SetActiveView«	Sets the active CView object.
»GetActiveView«	Returns the active CView object.
»GetActiveDocument«	Returns the active CDocument object.
»RecalcLayout«	Repositions control bars.
Overridables — Public Members

»OnSetPreviewMode«	Sets the application's main frame window into and out of print-preview mode.
Overridables — Protected Members

»OnCreateClient«	Creates a client window for the frame.


CFrameWnd Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CFrameWnd::ActivateFrame

virtual void ActivateFrame( int nCmdShow = − 1 );

nCmdShow    Specifies the parameter to pass to »CWnd::ShowWindow«. By default, the frame is shown and correctly restored.

Remarks

Call this member function to activate and restore the frame window so that it is visible and available to the user. This member function is usually called after a non-user interface event such as a DDE, Object Linking and Embedding (OLE), or other event that may show the frame window or its contents to the user.

The default implementation activates the frame and brings it to the top of the Z-order and, if necessary, carries out the same steps for the application's main frame window.

Override this member function to change how a frame is activated. For example, you can force MDI child windows to be maximized. Add the appropriate functionality, then call the base class version with an explicit nCmdShow.


  CFrameWnd::CFrameWnd

CFrameWnd();

Remarks

Constructs a CFrameWnd object, but doesn't create the visible frame window. Call Create to create the visible window.

See Also

»CFrameWnd::Create«, »CFrameWnd::LoadFrame«


  CFrameWnd::Create

BOOL Create( LPCSTR lpszClassName, LPCSTR lpszWindowName, DWORD dwStyle = WS_OVERLAPPEDWINDOW,
const RECT& rect = rectDefault, CWnd* pParentWnd = NULL,
LPCSTR lpszMenuName = NULL, DWORD dwExStyle = 0, CCreateContext* pContext = NULL );

lpszClassName    Points to a null-terminated character string that names the Windows class. The class name can be any name registered with the AfxRegisterWndClass global function or the RegisterClass Windows function. If NULL, uses the predefined default CFrameWnd attributes.

lpszWindowName    Points to a null-terminated character string that represents the window name. Used as text for the title bar.

dwStyle    Specifies the window »style« attributes. Include the FWS_ADDTOTITLE style if you want the title bar to automatically display the name of the document represented in the window.

See the »CWnd::Create« member function for a full list of window styles.

rect    Specifies the size and position of the window. The rectDefault value allows Windows to specify the size and position of the new window.

pParentWnd    Specifies the parent window of this frame window. This parameter should be NULL for top-level frame windows.

lpszMenuName    Identifies the name of the menu resource to be used with the window. Use MAKEINTRESOURCE if the menu has an integer ID instead of a string. This parameter can be NULL.

dwExStyle    Specifies the window extended »style« attributes.

See the »CWnd::CreateEx« member function for a list of extended window styles.

pContext    Specifies a pointer to a »CCreateContext« structure. This parameter can be NULL.

Remarks

Construct a CFrameWnd object in two steps. First invoke the constructor, which constructs the CFrameWnd object, then call Create, which creates the Windows frame window and attaches it to the CFrameWnd object. Create initializes the window's class name and window name and registers default values for its style, parent, and associated menu.

Use LoadFrame rather than Create to load the frame window from a resource instead of specifying its arguments.

Return Value

Nonzero if initialization is successful; otherwise 0.

See Also

»CFrameWnd::CFrameWnd«, »CFrameWnd::LoadFrame«, »CCreateContext«, »CWnd::Create«, »CWnd::PreCreateWindow«


  CFrameWnd::GetActiveDocument

virtual CDocument* GetActiveDocument();

Remarks

Call this member function to obtain a pointer to the current CDocument attached to the current active view.

Return Value

A pointer to the current CDocument. If there is no current document, returns NULL.

See Also

»CFrameWnd::GetActiveView«


  CFrameWnd::GetActiveView

CView* GetActiveView() const;

Remarks

Call this member function to obtain a pointer to the active view.

Return Value

A pointer to the current CView. If there is no current view, returns NULL.

See Also

»CFrameWnd::SetActiveView«, »CFrameWnd::GetActiveDocument«


  CFrameWnd::LoadAccelTable

BOOL LoadAccelTable( LPCSTR lpszResourceName );

lpszResourceName    Identifies the name of the accelerator resource. Use MAKEINTRESOURCE if the resource is identified with an integer ID.

Remarks

Call to load the specified accelerator table. Only one table may be loaded at a time.

Accelerator tables loaded from resources are freed automatically when the application terminates.

If you call LoadFrame to create the frame window, the framework loads an accelerator table along with the menu and icon resources, and a subsequent call to this member function is then unnecessary.

Return Value

Nonzero if the accelerator table was successfully loaded; otherwise 0.

See Also

»CFrameWnd::LoadFrame«, ::LoadAccelerators


  CFrameWnd::LoadFrame

virtual BOOL LoadFrame( UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );

nIDResource    The ID of shared resources associated with the frame window.

dwDefaultStyle    The frame's »style«. Include the FWS_ADDTOTITLE style if you want the title bar to automatically display the name of the document represented in the window.

See the »CWnd::Create« member function for a full list of window styles.

pParentWnd    A pointer to the frame's parent.

pContext    A pointer to a CCreateContext structure. This parameter can be NULL.

Remarks

Construct a CFrameWnd object in two steps. First invoke the constructor, which constructs the CFrameWnd object, then call LoadFrame, which loads the Windows frame window and associated resources and attaches the frame window to the CFrameWnd object. The nIDResource parameter specifies the menu, the accelerator table, the icon, and the string resource of the title for the frame window.

Use the Create member function rather than LoadFrame when you want to specify all of the frame window's creation parameters.

The framework calls LoadFrame when it creates a frame window using a document template object.

The framework uses the pContext argument to specify the objects to be connected to the frame window, including any contained view objects. You can set the pContext argument to NULL when you call LoadFrame.

See Also

»CDocTemplate«, »CFrameWnd::Create«, »CFrameWnd::CFrameWnd«, »CWnd::PreCreateWindow«


  CFrameWnd::OnCreateClient

Protected

virtual BOOL OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext ); ♦

lpcs    A pointer to a Windows »CREATESTRUCT« structure.

pContext    A pointer to a »CCreateContext« structure.

Remarks

Called by the framework during the execution of OnCreate. Never call this function.

The default implementation of this function creates a CView object from the information provided in pContext, if possible.

Override this function to override values passed in the CCreateContext object or to change the way controls in the main client area of the frame window are created. The CCreateContext members you can override are described in the »CCreateContext« class.

Note  Do not replace values passed in the CREATESTRUCT structure. They are for informational use only. If you want to override the initial window rectangle, for example, override the CWnd member function PreCreateWindow.


  CFrameWnd::OnSetPreviewMode

virtual void OnSetPreviewMode( BOOL bPreview, CPrintPreviewState* pModeStuff );

bPreview    Specifies whether or not to place the application in print-preview mode. Set to TRUE to place in print preview, FALSE to restore to cancel preview mode.

pModeStuff    A pointer to a CPrintPreviewState structure.

Remarks

Call this member function to set the application's main frame window into and out of print-preview mode.

The default implementation disables all standard toolbars and hides the main menu and the main client window. This turns MDI frame windows into temporary SDI frame windows.

Override this member function to customize the hiding and showing of control bars and other frame window parts during print preview. Call the base class implementation from within the overridden version.


  CFrameWnd::RecalcLayout

virtual void RecalcLayout();

Remarks

Call this member function to reposition control bars after changing the layout of the frame window. For example, call it when you turn on or off control bars or add another control bar.

Called by the framework when the standard control bars are toggled on or off or when the frame window is resized.

The default implementation of this member function calls the CWnd member function RepositionBars to reposition all the control bars in the frame as well as the main client window (usually a CView or MDICLIENT).

See Also

»CWnd::RepositionBars«


  CFrameWnd::SetActiveView

void SetActiveView( CView* pViewNew );

pViewNew    Specifies a pointer to a CView object, or NULL for no active view.

Remarks

Call this member function to set the active view. The framework will call this function automatically as the user changes the focus to a view within the frame window. You may explictly call SetActiveView to change the focus to the specified view.

See Also

»CFrameWnd::GetActiveView«, »CView::OnActivateView«, »CFrameWnd::GetActiveDocument«


CFrameWnd Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CFrameWnd::m_bAutoMenuEnable

Remarks

When this data member is enabled (which is the default), menu items that don't have ON_UPDATE_COMMAND_UI or ON_COMMAND handlers will be automatically disabled when the user pulls down a menu.

Menu items that have an ON_COMMAND handler but no ON_UPDATE_COMMAND_UI handler will be automatically enabled.

When this data member is set, menu items are automatically enabled in the same way that toolbar buttons are enabled.

This data member simplifies the implementation of optional commands based on the current selection and reduces the need for an application to write ON_UPDATE_COMMAND_UI handlers for enabling and disabling menu items.

See Also

»CCmdUI«, »CCmdTarget«


  CFrameWnd::rectDefault

Remarks

Pass this static CRect as a parameter when creating a window to allow Windows to choose the window's initial size and position.

See Also

CW_USEDEFAULT


CGdiObject
  class CGdiObject : public CObject

The CGdiObject class provides a base class for various kinds of Windows graphics device interface (GDI) objects such as bitmaps, regions, brushes, pens, palettes, and fonts. You never create a CGdiObject directly. Rather, you create an object from one of its derived classes, such as CPen or CBrush.

#include <afxwin.h>

See Also

»CBitmap«, »CBrush«, »CFont«, »CPalette«, »CPen«, »CRgn«


CGdiObject Class Members
  Class Members

Data Members — Public Members

»m_hObject«	A HANDLE containing the HBITMAP, HPALETTE, HRGN, HBRUSH, HPEN, or HFONT attached to this object.
Construction/Destruction — Public Members

»CGdiObject«	Constructs a CGdiObject object.
Operations — Public Members

»GetSafeHandle«	Returns m_hObject unless this is NULL, in which case NULL is returned.
»FromHandle«	Returns a pointer to a CGdiObject object given a handle to a Windows GDI object.
»Attach«	Attaches a Windows GDI object to a CGdiObject object.
»Detach«	Detaches a Windows GDI object from a CGdiObject object and returns a handle to the Windows GDI object.
»DeleteObject«	Deletes the Windows GDI object attached to the CGdiObject object from memory by freeing all system storage associated with the object.
»DeleteTempMap«	Deletes any temporary CGdiObject objects created by FromHandle.
»GetObject«	Fills a buffer with data that describes the Windows GDI object attached to the CGdiObject object.
»CreateStockObject«	Retrieves a handle to one of the Windows predefined stock pens, brushes, or fonts.
»UnrealizeObject«	Resets the origin of a brush or resets a logical palette.


GdiObject Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CGdiObject::Attach

BOOL Attach( HGDIOBJ hObject );

hObject    A HANDLE to a Windows GDI object (for example, HPEN or HBRUSH).

Remarks

Attaches a Windows GDI object to a CGdiObject object.

Return Value

Nonzero if attachment is successful; otherwise 0.

See Also

»CGdiObject::Detach«


  CGdiObject::CGdiObject

CGdiObject();

Remarks

Constructs a CGdiObject object. You never create a CGdiObject directly. Rather, you create an object from one of its derived classes, such as CPen or CBrush.

See Also

»CPen«, »CBrush«, »CFont«, »CBitmap«, »CRgn«, »CPalette«


  CGdiObject::CreateStockObject

BOOL CreateStockObject( int nIndex );

nIndex    A constant specifying the type of stock object desired. It can be one of the following values, with the meanings as given:

•	BLACK_BRUSH    Black brush.

•	DKGRAY_BRUSH    Dark gray brush.

•	GRAY_BRUSH    Gray brush.

•	HOLLOW_BRUSH    Hollow brush.

•	LTGRAY_BRUSH    Light gray brush.

•	NULL_BRUSH    Null brush.

•	WHITE_BRUSH    White brush.

•	BLACK_PEN    Black pen.

•	NULL_PEN    Null pen.

•	WHITE_PEN    White pen.

•	ANSI_FIXED_FONT    ANSI fixed system font.

•	ANSI_VAR_FONT    ANSI variable system font.

•	DEVICE_DEFAULT_FONT    Device-dependent font.

•	OEM_FIXED_FONT    OEM-dependent fixed font.

•	SYSTEM_FONT    The system font. By default, Windows uses the system font to draw menus, dialog-box controls, and other text. In Windows versions 3.0 and later, the system font is proportional width; earlier versions of Windows use a fixed-width system font.

•	SYSTEM_FIXED_FONT    The fixed-width system font used in Windows prior to version 3.0. This object is available for compatibility with earlier versions of Windows.

•	DEFAULT_PALETTE    Default color palette. This palette consists of the 20 static colors in the system palette.

Remarks

Retrieves a handle to one of the predefined stock Windows GDI pens, brushes, or fonts, and attaches the GDI object to the CGdiObject object. Call this function with one of the derived classes that corresponds to the Windows GDI object type, such as CPen for a stock pen.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CPen::CPen«, »CBrush::CBrush«, »CFont::CFont«, »CPalette::CPalette«


  CGdiObject::DeleteObject

BOOL DeleteObject();

Remarks

Deletes the attached Windows GDI object from memory by freeing all system storage associated with the Windows GDI object. The storage associated with the CGdiObject object is not affected by this call. An application should not call DeleteObject on a CGdiObject object that is currently selected into a device context.

When a pattern brush is deleted, the bitmap associated with the brush is not deleted. The bitmap must be deleted independently.

See Also

»CGdiObject::Detach«


  CGdiObject::DeleteTempMap

static void PASCAL DeleteTempMap();

Remarks

Called automatically by the CWinApp idle-time handler, DeleteTempMap deletes any temporary CGdiObject objects created by FromHandle. DeleteTempMap detaches the Windows GDI object attached to a temporary CGdiObject object before deleting the CGdiObject object.

See Also

»CGdiObject::Detach«, »CGdiObject::FromHandle«


  CGdiObject::Detach

HGDIOBJ Detach();

Remarks

Detaches a Windows GDI object from a CGdiObject object and returns a handle to the Windows GDI object.

Return Value

A HANDLE to the Windows GDI object detached; otherwise NULL if no GDI object is attached.

See Also

»CGdiObject::Attach«


  CGdiObject::FromHandle

static CGdiObject* PASCAL FromHandle( HGDIOBJ hObject );

hObject    A HANDLE to a Windows GDI object.

Remarks

Returns a pointer to a CGdiObject object given a handle to a Windows GDI object. If a CGdiObject object is not already attached to the Windows GDI object, a temporary CGdiObject object is created and attached.

This temporary CGdiObject object is only valid until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CGdiObject that may be temporary or permanent.

See Also

»CGdiObject::DeleteTempMap«


  CGdiObject::GetObject

int GetObject( int nCount, LPVOID lpObject ) const;

nCount    Specifies the number of bytes to copy into the lpObject buffer.

lpObject    Points to a user-supplied buffer that is to receive the information.

Remarks

Fills a buffer with data that defines a specified object. The function retrieves a data structure whose type depends on the type of graphic object, as shown by the following list:

Object	Buffer type
CPen	LOGPEN
CBrush	LOGBRUSH
CFont	LOGFONT
CBitmap	BITMAP
CPalette	int
CRgn	Not supported
If the object is a CBitmap object, GetObject returns only the width, height, and color format information of the bitmap. The actual bits can be retrieved by using »CBitmap::GetBitmapBits«.

If the object is a CPalette object, GetObject retrieves an integer that specifies the number of entries in the palette. The function does not retrieve the LOGPALETTEstructure that defines the palette. An application can get information on palette entries by calling »CPalette::GetPaletteEntries«.

Return Value

The number of bytes retrieved; otherwise 0 if an error occurs.

See Also

»CBitmap::GetBitmapBits«, »CPalette::GetPaletteEntries«


  CGdiObject::GetSafeHandle

HGDIOBJ GetSafeHandle() const;

Remarks

Returns m_hObject unless this is NULL, in which case NULL is returned. This is part of the general handle interface paradigm and is useful when NULL is a valid or special value for a handle.

Return Value

A HANDLE to the attached Windows GDI object; otherwise NULL if no object is attached.


  CGdiObject::UnrealizeObject

BOOL UnrealizeObject();

Remarks

Resets the origin of a brush or resets a logical palette. While UnrealizeObject is a member function of the CGdiObject class, it should be invoked only on CBrush or CPalette objects.

For CBrush objects, UnrealizeObject directs the system to reset the origin of the given brush the next time it is selected into a device context. If the object is a CPalette object, UnrealizeObject directs the system to realize the palette as though it had not previously been realized. The next time the application calls the »CDC::RealizePalette« function for the specified palette, the system completely remaps the logical palette to the system palette.

The UnrealizeObject function should not be used with stock objects. The UnrealizeObject function must be called whenever a new brush origin is set (by means of the »CDC::SetBrushOrg« function). The UnrealizeObject function must not be called for the currently selected brush or currently selected palette of any display context.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CDC::RealizePalette«, »CDC::SetBrushOrg«


GdiObject Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CGdiObject::m_hObject

Remarks

A HANDLE containing the HBITMAP, HRGN, HBRUSH, HPEN, HPALETTE, or HFONT attached to this object.


CListBox
  class CListBox : public CWnd

The CListBox class provides the functionality of a Windows list box. A list box displays a list of items, such as filenames, that the user can view and select.

In a single-selection list box, the user can select only one item. In a multiple-selection list box, a range of items can be selected. When the user selects an item, it is highlighted and the list box sends a notification message to the parent window.

The list box itself automatically displays horizontal or vertical scroll bars if the list within the box is too large for the list-box window.

You can create a list box either from a dialog template or directly in your code. In both cases, call the constructor CListBox to construct the CListBox object, then call the »Create« member function to create the Windows list-box control and attach it to the CListBox object.

Construction can be a one-step process in a class derived from CListBox. Write a constructor for the derived class and call Create from within the constructor.

If you want to handle Windows notification messages sent by a list box to its parent (usually a class derived from CDialog), add a message-map entry and message-handler member function to the parent class for each message.

Each message-map entry takes the following form:

ON_Notification( id, memberFxn )

Where id specifies the child window ID of the list-box control sending the notification and memberFxn is the name of the parent member function you have written to handle the notification.

The parent's function prototype is as follows:

afx_msg void memberFxn();

Following is a list of potential message-map entries and a description of the cases in which they would be sent to the parent:

•	ON_LBN_DBLCLK    The user double-clicks a string in a list box. Only a list box that has the »LBS_NOTIFY« style will send this notification message.

•	ON_LBN_ERRSPACE    The list box cannot allocate enough memory to meet the request.

•	ON_LBN_KILLFOCUS    The list box is losing the input focus.

Windows 3.1 Only

•	ON_LBN_SELCANCEL    The current list-box selection is cancelled. This message is only sent when a list box has the LBS_NOTIFY style. ♦

•	ON_LBN_SELCHANGE    The selection in the list box is about to change. This notification is not sent if the selection is changed by the »CListBox::SetCurSel« member function. This notification applies only to a list box that has the LBS_NOTIFY style. The LBN_SELCHANGE notification message is sent for a multiple-selection list box whenever the user presses an arrow key, even if the selection does not change.

•	ON_LBN_SETFOCUS    The list box is receiving the input focus.

If you create a CListBox object within a dialog box (through a dialog resource), the CListBox object is automatically destroyed when the user closes the dialog box.

If you create a CListBox object within a window, you may need to destroy the CListBox object. If you create the CListBox object on the stack, it is destroyed automatically. If you create the CListBox object on the heap by using the new function, you must call delete on the object to destroy it when the user terminates the Windows list box.

If you allocate any memory in the CListBox object, override the CListBox destructor to dispose of the allocations.

#include <afxwin.h>

See Also

»CWnd«, »CButton«, »CComboBox«, »CEdit«, »CScrollBar«, »CStatic«, »CDialog«


CListBox Class Members
  Class Members

Construction/Destruction — Public Members

»CListBox«	Constructs a CListBox object.
Initialization — Public Members

»Create«	Creates the Windows list box and attaches it to the CListBox object.
General Operations — Public Members

»GetCount«	Returns the number of strings in a list box.
»GetHorizontalExtent«	Returns the width in pixels that a list box can be scrolled horizontally.
»SetHorizontalExtent«	Sets the width in pixels that a list box can be scrolled horizontally.
»GetTopIndex«	Returns the index of the first visible string in a list box.
»SetTopIndex«	Sets the zero-based index of the first visible string in a list box.
»GetItemData«	Returns the 32-bit value associated with the list-box item.
»GetItemDataPtr«	Returns a pointer to a list-box item.
»SetItemData«	Sets the 32-bit value associated with the list-box item.
»SetItemDataPtr«	Sets a pointer to the list-box item.
»GetItemRect«	Returns the bounding rectangle of the list-box item as it is currently displayed.
»SetItemHeight«	Sets the height of items in a list box.
»GetItemHeight«	Determines the height of items in a list box.
»GetSel«	Returns the selection state of a list-box item.
»GetText«	Copies a list-box item into a buffer.
»GetTextLen«	Returns the length in bytes of a list-box item.
»SetColumnWidth«	Sets the column width of a multicolumn list box.
»SetTabStops«	Sets the tab-stop positions in a list box.
Single-Selection Operations — Public Members

»GetCurSel«	Returns the zero-based index of the currently selected string in a list box.
»SetCurSel«	Selects a list-box string.
Multiple-Selection Operations — Public Members

»SetSel«	Selects or deselects a list-box item in a multiple-selection list box.
»GetCaretIndex«	Determines the index of the item that has the focus rectangle in a multiple-selection list box.
»SetCaretIndex«	Set the focus rectangle to the item at the specified index in a multiple-selection list box.
»GetSelCount«	Returns the number of strings currently selected in a multiple-selection list box.
»GetSelItems«	Returns the indices of the strings currently selected in a list box.
»SelItemRange«	Selects or deselects a range of strings in a multiple-selection list box.
String Operations — Public Members

»AddString«	Adds a string to a list box.
»DeleteString«	Deletes a string from a list box.
»InsertString«	Inserts a string at a specific location in a list box.
»ResetContent«	Clears all the entries from a list box.
»Dir«	Adds filenames from the current directory to a list box.
»FindString«	Searches for a string in a list box.
»FindStringExact«	Finds the first list-box string that matches a specified string.
»SelectString«	Searches for and selects a string in a single-selection list box.
Overridables — Public Members

»DrawItem«	Called by the framework when a visual aspect of an owner-draw list box changes.
»MeasureItem«	Called by the framework when an owner-draw list box is created to determine list-box dimensions.
»CompareItem«	Called by the framework to determine the position of a new item in a sorted owner-draw list box.
»DeleteItem«	Called by the framework when the user deletes an item from an owner-draw list box.


CListbox Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CListBox::AddString

int AddString( LPCSTR lpszItem );

lpszItem    Points to the null-terminated string that is to be added.

Remarks

Call this member function to add a string to a list box. If the list box was not created with the »LBS_SORT« style, the string is added to the end of the list. Otherwise, the string is inserted into the list, and the list is sorted. If the list box was created with the LBS_SORT style but not the »LBS_HASSTRINGS« style, the framework sorts the list by one or more calls to the CompareItem member function.

Use »InsertString« to insert a string into a specific location within the list box.

Return Value

The zero-based index to the string in the list box. The return value is LB_ERR if an error occurs; the return value is LB_ERRSPACE if insufficient space is available to store the new string.

See Also

»CListBox::InsertString«, »CListBox::CompareItem«, LB_ADDSTRING


  CListBox::CListBox

CListBox();

Remarks

You construct a CListBox object in two steps. First call the constructor CListBox, then call Create, which initializes the Windows list box and attaches it to the CListBox.

See Also

»CListBox::Create«


  CListBox::CompareItem

virtual int CompareItem( LPCOMPAREITEMSTRUCT lpCompareItemStruct );

lpCompareItemStruct    A long pointer to a COMPAREITEMSTRUCT structure.

Remarks

Called by the framework to determine the relative position of a new item in a sorted owner-draw list box. By default, this member function does nothing. If you create an owner-draw list box with the LBS_SORT style, you must override this member function to assist the framework in sorting new items added to the list box.

Return Value

Indicates the relative position of the two items described in the COMPAREITEMSTRUCT structure. It may be any of the following values:

Value	Meaning
−1	Item 1 sorts before item 2.
0	Item 1 and item 2 sort the same.
1	Item 1 sorts after item 2.
See »CWnd::OnCompareItem« for a description of the COMPAREITEMSTRUCT structure.

See Also

WM_COMPAREITEM, »CWnd::OnCompareItem«, »CListBox::DrawItem«, »CListBox::MeasureItem«, »CListBox::DeleteItem«


  CListBox::Create

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle    Specifies the »style« of the list box.

rect    Specifies the list-box size and position. Can be either a CRect object or a RECT structure.

pParentWnd    Specifies the list box's parent window (usually a CDialog or CModalDialog object). It must not be NULL.

nID    Specifies the list box's control ID.

Remarks

You construct a CListBox object in two steps. First call the constructor, then call Create, which initializes the Windows list box and attaches it to the CListBox object.

When Create executes, Windows sends the »WM_NCCREATE«, »WM_CREATE«, »WM_NCCALCSIZE«, and »WM_GETMINMAXINFO« messages to the list-box control.

These messages are handled by default by the »OnNcCreate«, »OnCreate«, »OnNcCalcSize«, and »OnGetMinMaxInfo« member functions in the CWnd base class. To extend the default message handling, derive a class from CListBox, add a message map to the new class, and override the preceding message-handler member functions. Override OnCreate, for example, to perform needed initialization for a new class.

Apply the following »window styles« to a list-box control:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

•	WS_VSCROLL    To add a vertical scroll bar

•	WS_HSCROLL    To add a horizontal scroll bar

•	WS_GROUP    To group controls

•	WS_TABSTOP    To allow tabbing to this control

Apply any combination of »list-box styles« to a list box.

Return Value

Nonzero if successful; otherwise 0.

 List-Box Styles

You can use any combination of the following list-box styles for dwStyle:

•	LBS_EXTENDEDSEL    The user can select multiple items using the SHIFT key and the mouse or special key combinations.

•	LBS_HASSTRINGS    Specifies an owner-draw list box that contains items consisting of strings. The list box maintains the memory and pointers for the strings so the application can use the GetText member function to retrieve the text for a particular item.

•	LBS_MULTICOLUMN    Specifies a multicolumn list box that is scrolled horizontally. The SetColumnWidth member function sets the width of the columns.

•	LBS_MULTIPLESEL    String selection is toggled each time the user clicks or double-clicks the string. Any number of strings can be selected.

•	LBS_NOINTEGRALHEIGHT    The size of the list box is exactly the size specified by the application when it created the list box. Usually, Windows sizes a list box so that the list box does not display partial items.

•	LBS_NOREDRAW    List-box display is not updated when changes are made. This style can be changed at any time by sending a WM_SETREDRAW message.

•	LBS_NOTIFY    Parent window receives an input message whenever the user clicks or double-clicks a string.

•	LBS_OWNERDRAWFIXED    The owner of the list box is responsible for drawing its contents; the items in the list box are the same height.

•	LBS_OWNERDRAWVARIABLE    The owner of the list box is responsible for drawing its contents; the items in the list box are variable in height.

•	LBS_SORT    Strings in the list box are sorted alphabetically.

•	LBS_STANDARD    Strings in the list box are sorted alphabetically, and the parent window receives an input message whenever the user clicks or double-clicks a string. The list box contains borders on all sides.

•	LBS_USETABSTOPS    Allows a list box to recognize and expand tab characters when drawing its strings. The default tab positions are 32 dialog units. (A dialog unit is a horizontal or vertical distance. One horizontal dialog unit is equal to one-fourth of the current dialog base width unit. The dialog base units are computed based on the height and width of the current system font. The GetDialogBaseUnits Windows function returns the current dialog base units in pixels.)

•	LBS_WANTKEYBOARDINPUT    The owner of the list box receives WM_VKEYTOITEM or WM_CHARTOITEM messages whenever the user presses a key while the list box has input focus. This allows an application to perform special processing on the keyboard input.

Windows 3.1 Only

•	LBS_DISABLENOSCROLL    The list box shows a disabled vertical scroll bar when the list box does not contain enough items to scroll. Without this style, the scroll bar is hidden when the list box does not contain enough items. ♦

See Also

»CListBox::CListBox«


  CListBox::DeleteItem

virtual void DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct );

lpDeleteItemStruct    A long pointer to a Windows DELETEITEMSTRUCT structure that contains information about the deleted item.

Remarks

Called by the framework when the user deletes an item from an owner-draw CListBox object or destroys the list box. The default implementation of this function does nothing. Override this function to redraw an owner-draw list box as needed.

See »CWnd::OnDeleteItem« for a description of the DELETEITEMSTRUCT structure.

See Also

»CListBox::CompareItem«, »CWnd::OnDeleteItem«, »CListBox::DrawItem«, »CListBox::MeasureItem«, ::DeleteItem


  CListBox::DeleteString

int DeleteString( UINT nIndex );

nIndex    Specifies the zero-based index of the string to be deleted.

Remarks

Deletes an item in a list box.

Return Value

A count of the strings remaining in the list. The return value is LB_ERR if nIndex specifies an index greater then the number of items in the list.

See Also

LB_DELETESTRING, »CListBox::AddString«, »CListBox::InsertString«


  CListBox::Dir

int Dir( UINT attr, LPCSTR lpszWildCard );

attr    Can be any combination of the enum values described in »CFile::GetStatus«, or any combination of the following values:

Value	Meaning
0x0000	File can be read from or written to.
0x0001	File can be read from but not written to.
0x0002	File is hidden and does not appear in a directory listing.
0x0004	File is a system file.
0x0010	The name specified by lpszWildCard specifies a directory.
0x0020	File has been archived.
0x4000	Include all drives that match the name specified by lpszWildCard.
0x8000	Exclusive flag. If the exclusive flag is set, only files of the specified type are listed. Otherwise, files of the specified type are listed in addition to "normal" files.
lpszWildCard    Points to a file-specification string. The string can contain wildcards (for example, *.*).

Remarks

Adds a list of filenames and/or drives to a list box.

Return Value

The zero-based index of the last filename added to the list. The return value is LB_ERR if an error occurs; the return value is LB_ERRSPACE if insufficient space is available to store the new strings.

See Also

»CWnd::DlgDirList«, LB_DIR, »CFile::GetStatus«


  CListBox::DrawItem

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

lpDrawItemStruct    A long pointer to a DrawItemStruct structure that contains information about the type of drawing required.

Remarks

Called by the framework when a visual aspect of an owner-draw list box changes. The member of the DrawItemStruct structure defines the drawing action that is to be performed.

By default, this member function does nothing. Override this member function to implement drawing for an owner-draw CListBox object. The application should restore all graphics device interface (GDI) objects selected for the display context supplied in lpDrawItemStruct before this member function terminates.

See »CWnd::OnDrawItem« for a description of the DRAWITEMSTRUCT structure.

See Also

»CListBox::CompareItem«, »CWnd::OnDrawItem«, ::DrawItem, »CListBox::MeasureItem«, »CListBox::DeleteItem«


  CListBox::FindString

int FindString( int nStartAfter, LPCSTR lpszItem ) const;

nStartAfter    Contains the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nStartAfter. If nStartAfter is −1, the entire list box is searched from the beginning.

lpszItem    Points to the null-terminated string that contains the prefix to search for. The search is case independent, so this string may contain any combination of uppercase and lowercase letters.

Remarks

Finds the first string in a list box that contains the specified prefix without changing the list-box selection. Use the »SelectString« member function to both find and select a string.

Return Value

The zero-based index of the matching item, or LB_ERR if the search was unsuccessful.

See Also

»CListBox::SelectString«, »CListBox::AddString«, »CListBox::InsertString«, LB_FINDSTRING


  CListBox::FindStringExact

Windows 3.1 Only

int FindStringExact( int nIndexStart, LPCSTR lpszFind ) const; ♦

nIndexStart    Specifies the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nIndexStart. If nIndexStart is −1, the entire list box is searched from the beginning.

lpszFind    Points to the null-terminated string to search for. This string can contain a complete filename, including the extension. The search is not case sensitive, so the string can contain any combination of uppercase and lowercase letters.

Remarks

An application calls the FindStringExact member function to find the first list-box string that matches the string specified in lpszFind.

If the list box was created with an owner-draw style but without the »LBS_HASSTRINGS« style, the FindStringExact member function attempts to match the doubleword value against the value of lpszFind.

Return Value

The index of the matching item, or LB_ERR if the search was unsuccessful.

See Also

»CListBox::FindString«, LB_FINDSTRING, LB_FINDSTRINGEXACT


  CListBox::GetCaretIndex

Windows 3.1 Only

int GetCaretIndex() const; ♦

Remarks

An application calls the GetCaretIndex member function to determine the index of the item that has the focus rectangle in a multiple-selection list box. The item may or may not be selected.

Return Value

The zero-based index of the item that has the focus rectangle in a list box. If the list box is a single-selection list box, the return value is the index of the item that is selected, if any.

See Also

»CListBox::SetCaretIndex«, LB_GETCARETINDEX


  CListBox::GetCount

int GetCount() const;

Remarks

Retrieves the number of items in a list box.

The returned count is one greater than the index value of the last item (the index is zero-based).

Return Value

The number of items in the list box, or LB_ERR if an error occurs.

See Also

LB_GETCOUNT


  CListBox::GetCurSel

int GetCurSel() const;

Remarks

Retrieves the zero-based index of the currently selected item, if any, in a single-selection list box.

GetCurSel should not be called for a multiple-selection list box.

Return Value

The zero-based index of the currently selected item. It is LB_ERR if no item is currently selected or if the list box is a multiple-selection list box.

See Also

LB_GETCURSEL, »CListBox::SetCurSel«


  CListBox::GetHorizontalExtent

int GetHorizontalExtent() const;

Remarks

Retrieves from a list box the width in pixels by which the list box can be scrolled horizontally if the list box has horizontal scroll bars.

To respond to GetHorizontalExtent, the list box must have been defined with the »WS_HSCROLL« style.

Return Value

The scrollable width of the list box, in pixels.

See Also

»CListBox::SetHorizontalExtent«, LB_GETHORIZONTALEXTENT


  CListBox::GetItemData

DWORD GetItemData( int nIndex ) const;

nIndex    Specifies the zero-based index of the item in the list box.

Remarks

Retrieves the application-supplied doubleword value associated with the specified list-box item.

The doubleword value was the dwItemData parameter of a »SetItemData« call.

Return Value

The 32-bit value associated with the item, or LB_ERR if an error occurs.

See Also

»CListBox::AddString«, »CListBox::GetItemDataPtr«, »CListBox::SetItemDataPtr«, »CListBox::InsertString«, »CListBox::SetItemData«, LB_GETITEMDATA


  CListBox::GetItemDataPtr

void* GetItemDataPtr( int nIndex ) const;

nIndex    Specifies the zero-based index of the item in the list box.

Remarks

Retrieves the application-supplied 32-bit value associated with the specified list-box item as a pointer (void*).

Return Value

Retrieves a pointer, or −1 if an error occurs.

See Also

»CListBox::AddString«, »CListBox::GetItemData«, »CListBox::InsertString«, »CListBox::SetItemData«, LB_GETITEMDATA


  CListBox::GetItemHeight

Windows 3.1 Only

int GetItemHeight( int nIndex ) const; ♦

nIndex    Specifies the zero-based index of the item in the list box. This parameter is used only if the list box has the LBS_OWNERDRAWVARIABLE style; otherwise, it should be set to 0.

Remarks

An application calls the GetItemHeight member function to determine the height of items in a list box.

Return Value

The height, in pixels, of the items in the list box. If the list box has the LBS_OWNERDRAWVARIABLE style, the return value is the height of the item specified by nIndex. If an error occurs, the return value is LB_ERR.

See Also

LB_GETITEMHEIGHT, »CListBox::SetItemHeight«


  CListBox::GetItemRect

int GetItemRect( int nIndex, LPRECT lpRect ) const;

nIndex    Specifies the zero-based index of the item.

lpRect    Specifies a long pointer to a RECT data structure that receives the list-box client coordinates of the item.

Remarks

Retrieves the dimensions of the rectangle that bounds a list-box item as it is currently displayed in the list-box window.

Return Value

LB_ERR if an error occurs.

See Also

LB_GETITEMRECT


  CListBox::GetSel

int GetSel( int nIndex ) const;

nIndex    Specifies the zero-based index of the item.

Remarks

Retrieves the selection state of an item. This member function works with both single- and multiple-selection list boxes.

Return Value

A positive number if the specified item is selected; otherwise, it is 0. The return value is LB_ERR if an error occurs.

See Also

LB_GETSEL, »CListBox::SetSel«


  CListBox::GetSelCount

int GetSelCount() const;

Remarks

Retrieves the total number of selected items in a multiple-selection list box.

Return Value

The count of selected items in a list box. If the list box is a single-selection list box, the return value is LB_ERR.

See Also

»CListBox::SetSel«, LB_GETSELCOUNT


  CListBox::GetSelItems

int GetSelItems( int nMaxItems, LPINT rgIndex ) const;

nMaxItems    Specifies the maximum number of selected items whose item numbers are to be placed in the buffer.

rgIndex    Specifies a long pointer to a buffer large enough for the number of integers specified by nMaxItems.

Remarks

Fills a buffer with an array of integers that specifies the item numbers of selected items in a multiple-selection list box.

Return Value

The actual number of items placed in the buffer. If the list box is a single-selection list box, the return value is LB_ERR.

See Also

LB_GETSELITEMS


  CListBox::GetText

int GetText( int nIndex, LPSTR lpszBuffer ) const;

void GetText( int nIndex, CString& rString ) const;

nIndex    Specifies the zero-based index of the string to be retrieved.

lpszBuffer    Points to the buffer that receives the string. The buffer must have sufficient space for the string and a terminating null character. The size of the string can be determined ahead of time by calling the GetTextLen member function.

rString    A reference to a CString object.

Remarks

Gets a string from a list box. The second form of this member function fills a CString object with the string text.

Return Value

The length (in bytes) of the string, excluding the terminating null character. If nIndex does not specify a valid index, the return value is LB_ERR.

See Also

»CListBox::GetTextLen«, LB_GETTEXT


  CListBox::GetTextLen

int GetTextLen( int nIndex ) const;

nIndex    Specifies the zero-based index of the string.

Remarks

Gets the length of a string in a list-box item.

Return Value

The length of the string in bytes, excluding the terminating null character. If nIndex does not specify a valid index, the return value is LB_ERR.

See Also

»CListBox::GetText«, LB_GETTEXTLEN


  CListBox::GetTopIndex

int GetTopIndex() const;

Remarks

Retrieves the zero-based index of the first visible item in a list box. Initially, item 0 is at the top of the list box, but if the list box is scrolled, another item may be at the top.

Return Value

The zero-based index of the first visible item in a list box.

See Also

»CListBox::SetTopIndex«, LB_GETTOPINDEX


  CListBox::InsertString

int InsertString( int nIndex, LPCSTR lpszItem );

nIndex    Specifies the zero-based index of the position to insert the string. If this parameter is −1, the string is added to the end of the list.

lpszItem    Points to the null-terminated string that is to be inserted.

Remarks

Inserts a string into the list box. Unlike the »AddString« member function, InsertString does not cause a list with the »LBS_SORT« style to be sorted.

Return Value

The zero-based index of the position at which the string was inserted. The return value is LB_ERR if an error occurs; the return value is LB_ERRSPACE if insufficient space is available to store the new string.

See Also

»CListBox::AddString«, LB_INSERTSTRING


  CListBox::MeasureItem

virtual void MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct );

lpMeasureItemStruct    A long pointer to a MEASUREITEMSTRUCT structure.

Remarks

Called by the framework when a list box with an owner-draw style is created.

By default, this member function does nothing. Override this member function and fill in the MEASUREITEMSTRUCT structure to inform Windows of the list-box dimensions. If the list box is created with the LBS_OWNERDRAWVARIABLE style, the framework calls this member function for each item in the list box. Otherwise, this member is called only once.

For further information about using the OWNERDRAWFIXED style in an owner-draw list box created with the SubclassDlgItem member function of CWnd, see the discussion in Technical Note 14 in MSVCNT\HELP\MFCNOTES.HLP.

See »CWnd::OnMeasureItem« for a description of the MEASUREITEMSTRUCT structure.

See Also

»CListBox::CompareItem«, »CWnd::OnMeasureItem«, »CListBox::DrawItem«, ::MeasureItem, »CListBox::DeleteItem«


  CListBox::ResetContent

void ResetContent();

Remarks

Removes all items from a list box.

See Also

LB_RESETCONTENT


  CListBox::SelectString

int SelectString( int nStartAfter, LPCSTR lpszItem );

nStartAfter    Contains the zero-based index of the item before the first item to be searched. When the search reaches the bottom of the list box, it continues from the top of the list box back to the item specified by nStartAfter. If nStartAfter is −1, the entire list box is searched from the beginning.

lpszItem    Points to the null-terminated string that contains the prefix to search for. The search is case independent, so this string may contain any combination of uppercase and lowercase letters.

Remarks

Searches for a list-box item that matches the specified string, and if a matching item is found, it selects the item.

The list box is scrolled, if necessary, to bring the selected item into view.

This member function cannot be used with a list box that has the »LBS_MULTIPLESEL« style.

An item is selected only if its initial characters (from the starting point) match the characters in the string specified by lpszItem.

Use the FindString member function to find a string without selecting the item.

Return Value

The index of the selected item if the search was successful. If the search was unsuccessful, the return value is LB_ERR and the current selection is not changed.

See Also

»CListBox::FindString«, LB_SELECTSTRING


  CListBox::SelItemRange

int SelItemRange( BOOL bSelect, int nFirstItem, int nLastItem );

bSelect    Specifies how to set the selection. If bSelect is TRUE, the string is selected and highlighted; if FALSE, the highlight is removed and the string is no longer selected.

nFirstItem    Specifies the zero-based index of the first item to set.

nLastItem    Specifies the zero-based index of the last item to set.

Remarks

Selects one or more consecutive items in a multiple-selection list box.

Use this member function only with multiple-selection list boxes.

Return Value

LB_ERR if an error occurs.

See Also

LB_SELITEMRANGE, »CListBox::GetSelItems«


  CListBox::SetCaretIndex

Windows 3.1 Only

int SetCaretIndex( int nIndex, BOOL bScroll = TRUE ); ♦

nIndex    Specifies the zero-based index of the item to receive the focus rectangle in the list box.

bScroll    If this value is 0, the item is scrolled until it is fully visible. If this value is not 0, the item is scrolled until it is at least partially visible.

Remarks

An application calls the SetCaretIndex member function to set the focus rectangle to the item at the specified index in a multiple-selection list box. If the item is not visible, it is scrolled into view.

Return Value

LB_ERR if an error occurs.

See Also

»CListBox::GetCaretIndex«, LB_SETCARETINDEX


  CListBox::SetColumnWidth

void SetColumnWidth( int cxWidth );

cxWidth    Specifies the width in pixels of all columns.

Remarks

Sets the width in pixels of all columns in a multicolumn list box (created with the »LBS_MULTICOLUMN« style).

See Also

LB_SETCOLUMNWIDTH


  CListBox::SetCurSel

int SetCurSel( int nSelect );

nSelect    Specifies the zero-based index of the string to be selected. If nSelect is −1, the list box is set to have no selection.

Remarks

Selects a string and scrolls it into view, if necessary. When the new string is selected, the list box removes the highlight from the previously selected string.

Use this member function only with single-selection list boxes. It cannot be used to set or remove a selection in a multiple-selection list box.

Return Value

LB_ERR if an error occurs.

See Also

LB_SETCURSEL, »CListBox::GetCurSel«


  CListBox::SetHorizontalExtent

void SetHorizontalExtent( int cxExtent );

cxExtent    Specifies the number of pixels by which the list box can be scrolled horizontally.

Remarks

Sets the width, in pixels, by which a list box can be scrolled horizontally. If the size of the list box is smaller than this value, the horizontal scroll bar will horizontally scroll items in the list box. If the list box is as large or larger than this value, the horizontal scroll bar is hidden.

To respond to a call to SetHorizontalExtent, the list box must have been defined with the »WS_HSCROLL« style.

This member function is not useful for multicolumn listboxes. For multicolumn list boxes, call the SetColumnWidth member function.

See Also

»CListBox::GetHorizontalExtent«, LB_SETHORIZONTALEXTENT


  CListBox::SetItemData

int SetItemData( int nIndex, DWORD dwItemData );

nIndex    Specifies the zero-based index of the item.

dwItemData    Specifies the value to be associated with the item.

Remarks

Sets a 32-bit value associated with the specified item in a list box.

Return Value

LB_ERR if an error occurs.

See Also

»CListBox::SetItemDataPtr«, »CListBox::GetItemData«, LB_SETITEMDATA


  CListBox::SetItemDataPtr

int SetItemDataPtr( int nIndex, void* pData );

nIndex    Specifies the zero-based index of the item.

pData    Specifies the pointer to be associated with the item.

Remarks

Sets the 32-bit value associated with the specified item in a combo box to be the specified pointer (void*).

Return Value

LB_ERR if an error occurs.

See Also

»CListBox::SetItemData«, »CListBox::GetItemData«, »CListBox::GetItemDataPtr«, LB_SETITEMDATA


  CListBox::SetItemHeight

Windows 3.1 Only

int SetItemHeight( int nIndex, UINT cyItemHeight ); ♦

nIndex    Specifies the zero-based index of the item in the list box. This parameter is used only if the list box has the LBS_OWNERDRAWVARIABLE style; otherwise, it should be set to 0.

cyItemHeight    Specifies the height, in pixels, of the item.

Remarks

An application calls the SetItemHeight member function to set the height of items in a list box. If the list box has the »LBS_OWNERDRAWVARIABLE« style, this function sets the height of the item specified by nIndex. Otherwise, this function sets the height of all items in the list box.

Return Value

LB_ERR if the index or height is invalid.

See Also

»CListBox::GetItemHeight«, LB_SETITEMHEIGHT


  CListBox::SetSel

int SetSel( int nIndex, BOOL bSelect = TRUE );

nIndex    Contains the zero-based index of the string to be set. If −1, the selection is added to or removed from all strings, depending on the value of bSelect.

bSelect    Specifies how to set the selection. If bSelect is TRUE, the string is selected and highlighted; if FALSE, the highlight is removed and the string is no longer selected. The specified string is selected and highlighted by default.

Remarks

Selects a string in a multiple-selection list box.

Use this message only with multiple-selection list boxes.

Return Value

LB_ERR if an error occurs.

See Also

»CListBox::GetSel«, LB_SETSEL


  CListBox::SetTabStops

void SetTabStops();

BOOL SetTabStops( const int& cxEachStop );

BOOL SetTabStops( int nTabStops, LPINT rgTabStops );

cxEachStop    Tab stops are set at every cxEachStop dialog units. See rgTabStops  for a description of a dialog unit.

nTabStops    Specifies the number of tab stops to have in the list box.

rgTabStops    Points to the first member of an array of integers containing the tab-stop positions in dialog units. A dialog unit is a horizontal or vertical distance. One horizontal dialog unit is equal to one-fourth of the current dialog base width unit, and 1 vertical dialog unit is equal to one-eighth of the current dialog base height unit. The dialog base units are computed based on the height and width of the current system font. The GetDialogBaseUnits Windows function returns the current dialog base units in pixels. The tab stops must be sorted in increasing order; back tabs are not allowed.

Remarks

Sets the tab-stop positions in a list box.

To set tab stops to the default size of 2 dialog units, call the parameterless version of this member function. To set tab stops to a size other than 2, call the version with the cxEachStop argument.

To set tab stops to an array of sizes, use the version with the rgTabStops and nTabStops arguments. A tab stop will be set for each value in rgTabStops, up to the number specified by nTabStops.

To respond to a call to the SetTabStops member function, the list box must have been created with the »LBS_USETABSTOPS« style.

Return Value

Nonzero if all the tabs were set; otherwise 0.

See Also

LB_SETTABSTOPS, ::GetDialogBaseUnits


  CListBox::SetTopIndex

int SetTopIndex( int nIndex );

nIndex    Specifies the zero-based index of the list-box item.

Remarks

Ensures that a particular list-box item is visible.

The system scrolls the list box until either the list-box item appears at the top of the list box or the maximum scroll range has been reached.

Return Value

LB_ERR if an error occurs.

See Also

»CListBox::GetTopIndex«, LB_SETTOPINDEX


CMapPtrToPtr
  class CMapPtrToPtr : public CObject

The CMapPtrToPtr class supports maps of void pointers keyed by void pointers.

The member functions of CMapPtrToPtr are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a pointer to void. Wherever you see a CString or a const pointer to char as a function parameter or return value, substitute a pointer to void.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapPtrToPtr::Lookup( void* <key>, void*& <rValue> ) const;

CMapPtrToPtr incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual map elements (pointer values), you must set the depth of the dump context to 1 or greater.

Pointer-to-pointer maps may not be serialized.

When a CMapPtrToPtr object is deleted, or when its elements are removed, only the pointers are removed, not the entities they reference.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapPtrToPtr Class Members
  Class Members

Construction/Destruction — Public Members

»CMapPtrToPtr«	Constructs a collection that maps void pointers to void pointers.
Operations — Public Members

»Lookup«	Looks up a void pointer based on the void pointer key. The pointer value, not the entity it points to, is used for the key comparison.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator [ ]«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapPtrToWord
  class CMapPtrToWord : public CObject

The CMapPtrToWord class supports maps of 16-bit words keyed by void pointers.

The member functions of CMapPtrToWord are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute WORD. Wherever you see a CString or a const pointer to char as a function parameter or return value, substitute a pointer to void.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapPtrToWord::Lookup( const void* <key>, WORD& <rValue> ) const;

CMapWordToPtr incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual map elements, you must set the depth of the dump context to 1 or greater.

Pointer-to-word maps may not be serialized.

When a CMapPtrToWord object is deleted, or when its elements are removed, the pointers and the words are removed. The entities referenced by the key pointers are not removed.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapPtrToWord Class Members
  Class Members

Construction/Destruction — Public Members

»CMapPtrToWord«	Constructs a collection that maps void pointers to 16-bit words.
Operations — Public Members

»Lookup«	Returns a WORD using a void pointer as a key. The pointer value, not the entity it points to, is used for the key comparison.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapStringToOb
  class CMapStringToOb : public CObject

CMapStringToOb is a dictionary collection class that maps unique CString objects to CObject pointers. Once you have inserted a CString-CObject* pair (element) into the map, you can efficiently retrieve or delete the pair using a string or a CString value as a key. You can also iterate over all the elements in the map.

A variable of type POSITION is used for alternate entry access in all map variations. You can use a POSITION to "remember" an entry and to iterate through the map. You might think that this iteration is sequential by key value; it is not. The sequence of retrieved elements is indeterminate.

CMapStringToOb incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. Each element is serialized in turn if a map is stored to an archive, either with the overloaded insertion (<<) operator or with the Serialize member function.

If you need a diagnostic dump of the individual elements in the map (the CString value and the CObject contents), you must set the depth of the dump context to 1 or greater.

When a CMapStringToOb object is deleted, or when its elements are removed, the CString objects and the CObject pointers are removed. The objects referenced by the CObject pointers are not destroyed.

Map class derivation is similar to list derivation. See the the Class Library User's Guide for an illustration of the derivation of a special-purpose list class.

#include <afxcoll.h>

See Also

»CMapPtrToPtr«, »CMapPtrToWord«, »CMapStringToPtr«, »CMapStringToString«, »CMapWordToOb«, »CMapWordToPtr«


CMapStringToOb Class Members
  Class Members

Construction/Destruction — Public Members

»CMapStringToOb«	Constructs a collection that maps CString values to CObject pointers.
Operations — Public Members

»Lookup«	Returns a CObject pointer based on a CString value.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapStringToOb Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMapStringToOb::CMapStringToOb

CMapStringToOb( int nBlockSize = 10 );

nBlockSize    Specifies the memory-allocation granularity for extending the map.

Remarks

Constructs an empty CString-to-CObject* map. As the map grows, memory is allocated in units of nBlockSize entries.

 Example

// example for CMapStringToOb::CMapStringToOb

See »CObList::CObList« for a listing of the CAge class used in all collection examples.

CMapStringToOb map(20);  // Map on the stack with blocksize of 20

CMapStringToOb* pm = new CMapStringToOb;  // Map on the heap
                                          // with default blocksize


  CMapStringToOb::GetCount

int GetCount() const;

Return Value

The number of elements in this map.

See Also

»CMapStringToOb::IsEmpty«

 Example

// example for CMapStringToOb::GetCount

CMapStringToOb map;

map.SetAt( "Bart", new CAge( 13 ) );
map.SetAt( "Homer", new CAge( 36 ) );
ASSERT( map.GetCount() == 2 );


  CMapStringToOb::GetNextAssoc

void GetNextAssoc( POSITION& rNextPosition, CString& rKey,
CObject*& rValue ) const;

rNextPosition    Specifies a reference to a POSITION value returned by a previous GetNextAssoc or GetStartPosition call.

rKey    Specifies the returned key of the retrieved element (a string).

rValue    Specifies the returned value of the retrieved element (a CObject pointer).

Remarks

Retrieves the map element at rNextPosition, then updates rNextPosition to refer to the next element in the map. This function is most useful for iterating through all the elements in the map. Note that the position sequence is not necessarily the same as the key value sequence.

If the retrieved element is the last in the map, then the new value of rNextPosition is set to NULL.

See Also

»CMapStringToOb::GetStartPosition«

 Example

// example for CMapStringToOb::GetNextAssoc

CMapStringToOb map;
POSITION pos;
CString key;
CAge* pa;

map.SetAt( "Bart", new CAge( 13 ) );
map.SetAt( "Lisa", new CAge( 11 ) );
map.SetAt( "Homer", new CAge( 36 ) );
map.SetAt( "Marge", new CAge( 35 ) );
// Iterate through the entire map, dumping both name and age.
for( pos = map.GetStartPosition(); pos != NULL; )
{
map.GetNextAssoc( pos, key, pa );
#ifdef _DEBUG
afxDump << key << " : " << pa << "\n";
#endif
}

The results from this program are as follows:

Lisa : a CAge at $4724 11
Marge : a CAge at $47A8 35
Homer : a CAge at $4766 36
Bart : a CAge at $45D4 13


  CMapStringToOb::GetStartPosition

POSITION GetStartPosition() const;

Remarks

Starts a map iteration by returning a POSITION value that can be passed to a GetNextAssoc call. The iteration sequence is not predictable; therefore, the "first element in the map" has no special significance.

 Example

See the example for the member function »GetNextAssoc«.


  CMapStringToOb::IsEmpty

BOOL IsEmpty() const;

Return Value

Nonzero if this map contains no elements; otherwise 0.

See Also

»CMapStringToOb::GetCount«

 Example

See the example for »RemoveAll«.


  CMapStringToOb::Lookup

BOOL Lookup( const char* key, CObject*& rValue ) const;

key    Specifies the string key that identifies the element to be looked up.

rValue    Specifies the returned value from the looked-up element.

Remarks

Lookup uses a hashing algorithm to quickly find the map element with a key that matches exactly (CString value).

Return Value

Nonzero if the element was found; otherwise 0.

See Also

»CMapStringToOb::operator []«

 Example

// example for CMapStringToOb::LookUp

CMapStringToOb map;
CAge* pa;

map.SetAt( "Bart", new CAge( 13 ) );
map.SetAt( "Lisa", new CAge( 11 ) );
map.SetAt( "Homer", new CAge( 36 ) );
map.SetAt( "Marge", new CAge( 35 ) );
ASSERT( map.Lookup( "Lisa", ( CObject*& ) pa ) ); // Is "Lisa" in the map?
ASSERT( *pa ==  CAge( 11 ) ); // Is she 11?


  CMapStringToOb::RemoveAll

void RemoveAll();

Remarks

Removes all the elements from this map and destroys the CString key objects. The CObject objects referenced by each key are not destroyed. The RemoveAll function can cause memory leaks if you do not ensure that the referenced CObject objects are destroyed.

The function works correctly if the map is already empty.

See Also

»CMapStringToOb::RemoveKey«

 Example

// example for CMapStringToOb::RemoveAll

{
CMapStringToOb map;

CAge age1( 13 ); // Two objects on the stack
CAge age2( 36 );
map.SetAt( "Bart", &age1 );
map.SetAt( "Homer", &age2 );
ASSERT( map.GetCount() == 2 );
map.RemoveAll(); // CObject pointers removed; objects not removed.
ASSERT( map.GetCount() == 0 );
ASSERT( map.IsEmpty() );
} // The two CAge objects are deleted when they go out of scope.


  CMapStringToOb::RemoveKey

BOOL RemoveKey( const char* key );

key    Specifies the string used for map lookup.

Remarks

Looks up the map entry corresponding to the supplied key; then, if the key is found, removes the entry. This can cause memory leaks if the CObject object is not deleted elsewhere.

Return Value

Nonzero if the entry was found and successfully removed; otherwise 0.

See Also

»CMapStringToOb::RemoveAll«

 Example

// example for CMapStringToOb::RemoveKey

CMapStringToOb map;

map.SetAt( "Bart", new CAge( 13 ) );
map.SetAt( "Lisa", new CAge( 11 ) );
map.SetAt( "Homer", new CAge( 36 ) );
map.SetAt( "Marge", new CAge( 35 ) );
map.RemoveKey( "Lisa" ); // Memory leak: CAge object not
                         // deleted.
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "RemoveKey example: " << &map << "\n";
#endif

The results from this program are as follows:

RemoveKey example: A CMapStringToOb with 3 elements
    [Marge] = a CAge at $49A0 35
    [Homer] = a CAge at $495E 36
    [Bart] = a CAge at $4634 13


  CMapStringToOb::SetAt

void SetAt( const char* key, CObject* newValue )
throw( CMemoryException );

key    Specifies the string that is the key of the new element.

newValue    Specifies the CObject pointer that is the value of the new element.

Remarks

The primary means to insert an element in a map. First, the key is looked up. If the key is found, then the corresponding value is changed; otherwise a new key-value element is created.

See Also

»CMapStringToOb::Lookup«, »CMapStringToOb::operator []«

 Example

// example for CMapStringToOb::SetAt

CMapStringToOb map;
CAge* pa;

map.SetAt( "Bart", new CAge( 13 ) );
map.SetAt( "Lisa", new CAge( 11 ) ); // Map contains 2
                                     // elements.
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "before Lisa's birthday: " << &map << "\n";
#endif
if( map.Lookup( "Lisa", pa ) )
{ // CAge 12 pointer replaces CAge 11 pointer.
map.SetAt( "Lisa", new CAge( 12 ) );
delete pa;  // Must delete CAge 11 to avoid memory leak.
}
#ifdef _DEBUG
afxDump << "after Lisa's birthday: " << &map << "\n";
#endif

The results from this program are as follows:

before Lisa's birthday: A CMapStringToOb with 2 elements
    [Lisa] = a CAge at $493C 11
    [Bart] = a CAge at $4654 13
after Lisa's birthday: A CMapStringToOb with 2 elements
    [Lisa] = a CAge at $49C0 12
    [Bart] = a CAge at $4654 13


CMapStringToOb Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CMapStringToOb::operator [ ]

CObject*& operator []( const char* key );

Remarks

This operator is a convenient substitute for the SetAt member function. Thus it can be used only on the left side of an assignment statement (an l-value). If there is no map element with the specified key, then a new element is created.

There is no "right side" (r-value) equivalent to this operator because there is a possibility that a key may not be found in the map. Use the Lookup member function for element retrieval.

See Also

»CMapStringToOb::SetAt«, »CMapStringToOb::Lookup«

 Example

// example for CMapStringToOb::operator[]

CMapStringToOb map;

map["Bart"] = new CAge( 13 );
map["Lisa"] = new CAge( 11 );
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "Operator [] example: " << &map << "\n";
#endif

The results from this program are as follows:

Operator [] example: A CMapStringToOb with 2 elements
    [Lisa] = a CAge at $4A02 11
    [Bart] = a CAge at $497E 13


CMapStringToPtr
  class CMapStringToPtr : public CObject

The CMapStringToPtr class supports maps of void pointers keyed by CString objects.

The member functions of CMapStringToPtr are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a pointer to void.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapStringToPtr::Lookup( const char* <key>, void*& <rValue> )
                              const;

CMapStringToPtr incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual map elements, you must set the depth of the dump context to 1 or greater.

String-to-pointer maps may not be serialized.

When a CMapStringToPtr object is deleted, or when its elements are removed, the CString key objects and the words are removed.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapStringToPtr Class Members
  Class Members

Construction/Destruction — Public Members

»CMapStringToPtr«	Constructs a collection that maps CString objects to void pointers.
Operations — Public Members

»Lookup«	Returns a void pointer based on a CString value.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapStringToString
  class CMapStringToString : public CObject

The CMapStringToString class supports maps of CString objects keyed by CString objects.

The member functions of CMapStringToString are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CObject pointer as a return value or "output" function parameter, substitute a pointer to char. Wherever you see a CObject pointer as an "input" function parameter, substitute a pointer to char.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapStringToString::Lookup( const char* <key>,
                                 CString& <rValue> ) const;

CMapStringToString incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. Each element is serialized in turn if a map is stored to an archive, either with the overloaded insertion (<<) operator or with the Serialize member function.

If you need a dump of individual CString-CString elements, you must set the depth of the dump context to 1 or greater.

When a CMapStringToString object is deleted, or when its elements are removed, the CString objects are removed as appropriate.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapStringToString Class Members
  Class Members

Construction/Destruction — Public Members

»CMapStringToString«	Constructs a collection that maps CString objects to CString objects.
Operations — Public Members

»Lookup«	Returns a CString using a CString value as a key.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapWordToOb
  class CMapWordToOb : public CObject

The CMapWordToOb class supports maps of CObject pointers keyed by 16-bit words.

The member functions of CMapWordToOb are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CString or a const pointer to char as a function parameter or return value, substitute WORD.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapWordToOb::Lookup( WORD <key>, CObject*& <rValue> ) const;

CMapWordToOb incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. Each element is serialized in turn if a map is stored to an archive, either with the overloaded insertion (<<) operator or with the Serialize member function.

If you need a dump of individual WORD-CObject elements, you must set the depth of the dump context to 1 or greater.

When a CMapWordToOb object is deleted, or when its elements are removed, the CObject objects are deleted as appropriate.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapWordToOb Class Members
  Class Members

Construction/Destruction — Public Members

»CMapWordToOb«	Constructs a collection that maps words to CObject pointers.
Operations — Public Members

»Lookup«	Returns a CObject pointer using a word value as a key.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMapWordToPtr
  class CMapWordToPtr : public CObject

The CMapWordToPtr class supports maps of void pointers keyed by 16-bit words.

The member functions of CMapWordToPtr are similar to the member functions of class »CMapStringToOb«. Because of this similarity, you can use the CMapStringToOb reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a pointer to void. Wherever you see a CString or a const pointer to char as a function parameter or return value, substitute WORD.

BOOL CMapStringToOb::Lookup( const char* <key>,
                             CObject*& <rValue> ) const;

for example, translates to

BOOL CMapWordToPtr::Lookup( WORD <key>, void*& <rValue> ) const;

CMapWordToPtr incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual map elements, you must set the depth of the dump context to 1 or greater.

Word-to-pointer maps may not be serialized.

When a CMapWordToPtr object is deleted, or when its elements are removed, the words and the pointers are removed. The entities referenced by the pointers are not removed.

#include <afxcoll.h>

See Also

»CMapStringToOb«


CMapWordToPtr Class Members
  Class Members

Construction/Destruction — Public Members

»CMapWordToPtr«	Constructs a collection that maps words to void pointers.
Operations — Public Members

»Lookup«	Returns a void pointer using a word value as a key.
»SetAt«	Inserts an element into the map; replaces an existing element if a matching key is found.
»operator []«	Inserts an element into the map — operator substitution for SetAt.
»RemoveKey«	Removes an element specified by a key.
»RemoveAll«	Removes all the elements from this map.
»GetStartPosition«	Returns the position of the first element.
»GetNextAssoc«	Gets the next element for iterating.
Status — Public Members

»GetCount«	Returns the number of elements in this map.
»IsEmpty«	Tests for the empty-map condition (no elements).


CMDIChildWnd
  class CMDIChildWnd : public CFrameWnd

The CMDIChildWnd class provides the functionality of a Windows multiple document interface (MDI) child window, along with members for managing the window.

An MDI child window looks much like a typical frame window, except that the MDI child window appears inside an MDI frame window rather than on the desktop. An MDI child window does not have a menu bar of its own, but instead shares the menu of the MDI frame window. The framework automatically changes the MDI frame menu to represent the currently active MDI child window.

To create a useful MDI child window for your application, derive a class from CMDIChildWnd. Add member variables to the derived class to store data specific to your application. Implement message-handler member functions and a message map in the derived class to specify what happens when messages are directed to the window.

There are three ways to construct an MDI child window:

•	Directly construct it using Create.

•	Directly construct it using LoadFrame.

•	Indirectly construct it through a document template.

Before you call Create or LoadFrame, you must construct the frame-window object on the heap using the C++ new operator. Before calling Create you may also register a window class with the AfxRegisterWndClass global function to set the icon and class styles for the frame.

Use the Create member function to pass the frame's creation parameters as immediate arguments.

LoadFrame requires fewer arguments than Create, and instead retrieves most of its default values from resources, including the frame's caption, icon, accelerator table, and menu. To be accessible by LoadFrame, all these resources must have the same resource ID (for example, IDR_MAINFRAME).

When a CMDIChildWnd object contains views and documents, they are created indirectly by the framework instead of directly by the programmer. The CDocTemplate object orchestrates the creation of the frame, the creation of the containing views, and the connection of the views to the appropriate document. The parameters of the CDocTemplate constructor specify the CRuntimeClass of the three classes involved (document, frame, and view). A CRuntimeClass object is used by the framework to dynamically create new frames when specified by the user (for example, by using the File New command or the MDI Window New command).

A frame-window class derived from CMDIChildWnd must be declared with DECLARE_DYNCREATE in order for the above RUNTIME_CLASS mechanism to work correctly.

The CMDIChildWnd class inherits much of its default implementation from CFrameWnd. For a detailed list of these features, please refer to the CFrameWnd class description. The CMDIChildWnd class has the following additional features:

•	In conjunction with the CMultiDocTemplate class, multiple CMDIChildWnd objects from the same document template share the same menu, saving Windows system resources.

•	The currently active MDI child window menu entirely replaces the MDI frame window's menu, and the caption of the currently active MDI child window is added to the MDI frame window's caption. For further examples of MDI child window functions that are implemented in conjunction with an MDI frame window, see the CMDIFrameWnd class description.

Do not use the C++ delete operator to destroy a frame window. Use CWnd::DestroyWindow instead. The CFrameWnd implementation of PostNcDestroy will delete the C++ object when the window is destroyed. When the user closes the frame window, the default OnClose handler will call DestroyWindow.

#include <afxwin.h>

See Also

»CWnd«, »CFrameWnd«, »CMDIFrameWnd«


CMDIChildWnd Class Members
  Class Members

Construction/Destruction — Public Members

»CMDIChildWnd«	Constructs a CMDIChildWnd object.
Initialization — Public Members

»Create«	Creates the Windows MDI child window associated with the CMDIChildWnd object.
Operations — Public Members

»MDIDestroy«	Destroys this MDI child window.
»MDIActivate«	Activates this MDI child window.
»MDIMaximize«	Maximizes this MDI child window.
»MDIRestore«	Restores this MDI child window from maximized or minimized size.
»GetMDIFrame«	Returns the parent MDI frame of the MDI client window.


CMDIChildWnd Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMDIChildWnd::CMDIChildWnd

CMDIChildWnd();

Remarks

Call to construct a CMDIChildWnd object. Call Create to create the visible window.

See Also

»CMDIChildWnd::Create«


  CMDIChildWnd::Create

BOOL Create( LPCSTR lpszClassName, LPCSTR lpszWindowName,
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault, CMDIFrameWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );

lpszClassName    Points to a null-terminated character string that names the Windows class (a WNDCLASS structure). The class name can be any name registered with the AfxRegisterWndClass global function. Should be NULL for a standard CMDIChildWnd.

lpszWindowName    Points to a null-terminated character string that represents the window name. Used as text for the title bar.

dwStyle    Specifies the window »style« attributes. The WS_CHILD style is required.

rect    Contains the size and position of the window. The rectDefault value allows Windows to specify the size and position of the new CMDIChildWnd.

pParentWnd    Specifies the window's parent. If NULL, the main application window is used.

pContext    Specifies a CCreateContext structure. This parameter can be NULL.

Remarks

Call this member function to create a Windows MDI child window and attach it to the CMDIChildWnd object.

The currently active MDI child frame window can determine the caption of the parent frame window. This feature is disabled by turning off the FWS_ADDTOTITLE style bit of the child frame window.

The framework calls this member function in response to a user command to create a child window, and the framework uses the pContext parameter to properly connect the child window to the application. When you call Create, pContext may be NULL.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CMDIChildWnd::CMDIChildWnd«, »CWnd::PreCreateWindow«


  CMDIChildWnd::GetMDIFrame

CMDIFrameWnd* GetMDIFrame();

Remarks

Call this function to return the MDI parent frame. The frame returned is two parents removed from the CMDIChildWnd and is the parent of the window of type MDICLIENT that manages the CMDIChildWnd object. Call the »GetParent« member function to return the CMDIChildWnd object's immediate MDICLIENT parent as a temporary CWnd pointer.

See Also

»CWnd::GetParent«


  CMDIChildWnd::MDIActivate

void MDIActivate();

Remarks

Call this member function to activate an MDI child window independently of the MDI frame window. When the frame becomes active, the child window that was last activated will be activated as well.

See Also

»CMDIFrameWnd::MDIGetActive«, »CWnd::OnNcActivate«, »CMDIFrameWnd::MDINext«, WM_MDIACTIVATE


  CMDIChildWnd::MDIDestroy

void MDIDestroy();

Remarks

Call this member function to destroy an MDI child window.

The member function removes the title of the child window from the frame window and deactivates the child window.

See Also

WM_MDIDESTROY, »CMDIChildWnd::Create«


  CMDIChildWnd::MDIMaximize

void MDIMaximize();

Remarks

Call this member function to maximize an MDI child window. When a child window is maximized, Windows resizes it to make its client area fill the client area of the frame window. Windows places the child window's Control menu in the frame's menu bar so that the user can restore or close the child window and adds the title of the child window to the frame-window title.

See Also

WM_MDIMAXIMIZE, »CMDIChildWnd::MDIRestore«


  CMDIChildWnd::MDIRestore

void MDIRestore();

Remarks

Call this member function to restore an MDI child window from maximized or minimized size.

See Also

»CMDIChildWnd::MDIMaximize«, WM_MDIRESTORE


CMDIFrameWnd
  class CMDIFrameWnd : public CFrameWnd

The CMDIFrameWnd class provides the functionality of a Windows multiple document interface (MDI) frame window, along with members for managing the window.

To create a useful MDI frame window for your application, derive a class from CMDIFrameWnd. Add member variables to the derived class to store data specific to your application. Implement message-handler member functions and a message map in the derived class to specify what happens when messages are directed to the window.

You can construct an MDI frame window by calling the Create or LoadFrame member functions of CFrameWnd.

Before you call Create or LoadFrame, you must construct the frame window object on the heap using the C++ new operator. Before calling Create you may also register a window class with the AfxRegisterWndClass global function to set the icon and class styles for the frame.

Use the Create member function to pass the frame's creation parameters as immediate arguments.

LoadFrame requires fewer arguments than Create, and instead retrieves most of its default values from resources, including the frame's caption, icon, accelerator table, and menu. To be accessed by LoadFrame, all these resources must have the same resource ID (for example, IDR_MAINFRAME).

Though MDIFrameWnd is derived from CFrameWnd, a frame window class derived from CMDIFrameWnd need not be declared with DECLARE_DYNCREATE.

The CMDIFrameWnd class inherits much of its default implementation from CFrameWnd. For a detailed list of these features, refer to the CFrameWnd class description. The CMDIFrameWnd class has the following additional features:

•	An MDI frame window manages the MDICLIENT window, repositioning it in conjunction with control bars. The MDI client window is the direct parent of MDI child frame windows. The WS_HSCROLL and WS_VSCROLL window styles specified on a CMDIFrameWnd apply to the MDI client window rather than the main frame window so the user can scroll the MDI client area (as in the Windows Program Manager, for example).

•	An MDI frame window owns a default menu that is used as the menu bar when there is no active MDI child window. When there is an active MDI child, the MDI frame window's menu bar is automatically replaced by the MDI child window menu.

•	An MDI frame window works in conjunction with the current MDI child window, if there is one. For instance, command messages are delegated to the currently active MDI child before the MDI frame window.

•	An MDI frame window has default handlers for the following standard Window menu commands:

ID_WINDOW_TILE_VERT

ID_WINDOW_TILE_HORZ

ID_WINDOW_CASCADE

ID_WINDOW_ARRANGE

An MDI frame window also has an implementation of ID_WINDOW_NEW, which creates a new frame and view on the current document. An application can override these default command implementations to customize MDI window handling.

Do not use the C++ delete operator to destroy a frame window. Use CWnd::DestroyWindow instead. The CFrameWnd implementation of PostNcDestroy will delete the C++ object when the window is destroyed. When the user closes the frame window, the default OnClose handler will call DestroyWindow.

#include <afxwin.h>

See Also

»CWnd«, »CFrameWnd«, »CMDIChildWnd«


CMDIFrameWnd Class Members
  Class Members

Construction/Destruction — Public Members

»CMDIFrameWnd«	Constructs a CMDIFrameWnd.
Operations — Public Members

»MDIActivate«	Activates a different MDI child window.
»MDIGetActive«	Retrieves the currently active MDI child window, along with a flag indicating whether or not the child is maximized.
»MDIIconArrange«	Arranges all minimized document child windows.
»MDIMaximize«	Maximizes an MDI child window.
»MDINext«	Activates the child window immediately behind the currently active child window and places the currently active child window behind all other child windows.
»MDIRestore«	Restores an MDI child window from maximized or minimized size.
»MDISetMenu«	Replaces the menu of an MDI frame window, the Window pop-up menu, or both.
»MDITile«	Arranges all child windows in a tiled format.
»MDICascade«	Arranges all child windows in a cascaded format.
Overridables— Public Members

»CreateClient«	Creates a Windows MDICLIENT window for this CMDIFrameWnd. Called by the OnCreate member function of CWnd.
»GetWindowMenuPopup«	Returns the Window pop-up menu.


CMDIFrameWnd Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMDIFrameWnd::CMDIFrameWnd

CMDIFrameWnd();

Remarks

Call this member function to construct a CMDIFrameWnd object. Call the Create or LoadFrame member functions to create the visible MDI frame window.

See Also

»CFrameWnd::Create«, »CFrameWnd::LoadFrame«


  CMDIFrameWnd::CreateClient

virtual BOOL CreateClient( LPCREATESTRUCT lpCreateStruct, CMenu* pWindowMenu );

lpCreateStruct    A long pointer to a »CREATESTRUCT« structure.

pWindowMenu    A pointer to the Window pop-up menu.

Remarks

Creates the MDI client window that manages the CMDIChildWnd objects.

This member function should be called if you override the OnCreate member function directly.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CMDIFrameWnd::CMDIFrameWnd«


  CMDIFrameWnd::GetWindowMenuPopup

virtual HMENU GetWindowMenuPopup( HMENU hMenuBar );

hMenuBar    The current menu bar.

Remarks

Call this member function to obtain a handle to the current pop-up menu named "Window" (the pop-up menu with menu items for MDI window management).

The default implementation looks for a pop-up menu containing standard Window menu commands such as ID_WINDOW_NEW and ID_WINDOW_TILE_HORZ.

Override this member function if you have a Window menu that doesn't use the standard menu command IDs.

Return Value

The Window pop-up menu if one exists; otherwise NULL.

See Also

»CMDIFrameWnd::MDIGetActive«


  CMDIFrameWnd::MDIActivate

void MDIActivate( CWnd* pWndActivate );

pWndActivate    Points to the MDI child window to be activated.

Remarks

Call this member function to activate a different MDI child window. This member function sends the »WM_MDIACTIVATE« message to both the child window being activated and the child window being deactivated.

This is the same message that is sent if the user changes the focus to an MDI child window by using the mouse or keyboard.

Note  An MDI child window is activated independently of the MDI frame window. When the frame becomes active, the child window that was last activated is sent a »WM_NCACTIVATE« message to draw an active window frame and caption bar, but it does not receive another WM_MDIACTIVATE message.

See Also

»CMDIFrameWnd::MDIGetActive«, »CMDIFrameWnd::MDINext«, »WM_ACTIVATE«, WM_NCACTIVATE


  CMDIFrameWnd::MDICascade

void MDICascade();

Windows 3.1 Only

void MDICascade( int nType ); ♦

nType    Specifies a cascade flag. Only the following flag may be specified: MDITILE_SKIPDISABLED, which prevents disabled MDI child windows from being cascaded.

Remarks

Call this member function to arrange all the MDI child windows in a cascade format.

The first version of MDICascade, with no parameters, cascades all MDI child windows, including disabled ones. The second version optionally does not cascade disabled MDI child windows if you specify MDITILE_SKIPDISABLED for the nType parameter.

See Also

»CMDIFrameWnd::MDIIconArrange«, »CMDIFrameWnd::MDITile«, WM_MDICASCADE


  CMDIFrameWnd::MDIGetActive

CMDIChildWnd* MDIGetActive( BOOL* pbMaximized = NULL ) const;

pbMaximized    A pointer to a BOOL return value. Set to TRUE on return if the window is maximized; otherwise FALSE.

Remarks

Retrieves the current active MDI child window, along with a flag indicating whether the child window is maximized.

Return Value

A pointer to the active MDI child window.

See Also

»CMDIFrameWnd::MDIActivate«, WM_MDIGETACTIVE


  CMDIFrameWnd::MDIIconArrange

void MDIIconArrange();

Remarks

Arranges all minimized document child windows. It does not affect child windows that are not minimized.

See Also

»CMDIFrameWnd::MDICascade«, »CMDIFrameWnd::MDITile«, WM_MDIICONARRANGE


  CMDIFrameWnd::MDIMaximize

void MDIMaximize( CWnd* pWnd );

pWnd    Points to the window to maximize.

Remarks

Call this member function to maximize the specified MDI child window. When a child window is maximized, Windows resizes it to make its client area fill the client window. Windows places the child window's Control menu in the frame's menu bar so the user can restore or close the child window. It also adds the title of the child window to the frame-window title.

If another MDI child window is activated when the currently active MDI child window is maximized, Windows restores the currently active child and maximizes the newly activated child window.

See Also

WM_MDIMAXIMIZE, »CMDIFrameWnd::MDIRestore«


  CMDIFrameWnd::MDINext

void MDINext();

Remarks

Activates the child window immediately behind the currently active child window and places the currently active child window behind all other child windows.

If the currently active MDI child window is maximized, the member function restores the currently active child and maximizes the newly activated child.

See Also

»CMDIFrameWnd::MDIActivate«, »CMDIFrameWnd::MDIGetActive«, WM_MDINEXT


  CMDIFrameWnd::MDIRestore

void MDIRestore( CWnd* pWnd );

pWnd    Points to the window to restore.

Remarks

Restores an MDI child window from maximized or minimized size.

See Also

»CMDIFrameWnd::MDIMaximize«, WM_MDIRESTORE


  CMDIFrameWnd::MDISetMenu

CMenu* MDISetMenu( CMenu* pFrameMenu, CMenu* pWindowMenu );

pFrameMenu    Specifies the menu of the new frame-window menu. If NULL, the menu is not changed.

pWindowMenu    Specifies the menu of the new Window pop-up menu. If NULL, the menu is not changed.

Remarks

Call this member function to replace the menu of an MDI frame window, the Window pop-up menu, or both.

After calling MDISetMenu, an application must call the »DrawMenuBar« member function of CWnd to update the menu bar.

If this call replaces the Window pop-up menu, MDI child-window menu items are removed from the previous Window menu and added to the new Window pop-up menu.

If an MDI child window is maximized and this call replaces the MDI frame-window menu, the Control menu and restore controls are removed from the previous frame-window menu and added to the new menu.

Do not call this member function if you use the framework to manage your MDI child windows.

Return Value

A pointer to the frame-window menu replaced by this message. The pointer may be temporary and should not be stored for later use.

See Also

»CWnd::DrawMenuBar«, WM_MDISETMENU


  CMDIFrameWnd::MDITile

void MDITile();

Windows 3.1 Only

void MDITile( int nType ); ♦

nType    Specifies a tiling flag. This parameter can be one of the following flags, with the indicated meaning:

•	MDITILE_HORIZONTAL    Tiles MDI child windows so that one window appears above another.

•	MDITILE_SKIPDISABLED    Prevents disabled MDI child windows from being tiled.

•	MDITILE_VERTICAL    Tiles MDI child windows so that one window appears beside another.

Remarks

Call this member function to arrange all child windows in a tiled format.

The first version of MDITile, without parameters, tiles the windows vertically under Windows versions 3.1 and later and arbitrarily under Windows version 3.0. The second version tiles windows vertically or horizontally, depending on the value of the nType parameter.

See Also

»CMDIFrameWnd::MDICascade«, »CMDIFrameWnd::MDIIconArrange«, WM_MDITILE


CMemFile
  class CMemFile : public CFile

CMemFile is the CFile-derived class that supports in-memory files. These in-memory files behave like binary disk files except that bytes are stored in RAM. An in-memory file is a useful means of transferring raw bytes or serialized objects between independent processes.

Contiguous memory is automatically allocated in specified increments, and it is deleted when the object is destroyed. You can access this memory through a pointer supplied by a member function.

The Duplicate, LockRange, and UnlockRange functions are not implemented for CMemFile.

If you call these functions on a CMemFile object, you will get a CNotSupportedException.

The data member CFile::m_hFile is not used and has no meaning.

#include <afx.h>


CMemFile Class Members
  Class Members

Construction/Destruction — Public Members

»CMemFile«	Constructs a memory file using internally allocated memory.
»~CMemFile«	Closes the memory file, freeing allocated memory.


CMemFile Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMemFile::CMemFile

CMemFile( UINT nGrowBytes = 1024 )
throw ( CFileException, CMemoryException );

nGrowBytes    The memory-allocation increment in bytes.

Remarks

Allocates memory and opens an empty memory file.


Example

// example for CMemFile::CMemFile

CMemFile f; // Ready to use - no Open necessary.


  CMemFile::~CMemFile

virtual ~CMemFile();

Remarks

Frees all allocated memory associated with this memory file, effectively closing it.


CMemoryException
  class CMemoryException : public CException

A CMemoryException object represents an out-of-memory exception condition. No further qualification is necessary or possible. Memory exceptions are thrown automatically by new. If you write your own memory functions, using malloc, for example, then you are responsible for throwing memory exceptions.

#include <afx.h>


CMemoryException Class Members
  Class Members

Construction/Destruction — Public Members

»CMemoryException«	Constructs a CMemoryException object.


CMemoryException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMemoryException::CMemoryException

CMemoryException();

Remarks

Constructs a CMemoryException object. Do not use this constructor directly, but rather call the global function »AfxThrowMemoryException«. This global function can succeed in an out-of-memory situation because it constructs the exception object in previously allocated memory. For more information about exception processing, see Chapter 16, "Exceptions," in the Class Library User's Guide.

See Also

»AfxThrowMemoryException«

»Exception Processing«


struct CMemoryState

CMemoryState provides a convenient way to detect memory leaks in your program. A "memory leak" occurs when memory for an object is allocated on the heap but not deallocated when it is no longer required. Such memory leaks can eventually lead to out-of-memory errors. There are several ways to allocate and deallocate memory in your program:

•	Using the malloc/free family of functions from the run-time library

•	Using the Windows API memory management functions, LocalAlloc/LocalFree and GlobalAlloc/GlobalFree

•	Using the C++ new and delete operators

The CMemoryState diagnostics only help detect memory leaks caused when memory allocated using the new operator is not deallocated using delete. The other two groups of memory-management functions are for non-C++ programs, and mixing them with new and delete in the same program is not recommended. An additional macro, DEBUG_NEW, is provided to replace the new operator when you need file and line-number tracking of memory allocations. DEBUG_NEW is used whenever you would normally use the new operator.

As with other diagnostics, the CMemoryState diagnostics are only available in debug versions of your program. A debug version must have the _DEBUG constant defined.

If you suspect your program has a memory leak, you can use the Checkpoint, Difference, and DumpStatistics functions to discover the difference between the memory state (objects allocated) at two different points in program execution. This information can be useful in determining whether a function is cleaning up all the objects it allocates.

If simply knowing where the imbalance in allocation and deallocation occurs does not provide enough information, you can use the DumpAllObjectsSince function to dump all objects allocated since the a previous call to Checkpoint. This dump shows the order of allocation, the source file and line where the object was allocated (if you are using DEBUG_NEW for allocation), and the derivation of the object, its address, and its size. DumpAllObjectsSince also invokes each object's Dump function to provide information about its current state.

For more information about how to use CMemoryState and other diagnostics, see the Class Library User's Guide.

Note  Declarations of objects of type CMemoryState and calls to member functions should be bracketed by #if defined(_DEBUG)/#endif directives. This causes memory diagnostics to be included only in debugging builds of your program.


CMemoryState Class Members
  Class Members

Construction/Destruction — Public Members

»CMemoryState«	Constructs a class-like structure that controls memory checkpoints.
»Checkpoint«	Obtains a snapshot or "checkpoint" of the current memory state.
Operations — Public Members

»Difference«	Computes the difference between two objects of type CMemoryState.
»DumpAllObjectsSince«	Dumps a summary of all currently allocated objects since a previous checkpoint.
»DumpStatistics«	Prints memory allocation statistics for a CMemoryState object.


CMemoryState Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMemoryState::Checkpoint

void Checkpoint();

Remarks

Takes a snapshot summary of memory and stores it in this CMemoryState object. The CMemoryState member functions »Difference« and »DumpAllObjectsSince« use this snapshot data.

 Example

See the example for the »CMemoryState« constructor.


   CMemoryState::CMemoryState

CMemoryState();

Remarks

Constructs an empty CMemoryState object that must be filled in by the »Checkpoint« or »Difference« member functions.

 Example

// example for CMemoryState::CMemoryState

// Includes all CMemoryState functions
CMemoryState msOld, msNew, msDif;
msOld.Checkpoint();
CAge* page1 = new CAge( 21 );
CAge* page2 = new CAge( 22 );
msOld.DumpAllObjectsSince();
msNew.Checkpoint();
msDif.Difference( msOld, msNew );
msDif.DumpStatistics();

Output

Dumping objects ->
{2} a CObject at $190A
{1} a CObject at $18EA
Object dump complete.
0 bytes in 0 Free Blocks
8 bytes in 2 Object Blocks
0 bytes in 0 Non-Object Blocks
Largest number used: 8 bytes
Total allocations: 8 bytes


   CMemoryState::Difference

BOOL Difference( const CMemoryState& oldState,
const CMemoryState& newState );

oldState    The initial memory state as defined by a CMemoryState checkpoint.

newState    The new memory state as defined by a CMemoryState checkpoint.

Remarks

Compares two CMemoryState objects, then stores the difference into this CMemoryState object. »Checkpoint« must have been called for each of the two memory-state parameters.

 Example

See the example for the »CMemoryState« constructor.


  CMemoryState::DumpAllObjectsSince

void DumpAllObjectsSince() const;

Remarks

Calls the Dump function for all objects of a type derived from class CObject that were allocated (and are still allocated) since the last »Checkpoint« call for this CMemoryState object.

Calling DumpAllObjectsSince with an uninitialized CMemoryState object will dump out all objects currently in memory.

 Example

See the example for the »CMemoryState« constructor.


  CMemoryState::DumpStatistics

void DumpStatistics() const;

Remarks

Prints a concise memory statistics report from a CMemoryState object that is filled by the »Difference« member function. The report, which is printed on the afxDump device, shows the following:

•	Number of "object" blocks (blocks of memory allocated using CObject::operator new) still allocated on the heap.

•	Number of non-object blocks still allocated on the heap.

•	The maximum memory used by the program at any one time (in bytes).

•	The total memory currently used by the program (in bytes).

A sample report looks as follows:

0 bytes in 0 Free Blocks
8 bytes in 2 Object Blocks
0 bytes in 0 Non-Object Blocks
Largest number used: 8 bytes
Total allocations: 8 bytes

•	The first line describes the number of blocks whose deallocation was delayed if afxMemDF was set to delayFreeMemDF. For a description of afxMemDF, see "Macros and Globals."

•	The second line describes how many object blocks still remain allocated on the heap.

•	The third line describes how many nonobject blocks (arrays or structures allocated with new) were allocated on the heap and not deallocated.

•	The fourth line gives the maximum memory used by your program at any one time.

•	The last line lists the total amount of memory used by your program.

 Example

See the example for the »CMemoryState« constructor.


CMenu
  class CMenu : public CObject

The CMenu class is an encapsulation of the Windows HMENU. It provides member functions for creating, tracking, updating, and destroying a menu.

Create a CMenu object on the stack frame as a local, then call CMenu's member functions to manipulate the new menu as needed. Next, call CWnd::SetMenu to set the menu to a window, followed immediately by a call to the Detach member function. The CWnd::SetMenu member function sets the window's menu to the new menu, causes the window to be redrawn to reflect the menu change, and also passes ownership of the menu to the window. The call to Detach detaches the HMENU from the CMenu object, so that when the local CMenu variable passes out of scope, the CMenu object destructor does not attempt to destroy a menu it no longer owns. The menu itself is automatically destroyed when the window is destroyed.

You can use the LoadMenuIndirect member function to create a menu from a template in memory, but a menu created from a resource by a call to LoadMenu is more easily maintained, and the menu resource itself can be created and modified by App Studio.

#include <afxwin.h>

See Also

»CObject«


CMenu Class Members
  Class Members

Data Members — Public Members

»m_hMenu«	Specifies the handle to the Windows menu attached to the CMenu object.
Construction/Destruction — Public Members

»CMenu«	Constructs a CMenu object.
Initialization — Public Members

»Attach«	Attaches a Windows menu handle to a CMenu object.
»Detach«	Detaches a Windows menu handle from a CMenu object and returns the handle.
»FromHandle«	Returns a pointer to a CMenu object given a Windows menu handle.
»GetSafeHmenu«	Returns the m_hMenu wrapped by this CMenu object.
»DeleteTempMap«	Deletes any temporary CMenu objects created by the FromHandle member function.
»CreateMenu«	Creates an empty menu and attaches it to a CMenu object.
»CreatePopupMenu«	Creates an empty pop-up menu and attaches it to a CMenu object.
»LoadMenu«	Loads a menu resource from the executable file and attaches it to a CMenu object.
»LoadMenuIndirect«	Loads a menu from a menu template in memory and attaches it to a CMenu object.
»DestroyMenu«	Destroys the menu attached to a CMenu object and frees any memory that the menu occupied.
Menu Operations — Public Members

»DeleteMenu«	Deletes a specified item from the menu. If the menu item has an associated pop-up menu, destroys the handle to the pop-up menu and frees the memory used by it.
»TrackPopupMenu«	Displays a floating pop-up menu at the specified location and tracks the selection of items on the pop-up menu.
Menu Item Operations — Public Members

»AppendMenu«	Appends a new item to the end of this menu.
»CheckMenuItem«	Places check marks next to or removes check marks from menu items in the pop-up menu.
»EnableMenuItem«	Enables, disables, or dims (grays) a menu item.
»GetMenuItemCount«	Determines the number of items in a pop-up or top-level menu.
»GetMenuItemID«	Obtains the menu-item identifier for a menu item located at the specified position.
»GetMenuState«	Returns the status of the specified menu item or the number of items in a pop-up menu.
»GetMenuString«	Retrieves the label of the specified menu item.
»GetSubMenu«	Retrieves a pointer to a pop-up menu.
»InsertMenu«	Inserts a new menu item at the specified position, moving other items down the menu.
»ModifyMenu«	Changes an existing menu item at the specified position.
»RemoveMenu«	Deletes a menu item with an associated pop-up menu from the specified menu.
»SetMenuItemBitmaps«	Associates the specified check-mark bitmaps with a menu item.
Overridables — Public Members

»DrawItem«	Called by the framework when a visual aspect of an owner-drawn menu changes.
»MeasureItem«	Called by the framework to determine menu dimensions when an owner-drawn menu is created.


CMenu Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMenu::AppendMenu

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0, LPCSTR lpszNewItem = NULL );

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

nFlags    Specifies information about the state of the new menu item when it is added to the menu. It consists of one or more of the values listed in the "Remarks" section.

nIDNewItem    Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle (HMENU) of a pop-up menu. The nIDNewItem parameter is ignored (not needed) if nFlags is set to MF_SEPARATOR.

lpszNewItem    Specifies the content of the new menu item. The nFlags parameter is used to interpret lpszNewItem in the following way:

nFlags	Interpretation of lpszNewItem
MF_OWNERDRAW	Contains an application-supplied 32-bit value that the application can use to maintain additional data associated with the menu item. This 32-bit value is available to the application when it processes WM_MEASUREITEM and WM_DRAWITEM messages. The value is stored in the itemData member of the structure supplied with those messages.
MF_STRING	Contains a pointer to a null-terminated string. This is the default interpretation.
MF_SEPARATOR	The lpszNewItem parameter is ignored (not needed).
pBmp    Points to a CBitmap object that will be used as the menu item.

Remarks

Appends a new item to the end of a menu. The application can specify the state of the menu item by setting values in nFlags. When nIDNewItem specifies a pop-up menu, it becomes part of the menu to which it is appended. If that menu is destroyed, the appended menu will also be destroyed. An appended menu should be detached from a CMenu object to avoid conflict. Note that MF_STRING and MF_OWNERDRAW are not valid for the bitmap version of AppendMenu.

The following list describes the flags that may be set in nFlags:

•	MF_CHECKED    Acts as a toggle with MF_UNCHECKED to place the default check mark next to the item. When the application supplies check-mark bitmaps (see the SetMenuItemBitmaps member function), the "check mark on" bitmap is displayed.

•	MF_UNCHECKED    Acts as a toggle with MF_CHECKED to remove a check mark next to the item. When the application supplies check-mark bitmaps (see the SetMenuItemBitmaps member function), the "check mark off" bitmap is displayed.

•	MF_DISABLED    Disables the menu item so that it cannot be selected but does not dim it.

•	MF_ENABLED    Enables the menu item so that it can be selected and restores it from its dimmed state.

•	MF_GRAYED    Disables the menu item so that it cannot be selected and dims it.

•	MF_MENUBARBREAK    Places the item on a new line in static menus or in a new column in pop-up menus. The new pop-up menu column will be separated from the old column by a vertical dividing line.

•	MF_MENUBREAK    Places the item on a new line in static menus or in a new column in pop-up menus. No dividing line is placed between the columns.

•	MF_OWNERDRAW    Specifies that the item is an owner-draw item. When the menu is displayed for the first time, the window that owns the menu receives a WM_MEASUREITEM message, which retrieves the height and width of the menu item. The WM_DRAWITEM message is the one sent whenever the owner must update the visual appearance of the menu item. This option is not valid for a top-level menu item.

•	MF_POPUP    Specifies that the menu item has a pop-up menu associated with it. The ID parameter specifies a handle to a pop-up menu that is to be associated with the item. This is used for adding either a top-level pop-up menu or a hierarchical pop-up menu to a pop-up menu item.

•	MF_SEPARATOR    Draws a horizontal dividing line. Can only be used in a pop-up menu. This line cannot be dimmed, disabled, or highlighted. Other parameters are ignored.

•	MF_STRING    Specifies that the menu item is a character string.

Each of the following groups lists flags that are mutually exclusive and cannot be used together:

•	MF_DISABLED, MF_ENABLED, and MF_GRAYED

•	MF_STRING, MF_OWNERDRAW, MF_SEPARATOR, and the bitmap version

•	MF_MENUBARBREAK and MF_MENUBREAK

•	MF_CHECKED and MF_UNCHECKED

Whenever a menu that resides in a window is changed (whether or not the window is displayed), the application should call CWnd::DrawMenuBar.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::DrawMenuBar«, »CMenu::InsertMenu«, »CMenu::RemoveMenu«, »CMenu::SetMenuItemBitmaps«, »CMenu::Detach«, ::AppendMenu


  CMenu::Attach

BOOL Attach( HMENU hMenu );

hMenu    Specifies a handle to a Windows menu.

Remarks

Attaches an existing Windows menu to a CMenu object. This function should not be called if a menu is already attached to the CMenu object. The menu handle is stored in the m_hMenu data member.

Return Value

Nonzero if the operation was successful; otherwise 0.

See Also

»CMenu::Detach«, »CMenu::CMenu«


  CMenu::CheckMenuItem

UINT CheckMenuItem( UINT nIDCheckItem, UINT nCheck );

nIDCheckItem    Specifies the menu item to be checked, as determined by nCheck.

nCheck    Specifies how to check the menu item and how to determine the item's position in the menu. The nCheck parameter can be a combination of MF_CHECKED or MF_UNCHECKED with MF_BYPOSITION or MF_BYCOMMAND flags. These flags can be combined by using the bitwise-OR operator. They have the following meanings:

•	MF_BYCOMMAND    Specifies that the parameter gives the command ID of the existing menu item. This is the default.

•	MF_BYPOSITION    Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.

•	MF_CHECKED    Acts as a toggle with MF_UNCHECKED to place the default check mark next to the item.

•	MF_UNCHECKED    Acts as a toggle with MF_CHECKED to remove a check mark next to the item.

Remarks

Adds check marks to or removes check marks from menu items in the pop-up menu. The nIDCheckItem parameter specifies the item to be modified.

The nIDCheckItem parameter may identify a pop-up menu item as well as a menu item. No special steps are required to check a pop-up menu item. Top-level menu items cannot be checked. A pop-up menu item must be checked by position since it does not have a menu-item identifier associated with it.

Return Value

The previous state of the item: MF_CHECKED or MF_UNCHECKED, or −1 if the menu item did not exist.

See Also

»CMenu::GetMenuState«, ::CheckMenuItem


  CMenu::CMenu

CMenu();

Remarks

The menu is not created until you call one of the create or load member functions of CMenu, as listed in "See Also."


 See Also

»CMenu::CreateMenu«, »CMenu::CreatePopupMenu«, »CMenu::LoadMenu«, »CMenu::LoadMenuIndirect«, »CMenu::Attach«


  CMenu::CreateMenu

BOOL CreateMenu();

Remarks

Creates a menu and attaches it to the CMenu object.

The menu is initially empty. Menu items can be added by using the AppendMenu or InsertMenu member function.

If the menu is assigned to a window, it is automatically destroyed when the window is destroyed.

Before exiting, an application must free system resources associated with a menu if the menu is not assigned to a window. An application frees a menu by calling the »DestroyMenu« member function.

Return Value

Nonzero if the menu was created successfully; otherwise 0.

See Also

»CMenu::CMenu«, »CMenu::DestroyMenu«, »CMenu::InsertMenu«, »CWnd::SetMenu«, ::CreateMenu, »CMenu::AppendMenu«


  CMenu::CreatePopupMenu

BOOL CreatePopupMenu();

Remarks

Creates a pop-up menu and attaches it to the CMenu object.

The menu is initially empty. Menu items can be added by using the AppendMenu or InsertMenu member function. The application can add the pop-up menu to an existing menu or pop-up menu. The TrackPopupMenu member function may be used to display this menu as a floating pop-up menu and to track selections on the pop-up menu.

If the menu is assigned to a window, it is automatically destroyed when the window is destroyed. If the menu is added to an existing menu, it is automatically destroyed when that menu is destroyed.

Before exiting, an application must free system resources associated with a pop-up menu if the menu is not assigned to a window. An application frees a menu by calling the »DestroyMenu« member function.

Return Value

Nonzero if the pop-up menu was successfully created; otherwise 0.

See Also

»CMenu::CreateMenu«, »CMenu::InsertMenu«, »CWnd::SetMenu«, »CMenu::TrackPopupMenu«, ::CreatePopupMenu, »CMenu::AppendMenu«


  CMenu::DeleteMenu

BOOL DeleteMenu( UINT nPosition, UINT nFlags );

nPosition    Specifies the menu item that is to be deleted, as determined by nFlags.

nFlags    Is used to interpret nPosition in the following way:

nFlags	Interpretation of nPosition
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
Remarks

Deletes an item from the menu. If the menu item has an associated pop-up menu, DeleteMenu destroys the handle to the pop-up menu and frees the memory used by the pop-up menu.

Whenever a menu that resides in a window is changed (whether or not the window is displayed), the application must call CWnd::DrawMenuBar.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::DrawMenuBar«, ::DeleteMenu


  CMenu::DeleteTempMap

static void PASCAL DeleteTempMap();

Remarks

Called automatically by the CWinApp idle-time handler, DeleteTempMap deletes any temporary CMenu objects created by the FromHandle member function. DeleteTempMap detaches the Windows menu object attached to a temporary CMenu object before deleting the CMenu object.


  CMenu::DestroyMenu

BOOL DestroyMenu();

Remarks

Destroys the menu and any Windows resources that were used. The menu is detached from the CMenu object before it is destroyed. The Windows DestroyMenu function is automatically called in the CMenu destructor.

Return Value

Nonzero if the menu is destroyed; otherwise 0.

See Also

 ::DestroyMenu


  CMenu::Detach

HMENU Detach();

Remarks

Detaches a Windows menu from a CMenu object and returns the handle. The m_hMenu data member is set to NULL.

Return Value

The handle, of type HMENU, to a Windows menu, if successful; otherwise NULL.

See Also

»CMenu::Attach«


  CMenu::DrawItem

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

lpDrawItemStruct    A pointer to a »DRAWITEMSTRUCT« structure that contains information about the type of drawing required.

Remarks

Called by the framework when a visual aspect of an owner-drawn menu changes. The itemAction member of the DRAWITEMSTRUCT structure defines the drawing action that is to be performed. Override this member function to implement drawing for an owner-draw CMenu object. The application should restore all graphics device interface (GDI) objects selected for the display context supplied in lpDrawItemStruct before the termination of this member function.

See »CWnd::OnDrawItem« for a description of the DRAWITEMSTRUCT structure.


  CMenu::EnableMenuItem

UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );

nIDEnableItem    Specifies the menu item to be enabled, as determined by nEnable. This parameter can specify pop-up menu items as well as standard menu items.

nEnable    Specifies the action to take. It can be a combination of MF_DISABLED, MF_ENABLED, or MF_GRAYED, with MF_BYCOMMAND or MF_BYPOSITION. These values can be combined by using the bitwise-OR operator. These values have the following meanings:

•	MF_BYCOMMAND    Specifies that the parameter gives the command ID of the existing menu item. This is the default.

•	MF_BYPOSITION    Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.

•	MF_DISABLED    Disables the menu item so that it cannot be selected but does not dim it.

•	MF_ENABLED    Enables the menu item so that it can be selected and restores it from its dimmed state.

•	MF_GRAYED    Disables the menu item so that it cannot be selected and dims it.

Remarks

Enables, disables, or dims a menu item. The »CreateMenu«, »InsertMenu«, »ModifyMenu«, and »LoadMenuIndirect« member functions can also set the state (enabled, disabled, or dimmed) of a menu item.

Using the MF_BYPOSITION value requires an application to use the correct CMenu. If the CMenu of the menu bar is used, a top-level menu item (an item in the menu bar) is affected. To set the state of an item in a pop-up or nested pop-up menu by position, an application must specify the CMenu of the pop-up menu.

When an application specifies the MF_BYCOMMAND flag, Windows checks all pop-up menu items that are subordinate to the CMenu; therefore, unless duplicate menu items are present, using the CMenu of the menu bar is sufficient.

Return Value

Previous state (MF_DISABLED, MF_ENABLED, or MF_GRAYED) or −1 if not valid.

See Also

»CMenu::GetMenuState«, ::EnableMenuItem


  CMenu::FromHandle

static CMenu* PASCAL FromHandle( HMENU hMenu );

hMenu     A Windows handle to a menu.

Remarks

Returns a pointer to a CMenu object given a Windows handle to a menu. If a CMenu object is not already attached to the Windows menu object, a temporary CMenu object is created and attached.

This temporary CMenu object is only valid until the next time the application has idle time in its event loop, at which time all temporary objects are deleted.

Return Value

A pointer to a CMenu that may be temporary or permanent.


  CMenu::GetMenuItemCount

UINT GetMenuItemCount() const;

Remarks

Determines the number of items in a pop-up or top-level menu.

Return Value

The number of items in the menu if the function is successful; otherwise −1.

See Also

»CWnd::GetMenu«, »CMenu::GetMenuItemID«, »CMenu::GetSubMenu«, ::GetMenuItemCount


  CMenu::GetMenuItemID

UINT GetMenuItemID( int nPos ) const;

nPos    Specifies the position (zero-based) of the menu item whose ID is being retrieved.

Remarks

Obtains the menu-item identifier for a menu item located at the position defined by nPos.

Return Value

The item ID for the specified item in a pop-up menu if the function is successful. If the specified item is a pop-up menu (as opposed to an item within the pop-up menu), the return value is −1. If nPos corresponds to a SEPARATOR menu item, the return value is 0.

See Also

»CWnd::GetMenu«, »CMenu::GetMenuItemCount«, »CMenu::GetSubMenu«, ::GetMenuItemID


  CMenu::GetMenuState

UINT GetMenuState( UINT nID, UINT nFlags ) const;

nID    Specifies the menu item ID, as determined by nFlags.

nFlags    Specifies the nature of nID. It can be one of the following values:

•	MF_BYCOMMAND    Specifies that the parameter gives the command ID of the existing menu item. This is the default.

•	MF_BYPOSITION    Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.

Remarks

Returns the status of the specified menu item or the number of items in a pop-up menu.

Return Value

The value −1 if the specified item does not exist. If nId identifies a pop-up menu, the high-order byte contains the number of items in the pop-up menu and the low-order byte contains the menu flags associated with the pop-up menu. Otherwise the return value is a mask (Boolean OR) of the values from the following list (this mask describes the status of the menu item that nId identifies):

•	MF_CHECKED    Acts as a toggle with MF_UNCHECKED to place the default check mark next to the item. When the application supplies check-mark bitmaps (see the SetMenuItemBitmaps member function), the "check mark on" bitmap is displayed.

•	MF_DISABLED    Disables the menu item so that it cannot be selected but does not dim it.

•	MF_ENABLED    Enables the menu item so that it can be selected and restores it from its dimmed state. Note that the value of this constant is 0; an application should not test against 0 for failure when using this value.

•	MF_GRAYED    Disables the menu item so that it cannot be selected and dims it.

•	MF_MENUBARBREAK    Places the item on a new line in static menus or in a new column in pop-up menus. The new pop-up menu column will be separated from the old column by a vertical dividing line.

•	MF_MENUBREAK    Places the item on a new line in static menus or in a new column in pop-up menus. No dividing line is placed between the columns.

•	MF_SEPARATOR    Draws a horizontal dividing line. Can only be used in a pop-up menu. This line cannot be dimmed, disabled, or highlighted. Other parameters are ignored.

•	MF_UNCHECKED    Acts as a toggle with MF_CHECKED to remove a check mark next to the item. When the application supplies check-mark bitmaps (see the SetMenuItemBitmaps member function), the "check mark off" bitmap is displayed. Note that the value of this constant is 0; an application should not test against 0 for failure when using this value.

See Also

::GetMenuState, »CMenu::CheckMenuItem«, »CMenu::EnableMenuItem«


  CMenu::GetMenuString

int GetMenuString( UINT nIDItem, LPSTR lpString, int nMaxCount,
UINT nFlags ) const;

nIDItem    Specifies the integer identifier of the menu item or the offset of the menu item in the menu, depending on the value of nFlags.

lpString    Points to the buffer that is to receive the label.

nMaxCount    Specifies the maximum length (in bytes) of the label to be copied. If the label is longer than the maximum specified in nMaxCount, the extra characters are truncated.

nFlags    Specifies the interpretation of the nIDItem parameter. It can be one of the following values:

nFlags	Interpretation of nIDItem
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
Remarks

Copies the label of the specified menu item to the specified buffer.

The nMaxCount parameter should be one larger than the number of characters in the label to accommodate the null character that terminates a string.

Return Value

Specifies the actual number of bytes copied to the buffer, not including the null terminator.

See Also

»CWnd::GetMenu«, »CMenu::GetMenuItemID«, ::GetMenuString


  CMenu::GetSafeHmenu

HMENU GetSafeHmenu() const;

Remarks

Returns the HMENU wrapped by this CMenu object, or a NULL CMenu pointer.


  CMenu::GetSubMenu

CMenu* GetSubMenu( int nPos ) const;

nPos    Specifies the position of the pop-up menu contained in the menu. Position values start at 0 for the first menu item. The pop-up menu's identifier cannot be used in this function.

Remarks

Retrieves the CMenu object of a pop-up menu.

Return Value

A pointer to a CMenu object whose m_hMenu member contains a handle to the pop-up menu if a pop-up menu exists at the given position; otherwise NULL. If a CMenu object does not exist, then a temporary one is created. The CMenu pointer returned should not be stored.

See Also

::GetSubMenu


  CMenu::InsertMenu

BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCSTR lpszNewItem = NULL );

BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem,
const CBitmap* pBmp );

nPosition    Specifies the menu item before which the new menu item is to be inserted. The nFlags parameter can be used to interpret nPosition in the following ways:

nFlags	Interpretation of nPosition
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0. If nPosition is −1, the new menu item is appended to the end of the menu.
nFlags    Specifies how nPosition is interpreted and specifies information about the state of the new menu item when it is added to the menu. For a list of the flags that may be set, see the »AppendMenu« member function. To specify more than one value, use the bitwise-OR operator to combine them with the MF_BYCOMMAND or MF_BYPOSITION flag.

nIDNewItem    Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle (HMENU) of the pop-up menu. The nIDNewItem parameter is ignored (not needed) if nFlags is set to MF_SEPARATOR.

lpszNewItem    Specifies the content of the new menu item. nFlags can be used to interpret lpszNewItem in the following ways:

nFlags	Interpretation of lpszNewItem
MF_OWNERDRAW	Contains an application-supplied 32-bit value that the application can use to maintain additional data associated with the menu item. This 32-bit value is available to the application in the itemData member of the structure supplied by the WM_MEASUREITEM and WM_DRAWITEM messages. These messages are sent when the menu item is initially displayed or is changed.
MF_STRING	Contains a long pointer to a null-terminated string. This is the default interpretation.
MF_SEPARATOR	The lpszNewItem parameter is ignored (not needed).
pBmp    Points to a CBitmap object that will be used as the menu item.

Remarks

Inserts a new menu item at the position specified by nPosition and moves other items down the menu. The application can specify the state of the menu item by setting values in nFlags.

Whenever a menu that resides in a window is changed (whether or not the window is displayed), the application should call CWnd::DrawMenuBar.

When nIDNewItem specifies a pop-up menu, it becomes part of the menu in which it is inserted. If that menu is destroyed, the inserted menu will also be destroyed. An inserted menu should be detached from a CMenu object to avoid conflict.

If the active multiple document interface (MDI) child window is maximized and an application inserts a pop-up menu into the MDI application's menu by calling this function and specifying the MF_BYPOSITION flag, the menu is inserted one position farther left than expected. This happens because the Control menu of the active MDI child window is inserted into the first position of the MDI frame window's menu bar. To position the menu properly, the application must add 1 to the position value that would otherwise be used. An application can use the WM_MDIGETACTIVE message to determine whether the currently active child window is maximized.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CMenu::AppendMenu«, »CWnd::DrawMenuBar«, »CMenu::SetMenuItemBitmaps«, »CMenu::Detach«, ::InsertMenu


  CMenu::LoadMenu

BOOL LoadMenu( LPCSTR lpszResourceName );

BOOL LoadMenu( UINT nIDResource );

lpszResourceName    Points to a null-terminated string that contains the name of the menu resource to load.

nIDResource    Specifies the menu ID of the menu resource to load.

Remarks

Loads a menu resource from the application's executable file and attaches it to the CMenu object.

Before exiting, an application must free system resources associated with a menu if the menu is not assigned to a window. An application frees a menu by calling the »DestroyMenu« member function.

Return Value

Nonzero if the menu resource was loaded successfully; otherwise 0.

See Also

»CMenu::AppendMenu«, »CMenu::DestroyMenu«, »CMenu::LoadMenuIndirect«, ::LoadMenu


  CMenu::LoadMenuIndirect

BOOL LoadMenuIndirect( const void FAR* lpMenuTemplate );

lpMenuTemplate    Points to a menu template (which is a single MENUITEMTEMPLATEHEADER structure and a collection of one or more MENUITEMTEMPLATE structures).

Remarks

Loads a resource from a menu template in memory and attaches it to the CMenu object. A menu template is a header followed by a collection of one or more MENUITEMTEMPLATEstructures, each of which may contain one or more menu items and pop-up menus.

The version number should be 0.

The mtOption flags should include MF_END for the last item in a pop-up list and for the last item in the main list. See the AppendMenu member function for other flags. The mtId member must be omitted from the MENUITEMTEMPLATE structure when MF_POPUP is specified in mtOption.

The space allocated for the MENUITEMTEMPLATE structure must be large enough for mtString to contain the name of the menu item as a null-terminated string.

Before exiting, an application must free system resources associated with a menu if the menu is not assigned to a window. An application frees a menu by calling the »DestroyMenu« member function.

Return Value

Nonzero if the menu resource was loaded successfully; otherwise 0.

See Also

»CMenu::DestroyMenu«, »CMenu::LoadMenu«, ::LoadMenuIndirect, »CMenu::AppendMenu«


  CMenu::MeasureItem

virtual void MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct );

lpMeasureItemStruct    A pointer to a MEASUREITEMSTRUCT structure.

Remarks

Called by the framework when a menu with the owner-draw style is created. By default, this member function does nothing. Override this member function and fill in the MEASUREITEMSTRUCT structure to inform Windows of the menu's dimensions.

See »CWnd::OnMeasureItem« for a description of the MEASUREITEMSTRUCT structure.


  CMenu::ModifyMenu

BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCSTR lpszNewItem = NULL );

BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

nPosition    Specifies the menu item to be changed. The nFlags parameter can be used to interpret nPosition in the following ways:

nFlags	Interpretation of nPosition
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
nFlags    Specifies how nPosition is interpreted and gives information about the changes to be made to the menu item. For a list of flags that may be set, see the »AppendMenu« member function.

nIDNewItem    Specifies either the command ID of the modified menu item or, if nFlags is set to MF_POPUP, the menu handle (HMENU) of a pop-up menu. The nIDNewItem parameter is ignored (not needed) if nFlags is set to MF_SEPARATOR.

lpszNewItem    Specifies the content of the new menu item. The nFlags parameter can be used to interpret lpszNewItem in the following ways:

nFlags	Interpretation of lpszNewItem
MF_OWNERDRAW	Contains an application-supplied 32-bit value that the application can use to maintain additional data associated with the menu item. This 32-bit value is available to the application when it processes MF_MEASUREITEM and MF_DRAWITEM.
MF_STRING	Contains a long pointer to a null-terminated string or to a CString.
MF_SEPARATOR	The lpszNewItem parameter is ignored (not needed).
pBmp    Points to a CBitmap object that will be used as the menu item.

Remarks

Changes an existing menu item at the position specified by nPosition. The application specifies the new state of the menu item by setting values in nFlags. If this function replaces a pop-up menu associated with the menu item, it destroys the old pop-up menu and frees the memory used by the pop-up menu.

When nIDNewItem specifies a pop-up menu, it becomes part of the menu in which it is inserted. If that menu is destroyed, the inserted menu will also be destroyed. An inserted menu should be detached from a CMenu object to avoid conflict.

Whenever a menu that resides in a window is changed (whether or not the window is displayed), the application should call CWnd::DrawMenuBar. To change the attributes of existing menu items, it is much faster to use the CheckMenuItem and EnableMenuItem member functions.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CMenu::AppendMenu«, »CMenu::InsertMenu«, »CMenu::CheckMenuItem«, »CWnd::DrawMenuBar«, »CMenu::EnableMenuItem«, »CMenu::SetMenuItemBitmaps«, »CMenu::Detach«, ::ModifyMenu


  CMenu::RemoveMenu

BOOL RemoveMenu( UINT nPosition, UINT nFlags );

nPosition    Specifies the menu item to be removed. The nFlags parameter can be used to interpret nPosition in the following ways:

nFlags	Interpretation of nPosition
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
nFlags    Specifies how nPosition is interpreted.

Remarks

Deletes a menu item with an associated pop-up menu from the menu. It does not destroy the handle for a pop-up menu, so the menu can be reused. Before calling this function, the application may call the GetSubMenu member function to retrieve the pop-up CMenu object for reuse.

Whenever a menu that resides in a window is changed (whether or not the window is displayed), the application must call CWnd::DrawMenuBar.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::DrawMenuBar«, »CMenu::GetSubMenu«, ::RemoveMenu


  CMenu::SetMenuItemBitmaps

BOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked );

nPosition    Specifies the menu item to be changed. The nFlags parameter can be used to interpret nPosition in the following ways:

nFlags	Interpretation of nPosition
MF_BYCOMMAND	Specifies that the parameter gives the command ID of the existing menu item. This is the default if neither MF_BYCOMMAND nor MF_BYPOSITION is set.
MF_BYPOSITION	Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
nFlags    Specifies how nPosition is interpreted.

pBmpUnchecked    Specifies the bitmap to use for menu items that are not checked.

pBmpChecked    Specifies the bitmap to use for menu items that are checked.

Remarks

Associates the specified bitmaps with a menu item. Whether the menu item is checked or unchecked, Windows displays the appropriate bitmap next to the menu item.

If either pBmpUnchecked or pBmpChecked is NULL, then Windows displays nothing next to the menu item for the corresponding attribute. If both parameters are NULL, Windows uses the default check mark when the item is checked and removes the check mark when the item is unchecked.

When the menu is destroyed, these bitmaps are not destroyed; the application must destroy them.

The Windows GetMenuCheckMarkDimensions function retrieves the dimensions of the default check mark used for menu items. The application uses these values to determine the appropriate size for the bitmaps supplied with this function. Get the size, create your bitmaps, then set them.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::GetMenuCheckMarkDimensions, ::SetMenuItemBitmaps


  CMenu::TrackPopupMenu

BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = 0 );

nFlags    Specifies a screen-position flag and a mouse-button flag. The screen-position flag can be one of the following:

•	TPM_CENTERALIGN    Centers the pop-up menu horizontally relative to the coordinate specified by x.

•	TPM_LEFTALIGN    Positions the pop-up menu so that its left side is aligned with the coordinate specified by x.

•	TPM_RIGHTALIGN    Positions the pop-up menu so that its right side is aligned with the coordinate specified by x.

The mouse-button flag can be one of the following:

•	TPM_LEFTBUTTON    Causes the pop-up menu to track the left mouse button.

•	TPM_RIGHTBUTTON    Causes the pop-up menu to track the right mouse button.

x    Specifies the horizontal position in screen coordinates of the pop-up menu. Depending on the value of the nFlags parameter, the menu can be left-aligned, right-aligned, or centered relative to this position.

y    Specifies the vertical position in screen coordinates of the top of the menu on the screen.

pWnd    Identifies the window that owns the pop-up menu. This window receives all WM_COMMAND messages from the menu. In Windows versions 3.1 and later, the window does not receive WM_COMMAND messages until TrackPopupMenu returns. In Windows 3.0, the window receives WM_COMMAND messages before TrackPopupMenu returns.

lpRect    Points to a RECT structure or CRect object that contains the screen coordinates of a rectangle within which the user can click without dismissing the pop-up menu. If this parameter is NULL, the pop-up menu is dismissed if the user clicks outside the pop-up menu. This must be NULL for Windows 3.0.

Windows 3.1 Only

The use of the following constants for lpRect is new in Windows 3.1:

•	TPM_CENTERALIGN

•	TPM_LEFTALIGN

•	TPM_RIGHTALIGN

•	TPM_RIGHTBUTTON ♦

Remarks

Displays a floating pop-up menu at the specified location and tracks the selection of items on the pop-up menu. A floating pop-up menu can appear anywhere on the screen.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CMenu::CreatePopupMenu«, »CMenu::GetSubMenu«, ::TrackPopupMenu


CMenu Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CMenu::m_hMenu

Remarks

Specifies the HMENU handle of the Windows menu attached to the CMenu object.


CMetaFileDC
  class CMetaFileDC : public CDC

A Windows metafile contains a sequence of graphics device interface (GDI) commands that you can replay to create a desired image or text.

To implement a Windows metafile, first create a CMetaFileDC object. Invoke the CMetaFileDC constructor, then call the »Create« member function, which creates a Windows metafile device context and attaches it to the CMetaFileDC object.

Next send the CMetaFileDC object the sequence of CDC GDI commands that you intend for it to replay. Only those GDI commands that create output, such as MoveTo and LineTo, may be used.

After you have sent the desired commands to the metafile, call the Close member function, which closes the metafile device contexts and returns a metafile handle. Then dispose of the CMetaFileDC object.

»CDC::PlayMetaFile« can then use the metafile handle to play the metafile repeatedly. The metafile can also be manipulated by Windows functions such as CopyMetaFile, which copies a metafile to disk.

When the metafile is no longer needed, delete it from memory with the DeleteMetaFileWindows function.

You may also implement the CMetaFileDC object so that it can handle both output calls and attribute GDI calls such as GetTextExtent. Such a metafile is more flexible and can more easily reuse general GDI code, which often consists of a mix of output and attribute calls. The CMetaFileDC class inherits two device contexts, m_hDC and m_hAttribDC, from CDC. The m_hDC device context handles all CDC GDI output calls and the m_hAttribDC device context handles all CDC GDI attribute calls. Normally, these two device contexts refer to the same device. In the case of CMetaFileDC, the attribute DC is set to NULL by default.

Create a second device context that points to the screen, a printer, or device other than a metafile, then call the SetAttribDC member function to associate the new device context with m_hAttribDC. GDI calls for information will now be directed to the new m_hAttribDC. Output GDI calls will go to m_hDC, which represents the metafile.

#include <afxext.h>

See Also

»CDC«


CMetaFileDC Class Members
  Class Members

Construction/Destruction — Public Members

»CMetaFileDC«	Constructs a CMetaFileDC object.
Initialization — Public Members

»Create«	Creates the Windows metafile device context and attaches it to the CMetaFileDC object.
Operations — Public Members

»Close«	Closes the device context and creates a metafile handle.


CMetaFileDC Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMetaFileDC::Close

HMETAFILE Close();

Remarks

Closes the metafile device context and creates a Windows metafile handle that can be used to play the metafile by using the »CDC::PlayMetaFile« member function. The Windows metafile handle can also be used to manipulate the metafile with Windows functions such as CopyMetaFile

Delete the metafile after use by calling the Windows DeleteMetaFilefunction.

Return Value

A valid HMETAFILE if the function is successful; otherwise NULL.

See Also

»CDC::PlayMetaFile«, ::CloseMetaFile, ::GetMetaFileBits, ::CopyMetaFile, ::DeleteMetaFile


  CMetaFileDC::CMetaFileDC

CMetaFileDC();

Remarks

Construct a CMetaFileDC object in two steps. First, call CMetaFileDC, then call Create, which creates the Windows metafile device context and attaches it to the CMetaFileDC object.

See Also

»CMetaFileDC::Create«


  CMetaFileDC::Create

BOOL Create( LPCSTR lpszFilename = NULL );

lpszFilename    Points to a null-terminated character string. Specifies the filename of the metafile to create. If lpszFilename is NULL, a new in-memory metafile is created.

Remarks

Construct a CMetaFileDC object in two steps. First, call the constructor CMetaFileDC, then call Create, which creates the Windows metafile device context and attaches it to the CMetaFileDC object.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CMetaFileDC::CMetaFileDC«, »CDC::SetAttribDC«, ::CreateMetaFile


CMultiDocTemplate
  class CMultiDocTemplate : public CDocTemplate

The CMultiDocTemplate class defines a document template that implements the multiple document interface (MDI). An MDI application uses the main frame window as a workspace in which the user can open zero or more document frame windows, each of which displays a document. For a more detailed description of the MDI, see The Windows Interface: An Application Design Guide.

A document template defines the relationship between three types of classes:

•	A document class, which you derive from CDocument.

•	A view class, which displays data from the document class listed above. You can derive this class from CView, CScrollView, CFormView, or CEditView. (You can also use CEditView directly.)

•	A frame window class, which contains the view. For an MDI document template, you can derive this class from CMDIChildWnd, or, if you don't need to customize the behavior of the document frame windows, you can use CMDIChildWnd directly without deriving your own class.

An MDI application can support more than one type of document, and documents of different types can be open at the same time. Your application has one document template for each document type that it supports. For example, if your MDI application supports both spreadsheets and text documents, the application has two CMultiDocTemplate objects.

The application uses the document template(s) when the user creates a new document. If the application supports more than one type of document, then the framework gets the names of the supported document types from the document templates and displays them in a list in the File New dialog box. Once the user has selected a document type, the application creates a document object, a frame window object, and a view object and attaches them to each other.

You don't need to call any member functions of CMultiDocTemplate except the constructor. The framework handles CMultiDocTemplate objects internally.

See Also

»CDocTemplate«, »CDocument«, »CMDIChildWnd«, »CSingleDocTemplate«, »CView«, »CWinApp«


CMultiDocTemplate  Class Members
  Class Members

Construction/Destruction — Public Members

»CMultiDocTemplate«	Constructs a CMultiDocTemplate object.


CMultiDocTemplate Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CMultiDocTemplate::CMultiDocTemplate

CMultiDocTemplate( UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass );

nIDResource    Specifies the ID of the resources used with the document type. This may include menu, icon, accelerator table, and string resources.

The string resource consists of up to seven substrings separated by the '\n' character (the '\n' character is needed as a place holder if a substring is not included; however, trailing '\n' characters are not necessary); these substrings describe the document type. For information on the substrings, see »CDocTemplate::GetDocString«. This string resource is found in the application's resource file. For example:

// MYCALC.RC

STRINGTABLE PRELOAD DISCARDABLE

BEGIN

    IDR_SHEETTYPE "\nSheet\nWorksheet\nWorksheets (*.myc)\n.myc\n MyCalcSheet\nMyCalc Worksheet"

END

Note that the string begins with a '\n' character; this is because the first substring is not used for MDI applications and so is not included. You can edit this string using the String Editor in App Studio; the entire string appears as a single entry in the String Editor, not as seven separate entries.

For more information about these resource types, see the App Studio User's Guide.

pDocClass    Points to the CRuntimeClass object of the document class. This class is a CDocument-derived class you define to represent your documents.

pFrameClass    Points to the CRuntimeClass object of the frame-window class. This class can be a CMDIChildWnd-derived class, or it can be CMDIChildWnd itself if you want default behavior for your document frame windows.

pViewClass    Points to the CRuntimeClass object of the view class. This class is a CView-derived class you define to display your documents.

Remarks

Constructs a CMultiDocTemplate object. Dynamically allocate one CMultiDocTemplate object for each document type that your application supports and pass each one to CWinApp::AddDocTemplate from the InitInstance member function of your application class.

See Also

»CDocTemplate::GetDocString«, »CWinApp::AddDocTemplate«, »CWinApp::InitInstance«, »CRuntimeClass«

 Example

//example for CMultiDocTemplate

BOOL CMyApp::InitInstance()
{
        // ...
        // Establish all of the document types
        // supported by the application

        AddDocTemplate( new CMultiDocTemplate( IDR_SHEETTYPE,
                            RUNTIME_CLASS( CSheetDoc ),
                            RUNTIME_CLASS( CMDIChildWnd ),
                            RUNTIME_CLASS( CSheetView ) ) );

        AddDocTemplate( new CMultiDocTemplate( IDR_NOTETYPE,
                            RUNTIME_CLASS( CNoteDoc ),
                            RUNTIME_CLASS( CMDIChildWnd ),
                            RUNTIME_CLASS( CNoteView ) ) );
        // ...
}


CNotSupportedException
  class CNotSupportedException : public CException

A CNotSupportedException object represents an exception that is the result of a request for an unsupported feature. No further qualification is necessary or possible.

#include <afx.h>


CNotSupportedException Class Members
  Class Members

Construction/Destruction — Public Member

»CNotSupportedException«	Constructs a CNotSupportedException object.


CNotSupportedException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CNotSupportedException::CNotSupportedException

CNotSupportedException();

Remarks

Constructs a CNotSupportedException object.

Do not use this constructor directly, but rather call the global function »AfxThrowNotSupportedException«. For more information about exception processing, see Chapter 16, "Exceptions," in the Class Library User's Guide.

»Exception Processing«

See Also

»AfxThrowNotSupportedException«


CObArray
  class CObArray : public CObject

The CObArray class supports arrays of CObject pointers. These object arrays are similar to C arrays, but they can dynamically shrink and grow as necessary.

Array indexes always start at position 0. You can decide whether to fix the upper bound or allow the array to expand when you add elements past the current bound. Memory is allocated contiguously to the upper bound, even if some elements are null.

The elements of a CObArray object must fit in one 64K segment together with approximately 100 allocation overhead bytes. If CObject pointers are 16-bit near pointers (as they are in the small and medium memory models), then an array size limit is about 32,000 elements, but because there is only one data segment, the objects themselves will probably exhaust memory before the array does. If CObject pointers are 32-bit far pointers (as they are in the compact and large memory models), then an array size limit is about 16,000 elements.

As with a C array, the access time for a CObArray indexed element is constant and is independent of the array size.

CObArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of CObject pointers is stored to an archive, either with the overloaded insertion operator or with the Serialize member function, each CObject element is, in turn, serialized along with its array index.

If you need a dump of individual CObject elements in an array, you must set the depth of the CDumpContext object to 1 or greater.

When a CObArray object is deleted, or when its elements are removed, only the CObject pointers are removed, not the objects they reference.

Array class derivation is similar to list derivation. For details on the derivation of a special-purpose list class, Chapter 13, "Collections," in the Class Library User's Guide.

Note  You must use the IMPLEMENT_SERIAL macro in the implementation of your derived class if you intend to serialize the array.

#include <afxcoll.h>

See Also

»CStringArray«, »CPtrArray«, »CByteArray«, »CWordArray«, »CDWordArray«


CObArray Class Members
  Class Members

Construction/Destruction — Public Members

»CObArray«	Constructs an empty array for CObject pointers.
»~CObArray«	Destroys a CObArray object.
Bounds — Public Members

»GetSize«	Gets the number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array not allowed to grow.
»ElementAt«	Returns a temporary reference to the element pointer within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CObArray Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CObArray::Add

int Add( CObject* newElement )
throw( CMemoryException );

newElement    The CObject pointer to be added to this array.

Remarks

Adds a new element to the end of an array, growing the array by 1. If »SetSize« has been used with an nGrowBy value greater than 1, then extra memory may be allocated. However, the upper bound will increase by only 1.

Return Value

The index of the added element.

See Also

»CObArray::SetAt«, »CObArray::SetAtGrow«, »CObArray::InsertAt«, »CObArray::operator []«

Example

// example for CObArray::Add

CObArray array;

array.Add( new CAge( 21 ) ); // Element 0
array.Add( new CAge( 40 ) ); // Element 1
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "Add example: " << &array << "\n";
#endif

The results from this program are as follows:

Add example: A CObArray with 2 elements
    [0] = a CAge at $442A 21
    [1] = a CAge at $4468 40


  CObArray::CObArray

CObArray();

Remarks

Constructs an empty CObject pointer array. The array grows one element at a time.

See Also

»CObList::CObList«

Example

See the CObList constructor for a listing of the CAge class used in all collection examples.


  CObArray::~CObArray

~CObArray();

Remarks

Destroys a CObArray object but does not destroy the CObject objects that are referenced in the array.


  CObArray::ElementAt

CObject*& ElementAt( int nIndex );

nIndex    An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

Remarks

Returns a temporary reference to the element pointer within the array. It is used to implement the left-side assignment operator for arrays. Note that this is an advanced function that should be used only to implement special array operators.

Return Value

A reference to a CObject pointer.

See Also

»CObArray::operator []«


  CObArray::FreeExtra

void FreeExtra();

Remarks

Frees any extra memory that was allocated while the array was grown. This function has no effect on the size or upper bound of the array.


  CObArray::GetAt

CObject* GetAt( int nIndex ) const;

nIndex    An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

Remarks

Returns the array element at the specified index.

Return Value

The CObject pointer element currently at this index; NULL if no element is stored at the index.

See Also

»CObArray::SetAt«, »CObArray::operator []«

Example

// example for CObArray::GetAt

CObArray array;

array.Add( new CAge( 21 ) ); // Element 0
array.Add( new CAge( 40 ) ); // Element 1
ASSERT( *(CAge*) array.GetAt( 0 ) == CAge( 21 ) );


  CObArray::GetSize

int GetSize() const;

Remarks

Returns the size of the array. Since indexes are zero-based, the size is 1 greater than the largest index.

See Also

»CObArray::GetUpperBound«, »CObArray::SetSize«


  CObArray::GetUpperBound

int GetUpperBound() const;

Remarks

Returns the current upper bound of this array. Because array indexes are zero-based, this function returns a value 1 less than GetSize.

The condition GetUpperBound() = −1 indicates that the array contains no elements.

See Also

»CObArray::GetSize«, »CObArray::SetSize«

Example

// example for CObArray::GetUpperBound

CObArray array;

array.Add( new CAge( 21 ) ); // Element 0
array.Add( new CAge( 40 ) ); // Element 1
ASSERT( array.GetUpperBound() == 1 ); // Largest index


  CObArray::InsertAt

void InsertAt( int nIndex, CObject* newElement, int nCount = 1 )
throw( CMemoryException );

void InsertAt( int nStartIndex, CObArray* pNewArray )
throw( CMemoryException );

nIndex    An integer index that may be greater than the value returned by GetUpperBound.

newElement    The CObject pointer to be placed in this array. A newElement of value NULL is allowed.

nCount    The number of times this element should be inserted (defaults to 1).

nStartIndex    An integer index that may be greater than the value returned by GetUpperBound.

pNewArray    Another array that contains elements to be added to this array.

Remarks

The first version of InsertAt inserts one element (or multiple copies of an element) at a specified index in an array. In the process, it shifts up (by incrementing the index) the existing element at this index, and it shifts up all the elements above it.

The second version inserts all the elements from another CObArray collection, starting at the nStartIndex position.

The SetAt function, in contrast, replaces one specified array element and does not shift any elements.

See Also

»CObArray::SetAt«, »CObArray::RemoveAt«

Example

// example for CObArray::InsertAt

CObArray array;

array.Add( new CAge( 21 ) ); // Element 0
array.Add( new CAge( 40 ) ); // Element 1 (will become 2).
array.InsertAt( 1, new CAge( 30 ) );  // New element 1
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "InsertAt example: " << &array << "\n";
#endif

The results from this program are as follows:

InsertAt example: A CObArray with 3 elements
    [0] = a CAge at $45C8 21
    [1] = a CAge at $4646 30
    [2] = a CAge at $4606 40


  CObArray::RemoveAll

void RemoveAll();

Remarks

Removes all the pointers from this array but does not actually delete the CObject objects. If the array is already empty, the function still works.

The RemoveAll function frees all memory used for pointer storage.

Example

// example for CObArray::RemoveAll

CObArray array;
CAge* pa1;
CAge* pa2;

array.Add( pa1 = new CAge( 21 ) ); // Element 0
array.Add( pa2 = new CAge( 40 ) ); // Element 1
ASSERT( array.GetSize() == 2 );
array.RemoveAll(); // Pointers removed but objects not deleted.
ASSERT( array.GetSize() == 0 );
delete pa1;
delete pa2;  // Cleans up memory.


  CObArray::RemoveAt

void RemoveAt( int nIndex, int nCount = 1 );

nIndex    An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

nCount    The number of elements to remove.

Remarks

Removes one or more elements starting at a specified index in an array. In the process, it shifts down all the elements above the removed element(s). It decrements the upper bound of the array but does not free memory.

If you try to remove more elements than are contained in the array above the removal point, then the Debug version of the library asserts.

The RemoveAt function removes the CObject pointer from the array, but it does not delete the object itself.

See Also

»CObArray::SetAt«, »CObArray::SetAtGrow«, »CObArray::InsertAt«

Example

// example for CObArray::RemoveAt

   CObArray array;
   CObject* pa;

   array.Add( new CAge( 21 ) ); // Element 0
   array.Add( new CAge( 40 ) ); // Element 1
   if( ( pa = array.GetAt( 0 ) ) != NULL )
   {
       array.RemoveAt( 0 );  // Element 1 moves to 0.
       delete pa; // Delete the original element at 0.
   }
#ifdef _DEBUG
   afxDump.SetDepth( 1 );
   afxDump << "RemoveAt example: " << &array << "\n";
#endif

The results from this program are as follows:

RemoveAt example: A CObArray with 1 elements
    [0] = a CAge at $4606 40


  CObArray::SetAt

void SetAt( int nIndex, CObject* newElement );

nIndex    An integer index that is greater than or equal to 0 and less than or equal to the value returned by GetUpperBound.

newElement    The object pointer to be inserted in this array. A NULL value is allowed.

Remarks

Sets the array element at the specified index. SetAt will not cause the array to grow. Use SetAtGrow if you want the array to grow automatically.

You must ensure that your index value represents a valid position in the array. If it is out of bounds, then the Debug version of the library asserts.

See Also

»CObArray::GetAt«, »CObArray::SetAtGrow«, »CObArray::ElementAt«, »CObArray::operator []«

Example

// example for CObArray::SetAt

   CObArray array;
   CObject* pa;

   array.Add( new CAge( 21 ) ); // Element 0
   array.Add( new CAge( 40 ) ); // Element 1
   if( ( pa = array.GetAt( 0 ) ) != NULL )
   {
       array.SetAt( 0, new CAge( 30 ) );  // Replace element 0.
       delete pa; // Delete the original element at 0.
   }
#ifdef _DEBUG
   afxDump.SetDepth( 1 );
   afxDump << "SetAt example: " << &array << "\n";
#endif

The results from this program are as follows:

SetAt example: A CObArray with 2 elements
    [0] = a CAge at $47E0 30
    [1] = a CAge at $47A0 40


  CObArray::SetAtGrow

void SetAtGrow( int nIndex, CObject* newElement )
throw( CMemoryException );

nIndex    An integer index that is greater than or equal to 0.

newElement    The object pointer to be added to this array. A NULL value is allowed.

Remarks

Sets the array element at the specified index. The array grows automatically if necessary (that is, the upper bound is adjusted to accommodate the new element).

See Also

»CObArray::GetAt«, »CObArray::SetAt«, »CObArray::ElementAt«, »CObArray::operator []«

Example

// example for CObArray::SetAtGrow

   CObArray array;

   array.Add( new CAge( 21 ) ); // Element 0
   array.Add( new CAge( 40 ) ); // Element 1
   array.SetAtGrow( 3, new CAge( 65 ) ); // Element 2 deliberately
                                         // skipped.
#ifdef _DEBUG
   afxDump.SetDepth( 1 );
   afxDump << "SetAtGrow example: " << &array << "\n";
#endif

The results from this program are as follows:

SetAtGrow example: A CObArray with 4 elements
    [0] = a CAge at $47C0 21
    [1] = a CAge at $4800 40
    [2] = NULL
    [3] = a CAge at $4840 65


  CObArray::SetSize

To get information on a particular operator, double-click it in the Contents browser.

void SetSize( int nNewSize, int nGrowBy = −1 )
throw( CMemoryException );

nNewSize    The new array size (number of elements). Must be greater than or equal to 0.

nGrowBy    The minimum number of element slots to allocate if a size increase is necessary.

Remarks

Establishes the size of an empty or existing array; allocates memory if necessary.

If the new size is smaller than the old size, then the array is truncated and all unused memory is released.

The nGrowBy parameter affects internal memory allocation while the array is growing. Its use never affects the array size as reported by GetSize and GetUpperBound.


CObArray Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CObArray::operator [ ]

CObject*& operator [ ]( int nIndex );

CObject* operator [ ]( int nIndex ) const;

Remarks

These subscript operators are a convenient substitute for the SetAt and GetAt functions.

The first operator, invoked for arrays that are not const, may be used on either the right (r-value) or the left (l-value) of an assignment statement. The second, invoked for const arrays, may be used only on the right.

The Debug version of the library asserts if the subscript (either on the left or right side of an assignment statement) is out of bounds.

See Also

»CObArray::GetAt«, »CObArray::SetAt«

Example

// example for CObArray::operator []

CObArray array;
CAge* pa;

array.Add( new CAge( 21 ) ); // Element 0
array.Add( new CAge( 40 ) ); // Element 1
pa = (CAge*)array[0]; // Get element 0
ASSERT( *pa == CAge( 21 ) ); // Get element 0
array[0] = new CAge( 30 ); // Replace element 0
delete pa;
ASSERT( *(CAge*) array[0] == CAge( 30 ) ); // Get new element 0


CObject
  class CObject

CObject is the principal base class for the Microsoft Foundation Class Library. It serves as the root not only for library classes such as CFile and CObList, but also for the classes that you write. CObject provides basic services, including:

•	Serialization support

•	Run-time class information

•	Object diagnostic output

•	Compatibility with collection classes

Note that CObject does not support multiple inheritance. Your derived classes can have only one CObject base class, and that CObject must be leftmost in the hierarchy. It is permissible, though, to have structures and non-CObject-derived classes in right-hand multiple-inheritance branches.

You will realize major benefits from CObject derivation if you use some of the optional macros in your class implementation and declarations.

The first-level macros, DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, permit run-time access to the class name and its position in the hierarchy. This, in turn, allows meaningful diagnostic dumping.

The second-level macros, DECLARE_SERIAL and IMPLEMENT_SERIAL, include all the functionality of the first-level macros, and they enable an object to be "serialized" to and from an "archive."

For important information about deriving Microsoft Foundation classes and Visual C++ classes in general, see "How to Derive a Class from CObject" in Chapter 12 of the Class Library User's Guide.

#include <afx.h>


CObject Class Members
  Class Members

Construction/Destruction — Public Members

»~CObject«	Virtual destructor.
»operator new«	Special new operator.
»operator delete«	Special delete operator.
Diagnostics — Public Members

»AssertValid«	Validates this object's integrity.
»Dump«	Produces a diagnostic dump of this object.
Serialization — Public Members

»IsSerializable«	Tests to see if this object can be serialized.
»Serialize«	Loads or stores an object from/to an archive.
Miscellaneous — Public Members

»GetRuntimeClass«	Returns the CRuntimeClass structure corresponding to this object's class.
»IsKindOf«	Tests this object's relationship to a given class.
Construction/Destruction — Protected Members

»CObject«	Default constructor.
Private Members

»CObject«	Copy constructor.
»operator =«	Assignment operator.


CObject Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CObject::AssertValid

virtual void AssertValid() const;

Remarks

AssertValid performs a validity check on this object by checking its internal state. In the Debug version of the library, AssertValid may assert and thus terminate the program with a message that lists the line number and filename where the assertion failed.

When you write your own class, you should override the AssertValid function to provide diagnostic services for yourself and other users of your class. The overridden AssertValid usually calls the AssertValid function of its base class before checking data members unique to the derived class.

Because AssertValid is a const function, you are not permitted to change the object state during the test. Your own derived class AssertValid functions should not throw exceptions but rather should assert if they detect invalid object data.

The definition of "validity" depends on the object's class. As a rule, the function should perform a "shallow check." That is, if an object contains pointers to other objects, it should check to see if the pointers are not null but should not perform validity testing on the objects referred to by the pointers.

 Example

// example for CObject::AssertValid

See »CObList::CObList« for a listing of the CAge class used in all CObject examples.

void CAge::AssertValid() const
{
    CObject::AssertValid();
    ASSERT( m_years > 0 );
    ASSERT( m_years < 105 );
}


  CObject::CObject

Protected

CObject(); ♦

Private

CObject( constCObject& objectSrc ); ♦

objectSrc    A reference to another CObject.

Remarks

These functions are the standard CObject constructors. The default version is automatically called by the constructor of your derived class.

If your class is serializable (it incorporates the IMPLEMENT_SERIAL macro), then you must have a default constructor (a constructor with no arguments) in your class declaration. If you don't need a default constructor, declare a private or protected "empty" constructor. For more information, see "How to Derive a Class from CObject" in Chapter 12 of the Class Library User's Guide.

The standard Visual C++ default class copy constructor does a member-by-member copy. The presence of the private CObject copy constructor guarantees a compiler error message if the copy constructor of your class is needed but not available. You must, therefore, provide a copy constructor if your class requires this capability.


  CObject::~CObject

virtual ~CObject();

Remarks

This function is the standard CObject destructor. If your derived class must free allocated memory or do other cleanup work, you must provide your own destructor. Because ~CObject is a virtual destructor, Visual C++ ensures that CObject::~CObject is automatically called as part of the destructor of your class.

Note  Your destructor should not throw exceptions or allocate objects.


  CObject::Dump

virtual void Dump( CDumpContext& dc ) const;

dc    The diagnostic dump context for dumping, usually afxDump.

Remarks

Dumps the contents of your object to a »CDumpContext« object.

When you write your own class, you should override the Dump function to provide diagnostic services for yourself and other users of your class. The overridden Dump usually calls the Dump function of its base class before printing data members unique to the derived class. CObject::Dump prints the class name if your class uses the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macro.

Note  Your Dump function should not print a newline character at the end of its output.

Dump calls make sense only in the Debug version of the Microsoft Foundation Class Library. Bracket calls, function declarations, and function implementations with #ifdef _DEBUG/#endif statements for conditional compilation.

Since Dump is a const function, you are not permitted to change the object state during the dump.

The »CDumpContext insertion (<<) operator« calls Dump when a CObject pointer is inserted.

Dump permits only "acyclic" dumping of objects. You can dump a list of objects, for example, but if one of the objects is the list itself, you will eventually overflow the stack.

 Example

// example for CObject::Dump

void CAge::Dump( CDumpContext &dc ) const
 {
 CObject::Dump( dc );
 dc << "Age = " << m_years;
 }


  CObject::GetRuntimeClass

virtual CRuntimeClass* GetRuntimeClass() const;

Remarks

There is one CRuntimeClass structure for each CObject-derived class. The structure members are as follows:

•	const char* m_pszClassName    A null-terminated string containing the ASCII class name.

•	int m_nObjectSize    The actual size of the object. If the object has data members that point to allocated memory, the size of that memory is not included.

•	WORD m_wSchema    The schema number (−1 for nonserializable classes). See the »IMPLEMENT_SERIAL« macro for a description of schema number.

•	void (*m_pfnConstruct)(void* p)    A pointer to the default constructor of your class (valid only if the class is serializable).

•	CRuntimeClass* m_pBaseClass    A pointer to the CRuntimeClass structure that corresponds to the base class.

This function requires use of the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macros in the class implementation. You will get incorrect results otherwise.

Return Value

A pointer to the CRuntimeClass structure corresponding to this object's class; never NULL.

See Also

»CObject::IsKindOf«, »RUNTIME_CLASS Macro«

 Example

// example for CObject::GetRuntimeClass

CAge a(21);
CRuntimeClass* prt = a.GetRuntimeClass();
ASSERT( strcmp( prt->m_pszClassName, "CAge" )  == 0 );


  CObject::IsKindOf

BOOL IsKindOf( const CRuntimeClass* pClass ) const;

pClass    A pointer to a CRuntimeClass structure associated with your CObject-derived class.

Remarks

Tests pClass to see if (1) it is an object of the specified class or (2) it is an object of a class derived from the specified class. This function only works for classes declared with the DECLARE_DYNAMIC or DECLARE_SERIAL macros.

Do not use this function extensively because it defeats the Visual C++ polymorphism feature. Use virtual functions instead.

Return Value

Nonzero if the object corresponds to the class; otherwise 0.

See Also

»CObject::GetRuntimeClass«, »RUNTIME_CLASS Macro«

 Example

// example for CObject::IsKindOf

CAge a(21); // Must use IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL
ASSERT( a.IsKindOf( RUNTIME_CLASS( CAge ) ) );
ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );


  CObject::IsSerializable

BOOL IsSerializable() const;

Remarks

Tests whether this object is eligible for serialization. For a class to be serializable, its declaration must contain the DECLARE_SERIAL macro, and the implementation must contain the IMPLEMENT_SERIAL macro.

Note  Do not override this function.

Return Value

Nonzero if this object can be serialized; otherwise 0.

See Also

»CObject::Serialize«

 Example

// example for CObject::IsKindOf

CAge a(21);
ASSERT( a.IsSerializable() );


  CObject::Serialize

virtual void Serialize( CArchive& ar )
throw( CMemoryException, CArchiveException, CFileException );

ar    A CArchive object to serialize to or from.

Remarks

Reads or writes this object from or to an archive.

You must override Serialize for each class that you intend to serialize. The overridden Serialize must first call the Serialize function of its base class.

You must also use the DECLARE_SERIAL macro in your class declaration, and you must use the IMPLEMENT_SERIAL macro in the implementation.

Use »CArchive::IsLoading« or »CArchive::IsStoring« to determine whether the archive is loading or storing.

Serialize is called by »CArchive::ReadObject« and »CArchive::WriteObject«. These functions are associated with the CArchive insertion operator (<<) and extraction operator (>>).

For serialization examples, refer to both the cookbook and the tutorial in the Class Library User's Guide.

 Example

// example for CObject::IsSerializable

void CAge::Serialize( CArchive& ar )
 {
 CObject::Serialize( ar );
     if( ar.IsStoring() )
     ar << m_years;
     else
     ar >> m_years;
 }


CObject Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CObject::operator =

Private

void operator =( const CObject& src ); ♦

Remarks

The standard Visual C++ default class assignment behavior is a member-by-member copy. The presence of this private assignment operator guarantees a compiler error message if you assign without the overridden operator. You must, therefore, provide an assignment operator in your derived class if you intend to assign objects of your derived class.


  CObject::operator delete

void operator delete( void* p );

Remarks

For the Release version of the library, operator delete simply frees the memory allocated by operator new. In the Debug version, operator delete participates in an allocation-monitoring scheme designed to detect memory leaks. If you override operators new and delete, you forfeit the diagnostic capability.

See Also

»CObject::operator new«


  CObject::operator new

void* operator new( size_t nSize )
throw( CMemoryException );

void* operator new( size_t nSize, const char FAR* lpszFileName, int nLine )
throw( CMemoryException );

Remarks

For the Release version of the library, operator new performs an optimal memory allocation in a manner similar to malloc. In the Debug version, operator new participates in an allocation-monitoring scheme designed to detect memory leaks.

If you use the code line

#define new DEBUG_NEW

before any of your implementations in a .CPP file, then the second version of new will be used, storing the filename and line number in the allocated block for later reporting. You do not have to worry about supplying the extra parameters; a macro takes care of that for you.

Even if you don't use DEBUG_NEW in Debug mode, you still get leak detection but without the source-file line-number reporting described above.

Note  If you override this operator, you must also override delete. Do not use the standard library _new_handler function.

See Also

»CObject::operator delete«


CObList
  class CObList : public CObject

The CObList class supports ordered lists of nonunique CObject pointers accessible sequentially or by pointer value. CObList lists behave like doubly-linked lists.

A variable of type POSITION is a key for the list. You can use a POSITION variable as an iterator to sequentially traverse a list and as a bookmark to hold a place. A position is not the same as an index, however.

Element insertion is very fast at the list head, at the tail, and at a known POSITION. A sequential search is necessary to look up an element by value or index. This search can be slow if the list is long.

CObList incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If a list of CObject pointers is stored to an archive, either with an overloaded insertion operator or with the Serialize member function, each CObject element is, in turn, serialized.

If you need a dump of individual CObject elements in the list, you must set the depth of the dump context to 1 or greater.

When a CObList object is deleted, or when its elements are removed, only the CObject pointers are removed, not the objects they reference.

You can derive your own classes from CObList. Your new list class, designed to hold pointers to objects derived from CObject, adds new data members and new member functions. Note that the resulting list is not strictly type safe because it allows insertion of any CObject pointer.

Note  You must use the IMPLEMENT_SERIAL macro in the implementation of your derived class if you intend to serialize the list.

#include <afxcoll.h>

See Also

»CStringList«, »CPtrList«


CObList Class Members
  Class Members

Construction/Destruction — Public Members

»CObList«	Constructs an empty list for CObject pointers.
Head/Tail Access — Public Members

»GetHead«	Returns the head element of the list (cannot be empty).
»GetTail«	Returns the tail element of the list (cannot be empty).
Operations — Public Members

»RemoveHead«	Removes the element from the head of the list.
»RemoveTail«	Removes the element from the tail of the list.
»AddHead«	Adds an element (or all the elements in another list) to the head of the list (makes a new head).
»AddTail«	Adds an element (or all the elements in another list) to the tail of the list (makes a new tail).
»RemoveAll«	Removes all the elements from this list.
Iteration — Public Members

»GetHeadPosition«	Returns the position of the head element of the list.
»GetTailPosition«	Returns the position of the tail element of the list.
»GetNext«	Gets the next element for iterating.
»GetPrev«	Gets the previous element for iterating.
Retrieval/Modification — Public Members

»GetAt«	Gets the element at a given position.
»SetAt«	Sets the element at a given position.
»RemoveAt«	Removes an element from this list, specified by position.
Insertion — Public Members

»InsertBefore«	Inserts a new element before a given position.
»InsertAfter«	Inserts a new element after a given position.
Searching — Public Members

»Find«	Gets the position of an element specified by pointer value.
»FindIndex«	Gets the position of an element specified by a zero-based index.
Status — Public Members

»GetCount«	Returns the number of elements in this list.
»IsEmpty«	Tests for the empty list condition (no elements).


ObList Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CObList::AddHead

POSITION AddHead( CObject* newElement )
throw( CMemoryException );

void AddHead( CObList* pNewList )
throw( CMemoryException );

newElement    The CObject pointer to be added to this list.

pNewList    A pointer to another CObList list. The elements in pNewList will be added to this list.

Remarks

Adds a new element or list of elements to the head of this list. The list may be empty before the operation.

Return Value

The first version returns the POSITION value of the newly inserted element.

See Also

»CObList::GetHead«, »CObList::RemoveHead«

 Example

CObList list;
list.AddHead( new CAge( 21 ) ); // 21 is now at head.
list.AddHead( new CAge( 40 ) ); // 40 replaces 21 at head.
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "AddHead example: " << &list << "\n";
#endif

The results from this program are as follows:

AddHead example: A CObList with 2 elements
    a CAge at $44A8 40
    a CAge at $442A 21


  CObList::AddTail

POSITION AddTail( CObject* newElement )
throw( CMemoryException );

void AddTail( CObList* pNewList )
throw( CMemoryException );

newElement    The CObject pointer to be added to this list.

pNewList    A pointer to another CObList list. The elements in pNewList will be added to this list.

Remarks

Adds a new element or list of elements to the tail of this list. The list may be empty before the operation.

Return Value

The first version returns the POSITION value of the newly inserted element.

See Also

»CObList::GetTail«, »CObList::RemoveTail«

 Example

CObList list;
list.AddTail( new CAge( 21 ) );
list.AddTail( new CAge( 40 ) ); // List now contains (21, 40).
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "AddTail example: " << &list << "\n";
#endif

The results from this program are as follows:

AddTail example: A CObList with 2 elements
     a CAge at $444A 21
     a CAge at $4526 40


  CObList::CObList

CObList( int nBlockSize = 10 );

nBlockSize    The memory-allocation granularity for extending the list.

Remarks

Constructs an empty CObject pointer list.  As the list grows, memory is allocated in units of nBlockSize entries. If a memory allocation fails, a CMemoryException is thrown.

 Example

Below is a listing of the CObject-derived class CAge used in all the collection examples:

// Simple CObject-derived class for CObList examples
class CAge : public CObject
{
    DECLARE_SERIAL( CAge )
private:
    int	m_years;
public:
    CAge() { m_years = 0; }
    CAge( int age ) { m_years = age; }
    CAge( const CAge& a ) { m_years = a.m_years; } // Copy constructor
    void Serialize( CArchive& ar);
    void AssertValid() const;
    const CAge& operator=( const CAge& a )
    {
        m_years = a.m_years; return *this;
    }
    BOOL operator==(CAge a)
    {
        return m_years == a.m_years;
    }
 #ifdef _DEBUG
    void Dump( CDumpContext& dc ) const
    {
        CObject::Dump( dc );
        dc << m_years;
    }
 #endif
};

Below is an example of CObList constructor usage:

CObList list( 20 );  // List on the stack with blocksize = 20.

CObList* plist = new CObList; // List on the heap with default
                              // blocksize.


  CObList::Find

POSITION Find( CObject* searchValue, POSITION startAfter = NULL ) const;

searchValue    The object pointer to be found in this list.

startAfter    The start position for the search.

Remarks

Searches the list sequentially to find the first CObject pointer matching the specified CObject pointer. Note that the pointer values are compared, not the contents of the objects.

Return Value

A POSITION value that can be used for iteration or object pointer retrieval; NULL if the object is not found.

See Also

»CObList::GetNext«, »CObList::GetPrev«

 Example

CObList list;
CAge* pa1;
CAge* pa2;
POSITION pos;
list.AddHead( pa1 = new CAge( 21 ) );
list.AddHead( pa2 = new CAge( 40 ) );    // List now contains (40, 21).
if( ( pos = list.Find( pa1 ) ) != NULL ) // Hunt for pa1
{                                        // starting at head by default.
    ASSERT( *(CAge*) list.GetAt( pos ) == CAge( 21 ) );
}


  CObList::FindIndex

POSITION FindIndex( int nIndex ) const;

nIndex    The zero-based index of the list element to be found.

Remarks

Uses the value of nIndex as an index into the list. It starts a sequential scan from the head of the list, stopping on the nth element.

Return Value

A POSITION value that can be used for iteration or object pointer retrieval; NULL if nIndex is negative or too large.

See Also

»CObList::Find«, »CObList::GetNext«, »CObList::GetPrev«

 Example

CObList list;
POSITION pos;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos = list.FindIndex( 0 )) != NULL )
{
    ASSERT( *(CAge*) list.GetAt( pos ) == CAge( 40 ) );
}


  CObList::GetAt

CObject*& GetAt( POSITION position );

CObject* GetAt( POSITION position ) const;

position    A POSITION value returned by a previous GetHeadPosition or Find member function call.

Remarks

A variable of type POSITION is a key for the list. It is not the same as an index, and you cannot operate on a POSITION value yourself. GetAt retrieves the CObject pointer associated with a given position.

You must ensure that your POSITION value represents a valid position in the list. If it is invalid, then the Debug version of the Microsoft Foundation Class Library asserts.

Return Value

See the return value description for »GetHead«.

See Also

»CObList::Find«, »CObList::SetAt«, »CObList::GetNext«, »CObList::GetPrev«, »CObList::GetHead«

 Example

See the example for »FindIndex«.


  CObList::GetCount

int GetCount() const;

Remarks

Gets the number of elements in this list.

Return Value

An integer value containing the element count.

See Also

»CObList::IsEmpty«

 Example

CObList list;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( list.GetCount() == 2 );


  CObList::GetHead

CObject*& GetHead();

CObject* GetHead() const;

Remarks

Gets the CObject pointer that represents the head element of this list.

You must ensure that the list is not empty before calling GetHead. If the list is empty, then the Debug version of the Microsoft Foundation Class Library asserts. Use »IsEmpty« to verify that the list contains elements.

Return Value

If the list is accessed through a pointer to a const CObList, then GetHead returns a CObject pointer. This allows the function to be used only on the right side of an assignment statement and thus protects the list from modification.

If the list is accessed directly or through a pointer to a CObList, then GetHead returns a reference to a CObject pointer. This allows the function to be used on either side of an assignment statement and thus allows the list entries to be modified.

See Also

»CObList::GetTail«, »CObList::GetTailPosition«, »CObList::AddHead«, »CObList::RemoveHead«

 Example

The following example illustrates the use of GetHead on the left side of an assignment statement.

   const CObList* cplist;

   CObList* plist = new CObList;
   CAge* page1 = new CAge( 21 );
   CAge* page2 = new CAge( 30 );
   CAge* page3 = new CAge( 40 );
   plist->AddHead( page1 );
   plist->AddHead( page2 );  // List now contains (30, 21).
   // The following statement REPLACES the head element.
   plist->GetHead() = page3; // List now contains (40, 21).
   ASSERT( *(CAge*) plist->GetHead() == CAge( 40 ) );
   cplist = plist;  // cplist is a pointer to a const list.
// cplist->GetHead() = page3; // Does not compile!
   ASSERT( *(CAge*) plist->GetHead() == CAge( 40 ) ); // OK

   delete page1;
   delete page2;
   delete page3;
   delete plist; // Cleans up memory.


  CObList::GetHeadPosition

POSITION GetHeadPosition() const;

Remarks

Gets the position of the head element of this list.

Return Value

A POSITION value that can be used for iteration or object pointer retrieval; NULL if the list is empty.

See Also

»CObList::GetTailPosition«

 Example

CObList list;
POSITION pos;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos = list.GetHeadPosition() ) != NULL )
{
    ASSERT( *(CAge*) list.GetAt( pos ) == CAge( 40 ) );
}


  CObList::GetNext

CObject*& GetNext( POSITION& rPosition );

CObject* GetNext( POSITION& rPosition ) const;

rPosition    A reference to a POSITION value returned by a previous GetNext, GetHeadPosition, or other member function call.

Remarks

Gets the list element identified by rPosition, then sets rPosition to the POSITION value of the next entry in the list. You can use GetNext in a forward iteration loop if you establish the initial position with a call to GetHeadPosition or Find.

You must ensure that your POSITION value represents a valid position in the list. If it is invalid, then the Debug version of the Microsoft Foundation Class Library asserts.

If the retrieved element is the last in the list, then the new value of rPosition is set to NULL.

It is possible to remove an element during an iteration. See the example for »RemoveAt«.

Return Value

See the return value description for »GetHead«.

See Also

»CObList::Find«, »CObList::GetHeadPosition«, »CObList::GetTailPosition«, »CObList::GetPrev«, »CObList::GetHead«

 Example

CObList list;
POSITION pos;
list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
// Iterate through the list in head-to-tail order.
#ifdef _DEBUG
for( pos = list.GetHeadPosition(); pos != NULL; )
{
    afxDump << list.GetNext( pos ) << "\n";
}
#endif

The results from this program are as follows:

a CAge at $479C 40
a CAge at $46C0 21


  CObList::GetPrev

CObject*& GetPrev( POSITION& rPosition );

CObject* GetPrev( POSITION& rPosition ) const;

rPosition    A reference to a POSITION value returned by a previous GetPrev or other member function call.

Remarks

Gets the list element identified by rPosition, then sets rPosition to the POSITION value of the previous entry in the list. You can use GetPrev in a reverse iteration loop if you establish the initial position with a call to GetTailPosition or Find.

You must ensure that your POSITION value represents a valid position in the list. If it is invalid, then the Debug version of the Microsoft Foundation Class Library asserts.

If the retrieved element is the first in the list, then the new value of rPosition is set to NULL.

Return Value

See the return value description for »GetHead«.

See Also

»CObList::Find«, »CObList::GetTailPosition«, »CObList::GetHeadPosition«, »CObList::GetNext«, »CObList::GetHead«

 Example

CObList list;
POSITION pos;

list.AddHead( new CAge(21) );
list.AddHead( new CAge(40) ); // List now contains (40, 21).
// Iterate through the list in tail-to-head order.
for( pos = list.GetTailPosition(); pos != NULL; )
{
#ifdef _DEBUG
    afxDump << list.GetPrev( pos ) << "\n";
#endif
}

The results from this program are as follows:

a CAge at $421C 21
a CAge at $421C 40


  CObList::GetTail

CObject*& GetTail();

CObject* GetTail() const;

Remarks

Gets the CObject pointer that represents the tail element of this list.

You must ensure that the list is not empty before calling GetTail. If the list is empty, then the Debug version of the Microsoft Foundation Class Library asserts. Use »IsEmpty« to verify that the list contains elements.

Return Value

See the return value description for »GetHead«.

See Also

»CObList::AddTail«, »CObList::AddHead«, »CObList::RemoveHead«, »CObList::GetHead«

 Example

CObList list;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( *(CAge*) list.GetTail() == CAge( 21 ) );


  CObList::GetTailPosition

POSITION GetTailPosition() const;

Remarks

Gets the position of the tail element of this list; NULL if the list is empty.

Return Value

A POSITION value that can be used for iteration or object pointer retrieval; NULL if the list is empty.

See Also

»CObList::GetHeadPosition«, »CObList::GetTail«

 Example

CObList list;
POSITION pos;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos = list.GetTailPosition() ) != NULL )
{
    ASSERT( *(CAge*) list.GetAt( pos ) == CAge( 21 ) );
}


  CObList::InsertAfter

POSITION InsertAfter( POSITION position, CObject* newElement )
throw ( CMemoryException );

position    A POSITION value returned by a previous GetNext, GetPrev, or Find member function call.

newElement    The object pointer to be added to this list.

Remarks

Adds an element to this list after the element at the specified position.

See Also

»CObList::Find«, »CObList::InsertBefore«

 Example

CObList list;
POSITION pos1, pos2;
list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos1 = list.GetHeadPosition() ) != NULL )
{
    pos2 = list.InsertAfter( pos1, new CAge( 65 ) );
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "InsertAfter example: " << &list << "\n";
#endif

The results from this program are as follows:

InsertAfter example: A CObList with 3 elements
     a CAge at $4A44 40
     a CAge at $4A64 65
     a CAge at $4968 21


  CObList::InsertBefore

POSITION InsertBefore( POSITION position, CObject* newElement )
throw ( CMemoryException );

position    A POSITION value returned by a previous GetNext, GetPrev, or Find member function call.

newElement    The object pointer to be added to this list.

Remarks

Adds an element to this list before the element at the specified position.

Return Value

A POSITION value that can be used for iteration or object pointer retrieval; NULL if the list is empty.

See Also

»CObList::Find«, »CObList::InsertAfter«

 Example

CObList list;
POSITION pos1, pos2;
list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos1 = list.GetTailPosition() ) != NULL )
{
    pos2 = list.InsertBefore( pos1, new CAge( 65 ) );
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "InsertBefore example: " << &list << "\n";
#endif

The results from this program are as follows:

InsertBefore example: A CObList with 3 elements
    a CAge at $4AE2 40
    a CAge at $4B02 65
    a CAge at $49E6 21


  CObList::IsEmpty

BOOL IsEmpty() const;

Remarks

Indicates if this list contains no elements.

Return Value

Nonzero if this list is empty; otherwise 0.

See Also

»CObList::GetCount«

 Example

See the example for »RemoveAll«.


  CObList::RemoveAll

void RemoveAll();

Remarks

Removes all the elements from this list and frees the associated CObList memory. No error is generated if the list is already empty.

When you remove elements from a CObList, you remove the object pointers from the list. It is your responsibility to delete the objects themselves.

 Example

CObList list;
CAge* pa1;
CAge* pa2;
ASSERT( list.IsEmpty()); // Yes it is.
list.AddHead( pa1 = new CAge( 21 ) );
list.AddHead( pa2 = new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( !list.IsEmpty()); // No it isn't.
list.RemoveAll(); // CAge's aren't destroyed.
ASSERT( list.IsEmpty()); // Yes it is.
delete pa1;     // Now delete the CAge objects.
delete pa2;


  CObList::RemoveAt

void RemoveAt( POSITION position );

position    The position of the element to be removed from the list.

Remarks

Removes the specified element from this list.

When you remove an element from a CObList, you remove the object pointer from the list.  It is your responsibility to delete the objects themselves.

You must ensure that your POSITION value represents a valid position in the list. If it is invalid, then the Debug version of the Microsoft Foundation Class Library asserts.

 Example

Be careful when removing an element during a list iteration. The following example shows a removal technique that guarantees a valid POSITION value for »GetNext«:

CObList list;
POSITION pos1, pos2;
CObject* pa;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) );
list.AddHead( new CAge( 65 ) ); // List now contains (65 40, 21).
for( pos1 = list.GetHeadPosition(); ( pos2 = pos1 ) != NULL; )
{
    if( *(CAge*) list.GetNext( pos1 ) == CAge( 40 ) )
    {
        pa = list.GetAt( pos2 ); // Save the old pointer for
                         //deletion.
        list.RemoveAt( pos2 );
        delete pa; // Deletion avoids memory leak.
    }
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "RemoveAt example: " << &list << "\n";
#endif

The results from this program are as follows:

RemoveAt example: A CObList with 2 elements
    a CAge at $4C1E 65
    a CAge at $4B22 21


  CObList::RemoveHead

CObject* RemoveHead();

Remarks

Removes the element from the head of the list and returns a pointer to it.

You must ensure that the list is not empty before calling RemoveHead. If the list is empty, then the Debug version of the Microsoft Foundation Class Library asserts. Use »IsEmpty« to verify that the list contains elements.

Return Value

The CObject pointer previously at the head of the list.

See Also

»CObList::GetHead«, »CObList::AddHead«

 Example

CObList list;
CAge* pa1;
CAge* pa2;

list.AddHead( pa1 = new CAge( 21 ) );
list.AddHead( pa2 = new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( *(CAge*) list.RemoveHead() == CAge( 40 ) );  // Old head
ASSERT( *(CAge*) list.GetHead() == CAge( 21 ) );  // New head
delete pa1;
delete pa2;


  CObList::RemoveTail

CObject* RemoveTail();

Remarks

Removes the element from the tail of the list and returns a pointer to it.

You must ensure that the list is not empty before calling RemoveTail. If the list is empty, then the Debug version of the Microsoft Foundation Class Library asserts. Use »IsEmpty« to verify that the list contains elements.

Return Value

A pointer to the object that was at the tail of the list.

See Also

»CObList::GetTail«, »CObList::AddTail«

 Example

CObList list;
CAge* pa1;
CAge* pa2;

list.AddHead( pa1 = new CAge( 21 ) );
list.AddHead( pa2 = new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( *(CAge*) list.RemoveTail() == CAge( 21 ) );  // Old tail
ASSERT( *(CAge*) list.GetTail() == CAge( 40 ) );  // New tail
delete pa1;
delete pa2; // Clean up memory.


  CObList::SetAt

void SetAt( POSITION pos, CObject* newElement );

pos    The POSITION of the element to be set.

newElement    The CObject pointer to be written to the list.

Remarks

A variable of type POSITION is a key for the list. It is not the same as an index, and you cannot operate on a POSITION value yourself. SetAt writes the CObject pointer to the specified position in the list.

You must ensure that your POSITION value represents a valid position in the list. If it is invalid, then the Debug version of the Microsoft Foundation Class Library asserts.

See Also

»CObList::Find«, »CObList::GetAt«, »CObList::GetNext«, »CObList::GetPrev«

 Example

CObList list;
CObject* pa;
POSITION pos;

list.AddHead( new CAge( 21 ) );
list.AddHead( new CAge( 40 ) ); // List now contains (40, 21).
if( ( pos = list.GetTailPosition()) != NULL )
{
    pa = list.GetAt( pos ); // Save the old pointer for
                    //deletion.
    list.SetAt( pos, new CAge( 65 ) );  // Replace the tail
                                //element.
    delete pa;  // Deletion avoids memory leak.
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "SetAt example: " << &list << "\n";
#endif

The results from this program are as follows:

SetAt example: A CObList with 2 elements
    a CAge at $4D98 40
    a CAge at $4DB8 65


COleClientDoc
  class COleClientDoc : public COleDocument

COleClientDoc is the base class for Object Linking and Embedding (OLE) client documents. A client document can contain COleClientItem objects as well as any data created by the client application itself. The COleClientItem objects represent embedded items, which contain data created by other applications (servers), or linked items, which contain links to files created by servers.

To use COleClientDoc, derive a class from it and design a data structure for storing the application's native data as well as embedded or linked items. If you use CDocItem-derived classes to store the application's native data, you can use the interface defined by COleDocument to manipulate a document as a collection of items. This allows you to treat the application's native data in the same way you treat embedded or linked items.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»COleDocument«, »COleClientItem«


COleClientDoc Class Members
  Class Members

Construction/Destruction — Public Members

»COleClientDoc«	Constructs a COleClientDoc object.
Registration/Revocation — Public Members

»RegisterClientDoc«	Registers a client document with the OLE system dynamic-link library (DLL).
»Revoke«	Revokes the client document registration.
Operations — Public Members

»GetPrimarySelectedItem«	Returns primary selected item in the document.
»NotifyRename«	Notifies the OLE system DLL that the client document has been renamed.
»NotifyRevert«	Notifies the OLE system DLL that the client document has reverted to its previous state.
»NotifySaved«	Notifies the OLE system DLL that the client document has been saved.


COleCDoc Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleClientDoc::COleClientDoc

COleClientDoc();

Remarks

Creates a COleClientDoc object. It does not register the document with the OLE system DLL. You must call the RegisterClientDoc member function before you can create embedded or linked items.

See Also

»COleClientDoc::RegisterClientDoc«


  COleClientDoc::GetPrimarySelectedItem

virtual COleClientItem* GetPrimarySelectedItem( CView* pView );

pView    A pointer to the active view object displaying the document.

Remarks

Call this function to get the currently selected OLE item in the specified view. If one and only one COleClientItem object is selected, the function returns a pointer to it; otherwise the function returns NULL. You must implement the IsSelected member function in your view class for this function to work.

Return Value

A pointer to the single, selected OLE item; NULL if there are no OLE items selected or if there are more than one selected.

See Also

»CView::IsSelected«


  COleClientDoc::NotifyRename

void NotifyRename( LPCSTR lpszNewName );

lpszNewName    Pointer to the new name of the document. Must be a valid filename.

Remarks

Call this function after the user renames the client document. In the case where the user chooses the Save As command from the File menu, NotifyRename is called for you by COleClientDoc's implementation of the OnSaveDocument member function. This function notifies the OLE system DLL.

See Also

»COleClientDoc::NotifyRevert«, »COleClientDoc::NotifySaved«, »CDocument::OnSaveDocument«, ::OleRenameClientDoc


  COleClientDoc::NotifyRevert

void NotifyRevert();

Remarks

Call this function after the user reverts the client document, that is, reloads it without saving changes. This function notifies the OLE system DLL.

See Also

»COleClientDoc::NotifyRename«, »COleClientDoc::NotifySaved«, ::OleRevertClientDoc


  COleClientDoc::NotifySaved

void NotifySaved();

Remarks

Call this function after the user saves the client document. In the case where the user chooses the Save command from the File menu, NotifySaved is called for you by COleClientDoc's implementation of OnSaveDocument. This function notifies the OLE system DLL.

See Also

»COleClientDoc::NotifyRename«, »COleClientDoc::NotifyRevert«, »CDocument::OnSaveDocument«, ::OleSavedClientDoc


  COleClientDoc::RegisterClientDoc

BOOL RegisterClientDoc( LPCSTR lpszTypeName, LPCSTR lpszDoc );

lpszTypeName    Pointer to the name of the client document's type, usually the client application name.

lpszDoc    Pointer to the fully qualified name of the client document.

Remarks

Call this function to register your client document with the OLE system DLL; this allows the client to interact with server applications. When the user chooses the File New or File Open commands, RegisterClientDoc is called for you by COleClientDoc's implementation of OnNewDocument or OnOpenDocument, respectively.

When a document being copied onto the Clipboard exists only because the client application is copying Native data that contains objects, the name specified in the lpszDoc parameter must be "Clipboard."

Return Value

Nonzero if the document was successfully registered with the OLE system DLL; otherwise 0.

See Also

»COleClientDoc::COleClientDoc«,  »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«, ::OleRegisterClientDoc


  COleClientDoc::Revoke

void Revoke();

Remarks

Call this function to revoke a client document, that is, inform the OLE system DLL that the document is closed. This function is called by the COleClientDoc destructor, so you rarely need to call it explicitly. Revoke may be called for an already revoked document with no ill effects.

Before you call Revoke, you must delete or call COleClientItem::Release or COleClientItem::Delete for each item in the document.

See Also

»COleClientItem::Release«, »COleClientItem::Delete«, ::OleRevokeClientDoc


COleClientItem
  class COleClientItem : public CDocItem

The COleClientItem class defines the client interface to Object Linking and Embedding (OLE) items. An OLE item represents data incorporated into a client application's document but created by a server application; a document containing OLE items is called a "compound document."

An item can be either embedded or linked. If it is embedded, its data is stored in the compound document. If it is linked, its data is stored as part of a separate file created by the server application and only a link to that file is stored in the compound document. All items contain information specifying the server application that should be invoked to edit them.

COleClientItem defines several overridable functions that are called indirectly by the OLE system dynamic-link library (DLL), usually in response to notifications from the server application. This allows the server application to inform the client of changes that the user makes when editing the item.

To use COleClientItem, derive a class from it and implement the OnChange member function. This function defines how the client responds to changes made to the item.

Each item must be given a name that is unique within the document. An item's name must be preserved when the document is saved and cannot contain the "/" or "\" characters.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»CDocItem«, »COleClientDoc«, »COleServerItem«


COleClientItem Class Members
  Class Members

Construction/Destruction — Public Members

»COleClientItem«	Constructs a COleClientItem object.
Creation — Public Members

»CreateFromClipboard«	Creates an embedded item from the Clipboard.
»CreateInvisibleObject«	Creates an invisible embedded item.
»CreateStaticFromClipboard«	Creates an embedded picture of an item from the Clipboard.
»CreateLinkFromClipboard«	Creates a linked item from the Clipboard.
»CreateNewObject«	Creates a new embedded item by launching the server application.
»CreateCloneFrom«	Creates a duplicate of an existing item.
Status — Public Members

»GetLastStatus«	Returns the status of the last OLE operation.
»GetType«	Returns the type (embedded, linked, or static) of the item.
»GetName«	Returns the name of the item.
»GetSize«	Returns the size of the item.
»GetBounds«	Returns the bounds of the item's rectangle.
»IsOpen«	Indicates whether the item is currently attached to the OLE system DLL.
Data Access — Public Members

»EnumFormats«	Enumerates the Clipboard formats supported by an item.
»GetData«	Gets data from an item in a specified format.
»SetData«	Stores data to an item in a specified format.
»RequestData«	Initiates a data request from a server.
»IsEqual«	Compares two items.
»GetDocument«	Returns the COleClientDoc object that contains this item.
Global State — Public Members

»InWaitForRelease«	Indicates whether any item is still waiting for a server to respond.
Clipboard Helpers — Public Members

»CanPaste«	Indicates whether the Clipboard contains an embeddable or static OLE item.
»CanPasteLink«	Indicates whether the Clipboard contains a linkable OLE item.
Linked Object Status — Public Members

»GetLinkUpdateOptions«	Returns the update mode for a linked item (advanced feature).
»SetLinkUpdateOptions«	Sets the update mode for a linked item (advanced feature).
General Operations — Public Members

»Release«	Releases the connection to an OLE linked item and closes it if it was open. Does not destroy the server item.
»Delete«	Deletes the item or closes it if it was a linked item.
»Draw«	Draws the item.
»DoVerb«	Executes the specified verb.
»Activate«	Opens the item for an operation, then executes the specified verb.
Advanced Operations — Public Members

»Rename«	Renames the item.
»CopyToClipboard«	Copies the item to the Clipboard.
»SetTargetDevice«	Sets the target device used by the server to draw the item.
Embedded Object Operations — Public Members

»SetHostNames«	Sets the names the server displays when editing the item.
»SetBounds«	Sets the bounding rectangle of the item.
»SetColorScheme«	Sets the item's color scheme.
Linked Object Operations — Public Members

»UpdateLink«	Updates a link to a server.
»CloseLink«	Closes a link to a server but does not destroy the item.
»ReconnectLink«	Reconnects a linked item to a server.
Overridables — Protected Members

»OnChange«	Called when the server changes the item. Implementation required.
»OnRenamed«	Called when the server renames a document containing the item.


COleClientItem Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleClientItem::Activate

void Activate( UINT nVerb, BOOL bShow = TRUE,
BOOL bTakeFocus = TRUE,
CWnd* pWndContainer = NULL, LPCRECT lpBounds = NULL );

nVerb    Index of the verb to execute; 0 is the primary verb, 1 is the secondary verb, and so forth.

bShow    TRUE if the server window is to be shown; FALSE if the server should remain active without being visible.

bTakeFocus    TRUE if the server should receive the input focus. Relevant only if bShow is TRUE.

pWndContainer    Pointer to the client window object that contains the item.

lpBounds    Pointer to a RECT structure or CRect object that contains the bounding rectangle in which the destination document displays the item. Units are determined by the device-context mapping mode. Can be NULL.

Remarks

Call this function to execute the specified verb if you want full control of how the server will be displayed. For default server behavior, call the DoVerb member function to execute a verb. Both functions cause the OnDoVerb member function of COleServerItem to be executed. If the verb specified is Edit, the server application is launched in a separate window and editing occurs asynchronously.

You typically specify the primary verb when the user of the client application double-clicks the item. The action taken in response to each verb depends on the server. If the server supports only one action, it takes that action no matter which value is specified in the nVerb parameter.

See Also

»COleClientItem::DoVerb«, »COleServerItem::OnDoVerb«, ::OleActivate


  COleClientItem::CanPaste

static BOOL PASCAL CanPaste( OLEOPT_RENDER renderopt = olerender_draw, OLECLIPFORMAT cfFormat = 0 );

renderopt    Flag specifying how the server will render the item. For possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to see if an embedded item can be pasted from the Clipboard. This function is called for you by the framework when enabling or disabling the Paste command on the Edit menu.

Return Value

Nonzero if the Clipboard currently contains an embeddable or static (metafile-based) OLE item; otherwise 0.

See Also

»COleClientItem::CanPasteLink«, »COleClientItem::CreateFromClipboard«, »COleClientItem::CreateStaticFromClipboard«, ::OleQueryCreateFromClip


  COleClientItem::CanPasteLink

static BOOL PASCAL CanPasteLink( OLEOPT_RENDER renderopt =
olerender_draw, OLECLIPFORMAT cfFormat = 0 );

renderopt    Flag specifying how the server will render the item. For possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to see if a linked item can be pasted from the Clipboard. This function is called for you by the framework when enabling or disabling the Paste Link command on the Edit menu.

Return Value

Nonzero if the Clipboard currently contains a linkable OLE item; otherwise 0.

See Also

»COleClientItem::CanPaste«, »COleClientItem::CreateLinkFromClipboard«, ::OleQueryCreateFromClip


  COleClientItem::CloseLink

void CloseLink();

Remarks

Call this function to close the link between an open linked item and the server application. This function does not destroy the linked item; the item can be reconnected later.

See Also

»COleClientItem::ReconnectLink«, »COleClientItem::UpdateLink«, ::OleClose


  COleClientItem::COleClientItem

COleClientItem( COleClientDoc* pContainerDoc );

pContainerDoc    Pointer to the registered client document that will contain this item.

Remarks

Constructs a COleClientItem object and adds it to the container document's collection of document items. You must call one of the following creation member functions before you use the item: »CreateFromClipboard«, »CreateInvisibleObject«, »CreateStaticFromClipboard«, »CreateLinkFromClipboard«, »CreateNewObject«, or »CreateCloneFrom«.

See Also

»COleClientDoc«, »COleDocument::AddItem«


  COleClientItem::CopyToClipboard

void CopyToClipboard();

Remarks

Call this function to copy the item to the Clipboard. Typically, you call this function when writing message handlers for the Copy or Cut commands from the Edit menu. You must implement selection in your client application to implement the Copy or Cut commands. To use this function, you should open and empty the Clipboard, call CopyToClipboard for the selected item, and then close the Clipboard.

See Also

::OleCopyToClipboard


  COleClientItem::CreateCloneFrom

BOOL CreateCloneFrom( COleClientItem* pSrcItem, LPCSTR lpszItemName );

pSrcItem    Pointer to the OLE item to be duplicated.

lpszItemName    Pointer to the client name of the new item.

Remarks

Call this function to create a copy of the specified item. The copy is identical to the source item but is not connected to the server. You can use this function to support "undo" or "revert" operations.

Return Value

Nonzero if successful; otherwise 0.

See Also

::OleClone


  COleClientItem::CreateFromClipboard

BOOL CreateFromClipboard( LPCSTR lpszItemName,
OLEOPT_RENDER renderopt = olerender_draw,
OLECLIPFORMAT cfFormat = 0 );

lpszItemName    Pointer to the client name of the new item.

renderopt    Flag specifying how the server will render the item. For the possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to create an embedded item from the contents of the Clipboard. You typically call this function from the message handler for the Paste command on the Edit menu. (The Paste command is enabled by the framework if the CanPaste member function returns nonzero.) If the function is unsuccessful, try calling CreateStaticFromClipboard to paste a static (metafile-based) item.

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleClientItem::CreateStaticFromClipboard«, »COleClientItem::CanPaste«, ::OleCreateFromClip


  COleClientItem::CreateInvisibleObject

BOOL CreateInvisibleObject( LPCSTR lpszTypeName, LPCSTR lpszItemName,
OLEOPT_RENDER renderopt = olerender_draw,
OLECLIPFORMAT cfFormat = 0, BOOL bActivate = FALSE );

lpszTypeName    Pointer to the type name of the new item to create. This string is usually obtained from the global function AfxOleInsertDialog.

lpszItemName    Pointer to the client name of the new item.

renderopt    Flag specifying how the server will render the item. For the possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

bActivate    Specifies whether to activate the item or not.

Remarks

Call this function to create an item without displaying the server application to the user. This is an advanced operation; typically you call CreateNewObject.

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleClientItem::CreateNewObject«, ::OleCreateInvisible


  COleClientItem::CreateLinkFromClipboard

BOOL CreateLinkFromClipboard( LPCSTR lpszItemName,
OLEOPT_RENDER renderopt = olerender_draw,
OLECLIPFORMAT cfFormat = 0 );

lpszItemName    Pointer to the client name of the new item.

renderopt    Flag specifying how the server will render the item. For the possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to create a linked item from the contents of the Clipboard. You typically call this function from the message handler for the Paste Link command on the Edit menu. (The Paste Link command is enabled by the framework if the CanPasteLink member function returns nonzero.)

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleClientItem::CanPasteLink«, ::OleCreateLinkFromClip


  COleClientItem::CreateNewObject

BOOL CreateNewObject( LPCSTR lpszTypeName, LPCSTR lpszItemName,
OLEOPT_RENDER renderopt = olerender_draw,
OLECLIPFORMAT cfFormat = 0 );

lpszTypeName    Pointer to the type name of the new item to create. This string is usually obtained from the global function AfxOleInsertDialog.

lpszItemName    Pointer to the name of the new item.

renderopt   Flag specifying how the server will render the item. This parameter may have one of the following values:

•	olerender_draw     The item is drawn using COleClientItem::Draw. In this case the OLE system DLL obtains and manages the presentation data and stores the Native data for archiving purposes only.

•	olerender_none     The OLE system DLL does not obtain the presentation data and does not draw the object. The client calls COleClientItem::GetData to retrieve the server data in Native format, and it is assumed that the client knows how to interpret this format.

•	olerender_format     The client calls COleClientItem::GetData to retrieve data in the format specified by cfFormat. The client then uses the retrieved data to render the item.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to create an embedded item; this function launches the server application to allow the user to create the item. You typically call this function from the message handler for the Insert New Object command on the Edit menu. To create a linked item, use the CreateLinkFromClipboard function.

Return Value

Nonzero if successful; otherwise 0.

See Also

»AfxOleInsertDialog«, »COleClientItem::CreateLinkFromClipboard«, ::OleCreate


  COleClientItem::CreateStaticFromClipboard

BOOL CreateStaticFromClipboard( LPCSTR lpszItemName,
OLEOPT_RENDER renderopt = olerender_draw,
OLECLIPFORMAT cfFormat = 0 );

lpszItemName    Pointer to the client name of the new item.

renderopt    Flag specifying how the server will render the item. For possible values, see »COleClientItem::CreateNewObject«.

cfFormat    Specifies the Clipboard data format if renderopt is olerender_format.

Remarks

Call this function to create a static (metafile-based) embedded item from the contents of the Clipboard. You typically call this function from the message handler for the Paste command on the Edit menu, following an unsuccessful call to CreateFromClipboard. (The Paste command is enabled by the framework if the CanPaste member function returns nonzero.)

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleClientItem::CreateFromClipboard«, ::OleCreateFromClip


  COleClientItem::Delete

void Delete();

Remarks

Call this function to delete the item. If the item is embedded, the native data for the item is deleted. If the item is an open linked item, this function closes it. Unlike the Release member function, this function indicates that the item has been permanently removed.

The COleClientItem destructor calls Delete for embedded items.

See Also

»COleClientItem::Release«, ::OleDelete


  COleClientItem::DoVerb

virtual BOOL DoVerb( UINT nVerb );

nVerb    Index of the verb to execute; 0 is the primary verb, 1 is the secondary verb, and so forth.

Remarks

Call this function to execute the specified verb. This function uses the Activate member function to execute the verb; it also catches exceptions thrown as a result and alerts the user if an error occurs.

You typically specify the primary verb when the user of the client application double-clicks the item. The action taken in response to each verb depends on the server. If the server supports only one action, it takes that action no matter which value is specified in the nVerb parameter.

Return Value

Nonzero if the verb was sucessfully executed; otherwise 0.

See Also

»COleClientItem::Activate«


  COleClientItem::Draw

BOOL Draw( CDC* pDC, LPCRECT lpBounds, LPCRECT lpWBounds = NULL, CDC* pFormatDC = NULL );

pDC    Pointer to a CDC object used for drawing the item.

lpBounds    Pointer to a CRect object or RECT structure that defines the bounding rectangle in which to draw the object (in logical units determined by the device context).

lpWBounds    Pointer to a CRect object or RECT structure that defines the bounding rectangle if pDC specifies a metafile device context. NULL if pDC points to a screen device context.

pFormatDC    Pointer to a CDC object describing the target device for which to format the item. This parameter is used only by handler DLLs and is usually NULL.

Remarks

Call this function to draw the item into the specified bounding rectangle using the specified device context. The function uses the metafile representation of the item created by the OnDraw member function of COleServerItem.

Typically you use Draw for screen display, passing the screen device context as pDC. In this case, you need specify only the first two parameters. If you pass a metafile device context as pDC, the rectangle specified by lpWBounds must contain the rectangle specified by lpBounds. The pFormatDC parameter is used for formatting purposes by handler DLLs and must not be a metafile device context.

The lpBounds parameter identifies the rectangle in the target device context (relative to its current mapping mode). Rendering may involve scaling the picture and can be used by client applications to impose a view scaling between the displayed view and the final printed image.

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleClientItem::SetBounds«, »COleServerItem::OnDraw«, ::OleDraw


  COleClientItem::EnumFormats

OLECLIPFORMAT EnumFormats( OLECLIPFORMAT nFormat ) const;

nFormat    Specifies the format returned by the previous call to the EnumFormats member function. For the first call to this function, this parameter is NULL. This parameter can be one of the predefined Clipboard formats or the value returned by the native Windows RegisterClipboardFormat function.

Remarks

Call this function to retrieve the data formats available for the item. Call this function in a loop to retrieve all the formats, each time passing the format returned by the previous call.

Return Value

The next (or first) available format; NULL if no more formats are available.

See Also

»COleClientItem::GetData«, ::OleEnumFormats


  COleClientItem::GetBounds

BOOL GetBounds( LPRECT lpBounds );

lpBounds    Pointer to a CRect object or RECT structure that will receive the bounds information.

Remarks

Call this function to retrieve the extents of the bounding rectangle for the item on the target device. The coordinates are in MM_HIMETRIC units and the top and left coordinates are always 0.

Return Value

Nonzero if successful; 0 if the item is blank.

See Also

»COleClientItem::SetBounds«, ::OleQueryBounds


  COleClientItem::GetData

HANDLE GetData( OLECLIPFORMAT nFormat, BOOL& bMustDelete );

nFormat    Specifies the format in which data is returned. This parameter can be one of the predefined Clipboard formats or the value returned by the native Windows RegisterClipboardFormat function.

bMustDelete    A reference to a BOOL value that the function sets to TRUE if you are responsible for the deletion of the retrieved data (through the Windows GlobalFree function). If the function sets bMustDelete to FALSE, then you must copy the data if you need to keep it.

Remarks

Call this function to retrieve data from the item in the requested format.

Return Value

A handle to an entity that contains the data. If nFormat is CF_METAFILEPICT or CF_BITMAP, then this handle is a Windows graphics device interface (GDI) object handle; otherwise, it is a global memory block handle.

See Also

»COleClientItem::RequestData«, ::OleGetData


  COleClientItem::GetDocument

COleClientDoc* GetDocument() const;

Remarks

Call this function to get a pointer to the document that contains the item. This allows access to the client document that you passed as an argument to the COleClientItem constructor.

Return Value

A pointer to the document that contains the item. NULL if the item is not part of a document.

See Also

»COleClientItem::COleClientItem«, »COleClientDoc«


  COleClientItem::GetLastStatus

OLESTATUS GetLastStatus() const;

Remarks

Returns the status of the last OLE operation. For member functions that return a BOOL value of FALSE, GetLastStatus returns more detailed failure information.

Be aware that most OLE member functions throw exceptions for more serious errors.

Return Value

See »COleException« for a list of return values.


  COleClientItem::GetLinkUpdateOptions

OLEOPT_UPDATE GetLinkUpdateOptions();

Remarks

Call this function to get the current value of the link-update option for the item. This is an advanced operation.

Return Value

One of the following values:

•	oleupdate_always    Update the linked object whenever possible. This option supports the Automatic link-update radio button in the Links dialog box.

•	oleupdate_onsave    Update the linked object when the source document is saved by the server.

•	oleupdate_oncall    Update the linked object only on request from the client application. This option supports the Manual link-update radio button in the Links dialog box.

See Also

::OleGetLinkUpdateOptions


  COleClientItem::GetName

CString GetName();

Remarks

Call this function to get the client name of the item. This is the name passed in when the object was created or last renamed.

Return Value

The name of the item.

See Also

::OleQueryName


  COleClientItem::GetSize

DWORD GetSize();

Remarks

Call this function to get the number of bytes in the native representation of the item. You can use this information to determine the space required for saving it.

Return Value

Number of bytes required to save the item.

See Also

::OleQuerySize, »CObject::Serialize«


  COleClientItem::GetType

UINT GetType();

Remarks

Call this function to determine whether the item is embedded, linked, or static.

Return Value

An unsigned integer with one of the following values:

•	OT_LINK    The item is a link.

•	OT_EMBEDDED    The item is embedded.

•	OT_STATIC    The item is a static (metafile-based) picture.

See Also

::OleQueryType


  COleClientItem::InWaitForRelease

static BOOL PASCAL InWaitForRelease();

Remarks

Call this function from your main window's OnCommand or OnCmdMsg member function to disable user commands until all servers respond.

Return Value

Nonzero if this client application is still waiting for a server to complete an operation; otherwise 0.


  COleClientItem::IsEqual

BOOL IsEqual( COleClientItem* pOtherItem );

pOtherItem    Pointer to an OLE item object that is to be compared with this item.

Remarks

Call this function to compare two OLE items. Embedded items are equal if their type name, item name, and native data are identical. Linked items are equal if their type name, item name, and document name are identical.

Return Value

Nonzero if the items are equal; otherwise 0.

See Also

::OleEqual


  COleClientItem::IsOpen

BOOL IsOpen();

Remarks

Call this function to see if the item is connected to the OLE system DLL. Typically, an item is connected after a successful call to one of the COleClientItem creation functions.

Return Value

Nonzero if the item is connected; otherwise 0.

See Also

»COleClientItem::CreateFromClipboard«, »COleClientItem::CreateStaticFromClipboard«, »COleClientItem::CreateLinkFromClipboard«, »COleClientItem::CreateNewObject«, »COleClientItem::CreateCloneFrom«, ::OleQueryOpen


  COleClientItem::OnChange

Protected

virtual void OnChange( OLE_NOTIFICATION wNotification ) = 0; ♦

wNotification    Reason the server changed this item. It can have one of the following values:

•	OLE_CHANGED    The user of the server application modified the linked item. This notification is not sent for embedded items.

•	OLE_SAVED    The user of the server application saved the document containing the item.

•	OLE_CLOSED    The user of the server application closed the document containing the item.

The OLE_RENAMED notification is handled by the OnRenamed member function.

Remarks

Called by the framework when the user of the server application modifies the item or saves or closes the document containing the item. (If the server application is written with the Microsoft Foundation Class Library, this function is called in response to the Notify member functions of COleServerDoc or COleServerItem.) There is no default implementation. You must override this function to respond to changes in the item's state. Typically you update the item's appearance by invalidating the area in which the item is displayed.

See Also

»COleClientItem::OnRenamed«, »COleServerItem::NotifyChanged«, »COleServerDoc::NotifyChanged«, »COleServerDoc::NotifyClosed«, »COleServerDoc::NotifySaved«


  COleClientItem::OnRenamed

Protected

virtual void OnRenamed(); ♦

Remarks

Called by the framework when the user of the server application renames the document containing the item. (If the server application is written with the Microsoft Foundation Class Library, this function is called in response to the NotifyRename member function of COleServerDoc.) This function is called only for linked items, not for embedded items. The default implementation does nothing. Override this function if you want to perform special processing when an item is renamed.

See Also

»COleClientItem::OnChange«, »COleServerDoc::NotifyRename«


  COleClientItem::ReconnectLink

void ReconnectLink();

Remarks

Call this function to reestablish a link between an open linked item and the server. Typically, you call this function after closing a link with the CloseLink member function. If the item is not open, ReconnectLink does not open it.

See Also

»COleClientItem::CloseLink«, ::OleReconnect


  COleClientItem::Release

void Release();

Remarks

Call this function to release the connection to a linked item and close the link if it was open. It does not destroy the item. Release is called by the COleClientItem destructor for linked items.

See Also

»COleClientItem::Delete«, ::OleRelease


  COleClientItem::Rename

void Rename( LPCSTR lpszNewname );

lpszNewname    Pointer to the new client name for the item.

Remarks

Call this function to rename the item. The name must be unique within the document and must be preserved when the document is saved.

See Also

::OleRename


  COleClientItem::RequestData

void RequestData( OLECLIPFORMAT nFormat );

nFormat    Specifies the format in which data is returned. This parameter can be one of the predefined Clipboard formats or the value returned by the native Windows RegisterClipboardFormat function.

Remarks

Call this function to retrieve data in a specified format from the server application.

An exception is thrown if the server does not support data requests.

The client application should be connected to the server application when the client calls RequestData. After RequestData returns, the client can retrieve the data with the GetData member function, and it can examine information through other member functions such as GetBounds and GetSize.

See Also

»COleClientItem::GetData«, »COleClientItem::GetBounds«, »COleClientItem::GetSize«, ::OleRequestData


  COleClientItem::SetBounds

void SetBounds( LPCRECT lpRect );

lpRect    Pointer to a CRect object or RECT structure that contains the bounds information.

Remarks

Call this function to set the bounding rectangle on the target device for the item; this causes the OnSetBounds member function of the corresponding COleServerItem object to be called. The coordinates must be in MM_HIMETRIC units. This function is only meaningful for embedded items. The size of a linked item is determined by the source document for the link.

The bounding rectangle does not need to have the same dimensions as the rectangle specified by the Draw member function's lpBounds parameter. These dimensions may be different because of the view scaling used by the window in which the item is displayed. The client application can call SetBounds to make the server reformat the picture to better fit the client's rectangle.

See Also

»COleServerItem::OnSetBounds«, ::OleSetBounds


  COleClientItem::SetColorScheme

void SetColorScheme( const LOGPALETTE FAR* lpLogPalette );

lpLogPalette    Pointer to a Windows LOGPALETTE structure.

Remarks

Call this function to specify a recommended color scheme for the server application to use while displaying the item; this causes the OnSetColorScheme member function of the corresponding COleServerItem object to be called. The server does not have to use the specified palette. The client does not need to call SetColorScheme every time a server is opened.

The first palette entry in the LOGPALETTE structure specifies the foreground color recommended by the client application. The second palette entry specifies the background color. The first half of the remaining palette entries are fill colors, and the second half are colors for lines and text.

Client applications should specify an even number of palette entries. When there is an uneven number of entries, the server interprets the odd entry as a fill color; that is, if there were five entries, three would be interpreted as fill colors and two as line and text colors. When server applications render metafiles, they should use the suggested palette.

See Also

»COleServerItem::OnSetColorScheme«, ::OleSetColorScheme


  COleClientItem::SetData

void SetData( OLECLIPFORMAT nFormat, HANDLE hData );

nFormat    Specifies the format in which data is returned. This parameter can be one of the predefined Clipboard formats or the value returned by the native Windows RegisterClipboardFormat function.

hData    Identifies a memory object that contains the data in the format specified by the server. Do not free this memory; the server will free it.

Remarks

Call this function to send data to the server application using the specified format; this causes the OnSetData member function of the corresponding COleServerItem object to be called. An exception is thrown if the server cannot accept the data or the specified data format.

See Also

»COleServerItem::OnSetData«, ::OleSetData


  COleClientItem::SetHostNames

void SetHostNames( LPCSTR lpszHost, LPCSTR lpszHostObj );

lpszHost    Pointer to the name of the client application.

lpszHostObj    Pointer to the client's name for the item.

Remarks

Call this function to specify the name of the client application and the client's name for the specified object; this calls the OnSetHostNames member function of the COleServerDoc object that contains the item on the server side. This information can be used in window titles when the server application edits the item.

It is not necessary to call SetHostNames each time a server is activated.

See Also

»COleServerDoc::OnSetHostNames«, ::OleSetHostNames


  COleClientItem::SetLinkUpdateOptions

void SetLinkUpdateOptions( OLEOPT_UPDATE updateOpt );

updateOpt    The value of the link-update option for this item. This value must be one of the following:

•	oleupdate_always    Update the linked object whenever possible. This option supports the Automatic link-update radio button in the Links dialog box.

•	oleupdate_onsave    Update the linked object when the source document is saved by the server.

•	oleupdate_oncall    Update the linked object only on request from the client application. This option supports the Manual link-update radio button in the Links dialog box.

Remarks

Call this function to set the link-update option for the presentation of the specified linked item. Typically you should not change the update options chosen by the user in the Links dialog box.

See Also

»COleClientItem::GetLinkUpdateOptions«, »AfxOleLinksDialog«, ::OleSetLinkUpdateOptions


  COleClientItem::SetTargetDevice

void SetTargetDevice( HGLOBAL hData );

hData    Handle to an OLETARGETDEVICE structure that describes the target device. Do not free this structure; the server will free it.

Remarks

Call this function to specify an item's target output device; this causes the OnSetTargetDevice member function of the corresponding COleServerItem object to be called.

This function allows a linked or embedded item to be formatted correctly for a target device, even when the item is rendered on a different device. A client application should call this function whenever the target device changes so that servers can be notified to change the rendering of the item if necessary. The client application should call the UpdateLink member function after calling SetTargetDevice to ensure that the information is sent to the server and that the server can make the necessary changes to the item's presentation. The client application should call the Draw member function to redraw the item if it receives a notification from the server that the item has changed. The client does not need to call SetTargetDevice every time a server is activated.

See Also

»COleClientItem::Draw«, »COleClientItem::UpdateLink«, »COleServerItem::OnSetTargetDevice«, ::OleSetTargetDevice


  COleClientItem::UpdateLink

void UpdateLink();

Remarks

Call this function to update the item immediately. The user can also manually update individual links using the Links dialog box.

See Also

»AfxOleLinksDialog«, ::OleUpdate


COleDocument
  class COleDocument : public CDocument

COleDocument is the base class for Object Linking and Embedding (OLE) documents.  COleDocument is derived from CDocument, allowing your OLE applications to use the document/view architecture provided by the Microsoft Foundation Class Library. In addition, the COleDocument class defines an interface that treats a document as a collection of CDocItem objects. This interface is needed by both client and server applications because their documents must be able to contain OLE items.

You do not use COleDocument directly; instead, use the derived classes COleClientDoc and COleServerDoc. Use those classes as the base class for documents in your client and server applications, respectively.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»CDocItem«, »COleServerDoc«, »COleClientDoc«, »COleServerItem«, »COleClientItem«


COleDocument Class Members
  Class Members

Construction/Destruction — Public Members

»COleDocument«	Constructs a COleDocument object.
Operations — Public Members

»AddItem«	Adds an item to the list of items maintained by the document.
»GetNextItem«	Returns all the items in the document when called iteratively.
»GetStartPosition«	Gets the initial position to begin iteration.
»IsOpenClientDoc«	Tests if the document is a registered client document.
»IsOpenServerDoc«	Tests if the document is a registered server document.
»RemoveItem«	Removes an item from the list of items maintained by the document.


COleDocument Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleDocument::AddItem

void AddItem( CDocItem* pItem );

pItem    Pointer to the document item being added.

Remarks

Call this function to add an item to the document. You typically do not need to call this function explicitly; this function is called by the constructors for COleClientItem and COleServerItem.

See Also

»CDocItem«, »COleDocument::RemoveItem«, »COleServerItem::COleServerItem«, »COleClientItem::COleClientItem«


  COleDocument::COleDocument

COleDocument();

Remarks

Constructs a COleDocument object.


  COleDocument::GetNextItem

virtual CDocItem* GetNextItem( POSITION& rPosition );

rPosition    A reference to a POSITION value set by a previous call to GetNextItem; the initial value is returned by the GetStartPosition member function. This must not be NULL.

Remarks

Call this function repeatedly to access each of the items in your document. After each call, the value of rPosition is set to the POSITION value of the next item in the document. If the retrieved element is the last in the document, the new value of rPosition is NULL.

Return Value

A pointer to the document item at the specified position.

See Also

»COleDocument::GetStartPosition«

 Example

// example for COleDocument:GetNextItem

// pDoc points to a COleDocument object

POSITION pos = pDoc->GetStartPosition();

while( pos != NULL )

{

CDocItem *pItem = pDoc->GetNextItem( pos );

// use pItem

}


  COleDocument::GetStartPosition

virtual POSITION GetStartPosition() const;

Remarks

Call this function to get the position of the first item in the document. Pass the value returned to GetNextItem.

Return Value

A POSITION value that can be used to begin iterating through the document's items; NULL if the document is empty.

See Also

»COleDocument::GetNextItem«


  COleDocument::IsOpenClientDoc

BOOL IsOpenClientDoc() const;

Remarks

Call this function to see if the document is a registered client document. Note that a document can be both a client document and a server document if your application supports both.

Return Value

Nonzero if the document is a registered client document; otherwise 0.

See Also

»COleClientDoc::RegisterClientDoc«, »COleDocument::IsOpenServerDoc«


  COleDocument::IsOpenServerDoc

BOOL IsOpenServerDoc() const;

Remarks

Call this function to see if the document is a registered server document. Note that a document can be both a client document and a server document if your application supports both.

Return Value

Nonzero if the document is a registered server document; otherwise 0.

See Also

»COleServerDoc::RegisterServerDoc«, »COleDocument::IsOpenClientDoc«


  COleDocument::RemoveItem

void RemoveItem( CDocItem* pItem );

pItem    Pointer to the document item to be removed.

Remarks

Call this function to remove an item from the document. You typically do not need to call this function explicitly; this function is called by the destructors for COleClientItem and COleServerItem.

See Also

»CDocItem«, »COleServerItem«, »COleClientItem«, »COleDocument::AddItem«


COleException
  class COleException : public CException

A COleException object represents an exception condition related to an Object Linking and Embedding (OLE) operation. The COleException class includes a public data member that holds the status code indicating the reason for the exception.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>


COleException Class Members
  Class Members

Data Members — Public Members

»m_status«	Contains the status code that indicates the reason for the exception.
Construction/Destruction — Public Members

»COleException«	Constructs a COleException object.


COleException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleException::COleException

COleException( OLESTATUS status );

status    An enumerated type variable that indicates the reason for the exception. Must be one of the following enumerators:

•	OLE_OK    Function operated correctly (does not throw an exception).

•	OLE_BUSY    Tried to execute a member function while another operation was in progress.

•	OLE_ERROR_STREAM    OLESTREAM stream error.

•	OLE_ERROR_STATIC    Nonstatic item expected.

•	OLE_ERROR_BLANK    Critical data missing.

•	OLE_ERROR_DRAW    Error while drawing.

•	OLE_ERROR_METAFILE    Invalid metafile.

•	OLE_ERROR_ABORT    Client chose to abort metafile drawing.

•	OLE_ERROR_CLIPBOARD    Failed to get or set Clipboard data.

•	OLE_ERROR_FORMAT    Requested format not available.

•	OLE_ERROR_GENERIC    General error.

•	OLE_ERROR_DATATYPE    Data format not supported.

•	OLE_ERROR_PALETTE    Invalid color palette.

•	OLE_ERROR_NOT_LINK    Not a linked item.

•	OLE_ERROR_NOT_EMPTY    Client document contains items.

•	OLE_ERROR_SIZE    Incorrect buffer size passed to function that places a string in the caller's buffer.

•	OLE_ERROR_DRIVE    Drive letter in document name invalid.

•	OLE_ERROR_NETWORK    Failed to establish connection to network share on which the document is located.

•	OLE_ERROR_NAME    Invalid name (document name, item name, and so forth) passed to function.

•	OLE_ERROR_TEMPLATE    Server failed to load template.

•	OLE_ERROR_NEW    Server failed to create new document.

•	OLE_ERROR_EDIT    Server failed to create embedded instance.

•	OLE_ERROR_OPEN    Server failed to open document; possible invalid link.

•	OLE_ERROR_NOT_OPEN    Item not open for editing.

•	OLE_ERROR_LAUNCH    Failed to launch server.

•	OLE_ERROR_COMM    Failed to communicate with server.

•	OLE_ERROR_TERMINATE    Error in termination.

•	OLE_ERROR_COMMAND    Error in execution.

•	OLE_ERROR_SHOW    Error in showing.

•	OLE_ERROR_DOVERB    Error in sending do verb, or invalid verb.

•	OLE_ERROR_ADVISE_NATIVE    Item could be missing.

•	OLE_ERROR_ADVISE_PICT    Item could be missing or server doesn't understand this format.

•	OLE_ERROR_ADVISE_RENAME    Server doesn't support rename.

•	OLE_ERROR_POKE_NATIVE    Failure in poking native data to server.

•	OLE_ERROR_REQUEST_NATIVE    Server failed to render native data.

•	OLE_ERROR_REQUEST_PICT    Server failed to render presentation data.

•	OLE_ERROR_SERVER_BLOCKED    Trying to block a blocked server, or trying to revoke a blocked server or document.

•	OLE_ERROR_REGISTRATION    Server not registered in OLE registration database.

•	OLE_ERROR_ALREADY_REGISTERED    Trying to register same document multiple times.

•	OLE_ERROR_TASK    Server or client task invalid.

•	OLE_ERROR_OUTOFDATE    Item out of date.

•	OLE_ERROR_CANT_UPDATE_CLIENT    Client of embedded document doesn't accept updates.

•	OLE_ERROR_UPDATE    Error while trying to update.

•	OLE_WARN_DELETE_DATA    Caller must delete data when done with it (warning).

Remarks

Constructs a COleException object.

Do not use this constructor directly; instead call the global function AfxThrowOleException.

See Also

»AfxThrowOleException«


COleException Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  COleException::m_status

OLESTATUS m_status;

Remarks

This data member holds the status code that indicates the reason for the exception. This variable is set by the constructor.

See the COleException constructor documentation for a list of OLESTATUS enumerators.

See Also

»COleException::COleException«


COleServer
  class COleServer : public CObject

COleServer is the base class for Object Linking and Embedding (OLE) servers. One COleServer object is needed for each type of document a server application supports; for example, if your server application supports both worksheets and charts, you need to have two COleServer objects. Use the COleServer class if you are writing a mini-server (that is, a server application that is only launched by clients to edit embedded items). If you are writing a full server (that is, a server application that supports loading and saving files to and from disk), you can use the COleTemplateServer class, which combines a CDocTemplate object with a server.

COleServer defines several overridable member functions that are called by the OLE system dynamic-link library (DLL) in response to requests from client applications. Through these member functions, the client instructs the server to open embedded items as documents or open the documents that are the source of linked items.

To use COleServer, derive a class from it and implement the OnCreateDoc and OnEditDoc member functions, which allow your application to open and edit embedded items as documents. Derive a class from COleServerDoc to implement the documents edited by your server application and return objects of that class from OnCreateDoc and OnEditDoc.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»COleTemplateServer«, »COleServerDoc«, »COleServerItem«


COleServer Class Members
  Class Members

Construction/Destruction — Public Members

»COleServer«	Constructs a COleServer object.
Registration/Revocation — Public Members

»Register«	Registers the server with the OLE system DLL.
»BeginRevoke«	Begins server shutdown (called by the destructor).
Status — Public Members

»IsOpen«	Indicates whether the server is currently operational and registered.
»GetServerName«	Returns the name of the server registered with the OLE system DLL.
Overridables — Protected Members

»OnCreateDoc«	Called to create a document for a new embedded item. Implementation required.
»OnEditDoc«	Called to create a document to edit an existing embedded item. Implementation required.
»OnOpenDoc«	Called to open an existing document containing the source of a linked item.
»OnCreateDocFromTemplateFile«	Called to create a new document based on another file.
»OnExecute«	Called to handle dynamic data exchange (DDE) WM_DDE_EXECUTE messages.
»OnExit«	Called to instruct the server to quit.


COleServer Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleServer::BeginRevoke

void BeginRevoke();

Remarks

Call this function to close any registered documents and begin the server shutdown procedure. You typically call this function when the user exits your application. This function is also called by the COleServer destructor. This function does not wait for the OLE system DLL to complete the revoke operation; the DLL calls the implementation member function OnRelease when it is safe for the application to quit.

See Also

::OleRevokeServer


  COleServer::COleServer

COleServer( BOOL bLaunchEmbedded );

bLaunchEmbedded    TRUE if the server application was launched with the "/Embedded" command-line argument.

Remarks

Constructs a COleServer object. The server cannot receive requests from clients until you call the Register member function.

See Also

»COleServer::Register«


  COleServer::GetServerName

const CString& GetServerName() const;

Remarks

Call this function to get the name of the server registered with the OLE system DLL. This is the name that was passed to the Register member function.

Return Value

The registered name of the server.

See Also

»COleServer::Register«


  COleServer::IsOpen

BOOL IsOpen() const;

Remarks

Call this function to see if the server is registered with the OLE system DLL.

Return Value

Returns nonzero if the server has been successfully registered; otherwise 0.

See Also

»COleServer::Register«


  COleServer::OnCreateDoc

Protected

virtual COleServerDoc* OnCreateDoc( LPCSTR lpszTypeName, LPCSTR lpszDoc ) = 0; ♦

lpszTypeName    Pointer to the type name of the document being created.

lpszDoc    Pointer to the name of the document being created; note that this is not a filename because embedded items are not stored as their own files. This name can be used to identify the document in window titles.

Remarks

Called by the framework when a new embedded item is being created, that is, when the user of a client application executes the Insert New Object command. There is no default implementation. You must override this function to create a new document object of the specified type or return a pointer to an existing document object. The document object must be an object of a COleServerDoc-derived class.

This function is overriden for you in the derived class COleTemplateServer to use the document creation facilities of a CDocTemplate object.

Return Value

If successful, a pointer to a server document; otherwise NULL.

See Also

»COleServer::OnEditDoc«, »COleServerDoc«, »COleTemplateServer«, »COleClientItem::CreateNewObject«


  COleServer::OnCreateDocFromTemplateFile

Protected

virtual COleServerDoc* OnCreateDocFromTemplateFile( LPCSTR lpszTypeName, LPCSTR lpszDoc, LPCSTR lpszTemplate ); ♦

lpszTypeName    Pointer to the type name of the document being created.

lpszDoc    Pointer to the name of the document being created. Note that this is not a filename because embedded items are not stored as their own files. This name can be used to identify the document in window titles.

lpszTemplate    Pointer to the fully qualified name of a file on which the new document should be based.

Remarks

Called by the framework to create a server document for a new embedded item and initialize it with the contents of the specified file. The default implementation does nothing and returns NULL. Override this function if you want to use an existing file to initialize new embedded items. In such a situation, you must determine your own format for initializing the item from the template file. The document object you create must be an object of a COleServerDoc-derived class.

Note that the file used as the template for the embedded item is unrelated to the CDocTemplate classes defined by the Microsoft Foundation Class Library.

Return Value

If successful, a pointer to a server document; otherwise NULL. Returns NULL if the server does not support this feature.


  COleServer::OnEditDoc

Protected

virtual COleServerDoc* OnEditDoc( LPCSTR lpszTypeName, LPCSTR lpszDoc ) = 0; ♦

lpszTypeName    Pointer to the type name of the document being opened.

lpszDoc    Pointer to the name of an existing document; note that this is not a filename because embedded items are not stored as their own files. This name can be used to identify the document in window titles.

Remarks

Called by the framework when an existing embedded item is opened for editing, that is, when the user of a client application edits an embedded item. There is no default implementation. You must override this function to create a new document object of the specified type or to return a pointer to an existing document object. The document object you create must be an object of a COleServerDoc-derived class. Note that this function is called only for embedded items; the OnOpenDoc member function is called for linked items.

This function is overriden for you in the derived class COleTemplateServer to use the document creation facilities of a CDocTemplate object.

Return Value

If successful, a pointer to a server document; otherwise NULL.

See Also

»COleServer::OnOpenDoc«, »COleServerDoc«, »COleTemplateServer«


  COleServer::OnExecute

Protected

virtual OLESTATUS OnExecute( LPVOID lpCommands ); ♦

lpCommands    Points to a block of memory that contains dynamic data exchange (DDE) WM_DDE_EXECUTE command strings.

Remarks

Called by the framework when the client sends DDE WM_DDE_EXECUTE command strings to the server document. The default implementation does nothing and returns OLE_ERROR_COMMAND. Override this funtion to handle DDE WM_DDE_EXECUTE messages. Do not delete memory referenced by lpCommands.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.


  COleServer::OnExit

Protected

virtual OLESTATUS OnExit(); ♦

Remarks

Called by the framework to tell the server to close documents and quit. The default implementation calls the BeginRevoke member function to start shutting down the server application. Override this function if you want to perform special processing when you exit.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleServer::BeginRevoke«


  COleServer::OnOpenDoc

Protected

virtual COleServerDoc* OnOpenDoc( LPCSTR lpszDoc ); ♦

lpszDoc    Pointer to the filename of an existing document, which is the source of the linked item.

Remarks

Called by the framework when an existing linked item is opened; that is, when the user of a client application edits a linked item. The default implementation does nothing and returns NULL. You must override this function if you are supporting linked items; override this function to open the document with the specified name.

The document object you create must be an object of a COleServerDoc-derived class. Note that this function is called only for linked items; the OnEditDoc member function is called for embedded items.

This function is overriden in the derived class COleTemplateServer to open the document with the specified name using the document-creation facilities of a CDocTemplate object.

Return Value

If successful, a pointer to a server document; otherwise NULL.

See Also

»COleServer::OnEditDoc«, »COleServerDoc«, »COleTemplateServer«


  COleServer::Register

BOOL Register( LPCSTR lpszTypeName, BOOL bMultiInstance );

lpszTypeName    Pointer to the name of the server document type. This must be the type name passed to AfxOleRegisterServerName when registering the server with the Windows registration database.

bMultiInstance    Flag indicating whether multiple instances of the server application can be run simultaneously. Pass TRUE if your server is a single document interface (SDI) application; TRUE causes a separate instance of your application to run for each client. Pass FALSE if it is a multiple document interface (MDI) application since one instance of an MDI application can support multiple clients using separate document windows. Note that mini-servers are typically SDI applications and full servers are typically MDI applications.

Remarks

Call this function to register the server with the OLE system DLL so that it can receive requests from clients. You typically call this function for every COleServer object your application maintains when the application starts. The BeginRevoke function terminates the connection with the OLE system DLL.

Note that this operation is separate from the operation needed to create an entry for the server in the Windows registration database.

Return Value

Nonzero if the server was successfully registered; otherwise 0.

See Also

»COleServer::BeginRevoke«, ::OleRegisterServer, »AfxOleRegisterServerName«


COleServerDoc
  class COleServerDoc : public COleDocument

COleServerDoc is the base class for Object Linking and Embedding (OLE) server documents. A server document is a document that can contain COleServerItem objects, which represent the server interface to embedded or linked items. When a server application is launched by a client to edit an embedded item, the item is loaded as its own server document; the COleServerDoc object contains just one COleServerItem object, consisting of the entire document. When a server application is launched by a client to edit a linked item, an existing document is loaded from disk; this document has a portion of its contents highlighted to indicate the linked item.

Note that in server applications that support only embedding, a server document can contain only a single item. In server applications that support linking, a server document can contain zero or more linked items.

To use COleServerDoc, derive a class from it and implement the OnGetEmbeddedItem member function; this function lets your server support embedded items. Derive a class from COleServerItem to implement the items in your documents, and return objects of that class from OnGetEmbeddedItem.

To support linked items, COleServerDoc provides the OnGetLinkedItem member function. You can use the default implementation or override it if you have your own method to manage document items.

You need one COleServerDoc-derived class for every type of server document your application supports. For example, if your server application supports worksheets and charts, you need two COleServerDoc-derived classes.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»COleDocument«, »COleServer«, »COleTemplateServer«, »COleServerItem«


COleServerDoc Class Members
  Class Members

Construction/Destruction — Public Members

»COleServerDoc«	Constructs a COleServerDoc object.
Registration/Revocation — Public Members

»RegisterServerDoc«	Registers the document and informs the OLE system dynamic-link library (DLL) that it is ready for communication.
»Revoke«	Revokes the server document registration and waits to finish.
Operations — Public Members

»NotifyRename«	Notifies clients that the user has renamed the document.
»NotifyRevert«	Notifies clients that the user has reverted the document to the last saved state.
»NotifySaved«	Notifies clients that the user has saved the document.
»NotifyClosed«	Notifies clients that the user has closed the document.
»NotifyChanged«	Notifies clients that the user has changed the document.
Overridables — Protected Members

»OnGetEmbeddedItem«	Called to get a COleServerItem that represents the entire document; used to get an embedded item. Implementation required.
»OnGetLinkedItem«	Called to return a COleServerItem with the specified name; used to get a linked item.
»OnClose«	Called when a client requests to close the document.
»OnExecute«	Called when a client sends dynamic data exchange (DDE) WM_DDE_EXECUTE strings.
»OnSetDocDimensions«	Called when a client requests to change the document dimensions.
»OnSetHostNames«	Called when a client sets the window title for an embedded object.
»OnSetColorScheme«	Called when a client specifies a color palette for the document.
»OnUpdateDocument«	Called when a server document that is an embedded item is saved, updating the client's copy of the item.


COleServerDoc Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleServerDoc::COleServerDoc

COleServerDoc();

Remarks

Constructs a COleServerDoc object; it does not begin communications with the OLE system DLL. If your server application supports links, you must call the RegisterServerDoc member function; this informs clients who may be linked to the document that it is open.

See Also

»COleServerDoc::RegisterServerDoc«


  COleServerDoc::NotifyChanged

void NotifyChanged();

Remarks

Call this function to notify all linked items connected to the document that the document has changed. You typically call this function after the user changes some global attribute such as the dimensions of the server document. If a client item is linked to the document with an automatic link, the item is updated to reflect the changes. In client applications written with the Microsoft Foundation Class Library, the OnChange member function of COleClientItem is called.  Do not call this function if the document is an embedded item.

See Also

»COleServerDoc::NotifyClosed«, »COleServerDoc::NotifySaved«, »COleClientItem::OnChange«


  COleServerDoc::NotifyClosed

void NotifyClosed();

Remarks

Call this function to notify the client(s) that the document has been closed. In the case where the user chooses the Close command from the File menu, NotifyRename is called for you by COleServerDoc's implementation of the OnCloseDocument member function. In client applications written with the Microsoft Foundation Class Library, the OnChange member function of COleClientItem is called.

See Also

»COleServerDoc::NotifyChanged«, »COleServerDoc::NotifySaved«, »COleClientItem::OnChange«, »CDocument::OnCloseDocument«


  COleServerDoc::NotifyRename

void NotifyRename( LPCSTR lpszNewName );

lpszNewName    Pointer to a string specifying the new name of the server document; this is typically a fully qualified path.

Remarks

Call this function after the user renames the server document. In the case where the user chooses the Save As command from the File menu, NotifyRename is called for you by COleServerDoc's implementation of the OnSaveDocument member function. This function notifies the OLE system DLL, which in turn notifies the clients. In client applications written with the Microsoft Foundation Class Library, the OnRenamed member function of COleClientItem is called.

See Also

 ::OleRenameServerDoc, »COleServerDoc::NotifySaved«, »COleClientItem::OnRenamed«, »CDocument::OnSaveDocument«


  COleServerDoc::NotifyRevert

void NotifyRevert();

Remarks

Call this function to inform the OLE system DLL that the server has restored a document to its last saved state without closing it; the OLE system DLL notifies the clients. You typically call this function after the user reverts a server document to its last saved form. The framework calls this function in COleServerDoc's implementation of the OnCloseDocument member function if the document has been modified.

See Also

 ::OleRevertServerDoc, »COleServerDoc::NotifyRename«, »COleServerDoc::NotifySaved«, »CDocument::OnCloseDocument«


  COleServerDoc::NotifySaved

void NotifySaved();

Remarks

Call this function after the user saves the server document. In the case where the user chooses the Save command from the File menu, NotifySaved is called for you by COleServerDoc's implementation of OnSaveDocument. This function notifies the OLE system DLL, which in turn notifies the clients. In client applications written with the Microsoft Foundation Class Library, the OnChanged member function of COleClientItem is called.

See Also

 ::OleSavedServerDoc, »COleServerDoc::NotifyChanged«, »COleServerDoc::NotifyClosed«, »COleClientItem::OnChange«, »CDocument::OnSaveDocument«


  COleServerDoc::OnClose

Protected

virtual OLESTATUS OnClose(); ♦

Remarks

Called by the framework when a client requests that the server document be closed.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.


  COleServerDoc::OnExecute

Protected

virtual OLESTATUS OnExecute( LPVOID lpCommands ); ♦

lpCommands    Points to a block of memory that contains dynamic data exchange (DDE) WN_DDE_EXECUTE command strings.

Remarks

Called by the framework when the client sends DDE WN_DDE_EXECUTE command strings to the document. The default implementation does nothing and returns OLE_ERROR_COMMAND. Override this function to handle DDE WN_DDE_EXECUTE commands. Do not delete memory referenced by lpCommands.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.

See Also

»COleServer::OnExecute«


  COleServerDoc::OnGetEmbeddedItem

Protected

virtual COleServerItem* OnGetEmbeddedItem() = 0; ♦

Remarks

Called by the framework when a client application invokes the server application to create or edit an embedded item. There is no default implementation. You must override this function to return an item representing the entire document. This should be an instance of a COleServerItem-derived class.

Return Value

A pointer to an item representing the entire document; NULL if the operation failed.

See Also

»COleServerDoc::OnGetLinkedItem«, »COleServerItem«


  COleServerDoc::OnGetLinkedItem

Protected

virtual COleServerItem* OnGetLinkedItem( LPCSTR lpszItemName ); ♦

lpszItemName    The name of an existing linked item.

Remarks

Called by the framework when a client application invokes the server application to edit a linked item. The default implementation searches for the item with the specified name in the collection of items contained in the document. Override this function if you want to implement your own method of storing or retrieving linked items. The OnGetLinkedItem function is called only for documents that support links. If the document is an embedded item, the function should return NULL.

Return Value

A pointer to the specified item; NULL if the item is not found.

See Also

»COleServerDoc::OnGetEmbeddedItem«, »COleServerItem«


  COleServerDoc::OnSetColorScheme

Protected

virtual OLESTATUS OnSetColorScheme( const LOGPALETTE FAR* lpLogPalette ); ♦

lpLogPalette    Pointer to a Windows LOGPALETTE structure.

Remarks

Called by the framework when a client sets the color palette for this server document. The default implementation does nothing. Override this function if you want to use the color palette specified by the client. See COleClientItem::SetColorScheme for information on how your server should interpret the colors in the palette.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.

See Also

»COleClientItem::SetColorScheme«


  COleServerDoc::OnSetDocDimensions

Protected

virtual OLESTATUS OnSetDocDimensions( LPCRECT lpRect ); ♦

lpRect    A pointer to a RECT structure that contains the new window dimensions.

Remarks

Called by the framework when a client changes the size of the server's document window. The default implementation does nothing and returns OLE_OK. Override this function if your server can resize or move its document windows. This function is called only for documents that are embedded items.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.

See Also

»COleClientItem::SetBounds«


  COleServerDoc::OnSetHostNames

Protected

virtual OLESTATUS OnSetHostNames( LPCSTR lpszHost, LPCSTR lpszHostObj ); ♦

lpszHost    Pointer to a string that specifies the name of the client application.

lpszHostObj    Pointer to a string that specifies the client's name for the document.

Remarks

Called by the framework when the client sets or changes the host names for this item. The default implementation does nothing and returns OLE_OK. Override this function if you need to save these names.

Return Value

OLE_OK if successful; any other value indicates failure. See the »COleException« class for a list of possible values.

See Also

»COleClientItem::SetHostNames«


  COleServerDoc::OnUpdateDocument

Protected

virtual BOOL OnUpdateDocument(); ♦

Remarks

Called by the framework when saving a document that is an embedded item, that is, when updating an item in a compound document. The default implementation calls the NotifySaved member function and then marks the document as clean. Override this function if you want to perform special processing when updating an embedded item.

Return Value

Nonzero if the document was successfully updated; otherwise 0.

See Also

»COleServerDoc::NotifySaved«, »CDocument::OnSaveDocument«


  COleServerDoc::RegisterServerDoc

BOOL RegisterServerDoc( COleServer* pServer, LPCSTR lpszDoc );

pServer    Pointer to an OLE server that is already registered.

lpszDoc    Pointer to the fully qualified path of the server document.

Remarks

Call this function to register the document with the OLE system DLL. You need to call this function only if your server application supports links; this registration lets clients know that the document is open. Call this function when creating or opening a named file; however, if you are using COleTemplateServer to implement your server, RegisterServerDoc is called for you by COleServerDoc's implementation of OnNewDocument or OnOpenDocument, respectively. There is no need to call this function if the document represents an embedded item.

Return Value

Nonzero if the document was successfully registered; otherwise 0.

See Also

»COleServer«, »COleTemplateServer«, »CDocument::OnNewDocument«, »CDocument::OnOpenDocument«


  COleServerDoc::Revoke

void Revoke();

Remarks

Revokes, or shuts down, the server document and waits for any pending operation to finish. The Revoke member function is called by the COleServerDoc destructor; it is seldom called explicitly elsewhere.

See Also

::OleRevokeServerDoc


COleServerItem
  class COleServerItem : public CDocItem

The COleServerItem class provides the server interface to Object Linking and Embedding (OLE) items. A linked item can represent some or all of a server document. An embedded item always represents an entire server document.

The COleServerItem class defines several overridable member functions that are called by the OLE system dynamic-link library (DLL), usually in response to requests from the client application. These member functions allow the client application to indirectly manipulate the item in various ways, such as displaying it, executing its verbs, or retrieving its data in various formats.

To use COleServerItem, derive a class from it and implement the OnDraw and Serialize member functions. The OnDraw function provides the metafile representation of an item, allowing it to be displayed when a client application opens a compound document. The Serialize function of CObject provides the Native representation of an item, allowing an embedded item to be transferred between the server and client applications.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»COleClientItem«, »COleServer«, »COleServerDoc«, »COleTemplateServer«, »CObject::Serialize«


COleServerItem Class Members
  Class Members

Status — Public Members

»GetDocument«	Returns the server document that contains the item.
»GetItemName«	Returns the name of the item. Used for linked items only.
»SetItemName«	Sets the name of the item. Used for linked items only.
Operations — Public Members

»CopyToClipboard«	Copies the item to the Clipboard.
»NotifyChanged«	Updates all clients with automatic link update.
»Revoke«	Terminates the connection between the item and the OLE system DLL.
Construction/Destruction — Protected Members

»COleServerItem«	Constructs a COleServerItem object.
Status — Protected Members

»IsConnected«	Indicates whether the item is currently attached to an active client.
Overridables — Protected Members

»OnShow«	Called when the client requests to show the item.
»OnDraw«	Called when the client requests to draw the item; implementation required.
»OnExtraVerb«	Called to execute verbs other than the primary verb.
»OnSetTargetDevice«	Called to set the item's target device.
»OnSetBounds«	Called to set the item's bounding rectangle.
»OnGetTextData«	Called to get item data as a text string.
»OnSetColorScheme«	Called to set the item's color scheme.
»OnEnumFormats«	Called to enumerate available data formats.
»OnGetData«	Called to retrieve the item's data.
»OnSetData«	Called to set the item's data.
»OnDoVerb«	Called to execute the primary verb.


COleServerItem Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleServerItem::COleServerItem

Protected

COleServerItem( COleServerDoc* pContainerDoc ); ♦

pContainerDoc    Pointer to the document that contains the item.

Remarks

Constructs a COleServerItem object and adds it to the container document's collection of document items.

See Also

»COleDocument::AddItem«


  COleServerItem::CopyToClipboard

BOOL CopyToClipboard( BOOL bIncludeNative, BOOL bIncludeLink );

bIncludeNative    Set this to TRUE if Native data should be copied to the Clipboard. Set this to FALSE if your server application supports only links (this is rare).

bIncludeLink    Set this to TRUE if ObjectLink data should be copied to the Clipboard. Set this to FALSE if your server application does not support links.

Remarks

Call this function to copy the item to the Clipboard. The function first copies the item to the Clipboard using the formats returned by the OnEnumFormats member function. These typically include Native format followed by presentation formats. This causes the Serialize, OnDraw, and OnGetTextData member functions to be called. The function then checks whether the document containing the item is connected to a server; if so, the function copies OwnerLink format and, if specified, ObjectLink format.

Return Value

Nonzero if the item was successfully copied to the Clipboard; otherwise 0.

See Also

»COleClientItem::CopyToClipboard«, »COleServerItem::OnEnumFormats«,  »COleServerItem::OnDraw«, »COleServerItem::OnGetTextData«, »CObject::Serialize«


  COleServerItem::GetDocument

COleServerDoc* GetDocument() const;

Remarks

Call this function to get a pointer to the document that contains the item. This allows access to the server document that you passed as an argument to the COleServerItem constructor.

Return Value

A pointer to the document that contains the item, NULL if the item is not part of a document.

See Also

»COleServerItem::COleServerItem«, »COleServerDoc«


  COleServerItem::GetItemName

const CString& GetItemName() const;

Remarks

Call this function to get the name of the item. You typically call this function only for linked items.

Return Value

The name of the item.

See Also

»COleServerItem::SetItemName«, »COleServerDoc::OnGetLinkedItem«


  COleServerItem::IsConnected

Protected

BOOL IsConnected() const; ♦

Remarks

Call this function to determine if the item is connected to its corresponding client item.

Return Value

Nonzero if the item is connected; otherwise 0.


  COleServerItem::NotifyChanged

void NotifyChanged();

Remarks

Call this function after the linked item has been changed. If a client item is linked to the document with an automatic link, the item is updated to reflect the changes. In client applications written with the Microsoft Foundation Class Library, the OnChange member function of COleClientItem is called in response.

See Also

»COleClientItem::OnChange«, »COleServerDoc::NotifyChanged«


  COleServerItem::OnDoVerb

Protected

virtual OLESTATUS OnDoVerb( UINT nVerb, BOOL bShow,
BOOL bTakeFocus ); ♦

nVerb    Server verb index; 0 is the primary index, 1 is the secondary index, and so forth.

bShow    TRUE if the server should show the item when it performs the operation.

bTakeFocus    TRUE if the server should set the input focus.

Remarks

Called by the framework when the COleClientItem::Activate function is called. The default implementation calls the OnShow member function for the primary verb if bShow is TRUE and calls OnExtraVerb for nonprimary verbs. Override this function if your primary verb does not show the item. For example, suppose the item were a sound recording and its primary verb were Play; in this case, you would not have to display the server application to play back the item.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleClientItem::Activate«, »COleServerItem::OnShow«, »COleServerItem::OnExtraVerb«


  COleServerItem::OnDraw

Protected

virtual BOOL OnDraw( CDC* pDC ) = 0; ♦

pDC    A pointer to the CDC object on which to draw the item. This is an output-only CMetafileDC object; do not call any attribute member functions of CDC for this parameter.

Remarks

Called by the framework to render the item into a metafile. The metafile representation of the item is used by the COleClientItem::Draw function to display the item in the client application. There is no default implementation. You must override this function to draw the item into the device context specified.

Return Value

Nonzero if the item was successfully drawn; otherwise 0.

See Also

»COleServerItem::OnGetData«, »COleClientItem::Draw«


  COleServerItem::OnEnumFormats

Protected

virtual OLECLIPFORMAT OnEnumFormats( OLECLIPFORMAT nFormat ) const; ♦

nFormat    Specifies the format returned by the previous call to the OnEnumFormats member function. For the first call to OnEnumFormats, this parameter is NULL. This parameter can be one of the predefined Clipboard formats or the value returned by the Windows RegisterClipboardFormat function.

Remarks

Called by the framework to determine what formats are available for the item. This is called in response to the COleClientItem::EnumFormats function; it is also called by the OLE system DLL. When called iteratively, this function returns all the Clipboard formats that are supported by this server. The default implementation returns Native, CF_METAFILEPICT, and CF_TEXT formats.

Override this function if you want to specify the formats supported by your server; for example, if you wanted to support the Paste Special command in client applications. Note that if you want to support the CF_TEXT format, you must override the OnGetTextData member function.

Return Value

The next (or first) available format; NULL if no more formats are available.

See Also

»COleClientItem::EnumFormats«, »COleServerItem::OnGetTextData«::RegisterClipboardFormat


  COleServerItem::OnExtraVerb

Protected

virtual OLESTATUS OnExtraVerb( UINT nVerb ); ♦

nVerb    Index of the verb to execute; 1 is the secondary verb, 2 is the tertiary verb, and so forth.

Remarks

Called by the framework when a client makes a request to execute a nonprimary verb. The default implementation returns OLE_ERROR_DOVERB. Override this function if the item supports more than one verb. You must provide the names of all supported verbs to the client applications through the Windows registration database.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleServerItem::OnShow«, »COleServerItem::OnDoVerb«, »COleClientItem::Activate«


  COleServerItem::OnGetData

Protected

virtual OLESTATUS OnGetData( OLECLIPFORMAT nFormat, LPHANDLE lphReturn ); ♦

nFormat    Specifies the format of the data. This parameter can be one of the predefined Clipboard formats or the value returned by the Windows »RegisterClipboardFormat« function.

lphReturn    Pointer to a handle to the block of memory that contains the requested data when the function returns.

Remarks

Called by the framework to retrieve the contents of the item in a specified format. This is called in response to the COleClientItem::GetData function. The default implementation supports Native and metafile formats; it uses the implementations of the Serialize and OnDraw member functions that you provide. This function also supports the CF_TEXT format if you have overridden the OnGetTextData member function. Override this function if you want to handle other formats. Allocate a memory object, fill it with the data in the desired format, and return it via the lphReturn parameter. This is an advanced overridable.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleServerItem::OnGetTextData«, »COleServerItem::OnSetData«, »COleServerItem::OnDraw«, »CObject::Serialize«, »COleClientItem::GetData«


  COleServerItem::OnGetTextData

Protected

virtual BOOL OnGetTextData( CString& rStringReturn ) const; ♦

rStringReturn    A reference to a CString that receives the text data when the function returns.

Remarks

Called by the framework to get the contents of the item in text (CF_TEXT) format. The default implementation returns FALSE. Override this function if the item can return its data in text form.

Return Value

Nonzero if text data is supported; otherwise 0.


  COleServerItem::OnSetBounds

Protected

virtual OLESTATUS OnSetBounds( LPCRECT lpRect ); ♦

lpRect    A pointer to a RECT structure specifying the new bounding rectangle.

Remarks

Called by the framework when the COleClientItem::SetBounds function is called. The default implementation updates the item's bounding rectangle with the specified rectangle. Override this function to perform special processing when you change the bounding rectangle for the item.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleClientItem::SetBounds«


  COleServerItem::OnSetColorScheme

Protected

virtual OLESTATUS
OnSetColorScheme( const LOGPALETTE FAR* lpLogPalette ); ♦

lpLogPalette    Pointer to a Windows LOGPALETTE structure.

Remarks

Called by the framework when the COleClientItem::SetColorScheme function is called. The default implementation does nothing. Override this function if you want to use the recommended palette.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleClientItem::SetColorScheme«


  COleServerItem::OnSetData

Protected

virtual OLESTATUS OnSetData( OLECLIPFORMAT nFormat, HANDLE hData ); ♦

nFormat    Specifies the format of the data. This parameter can be one of the predefined Clipboard formats or the value returned by the Windows »RegisterClipboardFormat« function.

hData    Handle to a memory object that contains the data in the specified format.

Remarks

Called by the framework to provide the server application with the data for the item, typically when an embedded item is opened for editing. This is called in response to the COleClientItem::SetData function; it is also called by the OLE system DLLs. The default implementation handles only Native format; it calls the Serialize member function to load the contents of the specified block of memory into the item. Override this function to process non-Native formats. You must free the memory object after you have used it.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleClientItem::SetData«, »COleServerItem::OnGetData«, »CObject::Serialize«


  COleServerItem::OnSetTargetDevice

Protected

virtual OLESTATUS OnSetTargetDevice( LPOLETARGETDEVICE lpTargetDevice ); ♦

lpTargetDevice    Points to a Windows OLETARGETDEVICE structure that describes the target device for the item. If NULL, the target device is the video display. Do not free this structure after you have used it.

Remarks

Called by the framework to provide the server application with information about the client application's target device for the item. This is called in response to the COleClientItem::SetTargetDevice function. The default implementation does nothing. Override this function if you want to know what kind of device the item will be rendered on. You can use this information to optimize the format of the information that you supply the client through the OnGetData member function.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleServerItem::OnGetData«, »COleClientItem::SetTargetDevice«


  COleServerItem::OnShow

Protected

virtual OLESTATUS OnShow( BOOL bTakeFocus ); ♦

bTakeFocus    TRUE if the item should take the input focus; otherwise FALSE.

Remarks

Called by the framework to instruct the server application to display the item. This function is typically called when the user of the client application creates an item or executes a verb, such as Edit, that requires the item to be shown. The default implementation activates the first frame window displaying the document that contains the item and, if bTakeFocus is TRUE, gives the window the focus. Override this function to make the item visible in the window (for example, by scrolling) and to select the item, if possible.

Return Value

See the »COleException« class for a list of return values. The value OLE_OK indicates that the function operated correctly.

See Also

»COleServerItem::OnDoVerb«, »COleServerItem::OnExtraVerb«, »COleClientItem::Activate«


  COleServerItem::Revoke

void Revoke();

Remarks

Call this function to revoke the client's access to the item. You should call this function when the user of the server application destroys an item. This function does not return until the revoke operation is complete, but it allows other messages to be processed while waiting.

See Also

 ::OleRevokeObject


  COleServerItem::SetItemName

void SetItemName( const char* pszItemName );

pszItemName    Pointer to the new name of the item.

Remarks

Call this function to set the name of the item. You should call this function when you create a linked item; the name must be unique within the document. When a server application is invoked to edit a linked item, the application uses this name to find the item. You do not need to call this function for embedded items.

See Also

»COleServerItem::GetItemName«, »COleServerDoc::OnGetLinkedItem«


COleTemplateServer
  class COleTemplateServer : public COleServer

The COleTemplateServer class defines an Object Linking and Embedding (OLE) server. It is derived from the abstract class COleServer; however, you can use COleTemplateServer directly rather than having to derive a class. COleTemplateServer uses a CDocTemplate object to manage the server documents. Use COleTemplateServer when implementing a full server, that is, a server that can be run as a stand-alone application. Full servers are typically multiple document interface (MDI) applications, although single document interface (SDI) applications are supported. One COleTemplateServer object is needed for each type of server document an application supports; that is, if your server application supports both worksheets and charts, you must have two COleTemplateServer objects.

COleTemplateServer overrides the OnCreateDoc, OnEditDoc, and OnOpenDoc member functions defined by COleServer. These member functions are called by the OLE system dynamic-link library (DLL) in response to requests from client applications. Through these member functions, the OLE system DLL instructs the server to open embedded items as documents or open the documents that are the source of linked items. See the descriptions for these functions under »COleServer« for more information on when these member functions are called.

COleTemplateServer implements these member functions by using the document-creation facilities of its associated CDocTemplate object. This lets your server application take advantage of the document/view architecture provided by the Microsoft Foundation Class Library. To use COleTemplateServer, create a CDocTemplate object, specifying a COleServerDoc-derived class as the document class, and add it to your application by passing it to the AddDocTemplate member function of CWinApp. To execute the server, pass the document template to the RunEmbedded member function of COleTemplateServer.

Note  The OLE documentation refers to embedded and linked items as "objects" and refers to types of items as "classes." This reference uses the term "item" to distinguish the OLE entity from the corresponding C++ object and the term "type" to distinguish the OLE category from the C++ class.

#include <afxole.h>

See Also

»CDocTemplate«, »COleServer«, »COleServerDoc«, »COleServerItem«


COleTemplateServer Class Members
  Class Members

Construction/Destruction — Public Members

»COleTemplateServer«	Constructs a COleTemplateServer object.
Operations — Public Members

»RunEmbedded«	Launches the server in embedded mode.


COleTemplateServer Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  COleTemplateServer::COleTemplateServer

COleTemplateServer();

Remarks

Constructs a COleTemplateServer object. Call the RunEmbedded member function to run the server.

See Also

»COleTemplateServer::RunEmbedded«


  COleTemplateServer::RunEmbedded

BOOL RunEmbedded( CDocTemplate* pDocTemplate, BOOL bMultiInstance, LPCSTR lpszCmdLine );

pDocTemplate    Pointer to a CDocTemplate object describing the document type. The document class should be derived from COleServerDoc.

bMultiInstance    Flag indicating whether multiple instances of the server application can be run simultaneously. Pass TRUE if your server is an SDI application; TRUE causes a separate instance of your application to run for each client. Pass FALSE if it is an MDI application since one instance of an MDI application can support multiple clients using separate document windows. Note that mini servers are typically SDI applications and full servers are typically MDI applications.

lpszCmdLine    Pointer to the command line.

Remarks

Call this function from the InitInstance member function of your CWinApp-derived application class, passing the command line from CWinApp::m_lpCmdLine. This function parses the command line to see whether the "/Embedding" or "-Embedding" option is present; either option indicates that the server application was launched by a client application. The function then registers the server with the OLE system DLL so that it can receive requests from clients. (If the application was launched as a stand-alone application, the function registers the server application with the Windows registration database before registering it with the OLE system DLL.) If a filename appeared after the "/Embedding" or "-Embedding" option (referring to the source of a linked item), the function then opens the specified file.

Return Value

Nonzero if the server was launched successfully; otherwise 0.

See Also

»COleServer::Register«, »CDocTemplate«, »COleServerDoc«, »CWinApp::InitInstance«, »CWinApp::m_lpCmdLine«


CPaintDC
  class CPaintDC : public CDC

The CPaintDC class is a device-context class derived from CDC. It performs a »CWnd::BeginPaint« at construction time and »CWnd::EndPaint« at destruction time.

A CPaintDC object can only be used when responding to a WM_PAINTmessage, usually in your OnPaint message-handler member function.

#include <afxwin.h>

See Also

»CDC«


CPaintDC Class Members
  Class Members

Data Members — Public Members

»m_ps«	Contains the »PAINTSTRUCT« used to paint the client area.
Construction/Destruction — Public Members

»CPaintDC«	Constructs a CPaintDC connected to the specified »CWnd«.
Data Members — Protected Members

»m_hWnd«	The HWND to which this CPaintDC object is attached.


CPaintDC Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPaintDC::CPaintDC

CPaintDC( CWnd* pWnd )
throw( CResourceException );

pWnd    Points to the CWnd object to which the CPaintDC object belongs.

Remarks

Constructs a CPaintDC object, prepares the application window for painting, and stores the »PAINTSTRUCT« structure in the »m_ps« member variable.

An exception (of type CResourceException) is thrown if the Windows GetDCcall fails. A device context may not be available if Windows has already allocated all of its available device contexts. Your application competes for the five common display contexts available at any given time under Windows.


CPaintDC Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CPaintDC::m_hWnd

Remarks

The HWND to which this CPaintDC object is attached. m_hWnd is a protected variable of type HWND.


  CPaintDC::m_ps

Remarks

m_ps is a public member variable of type »PAINTSTRUCT«. It is the PAINTSTRUCT that is passed to and filled out by »CWnd::BeginPaint«.

The PAINTSTRUCT contains information that the application uses to paint the client area of the window associated with a CPaintDC object.

Note that you can access the device-context handle through the PAINTSTRUCT. However, you can access the handle more directly through the m_hDC member variable that CPaintDC inherits from CDC.

PAINTSTRUCTStructure

The PAINTSTRUCT structure looks like this:

typedef struct tagPAINTSTRUCT {
   HDC  hdc;
   BOOL fErase;
   RECT rcPaint;
   BOOL fRestore;
   BOOL fIncUpdate;
   BYTE rgbReserved[16];
} PAINTSTRUCT;

Members

hdc    Identifies the display context to be used for painting.

fErase    Specifies whether the background needs to be redrawn. It is not 0 if the application should redraw the background. The application is responsible for drawing the background if a Windows window-class is created without a background brush (see the description of the hbrBackground member of the WNDCLASS structure in the Windows Software Development Kit documentation).

rcPaint    Specifies the upper-left and lower-right corners of the rectangle in which the painting is requested.

fRestore    Reserved member. It is used internally by Windows.

fIncUpdate    Reserved member. It is used internally by Windows.

rgbReserved[16]    Reserved member. A reserved block of memory used internally by Windows.


CPalette
  class CPalette : public CGdiObject

The CPalette class encapsulates a Windows color palette. A palette provides an interface between an application and a color output device (such as a display device). The interface allows the application to take full advantage of the color capabilities of the output device without severely interfering with the colors displayed by other applications. Windows uses the application's logical palette (a list of needed colors) and the system palette (which defines available colors) to determine the colors used.

A CPalette object provides member functions for manipulating the palette referred to by the object. Construct a CPalette object and use its member functions to create the actual palette, a graphics device interface (GDI) object, and to manipulate its entries and other properties.

#include <afxwin.h>


CPalette  Class Members
  Class Members

Construction/Destruction — Public Members

»CPalette«	Constructs a CPalette object with no attached Windows palette. You must initialize the CPalette object with one of the other member functions before it can be used.
Initialization — Public Members

»CreatePalette«	Initializes a CPalette object by creating a Windows color palette and attaching the palette to the CPalette object.
Operations — Public Members

»FromHandle«	Returns a pointer to a CPalette object when given a handle to a Windows palette object. If a CPalette object is not already attached to the Windows palette, a temporary CPalette object is created and attached.
»GetPaletteEntries«	Retrieves a range of palette entries in a logical palette.
»SetPaletteEntries«	Sets RGB color values and flags in a range of entries in a logical palette.
»AnimatePalette«	Replaces entries in the logical palette identified by the CPalette object. The application does not have to update its client area because Windows maps the new entries into the system palette immediately.
»GetNearestPaletteIndex«	Returns the index of the entry in the logical palette that most closely matches a color value.
»ResizePalette«	Changes the size of the logical palette specified by the CPalette object to the specified number of entries.


CPalette Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPalette::AnimatePalette

void AnimatePalette( UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors );

nStartIndex    Specifies the first entry in the palette to be animated.

nNumEntries    Specifies the number of entries in the palette to be animated.

lpPaletteColors    Points to the first member of an array of PALETTEENTRY structures to replace the palette entries identified by nStartIndex and nNumEntries.

Remarks

Replaces entries in the logical palette attached to the CPalette object. When an application calls AnimatePalette, it does not have to update its client area because Windows maps the new entries into the system palette immediately.

The AnimatePalette function will only change entries with the PC_RESERVED flag set in the corresponding palPaletteEntry member of the LOGPALETTEstructure that is attached to the CPalette object.

See Also

»CPalette::CreatePalette«, ::AnimatePalette


  CPalette::CPalette

CPalette();

Remarks

Constructs a CPalette object. The object has no attached palette until you call CreatePalette to attach one.

See Also

»CPalette::CreatePalette«


  CPalette::CreatePalette

BOOL CreatePalette( LPLOGPALETTE lpLogPalette );

lpLogPalette    Points to a LOGPALETTE structure that contains information about the colors in the logical palette.

Remarks

Initializes a CPalette object by creating a Windows logical color palette and attaching it to the CPalette object.

Return Value

Nonzero if successful; otherwise 0.

See Also

::CreatePalette


  CPalette::FromHandle

static CPalette* PASCAL FromHandle( HPALETTE hPalette );

hPalette    A handle to a Windows GDI color palette.

Remarks

Returns a pointer to a CPalette object when given a handle to a Windows palette object. If a CPalette object is not already attached to the Windows palette, a temporary CPalette object is created and attached. This temporary CPalette object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CPalette object if successful; otherwise NULL.


  CPalette::GetNearestPaletteIndex

UINT GetNearestPaletteIndex( COLORREF crColor ) const;

crColor    Specifies the color to be matched.

Remarks

Returns the index of the entry in the logical palette that most closely matches the specified color value.

Return Value

The index of an entry in a logical palette. The entry contains the color that most nearly matches the specified color.

See Also

::GetNearestPaletteIndex


  CPalette::GetPaletteEntries

UINT GetPaletteEntries( UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors ) const;

nStartIndex    Specifies the first entry in the logical palette to be retrieved.

nNumEntries    Specifies the number of entries in the logical palette to be retrieved.

lpPaletteColors    Points to an array of PALETTEENTRY data structures to receive the palette entries. The array must contain at least as many data structures as specified by nNumEntries.

Remarks

Retrieves a range of palette entries in a logical palette.

Return Value

The number of entries retrieved from the logical palette; 0 if the function failed.

See Also

::GetPaletteEntries


  CPalette::ResizePalette

BOOL ResizePalette( UINT nNumEntries );

nNumEntries    Specifies the number of entries in the palette after it has been resized.

Remarks

Changes the size of the logical palette attached to the CPalette object to the number of entries specified by nNumEntries. If an application calls ResizePalette to reduce the size of the palette, the entries remaining in the resized palette are unchanged. If the application calls ResizePalette to enlarge the palette, the additional palette entries are set to black (the red, green, and blue values are all 0), and the flags for all additional entries are set to 0.

Return Value

Nonzero if the palette was successfully resized; otherwise 0.

See Also

::ResizePalette


  CPalette::SetPaletteEntries

UINT SetPaletteEntries( UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors );

nStartIndex    Specifies the first entry in the logical palette to be set.

nNumEntries    Specifies the number of entries in the logical palette to be set.

lpPaletteColors    Points to an array of PALETTEENTRY data structures to receive the palette entries. The array must contain at least as many data structures as specified by nNumEntries.

Remarks

Sets RGB color values and flags in a range of entries in a logical palette.

If the logical palette is selected into a device context when the application calls SetPaletteEntries, the changes will not take effect until the application calls »CDC::RealizePalette«.

Return Value

The number of entries set in the logical palette; 0 if the function failed.

See Also

»CDC::RealizePalette«, ::SetPaletteEntries


CPen
  class CPen : public CGdiObject

The CPen class encapsulates a Windows graphics device interface (GDI) pen.

#include <afxwin.h>


CPen Class Members
  Class Members

Construction/Destruction — Public Members

»CPen«	Constructs a CPen object.
Initialization — Public Members

»CreatePen«	Initializes a pen with the specified style, width, and color.
»CreatePenIndirect«	Initializes a pen with the style, width, and color given in a LOGPEN structure.
Operations — Public Members

»FromHandle«	Returns a pointer to a CPen object when given a Windows HPEN.


CPen Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPen::CPen

CPen();

CPen( int nPenStyle, int nWidth, COLORREF crColor )
throw( CResourceException );

nPenStyle    Specifies the pen style. This parameter can be one of the following values:

•	PS_SOLID    Creates a solid pen.

•	PS_DASH    Creates a dashed pen. Valid only when the pen width is 1.

•	PS_DOT    Creates a dotted pen. Valid only when the pen width is 1.

•	PS_DASHDOT    Creates a pen with alternating dashes and dots. Valid only when the pen width is 1.

•	PS_DASHDOTDOT    Creates a pen with alternating dashes and double dots. Valid only when the pen width is 1.

•	PS_NULL    Creates a null pen.

•	PS_INSIDEFRAME    Creates a pen that draws a line inside the frame of closed shapes produced by the Windows GDI output functions that specify a bounding rectangle (for example, the Ellipse, Rectangle, RoundRect, Pie, and Chord member functions). When this style is used with Windows GDI output functions that do not specify a bounding rectangle (for example, the LineTo member function), the drawing area of the pen is not limited by a frame.

nWidth    Specifies the width, in logical units, of the pen. If this value is 0, the width in device units is always 1 pixel, regardless of the mapping mode.

crColor    Contains an RGB color for the pen.

Remarks

If you use the constructor with no arguments, you must initialize the resulting CPen object with the CreatePen, CreatePenIndirect, or CreateStockObject member functions. If you use the constructor that takes arguments, then no further initialization is necessary. The constructor with arguments can throw an exception if errors are encountered, while the constructor with no arguments will always succeed.

See Also

»CPen::CreatePen«, »CPen::CreatePenIndirect«, »CGdiObject::CreateStockObject«


  CPen::CreatePen

BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );

nPenStyle    Specifies the style for the pen. For a list of possible values, see the nPenStyle parameter to the »CPen« constructor.

nWidth    Specifies the width of the pen (in logical units). If this value is 0, the width in device units is always 1 pixel, regardless of the mapping mode.

crColor    Contains an RGB color for the pen.

Remarks

Initializes a pen with the specified style, width, and color. The pen can be subsequently selected as the current pen for any device context.

Pens that have a width greater than 1 pixel should always have either the PS_NULL, PS_SOLID, or PS_INSIDEFRAME style.

If a pen has the PS_INSIDEFRAME style and a color that does not match a color in the logical color table, the pen is drawn with a dithered color. The PS_SOLID pen style cannot be used to create a pen with a dithered color. The style PS_INSIDEFRAME is identical to PS_SOLID if the pen width is less than or equal to 1.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CPen::CreatePenIndirect«, »CPen::CPen«


  CPen::CreatePenIndirect

BOOL CreatePenIndirect( LPLOGPEN lpLogPen );

lpLogPen    Points to the Windows »LOGPEN« structure that contains information about the pen.

Remarks

Initializes a pen that has the style, width, and color given in the structure pointed to by lpLogPen.

Pens that have a width greater than 1 pixel should always have either the PS_NULL, PS_SOLID, or PS_INSIDEFRAME style.

If a pen has the PS_INSIDEFRAME style and a color that does not match a color in the logical color table, the pen is drawn with a dithered color. The PS_INSIDEFRAME style is identical to PS_SOLID if the pen width is less than or equal to 1.

Return Value

Nonzero if the function is successful; otherwise 0.

LOGPEN Structure

A LOGPEN structure has this form:

typedef struct tagLOGPEN {  /* lgpn */

    UINT     lopnStyle;

    POINT    lopnWidth;

    COLORREF lopnColor;

} LOGPEN;

The LOGPEN structure defines the style, width, and color of a pen, a drawing object used to draw lines and borders. The CreatePenIndirect function uses the LOGPEN structure.

Members

lopnStyle    Specifies the pen type. This member can be one of the following values:

•	PS_SOLID    Creates a solid pen.

•	PS_DASH    Creates a dashed pen. (Valid only when the pen width is 1.)

•	PS_DOT    Creates a dotted pen. (Valid only when the pen width is 1.)

•	PS_DASHDOT    Creates a pen with alternating dashes and dots. (Valid only when the pen width is 1.)

•	PS_DASHDOTDOT    Creates a pen with alternating dashes and double dots. (Valid only when the pen width is 1.)

•	PS_NULL    Creates a null pen.

•	PS_INSIDEFRAME    Creates a pen that draws a line inside the frame of closed shapes produced by GDI output functions that specify a bounding rectangle (for example, the Ellipse, Rectangle, RoundRect, Pie, and Chord member functions). When this style is used with GDI output functions that do not specify a bounding rectangle (for example, the LineTo member function), the drawing area of the pen is not limited by a frame.

If a pen has the PS_INSIDEFRAME style and a color that does not match a color in the logical color table, the pen is drawn with a dithered color. The PS_SOLID pen style cannot be used to create a pen with a dithered color. The PS_INSIDEFRAME style is identical to PS_SOLID if the pen width is less than or equal to 1.

When the PS_INSIDEFRAME style is used with GDI objects produced by functions other than Ellipse, Rectangle, and RoundRect, the line may not be completely inside the specified frame.

lopnWidth    Specifies the pen width, in logical units. If the lopnWidth member is 0, the pen is 1 pixel wide on raster devices regardless of the current mapping mode.

lopnColor    Specifies the pen color.

Comments

The y value in the POINT structure for the lopnWidth member is not used.

See Also

»CPen::CreatePen«, »CPen::CPen«


  CPen::FromHandle

static CPen* PASCAL FromHandle( HPEN hPen );

hPen    HPEN handle to Windows GDI pen.

Remarks

Returns a pointer to a CPen object given a handle to a Windows GDI pen object. If a CPen object is not attached to the handle, a temporary CPen object is created and attached. This temporary CPen object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. In other words, the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CPen object if successful; otherwise NULL.


CPoint
  class CPoint : public tagPOINT

The CPoint class is similar to the Windows POINT structure and also includes member functions to manipulate CPoint and »POINT« structures.

A CPoint object can be used wherever a POINT structure is used. The operators of this class that interact with a "size" accept either CSize objects or SIZE structures, as the two are interchangeable.

#include <afxwin.h>

POINT Structure

The POINT data structure looks like this:

typedef struct tagPOINT {
   int x;
   int y;
} POINT;

The POINT structure defines the x- and y-coordinates of a point.

Members

x    Specifies the x-coordinate of a point.

y    Specifies the y-coordinate of a point.

See Also

»CRect«, »CSize«


CPoint Class Members
  Class Members

Construction/Destruction — Public Members

»CPoint«	Constructs a CPoint.
Operations — Public Members

»Offset«	Adds separate values to the x and y members of the CPoint.
»operator ==«	Checks for equality between two points.
»operator !=«	Checks for inequality between two points.
»operator +=«	Offsets a CPoint by a size.
»operator −=«	Subtracts a size from the CPoint.
Operators Returning CPoint Values — Public Members

»operator +«	Returns a CPoint offset by a size.
»operator −«	Returns a CPoint offset by a negative size.
Operators Returning CSize Values — Public Members

»operator −«	Returns the size difference between two points.


CPoint Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPoint::CPoint

CPoint();

CPoint( int initX, int initY );

CPoint( POINT initPt );

CPoint( SIZE initSize );

CPoint( DWORD dwPoint );

initX    Sets the x member for the CPoint.

initY    Sets the y member for the CPoint.

initPt    Windows POINT structure or CPoint used to initialize CPoint.

initSize    Sets the x and y members equal to the corresponding values in cx and cy values in initSize.

dwPoint    Sets the low-order word to the x member and the high-order word to the y member.

Remarks

Constructs a CPoint object. If no arguments are given, x and y members are not initialized.


  CPoint::Offset

void Offset( int xOffset, int yOffset );

void Offset( POINT point );

void Offset( SIZE size );

xOffset    Specifies the amount to offset the x member of the CPoint.

yOffset    Specifies the amount to offset the y member of the CPoint.

point    Specifies the amount (POINT or CPoint) to offset the CPoint.

size    Specifies the amount (SIZE or CSize) to offset the CPoint.

Remarks

Adds separate values to the x and y members of the CPoint.

Return Value

A CPoint offset by a POINT, CPoint, CSize, or SIZE.


CPoint Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CPoint::operator ==

BOOL operator ==( POINT point ) const;

point    Contains a POINT structure or CPoint object.

Remarks

Checks for equality between two points.

Return Value

Nonzero if the points are equal; otherwise 0.


  CPoint::operator !=

BOOL operator !=( POINT point ) const;

point    Contains a POINT structure or CPoint object.

Remarks

Checks for inequality between two points.

Return Value

Nonzero if the points are not equal; otherwise 0.


  CPoint::operator +=

void operator +=( SIZE size );

size    Contains a SIZE structure or CSize object.

Remarks

Offsets a CPoint by a size.


CPoint::operator -=
  CPoint::operator −=

void operator −=( SIZE size );

size    Contains a SIZE structure or CSize object.

Remarks

Subtracts a size from the CPoint.


  CPoint::operator +

CPoint operator +( SIZE size ) const;

size    Contains a SIZE structure or CSize object.

Return Value

A CPoint that is offset by a size.


CPoint::operator -
  CPoint::operator −

CSize operator −( POINT point ) const;

CPoint operator −( SIZE size ) const;

CPoint operator −() const;

point    Contains a POINT structure or CPoint object.

size    Contains a SIZE structure or CSize object.

Return Value

A CSize that is the difference between two points, or returns a CPoint that is offset by a negative size.


CPrintDialog
  class CPrintDialog : public CDialog

The CPrintDialog class encapsulates the services provided by the Windows common dialog box for printing. Common print dialog boxes provide an easy way to implement Print and Print Setup dialog boxes in a manner consistent with Windows standards.

If you wish, you can rely on the framework to handle many aspects of the printing process for your application. In this case, the framework automatically displays the Windows common dialog box for printing. You can also have the framework handle printing for your application but override the common Print dialog box with your own print dialog box. For more information on using the framework to handle printing tasks, see Chapter 9 of the Class Library User's Guide.

If you want your application to handle printing without the framework's involvement, you can use the CPrintDialog class "as is" with the constructor provided, or you can derive your own dialog class from CPrintDialog and write a constructor to suit your needs. In either case, these dialog boxes will behave like standard Microsoft Foundation class dialog boxes because they are derived from class CDialog.

To use a CPrintDialog object, first create the object using the CPrintDialog constructor. Once the dialog box has been constructed, you can set or modify any values in the m_pd structure to initialize the values of the dialog box's controls. The m_pd structure is of type PRINTDLG. For more information on this structure, see the Windows Software Development Kit (SDK) documentation.

If you do not supply your own handles in m_pd for the hDevMode and hDevNames members, be sure to call the Windows function GlobalFree for these handles when you are done with the dialog box.

After initializing the dialog box controls, call the DoModal member function to display the dialog box and allow the user to select the path and file. DoModal returns whether the user selected the OK (IDOK) or Cancel (IDCANCEL) button.

If DoModal returns IDOK, you can use one of CPrintDialog's member functions to retrieve the information input by the user.

The CPrintDialog::GetDefaults member function is useful for retrieving the current printer defaults without displaying a dialog box. This member function requires no user interaction.

You can use the Windows CommDlgExtendedError function to determine if an error occurred during initialization of the dialog box and to learn more about the error. For more information on this function, see the Windows SDK documentation.

CPrintDialog relies on the COMMDLG.DLL file that ships with Windows versions 3.1 and later. For details about redistributing COMMDLG.DLL to Windows version 3.0 users, see the Getting Started manual for the Windows version 3.1 SDK.

To customize the dialog box, derive a class from CPrintDialog, provide a custom dialog template, and add a message map to process the notification messages from the extended controls. Any unprocessed messages should be passed on to the base class. Customizing the hook function is not required.

To process the same message differently depending on whether the dialog box is Print or Print Setup, you must derive a class for each dialog box. You must also override the Windows AttachOnSetup function, which handles the creation of a new dialog box when the Print Setup button is selected within a Print dialog box.

#include <afxdlgs.h>


CPrintDialog  Class Members
  Class Members

Data Members — Public Members

»m_pd«	A structure used to customize a CPrintDialog object.
Construction/Destruction — Public Members

»CPrintDialog«	Constructs a CPrintDialog object.
Operations — Public Members

»DoModal«	Displays the dialog box and allows the user to make a selection.
»GetCopies«	Retrieves the number of copies requested.
»GetDefaults«	Retrieves device defaults without displaying a dialog box.
»GetDeviceName«	Retrieves the name of the currently selected printer device.
»GetDevMode«	Retrieves the DEVMODE structure.
»GetDriverName«	Retrieves the name of the currently selected printer driver.
»GetFromPage«	Retrieves the starting page of the print range.
»GetToPage«	Retrieves the ending page of the print range.
»GetPortName«	Retrieves the name of the currently selected printer port.
»GetPrinterDC«	Retrieves a handle to the printer device context.
»PrintAll«	Determines whether to print all pages of the document.
»PrintCollate«	Determines whether collated copies are requested.
»PrintRange«	Determines whether to print only a specified range of pages.
»PrintSelection«	Determines whether to print only the currently selected items.


CPrintDialog Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPrintDialog::CPrintDialog

CPrintDialog( BOOL bPrintSetupOnly, DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_HIDEPRINTTOFILE
| PD_NOSELECTION, CWnd* pParentWnd = NULL );

bPrintSetupOnly    Specifies whether the standard Windows Print dialog box or Print Setup dialog box is displayed. Set this parameter to TRUE to display the standard Windows Print Setup dialog box. Set it to FALSE to display the Windows Print dialog box. If bPrintSetupOnly is FALSE, a Print Setup option button is still displayed in the Print dialog box.

dwFlags    One or more flags you can use to customize the settings of the dialog box, combined using the bitwise-OR operator. For example, the PD_ALLPAGES flag sets the default print range to all pages of the document. See the PRINTDLG structure in the Windows SDK for more information on these flags.

pParentWnd    A pointer to the dialog box's parent or owner window.

Remarks

Constructs either a Windows Print or Print Setup dialog object. This member function only constructs the object. Use the DoModal member function to invoke the dialog box.

See Also

»CPrintDialog::DoModal«, ::PrintDlg, PRINTDLG


  CPrintDialog::DoModal

virtual int DoModal();

Remarks

Call this function to display the Windows common print dialog box and allow the user to select various printing options such as the number of copies, page range, and whether copies should be collated.

If you want to initialize the various print dialog options by setting members of the m_pd structure, you should do this before calling DoModal, but after the dialog object is constructed.

After calling DoModal, you can call other member functions to retrieve the settings or information input by the user into the dialog box.

Return Value

IDOK or IDCANCEL if the function is successful; otherwise 0. IDOK and IDCANCEL are constants that indicate whether the user selected the OK or Cancel button.

If IDCANCEL is returned, you can call the Windows CommDlgExtendedError function to determine if an error occured.

See Also

»CPrintDialog::CPrintDialog«, »CDialog::DoModal«


  CPrintDialog::GetCopies

int GetCopies() const;

Remarks

Call this function after calling DoModal to retrieve the number of copies requested.

Return Value

The number of copies requested.

See Also

»CPrintDialog::PrintCollate«


  CPrintDialog::GetDefaults

BOOL GetDefaults();

Remarks

Call this function to retrieve the device defaults of the default printer without displaying a dialog box. The retrieved values are placed in the m_pd structure.

Return Value

Nonzero if the function was successful; otherwise 0.

See Also

»CPrintDialog::m_pd«


  CPrintDialog::GetDeviceName

CString GetDeviceName() const;

Remarks

Call this function after calling DoModal to retrieve the name of the currently selected printer.

Return Value

The name of the currently selected printer.

See Also

»CPrintDialog::GetDriverName«, »CPrintDialog::GetDevMode«, »CPrintDialog::GetPortName«


  CPrintDialog::GetDevMode

LPDEVMODE GetDevMode() const;

Remarks

Call this function after calling DoModal to retrieve information about the printing device.

Return Value

The »DEVMODE« data structure, which contains information about the device initialization and environment of a print driver. You must free the memory taken by this structure with the Windows GlobalFree function. See PRINTDLG in the Windows SDK reference for more information about using GlobalFree.

A DEVMODE data structure has this form:

#include <print.h>

typedef struct tagDEVMODE {   /* dm */

    char  dmDeviceName[CCHDEVICENAME];

    UINT  dmSpecVersion;

    UINT  dmDriverVersion;

    UINT  dmSize;

    UINT  dmDriverExtra;

    DWORD dmFields;

    int   dmOrientation;

    int   dmPaperSize;

    int   dmPaperLength;

    int   dmPaperWidth;

    int   dmScale;

    int   dmCopies;

    int   dmDefaultSource;

    int   dmPrintQuality;

    int   dmColor;

    int   dmDuplex;

    int   dmYResolution;

    int   dmTTOption;

} DEVMODE;

For more complete information about this structure, see DEVMODEin the Windows SDK.

See Also

»CDC::GetDeviceCaps«


  CPrintDialog::GetDriverName

CString GetDriverName() const;

Remarks

Call this function after calling DoModal to retrieve the name of the currently selected printer device driver.

Return Value

The name of the currently selected printer device driver.

See Also

»CPrintDialog::GetDeviceName«, »CPrintDialog::GetDevMode«, »CPrintDialog::GetPortName«


  CPrintDialog::GetFromPage

int GetFromPage() const;

Remarks

Call this function after calling DoModal to retrieve the starting page number in the range of pages to be printed.

Return Value

The starting page number in the range of pages to be printed.

See Also

»CPrintDialog::GetToPage«, »CPrintDialog::PrintRange«


  CPrintDialog::GetPortName

CString GetPortName() const;

Remarks

Call this function after calling DoModal to retrieve the name of the currently selected printer port.

Return Value

The name of the currently selected printer port.

See Also

»CPrintDialog::GetDriverName«, »CPrintDialog::GetDeviceName«


  CPrintDialog::GetPrinterDC

HDC GetPrinterDC() const;

Remarks

If the bPrintSetupOnly parameter of the CPrintDialog constructor was FALSE (indicating that the Print dialog box is displayed), then GetPrinterDC returns a handle to the printer device context. You must call the Windows DeleteDC function to delete the device context when you are done using it.

Return Value

A handle to the printer device context if successful; otherwise NULL.


  CPrintDialog::GetToPage

int GetToPage() const;

Remarks

Call this function after calling DoModal to retrieve the ending page number in the range of pages to be printed.

Return Value

The ending page number in the range of pages to be printed.

See Also

»CPrintDialog::GetFromPage«, »CPrintDialog::PrintRange«


  CPrintDialog::PrintAll

BOOL PrintAll() const;

Remarks

Call this function after calling DoModal to determine whether to print all pages in the document.

Return Value

Nonzero if all pages in the document are to be printed; otherwise 0.

See Also

»CPrintDialog::PrintRange«, »CPrintDialog::PrintSelection«


  CPrintDialog::PrintCollate

BOOL PrintCollate() const;

Remarks

Call this function after calling DoModal to determine whether the printer should collate all printed copies of the document.

Return Value

Nonzero if the user selects the collate check box in the dialog box; otherwise 0.

See Also

»CPrintDialog::GetCopies«


  CPrintDialog::PrintRange

BOOL PrintRange() const;

Remarks

Call this function after calling DoModal to determine whether to print only a range of pages in the document.

Return Value

Nonzero if only a range of pages in the document are to be printed; otherwise 0.

See Also

»CPrintDialog::PrintAll«, »CPrintDialog::PrintSelection«, »CPrintDialog::GetFromPage«, »CPrintDialog::GetToPage«


  CPrintDialog::PrintSelection

BOOL PrintSelection() const;

Remarks

Call this function after calling DoModal to determine whether to print only the currently selected items.

Return Value

Nonzero if only the selected items are to be printed; otherwise 0.

See Also

»CPrintDialog::PrintRange«, »CPrintDialog::PrintAll«


CPrintDialog Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CPrintDialog::m_pd

PRINTDLG FAR& m_pd;

Remarks

A structure whose members store the characteristics of the dialog object. After constructing a CPrintDialog object, you can use m_pd to set various aspects of the dialog box before calling the DoModal member function. For more information on the m_pd structure, see PRINTDLG in the Windows SDK documentation.

If you modify the m_pd data member directly, you will override any default behavior.


CPrintInfo
struct CPrintInfo

CPrintInfo stores information about a print or print-preview job. The framework creates an object of CPrintInfo each time the Print or Print Preview command is chosen and destroys it when the command is completed.

CPrintInfo contains information about both the print job as a whole, such as the range of pages to be printed, and the current status of the print job, such as the page currently being printed. Some information is stored in an associated CPrintDialog object; this object contains the values entered by the user in the Print dialog box.

A CPrintInfo object is passed between the framework and your view class during the printing process and is used to exchange information between the two. For example, the framework informs the view class which page of the document to print by assigning a value to the m_nCurPage member of CPrintInfo; the view class retrieves the value and performs the actual printing of the specified page.

Another example is the case when the length of the document is not known until it is printed. In this situation, the view class tests for the end of the document each time a page is printed. When the end is reached, the view class sets the m_bContinuePrinting member of CPrintInfo to FALSE; this informs the framework to stop the print loop.

CPrintInfo is used by the member functions of CView that are listed under "See Also." For more information about the printing architecture provided by the Microsoft Foundation Class Library, see Chapter 4, »Working with Frame Windows, Documents, and Views«, in this manual and Chapter 9 of the Class Library User's Guide.

#include <afxext.h>

See Also

»CView::OnBeginPrinting«, »CView::OnEndPrinting«, »CView::OnEndPrintPreview«, »CView::OnPrepareDC«, »CView::OnPreparePrinting«, »CView::OnPrint«


CPrintInfo Class Members
  Class Members

Data Members — Public Members

»m_pPD«	Contains a pointer to CPrintDialog object used for the Print dialog box.
»m_bPreview«	Contains a flag indicating whether the document is being previewed.
»m_bContinuePrinting«	Contains a flag indicating whether the framework should continue the print loop.
»m_nCurPage«	Identifies the number of the page currently being printed.
»m_nNumPreviewPages«	Identifies the number of pages displayed in the preview window; either 1 or 2.
»m_lpUserData«	Contains a pointer to a user-created structure.
»m_rectDraw«	Specifies a rectangle defining the current usable page area.
»m_strPageDesc«	Contains a format string for page-number display.
Attributes — Public Members

»SetMinPage«	Sets the number of the first page of the document.
»SetMaxPage«	Sets the number of the last page of the document.
»GetMinPage«	Returns the number of the first page of the document.
»GetMaxPage«	Returns the number of the last page of the document.
»GetFromPage«	Returns the number of the first page being printed.
»GetToPage«	Returns the number of the last page being printed.


CPrintInfo Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CPrintInfo::GetFromPage

UINT GetFromPage();

Remarks

Call this function to retrieve the number of the first page to be printed. This is the value specified by the user in the Print dialog box, and it is stored in the CPrintDialog object referenced by the m_pPD member. If the user has not specified a value, the default is the first page of the document.

See Also

»CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetToPage«


  CPrintInfo::GetMaxPage

UINT GetMaxPage();

Remarks

Call this function to retrieve the number of the last page of the document. This value is stored in the CPrintDialog object referenced by the m_pPD member.

See Also

»CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetMinPage«, »CPrintInfo::SetMaxPage«, »CPrintInfo::SetMinPage«


  CPrintInfo::GetMinPage

UINT GetMinPage();

Remarks

Call this function to retrieve the number of the first page of the document. This value is stored in the CPrintDialog object referenced by the m_pPD member.

See Also

»CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetMaxPage«, »CPrintInfo::SetMaxPage«, »CPrintInfo::SetMinPage«


  CPrintInfo::GetToPage

UINT GetToPage();

Remarks

Call this function to retrieve the number of the last page to be printed. This is the value specified by the user in the Print dialog box, and it is stored in the CPrintDialog object referenced by the m_pPD member. If the user has not specified a value, the default is the last page of the document.

See Also

»CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetFromPage«


  CPrintInfo::SetMaxPage

void SetMaxPage( UINT nMaxPage );

nMaxPage    Number of the last page of the document.

Remarks

Call this function to specify the number of the last page of the document. This value is stored in the CPrintDialog object referenced by the m_pPD member. If the length of the document is known before it is printed, call this function from your override of CView::OnPreparePrinting. If the length of the document depends on a setting specified by the user in the Print dialog box, call this function from your override of CView::OnBeginPrinting. If the length of the document is not known until it is printed, use the m_bContinuePrinting member to control the print loop.

See Also

»CPrintInfo::m_bContinuePrinting«, »CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetMinPage«, »CPrintInfo::GetToPage«, »CPrintInfo::SetMinPage«, »CView::OnBeginPrinting«, »CView::OnPreparePrinting«


  CPrintInfo::SetMinPage

void SetMinPage( UINT nMinPage );

nMinPage    Number of the first page of the document.

Remarks

Call this function to specify the number of the first page of the document. Page numbers normally start at 1. This value is stored in the CPrintDialog object referenced by the m_pPD member.

See Also

»CPrintInfo::m_nCurPage«, »CPrintInfo::m_pPD«, »CPrintInfo::GetMaxPage«, »CPrintInfo::GetMinPage«, »CPrintInfo::SetMaxPage«


CPrintInfo Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CPrintInfo::m_bContinuePrinting

Remarks

Contains a flag indicating whether the framework should continue the print loop. If you are doing print-time pagination, you can set this member to FALSE in your override of CView::OnPrepareDC once the end of the document has been reached. You do not have to modify this variable if you have specified the length of the document at the beginning of the print job using the SetMaxPage member function. The m_bContinuePrinting member is a public variable of type BOOL.

See Also

»CPrintInfo::SetMaxPage«, »CView::OnPrepareDC«


  CPrintInfo::m_bPreview

Remarks

Contains a flag indicating whether the document is being previewed. This is set by the framework depending on which command the user executed. The Print dialog box is not displayed for a print-preview job. The m_bPreview member is a public variable of type BOOL.

See Also

»CView::DoPreparePrinting«, »CView::OnPreparePrinting«


  CPrintInfo::m_lpUserData

Remarks

Contains a pointer to a user-created structure. You can use this to store printing-specific data that you don't want to store in your view class. The m_lpUserData member is a public variable of type LPVOID.


  CPrintInfo::m_nCurPage

Remarks

Contains the number of the current page. The framework calls  CView::OnPrepareDC and CView::OnPrint once for each page of the document, specifying a different value for this member each time; its values range from the value returned by GetFromPage to that returned by GetToPage. Use this member in your overrides of CView::OnPrepareDC and CView::OnPrint to print the specified page of the document.

When preview mode is first invoked, the framework reads the value of this member to determine which page of the document should be previewed initially. You can set the value of this member in your override of CView::OnPreparePrinting to maintain the user's current position in the document when entering preview mode. The m_nCurPage member is a public variable of type UINT.

See Also

»CPrintInfo::GetFromPage«, »CPrintInfo::GetToPage«, »CView::OnPrepareDC«, »CView::OnPreparePrinting«, »CView::OnPrint«


  CPrintInfo::m_nNumPreviewPages

Remarks

Contains the number of pages displayed in preview mode; it can be either 1 or 2. The m_nNumPreviewPages member is a public variable of type UINT.

See Also

»CPrintInfo::m_strPageDesc«


  CPrintInfo::m_pPD

Remarks

Contains a pointer to the CPrintDialog object used to display the Print dialog box for the print job. The m_pPD member is a public variable of type CPrintDialog*.

See Also

»CPrintDialog«


  CPrintInfo::m_rectDraw

Remarks

Specifies the usable drawing area of the page in logical coordinates. You may want to refer to this in your override of CView::OnPrint. You can use this member to keep track of what area remains usable after you print headers, footers, etc. The m_rectDraw member is a public variable of type CRect.

See Also

»CView::OnPrint«


  CPrintInfo::m_strPageDesc

Remarks

Contains a format string used to display the page numbers during print preview; this string consists of two substrings, one for single-page display and one for double-page display, each terminated by a '\n' character. The framework uses "Page %u\nPages %u-%u\n" as the default value. If you want a different format for the page numbers, specify a format string in your override of CView::OnPreparePrinting. The m_strPageDesc member is a public variable of type CString.

See Also

»CView::OnPreparePrinting«


CPtrArray
  class CPtrArray : public CObject

The CPtrArray class supports arrays of void pointers.

The member functions of CPtrArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a pointer to void.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

void* CPtrArray::GetAt( int <nIndex> ) const;

CPtrArray incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual pointer array elements, you must set the depth of the dump context to 1 or greater.

Pointer arrays may not be serialized.

When a pointer array is deleted, or when its elements are removed, only the pointers are removed, not the entities they reference.

#include <afxcoll.h>


CPtrArray Class Members
  Class Members

Construction/Destruction — Public Members

»CPtrArray«	Constructs an empty array for void pointers.
»~CPtrArray«	Destroys a CPtrArray object.
Bounds — Public Members

»GetSize«	Gets number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array is not allowed to grow.
»ElementAt«	Returns a temporary reference to the element pointer within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CPtrList
  class CPtrList : public CObject

The CPtrList class supports lists of void pointers.

The member functions of CPtrList are similar to the member functions of class »CObList«. Because of this similarity, you can use the CObList reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a pointer to void.

CObject*& CObList::GetHead() const;

for example, translates to

void*& CPtrList::GetHead() const;

CPtrList incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual pointer list elements, you must set the depth of the dump context to 1 or greater.

Pointer lists may not be serialized.

When a CPtrList object is deleted, or when its elements are removed, only the pointers are removed, not the entities they reference.

#include <afxcoll.h>


CPtrList Class Members
  Class Members

Construction/Destruction — Public Members

»CPtrList«	Constructs an empty list for void pointers.
Head/Tail Access — Public Members

»GetHead«	Returns the head element of the list (cannot be empty).
»GetTail«	Returns the tail element of the list (cannot be empty).
Operations — Public Members

»RemoveHead«	Removes the element from the head of the list.
»RemoveTail«	Removes the element from the tail of the list.
»AddHead«	Adds an element (or all the elements in another list) to the head of the list (makes a new head).
»AddTail«	Adds an element (or all the elements in another list) to the tail of the list (makes a new tail).
»RemoveAll«	Removes all the elements from this list.
Iteration — Public Members

»GetHeadPosition«	Returns the position of the head element of the list.
»GetTailPosition«	Returns the position of the tail element of the list.
»GetNext«	Gets the next element for iterating.
»GetPrev«	Gets the previous element for iterating.
Retrieval/Modification — Public Members

»GetAt«	Gets the element at a given position.
»SetAt«	Sets the element at a given position.
»RemoveAt«	Removes an element from this list, specified by position.
Insertion — Public Members

»InsertBefore«	Inserts a new element before a given position.
»InsertAfter«	Inserts a new element after a given position.
Searching — Public Members

»Find«	Gets the position of an element specified by pointer value.
»FindIndex«	Gets the position of an element specified by a zero-based index.
Status — Public Members

»GetCount«	Returns the number of elements in this list.
»IsEmpty«	Tests for the empty list condition (no elements).


CRect
  class CRect : public tagRECT

The CRect class is similar to a Windows RECT structure and also includes member functions to manipulate CRect objects and Windows RECT structures.

A CRect object can be passed as a function parameter wherever an LPRECT or RECT structure can be passed.

A CRect contains member variables that define the top-left and bottom-right points of a rectangle. The width or height of the rectangle defined by CRect must not exceed 32,767 units.

When specifying a CRect, you must be careful to construct it so that the top-left point is above and to the left of the bottom-right point in the Windows coordinate system; otherwise, the CRect will not be recognized by some functions, such as IntersectRect, UnionRect, and PtInRect. For example, a top left of (10,10) and bottom right of (20,20) defines a valid rectangle; a top left of (20,20) and bottom right of (10,10), an empty rectangle.

Use caution when manipulating a CRect with the CDC::DPtoLP and CDC::LPtoDP member functions. If the mapping mode of a display context is such that the y-extent is negative, as in MM_LOENGLISH, then CDC::DPtoLP will transform the CRect so that its top is greater than the bottom. Functions such as Height and Size will then return negative values for the height of the transformed CRect.

When using overloaded CRect operators, the first operator must be a CRect; the second can be either a »RECT« structure or a CRect object.

#include <afxwin.h>

RECT Structure

The RECT data structure looks like this:

typedef struct tagRECT {
   int left;
   int top;
   int right;
   int bottom;
} RECT;

The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.

Members

left    Specifies the x-coordinate of the upper-left corner of a rectangle.

top    Specifies the y-coordinate of the upper-left corner of a rectangle.

right    Specifies the x-coordinate of the lower-right corner of a rectangle.

bottom    Specifies the y-coordinate of the lower-right corner of a rectangle.

See Also

»CPoint«, »CSize«


CRect Class Members
  Class Members

Construction/Destruction — Public Members

»CRect«	Constructs a CRect object.
Operations — Public Members

»Width«	Calculates the width of CRect.
»Height«	Calculates the height of CRect.
»Size«	Calculates the size of CRect.
»TopLeft«	Returns a reference to the top-left point of CRect.
»BottomRight«	Returns a reference to the bottom-right point of CRect.
»IsRectEmpty«	Determines whether CRect is empty. CRect is empty if the width and/or height are 0.
»IsRectNull«	Determines if the top, bottom, left, and right member variables are all equal to 0.
»PtInRect«	Determines whether the specified point lies within CRect.
»SetRect«	Sets the dimensions of CRect.
»SetRectEmpty«	Sets CRect to an empty rectangle (all coordinates equal to 0).
»CopyRect«	Copies the dimensions of a source rectangle to CRect.
»EqualRect«	Determines whether CRect is equal to the given rectangle.
»InflateRect«	Increases or decreases the width and height of CRect.
»OffsetRect«	Moves CRect by the specified offsets.
»SubtractRect«	Subtracts one rectangle from another.
»IntersectRect«	Sets CRect equal to the intersection of two rectangles.
»UnionRect«	Sets CRect equal to the union of two rectangles.
Operators — Public Members

»operator LPCRECT«	Converts a CRect to an LPCRECT.
»operator LPRECT«	Converts a CRect to an LPRECT.
»operator =«	Copies the dimensions of a rectangle to CRect.
»operator ==«	Determines whether CRect is equal to a rectangle.
»operator !=«	Determines whether CRect is not equal to a rectangle.
»operator +=«	Adds the specified offsets to CRect.
»operator −=«	Subtracts the specified offsets from CRect.
»operator &=«	Sets CRect equal to the intersection of CRect and a rectangle.
»operator |=«	Sets CRect equal to the union of CRect and a rectangle.
»operator +«	Adds the given offsets to CRect and returns the resulting CRect.
»operator −«	Subtracts the given offsets from CRect and returns the resulting CRect.
»operator &«	Creates the intersection of CRect and a rectangle and returns the resulting CRect.
»operator |«	Creates the union of CRect and a rectangle and returns the resulting CRect.


CRect Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CRect::BottomRight

CPoint& BottomRight();

Remarks

Returns a reference to the bottom-right point of CRect.

Return Value

CPOINT&, a reference to a CPoint object.


  CRect::CopyRect

void CopyRect( LPCRECT lpSrcRect );

lpSrcRect    Points to the RECT structure or CRect object whose dimensions are to be copied.

Remarks

Copies the lpSrcRect rectangle to the CRect object.

See Also

::CopyRect »CRect::operator =«


  CRect::CRect

CRect();

CRect( int l, int t, int r, int b );

CRect( const RECT& srcRect );

CRect( LPCRECT lpSrcRect );

CRect( POINT point, SIZE size );

l    Specifies the left position of the CRect.

t    Specifies the top of the CRect.

r    Specifies the right position of the CRect.

b    Specifies the bottom of the CRect.

srcRect    Refers to the RECT structure with the coordinates for the CRect object.

lpSrcRect    Points to the RECT structure with the coordinates for the CRect object.

point    Specifies the origin point for the rectangle to be constructed. Corresponds to the top-left corner.

size    Specifies the displacement from the top-left corner to the bottom-right corner of the rectangle to be constructed.

Remarks

Constructs a CRect object.

The CRect( const RECT& ) and CRect( LPCRECT ) constructors perform a CopyRect. The other constructors initialize the member variables of the object directly.

See Also

»CRect::SetRect«, »CRect::CopyRect«, »CRect::operator =«


  CRect::EqualRect

BOOL EqualRect( LPCRECT lpRect ) const;

lpRect    Points to a RECT structure or CRect object that contains the upper-left and lower-right corner coordinates of a rectangle.

Return Value

Nonzero if the two rectangles have the same top, left, bottom, and right values; otherwise 0.

See Also

::EqualRect


  CRect::Height

int Height() const;

Remarks

Calculates the height of CRect by subtracting the top value from the bottom value. The resulting value may be negative.

Return Value

The height of CRect.


  CRect::InflateRect

void InflateRect( int x, int y );

void InflateRect( SIZE size );

x    Specifies the amount to increase or decrease the width of CRect. It must be negative to decrease the width.

y    Specifies the amount to increase or decrease the height of CRect. It must be negative to decrease the height.

size    Contains a SIZE or CSize that specifies the amounts to add to the CRect's height and width.

Remarks

The parameters of InflateRect are signed values; positive values inflate the CRect and negative values deflate it.

When inflated, the width of CRect is increased by two times x and its height is increased by two times y.

See Also

::InflateRect


  CRect::IntersectRect

BOOL IntersectRect( LPCRECT lpRect1, LPCRECT lpRect2 );

lpRect1    Points to a RECT structure or CRect object that contains a source rectangle.

lpRect2    Points to a RECT structure or CRect object that contains a source rectangle.

Remarks

Makes a CRect equal to the intersection of two existing rectangles. The intersection is the largest rectangle contained in both existing rectangles.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both lpRect1 and lpRect2.

Return Value

Nonzero if the intersection is not empty; 0 if the intersection is empty.

See Also

::IntersectRect, »CRect::operator &=«, »CRect::operator &«


  CRect::IsRectEmpty

BOOL IsRectEmpty() const;

Remarks

Determines if CRect is empty. A rectangle is empty if the width and/or height are 0 or negative. Differs from IsRectNull, which determines if the rectangle is NULL.

Return Value

Nonzero if CRect is empty; 0 if CRect is not empty.

See Also

::IsRectEmpty, »CRect::IsRectNull«


  CRect::IsRectNull

BOOL IsRectNull() const;

Remarks

Determines if the top, left, bottom, and right values of the CRect are all equal to 0. Differs from IsRectEmpty, which determines if the rectangle is empty.

Return Value

Nonzero if the CRect object's top, left, bottom, and right values are all equal to 0; otherwise 0.

See Also

»CRect::IsRectEmpty«


  CRect::OffsetRect

void OffsetRect( int x, int y );

void OffsetRect( POINT point );

void OffsetRect( SIZE size );

x    Specifies the amount to move left or right. It must be negative to move left.

y    Specifies the amount to move up or down. It must be negative to move up.

point    Contains a POINT or CPoint specifying both dimensions by which to move.

size    Contains a SIZE or CSize specifying both dimensions by which to move.

Remarks

Moves CRect by the specified offsets. Moves CRect x units along the x-axis and y units along the y-axis. The x and y parameters are signed values, so CRect can be moved left or right and up or down.


  CRect::PtInRect

BOOL PtInRect( POINT point ) const;

point    Contains a POINT structure or CPoint object.

Remarks

Determines whether the specified point lies within CRect. A point is within CRect if it lies on the left or top side or is within all four sides. A point on the right or bottom side is outside CRect.

Note  The value of the left coordinate of CRect must be less than the right and the top less than the bottom.

Return Value

Nonzero if the point lies within CRect; otherwise 0.

See Also

::PtInRect


  CRect::SetRect

void SetRect( int x1, int y1, int x2, int y2 );

x1    Specifies the x-coordinate of the upper-left corner.

y1    Specifies the y-coordinate of the upper-left corner.

x2    Specifies the x-coordinate of the lower-right corner.

y2    Specifies the y-coordinate of the lower-right corner.

Remarks

Sets the dimensions of CRect to the specified coordinates.

See Also

»CRect::CRect«, »CRect::SetRectEmpty«, ::SetRect


  CRect::SetRectEmpty

void SetRectEmpty();

Remarks

Creates a NULL rectangle (all coordinates equal to 0).

See Also

::SetRectEmpty


  CRect::Size

CSize Size() const;

Return Value

The CRect width and height encapsulated as the cx and cy member variables of a CSize object.


  CRect::SubtractRect

Windows 3.1 Only

BOOL SubtractRect( LPCRECT lpRectSrc1, LPCRECT lpRectSrc2 ); ♦

lpRectSrc1    Points to the RECT structure from which a rectangle is to be subtracted.

lpRectSrc2    Points to the RECT structure that is to be subtracted from the rectangle pointed to by the lpRectSrc1 parameter.

Remarks

Makes the dimensions of a CRect object equal to the subtraction of lpRectSrc2 from lpRectSrc1.

The rectangle specified by lpRectSrc2 is subtracted from the rectangle specified by lpRectSrc1 only when the rectangles intersect completely in either the x- or y-direction.

For example, if lpRectSrc1 were (10,10, 100,100) and lpRectSrc2 were (50,50, 150,150), the rectangle pointed to by lpRectSrc1 would contain the same coordinates as the original lpRectSrc1 when the function returned. If lpRectSrc1 were (10,10, 100,100) and lpRectSrc2 were (50,10, 150,150), however, the rectangle pointed to by lpRectSrc1 would contain the coordinates (10,10, 50,100) when the function returned.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CRect::IntersectRect«, ::UnionRect


  CRect::TopLeft

CPoint& TopLeft();

Return Value

A reference to the top-left point of CRect.


  CRect::UnionRect

BOOL UnionRect( LPCRECT lpRect1, LPCRECT lpRect2 );

lpRect1    Points to a RECT or CRect that contains a source rectangle.

lpRect2    Points to a RECT or CRect that contains a source rectangle.

Remarks

Makes the dimensions of CRect equal to the union of the two source rectangles. The union is the smallest rectangle that contains both source rectangles.

Windows ignores the dimensions of an empty rectangle; that is, a rectangle that has no height or has no width.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both lpRect1 and lpRect2.

Return Value

Nonzero if the union is not empty; 0 if the union is empty.

See Also

»::UnionRect« »CRect::operator |=«, »CRect::operator |«


  CRect::Width

int Width() const;

Remarks

Calculates the width of CRect by subtracting the left value from the right value. The width may be negative.

Return Value

The width of CRect.


CRect Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CRect::operator LPCRECT

operator LPCRECT() const;

Remarks

Converts a CRect to an LPCRECT with no need for the address-of (&) operator.


  CRect::operator LPRECT

operator LPRECT();

Remarks

Converts a CRect defined as a constant to an LPRECT with no need for the address-of (&) operator.


  CRect::operator =

void operator =( const RECT& srcRect );

srcRect    Refers to a source rectangle. May be a RECT or CRect.

Remarks

Copies the dimensions of srcRect to CRect.

See Also

»CRect::SetRect«,  ::CopyRect


  CRect::operator ==

BOOL operator ==( const RECT& rect ) const;

rect    Refers to a source rectangle. May be a RECT or CRect.

Remarks

Determines if rect is equal to CRect by comparing the coordinates of their upper-left and lower-right corners.

Return Value

If the values of these coordinates are equal, returns nonzero; otherwise 0.

See Also

 ::EqualRect


  CRect::operator !=

BOOL operator !=( const RECT& rect ) const;

rect    Refers to a source rectangle. May be a RECT or CRect.

Remarks

Determines if rect is not equal to CRect by comparing the coordinates of their upper-left and lower-right corners.

Return Value

Nonzero if not equal; otherwise 0.

See Also

»CRect::operator ==«


  CRect::operator +=

void operator +=( POINT point );

point    Contains a POINT or CPoint.

Remarks

Moves CRect by the specified offsets. The point parameter's x and y parameters are added to CRect.

See Also

»CRect::OffsetRect«


CRect::operator-=
  CRect::operator −=

void operator −=( POINT point );

point    Contains a POINT or CPoint.

Remarks

Moves CRect by the specified offsets. The point parameter's x and y parameters are subtracted from CRect.

See Also

»CRect::OffsetRect«


  CRect::operator &=

void operator &=( const RECT& rect );

rect    Contains a RECT or CRect.

Remarks

Sets CRect equal to the intersection of CRect and rect. The intersection is the largest rectangle contained in both rectangles.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both CRect and rect.

See Also

»CRect::IntersectRect«


  CRect::operator |=

void operator |=( const RECT& rect );

rect    Contains a CRect or RECT.

Remarks

Sets CRect equal to the union of CRect and rect. The union is the smallest rectangle that contains both source rectangles.

Windows ignores the dimensions of an empty rectangle; that is, a rectangle that has no height or has no width.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both CRect and rect.

See Also

»CRect::UnionRect«


  CRect::operator +

CRect operator +( POINT point ) const;

point    Contains a POINT or CPoint.

Remarks

Returns a new CRect that is equal to CRect displaced by point. The point parameter's x and y parameters are added to CRect's position.

Return Value

The CRect resulting from the offset by point.

See Also

»CRect::OffsetRect«


CRect::operator -
  CRect::operator −

CRect operator −( POINT point ) const;

point    Contains a POINT or CPoint.

Remarks

A new CRect that is equal to CRect displaced by −point. The point parameter's x and y parameters are subtracted from CRect's dimensions.

Return Value

The CRect resulting from the offset by point.

See Also

»CRect::OffsetRect«


  CRect::operator &

CRect operator &( const RECT& rect2 ) const;

rect2    Contains a RECT or CRect.

Return Value

A CRect that is the intersection of CRect and rect2. The intersection is the largest rectangle contained in both rectangles.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both CRect and rect2.

See Also

»CRect::IntersectRect«


  CRect::operator |

CRect operator |( const RECT& rect2 ) const;

rect2    Contains a RECT or CRect.

Return Value

A CRect that is the union of CRect and rect2. A union is the smallest rectangle that contains both source rectangles.

Windows ignores the dimensions of an empty rectangle; that is, a rectangle that has no height or has no width.

Note  The value of the left coordinate must be less than the right and the top less than the bottom for both CRect and rect2.

See Also

»CRect::UnionRect«


CResourceException
  class CResourceException : public CException

A CResourceException object is generated when Windows cannot find or allocate a requested resource. No further qualification is necessary or possible.

#include <afxwin.h>


CResourceException Class Members
  Class Members

Construction/Destruction — Public Members

»CResourceException«	Constructs a CResourceException object.


CResourceException Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CResourceException::CResourceException

CResourceException();

Remarks

Constructs a CResourceException object.

Do not use this constructor directly, but rather call the global function »AfxThrowResourceException«. For more information about exceptions, see Chapter 16, "Exceptions," in the Class Library User's Guide.

See Also

»AfxThrowResourceException«

»Exception Processing«


CRgn
  class CRgn : public CGdiObject

The CRgn class encapsulates a Windows graphics device interface (GDI) region. A region is an elliptical or polygonal area within a window. To use regions, you use the member functions of class CRgn with the clipping functions defined as members of class CDC.

The member functions of CRgn create, alter, and retrieve information about the region object for which they are called.

#include <afxwin.h>


CRgn Class Members
  Class Members

Construction/Destruction — Public Members

»CRgn«	Constructs a CRgn object.
Initialization — Public Members

»CreateRectRgn«	Initializes a CRgn object with a rectangular region.
»CreateRectRgnIndirect«	Initializes a CRgn object with a rectangular region defined by a RECTstructure.
»CreateEllipticRgn«	Initializes a CRgn object with an elliptical region.
»CreateEllipticRgnIndirect«	Initializes a CRgn object with an elliptical region defined by a RECTstructure.
»CreatePolygonRgn«	Initializes a CRgn object with a polygonal region. The system closes the polygon automatically, if necessary, by drawing a line from the last vertex to the first.
»CreatePolyPolygonRgn«	Initializes a CRgn object with a region consisting of a series of closed polygons. The polygons may be disjoint or they may overlap.
»CreateRoundRectRgn«	Initializes a CRgn object with a rectangular region with rounded corners.
»CombineRgn«	Sets a CRgn object so that it is equivalent to the union of two specified CRgn objects.
»CopyRgn«	Sets a CRgn object so that it is a copy of a specified CRgn object.
Operations — Public Members

»EqualRgn«	Checks two CRgn objects to determine whether they are equivalent.
»FromHandle«	Returns a pointer to a CRgn object when given a handle to a Windows region.
»GetRgnBox«	Retrieves the coordinates of the bounding rectangle of a CRgn object.
»OffsetRgn«	Moves a CRgn object by the specified offsets.
»PtInRegion«	Determines whether a specified point is in the region.
»RectInRegion«	Determines whether any part of a specified rectangle is within the boundaries of the region.
»SetRectRgn«	Sets the CRgn object to the specified rectangular region.


CRgn Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CRgn::CombineRgn

int CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nCombineMode );

pRgn1    Identifies an existing region.

pRgn2    Identifies an existing region.

nCombineMode    Specifies the operation to be performed when combining the two source regions. It can be any one of the following values:

•	RGN_AND    Uses overlapping areas of both regions (intersection).

•	RGN_COPY    Creates a copy of region 1 (identified by pRgn1).

•	RGN_DIFF    Creates a region consisting of the areas of region 1 (identified by pRgn1) that are not part of region 2 (identified by pRgn2).

•	RGN_OR    Combines both regions in their entirety (union).

•	RGN_XOR    Combines both regions but removes overlapping areas.

Remarks

Creates a new GDI region by combining two existing regions. The regions are combined as specified by nCombineMode.

The two specified regions are combined, and the resulting region handle is stored in the CRgn object. Thus, whatever region is stored in the CRgn object is replaced by the combined region.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

Use »CopyRgn« to simply copy one region into another region.

Return Value

Specifies the type of the resulting region. It can be one of the following values:

•	COMPLEXREGION    New region has overlapping borders.

•	ERROR    No new region created.

•	NULLREGION    New region is empty.

•	SIMPLEREGION    New region has no overlapping borders.

See Also

»CRgn::CopyRgn«, ::CombineRgn


  CRgn::CopyRgn

int CopyRgn( CRgn* pRgnSrc );

pRgnSrc    Identifies an existing region.

Remarks

Copies the region defined by pRgnSrc into the CRgn object. The new region replaces the region formerly stored in the CRgn object. This function is a special case of the »CombineRgn« member function.

Return Value

Specifies the type of the resulting region. It can be one of the following values:

•	COMPLEXREGION    New region has overlapping borders.

•	ERROR    No new region created.

•	NULLREGION    New region is empty.

•	SIMPLEREGION    New region has no overlapping borders.

See Also

»CRgn::CombineRgn«, ::CombineRgn


  CRgn::CreateEllipticRgn

BOOL CreateEllipticRgn( int x1, int y1, int x2, int y2 );

x1    Specifies the logical x-coordinate of the upper-left corner of the bounding rectangle of the ellipse.

y1    Specifies the logical y-coordinate of the upper-left corner of the bounding rectangle of the ellipse.

x2    Specifies the logical x-coordinate of the lower-right corner of the bounding rectangle of the ellipse.

y2    Specifies the logical y-coordinate of the lower-right corner of the bounding rectangle of the ellipse.

Remarks

Creates an elliptical region. The region is defined by the bounding rectangle specified by x1, y1, x2, and y2. The region is stored in the CRgn object.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

When it has finished using a region created with the CreateEllipticRgn function, an application should select the region out of the device context and use the DeleteObject function to remove it.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreateEllipticRgnIndirect«, ::CreateEllipticRgn


  CRgn::CreateEllipticRgnIndirect

BOOL CreateEllipticRgnIndirect( LPCRECT lpRect );

lpRect    Points to a RECT structure or a CRect object that contains the logical coordinates of the upper-left and lower-right corners of the bounding rectangle of the ellipse.

Remarks

Creates an elliptical region. The region is defined by the structure or object pointed to by lpRect and is stored in the CRgn object.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

When it has finished using a region created with the CreateEllipticRgnIndirect function, an application should select the region out of the device context and use the DeleteObject function to remove it.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreateEllipticRgn«, ::CreateEllipticRgnIndirect


  CRgn::CreatePolygonRgn

BOOL CreatePolygonRgn( LPPOINT lpPoints, int nCount, int nMode );

lpPoints    Points to an array of POINT structures or an array of CPoint objects. Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon. The POINT structure has the following form:

typedef struct tagPOINT {
   int x;
   int y;
} POINT;

nCount    Specifies the number of POINT structures or CPoint objects in the array pointed to by lpPoints.

nMode    Specifies the filling mode for the region. This parameter may be either ALTERNATE or WINDING.

Remarks

Creates a polygonal region. The system closes the polygon automatically, if necessary, by drawing a line from the last vertex to the first. The resulting region is stored in the CRgn object.

The size of a region is limited to 32,767, by 32,767, logical units or 64K of memory, whichever is smaller.

When the polygon-filling mode is ALTERNATE, the system fills the area between odd-numbered and even-numbered polygon sides on each scan line. That is, the system fills the area between the first and second side, between the third and fourth side, and so on.

When the polygon-filling mode is WINDING, the system uses the direction in which a figure was drawn to determine whether to fill an area. Each line segment in a polygon is drawn in either a clockwise or a counterclockwise direction. Whenever an imaginary line drawn from an enclosed area to the outside of a figure passes through a clockwise line segment, a count is incremented. When the line passes through a counterclockwise line segment, the count is decremented. The area is filled if the count is nonzero when the line reaches the outside of the figure.

When an application has finished using a region created with the CreatePolygonRgn function, it should select the region out of the device context and use the DeleteObject function to remove it.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreatePolyPolygonRgn«, ::CreatePolygonRgn


  CRgn::CreatePolyPolygonRgn

BOOL CreatePolyPolygonRgn( LPPOINT lpPoints, LPINT lpPolyCounts,
int nCount, int nPolyFillMode );

lpPoints    Points to an array of POINT structures or an array of CPoint objects that defines the vertices of the polygons. Each polygon must be explicitly closed because the system does not close them automatically. The polygons are specified consecutively. The POINT structure has the following form:

typedef struct tagPOINT {
   int x;
   int y;
} POINT;

lpPolyCounts    Points to an array of integers. The first integer specifies the number of vertices in the first polygon in the lpPoints array, the second integer specifies the number of vertices in the second polygon, and so on.

nCount    Specifies the total number of integers in the lpPolyCounts array.

nPolyFillMode    Specifies the polygon-filling mode. This value may be either ALTERNATE or WINDING.

Remarks

Creates a region consisting of a series of closed polygons. The resulting region is stored in the CRgn object.

The polygons may be disjoint or they may overlap.

The size of a region is limited to 32,767, by 32,767 logical units or 64K of memory, whichever is smaller.

When the polygon-filling mode is ALTERNATE, the system fills the area between odd-numbered and even-numbered polygon sides on each scan line. That is, the system fills the area between the first and second side, between the third and fourth side, and so on.

When the polygon-filling mode is WINDING, the system uses the direction in which a figure was drawn to determine whether to fill an area. Each line segment in a polygon is drawn in either a clockwise or a counterclockwise direction. Whenever an imaginary line drawn from an enclosed area to the outside of a figure passes through a clockwise line segment, a count is incremented. When the line passes through a counterclockwise line segment, the count is decremented. The area is filled if the count is nonzero when the line reaches the outside of the figure.

When an application has finished using a region created with the CreatePolyPolygonRgn function, it should select the region out of the device context and use the DeleteObject function to remove it.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreatePolygonRgn«, »CDC::SetPolyFillMode«, ::CreatePolyPolygonRgn


  CRgn::CreateRectRgn

BOOL CreateRectRgn( int x1, int y1, int x2, int y2 );

x1    Specifies the logical x-coordinate of the upper-left corner of the region.

y1    Specifies the logical y-coordinate of the upper-left corner of the region.

x2    Specifies the logical x-coordinate of the lower-right corner of the region.

y2    Specifies the logical y-coordinate of the lower-right corner of the region.

Remarks

Creates a rectangular region that is stored in the CRgn object.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

When it has finished using a region created by CreateRectRgn, an application should use the DeleteObject function to remove the region.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreateRectRgnIndirect«, »CRgn::CreateRoundRectRgn«, ::CreateRectRgn


  CRgn::CreateRectRgnIndirect

BOOL CreateRectRgnIndirect( LPCRECT lpRect );

lpRect    Points to a RECT structure or CRect object that contains the logical coordinates of the upper-left and lower-right corners of the region. The RECT structure has the following form:

typedef struct tagRECT {
   int left;
   int top;
   int right;
   int bottom;
} RECT;

Remarks

Creates a rectangular region that is stored in the CRgn object.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

When it has finished using a region created by CreateRectRgnIndirect, an application should use the DeleteObject function to remove the region.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreateRectRgn«, »CRgn::CreateRoundRectRgn«, ::CreateRectRgnIndirect


  CRgn::CreateRoundRectRgn

BOOL CreateRoundRectRgn( int x1, int y1, int x2, int y2, int x3, int y3 );

x1    Specifies the logical x-coordinate of the upper-left corner of the region.

y1    Specifies the logical y-coordinate of the upper-left corner of the region.

x2    Specifies the logical x-coordinate of the lower-right corner of the region.

y2    Specifies the logical y-coordinate of the lower-right corner of the region.

x3    Specifies the width of the ellipse used to create the rounded corners.

y3    Specifies the height of the ellipse used to create the rounded corners.

Remarks

Creates a rectangular region with rounded corners that is stored in the CRgn object.

The size of a region is limited to 32,767 by 32,767 logical units or 64K of memory, whichever is smaller.

When an application has finished using a region created with the CreateRoundRectRgn function, it should select the region out of the device context and use the DeleteObject function to remove it.

Return Value

Nonzero if the operation succeeded; otherwise 0.

See Also

»CRgn::CreateRectRgn«, »CRgn::CreateRectRgnIndirect«, ::CreateRoundRectRgn


  CRgn::CRgn

CRgn();

Remarks

Constructs a CRgn object. The m_hObject data member does not contain a valid Windows GDI region until the object is initialized with one or more of the other CRgn member functions.


  CRgn::EqualRgn

BOOL EqualRgn( CRgn* pRgn ) const;

pRgn    Identifies a region.

Remarks

Determines whether the given region is equivalent to the region stored in the CRgn object.

Return Value

Nonzero if the two regions are equivalent; otherwise 0.

See Also

::EqualRgn


  CRgn::FromHandle

static CRgn* PASCAL FromHandle( HRGN hRgn );

hRgn    Specifies a handle to a Windows region.

Remarks

Returns a pointer to a CRgn object when given a handle to a Windows region. If a CRgn object is not already attached to the handle, a temporary CRgn object is created and attached. This temporary CRgn object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.

Return Value

A pointer to a CRgn object. If the function was not successful, the return value is NULL.


  CRgn::GetRgnBox

int GetRgnBox( LPRECT lpRect ) const;

lpRect    Points to a RECT structure or CRect object to receive the coordinates of the bounding rectangle. The RECT structure has the following form:

typedef struct tagRECT {
   int left;
   int top;
   int right;
   int bottom;
} RECT;

Remarks

Retrieves the coordinates of the bounding rectangle of the CRgn object.

Return Value

Specifies the region's type. It can be any of the following values:

•	COMPLEXREGION     Region has overlapping borders.

•	NULLREGION    Region is empty.

•	ERROR    CRgn object does not specify a valid region.

•	SIMPLEREGION     Region has no overlapping borders.

See Also

::GetRgnBox


  CRgn::OffsetRgn

int OffsetRgn( int x, int y );

int OffsetRgn( POINT point );

x    Specifies the number of units to move left or right.

y    Specifies the number of units to move up or down.

point    The x-coordinate of point specifies the number of units to move left or right. The y-coordinate of point specifies the number of units to move up or down. The point parameter may be either a POINT structure or a CPoint object.

Remarks

Moves the region stored in the CRgn object by the specified offsets. The function moves the region x units along the x-axis and y units along the y-axis.

The coordinate values of a region must be less than or equal to 32,767 and greater than or equal to −32,768. The x and y parameters must be carefully chosen to prevent invalid region coordinates.

Return Value

The new region's type. It can be any one of the following values:

•	COMPLEXREGION    Region has overlapping borders.

•	ERROR    Region handle is not valid.

•	NULLREGION    Region is empty.

•	SIMPLEREGION    Region has no overlapping borders.

See Also

::OffsetRgn


  CRgn::PtInRegion

BOOL PtInRegion( int x, int y ) const;

BOOL PtInRegion( POINT point ) const;

x    Specifies the logical x-coordinate of the point to test.

y    Specifies the logical y-coordinate of the point to test.

point    The x- and y-coordinates of point specify the x- and y-coordinates of the point to test the value of. The point parameter can either be a POINT structure or a CPoint object.

Remarks

Checks whether the point given by x and y is in the region stored in the CRgn object.

Return Value

Nonzero if the point is in the region; otherwise 0.

See Also

::PtInRegion


  CRgn::RectInRegion

BOOL RectInRegion( LPCRECT lpRect ) const;

lpRect    Points to a RECT structure or CRect object. The RECT structure has the following form:

typedef struct tagRECT {
   int left;
   int top;
   int right;
   int bottom;
} RECT;

Remarks

Determines whether any part of the rectangle specified by lpRect is within the boundaries of the region stored in the CRgn object.

Return Value

Nonzero if any part of the specified rectangle lies within the boundaries of the region; otherwise 0.

See Also

::RectInRegion


  CRgn::SetRectRgn

void SetRectRgn( int x1, int y1, int x2, int y2 );

void SetRectRgn( LPCRECT lpRect );

x1    Specifies the x-coordinate of the upper-left corner of the rectangular region.

y1    Specifies the y-coordinate of the upper-left corner of the rectangular region.

x2    Specifies the x-coordinate of the lower-right corner of the rectangular region.

y2    Specifies the y-coordinate of the lower-right corner of the rectangular region.

lpRect    Specifies the rectangular region. Can be either a pointer to a RECT structure or a CRect object.

Remarks

Creates a rectangular region. Unlike »CreateRectRgn«, however, it does not allocate any additional memory from the local Windows application heap. Instead, it uses the space allocated for the region stored in the CRgn object. This means that the CRgn object must already have been initialized with a valid Windows region before calling SetRectRgn. The points given by x1, y1, x2, and y2 specify the minimum size of the allocated space.

Use this function instead of the CreateRectRgn member function to avoid calls to the local memory manager.

See Also

»CRgn::CreateRectRgn«, ::SetRectRgn


CRuntimeClass
struct CRuntimeClass

Each class derived from CObject is associated with a CRuntimeClass structure that you can use to obtain information about an object or its base class at run time. The ability to determine the class of an object at run time is useful when extra type checking of function arguments is needed, or when you must write special-purpose code based on the class of an object. Run-time class information is not supported directly by the C++ language.

The structure has the following members:

LPCSTR m_lpszClassName

A null-terminated string containing the ASCII class name.

int m_nObjectSize

that point to allocated memory, the size of that memory is not included.

The size of the object, in bytes. If the object has data members that point to allocated memory, the size of that memory is not included.

WORD m_wSchema

The schema number ( − 1 for nonserializable classes). See the IMPLEMENT_SERIAL macro for a description of the schema number.

void (*m_pfnConstruct)(void* p)

A pointer to the default constructor of your class (valid only if the class supports dynamic creation).

CRuntimeClass* m_pBaseClass

A pointer to the CRuntimeClass structure that corresponds to the base class.

CObject* CreateObject();

Classes derived from CObject can support dynamic creation, which is the ability to create an object of a specified class at run time. Document, view, and frame classes, for example, should support dynamic creation. The CreateObject member function can be used to implement this function and create objects for these classes during run time. For more information on dynamic creation and the CreateObject member, see Chapter 12 of the Class Library User's Guide.

Note  To use the CRuntimeClass structure, you must include the IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE or IMPLEMENT_SERIAL macro in the implementation of the class for which you want to retrieve run-time object information.

See Also

»CObject::GetRuntimeClass«, »CObject::IsKindOf«, »RUNTIME_CLASS«, »IMPLEMENT_DYNAMIC«, »IMPLEMENT_DYNCREATE«, »IMPLEMENT_SERIAL«


CScrollBar
  class CScrollBar : public CWnd

The CScrollBar class provides the functionality of a Windows scroll-bar control.

You create a scroll-bar control in two steps. First, call the constructor CScrollBar to construct the CScrollBar object, then call the »Create« member function to create the Windows scroll-bar control and attach it to the CScrollBar object.

If you create a CScrollBar object within a dialog box (through a dialog resource), the CScrollBar is automatically destroyed when the user closes the dialog box.

If you create a CScrollBar object within a window, you may also need to destroy it.

If you create the CScrollBar object on the stack, it is destroyed automatically. If you create the CScrollBar object on the heap by using the new function, you must call delete on the object to destroy it when the user terminates the Windows scroll bar.

If you allocate any memory in the CScrollBar object, override the CScrollBar destructor to dispose of the allocations.

#include <afxwin.h>

See Also

»CWnd«, »CButton«, »CComboBox«, »CEdit«, »CListBox«, »CStatic«, »CDialog«


CScrollBar Class Members
  Class Members

Construction/Destruction — Public Members

»CScrollBar«	Constructs a CScrollBar object.
Initialization — Public Members

»Create«	Creates the Windows scroll bar and attaches it to the CScrollBar object.
Operations — Public Members

»GetScrollPos«	Retrieves the current position of a scroll box.
»SetScrollPos«	Sets the current position of a scroll box.
»GetScrollRange«	Retrieves the current minimum and maximum scroll-bar positions for the given scroll bar.
»SetScrollRange«	Sets minimum and maximum position values for the given scroll bar.
»ShowScrollBar«	Shows or hides a scroll bar.
»EnableScrollBar«	Enables or disables one or both arrows of a scroll bar.


CScrollBar Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CScrollBar::Create

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle    Specifies the scroll bar's style.

rect    Specifies the scroll bar's size and position. Can be either a RECT structure or a CRect object.

pParentWnd    Specifies the scroll bar's parent window, usually a CDialog object. It must not be NULL.

nID    The scroll bar's control ID.

Remarks

You construct a CScrollBar object in two steps. First call the constructor, which constructs the CScrollBar object; then call Create, which creates and initializes the associated Windows scroll bar and attaches it to the CScrollBar object.

Apply the following »window styles« to a scroll bar:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

•	WS_GROUP    To group controls

Return Value

Nonzero if successful; otherwise 0.

Apply any combination of »scroll-bar styles« to the scroll bar.

Scroll-Bar Styles

You can use any combination of the following scroll-bar styles for dwStyle:

•	SBS_BOTTOMALIGN    Used with the SBS_HORZ style. The bottom edge of the scroll bar is aligned with the bottom edge of the rectangle specified in the Create member function. The scroll bar has the default height for system scroll bars.

•	SBS_HORZ    Designates a horizontal scroll bar. If neither the SBS_BOTTOMALIGN nor SBS_TOPALIGN style is specified, the scroll bar has the height, width, and position given in the Create member function.

•	SBS_LEFTALIGN    Used with the SBS_VERT style. The left edge of the scroll bar is aligned with the left edge of the rectangle specified in the Create member function. The scroll bar has the default width for system scroll bars.

•	SBS_RIGHTALIGN    Used with the SBS_VERT style. The right edge of the scroll bar is aligned with the right edge of the rectangle specified in the Create member function. The scroll bar has the default width for system scroll bars.

•	SBS_SIZEBOX    Designates a size box. If neither the SBS_SIZEBOXBOTTOMRIGHTALIGN nor SBS_SIZEBOXTOPLEFTALIGN style is specified, the size box has the height, width, and position given in the Create member function.

•	SBS_SIZEBOXBOTTOMRIGHTALIGN    Used with the SBS_SIZEBOX style. The lower-right corner of the size box is aligned with the lower-right corner of the rectangle specified in the Create member function. The size box has the default size for system size boxes.

•	SBS_SIZEBOXTOPLEFTALIGN    Used with the SBS_SIZEBOX style. The upper-left corner of the size box is aligned with the upper-left corner of the rectangle specified in the Create member function. The size box has the default size for system size boxes.

•	SBS_TOPALIGN    Used with the SBS_HORZ style. The top edge of the scroll bar is aligned with the top edge of the rectangle specified in the Create member function. The scroll bar has the default height for system scroll bars.

•	SBS_VERT    Designates a vertical scroll bar. If neither the SBS_RIGHTALIGN nor SBS_LEFTALIGN style is specified, the scroll bar has the height, width, and position given in the Create member function.

See Also

»CScrollBar::CScrollBar«


  CScrollBar::CScrollBar

CScrollBar();

Remarks

Constructs a CScrollBar object. After constructing the object, call the Create member function to create and initialize the Windows scroll bar.

See Also

»CScrollBar::Create«


  CScrollBar::EnableScrollBar

Windows 3.1 Only

BOOL EnableScrollBar( UINT nArrowFlags = ESB_ENABLE_BOTH ); »

nArrowFlags    Specifies whether the scroll arrows are enabled or disabled and which arrows are enabled or disabled. This parameter can be one of the following values:

•	ESB_ENABLE_BOTH    Enables both arrows of a scroll bar.

•	ESB_DISABLE_LTUP    Disables the left arrow of a horizontal scroll bar or the up arrow of a vertical scroll bar.

•	ESB_DISABLE_RTDN    Disables the right arrow of a horizontal scroll bar or the down arrow of a vertical scroll bar.

•	ESB_DISABLE_BOTH    Disables both arrows of a scroll bar.

Remarks

Enables or disables one or both arrows of a scroll bar.

Return Value

Nonzero if the arrows are enabled or disabled as specified; otherwise 0, which indicates that the arrows are already in the requested state or that an error occurred.

See Also

»CWnd::EnableScrollBar«, »::EnableScrollBar«


  CScrollBar::GetScrollPos

int GetScrollPos() const;

Remarks

Retrieves the current position of a scroll box. The current position is a relative value that depends on the current scrolling range. For example, if the scrolling range is 100 to 200 and the scroll box is in the middle of the bar, the current position is 150.

Return Value

Specifies the current position of the scroll box if successful; otherwise 0.

See Also

»CScrollBar::SetScrollPos«, »CScrollBar::GetScrollRange«, »CScrollBar::SetScrollRange«, »::GetScrollPos«


  CScrollBar::GetScrollRange

void GetScrollRange( LPINT lpMinPos, LPINT lpMaxPos ) const;

lpMinPos    Points to the integer variable that is to receive the minimum position.

lpMaxPos    Points to the integer variable that is to receive the maximum position.

Remarks

Copies the current minimum and maximum scroll-bar positions for the given scroll bar to the locations specified by lpMinPos and lpMaxPos.

The default range for a scroll-bar control is empty (both values are 0).

See Also

»::GetScrollRange«, »CScrollBar::SetScrollRange«, »CScrollBar::GetScrollPos«, »CScrollBar::SetScrollPos«


  CScrollBar::SetScrollPos

int SetScrollPos( int nPos, BOOL bRedraw = TRUE );

nPos    Specifies the new position for the scroll box. It must be within the scrolling range.

bRedraw    Specifies whether the scroll bar should be redrawn to reflect the new position. If bRedraw is TRUE, the scroll bar is redrawn. If it is FALSE, it is not redrawn. The scroll bar is redrawn by default.

Remarks

Sets the current position of a scroll box to that specified by nPos and, if specified, redraws the scroll bar to reflect the new position.

Set bRedraw to FALSE whenever the scroll bar will be redrawn by a subsequent call to another function to avoid having the scroll bar redrawn twice within a short interval.

Return Value

Specifies the previous position of the scroll box if successful; otherwise 0.

See Also

»CScrollBar::GetScrollPos«, »CScrollBar::GetScrollRange«, »CScrollBar::SetScrollRange«, »::SetScrollPos«


  CScrollBar::SetScrollRange

void SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw = TRUE );

nMinPos    Specifies the minimum scrolling position.

nMaxPos    Specifies the maximum scrolling position.

bRedraw    Specifies whether the scroll bar should be redrawn to reflect the change. If bRedraw is TRUE, the scroll bar is redrawn; if FALSE, it is not redrawn. It is redrawn by default.

Remarks

Sets minimum and maximum position values for the given scroll bar. Set nMinPos and nMaxPos to 0 to hide standard scroll bars.

Do not call this function to hide a scroll bar while processing a scroll-bar notification message.

If a call to SetScrollRange immediately follows a call to the SetScrollPos member function, set bRedraw in SetScrollPos to 0 to prevent the scroll bar from being redrawn twice.

The difference between the values specified by nMinPos and nMaxPos must not be greater than 32,767. The default range for a scroll-bar control is empty (both nMinPos and nMaxPos are 0).

See Also

»CScrollBar::GetScrollPos«, »CScrollBar::SetScrollPos«, »CScrollBar::GetScrollRange«, »::SetScrollRange«


  CScrollBar::ShowScrollBar

Windows 3.1 Only

void ShowScrollBar( BOOL bShow = TRUE ); »

bShow    Specifies whether the scroll bar is shown or hidden. If this parameter is TRUE, the scroll bar is shown; otherwise it is hidden.

Remarks

Shows or hides a scroll bar.

An application should not call this function to hide a scroll bar while processing a scroll-bar notification message.

See Also

»CScrollBar::GetScrollPos«, »CScrollBar::GetScrollRange«, »CWnd::ScrollWindow«, »CScrollBar::SetScrollPos«, »CScrollBar::SetScrollRange«


CScrollView
  class CScrollView : public CView

The CScrollView class is a »CView« with scrolling capabilities.

You can handle scrolling yourself in any class derived from CView by overriding the message-mapped »OnHScroll« and »OnVScroll« member functions. But CScrollView adds the following features to its CView capabilities:

•	It manages window and viewport sizes and mapping modes.

•	It scrolls automatically in response to scroll-bar messages.

To take advantage of automatic scrolling, derive your view class from CScrollView instead of from CView. When the view is first created, if you want to calculate the size of the scrollable view based on the size of the document, call the SetScrollSizes member function from your override of either »CView::OnInitialUpdate« or »CView::OnUpdate«. (You must write your own code to query the size of the document. For an example, see Chapter 8 in the Class Library User's Guide.)

The call to the SetScrollSizes member function sets the view's mapping mode, the total dimensions of the scroll view, and the amounts to scroll horizontally and vertically. All sizes are in logical units. The logical size of the view is usually calculated from data stored in the document, but in some cases you may want to specify a fixed size. For examples of both approaches, see »CScrollView::SetScrollSizes«.

You specify the amounts to scroll horizontally and vertically in logical units. By default, if the user clicks a scroll bar shaft outside of the scroll box, CScrollView scrolls a "page." If the user clicks a scroll arrow at either end of a scroll bar, CScrollView scrolls a "line." By default, a page is 1/10 of the total size of the view; a line is 1/10 of the page size. Override these default values by passing custom sizes in the SetScrollSizes member function. For example, you might set the horizontal size to some fraction of the width of the total size and the vertical size to the height of a line in the current font.

Instead of scrolling, CScrollView can automatically scale the view to the current window size. In this mode, the view has no scroll bars and the logical view is stretched or shrunk to exactly fit the window's client area. To use this scale-to-fit capability, call »CScrollView::SetScaleToFitSize«. (Call either SetScaleToFitSize or SetScrollSizes, but not both.)

Before the OnDraw member function of your derived view class is called, CScrollView automatically adjusts the viewport origin for the CPaintDC device-context object that it passes to OnDraw.

To adjust the viewport origin for the scrolling window, CScrollView overrides »CView::OnPrepareDC«. This adjustment is automatic for the CPaintDC device context that CScrollView passes to OnDraw, but you must call CScrollView::OnPrepareDC yourself for any other device contexts you use, such as a CClientDC. You can override CScrollView::OnPrepareDC to set the pen, background color, and other drawing attributes, but call the base class to do scaling.

Scroll bars may appear in three places relative to a view, as shown in the following cases:

•	Standard window-style scroll bars can be set for the view using the WS_HSCROLL and WS_VSCROLL styles.

•	Scroll-bar controls can also be added to the frame containing the view, in which case the framework forwards WM_HSCROLL and WM_VSCROLL messages from the frame window to the currently active view.

•	The framework also forwards scroll messages from a CSplitterWnd splitter control to the currently active splitter pane (a view). When placed in a »CSplitterWnd« with shared scroll bars, a CScrollView object will use the shared ones rather than creating its own.

#include <afxwin.h>

See Also

»CView«, »CSplitterWnd«


CScrollView Class Members
  Class Members

Operations — Public Members

»FillOutsideRect«	Fills the area of a view outside the scrolling area.
»GetDeviceScrollPosition«	Gets the current scroll position in device units.
»GetDeviceScrollSizes«	Gets the current mapping mode, the total size, and the line and page sizes of the scrollable view. Sizes are in device units.
»GetScrollPosition«	Gets the current scroll position in logical units.
»GetTotalSize«	Gets the total size of the scroll view in logical units.
»ResizeParentToFit«	Causes the size of the view to dictate the size of its frame.
»ScrollToPosition«	Scrolls the view to a given point, specified in logical units.
»SetScaleToFitSize«	Puts the scroll view into scale-to-fit mode.
»SetScrollSizes«	Sets the scroll view's mapping mode, total size, and horizontal and vertical scroll amounts.
Construction/Destruction — Protected Members

»CScrollView«	Constructs a CScrollView object.


CScrollView Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CScrollView::CScrollView

Protected

CScrollView(); ♦

Remarks

Constructs a CScrollView object. You must call either SetScrollSizes or SetScaleToFitSize before the scroll view is usable.

See Also

»CScrollView::SetScrollSizes«, »CScrollView::SetScaleToFitSize«


  CScrollView::FillOutsideRect

void FillOutsideRect( CDC* pDC, CBrush* pBrush );

pDC    Device context in which the filling is to be done.

pBrush    Brush with which the area is to be filled.

Remarks

Call FillOutsideRect to fill the area of the view that appears outside of the scrolling area. Use FillOutsideRect in your scroll view's OnEraseBkgnd handler function to prevent excessive background repainting.

See Also

»CWnd::OnEraseBkgnd«

 Example

BOOL CScaleView::OnEraseBkgnd( CDC* pDC )
{
    CBrush br( GetSysColor( COLOR_WINDOW ) );
    FillOutsideRect( pDC, &br );
    return TRUE;                   // Erased
}


  CScrollView::GetDeviceScrollPosition

CPoint GetDeviceScrollPosition() const;

Remarks

Call GetDeviceScrollPosition when you need the current horizontal and vertical positions of the scroll boxes in the scroll bars. This coordinate pair corresponds to the location in the document to which the upper-left corner of the view has been scrolled. This is useful for offsetting mouse-device positions to scroll-view device positions.

GetDeviceScrollPosition returns values in device units. If you want logical units, use GetScrollPosition instead.

See Also

»CScrollView::GetScrollPosition«


  CScrollView::GetDeviceScrollSizes

void GetDeviceScrollSizes( int& nMapMode, SIZE& sizeTotal, SIZE& sizePage, SIZE& sizeLine ) const;

nMapMode    Returns the current mapping mode for this view. For a list of possible values, see SetScrollSizes.

sizeTotal    Returns the current total size of the scroll view in device units.

sizePage    Returns the current horizontal and vertical amounts to scroll in each direction in response to a mouse click in a scroll-bar shaft. The cx member contains the horizontal amount. The cy member contains the vertical amount.

sizeLine    Returns the current horizontal and vertical amounts to scroll in each direction in response to a mouse click in a scroll arrow. The cx member contains the horizontal amount. The cy member contains the vertical amount.

Remarks

GetDeviceScrollSizes gets the current mapping mode, the total size, and the line and page sizes of the scrollable view. Sizes are in device units. This member function is rarely called.

See Also

»CScrollView::SetScrollSizes«, »CScrollView::GetTotalSize«


  CScrollView::GetScrollPosition

CPoint GetScrollPosition() const;

Remarks

Call GetScrollPosition when you need the current horizontal and vertical positions of the scroll boxes in the scroll bars. This coordinate pair corresponds to the location in the document to which the upper-left corner of the view has been scrolled.

GetScrollPosition returns values in logical units. If you want device units, use GetDeviceScrollPosition instead.

See Also

»CScrollView::GetDeviceScrollPosition«


  CScrollView::GetTotalSize

CSize GetTotalSize() const;

Remarks

Call GetTotalSize to retrieve the current horizontal and vertical sizes of the scroll view.

Return Value

The total size of the scroll view in logical units. The horizontal size is in the cx member of the CSize return value. The vertical size is in the cy member.

See Also

»CScrollView::GetDeviceScrollSizes«, »CScrollView::SetScrollSizes«


  CScrollView::ResizeParentToFit

void ResizeParentToFit( BOOL bShrinkOnly = TRUE );

bShrinkOnly    The kind of resizing to perform. The default value, TRUE, shrinks the frame window if appropriate. Scroll bars will still appear for large views or small frame windows. A value of FALSE causes the view always to resize the frame window exactly. This can be somewhat dangerous since the frame window could get too big to fit inside the multiple document interface (MDI) frame window or the screen.

Remarks

Call ResizeParentToFit to let the size of your view dictate the size of its frame window. This is recommended only for views in MDI child frame windows. Use ResizeParentToFit in the OnInitialUpdate handler function of your derived CScrollView class. For an example of this member function, see »CScrollView::SetScrollSizes«.

ResizeParentToFit assumes that the size of the view window has been set. If the view window size has not been set when ResizeParentToFit is called, you will get an assertion. To ensure that this does not happen, make the following call before calling ResizeParentToFit:

GetParentFrame()->RecalcLayout();

See Also

»CView::OnInitialUpdate«, »CScrollView::SetScrollSizes«


  CScrollView::ScrollToPosition

void ScrollToPosition( POINT pt );

pt   The point to scroll to, in logical units. The cx member must be a positive value (greater than or equal to 0, up to the total size of the view). The same is true for the cy member when the mapping mode is MM_TEXT. The cy member is negative in mapping modes other than MM_TEXT.

Remarks

Call ScrollToPosition to scroll to a given point in the view. The view will be scrolled so that this point is at the upper-left corner of the window. This member function must not be called if the view is scaled to fit.

See Also

»CScrollView::GetDeviceScrollPosition«, »CScrollView::SetScaleToFitSize«, »CScrollView::SetScrollSizes«


  CScrollView::SetScaleToFitSize

void SetScaleToFitSize( SIZE sizeTotal );

sizeTotal    The horizontal and vertical sizes to which the view is to be scaled. The scroll view's size is measured in logical units. The horizontal size is contained in the cx member. The vertical size is contained in the cy member. Both cx and cy must be greater than or equal to 0.

Remarks

Call SetScaleToFitSize when you want to scale the viewport size to the current window size automatically. With scroll bars, only a portion of the logical view may be visible at any time. But with the scale-to-fit capability, the view has no scroll bars and the logical view is stretched or shrunk to exactly fit the window's client area. When the window is resized, the view draws its data at a new scale based on the size of the window.

You'll typically place the call to SetScaleToFitSize in your override of the view's OnInitialUpdate member function. If you don't want automatic scaling, call the SetScrollSizes member function instead.

SetScaleToFitSize can be used to implement a "Zoom to Fit" operation. Use SetScrollSizes to reinitialize scrolling.

SetScaleToFitSize assumes that the size of the view window has been set. If the view window size has not been set when SetScaleToFitSize is called, you will get an assertion. To ensure that this does not happen, make the following call before calling SetScaleToFitSize:

GetParentFrame()->RecalcLayout();

See Also

»CScrollView::SetScrollSizes«, »CView::OnInitialUpdate«


  CScrollView::SetScrollSizes

void SetScrollSizes( int nMapMode, SIZE sizeTotal, const SIZE& sizePage = sizeDefault, const SIZE& sizeLine = sizeDefault );

nMapMode    The mapping mode to set for this view. Possible values include:

Mapping Mode	Logical Unit	Positive y-axis Extends...
MM_TEXT	1 pixel	Downward
MM_HIMETRIC	0.01 mm	Upward
MM_TWIPS	1/1440 in	Upward
MM_HIENGLISH	0.001 in	Upward
MM_LOMETRIC	0.1 mm	Upward
MM_LOENGLISH	0.01 in	Upward
All of these modes are defined by Windows. Two standard mapping modes, MM_ISOTROPIC and MM_ANISOTROPIC, are not used for CScrollView. The class library provides the SetScaleToFitSize member function for scaling the view to window size. Column three in the table above describes the coordinate orientation.

sizeTotal    The total size of the scroll view. The cx member contains the horizontal extent. The cy member contains the vertical extent. Sizes are in logical units. Both cx and cy must be greater than or equal to 0.

sizePage    The horizontal and vertical amounts to scroll in each direction in response to a mouse click in a scroll-bar shaft. The cx member contains the horizontal amount. The cy member contains the vertical amount.

sizeLine    The horizontal and vertical amounts to scroll in each direction in response to a mouse click in a scroll arrow. The cx member contains the horizontal amount. The cy member contains the vertical amount.

Remarks

Call SetScrollSizes when the view is about to be updated. Call it in your override of the OnUpdate member function to adjust scrolling characteristics when, for example, the document is initially displayed or when it changes size.

You will typically obtain size information from the view's associated document by calling a document member function, perhaps called GetMyDocSize, that you supply with your derived document class. The following code shows this approach:

SetScrollSizes( nMapMode, GetDocument( )->GetMyDocSize( ) );

Alternatively, you might sometimes need to set a fixed size, as in the following code:

SetScrollSizes( nMapMode, CSize(100, 100) );

You must set the mapping mode to any of the Windows mapping modes except MM_ISOTROPIC or MM_ANISOTROPIC. If you want to use an unconstrained mapping mode, call the SetScaleToFitSize member function instead of SetScrollSizes.

See Also

»CScrollView::SetScaleToFitSize«, »CScrollView::GetDeviceScrollSizes«, »CScrollView::GetTotalSize«

 Example

void CScaleView::OnUpdate( )
{
   // ...
   // Implement a GetDocSize( ) member function in
   // your document class; it returns a CSize.
   SetScrollSizes( MM_LOENGLISH, GetDocument( )->GetDocSize( ) );
   ResizeParentToFit( );   // Default bShrinkOnly argument
   // ...
}


CSingleDocTemplate
  class CSingleDocTemplate : public CDocTemplate

The CSingleDocTemplate class defines a document template that implements the single document interface (SDI). An SDI application uses the main frame window to display a document; only one document can be open at a time. For a more detailed description of the SDI, see The Windows Interface: An Application Design Guide.

A document template defines the relationship between three types of classes:

•	A document class, which you derive from CDocument.

•	A view class, which displays data from the document class listed above. You can derive this class from CView, CScrollView, CFormView, or CEditView. (You can also use CEditView directly.)

•	A frame window class, which contains the view. For an SDI document template, you can derive this class from CFrameWnd, or, if you don't need to customize the behavior of the main frame window, you can use CFrameWnd directly without deriving your own class.

An SDI application typically supports one type of document, so it has only one CSingleDocTemplate object. Only one document can be open at a time.

You don't need to call any member functions of CSingleDocTemplate except the constructor. The framework handles CSingleDocTemplate objects internally.

See Also

»CDocTemplate«, »CDocument«, »CFrameWnd«, »CMultiDocTemplate«, »CView«, »CWinApp«


CSingleDocTemplate Class Members
  Class Members

Construction/Destruction — Public Members

»CSingleDocTemplate«	Constructs a CSingleDocTemplate object.


CSingleDocTemplate Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CSingleDocTemplate::CSingleDocTemplate

CSingleDocTemplate( UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass );

nIDResource    Specifies the ID of the resources used with the document type. This may include menu, icon, accelerator table, and string resources.

The string resource consists of up to seven substrings separated by the '\n' character (the '\n' character is needed as a placeholder if a substring is not included; however, trailing '\n' characters are not necessary); these substrings describe the document type. For information about the substrings, see »CDocTemplate::GetDocString«. This string resource is found in the application's resource file. For example:

// MYCALC.RC

STRINGTABLE PRELOAD DISCARDABLE

BEGIN

    IDR_MAINFRAME "MyCalc Windows Application\nSheet\nWorksheet\n Worksheets (*.myc)\n.myc\nMyCalcSheet\n MyCalc Worksheet"

END

You can edit this string using the String Editor in App Studio; the entire string appears as a single entry in the String Editor, not as seven separate entries.

For more information about these resource types, see the App Studio User's Guide.

pDocClass    Points to the CRuntimeClass object of the document class. This class is a CDocument-derived class you define to represent your documents.

pFrameClass    Points to the CRuntimeClass object of the frame window class. This class can be a CFrameWnd-derived class, or it can be CFrameWnd itself if you want default behavior for your main frame window.

pViewClass    Points to the CRuntimeClass object of the view class. This class is a CView-derived class you define to display your documents.

Remarks

Constructs a CSingleDocTemplate object. Dynamically allocate a CSingleDocTemplate object and pass it to CWinApp::AddDocTemplate from the InitInstance member function of your application class.

See Also

»CDocTemplate::GetDocString«, »CWinApp::AddDocTemplate«, »CWinApp::InitInstance«, »CRuntimeClass«, RUNTIME_CLASS

 Example

// example for CSingleDocTemplate::CSingleDocTemplate

BOOL CMyApp::InitInstance()
{
        // ...
        // Establish the document type
        // supported by the application

        AddDocTemplate( new CSingleDocTemplate( IDR_MAINFRAME,
                            RUNTIME_CLASS( CSheetDoc ),
                            RUNTIME_CLASS( CFrameWnd ),
                            RUNTIME_CLASS( CSheetView ) ) );

        // ...
}


CSize
  class CSize : public tagSIZE

The CSize class is similar to the Windows »SIZE« structure, which implements a relative coordinate or position.

Because CSize derives from tagSIZE, CSize objects may be used as SIZE structures. The operators of this class that interact with a "size" accept either CSize objects or SIZE structures.

The cx and cy members of SIZE (and CSize) are public. In addition, CSize implements member functions to manipulate the SIZE structure.

#include <afxwin.h>

SIZE Structure

A SIZE structure has this form:

typedef struct tagSIZE {

    int cx;

    int cy;

} SIZE;

Members

cx    Specifies the x-extent when a function returns.

cy    Specifies the y-extent when a function returns.

Some extended functions of Windows versions 3.1 and later place viewport extents, window extents, text extents, bitmap dimensions, and the aspect-ratio filter in the SIZE structure.

See Also

»CRect«, »CPoint«


CSize Class Members
  Class Members

Construction/Destruction — Public Members

»CSize«	Constructs a CSize object.
Operators — Public Members

»operator ==«	Checks for equality between CSize and a size.
»operator != «	Checks for inequality between CSize and a size.
»operator +=«	Adds a size to CSize.
»operator −=«	Subtracts a size from CSize.
Operators Returning CSize Values — Public Members

»operator +«	Adds two sizes.
»operator −«	Subtracts two sizes.


CSize Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CSize::CSize

CSize();

CSize( int initCX, int initCY );

CSize( SIZE initSize );

CSize( POINT initPt );

CSize( DWORD dwSize );

initCX    Sets the cx member for the CSize.

initCY    Sets the cy member for the CSize.

initSize    SIZE structure or CSize object used to initialize CSize.

initPt    POINT structure or CPoint object used to initialize CSize.

dwSize    DWORD used to initialize CSize. The low-order word is the cx member and the high-order word is the cy member.

Remarks

Constructs a CSize object. If no arguments are given, cx and cy members are not initialized.


CSize Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CSize::operator ==

BOOL operator ==( SIZE size ) const;

Remarks

Checks for equality between two sizes.

Return Value

Nonzero if the sizes are equal; otherwise 0.


  CSize::operator !=

BOOL operator !=( SIZE size ) const;

Remarks

Checks for inequality between two sizes.

Return Value

Nonzero if the sizes are not equal; otherwise 0.


  CSize::operator +=

void operator +=( SIZE size );

Remarks

Adds a size to a CSize.


CSize::operator -=
  CSize::operator −=

void operator −=( SIZE size );

Remarks

Subtracts a size from a CSize.


  CSize::operator +

CSize operator +( SIZE size ) const;

Return Value

A CSize that is the sum of two sizes.


CSize::operator -
  CSize::operator −

CSize operator −( SIZE size ) const;

CSize operator −() const;

Return Value

A CSize that is the difference between two sizes.


CSplitterWnd
  class CSplitterWnd : public CWnd

The CSplitterWnd class provides the functionality of a splitter window, which is a window that contains multiple panes. A pane is usually an application-specific object derived from CView, but it can be any CWnd object that has the appropriate child window ID.

A CSplitterWnd object is usually embedded in a parent CFrameWnd or CMDIChildWnd object. Create a CSplitterWnd object using the following steps:

1.	Embed a CSplitterWnd member variable in the parent frame.

2.	Override the parent frame's OnCreateClient member function.

3.	From within the overridden OnCreateClient, call the Create or CreateStatic member function of CSplitterWnd.

Call the Create member function to create a dynamic splitter window. A dynamic splitter window typically is used to create and scroll a number of individual panes, or views, of the same document. The framework automatically creates an initial pane for the splitter; then the framework creates, resizes, and disposes of additional panes as the user operates the splitter window's controls.

When you call Create, you specify a minimum row height and column width that determine when the panes are too small to be fully displayed. After you call Create, you can adjust these minimums by calling the »SetColumnInfo« and »SetRowInfo« member functions.

Also use the SetColumnInfo and SetRowInfo member functions to set an "ideal" width for a column and "ideal" height for a row. When the framework displays a splitter window, it first displays the parent frame, then the splitter window. The framework then lays out the panes in columns and rows according to their ideal dimensions, working from the upper-left to lower-right corner of the splitter window's client area.

All panes in a dynamic splitter window must be of the same class. Familiar applications that support dynamic splitter windows include Microsoft Word and Microsoft Excel.

Use the CreateStatic member function to create a static splitter window. The user can change only the size of the panes in a static splitter window, not their number or order.

You must specifically create all the static splitter's panes when you create the static splitter. Make sure you create all the panes before the parent frame's OnCreateClient member function returns, or the framework will not display the window correctly.

The CreateStatic member function automatically initializes a static splitter with a minimum row height and column width of 0. After you call Create, adjust these minimums by calling the »SetColumnInfo« and »SetRowInfo« member functions. Also use SetColumnInfo and SetRowInfo after you call CreateStatic to indicate desired ideal pane dimensions.

The individual panes of a static splitter often belong to different classes. For examples of static splitter windows, see the App Studio graphics editor and the Windows File Manager.

A splitter window supports special scroll bars (apart from the scroll bars that panes may have). These scroll bars are children of the CSplitterWnd object and are shared with the panes.

You create these special scroll bars when you create the splitter window. For example, a CSplitterWnd that has one row, two columns, and the WS_VSCROLL style will display a vertical scroll bar that is shared by the two panes. When the user moves the scroll bar, WM_VSCROLL messages are sent to both panes. When the panes set the scroll-bar position, the shared scroll bar is set.

For further information on splitter windows, see Technical Note 29 in MSVCNT\HELP\MFCNOTES.HLP. For more information on how to create dynamic splitter windows, see the Scribble sample application in Chapter 8 of the Class Library User's Guide, and the VIEWEX example in the MFC\SAMPLES\VIEWEX subdirectory.

include <afxext.h>

See Also

»CWnd«


CSplitterWnd Class Members
  Class Members

Construction — Public Members

»CSplitterWnd«	Call to construct a CSplitterWnd object.
»Create«	Call to create a dynamic splitter window and attach it to the CSplitterWnd object.
»CreateStatic«	Call to create a static splitter window and attach it to the CSplitterWnd object.
»CreateView«	Call to create a pane in a splitter window.
Operations — Public Members

»GetRowCount«	Returns the current pane row count.
»GetColumnCount«	Returns the current pane column count.
»GetRowInfo«	Returns information on the specified row.
»SetRowInfo«	Call to set the specified row information.
»GetColumnInfo«	Returns information on the specified column.
»SetColumnInfo«	Call to set the specified column information.
»GetPane«	Returns the pane at the specified row and column.
»IsChildPane«	Call to determine if the window is currently a child pane of this splitter window.
»IdFromRowCol«	Returns the child window ID of the pane at the specified row and column.
»RecalcLayout«	Call to redisplay the splitter window after adjusting row or column size.


CSplitterWnd Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CSplitterWnd::Create

BOOL Create( CWnd* pParentWnd, int nMaxRows, int nMaxCols, SIZE sizeMin, CCreateContext* pContext, DWORD dwStyle = WS_CHILD | WS_VISIBLE |WS_HSCROLL | WS_VSCROLL | SPLS_DYNAMIC_SPLIT, UINT nID = AFX_IDW_PANE_FIRST );

pParentWnd    The parent frame window of the splitter window.

nMaxRows    The maximum number of rows in the splitter window. This value must not exceed 2.

nMaxCols    The maximum number of columns in the splitter window. This value must not exceed 2.

sizeMin    Specifies the minimum size at which a pane may be displayed.

pContext    A pointer to a CCreateContext structure. In most cases, this can be the pContext passed to the parent frame window.

dwStyle    Specifies the window style.

nID    The child window ID of the window. The ID can be AFX_IDW_PANE_FIRST unless the splitter window is nested inside another splitter window.

Remarks

To create a dynamic splitter window, call the Create member function.

You can embed a CSplitterWnd in a parent CFrameWnd or CMDIChildWnd object by taking the following steps:

1.	Embed a CSplitterWnd member variable in the parent frame.

2.	Override the parent frame's OnCreateClient member function.

3.	Call the Create member function from within the overridden OnCreateClient.

When you create a splitter window from within a parent frame, pass the parent frame's pContext parameter to the splitter window. Otherwise, this parameter can be NULL.

The initial minimum row height and column width of a dynamic splitter window are set by the sizeMin parameter. These minimums, which determine if a pane is too small to be shown in its entirety, can be changed with the SetRowInfo and SetColumnInfo member functions.

For more on dynamic splitter windows, see Chapter 4, »Working with Frame Windows Documents and Views« in this manual, Technical Note 29, and the CSplitterWnd class overview.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CSplitterWnd::CreateStatic«, »CFrameWnd::OnCreateClient«, »CSplitterWnd::SetRowInfo«, »CSplitterWnd::SetColumnInfo«, »CSplitterWnd::CreateView«


  CSplitterWnd::CreateStatic

BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols, DWORD dwStyle = WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST );

pParentWnd    The parent frame window of the splitter window.

nRows    The number of rows. This value must not exceed 16.

nCols    The number of columns. This value must not exceed 16.

dwStyle    Specifies the window style.

nID    The child window ID of the window. The ID can be AFX_IDW_PANE_FIRST unless the splitter window is nested inside another splitter window.

Remarks

To create a static splitter window, call the CreateStatic member function.

A CSplitterWnd is usually embedded in a parent CFrameWnd or CMDIChildWnd object by taking the following steps:

1.	Embed a CSplitterWnd member variable in the parent frame.

2.	Override the parent frame's OnCreateClient member function.

3.	Call the CreateStatic member function from within the overridden OnCreateClient.

A static splitter window contains a fixed number of panes, often from different classes.

When you create a static splitter window, you must at the same time create all its panes. The CreateView member function is usually used for this purpose, but you can create other nonview classes as well.

The initial minimum row height and column width for a static splitter window is 0. These minimums, which determine when a pane is too small to be shown in its entirety, can be changed with the SetRowInfo and SetColumnInfo member functions.

To add scroll bars to a static splitter window, add the WS_HSCROLL and WS_VSCROLL styles to dwStyle.

See Chapter 4, »Working with Frame Windows Documents and Views« in this manual, Technical Note 29, and the CSplitterWnd class description for more on static splitter windows.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CSplitterWnd::Create«, »CFrameWnd::OnCreateClient«, »CSplitterWnd::SetRowInfo«, »CSplitterWnd::SetColumnInfo«, »CSplitterWnd::CreateView«


  CSplitterWnd::CreateView

virtual BOOL CreateView( int row, int col, CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext );

Parameters

row    Specifies the splitter window row in which to place the new view.

col    Specifies the splitter window column in which to place the new view.

pViewClass    Specifies the CRuntimeClass of the new view.

sizeInit    Specifies the initial size of the new view.

pContext    A pointer to a creation context used to create the view (usually the pContext passed into the parent frame's overridden OnCreateClient member function in which the splitter window is being created).

Remarks

Call this member function to create the panes for a static splitter window. All panes of a static splitter window must be created before the framework displays the splitter.

The framework also calls this member function to create new panes when the user of a dynamic splitter window splits a pane, row, or column.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CSplitterWnd::Create«


  CSplitterWnd::CSplitterWnd

CSplitterWnd();

Remarks

Construct a CSplitterWnd object in two steps. First call the constructor, which creates the CSplitterWnd object, then call the Create member function, which creates the splitter window and attaches it to the CSplitterWnd object.

See Also

»CSplitterWnd::Create«


  CSplitterWnd::GetColumnCount

int GetColumnCount();

Return Value

Returns the current number of columns in the splitter. For a static splitter this will also be the maximum number of columns.

See Also

»CSplitterWnd::GetRowCount«


  CSplitterWnd::GetColumnInfo

void GetColumnInfo( int col, int& cxCur, int& cxMin );

col    Specifies a column.

cxCur    A reference to an int to be set to the current width of the column.

cxMin    A reference to an int to be set to the current minimum width of the column.

Remarks

Call this member function to obtain information about the specified column.

See Also

»CSplitterWnd::SetColumnInfo«, »CSplitterWnd::GetRowInfo«


  CSplitterWnd::GetPane

CWnd* GetPane( int row, int col );

row    Specifies a row.

col    Specifies a column.

Return Value

Returns the pane at the specified row and column. The returned pane is usually a CView-derived class.

See Also

»CSplitterWnd::IdFromRowCol«, »CSplitterWnd::IsChildPane«


  CSplitterWnd::GetRowCount

int GetRowCount();

Return Value

Returns the current number of rows in the splitter window. For a static splitter window, this will also be the maximum number of rows.

See Also

»CSplitterWnd::GetColumnCount«


  CSplitterWnd::GetRowInfo

void GetRowInfo( int row, int& cyCur, int& cyMin );

row    Specifies a row.

cyCur    Reference to int to be set to the current height of the row in pixels.

cyMin    Reference to int to be set to the current minimum height of the row in pixels.

Remarks

Call this member function to obtain information about the specified row.

Return Value

The cyCur parameter is filled with the current height of the specified row, and cyMin is filled with the minimum height of the row.

See Also

»CSplitterWnd::SetRowInfo«, »CSplitterWnd::GetColumnInfo«


  CSplitterWnd::IdFromRowCol

int IdFromRowCol( int row, int col );

row    Specifies the splitter window row.

col    Specifies the splitter window column.

Remarks

Call this member function to obtain the child window ID for the pane at the specified row and column. This member function is used for creating nonviews as panes and may be called before the pane exists.

Return Value

The child window ID for the pane.

See Also

»CSplitterWnd::GetPane«, »CSplitterWnd::IsChildPane«


  CSplitterWnd::IsChildPane

BOOL IsChildPane( CWnd* pWnd, int& row, int& col );

pWnd    A pointer to a CWnd object to be tested.

row    Reference to an int in which to store row number.

col    Reference to an int in which to store a column number.

Remarks

Call this member function to determine whether pWnd is currently a child pane of this splitter window.

Return Value

If nonzero, pWnd is currently a child pane of this splitter window, and row and col are filled in with the position of the pane in the splitter window. If pWnd is not a child pane of this splitter window, 0 is returned.

See Also

»CSplitterWnd::GetPane«


  CSplitterWnd::RecalcLayout

void RecalcLayout();

Remarks

Call this member function to correctly redisplay the splitter window after you have adjusted row and column sizes with the SetRowInfo and SetColumnInfo member functions. If you change row and column sizes as part of the creation process before the splitter window is visible, it is not necessary to call this member function.

The framework calls this member function whenever the user resizes the splitter window or moves a split.

See Also

»CSplitterWnd::SetRowInfo«, »CSplitterWnd::SetColumnInfo«


  CSplitterWnd::SetColumnInfo

void SetColumnInfo( int col, int cxIdeal, int cxMin );

col    Specifies a splitter window column.

cxIdeal    Specifies an ideal width for the splitter window column in pixels.

cxMin    Specifies a minimum width for the splitter window column in pixels.

Remarks

Call this member function to set a new minimum width and ideal width for a column. The column minimum value determines when the column will be too small to be fully displayed.

When the framework displays the splitter window, it lays out the panes in columns and rows according to their ideal dimensions, working from the upper-left to lower-right corner of the splitter window's client area.

See Also

»CSplitterWnd::GetRowInfo«, »CSplitterWnd::RecalcLayout«


  CSplitterWnd::SetRowInfo

void SetRowInfo( int row, int cyIdeal, int cyMin );

row    Specifies a splitter window row.

cyIdeal    Specifies an ideal height for the splitter window row in pixels.

cyMin    Specifies a minimum height for the splitter window row in pixels.

Remarks

Call this member function to set a new minimum height and ideal height for a row. The row minimum value determines when the row will be too small to be fully displayed.

When the framework displays the splitter window, it lays out the panes in columns and rows according to their ideal dimensions, working from the upper-left to lower-right corner of the splitter window's client area.

See Also

»CSplitterWnd::GetRowInfo«, »CSplitterWnd::SetColumnInfo«, »CSplitterWnd::RecalcLayout«


CStatic
  class CStatic : public CWnd

The CStatic class provides the functionality of a Windows static control. A static control is a simple text field, box, or rectangle that can be used to label, box, or separate other controls. A static control takes no input and provides no output.

Create a static control in two steps. First, call the constructor CStatic to construct the CStatic object, then call the »Create« member function to create the static control and attach it to the CStatic object.

If you create a CStatic object within a dialog box (through a dialog resource), the CStatic object is automatically destroyed when the user closes the dialog box.

If you create a CStatic object within a window, you may also need to destroy it. A CStatic object created on the stack within a window is automatically destroyed. If you create the CStatic object on the heap by using the new function, you must call delete on the object to destroy it when the user terminates the Windows static control.

#include <afxwin.h>

See Also

»CWnd«, »CButton«, »CComboBox«, »CEdit«, »CListBox«, »CScrollBar«, »CDialog«


CStatic Class Members
  Class Members

Construction/Destruction — Public Members

»CStatic«	Constructs a CStatic object.
Initialization — Public Members

»Create«	Creates the Windows static control and attaches it to the CStatic object.
Operations — Public Members

»SetIcon«	Associates an icon with an icon resource.
»GetIcon«	Retrieves the handle of the icon associated with an icon resource.


CStatic Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CStatic::Create

BOOL Create( LPCSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff );

lpszText    Specifies the text to place in the control. If NULL, no text will be visible.

dwStyle    Specifies the static control's window »style«.

rect    Specifies the position and size of the static control. It can be either a RECT structure or a CRect object.

pParentWnd    Specifies the CStatic parent window, usually a CDialog object. It must not be NULL.

nID    Specifies the static control's control ID.

Remarks

Construct a CStatic object in two steps. First call the constructor CStatic, then call Create, which creates the Windows static control and attaches it to the CStatic object.

Apply the following »window styles« to a static control:

•	WS_CHILD    Always

•	WS_VISIBLE    Usually

•	WS_DISABLED    Rarely

Return Value

Nonzero if successful; otherwise 0.

Apply any combination of »static control styles« to the static control.

 Static Styles

You can use any combination of the following static control styles for dwStyle:

•	SS_BLACKFRAME    Specifies a box with a frame drawn with the same color as window frames. The default is black.

•	SS_BLACKRECT    Specifies a rectangle filled with the color used to draw window frames. The default is black.

•	SS_CENTER    Designates a simple rectangle and displays the given text centered in the rectangle. The text is formatted before it is displayed. Words that would extend past the end of a line are automatically wrapped to the beginning of the next centered line.

•	SS_GRAYFRAME    Specifies a box with a frame drawn with the same color as the screen background (desktop). The default is gray.

•	SS_GRAYRECT    Specifies a rectangle filled with the color used to fill the screen background. The default is gray.

•	SS_ICON    Designates an icon displayed in the dialog box. The given text is the name of an icon (not a filename) defined elsewhere in the resource file. The nWidth and nHeight parameters are ignored; the icon automatically sizes itself.

•	SS_LEFT    Designates a simple rectangle and displays the given text flush-left in the rectangle. The text is formatted before it is displayed. Words that would extend past the end of a line are automatically wrapped to the beginning of the next flush-left line.

•	SS_LEFTNOWORDWRAP    Designates a simple rectangle and displays the given text flush-left in the rectangle. Tabs are expanded, but words are not wrapped. Text that extends past the end of a line is clipped.

•	SS_NOPREFIX    Unless this style is specified, Windows will interpret any ampersand (&) characters in the control's text to be accelerator prefix characters. In this case, the ampersand (&) is removed and the next character in the string is underlined. If a static control is to contain text where this feature is not wanted, SS_NOPREFIX may be added. This static-control style may be included with any of the defined static controls. You can combine SS_NOPREFIX with other styles by using the bitwise-OR operator. This is most often used when filenames or other strings that may contain an ampersand (&) need to be displayed in a static control in a dialog box.

•	SS_RIGHT    Designates a simple rectangle and displays the given text flush-right in the rectangle. The text is formatted before it is displayed. Words that would extend past the end of a line are automatically wrapped to the beginning of the next flush-right line.

•	SS_SIMPLE    Designates a simple rectangle and displays a single line of text flush-left in the rectangle. The line of text cannot be shortened or altered in any way. (The control's parent window or dialog box must not process the WM_CTLCOLOR message.)

•	SS_USERITEM    Specifies a user-defined item.

•	SS_WHITEFRAME    Specifies a box with a frame drawn with the same color as the window background. The default is white.

•	SS_WHITERECT    Specifies a rectangle filled with the color used to fill the window background. The default is white.

See Also

»CStatic::CStatic«


  CStatic::CStatic

CStatic();

Remarks

Constructs a CStatic object.

See Also

»CStatic::Create«


  CStatic::GetIcon

Windows 3.1 Only

HICON GetIcon() const; »

Return Value

Returns the handle of the icon associated with an icon resource. This function should be called only for CStatic objects that represent icons created with the SS_ICON style.

See Also

STM_GETICON, »CStatic::SetIcon«


  CStatic::SetIcon

Windows 3.1 Only

HICON SetIcon( HICON hIcon ); »

hIcon    Identifies the icon to associate with an icon resource.

Remarks

Associates an icon with an icon resource. This is a CStatic object created with the SS_ICON style.

Return Value

The handle of the icon that was previously associated with the icon resource; 0 if an error occurred.

See Also

STM_SETICON, ::LoadIcon, »CStatic::GetIcon«


CStatusBar
  class CStatusBar : public CControlBar

A CStatusBar object is a control bar with a row of text output panes, or "indicators." The output panes commonly are used as message lines and as status indicators. Examples include the menu help-message lines that briefly explain the selected menu command and the indicators that show the status of the Scroll Lock, Num Lock, and other keys.

The framework stores indicator information in an array with the leftmost indicator at position 0. When you create a status bar, you use an array of string IDs that the framework associates with the corresponding indicators. You can then use either a string ID or an index to access an indicator.

By default, the first indicator is "stretchy": it takes up the status-bar length not used by the other indicator panes, so that the other panes are right-aligned.

To create a status bar, follow these steps:

1.	Construct the CStatusBar object.

2.	Call the Create function to create the status-bar window and attach it to the CStatusBar object.

3.	Call SetIndicators to associate a string ID with each indicator.

There are three ways to update the text in a status-bar pane:

1.	Call »SetWindowText« to update the text in pane 0 only.

2.	Call »SetText« in the status bar's ON_UPDATE_COMMAND_UI handler.

3.	Call »SetPaneText« to update the text for any pane.

#include <afxext.h>

See Also

»CControlBar«, »CWnd::SetWindowText«, »CStatusBar::SetIndicators«


CStatusBar  Class Members
  Class Members

Construction/Destruction — Public Members

»CStatusBar«	Constructs a CStatusBar object.
»Create«	Creates the Windows status bar, attaches it to the CStatusBar object, and sets the initial font and bar height.
»SetIndicators«	Sets indicator IDs.
Attributes — Public Members

»CommandToIndex«	Gets index for a given indicator ID.
»GetItemID«	Gets indicator ID for a given index.
»GetItemRect«	Gets display rectangle for a given index.
»GetPaneText«	Gets indicator text for a given index.
»SetPaneText«	Sets indicator text for a given index.
»GetPaneInfo«	Gets indicator ID, style, and width for a given index.
»SetPaneInfo«	Sets indicator ID, style, and width for a given index.


CStatusBar Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CStatusBar::CommandToIndex

int CommandToIndex( UINT nIDFind ) const;

nIDFind    String ID of the indicator whose index is to be retrieved.

Remarks

Gets the indicator index for a given ID. The index of the first indicator is 0.

Return Value

The index of the indicator if successful; −1 if not successful.

See Also

»CStatusBar::GetItemID«


  CStatusBar::Create

BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR );

pParentWnd    Pointer to the CWnd object whose Windows window is the parent of the status bar.

dwStyle    The status-bar style. In addition to the standard Windows styles, these styles are supported:

•	CBRS_TOP    Control bar is at top of frame window.

•	CBRS_BOTTOM    Control bar is at bottom of frame window.

•	CBRS_NOALIGN    Control bar is not repositioned when the parent is resized.

nID    The tool bar's child-window ID.

Remarks

Creates a status bar (a child window) and associates it with the CStatusBar object. Also sets the initial font and sets the status bar's height to a default value.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CStatusBar::SetIndicators«


  CStatusBar::CStatusBar

CStatusBar();

Remarks

Constructs a CStatusBar object, creates a default status-bar font if necessary, and sets the font characteristics to default values.

See Also

»CStatusBar::Create«


  CStatusBar::GetItemID

UINT GetItemID( int nIndex ) const;

nIndex    Index of the indicator whose ID is to be retrieved.

Remarks

Returns the ID of the indicator specified by nIndex.

Return Value

The ID of the indicator specified by nIndex.

See Also

»CStatusBar::CommandToIndex«


  CStatusBar::GetItemRect

void GetItemRect( int nIndex, LPRECT lpRect ) const;

nIndex    Index of the indicator whose rectangle coordinates are to be retrieved.

lpRect    Points to a »RECT« structure or a CRect object that will receive the coordinates of the indicator specified by nIndex.

Remarks

Copies the coordinates of the indicator specified by nIndex into the structure pointed to by lpRect. Coordinates are in pixels relative to the upper-left corner of the status bar.

See Also

»CStatusBar::CommandToIndex«, »CStatusBar::GetPaneInfo«


  CStatusBar::GetPaneInfo

void GetPaneInfo( int nIndex, UINT& nID, UINT& nStyle, int& cxWidth ) const;

nIndex    Index of the pane whose information is to be retrieved.

nID    Reference to a UINT that is set to the ID of the pane.

nStyle    Reference to a UINT that is set to the style of the pane.

cxWidth    Reference to an integer that is set to the width of the pane.

Remarks

Sets nID, nStyle, and cxWidth to the ID, style, and width of the indicator pane at the location specified by nIndex.

See Also

»CStatusBar::SetPaneInfo«, »CStatusBar::GetItemID«, »CStatusBar::GetItemRect«


  CStatusBar::GetPaneText

void GetPaneText( int nIndex, CString& s ) const;

nIndex    Index of the pane whose text is to be retrieved.

s    Reference to a CString object to which the pane's text is copied.

Remarks

Copies the pane's text to the CString object.

See Also

»CStatusBar::SetPaneText«


  CStatusBar::SetIndicators

BOOL SetIndicators( const UINT FAR* lpIDArray, int nIDCount );

lpIDArray    Pointer to an array of IDs.

nIDCount    Number of elements in the array pointed to by lpIDArray.

Remarks

Sets each indicator's ID to the value specified by the corresponding element of the array lpIDArray, loads the string resource specified by each ID, and sets the indicator's text to the string.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CStatusBar::CStatusBar«, »CStatusBar::Create«, »CStatusBar::SetPaneInfo«, »CStatusBar::SetPaneText«


  CStatusBar::SetPaneInfo

void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );

nIndex    Index of the indicator pane whose style is to be set.

nID    New ID for the indicator pane.

nStyle    New style for the indicator pane.

cxWidth    New width for the indicator pane.

Remarks

Sets the specified indicator pane to a new ID, style, and width.

The following indicator styles are supported:

•	SBPS_NOBORDERS    No 3-D border around the pane.

•	SBPS_POPOUT    Reverse border so that text "pops out."

•	SBPS_DISABLED    Do not draw text.

•	SBPS_STRETCH    Stretch pane to fill unused space. Only one pane per status bar can have this style.

•	SBPS_NORMAL    No stretch, borders, or pop-out.

See Also

»CStatusBar::GetPaneInfo«


  CStatusBar::SetPaneText

BOOL SetPaneText( int nIndex, LPCSTR lpszNewText, BOOL bUpdate = TRUE );

nIndex    Index of the pane whose text is to be set.

lpszNewText    Pointer to the new pane text.

bUpdate    If TRUE, the pane is invalidated after the text is set.

Remarks

Sets the pane text to the string pointed to by lpszNewText.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CStatusBar::GetPaneText«


CStdioFile
  class CStdioFile : public CFile

A CStdioFile object represents a C run-time stream file as opened by the fopen function. Stream files are buffered and can be opened in either text mode (the default) or binary mode.

Text mode provides special processing for carriage return−linefeed pairs. When you write a newline character (0x0A) to a text-mode CStdioFile object, the byte pair (0x0A, 0x0D) is sent to the file. When you read, the byte pair (0x0A, 0x0D) is translated to a single 0x0A byte.

The CFile functions Duplicate, LockRange, and UnlockRange are not implemented for CStdioFile.

If you call these functions on a CStdioFile, you will get a CNotSupportedException.

#include <afx.h>


CStdioFile Class Members
  Class Members

Data Members — Public Members

»m_pStream«	Contains a pointer to an open file.
Construction/Destruction — Public Members

»CStdioFile«	Constructs a CStdioFile object from a path or file pointer.
Text Read/Write — Public Members

»ReadString«	Reads a single line of text.
»WriteString«	Writes a single line of text.


CStdioFile Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CStdioFile::CStdioFile

CStdioFile();

CStdioFile( FILE* pOpenStream );

CStdioFile( const char* pszFileName, UINT nOpenFlags )
throw( CFileException );

pOpenStream    Specifies the file pointer returned by a call to the C run-time function fopen.

pszFileName    Specifies a string that is the path to the desired file. The path can be relative or absolute.

nOpenFlags    Sharing and access mode. Specifies the action to take when the file is opened. You can combine options by using the bitwise-OR (|) operator. One access permission and a text-binary specifier are required; the create and noInherit modes are optional. See »CFile::CFile« for a list of mode options. The share flags do not apply.

Remarks

The default version of the constructor works in conjunction with the CFile::Open member function to test errors.

The one-parameter version constructs a CStdioFile object from a pointer to a file that is already open. Allowed pointer values include the predefined input/output file pointers stdin, stdout, or stderr.

The two-parameter version constructs a CStdioFile object and opens the corresponding operating-system file with the given path.

CFileException is thrown if the file cannot be opened or created.

 Example

// example for CStdioFile::CStdioFile

char* pFileName = "test.dat";
CStdioFile f1;
if( !f1.Open( pFileName,
CFile::modeCreate | CFile::modeWrite | CFile::typeText ) ) {
#ifdef _DEBUG
afxDump << "Unable to open file" << "\n";
#endif
exit( 1 );
}
CStdioFile f2( stdout );
TRY
{
CStdioFile f3( pFileName,
CFile::modeCreate | CFile::modeWrite | CFile::typeText );
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "\n";
#endif
}
END_CATCH


  CStdioFile::ReadString

virtual char FAR* ReadString( char FAR* lpsz, UINT nMax )
throw( CFileException );

lpsz    Specifies a pointer to a user-supplied buffer that will receive a null-terminated text string.

nMax    Specifies the maximum number of characters to read. Should be one less than the size of the lpsz buffer.

Remarks

Reads text data into a buffer, up to a limit of nMax−1 characters, from the file associated with the CStdioFile object. Reading is stopped by a carriage return−linefeed pair. If, in that case, fewer than nMax−1 characters have been read, a newline character is stored in the buffer. A null character ('\0') is appended in either case.

»CFile::Read« is also available for text-mode input, but it does not terminate on a carriage return−linefeed pair.

Return Value

A pointer to the buffer containing the text data; NULL if end-of-file was reached.

 Example

// example for CStdioFile::ReadString

extern CStdioFile f;
char buf[100];

f.ReadString( buf, 100 );


  CStdioFile::WriteString

virtual void WriteString( const char FAR* lpsz )
throw( CFileException );

lpsz    Specifies a pointer to a buffer containing a null-terminated text string.

Remarks

Writes data from a buffer to the file associated with the CStdioFile object. The terminating null character ('\0') is not written to the file. Any newline character in lpsz is written to the file as a carriage return−linefeed pair.

WriteString throws an exception in response to several conditions, including the disk-full condition.

This is a text-oriented write function available only to CStdioFile and its descendents. »CFile::Write« is also available, but rather than terminating on a null character, it writes the requested number of bytes to the file.

 Example

// example for CStdioFile::WriteString

extern CStdioFile f;
char buf[] = "test string";

f.WriteString( buf );


CStdioFile Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CStdioFile::m_pStream

Remarks

The m_pStream data member is the pointer to an open file as returned by the C run-time function fopen. It is NULL if the file has never been opened or has been closed.


CString
  class CString

A CString object consists of a variable-length sequence of characters. The CString class provides a variety of functions and operators that manipulate CString objects using a syntax similar to that of Basic. Concatenation and comparison operators, together with simplified memory management, make CString objects easier to use than ordinary character arrays. The increased processing overhead is not significant.

The CString »Application Notes« section offers useful information on:

•	»CString Exception Cleanup«

•	»CString Argument Passing«

The maximum size of a CString object is MAXINT (32,767) characters.

The const char* operator gives direct access to the characters in a CString object, which makes it look like a C-language character array. Unlike a character array, however, the CString class has a built-in memory-allocation capability. This allows string objects to grow as a result of concatenation operations.

No attempt is made to fold CString objects. If you make two CString objects containing Chicago, for example, the characters in Chicago are stored in two places.

The CString class is not implemented as a Microsoft Foundation Class Library collection class, although CString objects can certainly be stored as elements in collections.

The overloaded const char* conversion operator allows CString objects to be freely substituted for character pointers in function calls. The CString( const char* psz ) constructor allows character pointers to be substituted for CString objects.

Use the GetBuffer and ReleaseBuffer member functions when you need to directly access a CString as a nonconstant pointer to char (char* instead of a const char*).

CString objects follow "value semantics." A CString object represents a unique value. Think of a CString as an actual string, not as a pointer to a string.

Where possible, allocate CString objects on the frame rather than on the heap. This saves memory and simplifies parameter passing.

#include <afx.h>


CString Class Members
  Class Members

Construction/Destruction — Public Members

»CString«	Constructs CString objects in various ways.
»~CString«	Destroys a CString object.
The String as an Array — Public Members

»GetLength«	Returns the number of characters in a CString object.
»IsEmpty«	Tests whether the length of a CString object is 0.
»Empty«	Forces a string to have 0 length.
»GetAt«	Returns the character at a given position.
»operator [ ]«	Returns the character at a given position — operator substitution for GetAt.
»SetAt«	Sets a character at a given position.
»operator const char* ()«	Directly accesses characters stored in a CString object.
Assignment/Concatenation — Public Members

»operator =«	Assigns a new value to a CString object.
»operator +«	Concatenates two strings and returns a new string.
»operator +=«	Concatenates a new string to the end of an existing string.
Comparison — Public Members

»operator ==, <, etc.«	Comparison operators (ASCII, case sensitive).
»Compare«	Compares two strings (ASCII, case sensitive).
»CompareNoCase«	Compares two strings (ASCII, case insensitive).
»Collate«	Compares two strings with proper language-dependent ordering.
Extraction — Public Members

»Mid«	Extracts the middle part of a string (like the Basic MID$ command).
»Left«	Extracts the left part of a string (like the Basic LEFT$ command).
»Right«	Extracts the right part of a string (like the Basic RIGHT$ command).
»SpanIncluding«	Extracts a substring that contains only the characters in a set.
»SpanExcluding«	Extracts a substring that contains only the characters not in a set.
Other Conversions — Public Members

»MakeUpper«	Converts all the characters in this string to uppercase characters.
»MakeLower«	Converts all the characters in this string to lowercase characters.
»MakeReverse«	Reverses the characters in this string.
Searching — Public Members

»Find«	Finds a character or substring inside a larger string.
»ReverseFind«	Finds a character inside a larger string; starts from the end.
»FindOneOf«	Finds the first matching character from a set.
Archive/Dump — Public Members

»operator <<«	Inserts a CString object to an archive or dump context.
»operator >>«	Extracts a CString object from an archive.
Buffer Access — Public Members

»GetBuffer«	Returns a pointer to the characters in the CString.
»GetBufferSetLength«	Returns a pointer to the characters in the CString, truncating to the specified length.
»ReleaseBuffer«	Yields control of the buffer returned by GetBuffer.
Windows-Specific — Public Members

»LoadString«	Loads an existing CString object from a Windows resource.
»AnsiToOem«	Makes an in-place conversion from the ANSI character set to the OEM character set.
»OemToAnsi«	Makes an in-place conversion from the OEM character set to the ANSI character set.


CString Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CString::AnsiToOem

void AnsiToOem();

Remarks

Converts all the characters in this CString object from the ANSI character set to the OEM character set. See the IBM PC Extended Character Set table and the ANSI table in the Programmer's Reference in the Windows Software Development Kit (SDK).

This function is available only in the Windows compiled version of the Microsoft Foundation Class Library, and it is declared in AFX.H only if _WINDOWS is defined.

See Also

»CString::OemToAnsi«

 Example

// example for CString::AnsiToOem

CString s( '\265' );  // Octal ANSI code for '1/2'
s.AnsiToOem();
ASSERT( s == "\253" ); // Octal OEM code for '1/2'


  CString::Collate

int Collate( const char* psz ) const;

psz    The other string used for comparison.

Remarks

Performs a locale-specific comparison of two strings; uses the run-time function strcoll. »Compare« performs a faster, ASCII-only comparison.

A CString object can be used as the argument because the class provides the appropriate conversion operator.

Return Value

The function returns 0 if the strings are identical, −1 if this CString object is less than psz, or 1 if this CString object is greater than psz.

See Also

»CString::Compare«, »CString::CompareNoCase«

 Example

// example for CString::Collate

CString s1( "abc" );
CString s2( "abd" );
ASSERT( s1.Collate( s2 ) == -1 );


  CString::Compare

int Compare( const char* psz ) const;

psz    The other string used for comparison.

Remarks

Compares this CString object with another string, character by character; uses the run-time function strcmp. If you need a language-specific comparison, use the »Collate« member function.

Return Value

The function returns 0 if the strings are identical, −1 if this CString object is less than psz, or 1 if this CString object is greater than psz.

See Also

»CString::CompareNoCase«, »CString::Collate«

 Example

// example for CString::Compare

CString s1( "abc" );
CString s2( "abd" );
ASSERT( s1.Compare( s2 ) == -1 ); // Compare with another CString.
ASSERT( s1.Compare( "abe" ) == -1 ); // Compare with a char * string.


  CString::CompareNoCase

int CompareNoCase( const char* psz ) const;

psz    The other string used for comparison.

Remarks

Compares this CString object with another string, character by character; uses the run-time function stricmp. The algorithm for deciding case applies only to ASCII characters: 'A' == 'a' -> 'Z' == 'z'.

If you need a language-specific comparison, use the »Collate« member function.

Return Value

The function returns 0 if the strings are identical (ignoring case), −1 if this CString object is less than psz (ignoring case), or 1 if this CString object is greater than psz (ignoring case).

See Also

»CString::Compare«, »CString::Collate«

 Example

// example for CString::CompareNoCase

CString s1( "abc" );
CString s2( "ABD" );
ASSERT( s1.CompareNoCase( s2 ) == -1 ); // Compare with a CString.
ASSERT( s1.Compare( "ABE" ) == -1 ); // Compare with a char * string.


  CString::CString

CString();

CString( const CString& stringSrc )
throw( CMemoryException );

CString( const char* psz )
throw( CMemoryException );

CString( char ch, int nRepeat = 1 )
throw( CMemoryException );

CString( const char* pch, int nLength )
throw( CMemoryException );

CString( const char FAR* lpsz )
throw( CMemoryException );

CString( const char FAR* lpch, int nLength )
throw( CMemoryException );

stringSrc    An existing CString object to be copied into this CString object.

psz    A null-terminated string to be copied into this CString object.

ch    A single character to be repeated nRepeat times.

nRepeat    The repeat count for ch.

pch    A pointer to an array of characters of length nLength, not null-terminated.

nLength    A count of the number of characters in pch.

lpsz    A far pointer to a null-terminated ASCII string.

lpch    A far pointer to an array of characters of length nLength.

Remarks

Each of these constructors initializes a new CString object with the specified data.

Because the constructors copy the input data into new allocated storage, you should be aware that memory exceptions may result.

Note that some of these constructors act as conversion functions. This allows you to substitute, for example, a char* where a CString object is expected.

See Also

»CString::operator =«, »CString Exception Cleanup«

 Example

// example for CString::CString

CString s1;                    // Empty string
CString s2( "cat" );           // From a C string literal
CString s3 = s2;               // Copy constructor
CString s4( s2 + " " + s3 );   // From a string expression

CString s5( 'x' );             // s5 = "x"
CString s6( 'x', 6 );          // s6 = "xxxxxx"

CString city = "Philadelphia"; // NOT the assignment operator


  CString::~CString

~CString();

Remarks

Releases allocated memory used to store the string's character data.


  CString::Empty

void Empty();

Remarks

Makes this CString object an empty string and frees memory as appropriate.

See Also

»CString::IsEmpty«, »CString Exception Cleanup«

 Example

// example for CString::Empty

CString s1( "abc" );
CString s2;
s1.Empty();
ASSERT( s1 == s2 );


  CString::Find

int Find( char ch ) const;

int Find( const char* pszSub ) const;

ch    A single character to search for.

pszSub    A substring to search for.

Remarks

Searches this string for the first match of a substring. The function is overloaded to accept both single characters (similar to the run-time function strchr) and strings (similar to strstr).

Return Value

The zero-based index of the first character in this CString object that matches the requested substring or characters; −1 if the substring or character is not found.

See Also

»CString::ReverseFind«, »CString::FindOneOf«

 Example

// example for CString::Find

CString s( "abcdef" );
ASSERT( s.Find( 'c' ) == 2 );
ASSERT( s.Find( "de" ) == 3 );


  CString::FindOneOf

int FindOneOf( const char* pszCharSet ) const;

pszCharSet    String containing characters for matching.

Remarks

Searches this string for the first character that matches any character contained in pszCharSet.

Return Value

The zero-based index of the first character in this string that is also in pszCharSet; −1 if there is no match.

See Also

»CString::Find«

 Example

// example for CString::FindOneOf

CString s( "abcdef" );
ASSERT( s.FindOneOf( "xd" ) == 3 ); // 'd' is first match


  CString::GetAt

char GetAt( int nIndex ) const;

nIndex    Zero-based index of the character in the CString object. The nIndex parameter must be greater than or equal to 0 and less than the value returned by GetLength. The Debug version of the Microsoft Foundation Class Library validates the bounds of nIndex; the Release version will not.

Remarks

You can think of a CString object as an array of characters. The GetAt member function returns a single character specified by an index number. The overloaded subscript ([ ]) operator is a convenient alias for GetAt.

Return Value

A char containing the character at the specified position in the string.

See Also

»CString::SetAt«, »CString::GetLength«, »CString::operator [ ]«

 Example

// example for CString::GetAt

CString s( "abcdef" );
ASSERT( s.GetAt(2) == 'c' );


  CString::GetBuffer

char* GetBuffer( int nMinBufLength )
throw( CMemoryException );

nMinBufLength    The minimum size of the CString character buffer in bytes. You do not need to allow space for a null terminator.

Remarks

Returns a pointer to the internal character buffer for the CString object. The returned pointer to char is not const and thus allows direct modification of CString contents.

If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.

The address returned by GetBuffer is invalid after the call to ReleaseBuffer or any other CString operation.

The buffer memory will be freed automatically when the CString object is destroyed.

Note that if you keep track of the string length yourself, you need not append the terminating null byte. You must, however, specify the final string length when you release the buffer with ReleaseBuffer, or you can pass −1 for the length and ReleaseBuffer will perform a strlen on the buffer to determine its length.

Return Value

A char pointer to the object's (usually null-terminated) ASCII character buffer.

See Also

»CString::GetBufferSetLength«, »CString::ReleaseBuffer«

 Example

// example for CString::GetBuffer

CString s;
char* p = s.GetBuffer(10); // Allocate space for 10 characters.
s = "abcdefg"; // p is still valid because length of s is 7
       // characters.
p[1] = 'B'; // Change 'b' to 'B'.
#ifdef _DEBUG
afxDump << "char* p " << (void*) p << ":" << p << "\n";
#endif
char* q = s.GetBuffer(12);  // Get a new, larger buffer.
// q is a different address from p, but the string is the same.
#ifdef _DEBUG
afxDump << "char* q " << (void*) q << ":" << q << "\n";
#endif
s += "hij";  // String length is still smaller than 12.
#ifdef _DEBUG
afxDump << "char* q " << (void*) q << ":" << q << "\n";
#endif
s += "klmnop";  // Now it is larger than 12, so the characters
        // are moved, and q is no longer valid.
#ifdef _DEBUG
afxDump << "char* q " << (void*) q << ":" << q << "\n";
afxDump << "CString s " << s << "\n"; // s contains
  // "aBcdefghijklmnop".
#endif
s.ReleaseBuffer();


  CString::GetBufferSetLength

char* GetBufferSetLength( int nNewLength )
throw( CMemoryException );

nNewLength    The exact size of the CString character buffer in bytes.

Remarks

Returns a pointer to the internal character buffer for the CString object, truncating or growing its length if necessary to exactly match the length specified in nNewLength. The returned pointer to char is not const and thus allows direct modification of CString contents.

If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.

The address returned by GetBuffer is invalid after the call to ReleaseBuffer or any other CString operation.

The buffer memory will be freed automatically when the CString object is destroyed.

Note that if you keep track of the string length yourself, you need not append the terminating null byte. You must, however, specify the final string length when you release the buffer with ReleaseBuffer, or you can pass −1 for the length and ReleaseBuffer will perform a strlen on the buffer to determine its length.

Return Value

A char pointer to the object's (usually null-terminated) ASCII character buffer.

See Also

»CString::GetBuffer«, »CString::ReleaseBuffer«


  CString::GetLength

int GetLength() const;

Remarks

Returns a count of the characters in this CString object. The count does not include a null terminator.

See Also

»CString::IsEmpty«

 Example

// example for CString::GetLength

CString s( "abcdef" );
ASSERT( s.GetLength() == 6 );


  CString::IsEmpty

BOOL IsEmpty() const;

Remarks

Tests a CString object for the empty condition.

Return Value

Nonzero if the CString object has 0 length; otherwise 0.

See Also

»CString::GetLength«

 Example

// example for CString::IsEmpty

CString s;
ASSERT( s.IsEmpty() );


  CString::Left

CString Left( int nCount ) const
throw( CMemoryException );

nCount    The number of characters to extract from this CString object.

Remarks

Extracts the first (that is, leftmost) nCount characters from this CString object and returns a copy of the extracted substring. If nCount exceeds the string length, then the entire string is extracted.

Left is similar to the Basic LEFT$ command (except that indexes are zero-based).

Return Value

A CString object containing a copy of the specified range of characters. Note that the returned CString object may be empty.

See Also

»CString::Mid«, »CString::Right«

 Example

// example for CString::Left

CString s( "abcdef" );
ASSERT( s.Left(3) == "abc" );


  CString::LoadString

BOOL LoadString( UINT nID )
throw( CMemoryException );

nID    A Windows string resource ID.

Remarks

Reads a Windows string resource, identified by nID, into an existing CString object. The maximum string size is 255 characters.

This function is declared in AFX.H only if _WINDOWS is defined. Its use requires the Windows-compiled version of the Microsoft Foundation classes, and it is normally used with AFXWIN.H.

Return Value

Nonzero if resource load was successful; otherwise 0.

 Example

// example for CString::LoadString

#define IDS_FILENOTFOUND 1
CString s;
s.LoadString( IDS_FILENOTFOUND );


  CString::MakeLower

void MakeLower();

Remarks

Converts this CString object to a lowercase string.

See Also

»CString::MakeUpper«

 Example

// example for CString::MakeLower

CString s( "ABC" );
s.MakeLower();
ASSERT( s == "abc" );


  CString::MakeReverse

void MakeReverse();

Remarks

Reverses the order of the characters in this CString object.

 Example

CString s( "abc" );
s.MakeReverse();
ASSERT( s == "cba" );


  CString::MakeUpper

void MakeUpper();

Remarks

Converts this CString object to an uppercase string.

See Also

»CString::MakeLower«

 Example

// example for CString::MakeReverse

CString s( "abc" );
s.MakeUpper();
ASSERT( s == "ABC" );


  CString::Mid

CString Mid( int nFirst ) const
throw( CMemoryException );

CString Mid( int nFirst, int nCount ) const
throw( CMemoryException );

nFirst    The zero-based index of the first character in this CString object that is to be included in the extracted substring.

nCount    The number of characters to extract from this CString object. If this parameter is not supplied, then the remainder of the string is extracted.

Remarks

Extracts a substring of length nCount characters from this CString object, starting at position nFirst (zero-based). The function returns a copy of the extracted substring.

Mid is similar to the Basic MID$ command (except that indexes are zero-based).

Return Value

A CString object that contains a copy of the specified range of characters. Note that the returned CString object may be empty.

See Also

»CString::Left«, »CString::Right«

 Example

// example for CString::MakeUpper

CString s( "abcdef" );
ASSERT( s.Mid( 2, 3 ) == "cde" );


  CString::OemToAnsi

void OemToAnsi();

Remarks

Converts all the characters in this CString object from the OEM character set to the ANSI character set. See the IBM PC Extended Character Set table and the ANSI table in the Programmer's Reference in the Windows SDK.

This function is available only in the Windows-compiled library of the Microsoft Foundation classes and is declared in AFX.H only if _WINDOWS is defined.

See Also

»CString::AnsiToOem«

 Example

// example for CString::Mid

CString s( '\253' );  // Octal OEM code for '1/2'
s.OemToAnsi();
ASSERT( s == "\265" ); // Octal ANSI code for '1/2'


  CString::ReleaseBuffer

void ReleaseBuffer( int nNewLength = −1 );

nNewLength    The new length of the string in characters, not counting a null terminator. If the string is null-terminated, the −1 default value sets the CString size to the current length of the string.

Remarks

Use ReleaseBuffer to end use of a buffer allocated by GetBuffer.

If you know that the string in the buffer is null-terminated, you can omit the nNewLength argument. If your string is not null-terminated, then use nNewLength to specify its length.

The address returned by GetBuffer is invalid after the call to ReleaseBuffer or any other CString operation.

See Also

»CString::GetBuffer«

 Example

// example for CString::OemToAnsi

CString s;
char* p = s.GetBuffer( 1024 );
s = "abc";
ASSERT( s.GetLength() == 3 ); // String length = 3
s.ReleaseBuffer();  // Surplus memory released, p is now invalid.
ASSERT( s.GetLength() == 3 ); // Length still 3


  CString::ReverseFind

int ReverseFind( char ch ) const;

ch    The character to search for.

Remarks

Searches this CString object for the last match of a substring. The function is similar to the run-time function strrchr.

Return Value

The index of the last character in this CString object that matches the requested character; −1 if the character is not found.

See Also

»CString::Find«, »CString::FindOneOf«

 Example

CString s( "abcabc" );
ASSERT( s.ReverseFind( 'b' ) == 4 );


  CString::Right

CString Right( int nCount ) const
throw( CMemoryException );

nCount    The number of characters to extract from this CString object.

Remarks

Extracts the last (that is, rightmost) nCount characters from this CString object and returns a copy of the extracted substring. If nCount exceeds the string length, then the entire string is extracted.

Right is similar to the Basic RIGHT$ command (except that indexes are zero-based).

Return Value

A CString object that contains a copy of the specified range of characters. Note that the returned CString object may be empty.

See Also

»CString::Mid«, »CString::Left«

 Example

// example for CString::ReverseFind

CString s( "abcdef" );
ASSERT( s.Right(3) == "def" );


  CString::SetAt

void SetAt( int nIndex, char ch );

nIndex    Zero-based index of the character in the CString object. The nIndex parameter must be greater than or equal to 0 and less than the value returned by GetLength. The Debug version of the Microsoft Foundation Class Library will validate the bounds of nIndex; the Release version will not.

ch    The character to insert. Must not be '\0'.

Remarks

You can think of a CString object as an array of characters. The SetAt member function overwrites a single character specified by an index number. SetAt will not enlarge the string if the index exceeds the bounds of the existing string.

See Also

»CString::GetAt«, »CString::operator [ ]«


  CString::SpanExcluding

CString SpanExcluding( const char* pszCharSet ) const
throw( CMemoryException );

pszCharSet    A string interpreted as a set of characters.

Remarks

Extracts the largest substring that excludes only the characters in the specified set pszCharSet; starts from the first character in this CString object.

If the first character of the string is included in the character set, then SpanExcluding returns an empty string.

Return Value

A copy of the substring that contains only characters not in pszCharSet.

See Also

»CString::SpanIncluding«


  CString::SpanIncluding

CString SpanIncluding( const char* pszCharSet ) const
throw( CMemoryException );

pszCharSet    A string interpreted as a set of characters.

Remarks

Extracts the largest substring that contains only the characters in the specified set pszCharSet; starts from the first character in this CString object.

If the first character of the string is not in the character set, then SpanIncluding returns an empty string.

Return Value

A copy of the substring that contains only characters in pszCharSet.

See Also

»CString::SpanExcluding«


CString Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CString::operator =

const CString& operator =( const CString& stringSrc )
throw( CMemoryException );

const CString& operator =( const char* psz )
throw( CMemoryException );

const CString& operator =( char ch )
throw( CMemoryException );

Remarks

The CString assignment (=) operator reinitializes an existing CString object with new data. If the destination string (that is, the left side) is already large enough to store the new data, no new memory allocation is performed.

You should be aware that memory exceptions may occur whenever you use the assignment operator because new storage is often allocated to hold the resulting CString object.

See Also

»CString::CString«

 Example

// example for CString::ReverseFind

CString s1, s2;               // Empty CString objects

s1 = "cat";                   // s1 = "cat"
s2 = s1;                      // s1 and s2 each = "cat"
s1 = "the " + s1;             // Or expressions
s1 = 'x';                     // Or just individual characters


  CString::operator const char* ()

operator const char* () const;

Remarks

This useful casting operator provides an efficient method to access the null-terminated C string contained in a CString object.  No characters are copied; only a pointer is returned.

Be careful with this operator. If you change a CString object after you have obtained the character pointer, you may cause a reallocation of memory that invalidates the pointer.

Return Value

A character pointer if the cast was successful; otherwise a null pointer.


CString::operators <<, >>
  CString::operator <<, >>

friend CArchive& operator <<( CArchive& ar, const CString& string )
throw( CArchiveException );

friend CArchive& operator >>( CArchive& ar, CString& string )
throw( CArchiveException );

friend CDumpContext& operator <<( CDumpContext& dc,
const CString& string );

Remarks

The CString insertion (<<) operator supports diagnostic dumping and storing to an archive. The extraction (>>) operator supports loading from an archive.

The CDumpContext operators are valid only in the Debug version of the Microsoft Foundation Class Library.

 Example

// example for CString::Right

// Operator <<, >> example
extern CArchive ar;
CString s( "abc" );
#ifdef _DEBUG
afxDump << s;  // Prints the value (abc)
afxDump << &s;  // Prints the address
#endif

if( ar.IsLoading() )
ar >> s;
else
ar << s;


  CString::operator +

friend CString operator +( const CString& string1, const CString& string2 )
throw( CMemoryException );

friend CString operator +( const CString& string, char ch )
throw( CMemoryException );

friend CString operator +( char ch, const CString& string )
throw( CMemoryException );

friend CString operator +( const CString& string, const char* psz )
throw( CMemoryException );

friend CString operator +( const char* psz, const CString& string )
throw( CMemoryException );

Remarks

The + concatenation operator joins two strings and returns a CString object. One of the two argument strings must be a CString object. The other can be a character pointer or a character.

You should be aware that memory exceptions may occur whenever you use the concatenation operator since new storage may be allocated to hold temporary data.

You must ensure that the maximum length limit is not exceeded. The Debug version of the Microsoft Foundation Class Library asserts when it detects strings that are too long.

Return Value

A CString object that is the temporary result of the concatenation. This return value makes it possible to combine several concatenations in the same expression.

See Also

»CString::operator +=«

 Example

// example for CString::operator =

CString s1( "abc" );
CString s2( "def" );
ASSERT( (s1 + s2 ) == "abcdef" );
CString s3;
s3 = CString( "abc" ) + "def" ; // Correct
// s3 = "abc" + "def"; // Wrong! One of the arguments must be a CString.


  CString::operator +=

const CString& operator +=( const CString& string )
throw( CMemoryException );

const CString& operator +=( char ch )
throw( CMemoryException );

const CString& operator +=( const char* psz )
throw( CMemoryException );

Remarks

The += concatenation operator joins characters to the end of this string. The operator accepts another CString object, a character pointer, or a single character.

You should be aware that memory exceptions may occur whenever you use this concatenation operator because new storage may be allocated for characters added to this CString object.

You must ensure that the maximum length limit is not exceeded. The Debug version of the Microsoft Foundation Class Library asserts when it detects strings that are too long.

See Also

»CString::operator +«

 Example

// Operator <<, >> example
CString s( "abc" );
ASSERT( ( s += "def" ) == "abcdef" );


  CString Comparison Operators

BOOL operator ==( const CString& s1, const CString& s2 );

BOOL operator ==( const CString& s1, const char* s2 );

BOOL operator ==( const char* s1, const CString& s2 );

BOOL operator !=( const CString& s1, const CString& s2 );

BOOL operator !=( const CString& s1, const char* s2 );

BOOL operator !=( const char* s1, const CString& s2 );

BOOL operator <( const CString& s1, const CString& s2 );

BOOL operator <( const CString& s1, const char* s2 );

BOOL operator <( const char* s1, const CString& s2 );

BOOL operator >( const CString& s1, const CString& s2 );

BOOL operator >( const CString& s1, const char* s2 );

BOOL operator >( const char* s1, const CString& s2 );

BOOL operator <=( const CString& s1, const CString& s2 );

BOOL operator <=( const CString& s1, const char* s2 );

BOOL operator <=( const char* s1, const CString& s2 );

BOOL operator >=( const CString& s1, const CString& s2 );

BOOL operator >=( const CString& s1, const char* s2 );

BOOL operator >=( const char* s1, const CString& s2 );

Remarks

These comparison operators compare two CString objects, and they compare a CString object with an ordinary null-terminated C string. The operators are a convenient substitute for the case-sensitive Compare member function.

Return Value

Nonzero if the strings meet the comparison condition; otherwise 0.

 Example

// example for CString::operator +

CString s1( "abc" );
CString s2( "abd" );
ASSERT( s1 < s2 ); // Operator is overloaded for both.
ASSERT( "ABC" < s1 ); // CString and char*
ASSERT( s2 > "abe" );


  CString::operator [ ]

char operator [ ]( int nIndex ) const;

Remarks

You can think of a CString object as an array of characters. The overload subscript ([ ]) operator returns a single character specified by the zero-based index in nIndex. This operator is a convenient substitute for the GetAt member function.

You can use the subscript ([ ]) operator on the right side of an expression (r-value semantics), but you cannot use it on the left side of an expression (l-value semantics). That is, you can use this operator to get characters in a CString, but you cannot use it to set characters in the CString.

See Also

»CString::GetAt«, »CString::SetAt«

 Example

// example for CString::operator +=

CString s( "abc" );
ASSERT( s[1] == 'b' );


  Application Notes

The CString Application Notes section offers useful information on:

•	»CString Exception Cleanup«

•	»CString Argument Passing«


  CString Exception Cleanup

Memory Leaks

If you notice that the Microsoft Foundation Class Library diagnostic memory allocator is reporting leaks for non-CObject memory blocks, check your exception-processing logic to see if CString objects are being cleaned up properly.

The CString class is typical in that its constructor and member functions allocate memory that must be freed by the destructor. CString is unique, however, in that instances are often allocated on the frame rather than on the heap. When a frame-allocated CString object goes out of scope, its destructor is called invisibly without need for a delete statement.

Whether you explicitly destroy an object or not, you must be sure that the destructor call is not bypassed by uncaught exceptions. For frame-allocated (and heap-allocated) CString objects, use a CATCH statement to channel execution through the end of the function that contains the CString allocation.

 Example

// example for CString comparison operators

This is an example of incorrect programming.

void TestFunction1()
{
CString s1 = "test";
OtherFunction();   // OtherFunction may raise an exception.
   // This point not passed if an exception occurred.
   // s1's destructor called here (frees character storage for
   // "test")
}

You must add TRY/CATCH code to free the string character data in response to memory exceptions.

Now the program has been improved to properly handle exceptions.

void TestFunction2()
{
CString s1;
TRY
{
s1 = "test";
OtherFunction(); // OtherFunction may raise an exception.
}
CATCH( CException, e )
{
s1.Empty();                // Frees up associated data
THROW_LAST()
}
END_CATCH
}


  CString Argument Passing

Argument-Passing Conventions

When you define a class interface, you must determine the argument-passing convention for your member functions. There are some standard rules for passing and returning CString objects. If you follow these rules, you will have efficient, correct code.

Strings as Function Inputs

If a string is an input to a function, in most cases it is best to declare the string function parameter as const char*. Convert to a CString object as necessary within the function using constructors and assignment operators. If the string contents are to be changed by a function, declare the parameter as a nonconstant CString reference (CString&).

Strings as Function Outputs

Normally you can return CString objects from functions since CString objects follow value semantics like primitive types. To return a read-only string, use a constant CString reference (const CString&).

 Example

// example for CString::operator [ ]

class CName : public CObject
{
private:
CString m_firstName;
char m_middleInit;
CString m_lastName;
public:
CName() {}
void SetData( const char* fn, const char mi, const char* ln )
{
m_firstName = fn;
m_middleInit = mi;
m_lastName = ln;
}
void GetData( CString& cfn, char mi, CString& cln )
{
cfn = m_firstName;
mi = m_middleInit;
cln = m_lastName;
}
CString GetLastName()
{
return m_lastName;
}
};
CName name;
CString last, first;
char middle;
name.SetData( "John", 'Q', "Public" );
ASSERT( name.GetLastName() == "Public" );
name.GetData( first, middle, last );
ASSERT( ( first == "John" ) && ( last == "Public" ) );
}
return 0;
}


CStringArray
  class CStringArray : public CObject

The CStringArray class supports arrays of CString objects.

The member functions of CStringArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a return value, substitute a CString. Wherever you see a CObject pointer as a function parameter, substitute a const pointer to char.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

CString CStringArray::GetAt( int <nIndex> ) const;

and

void SetAt( int <nIndex>, CObject* <newElement> )

translates to

void SetAt( int <nIndex>, const char* <newElement> )

CStringArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of CString objects is stored to an archive, either with an overloaded insertion operator or with the Serialize member function, each element is, in turn, serialized.

If you need a dump of individual string elements in the array, you must set the depth of the dump context to 1 or greater.

When a CString array is deleted, or when its elements are removed, string memory is freed as appropriate.

#include <afxcoll.h>


CStringArray Class Members
  Class Members

Construction/Destruction — Public Members

»CStringArray«	Constructs an empty array for CString objects.
»~CStringArray«	Destroys a CStringArray object.
Bounds — Public Members

»GetSize«	Gets number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array not allowed to grow.
»ElementAt«	Returns a temporary reference to the element pointer within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CStringList
  class CStringList : public CObject

The CStringList class supports lists of CString objects. All comparisons are done by value, meaning that the characters in the string are compared instead of the addresses of the strings.

The member functions of CStringList are similar to the member functions of class »CObList«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a return value, substitute a CString. Wherever you see a CObject pointer as a function parameter, substitute a const pointer to char.

CObject*& CObList::GetHead() const;

for example, translates to

CString& CStringList::GetHead() const;

and

POSITION AddHead( CObject* <newElement> );

translates to

POSITION AddHead( const char* <newElement> );

CStringList incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If a list of CString objects is stored to an archive, either with an overloaded insertion operator or with the Serialize member function, each CString element is, in turn, serialized.

If you need a dump of individual CString elements, you must set the depth of the dump context to 1 or greater.

When a CStringList object is deleted, or when its elements are removed, the CString objects are deleted as appropriate.

#include <afxcoll.h>


CStringList Class Members
  Class Members

Construction/Destruction — Public Members

»CStringList«	Constructs an empty list for CString objects.
Head/Tail Access — Public Members

»GetHead«	Returns the head element of the list (cannot be empty).
»GetTail«	Returns the tail element of the list (cannot be empty).
Operations — Public Members

»RemoveHead«	Removes the element from the head of the list.
»RemoveTail«	Removes the element from the tail of the list.
»AddHead«	Adds an element (or all the elements in another list) to the head of the list (makes a new head).
»AddTail«	Adds an element (or all the elements in another list) to the tail of the list (makes a new tail).
»RemoveAll«	Removes all the elements from this list.
Iteration — Public Members

»GetHeadPosition«	Returns the position of the head element of the list.
»GetTailPosition«	Returns the position of the tail element of the list.
»GetNext«	Gets the next element for iterating.
»GetPrev«	Gets the previous element for iterating.
Retrieval/Modification — Public Members

»GetAt«	Gets the element at a given position.
»SetAt«	Sets the element at a given position.
»RemoveAt«	Removes an element from this list as specified by position.
Insertion — Public Members

»InsertBefore«	Inserts a new element before a given position.
»InsertAfter«	Inserts a new element after a given position.
Searching — Public Members

»Find«	Gets the position of an element specified by string value.
»FindIndex«	Gets the position of an element specified by a zero-based index.
Status — Public Members

»GetCount«	Returns the number of elements in this list.
»IsEmpty«	Tests for the empty list condition (no elements).


CTime
  class CTime

A CTime object represents an absolute time and date. The CTime class incorporates the ANSI time_t data type and its associated run-time functions, including the ability to convert to and from a Gregorian date and 24-hour time.

CTime values are based on universal coordinated time (UCT), which is equivalent to Greenwich mean time (GMT). The local time zone is controlled by the TZ environment variable.

See the Run-Time Library Reference for more information on the time_t data type and the run-time functions that are used by CTime. Note that CTime was the strftime function, which is not supported for Windows dynamic-link libraries (DLL). Therefore, CTime cannot be used in Windows DLLs.

A companion class, »CTimeSpan«, represents a time interval — the difference between two CTime objects.

The CTime and CTimeSpan classes are not designed for derivation. Because there are no virtual functions, the size of CTime and CTimeSpan objects is exactly 4 bytes. Most member functions are inline.

#include <afx.h>

See Also

Run-time functions: asctime, _ftime, gmtime, localtime, strftime, time


CTime Class Members
  Class Members

Construction/Destruction — Public Members

»CTime«	Constructs CTime objects in various ways.
»GetCurrentTime«	Creates a CTime object that represents the current time (static member function).
Extraction — Public Members

»GetTime«	Returns a time_t that corresponds to this CTime object.
»GetYear«	Returns the year that this CTime object represents.
»GetMonth«	Returns the month that this CTime object represents (1 through 12).
»GetDay«	Returns the day that this CTime object represents (1 through 31).
»GetHour«	Returns the hour that this CTime object represents (0 through 23).
»GetMinute«	Returns the minute that this CTime object represents (0 through 59).
»GetSecond«	Returns the second that this CTime object represents (0 through 59).
»GetDayOfWeek«	Returns the day of the week (1 for Sunday, 2 for Monday, and so forth).
Conversion — Public Members

»GetGmtTm«	Breaks down a CTime object into components — based on UCT.
»GetLocalTm«	Breaks down a CTime object into components — based on the local time zone.
»Format«	Converts a CTime object into a formatted string — based on the local time zone.
»FormatGmt«	Converts a CTime object into a formatted string — based on UCT.
Operators — Public Members

»operator =«	Assigns new time values.
»operator +, −«	Add and subtract CTimeSpan and CTime objects.
»operator +=, −=«	Add and subtract a CTimeSpan object to and from this CTime object.
»operator ==, < , etc.«	Compare two absolute times.
Archive/Dump — Public Members

»operator <<«	Outputs a CTime object to CArchive or CDumpContext.
»operator >>«	Inputs a CTime object from CArchive.


CTime Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CTime::CTime

CTime();

CTime( const CTime& timeSrc );

CTime( time_t time );

CTime( int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec );

CTime( WORD wDosDate, WORD wDosTime );

CTime( const SYSTEMTIME& sysTime );

CTime( const FILETIME& fileTime );

timeSrc    Indicates a CTime object that already exists.

time    Indicates a time value.

nYear, nMonth, nDay, nHour, nMin, nSec    Indicate year, month, day, hour, minute, and second.

wDosDate, wDosTime    Indicate the date and time in the form obtained through the
MS-DOS function _dos_getftime.

sysTime    Indicates the date and time retrieved from Windows NT. The fileTime parameter is a reference to a Windows NT FILETIME structure, which represents time as a 64-bit value, a more convenient format for internal storage than a SYSTEMTIME structure and the format used by Windows NT to represent the time of file creation.

fileTime    Indicates a file time stamp in Windows NT.

Remarks

All these constructors create a new CTime object initialized with the specified absolute time, based on the current time zone.

Each constructor is described below:

•	CTime();    Constructs a CTime object with a 0 (illegal) value. Note that 0 is an invalid time. This constructor allows you to define CTime object arrays. You should initialize such arrays with valid times prior to use.

•	CTime( const CTime& );    Constructs a CTime object from another CTime value.

•	CTime( time_t );    Constructs a CTime object from a time_t type.

•	CTime( int, int, etc.);    Constructs a CTime object from local time components with each component constrained to the following ranges:

Component	Range
nYear	1970−2038
nMonth	1−12
nDay	1−31
nHour	0−23
nMin	0−59
nSec	0−59
This constructor makes the appropriate conversion to UCT. The Debug version of the Microsoft Foundation Class Library asserts if one or more of the time-day components is out of range. It is your responsibility to validate the arguments prior to calling.

•	CTime( WORD, WORD );    Constructs a CTime object from a date and time in the form obtained through the MS-DOS function _dos_get ftime.

•	CTime( const SYSTEMTIME& );    Constructs a CTime object from a Windows NT SYSTEMTIME structure.

•	CTime( const FILETIME& );    Constructs a CTime object from a Windows NT FILETIME structure. You most likely will not use CTime FILETIME initialization directly. If you use a CFile object to manipulate a file, CFile::GetStatus retrieves the file time stamp for you via a CTime object initialized with a FILETIME structure.

SYSTEMTIME Structure

A Windows NT SYSTEMTIME structure has this form:

typedef struct _SYSTEMTIME {

WORD wYear;

WORD wMonth;

    WORD wDayOfWeek;

    WORD wDay;

    WORD wHour;

    WORD wMinute;

    WORD wSecond;

    WORD wMilliseconds;

} SYSTEMTIME;

Members

The SYSTEMTIME structure has the following members:

wYear    The current year

wMonth    The current month; January is 1

wDayOfWeek    The current day of the week; Sunday is 0, Monday is 1, etc.

wDay    The current day of the month

wHour    The current hour

wMinute    The current minute

wSecond    The current second

wMilliseconds    The current millisecond

FILETIME Structure

A Windows NT FILETIME structure has this form:

typedef struct _FILETIME {

    DWORD dwLowDateTime;   /* low 32 bits  */

    DWORD dwHighDateTime;  /* high 32 bits */

} FILETIME, *PFILETIME, *LPFILETIME;

Members

The FILETIME structure has the following members:

ateTidwLowDme    Specifies the low 32 bits of the file time.

dwHighDateTime    Specifies the high 32 bits of the file time.

 Example

// example for CTime::CTime

time_t osBinaryTime;  // C run-time time (defined in <time.h>)
time( &osBinaryTime ) ;  // Get the current time from the
                         // operating system.
CTime time1; // Empty CTime. (0 is illegal time value.)
CTime time2 = time1; // Copy constructor.
CTime time3( osBinaryTime );  // CTime from C run-time time
CTime time4( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999


  CTime::Format

CString Format( const char* pFormat );

pFormat    Specifies a formatting string similar to the printf formatting string. See the run-time function strftime for details.

Remarks

Generates a formatted string that corresponds to this CTime object. The time value is converted to local time.

Return Value

A CString that contains the formatted time.

See Also

»CTime::FormatGmt«

 Example

// example for CTime::Format

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
CString s = t.Format( "%A, %B %d, %Y" );
ASSERT( s == "Friday, March 19, 1999" );


  CTime::FormatGmt

CString FormatGmt( const char* pFormat );

pFormat    Specifies a formatting string similar to the printf formatting string. See the run-time function strftime for details.

Remarks

Generates a formatted string that corresponds to this CTime object. The time value is not converted and thus reflects UCT.

Return Value

A CString that contains the formatted time.

See Also

»CTime::Format«

 Example

See the example for »Format«.


  CTime::GetCurrentTime

static CTime PASCAL GetCurrentTime();

Remarks

Returns a CTime object that represents the current time.

 Example

// example for CTime::GetCurrentTime

CTime t = CTime::GetCurrentTime();


  CTime::GetDay

int GetDay() const;

Remarks

Returns the day of the month, based on local time, in the range 1 through 31.

See Also

»CTime::GetDayOfWeek«

 Example

// example for CTime::GetDay

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
ASSERT( t.GetDay() == 19 );
ASSERT( t.GetMonth() == 3 );
ASSERT( t.GetYear() == 1999 );


  CTime::GetDayOfWeek

int GetDayOfWeek() const;

Remarks

Returns the day of the week based on local time; 1 = Sunday, 2 = Monday, ..., 7 = Saturday.


  CTime::GetGmtTm

struct tm* GetGmtTm( struct tm* ptm = NULL ) const;

ptm    Points to a buffer that will receive the time data. If this pointer is NULL, an internal, statically allocated buffer is used. The data in this default buffer is overwritten as a result of calls to other CTime member functions.

Remarks

Gets a struct tm that contains a decomposition of the time contained in this CTime object. GetGmtTm returns UCT.

Return Value

A pointer to a filled-in struct tm as defined in the include file TIME.H. The members and the values they store are as follows:

•	tm_sec    Seconds

•	tm_min    Minutes

•	tm_hour    Hours (0−23)

•	tm_mday    Day of month (1−31)

•	tm_mon    Month (0−11; January = 0)

•	tm_year    Year (actual year minus 1900)

•	tm_wday    Day of week (1−7; Sunday = 1)

•	tm_yday    Day of year (0−365; January 1 = 0)

•	tm_isdst    Always 0

Note  The year in struct tm is in the range 70 to 138; the year in the CTime interface is in the range 1970 to 2038 (inclusive).

 Example

See the example for »GetLocalTm«.


  CTime::GetHour

int GetHour() const;

Remarks

Returns the hour, based on local time, in the range 0 through 23.

 Example

// example for CTime::GetHour

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
ASSERT( t.GetSecond() == 0 );
ASSERT( t.GetMinute() == 15 );
ASSERT( t.GetHour() == 22 );


  CTime::GetLocalTm

struct tm* GetLocalTm( struct tm* ptm = NULL ) const;

ptm    Points to a buffer that will receive the time data. If this pointer is NULL, an internal, statically allocated buffer is used. The data in this default buffer is overwritten as a result of calls to other CTime member functions.

Remarks

Gets a struct tm containing a decomposition of the time contained in this CTime object. GetLocalTm returns local time.

Return Value

A pointer to a filled-in struct tm as defined in the include file TIME.H. See »GetGmtTm« for the structure layout.

 Example

// example for CTime::GetLocalTm

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
struct tm* osTime;  // A pointer to a structure containing time
                    // elements.
osTime = t.GetLocalTm( NULL );
ASSERT( osTime->tm_mon == 2 ); // Note zero-based month!


  CTime::GetMinute

int GetMinute() const;

Remarks

Returns the minute, based on local time, in the range 0 through 59.

 Example

See the example for »GetHour«.


  CTime::GetMonth

int GetMonth() const;

Remarks

Returns the month, based on local time, in the range 1 through 12 (1 = January).

 Example

See the example for »GetDay«.


  CTime::GetSecond

int GetSecond() const;

Remarks

Returns the second, based on local time, in the range 0 through 59.

 Example

See the example for »GetHour«.


  CTime::GetTime

time_t GetTime() const;

Remarks

Returns a time_t value for the given CTime object.

See Also

»CTime::CTime«

 Example

// example for CTime::GetTime

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
time_t osBinaryTime = t.GetTime(); // time_t defined in <time.h>
printf( "time_t = %ld\n", osBinaryTime );


  CTime::GetYear

int GetYear() const;

Remarks

Returns the year, based on local time, in the range 1970 to 2038.

 Example

See the example for »GetDay«.


CTime Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CTime::operator =

const CTime& operator =( const CTime& timeSrc );

const CTime& operator =( time_t  t );

Remarks

These overloaded assignment operators copy the source time into this CTime object.

The internal time storage in a CTime object is independent of time zone. Time-zone conversion is not necessary during assignment.

See Also

»CTime::CTime«

 Example

// example for CTime::operator =

time_t osBinaryTime;  // C run-time time (defined in <time.h>)
CTime t1 = osBinaryTime; // Assignment from time_t
CTime t2 = t1; // Assignment from CTime


CTime::operator +, -
  CTime::operator +, −

CTime operator +( CTimeSpan timeSpan ) const;

CTime operator −( CTimeSpan timeSpan ) const;

CTimeSpan operator −( CTime time ) const;

Remarks

CTime objects represent absolute time. CTimeSpan objects represent relative time. The first two operators allow you to add and subtract CTimeSpan objects to and from CTime objects. The third allows you to subtract one CTime object from another to yield a CTimeSpan object.

 Example

// example for CTime::operator  +, -

CTime t1( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
CTime t2( 1999, 3, 20, 22, 15, 0 ); // 10:15PM March 20, 1999
CTimeSpan ts = t2 - t1;  // Subtract 2 CTimes
ASSERT( ts.GetTotalSeconds() == 86400L );
ASSERT( ( t1 + ts ) == t2 );  // Add a CTimeSpan to a CTime.
ASSERT( ( t2 - ts ) == t1 );  // Subtract a CTimeSpan from a CTime.


CTime::operator +=, -=
  CTime::operator +=, −=

const CTime& operator +=( CTimeSpan timeSpan );

const CTime& operator −=( CTimeSpan timeSpan );

Remarks

These operators allow you to add and subtract a CTimeSpan object to and from this CTime object.

 Example

// example for CTime::operator -=

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
t += CTimeSpan( 0, 1, 0, 0 ); // 1 hour exactly
ASSERT( t.GetHour() == 23 );


  CTime Comparison Operators

BOOL operator ==( CTime time ) const;

BOOL operator !=( CTime time ) const;

BOOL operator <( CTime time ) const;

BOOL operator >( CTime time ) const;

BOOL operator <=( CTime time ) const;

BOOL operator >=( CTime time ) const;

Remarks

These operators compare two absolute times and return nonzero if the condition is true; otherwise 0.

 Example

// example for CTime comparison operators

CTime t1 = CTime::GetCurrentTime();
CTime t2 = t1 + CTimeSpan( 0, 1, 0, 0 );    // 1 hour later
ASSERT( t1 != t2 );
ASSERT( t1 < t2 );
ASSERT( t1 <= t2 );


  CTime::operators <<, >>

friend CDumpContext& operator <<( CDumpContext& dc, CTime time );

friend CArchive& operator <<( CArchive& ar, CTime time );

friend CArchive& operator >>( CArchive& ar, CTime& rtime );

Remarks

The CTime insertion (<<) operator supports diagnostic dumping and storing to an archive. The extraction (>>) operator supports loading from an archive.

When you send a CTime object to the dump context, the local time is displayed in readable date-time format.

See Also

»CArchive«, »CDumpContext«

 Example

// example for CTime::operators <<, >>

CTime t( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999
afxDump << t << "\n"; // Prints 'CTime("Fri Mar 19 22:15:00 1999")'.

extern CArchive ar;
if( ar.IsLoading() )
  ar >> t;
else
  ar << t;


CTimeSpan
  class CTimeSpan

A CTimeSpan object represents a relative time span. The CTimeSpan class incorporates the ANSI time_t data type and its associated run-time functions. These functions convert seconds to various combinations of days, hours, minutes, and seconds.

A CTimeSpan object keeps time in seconds. Because the CTimeSpan object is stored as a signed number in 4 bytes, the maximum allowed span is approximately ± 68 years.

A companion class, »CTime«, represents an absolute time. A CTimeSpan is the difference between two CTime values.

The CTime and CTimeSpan classes are not designed for derivation. Because there are no virtual functions, the size of both CTime and CTimeSpan objects is exactly 4 bytes. Most member functions are inline.

#include <afx.h>

See Also

Run-time functions: asctime, _ftime, gmtime, localtime, strftime, time


CTimeSpan Class Members
  Class Members

Construction/Destruction — Public Members

»CTimeSpan«	Constructs CTimeSpan objects in various ways.
Extraction — Public Members

»GetDays«	Returns the number of complete days in this CTimeSpan.
»GetHours«	Returns the number of hours in the current day (−23 through 23).
»GetTotalHours«	Returns the total number of complete hours in this CTimeSpan.
»GetMinutes«	Returns the number of minutes in the current hour (−59 through 59).
»GetTotalMinutes«	Returns the total number of complete minutes in this CTimeSpan.
»GetSeconds«	Returns the number of seconds in the current minute (−59 through 59).
»GetTotalSeconds«	Returns the total number of complete seconds in this CTimeSpan.
Conversion — Public Members

»Format«	Converts a CTimeSpan into a formatted string.
Operators — Public Members

»operator =«	Assigns new time-span values.
»operator +, −«	Add and subtract CTimeSpan objects.
»operator +=, −=«	Add and subtract a CTimeSpan object to and from this CTimeSpan.
»operator ==, <, etc.«	Compare two relative time values.
Archive/Dump — Public Members

»operator <<«	Outputs a CTimeSpan object to CArchive or CDumpContext.
»operator >>«	Inputs a CTimeSpan object from CArchive.


CTimeSpan Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CTimeSpan::CTimeSpan

CTimeSpan();

CTimeSpan( const CTimeSpan& timeSpanSrc );

CTimeSpan( time_t time );

CTimeSpan( LONG lDays, int nHours, int nMins, int nSecs );

timeSpanSrc    A CTimeSpan object that already exists.

time    A time_t time value.

lDays, nHours, nMins, nSecs    Days, hours, minutes, and seconds, respectively.

Remarks

All these constructors create a new CTimeSpan object initialized with the specified relative time. Each constructor is described below:

•	CTimeSpan();    Constructs an uninitialized CTimeSpan object.

•	CTimeSpan( const CTimeSpan& );    Constructs a CTimeSpan object from another CTimeSpan value.

•	CTimeSpan( time_t );    Constructs a CTimeSpan object from a time_t type. This value should be the difference between two absolute time_t values.

•	CTimeSpan( LONG, int, int, int );    Constructs a CTimeSpan object from components with each component constrained to the following ranges:

Component	Range
lDays	0−25,000 (approximately)
nHours	0−23
nMins	0−59
nSecs	0−59
Note that the Debug version of the Microsoft Foundation Class Library asserts if one or more of the time-day components is out of range. It is your responsibility to validate the arguments prior to calling.

Example

// example for CTimeSpan::CTimeSpan

CTimeSpan ts1;  // Uninitialized time value
CTimeSpan ts2a( ts1 ); // Copy constructor
CTimeSpan ts2b = ts1; // Copy constructor again
CTimeSpan ts3( 100 ); // 100 seconds
CTimeSpan ts4( 0, 1, 5, 12 );    // 1 hour, 5 minutes, and 12 seconds


  CTimeSpan::Format

CString Format( const char* pFormat );

pFormat    A formatting string similar to the printf formatting string. Formatting codes, preceded by a percent (%) sign, are replaced by the corresponding CTimeSpan component. Other characters in the formatting string are copied unchanged to the returned string. The value and meaning of the formatting codes for Format are listed below:

•	%D    Total days in this CTimeSpan

•	%H    Hours in the current day

•	%M    Minutes in the current hour

•	%S    Seconds in the current minute

•	%%    Percent sign

Remarks

Generates a formatted string that corresponds to this CTimeSpan.

The Debug version of the library checks the formatting codes and asserts if the code is not in the table above.

Return Value

A CString object that contains the formatted time.

 Example

// example for CTimeSpan::Format

CTimeSpan ts( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
CString s = ts.Format( "Total days: %D, hours: %H, mins: %M, secs: %S" 	);
ASSERT( s == "Total days: 3, hours: 01, mins: 05, secs: 12" );


  CTimeSpan::GetDays

LONG GetDays() const;

Remarks

Returns the number of complete days. This value may be negative if the time span is negative.

Example

// example for CTimeSpan::GetDays

CTimeSpan ts( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
ASSERT( ts.GetDays() == 3 );


  CTimeSpan::GetHours

int GetHours() const;

Remarks

Returns the number of hours in the current day. The range is  −23 through 23.

 Example

// example for CTimeSpan::GetHours

CTimeSpan ts( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
ASSERT( ts.GetHours() == 1 );
ASSERT( ts.GetMinutes() == 5 );
ASSERT( ts.GetSeconds() == 12 );


  CTimeSpan::GetMinutes

int GetMinutes() const;

Remarks

Returns the number of minutes in the current hour. The range is  −59 through 59.

 Example

See the example for »GetHours«.


  CTimeSpan::GetSeconds

int GetSeconds() const;

Remarks

Returns the number of seconds in the current minute. The range is  −59 through 59.

 Example

See the example for »GetHours«.


  CTimeSpan::GetTotalHours

LONG GetTotalHours() const;

Remarks

Returns the total number of complete hours in this CTimeSpan.

 Example

// example for CTimeSpan::GetTotalHours

CTimeSpan ts( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
ASSERT( ts.GetTotalHours() == 73 );
ASSERT( ts.GetTotalMinutes() == 4385 );
ASSERT( ts.GetTotalSeconds() == 263112 );


  CTimeSpan::GetTotalMinutes

LONG GetTotalMinutes() const;

Remarks

Returns the total number of complete minutes in this CTimeSpan.

 Example

See the example for »GetTotalHours«.


  CTimeSpan::GetTotalSeconds

LONG GetTotalSeconds() const;

Remarks

Returns the total number of complete seconds in this CTimeSpan.

 Example

See the example for »GetTotalHours«.


CTimeSpan Operators
  Operators

To get information on a particular operator, double-click it in the Contents window.


  CTimeSpan::operator =

const CTimeSpan& operator =( const CTimeSpan& timeSpanSrc );

Remarks

The overloaded assignment operator copies the source CTimeSpan timeSpanSrc object into this CTimeSpan object.

See Also

»CTimeSpan::CTimeSpan«

 Example

// example for CTimeSpan::operator =

CTimeSpan ts1;
CTimeSpan ts2( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
ts1 = ts2;
ASSERT( ts1 == ts2 );


CTimeSpan::operators +, -
  CTimeSpan::operator +, −

CTimeSpan operator +( CTimeSpan timeSpan ) const;

CTimeSpan operator −( CTimeSpan timeSpan ) const;

Remarks

These two operators allow you to add and subtract CTimeSpan objects to and from each other.

 Example

// example for CTimeSpan::operator +, -

CTimeSpan ts1( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
CTimeSpan ts2( 100 ); // 100 seconds
CTimeSpan ts3 = ts1 + ts2;
ASSERT( ts3.GetSeconds() == 52 ); // 6 mins, 52 secs


CTimeSpan::operator +=, -=
  CTimeSpan::operator +=, −=

const CTimeSpan& operator +=( CTimeSpan timeSpan );

const CTimeSpan& operator −=( CTimeSpan timeSpan );

Remarks

These operators allow you to add and subtract a CTimeSpan object to and from this CTimeSpan.

 Example

// example for CTimeSpan::operator +=, -=

CTimeSpan ts1( 10 ); // 10 seconds
CTimeSpan ts2( 100 ); // 100 seconds
ts2 -= ts1;
ASSERT( ts2.GetTotalSeconds() == 90 );


  CTimeSpan Comparison Operators

BOOL operator ==( CTimeSpan timeSpan ) const;

BOOL operator !=( CTimeSpan timeSpan ) const;

BOOL operator <( CTimeSpan timeSpan ) const;

BOOL operator >( CTimeSpan timeSpan ) const;

BOOL operator <=( CTimeSpan timeSpan ) const;

BOOL operator >=( CTimeSpan timeSpan ) const;

Remarks

These operators compare two relative time values. They return nonzero if the condition is true; otherwise 0.

 Example

// example for CTimeSpan comparison operators

CTimeSpan ts1( 100 );
CTimeSpan ts2( 110 );
ASSERT( ( ts1 != ts2 ) && ( ts1 < ts2 ) && ( ts1 <= ts2 ) );


  CTimeSpan::operators <<, >>

friend CDumpContext& operator <<( CDumpContext& dc,
CTimeSpan timeSpan );

friend CArchive& operator <<( CArchive& ar, CTimeSpan timeSpan );

friend CArchive& operator >>( CArchive& ar, CTimeSpan& timeSpan );

Remarks

The CTimeSpan insertion (<<) operator supports diagnostic dumping and storing to an archive. The extraction (>>) operator supports loading from an archive.

When you send a CTimeSpan object to the dump context, the value is displayed in a human-readable format that shows days, hours, minutes, and seconds.

 Example

// example for CTimeSpan::operators <<, >>

CTimeSpan ts( 3, 1, 5, 12 ); // 3 days, 1 hour, 5 min, and 12 sec
#ifdef _DEBUG
afxDump << ts << "\n";
#endif
// Prints 'CTimeSpan(3 days, 1 hours, 5 minutes and 12 seconds)'

extern CArchive ar;
if( ar.IsLoading( ))
  ar >> ts;
else
  ar << ts;


CToolBar
  class CToolBar : public CControlBar

Objects of the class CToolBar are control bars that have a row of bitmapped buttons and optional separators. The buttons can act like pushbuttons, check-box buttons, or radio buttons. CToolBar objects are usually embedded members of frame-window objects derived from the class CFrameWnd or CMDIFrameWnd.

To create a toolbar from within a frame-window object, follow these steps:

1.	Construct the CToolBar object.

2.	Call the »Create« function to create the Windows toolbar and attach it to the CToolBar object.

3.	Call »LoadBitmap« to load the bitmap that contains the toolbar button images.

4.	Call »SetButtons« to set the button style and associate each button with an image in the bitmap.

All the button images in the toolbar are taken from one bitmap, which must contain one image for each button. All images must be the same size; the default is 16 pixels wide and 15 pixels high. Images must be side by side in the bitmap.

The SetButtons function takes a pointer to an array of control IDs and an integer that specifies the number of elements in the array. The function sets each button's ID to the value of the corresponding element of the array and assigns each button an image index, which specifies the position of the button's image in the bitmap. If an array element has the value ID_SEPARATOR, no image index is assigned.

The order of the images in the bitmap is typically the order in which they are drawn on the screen, but you can use the SetButtonInfo function to change the relationship between image order and drawing order.

All buttons in a toolbar are the same size. The default is 24 % 22 pixels, in accordance with The Windows Interface: An Application Design Guide. Any additional space between the image and button dimensions is used to form a border around the image.

Each button has one image. The various button states and styles (pressed, up, down, disabled, disabled down, and indeterminate) are generated from that one image. Although bitmaps can be any color, you can achieve the best results with images in black and shades of gray.

Toolbar buttons imitate pushbuttons by default. However, toolbar buttons can also imitate check-box buttons or radio buttons. Check-box buttons have three states: checked, cleared, and indeterminate. Radio buttons have only two states: checked and cleared.

To create a check-box button, assign it the style TBBS_CHECKBOX or use a CCmdUI object's SetCheck member function in an ON_UPDATE_COMMAND_UI handler. Calling SetCheck turns a pushbutton into a check-box button. Pass SetCheck an argument of 0 for unchecked, 1 for checked, or 2 for indeterminate.

To create a radio button, call a CCmdUI object's SetRadio member function from an ON_UPDATE_COMMAND_UI handler. Pass SetRadio an argument of 0 for unchecked or nonzero for checked. In order to provide a radio group's mutually exclusive behavior, you must have ON_UPDATE_COMMAND_UI handlers for all of the buttons in the group.

See Also

»CControlBar«, »CToolBar::Create«, »CToolBar::LoadBitmap«, »CToolBar::SetButtons«, »CCmdUI::SetCheck«, »CCmdUI::SetRadio«


CToolBar Class Members
  Class Members

Construction/Destruction — Public Members

»CToolBar«	Constructs a CToolBar object.
»Create«	Creates the Windows toolbar and attaches it to the CToolBar object.
»SetSizes«	Sets the sizes of buttons and their bitmaps.
»SetHeight«	Sets the height of the toolbar.
»LoadBitmap«	Loads the bitmap containing bitmap-button images.
»SetButtons«	Sets button styles and an index of button images within the bitmap.
Attributes — Public Members

»CommandToIndex«	Returns the index of a button with the given command ID.
»GetItemID«	Returns the command ID of a button or separator at the given index.
»GetItemRect«	Gets the display rectangle for the item at the given index.
»GetButtonInfo«	Gets a button's ID, style, and image number.
»SetButtonInfo«	Sets a button's ID, style, and image number.


CToolBar Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CToolBar::CommandToIndex

int CommandToIndex( UINT nIDFind );

nIDFind    Command ID of a toolbar button.

Remarks

Returns the index of the first toolbar button, starting at position 0, whose command ID matches nIDFind.

Return Value

The index of the button, or −1 if no button has the given command ID.

See Also

»CToolBar::GetItemId«


  CToolBar::Create

BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP, UINT nID = AFX_IDW_TOOLBAR );

pParentWnd    Pointer to the window that is the toolbar's parent.

dwStyle    The toolbar style. Additional toolbar styles supported are:

•	CBRS_TOP    Control bar is at top of the frame window.

•	CBRS_BOTTOM    Control bar is at bottom of the frame window.

•	CBRS_NOALIGN    Control bar is not repositioned when the parent is resized.

nID    The toolbar's child-window ID.

Remarks

Creates a Windows toolbar (a child window) and associates it with the CToolBar object. Also sets the toolbar height to a default value.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CToolBar::CToolBar«, »CToolBar::LoadBitmap«, »CToolBar::SetButtons«


  CToolBar::CToolBar

CToolBar();

Remarks

Constructs a CToolBar object and sets the default sizes.

Call Create to create the toolbar window.

See Also

»CToolBar::Create«


  CToolBar::GetButtonInfo

void GetButtonInfo( int nIndex, UINT& nID, UINT& nStyle, int& iImage ) const;

nIndex    Index of the toolbar button or separator whose information is to be retrieved.

nID    Reference to a UINT that is set to the command ID of the button.

nStyle    Reference to a UINT that is set to the style of the button.

iImage    Reference to an integer that is set to the index of the button's image within the bitmap.

Remarks

Gets the control ID, style, and image index of the toolbar button or separator at the location specified by nIndex. Those values are assigned to the variables referenced by nID, nStyle, and iImage. The image index is the position of the image within the bitmap that contains images for all the toolbar buttons. The first image is at position 0.

If nIndex specifies a separator, iImage is set to the separator width in pixels.

See Also

»CToolBar::SetButtonInfo«, »CToolBar::GetItemID«


  CToolBar::GetItemID

UINT GetItemID( int nIndex ) const;

nIndex    Index of the item (button or separator) whose ID is to be retrieved.

Remarks

Returns the command ID of the button or separator specified by nIndex. Separators return ID_SEPARATOR.

Return Value

The command ID of the button or separator specified by nIndex.

See Also

»CToolBar::CommandToIndex«, »CControlBar::GetCount«


  CToolBar::GetItemRect

void GetItemRect( int nIndex, LPRECT lpRect );

nIndex    Index of the item (button or separator) whose rectangle coordinates are to be retrieved.

lpRect    Address of the RECT structure that will contain the item's coordinates.

Remarks

Fills the RECT structure whose address is contained in lpRect with the coordinates of the button or separator specified by nIndex. Coordinates are in pixels relative to the upper-left corner of the toolbar.

Use GetItemRect to get the coordinates of a separator you want to replace with a combo box or other control.

See Also

»CToolBar::CommandToIndex«


  CToolBar::LoadBitmap

BOOL LoadBitmap( LPCSTR lpszResourceName );

BOOL LoadBitmap( UINT nIDResource );

lpszResourceName    Pointer to the resource name of the bitmap to be loaded.

nIDResource    Resource ID of the bitmap to be loaded.

Remarks

Loads the bitmap specified by lpszResourceName or nIDResource. The bitmap should contain one image for each toolbar button. If the images are not of the standard size (16 pixels wide and 15 pixels high), call SetSizes to set the button sizes and their images.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CToolBar::Create«, »CToolBar::SetButtons«, »CToolBar::SetSizes«


  CToolBar::SetButtonInfo

void SetButtonInfo( int nIndex, UINT nID, UINT nStyle, int iImage );

nIndex    Index of the button or separator whose information is to be set.

nID    The value to which the button's command ID is set.

nStyle    The new button style. The following button styles are supported:

•	TBBS_BUTTON    Standard pushbutton (default)

•	TBBS_SEPARATOR    Separator

•	TBBS_CHECKBOX    Auto check-box button

iImage    New index for the button's image within the bitmap.

Remarks

Sets the button's command ID, style, and image number. For separators, which have the style TBBS_SEPARATOR, this function sets the separator's width in pixels to the value stored in iImage.

For information on bitmap images and buttons, see »CToolBar« and »CToolBar::LoadBitmap«.

See Also

»CToolBar::GetButtonInfo«, »CToolBar::LoadBitmap«


  CToolBar::SetButtons

BOOL SetButtons( const UINT FAR* lpIDArray, int nIDCount );

lpIDArray    Pointer to an array of command IDs.

nIDCount    Number of elements in the array pointed to by lpIDArray.

Remarks

Sets each toolbar button's command ID to the value specified by the corresponding element of the array lpIDArray. If an element of the array has the value ID_SEPARATOR, a separator is created in the corresponding position of the toolbar. This function also sets each button's style to TBBS_BUTTON and each separator's style to TBBS_SEPARATOR, and assigns an image index to each button. The image index specifies the position of the button's image within the bitmap.

You do not need to account for separators in the bitmap because this function does not assign image indexes for separators. If your toolbar has buttons at positions 0, 1, and 3 and a separator at position 2, the images at positions 0, 1, and 2 in your bitmap are assigned to the buttons at positions 0, 1, and 3, respectively.

If lpIDArray is NULL, this function allocates space for the number of items specified by nIDCount. Use SetButtonInfo to set each item's attributes.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CToolBar::Create«, »CToolBar::SetButtonInfo«


  CToolBar::SetHeight

void SetHeight( int cyHeight );

cyHeight    The height in pixels of the toolbar.

Remarks

Sets the toolbar's height to the value, in pixels, specified in cyHeight.

After calling SetSizes, use this function to override the standard toolbar height. If the height is too small, the buttons will be clipped at the bottom.

If this function is not called, the framework uses the size of the button to determine the toolbar height.

See Also

»CToolBar::SetSizes«, »CToolBar::SetButtonInfo«, »CToolBar::SetButtons«


  CToolBar::SetSizes

void SetSizes( SIZE sizeButton, SIZE sizeImage );

sizeButton    The size in pixels of each button.

sizeImage    The size in pixels of each image.

Remarks

Sets the toolbar's buttons to the size, in pixels, specified in sizeButton. The sizeImage parameter must contain the size, in pixels, of the images in the toolbar's bitmap. The dimensions in sizeButton must be sufficient to hold the image plus 3 pixels on each side for the button outline. This function also sets the toolbar height to fit the buttons.

Call this function only for toolbars that do not follow The Windows Interface: An Application Design Guide recommendations for button and image sizes.

See Also

»CToolBar::LoadBitmap«, »CToolBar::SetButtonInfo«, »CToolBar::SetButtons«, »CToolBar::SetHeight«


CUIntArray
  class CUIntArray : public CObject

The CUIntArray class supports arrays of unsigned integers. An unsigned integer, or UINT, differs from words and doublewords in that the physical size of a UINT can change depending on the target operating environment. Under Windows version 3.1, a UINT is the same size as a WORD. Under Windows NT, a UINT is the same size as a doubleword.

The member functions of CUIntArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a UINT.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

UINT CUIntArray::GetAt( int <nIndex> ) const;

CUIntArray incorporates the IMPLEMENT_DYNAMIC macro to support run-time type access and dumping to a CDumpContext object. If you need a dump of individual unsigned integer elements, you must set the depth of the dump context to 1 or greater. Unsigned integer arrays may not be serialized.

#include <afxcoll.h>


CUIntArray Class Members
  Class Members

Construction/Destruction — Public Members

»CUIntArray«	Constructs an empty array for unsigned integers.
»~CUIntArray«	Destroys a CUIntArray object.
Bounds — Public Members

»GetSize«	Gets the number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; the array is not allowed to grow.
»ElementAt«	Returns a temporary reference to the element pointer within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


CUserException
   class CUserException : public CException

A CUserException is thrown to stop an end-user operation. Use CUserException when you want to use the throw/catch exception mechanism for application-specific exceptions. "User" in the class name can be interpreted as "my user did something exceptional that I need to handle."

A CUserException is usually thrown after calling the global function AfxMessageBox to notify the user that an operation has failed. When you write an exception handler, handle the exception specially since the user usually has already been notified of the failure. The framework throws this exception in some cases. To throw a CUserException yourself, alert the user and then call the global function AfxThrowUserException.

In the example below, a function containing operations that may fail alerts the user and throws a CUserException. The calling function catches the exception and handles it specially:

void DoSomeOperation( )

{

    // Processing

    // If something goes wrong...

    AfxMessageBox( "The x operation failed" );

    AfxThrowUserException( );

}

BOOL TrySomething( )

{

    TRY

    {

        // Could throw a CUserException or other exception.

        DoSomeOperation( );

    }

    CATCH( CUserException, e )

    {

        return FALSE;    // User already notified.

    }

    AND_CATCH( CException, e )

    {

        // For other exception types, notify user here.

        AfxMessageBox( "Some operation failed" );

        return FALSE;

    }

    END_CATCH

    return TRUE;   // No exception thrown.

}

#include <afxwin.h>

See Also

»CException«, »AfxMessageBox«, »AfxThrowUserException«


CView
  class CView : public CWnd

The CView class provides the basic functionality for user-defined view classes. A view is attached to a document and acts as an intermediary between the document and the user: the view renders an image of the document on the screen or printer and interprets user input as operations upon the document.

A view is a child of a frame window. More than one view can share a frame window, as in the case of a splitter window. The relationship between a view class, a frame window class, and a document class is established by a CDocTemplate object. When the user opens a new window or splits an existing one, the framework constructs a new view and attaches it to the document.

A view can be attached to only one document, but a document can have multiple views attached to it at once — for example, if the document is displayed in a splitter window or in multiple child windows in a multiple document interface (MDI) application. Your application can support different types of views for a given document type; for example, a word-processing program might provide both a complete text view of a document and an outline view that shows only the section headings. These different types of views can be placed in separate frame windows or in separate panes of a single frame window if you use a splitter window.

A view may be responsible for handling several different types of input, such as keyboard input or mouse input, as well as commands from menus, toolbars, or scroll bars. A view receives commands forwarded by its frame window. If the view does not handle a given command, it forwards the command to its associated document. Like all command targets, a view handles messages via a message map.

The view is responsible for displaying and modifying the document's data but not for storing it. The document provides the view with the necessary details about its data. You can let the view access the document's data members directly, or you can provide member functions in the document class for the view class to call.

When a document's data changes, the view responsible for the changes typically calls the CDocument::UpdateAllViews function for the document, which notifies all the other views by calling the OnUpdate member function for each. The default implementation of OnUpdate invalidates the view's entire client area. You can override it to invalidate only those regions of the client area that map to the modified portions of the document.

To use CView, derive a class from it and implement the OnDraw member function to perform screen display. You can also use OnDraw to perform printing and print preview. The framework handles the print loop for printing and previewing your document.

A view handles scroll-bar messages in its OnHScroll and OnVScroll member functions. You can implement scroll-bar message handling in these functions, or you can use the derived class CScrollView to handle scrolling for you.

Besides CScrollView, the Microsoft Foundation Class Library provides two other classes derived from CView:

•	CFormView, a scrollable view that contains dialog-box controls and is based on a dialog template resource.

•	CEditView, a view that provides a simple multiline text editor. You can use a CEditView object as a control in a dialog box as well as a view on a document.

The CView class also has a derived class named CPreviewView, which is used by the framework to perform print previewing. This class provides support for the features unique to the print-preview window, such as a toolbar, single- or double-page preview, and zooming, that is, enlarging the previewed image. You don't need to call or override any of CPreviewView's member functions unless you want to implement your own interface for print preview  (for example, if you want to support editing in print preview mode). See Technical Note 30 in MSVCNT\HELP\MFCNOTES.HLP for more details on customizing print preview.

include <afxwin.h>

See Also

»CWnd«, »CFrameWnd«, »CSplitterWnd«, »CDC«, »CDocTemplate«, »CDocument«, »CFormView«, »CEditView«, »CScrollView«


CView Class Members
  Class Members

Operations — Public Members

»DoPreparePrinting«	Displays Print dialog box and creates printer device context; call when overriding the OnPreparePrinting member function.
»GetDocument«	Returns the document associated with the view.
Overridables — Public Members

»IsSelected«	Tests whether a document item is selected. Required for Object Linking and Embedding (OLE) support.
Constructors — Protected Members

»CView«	Constructs a CView object.
Overridables — Protected Members

»OnActivateView«	Called when a view is activated.
»OnBeginPrinting«	Called when a print job begins; override to allocate graphics device interface (GDI) resources.
»OnDraw«	Called to render an image of the document for screen display, printing, or print preview. Implementation required.
»OnEndPrinting«	Called when a print job ends; override to deallocate GDI resources.
»OnEndPrintPreview«	Called when preview mode is exited.
»OnInitialUpdate«	Called after a view is first attached to a document.
»OnPrepareDC«	Called before the OnDraw member function is called for screen display or the OnPrint member function is called for printing or print preview.
»OnPreparePrinting«	Called before a document is printed or previewed; override to initialize Print dialog box.
»OnPrint«	Called to print or preview a page of the document.
»OnUpdate«	Called to notify a view that its document has been modified.


CView Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CView::CView

Protected

CView();♦

Remarks

Constructs a CView object. The framework calls the constructor when a new frame window is created or a window is split. Override the OnInitialUpdate member function to initialize the view after the document is attached.

See Also

»CView::OnInitialUpdate«


  CView::DoPreparePrinting

BOOL DoPreparePrinting( CPrintInfo* pInfo );

pInfo    Points to a CPrintInfo structure that describes the current print job.

Remarks

Call this function from your override of OnPreparePrinting to invoke the Print dialog box and create a printer device context.

This function's behavior depends on whether it is being called for printing or print preview (specified by the m_bPreview member of the pInfo parameter). If a file is being printed, this function invokes the Print dialog box, using the values in the CPrintInfo structure that pInfo points to; after the user has closed the dialog box, the function creates a printer device context based on settings the user specified in the dialog box and returns this device context through the pInfo parameter. This device context is used to print the document.

If a file is being previewed, this function creates a printer device context using the current printer settings; this device context is used for simulating the printer during preview.

Return Value

Nonzero if printing or print preview can begin; 0 if the operation has been cancelled.

See Also

»CPrintInfo«, »CView::OnPreparePrinting«


  CView::GetDocument

CDocument* GetDocument() const;

Remarks

Call this function to get a pointer to the view's document. This allows you to call the document's member functions.

Return Value

A pointer to the CDocument object associated with the view. NULL if the view is not attached to a document.

See Also

»CDocument«


  CView::IsSelected

virtual BOOL IsSelected( const CObject* pDocItem ) const;

pDocItem    Points to the document item being tested.

Remarks

Called by the framework to check whether the specified document item is selected. The default implementation of this function returns FALSE. Override this function if you're implementing selection using CDocItem objects. You must override this function if your view contains Object Linking and Embedding (OLE) items. See Chapter 17 in the Class Library User's Guide for more information on OLE.

Return Value

Nonzero if the specified document item is selected; otherwise 0.

See Also

»CDocItem«, »COleClientItem«


  CView::OnActivateView

Protected

virtual void OnActivateView( BOOL bActivate, CView* pActivateView, CView* pDeactiveView ); ♦

bActivate    Indicates whether the view is being activated or deactivated.

pActivateView    Points to the view object that is being activated.

pDeactiveView    Points to the view object that is being deactivated.

Remarks

Called by the framework when a view is activated or deactivated. The default implementation of this function sets the focus to the view being activated. Override this function if you want to perform special processing when a view is activated or deactivated. For example, if you want to provide special visual cues that distinguish the active view from the inactive views, you would examine the bActivate parameter and update the view's appearance accordingly.

The pActivateView and pDeactiveView parameters point to the same view if the application's main frame window is activated with no change in the active view — for example, if the focus is being transferred from another application to this one, rather than from one view to another within the application. This allows a view to re-realize its palette, if needed.

See Also

»CWnd::OnActivate«


  CView::OnBeginPrinting

Protected

virtual void OnBeginPrinting( CDC* pDC, CPrintInfo* pInfo ); ♦

pDC    Points to the printer device context.

pInfo    Points to a CPrintInfo structure that describes the current print job.

Remarks

Called by the framework at the beginning of a print or print preview job, after OnPreparePrinting has been called. The default implementation of this function does nothing. Override this function to allocate any GDI resources, such as pens or fonts, needed specifically for printing. Select the GDI objects into the device context from within the OnPrint member function for each page that uses them. If you are using the same view object to perform both screen display and printing, use separate variables for the GDI resources needed for each display; this allows you to update the screen during printing.

You can also use this function to perform initializations that depend on properties of the printer device context. For example, the number of pages needed to print the document may depend on settings that the user specified from the Print dialog box (such as page length). In such a situation, you cannot specify the document length in the OnPreparePrinting member function, where you would normally do so; you must wait until the printer device context has been created based on the dialog box settings. OnBeginPrinting is the first overridable function that gives you access to the CDC object representing the printer device context, so you can set the document length from this function. Note that if the document length is not specified by this time, a scroll bar is not displayed during print preview.

See Also

»CView::OnEndPrinting«,  »CView::OnPreparePrinting«, »CView::OnPrint«


  CView::OnDraw

Protected

virtual void OnDraw( CDC* pDC ) = 0; ♦

pDC    Points to the device context to be used for rendering an image of the document.

Remarks

Called by the framework to render an image of the document. The framework calls this function to perform screen display, printing, and print preview, passing a different device context in each case. There is no default implementation.

You must override this function to display your view on the document. You can make graphic device interface (GDI) calls using the CDC object that the pDC parameter points to. You can select GDI resources, such as pens or fonts, into the device context before drawing and then deselect them afterwards. Often your drawing code can be device-independent; that is, it doesn't require information about what type of device is displaying the image.

To optimize drawing, you can find out if a given rectangle will be drawn or not by calling the RectVisible member function of the device context. If you need to distinguish between normal screen display and printing, call the IsPrinting member function of the device context.

See Also

»CDC::IsPrinting«, »CDC::RectVisible«, »CView::OnPrint«, »CWnd::OnCreate«, »CWnd::OnDestroy«, »CWnd::PostNcDestroy«


  CView::OnEndPrinting

Protected

virtual void OnEndPrinting( CDC* pDC, CPrintInfo* pInfo ); ♦

pDC    Points to the printer device context.

pInfo    Points to a CPrintInfo structure that describes the current print job.

Remarks

Called by the framework after a document has been printed or previewed. The default implementation of this function does nothing. Override this function to free any GDI resources you allocated in the OnBeginPrinting member function.

See Also

»CView::OnBeginPrinting«


  CView::OnEndPrintPreview

Protected

virtual void OnEndPrintPreview( CDC* pDC, CPrintInfo* pInfo, POINT point, CPreviewView* pView ); ♦

pDC    Points to the printer device context.

pInfo    Points to a CPrintInfo structure that describes the current print job.

point    Specifies the point on the page that was last displayed in preview mode.

pView    Points to the view object used for previewing.

Remarks

Called by the framework when the user exits print preview mode. The default implementation of this function calls the OnEndPrinting member function and restores the main frame window to the state it was in before print preview began. Override this function to perform special processing when preview mode is terminated. For example, if you want to maintain the user's position in the document when switching from preview mode to normal display mode, you can scroll to the position described by the point parameter and the m_nCurPage member of the CPrintInfo structure that the pInfo parameter points to.

Always call the base class version of OnEndPrintPreview from your override, typically at the end of the function.

See Also

»CPrintInfo«, »CView::OnEndPrinting«


  CView::OnInitialUpdate

Protected

virtual void OnInitialUpdate(); ♦

Remarks

Called by the framework after the view is first attached to the document, but before the view is initially displayed. The default implementation of this function calls the OnUpdate member function with no hint information (that is, using the default values of 0 for the lHint parameter and NULL for the pHint parameter). Override this function to perform any one-time initialization that requires information about the document. For example, if your application has fixed-sized documents, you can use this function to initialize a view's scrolling limits based on the document size. If your application supports variable-sized documents, use OnUpdate to update the scrolling limits every time the document changes.

See Also

»CView::OnUpdate«


  CView::OnPrepareDC

Protected

virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL ); ♦

pDC    Points to the device context to be used for rendering an image of the document.

pInfo    Points to a CPrintInfo structure that describes the current print job if OnPrepareDC is being called for printing or print preview; the m_nCurPage member specifies the page about to be printed. This parameter is NULL if OnPrepareDC is being called for screen display.

Remarks

Called by the framework before the OnDraw member function is called for screen display and before the OnPrint member function is called for each page during printing or print preview. The default implementation of this function does nothing if the function is called for screen display. However, this function is overridden in derived classes, such as CScrollView, to adjust attributes of the device context; consequently, you should always call the base class implementation at the beginning of your override.

If the function is called for printing, the default implementation examines the page information stored in the pInfo parameter. If the length of the document has not been specified, OnPrepareDC assumes the document to be one page long and stops the print loop after one page has been printed. The function stops the print loop by setting the m_bContinuePrinting member of the structure to FALSE.

Override OnPrepareDC for any of the following reasons:

•	To adjust attributes of the device context as needed for the specified page. For example, if you need to set the mapping mode or other characteristics of the device context, do so in this function.

•	To perform print-time pagination. Normally you specify the length of the document when printing begins, using the OnPreparePrinting member function. However, if you don't know in advance how long the document is (for example, when printing an undetermined number of records from a database), override OnPrepareDC to test for the end of the document while it is being printed. When there is no more of the document to be printed, set the m_bContinuePrinting member of the CPrintInfo structure to FALSE.

•	To send escape codes to the printer on a page-by-page basis. To send escape codes from OnPrepareDC, call the Escape member function of the pDC parameter.

Call the base class version of OnPrepareDC at the beginning of your override.

See Also

»CDC::Escape«, »CPrintInfo«, »CView::OnBeginPrinting«, »CView::OnDraw«, »CView::OnPreparePrinting«, »CView::OnPrint«


  CView::OnPreparePrinting

Protected

virtual BOOL OnPreparePrinting( CPrintInfo* pInfo ); ♦

pInfo    Points to a CPrintInfo structure that describes the current print job.

Remarks

Called by the framework before a document is printed or previewed. The default implementation does nothing.

You must override this function to enable printing and print preview. Call the DoPreparePrinting member function, passing it the pInfo parameter, and then return its return value; DoPreparePrinting displays the Print dialog box and creates a printer device context. If you want to initialize the Print dialog box with values other than the defaults, assign values to the members of pInfo. For example, if you know the length of the document, pass the value to the SetMaxPages member function of pInfo before calling DoPreparePrinting. This value is displayed in the To: box in the Range portion of the Print dialog box.

DoPreparePrinting does not display the Print dialog box for a preview job. If you want to bypass the Print dialog box for a print job, check that the m_bPreview member of pInfo is FALSE and then set it to TRUE before passing it to DoPreparePrinting; reset it to FALSE afterwards.

If you need to perform initializations that require access to the CDC object representing the printer device context (for example, if you need to know the page size before specifying the length of the document), override the OnBeginPrinting member function.

If you want to set the value of the m_nNumPreviewPages or m_strPageDesc members of the pInfo parameter, do so after calling DoPreparePrinting. The DoPreparePrinting member function sets m_nNumPreviewPages to the value found in the application's .INI file and sets m_strPageDesc to its default value.

Return Value

Nonzero to begin printing; 0 if the print job has been cancelled.

See Also

»CPrintInfo«, »CView::DoPreparePrinting«, »CView::OnBeginPrinting«, »CView::OnPrepareDC«, »CView::OnPrint«

 Example

The following is an override of OnPreparePrinting provided by AppWizard if you select the printing option when you create a set of starter files. This override is sufficient unless you want to initialize the Print dialog box.

void CMyView::OnPreparePrinting( CPrintInfo *pInfo )
{
return DoPreparePrinting( pInfo );
}


  CView::OnPrint

Protected

virtual void OnPrint( CDC* pDC, CPrintInfo* pInfo ); ♦

pDC    Points to the printer device context.

pInfo    Points to a CPrintInfo structure that describes the current print job.

Remarks

Called by the framework to print or preview a page of the document. For each page being printed, the framework calls this function immediately after calling the OnPrepareDC member function. The page being printed is specified by the m_nCurPage member of the CPrintInfo structure that pInfo points to. The default implementation calls the OnDraw member function and passes it the printer device context.

Override this function for any of the following reasons:

•	To allow printing of multipage documents. Render only the portion of the document that corresponds to the page currently being printed. If you're using OnDraw to perform the rendering, you can adjust the viewport origin so that only the appropriate portion of the document is printed.

•	To make the printed image look different from the screen image (that is, if your application is not WYSIWYG). Instead of passing the printer device context to OnDraw, use the device context to render an image using attributes not shown on the screen.

If you need GDI resources for printing that you don't use for screen display, select them into the device context before drawing and deselect them afterwards. These GDI resources should be allocated in OnBeginPrinting and released in OnEndPrinting.

•	To implement headers or footers. You can still use OnDraw to do the rendering by restricting the area that it can print on.

Note that the m_rectDraw member of the pInfo parameter describes the printable area of the page in logical units.

Do not call OnPrepareDC in your override of OnPrint; the framework calls OnPrepareDC automatically before calling OnPrint.

See Also

»CView::OnBeginPrinting«, »CView::OnEndPrinting«, »CView::OnPrepareDC«, »CView::OnDraw«

 Example

The following is a skeleton for an overridden OnPrint function:

void CMyView::OnPrint( CDC *pDC, CPrintInfo *pInfo )
{
// Print headers and/or footers, if desired.
// Find portion of document corresponding to pInfo->m_nCurPage.
OnDraw( pDC );
}


  CView::OnUpdate

Protected

virtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint ); ♦

pSender    Points to the view that modified the document, or NULL if all views are to be updated.

lHint    Contains information about the modifications.

pHint    Points to an object storing information about the modifications.

Remarks

Called by the framework after the view's document has been modified; this function is called by CDocument::UpdateAllViews and allows the view to update its display to reflect those modifications. It is also called by the default implementation of OnInitialUpdate. The default implementation invalidates the entire client area, marking it for painting when the next WM_PAINT message is received. Override this function if you want to update only those regions that map to the modified portions of the document. To do this you must pass information about the modifications using the hint parameters.

To use lHint, define special hint values, typically a bitmask or an enumerated type, and have the document pass one of these values. To use pHint, derive a hint class from CObject and have the document pass a pointer to a hint object; when overriding OnUpdate, use the CObject::IsKindOf member function to determine the run-time type of the hint object.

Typically you should not perform any drawing directly from OnUpdate. Instead, determine the rectangle describing, in device coordinates, the area that requires updating; pass this rectangle to CWnd::InvalidateRect. This causes painting to occur the next time a WM_PAINT message is received.

If lHint is 0 and pHint is NULL, the document has sent a generic update notification. If a view receives a generic update notification, or if it cannot decode the hints, it should invalidate its entire client area.

See Also

»CDocument::UpdateAllViews«, »CView::OnInitialUpdate«, »CWnd::Invalidate«, »CWnd::InvalidateRect«


CWinApp
 class CWinApp : public CCmdTarget

The CWinApp class is the base class from which you derive a Windows application object. An application object provides member functions for initializing your application (and each instance of it) and for running the application.

Each application that uses the Microsoft Foundation classes can only contain one object derived from CWinApp. This object is constructed when other C++ global objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the Microsoft Foundation Class Library. Declare your derived CWinApp object at the global level.

When you derive an application class from CWinApp, override the »InitInstance« member function to create your application's main window object.

In addition to the CWinApp member functions, the Microsoft Foundation Class Library provides the following global functions to access your CWinApp object and other global information:

•	»AfxGetApp«    Obtains a pointer to the CWinApp object.

•	»AfxGetInstanceHandle«    Obtains a handle to the current application instance.

•	»AfxGetResourceHandle«    Obtains a handle to the application's resources.

•	»AfxGetAppName«    Obtains a pointer to a string containing the application's name. Alternately, if you have a pointer to the CWinApp object, use m_pszExeName to get the application's name.

For more information about these global functions, see "»Macros and Globals«" in this manual.

See Chapter 2, »Using the Classes to Write Applications for Windows«, in this manual for more on the CWinApp class, including an overview of:

•	CWinApp-derived code written by AppWizard.

•	CWinApp's role in the execution sequence of your application.

•	CWinApp's default member function implementations.

•	CWinApp's key overridables.

#include <afxwin.h>


CWinApp Class Members
  Class Members

Data Members — Public Members

»m_pszAppName«	Specifies the name of the application.
»m_hInstance«	Identifies the current instance of the application.
»m_hPrevInstance«	Identifies the previous instance of the application.
»m_lpCmdLine«	Points to a null-terminated string that specifies the command line for the application.
»m_nCmdShow«	Specifies how the window is to be shown initially.
»m_pMainWnd«	Holds a pointer to the application's main window. For an example of how to initialize m_pMainWnd, see »InitInstance«.
»m_bHelpMode«	Indicates if the user is in Help context mode (typically invoked with Shift+F1).
»m_pszExeName«	The module name of the application.
»m_pszHelpFilePath«	The path to the application's Help file.
»m_pszProfileName«	The application's .INI filename.
Construction/Destruction — Public Members

»CWinApp«	Constructs a CWinApp object.
Operations — Public Members

»LoadCursor«	Loads a cursor resource.
»LoadStandardCursor«	Loads a Windows predefined cursor that the IDC_ constants specify in WINDOWS.H.
»LoadOEMCursor«	Loads a Windows OEM predefined cursor that the OCR_ constants specify in WINDOWS.H.
»LoadIcon«	Loads an icon resource.
»LoadStandardIcon«	Loads a Windows predefined icon that the IDI_ constants specify in WINDOWS.H.
»LoadOEMIcon«	Loads a Windows OEM predefined icon that the OIC_ constants specify in WINDOWS.H.
»GetProfileInt«	Retrieves an integer from an entry in the application's .INI file.
»WriteProfileInt«	Writes an integer to an entry in the application's .INI file.
»GetProfileString«	Retrieves a string from an entry in the application's .INI file.
»WriteProfileString«	Writes a string to an entry in the application's .INI file.
»AddDocTemplate«	Adds a document template to the application's list of available document templates.
»OpenDocumentFile«	Called by the framework to open a document from a file.
»AddToRecentFileList«	Adds a filename to the most recently used (MRU) file list.
»GetPrinterDeviceDefaults«	Retrieves the printer device defaults.
Overridables — Public Members

»InitApplication«	Override to perform any application-level initialization.
»InitInstance«	Override to perform Windows instance initialization, such as creating your window objects.
»Run«	Runs the default message loop. Override to customize the message loop.
»OnIdle«	Override to perform application-specific idle-time processing.
»ExitInstance«	Override to clean up when your application terminates.
»PreTranslateMessage«	Filters messages before they are dispatched to the Windows functions TranslateMessage and DispatchMessage.
»SaveAllModified«	Prompts the user to save all modified documents.
»DoMessageBox«	Implements AfxMessageBox for the application.
»ProcessMessageFilter«	Intercepts certain messages before they reach the application.
»ProcessWndProcException«	Intercepts all unhandled exceptions thrown by the application's message and command handlers.
»DoWaitCursor«	Turns the wait cursor on and off.
»OnDDECommand«	Called by the framework in response to a dynamic data exchange (DDE) execute command.
»WinHelp«	Calls the WinHelp Windows function.
Initialization — Protected Members

»LoadStdProfileSettings«	Loads standard .INI file settings and enables the MRU file list feature.
»SetDialogBkColor«	Sets the default background color for dialog boxes and message boxes.
»EnableShellOpen«	Allows the user to open data files from the Windows File Manager.
»RegisterShellFileTypes«	Registers all the application's document types with the Windows File Manager.
Command Handlers — Protected Members

»OnFileNew«	Implements the ID_FILE_NEW command.
»OnFileOpen«	Implements the ID_FILE_OPEN command.
»OnFilePrintSetup«	Implements the ID_FILE_PRINT_SETUP command.
»OnContextHelp«	Handles Shift+F1 Help within the application.
»OnHelp«	Handles F1 Help within the application (using the current context).
»OnHelpIndex«	Handles the ID_HELP_INDEX command and provides a default Help topic.
»OnHelpUsing«	Handles the ID_HELP_USING command.


CWinApp Member Functions
 Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CWinApp::AddDocTemplate

void AddDocTemplate( CDocTemplate* pTemplate );

pTemplate    A pointer to the CDocTemplate to be added.

Remarks

Call this member function to add a document template to the list of available document templates that the application maintains. You should add all document templates to an application before you call »RegisterShellFileTypes«.

See Also

»CWinApp::RegisterShellFileTypes«, »CMultiDocTemplate«, »CSingleDocTemplate«


  CWinApp::AddToRecentFileList

virtual void AddToRecentFileList( const char* pszPathName );

pszPathName    The path of the file.

Remarks

Call this member function to add pszPathName to the MRU file list. You should call the »LoadStdProfileSettings« member function to load the current MRU file list before you use this member function.

The framework calls this member function when it opens a file or executes the Save As command to save a file with a new name.

See Also

»CWinApp::LoadStdProfileSettings«


  CWinApp::CWinApp

CWinApp( const char* pszAppName = NULL );

pszAppName    A null-terminated string that contains the application name that Windows uses. If this argument is not supplied or is NULL, CWinApp uses the resource string AFX_IDS_APP_TITLE or the filename of the executable file.

Remarks

Constructs a CWinApp object and passes pszAppName to be stored as the application name. You should construct one global object of your CWinApp-derived class. You can have only one CWinApp object in your application. The constructor stores a pointer to the CWinApp object so that WinMain can call the object's member functions to initialize and run the application.


  CWinApp::DoMessageBox

virtual int DoMessageBox( LPCSTR lpszPrompt, UINT nType, UINT nIDPrompt );

lpszPrompt    Address of text in the message box.

nType    The message box »style«.

nIDPrompt    An index to a Help context string.

Remarks

The framework calls this member function to implement a message box for the global function »AfxMessageBox«.

Do not call this member function to open a message box; use AfxMessageBox instead.

Override this member function to customize your application-wide processing of AfxMessageBox calls.

Return Value

Returns the same values as AfxMessageBox.

See Also

»AfxMessageBox«  , ::MessageBox


  CWinApp::DoWaitCursor

virtual void DoWaitCursor( int nCode );

nCode    If this parameter is 0, the original cursor is restored. If 1, a wait cursor appears. If −1, the wait cursor ends.

Remarks

Called by the framework to implement »CCmdTarget::BeginWaitCursor«, »CCmdTarget::EndWaitCursor«, and »CCmdTarget::RestoreWaitCursor«. Implements an hourglass cursor. DoWaitCursor maintains a reference count. When positive, the hourglass cursor is displayed.

If your code changes the cursor, call DoWaitCursor(0) to restore the cursor to the state the framework is maintaining.

Override this member function to change the wait cursor or to do additional processing while the wait cursor is displayed.

See Also

»CCmdTarget::BeginWaitCursor«, »CCmdTarget::EndWaitCursor«, »CCmdTarget::RestoreWaitCursor«


  CWinApp::EnableShellOpen

Protected

void EnableShellOpen(); ♦

Remarks

Call this function, typically from your InitInstance override, to enable your application's users to open data files when they double-click the files from within the Windows File Manager. Call the RegisterShellFileTypes member function in conjunction with this function, or provide a .REG file with your application for manual registration of document types.

See Also

»CWinApp::OnDDECommand«, »CWinApp::RegisterShellFileTypes«


  CWinApp::ExitInstance

virtual int ExitInstance();

Remarks

Called by the framework from within the Run member function to exit this instance of the application.

Do not call this member function from anywhere but within the Run member function.

The default implementation of this function writes framework options to the application's .INI file. Override this function to clean up when your application terminates.

Return Value

The application's exit code; 0 indicates no errors, and values greater than 0 indicate an error. This value is used as the return value from WinMain.

See Also

»CWinApp::Run«, »CWinApp::InitInstance«


  CWinApp::GetPrinterDeviceDefaults

BOOL GetPrinterDeviceDefaults( PRINTDLG FAR* pPrintDlg );

pPrintDlg    A far pointer to a PRINTDLG structure.

Remarks

Call this member function to prepare a printer device context for printing. Retrieves the current printer defaults from the Windows .INI file as necessary, or uses the last printer configuration set by the user in Print Setup.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CPrintDialog«, PRINTDLG


  CWinApp::GetProfileInt

UINT GetProfileInt( LPCSTR lpszSection, LPCSTR lpszEntry, int nDefault );

lpszSection    Points to a null-terminated string that specifies the section containing the entry.

lpszEntry    Points to a null-terminated string that contains the entry whose value is to be retrieved.

nDefault    Specifies the default value to return if the framework cannot find the entry. This value can be an unsigned value in the range 0 through 65,535 or a signed value in the range −32,768 through 32,767.

Remarks

Call this member function to retrieve the value of an integer from an entry within a specified section of the application's .INI file.

This member function is not case sensitive, so the strings in the lpszSection and lpszEntry parameters may differ in case.

Return Value

The integer value of the string that follows the specified entry if the function is successful. The return value is the value of the nDefault parameter if the function does not find the entry. The return value is 0 if the value that corresponds to the specified entry is not an integer.

Windows 3.1 Only

This member function supports hexadecimal notation for the value in the .INI file. When you retrieve a signed integer, you should cast the value into an int. ♦

See Also

»CWinApp::GetProfileString«, »CWinApp::WriteProfileInt« , ::GetPrivateProfileInt


  CWinApp::GetProfileString

CString GetProfileString( LPCSTR lpszSection, LPCSTR lpszEntry, LPCSTR lpszDefault = NULL );

lpszSection    Points to a null-terminated string that specifies the section containing the entry.

lpszEntry    Points to a null-terminated string that contains the entry whose string is to be retrieved. This value must not be NULL.

lpszDefault    Points to the default string value for the given entry if the entry cannot be found in the initialization file.

Remarks

Call this member function to retrieve the string associated with an entry within the specified section in the application's .INI file.

Return Value

The return value is the string from the application's .INI file or lpszDefault if the string cannot be found. The maximum string length supported by the framework is _MAX_PATH. If lpszDefault is NULL, the return value is an empty string.

See Also

»CWinApp::GetProfileInt«, »CWinApp::WriteProfileString«, ::GetPrivateProfileString


  CWinApp::InitApplication

virtual BOOL InitApplication();

Remarks

Windows allows several copies of the same program to run at the same time. There are two types of application initialization:

1.	One-time application initialization that is done the first time the program runs.

2.	Instance initialization that runs each time a copy of the program runs, including the first time.

This function is called by the version of WinMain that the framework provides. Override InitApplication to implement one-time initialization such as Windows class registration. Override InitInstance to implement per-instance initialization.

Return Value

Nonzero if initialization is successful; otherwise 0.

See Also

»CWinApp::InitInstance«


  CWinApp::InitInstance

virtual BOOL InitInstance();

Remarks

Windows allows several copies of the same program to run at the same time. Application initialization is conceptually divided into two sections: one-time application initialization that is done the first time the program runs, and instance initialization that runs each time a copy of the program runs, including the first time. The framework's implementation of WinMain calls this function.

Override InitInstance to initialize each new instance of your application running under Windows. Typically, you override InitInstance to construct your main window object and set the m_pMainWnd data member to point to that window. For more information on overriding this member function, see Chapter 2, "»Using the Classes to Write Applications for Windows«."Return Value

Nonzero if initialization is successful; otherwise 0.

See Also

»CWinApp::InitApplication«


  CWinApp::LoadCursor

HCURSOR LoadCursor( LPCSTR lpszResourceName ) const;

HCURSOR LoadCursor( UINT nIDResource ) const;

lpszResourceName    Points to a null-terminated string that contains the name of the cursor resource. You can use a CString for this argument.

nIDResource    ID number of the cursor resource.

Remarks

Loads the cursor resource named by lpszResourceName or specified by nIDResource from the current executable file. LoadCursor loads the cursor into memory only if it has not been previously loaded; otherwise, it retrieves a handle of the existing resource.

Use the »LoadStandardCursor« or »LoadOEMCursor« member function to access the predefined Windows cursors.

Return Value

A handle to a cursor. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadStandardCursor«, »CWinApp::LoadOEMCursor«, ::LoadCursor


  CWinApp::LoadIcon

HICON LoadIcon( LPCSTR lpszResourceName ) const;

HICON LoadIcon( UINT nIDResource ) const;

lpszResourceName    Points to a null-terminated string that contains the name of the icon resource. You can also use a CString for this argument.

nIDResource    ID number of the icon resource.

Remarks

Loads the icon resource named by lpszResourceName or specified by nIDResource from the executable file. LoadIcon loads the icon only if it has not been previously loaded; otherwise, it retrieves a handle of the existing resource.

You can use the »LoadStandardIcon« or »LoadOEMIcon« member function to access the predefined Windows icons.

Return Value

A handle to an icon. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadStandardIcon«, »CWinApp::LoadOEMIcon«, ::LoadIcon


  CWinApp::LoadOEMCursor

HCURSOR LoadOEMCursor( UINT nIDCursor ) const;

nIDCursor    An OCR_ manifest constant identifier that specifies a predefined Windows cursor. You must have #define OEMRESOURCE before #include <afxwin.h> to gain access to the OCR_ constants in WINDOWS.H.

Remarks

Loads the Windows predefined cursor resource specified by nIDCursor.

Use the LoadOEMCursor or »LoadStandardCursor« member function to access the predefined Windows cursors.

Return Value

A handle to a cursor. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadCursor«, »CWinApp::LoadStandardCursor«, ::LoadCursor


  CWinApp::LoadOEMIcon

HICON LoadOEMIcon( UINT nIDIcon ) const;

nIDIcon    An OIC_ manifest constant identifier that specifies a predefined Windows icon. You must have #define OEMRESOURCE before #include afxwin.h to access the OIC_ constants in WINDOWS.H.

Remarks

Loads the Windows predefined icon resource specified by nIDIcon.

Use the LoadOEMIcon or »LoadStandardIcon« member function to access the predefined Windows icons.

Return Value

A handle to an icon. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadStandardIcon«, »CWinApp::LoadIcon«, ::LoadIcon


  CWinApp::LoadStandardCursor

HCURSOR LoadStandardCursor( LPCSTR lpszCursorName ) const;

lpszCursorName    An IDC_ manifest constant identifier that specifies a predefined Windows cursor. These identifiers are defined in WINDOWS.H. The following list shows the possible predefined values and meanings for lpszCursorName:

•	IDC_ARROW    Standard arrow cursor

•	IDC_IBEAM    Standard text-insertion cursor

•	IDC_WAIT    Hourglass cursor used when Windows performs a time-consuming task

•	IDC_CROSS    Cross-hair cursor for selection

•	IDC_UPARROW    Arrow that points straight up

•	IDC_SIZE    Cursor to use to resize a window

•	IDC_ICON    Cursor to use to drag a file

•	IDC_SIZENWSE    Two-headed arrow with ends at upper left and lower right

•	IDC_SIZENESW    Two-headed arrow with ends at upper right and lower left

•	IDC_SIZEWE    Horizontal two-headed arrow

•	IDC_SIZENS    Vertical two-headed arrow

Remarks

Loads the Windows predefined cursor resource that lpszCursorName specifies.

Use the LoadStandardCursor or »LoadOEMCursor« member function to access the predefined Windows cursors.

Return Value

A handle to a cursor. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadOEMCursor«, »CWinApp::LoadCursor«, »::LoadCursor«


  CWinApp::LoadStandardIcon

HICON LoadStandardIcon( LPCSTR lpszIconName ) const;

lpszIconName    A manifest constant identifier that specifies a predefined Windows icon. These identifiers are defined in WINDOWS.H. The following list shows the possible predefined values and meanings for lpszIconName:

•	IDI_APPLICATION    Default application icon

•	IDI_HAND    Hand-shaped icon used in serious warning messages

•	IDI_QUESTION    Question-mark shape used in prompting messages

•	IDI_EXCLAMATION    Exclamation point shape used in warning messages

•	IDI_ASTERISK    Asterisk shape used in informative messages

Remarks

Loads the Windows predefined icon resource that lpszIconName specifies.

Use the LoadStandardIcon or »LoadOEMIcon« member function to access the predefined Windows icons.

Return Value

A handle to an icon. If unsuccessful, returns NULL.

See Also

»CWinApp::LoadOEMIcon«, »CWinApp::LoadIcon«, ::LoadIcon


  CWinApp::LoadStdProfileSettings

Protected

void LoadStdProfileSettings(); ♦

Remarks

Call this member function from within the InitInstance member function to enable and load the current MRU file list and the last preview state.

See Also

»CWinApp::AddToRecentFileList«


  CWinApp::OnContextHelp

Protected

afx_msg void OnContextHelp(); ♦

Remarks

You must add an

ON_COMMAND( ID_CONTEXT_HELP, OnContextHelp )

statement to your CWinApp class message map and also add an accelerator table entry, typically SHIFT+F1, to enable this member function.

OnContextHelp puts the application into Help mode. The cursor changes to an arrow and a question mark, and the user can then move the mouse pointer and press the left mouse button to select a dialog box, window, menu, or command button. This member function retrieves the Help context of the object under the cursor and calls the Windows function WinHelp with that Help context.

See Also

»CWinApp::OnHelp«, »CWinApp::WinHelp«


  CWinApp::OnDDECommand

virtual BOOL OnDDECommand( char* pszCommand );

pszCommand    Points to a DDE command string received by the application.

Remarks

Called by the framework when the main frame window receives a DDE execute message. The default implementation checks whether the command is a request to open a document and, if so, opens the specified document. The Windows File Manager usually sends such DDE command strings when the user double-clicks a data file. Override this function to handle other DDE execute commands, such as the command to print.

Return Value

Nonzero if the command is handled; otherwise 0.

See Also

»CWinApp::EnableShellOpen«


  CWinApp::OnFileNew

Protected

afx_msg void OnFileNew(); ♦

Remarks

You must add an

ON_COMMAND( ID_FILE_NEW, OnFileNew )

statement to your CWinApp class message map to enable this member function.

If enabled, this function handles execution of the File New command.

See Technical Note 22 in MSVCNT\HELP\MFCNOTES.HLP for information on default behavior and guidance on how to override this member function.

See Also

»CWinApp::OnFileOpen«


  CWinApp::OnFileOpen

Protected

afx_msg void OnFileOpen(); ♦

Remarks

You must add an

ON_COMMAND( ID_FILE_OPEN, OnFileOpen )

statement to your CWinApp class message map to enable this member function.

If enabled, this function handles execution of the File Open command.

For information on default behavior and guidance on how to override this member function, see Technical Note 22.

See Also

»CWinApp::OnFileNew«


  CWinApp::OnFilePrintSetup

Protected

afx_msg void OnFilePrintSetup(); ♦

Remarks

You must add an

ON_COMMAND( ID_FILE_PRINT_SETUP, OnFilePrintSetup )

statement to your CWinApp class message map to enable this member function.

If enabled, this function handles execution of the File Print command.

For information on default behavior and guidance on how to override this member function, see Technical Note 22.

See Also

»CWinApp::OnFileNew«


  CWinApp::OnHelp

Protected

afx_msg void OnHelp(); ♦

Remarks

You must add an

ON_COMMAND( ID_ON_HELP, OnHelp )

statement to your CWinApp class message map to enable this member function. Usually you will also add an accelerator-key entry for the F1 key. Enabling the F1 key is only a convention, not a requirement.

If enabled, called by the framework when the user presses the F1 key.

The default implementation of this message-handler function determines the Help context that corresponds to the current window, dialog box, or menu item and then calls WINHELP.EXE. If no context is currently available, the function uses the default context.

Override this member function to set the Help context to something other than the window, dialog box, menu item, or toolbar button that currently has the focus. Call WinHelp with the desired Help context ID.

See Also

»CWinApp::OnContextHelp«, »CWinApp::OnHelpUsing«, »CWinApp::OnHelpIndex«, »CWinApp::WinHelp«


  CWinApp::OnHelpIndex

Protected

afx_msg void OnHelpIndex(); ♦

Remarks

You must add an

ON_COMMAND( ID_HELP_INDEX, OnHelpIndex )

statement to your CWinApp class message map to enable this member function.

If enabled, the framework calls this message-handler function when the user of your application selects the Help Index command to invoke WinHelp with the standard HELP_INDEX topic.

See Also

»CWinApp::OnHelp«, »CWinApp::OnHelpUsing«, »CWinApp::WinHelp«


  CWinApp::OnHelpUsing

Protected

afx_msg void OnHelpUsing(); ♦

Remarks

You must add an

ON_COMMAND( ID_HELP_USING, OnHelpUsing )

statement to your CWinApp class message map to enable this member function.

The framework calls this message-handler function when the user of your application selects the Help Using command to invoke the WinHelp application with the standard HELP_HELPONHELP topic.

See Also

»CWinApp::OnHelp«, »CWinApp::OnHelpIndex«, »CWinApp::WinHelp«


   CWinApp::OnIdle

virtual BOOL OnIdle( LONG lCount );

lCount    A counter incremented each time OnIdle is called when the application's message queue is empty. This count is reset to 0 each time a new message is processed. You can use the lCount parameter to determine the relative length of time the application has been idle without processing a message.

Remarks

Override this member function to perform idle-time processing. OnIdle is called in the default message loop when the application's message queue is empty. Use your override to call your own background idle-handler tasks.

OnIdle should return 0 to indicate that no idle processing time is required. The lCount parameter is incremented each time OnIdle is called when the message  queue is empty and resets to 0 each time a new message is processed. You can call your different idle routines based on this count.

The following summarizes idle loop processing:

1.	If the message loop in the Microsoft Foundation Class Library checks the message queue and finds no pending messages, it calls OnIdle for the application object and supplies 0 as the lCount argument.

2.	OnIdle performs some processing and returns a nonzero value to indicate it should be called again to do further processing.

3.	The message loop checks the message queue again. If no messages are pending, it calls OnIdle again, incrementing the lCount argument.

4.	Eventually, OnIdle finishes processing all its idle tasks and returns 0. This tells the message loop to stop calling OnIdle until the next message is received from the message queue, at which point the idle cycle restarts with the argument set to 0.

Do not perform lengthy tasks during OnIdle because your application cannot process user input until OnIdle returns.

Note  The default implementation of OnIdle updates command user-interface objects such as menu items and toolbar buttons, and it performs internal data structure cleanup. Therefore, if you override OnIdle, you must call CWinApp::OnIdle with the lCount in your overridden version. First call all base-class idle processing (that is, until the base class OnIdle returns 0). If you need to perform work before the base-class processing completes, review the base-class implementation to select the proper lCount during which to do your work.

Return Value

Nonzero to receive more idle processing time; 0 if no more idle time is needed.

 Example

The following example shows how to process two idle tasks using the lCount argument to prioritize the tasks. The first task is high priority, and you should do it whenever possible. The second task is less important and should be done only when there is a long pause in user input. Note the call to the base-class version of OnIdle.

BOOL CMyApp::OnIdle(LONG lCount)

{

    BOOL bMore = CWinApp::OnIdle(lCount);

    if (lCount == 0)

    {

    TRACE("App idle for short period of time\n");

    bMore = TRUE;

    }

    else if (lCount == 10)

    {

    TRACE("App idle for longer amount of time\n");

        bMore = TRUE;

    }

    else if (lCount == 100)

    {

        TRACE("App idle for even longer amount of time\n");

        bMore = TRUE;

    }

    else if (lCount == 1000)

    {

        TRACE("App idle for quite a long period of time\n");

     // bMore is not set to TRUE, no longer need idle

     // IMPORTANT: bMore is not set to FALSE since CWinApp::OnIdle may

     // have more idle tasks to complete.

    }

    return bMore;

     // return TRUE as long as there is any more idle tasks

}


  CWinApp::OpenDocumentFile

virtual CDocument* OpenDocumentFile( LPCSTR lpszFileName );

lpszFileName    The name of the file to be opened.

Remarks

The framework calls this member function to open the named CDocument file for the application. If a document with that name is already open, the first frame window that contains that document will be activated. If an application supports multiple document templates, the framework uses file extension to find the appropriate document template to attempt to load the document. If successful, the document template then creates a frame window and view for the document.

Return Value

A pointer to a CDocument if successful; otherwise NULL.


  CWinApp::PreTranslateMessage

virtual BOOL PreTranslateMessage( MSG* pMsg );

pMsg    A pointer to an MSG structure that contains the message to process.

Remarks

Override this function to filter window messages before they are dispatched to the Windows functions »TranslateMessage« and DispatchMessage The default implementation performs accelerator-key translation, so you must call the CWinApp::PreTranslateMessage member function in your overridden version.

Return Value

Nonzero if the message was fully processed in PreTranslateMessage and should not be processed further. Zero if the message should be processed in the normal way.

See Also

::DispatchMessage, ::TranslateMessage


  CWinApp::ProcessMessageFilter

virtual BOOL ProcessMessageFilter( int code, LPMSG lpMsg );

code    Specifies a hook code. This member function uses the code to determine how to process lpMsg.

lpMsg    A pointer to a Windows MSG structure.

Remarks

The framework's hook function calls this member function to filter and respond to certain Windows messages. A hook function processes events before they are sent to the application's normal message processing.

If you override this advanced feature, be sure to call the base-class version to maintain the framework's hook processing.

Return Value

Nonzero if the message is processed; otherwise 0.

See Also

MessageProc, WH_MSGFILTER


  CWinApp::ProcessWndProcException

virtual LRESULT ProcessWndProcException( CException* e, const MSG* pMsg );

e    A pointer to an uncaught exception.

pMsg    An MSG structure that contains information about the windows message that caused the framework to throw an exception.

Remarks

The framework calls this member function whenever the handler does not catch an exception thrown in one of your application's message or command handlers.

Do not call this member function directly.

The default implementation of this member function creates a message box. If the uncaught exception originates with a menu, toolbar, or accelerator command failure, the message box displays a "Command failed" message; otherwise, it displays an "Internal application error" message.

Override this member function to provide global handling of your exceptions. Only call the base functionality if you wish the message box to be displayed.

Return Value

The value that should be returned to Windows. Normally this is 0L for windows messages, 1L (TRUE) for command messages.

See Also

»CWnd::WindowProc«, »CException«


  CWinApp::RegisterShellFileTypes

Protected

void RegisterShellFileTypes(); ♦

Remarks

Call this function to register all of your application's document types with the Windows File Manager. This allows the user to open a data file created by your application by double-clicking it from within File Manager. Call this member function after you call AddDocTemplate for each of the document templates in your application. Also call the EnableShellOpen member function when you call this member function.

This function iterates through the list of CDocTemplate objects that the application maintains and, for each document template, adds entries to the registration database that Windows maintains for file associations. File Manager uses these entries to open a data file when the user double-clicks it. This eliminates the need to ship a .REG file with your application.

If the registration database already associates a given filename extension with another file type, no new association is created. See the CDocTemplate class for the format of strings necessary to register this information.

See Also

»CDocTemplate«, »CWinApp::EnableShellOpen«, »CWinApp::AddDocTemplate«


  CWinApp::Run

virtual int Run();

Remarks

Provides a default message loop. Run acquires and dispatches Windows messages until the application receives a WM_QUIT message. If the application's message queue currently contains no messages, Run calls »OnIdle« to perform idle-time processing. Incoming messages go to the »PreTranslateMessage« member function for special processing and then to the Windows function TranslateMessage for standard keyboard translation; finally, the DispatchMessage Windows function is called.

Run is rarely overridden, but you can override it to provide special behavior.

Return Value

An int value that is returned by WinMain.

See Also

»CWinApp::PreTranslateMessage«, WM_QUIT, ::DispatchMessage, ::TranslateMessage


  CWinApp::SaveAllModified

virtual BOOL SaveAllModified();

Remarks

Called by the framework to save all documents when the application's main frame window is to be closed, or through a WM_QUERYENDSESSION message.

The default implementation of this member function calls the SaveModified member function in turn for all modified documents within the application.

Return Value

Nonzero if safe to terminate the application; 0 if not safe to terminate the application.


  CWinApp::SetDialogBkColor

Protected

void SetDialogBkColor( COLORREF clrCtlBk = RGB(192, 192, 192), COLORREF clrCtlText = RGB(0, 0, 0) ); ♦

clrCtlBk    The dialog background color for the application.

clrCtlText     The dialog control color for the application.

Remarks

Call this member function from within the InitInstance member function to set the default background and text color for dialog boxes and message boxes within your application.


  CWinApp::WinHelp

virtual void WinHelp( DWORD dwData, UINT nCmd = HELP_CONTEXT );

dwData    Specifies additional data. The value used depends on the value of the nCmd parameter.

nCmd    Specifies the type of help requested. For a list of possible values and how they affect the dwData parameter, see the WinHelp Windows function.

Remarks

Call this member function to invoke the WinHelp application. The framework also calls this function to invoke the WinHelp application.

The framework will automatically close the WinHelp application when your application terminates.

See Also

»CWinApp::OnContextHelp«, »CWinApp::OnHelpUsing«, »CWinApp::OnHelp«, »CWinApp::OnHelpIndex«,  ::WinHelp


  CWinApp::WriteProfileInt

BOOL WriteProfileInt( LPCSTR lpszSection, LPCSTR lpszEntry, int nValue );

lpszSection    Points to a null-terminated string that specifies the section containing the entry. If the section does not exist, it is created. The name of the section is case independent; the string may be any combination of uppercase and lowercase letters.

lpszEntry    Points to a null-terminated string that contains the entry into which the value is to be written. If the entry does not exist in the specified section, it is created.

nValue    Contains the value to be written.

Remarks

Call this member function to write the specified value into the specified section of the application's .INI file.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWinApp::GetProfileInt«, »CWinApp::WriteProfileString«


  CWinApp::WriteProfileString

BOOL WriteProfileString( LPCSTR lpszSection, LPCSTR lpszEntry, LPCSTR lpszValue );

lpszSection    Points to a null-terminated string that specifies the section containing the entry. If the section does not exist, it is created. The name of the section is case independent; the string may be any combination of uppercase and lowercase letters.

lpszEntry    Points to a null-terminated string that contains the entry into which the value is to be written. If the entry does not exist in the specified section, it is created.

lpszValue    Points to the string to be written. If this parameter is NULL, the entry specified by the lpszEntry parameter is deleted.

Remarks

Call this member function to write the specified string into the specified section of the application's .INI file.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWinApp::GetProfileString«, »CWinApp::WriteProfileInt«, PrivateProfileString


CWinApp Data Members
 Data Members

To get information on a particular data member, double-click it in the Contents window.


  CWinApp::m_bHelpMode

Remarks

TRUE if the application is in Help context mode (conventionally invoked with Shift+F1); otherwise FALSE. In Help context mode, the cursor becomes a question mark and the user can move it about the screen. Examine this flag if you want to implement special handling when in the Help mode. m_bHelpMode is a public variable of type BOOL.


  CWinApp::m_hInstance

Remarks

Corresponds to the hInstance parameter passed by Windows to WinMain. The m_hInstance data member is a handle to the current instance of the application running under Windows. This is returned by the global function AfxGetInstanceHandle. m_hInstance is a public variable of type HINSTANCE.


  CWinApp::m_hPrevInstance

Remarks

Corresponds to the hPrevInstance parameter passed by Windows to WinMain.

Identifies the previous instance of the application. The m_hPrevInstance data member has the value NULL if this is the first instance of the application that is running. m_hPrevInstance is a public variable of type HINSTANCE.


  CWinApp::m_lpCmdLine

Remarks

Corresponds to the lpCmdLine parameter passed by Windows to WinMain. Points to a null-terminated string that specifies the command line for the application. Use m_lpCmdLine to access any command-line arguments the user entered when the application was started. m_lpCmdLine is a public variable of type LPSTR.


  CWinApp::m_nCmdShow

Remarks

Corresponds to the nCmdShow parameter passed by Windows to WinMain. You should pass m_nCmdShow as an argument when you call ShowWindow for your application's main window. m_nCmdShow is a public variable of type int.


  CWinApp::m_pMainWnd

Remarks

Use this data member to store a pointer to your application's main window object. The Microsoft Foundation Class Library will automatically terminate your application when the window referred to by m_pMainWnd is closed. If you don't store a valid CWnd pointer here, many default framework implementations will not work correctly. m_pMainWnd is a public variable of type CWnd*.

Typically, you set this member variable when you override InitInstance.

See Also

»CWinApp::InitInstance«


  CWinApp::m_pszAppName

Remarks

Specifies the name of the application. The application name can come from the parameter passed to the CWinApp constructor, or, if not specified, to the resource string with the ID of AFX_IDS_APP_TITLE. If the application name is not found in the resource, it comes from the program's .EXE filename.

Returned by the global function AfxGetAppName. m_pszAppName is a public variable of type const char*.


  CWinApp::m_pszExeName

Remarks

Contains the name of the application's executable file without an extension. Unlike m_pszAppName, this name cannot contain blanks. m_pszExeName is a public variable of type const char*.


  CWinApp::m_pszHelpFilePath

Remarks

Contains the path to the application's Help file. The framework expects a single Help file, which must have the same name as the application but with a .HLP extension. m_pszHelpFilePath is a public variable of type const char*.


  CWinApp::m_pszProfileName

Remarks

Contains the name of the application's .INI file. m_pszProfileName is a public variable of type const char*.

See Also

»CWinApp::GetProfileString«, »CWinApp::GetProfileInt«, »CWinApp::WriteProfileInt«, »CWinApp::WriteProfileString«


CWindowDC
  class CWindowDC : public CDC

The CWindowDC class is derived from CDC. It calls the Windows functions GetWindowDC at construction time and ReleaseDC at destruction time. This means that a CWindowDC object accesses the entire screen area of a »CWnd« (both client and nonclient areas).

#include <afxwin.h>

See Also

»CDC«


CWindowDC Class Members
  Class Members

Construction/Destruction — Public Members

»CWindowDC«	Constructs a CWindowDC object.
Data Members — Protected Members

»m_hWnd«	The HWND to which this CWindowDC is attached.


CWindowDC Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CWindowDC::CWindowDC

CWindowDC( CWnd* pWnd )
throw( CResourceException );

pWnd    The window whose client area the device-context object will access.

Remarks

Constructs a CWindowDC object that accesses the entire screen area (both client and nonclient) of the CWnd object pointed to by pWnd. The constructor calls the Windows function  GetDC.

An exception (of type CResourceException) is thrown if the Windows GetDC call fails. A device context may not be available if Windows has already allocated all of its available device contexts. Your application competes for the five common display contexts available at any given time under Windows.

See Also

»CDC«, »CClientDC«, »CWnd«


CWindowDC Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CWindowDC::m_hWnd

Remarks

The HWND of the CWnd pointer is used to construct the CWindowDC object. m_hWnd is a protected variable of type HWND.


CWnd
  class CWnd : public CCmdTarget

The CWnd class provides the base functionality of all window classes in the Microsoft Foundation Class Library.

A CWnd object is distinct from a Windows window, but the two are tightly linked. A CWnd object is created or destroyed by the CWnd constructor and destructor. The Windows window, on the other hand, is a data structure internal to Windows that is created by a Create member function and destroyed by the CWnd virtual destructor. The DestroyWindow function destroys the Windows window without destroying the object.

The CWnd class and the message-map mechanism hide the WndProc function. Incoming Windows notification messages are automatically routed through the message map to the proper OnMessage CWnd member functions. You override an OnMessage member function to handle a member's particular message in your derived classes.

The CWnd class also lets you create a Windows child window for your application. Derive a class from CWnd, then add member variables to the derived class to store data specific to your application. Implement message-handler member functions and a message map in the derived class to specify what happens when messages are directed to the window.

You create a child window in two steps. First, call the constructor CWnd to construct the CWnd object, then call the »Create« member function to create the child window and attach it to the CWnd object.

When the user terminates your child window, destroy the CWnd object, or call the DestroyWindow member function to remove the window and destroy its data structures.

Within the Microsoft Foundation Class Library, further classes are derived from CWnd to provide specific window types. Many of these classes, including CFrameWnd, CMDIFrameWnd, CMDIChildWnd, CView, and CDialog, are designed for further derivation. The control classes derived from CWnd, such as CButton, can be used directly or can be used for further derivation of classes.

#include <afxwin.h>

See Also

»CDialog«, »CFrameWnd«, »CView«


CWnd Class Members
  Class Members

Data Members — Public Members

»m_hWnd«	Indicates the HWND attached to this CWnd.
Construction/Destruction — Public Members

»CWnd«	Constructs a CWnd object.
»DestroyWindow«	Destroys the attached Windows window.
Initialization — Public Members

»Create«	Creates and initializes the child window associated with the CWnd object.
»PreCreateWindow«	Called before the creation of the Windows window attached to this CWnd object.
»CalcWindowRect«	Called to calculate the window rectangle from the client rectangle.
»GetStyle«	Returns the current window style.
»GetExStyle«	Returns the window's extended style.
»Attach«	Attaches a Windows handle to a CWnd object.
»Detach«	Detaches a Windows handle from a CWnd object and returns the handle.
»SubclassWindow«	Attaches a window to a CWnd object and makes it route messages through the CWnd's message map.
»FromHandle«	Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, a temporary CWnd object is created and attached.
»FromHandlePermanent«	Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, NULL is returned.
»DeleteTempMap«	Called automatically by the CWinApp idle-time handler and deletes any temporary CWnd objects created by FromHandle.
»GetSafeHwnd«	Returns m_hWnd, or NULL if the this pointer is NULL.
Window State Functions — Public Members

»IsWindowEnabled«	Determines if the window is enabled for mouse and keyboard input.
»EnableWindow«	Enables or disables mouse and keyboard input.
»GetActiveWindow«	Retrieves the active window.
»SetActiveWindow«	Activates the window.
»GetCapture«	Retrieves the CWnd that has the mouse capture.
»SetCapture«	Causes all subsequent mouse input to be sent to the CWnd.
»GetFocus«	Retrieves the CWnd that currently has the input focus.
»SetFocus«	Claims the input focus.
»GetDesktopWindow«	Retrieves the Windows desktop window.
Window Size and Position — Public Members

»GetWindowPlacement«	Retrieves the show state and the normal (restored), minimized, and maximized positions of a window.
»SetWindowPlacement«	Sets the show state and the normal (restored), minimized, and maximized positions for a window.
»IsIconic«	Determines whether CWnd is minimized (iconic).
»IsZoomed«	Determines whether CWnd is maximized.
»MoveWindow«	Changes the position and/or dimensions of CWnd.
»SetWindowPos«	Changes the size, position, and ordering of child, pop-up, and top-level windows.
»ArrangeIconicWindows«	Arranges all the minimized (iconic) child windows.
»BringWindowToTop«	Brings CWnd to the top of a stack of overlapping windows.
»GetWindowRect«	Gets the screen coordinates of CWnd.
»GetClientRect«	Gets the dimensions of the CWnd client area.
Window Access Functions — Public Members

»ChildWindowFromPoint«	Determines which, if any, of the child windows contains the specified point.
»FindWindow«	Returns the handle of the window, which is identified by its window name and window class.
»GetNextWindow«	Returns the next (or previous) window in the window manager's list.
»GetTopWindow«	Returns the first child window that belongs to the CWnd.
»GetWindow«	Returns the window with the specified relationship to this window.
»GetLastActivePopup«	Determines which pop-up window owned by CWnd was most recently active.
»IsChild«	Indicates whether CWnd is a child window or other direct descendant of the specified window.
»GetParent«	Retrieves the parent window of CWnd (if any).
»SetParent«	Changes the parent window.
»WindowFromPoint«	Identifies the window that contains the given point.
»GetDlgItem«	Retrieves the control with the specified ID from the specified dialog box.
»GetDlgCtrlID«	If the CWnd is a child window, calling this function returns its ID value.
»GetDescendantWindow«	Searches all descendant windows and returns the window with the specified ID.
»SendMessageToDescendants«	Sends a message to all descendant windows of the window.
»GetParentFrame«	Returns the CWnd object's parent frame window.
»UpdateDialogControls«	Call to update the state of dialog buttons and other controls.
»UpdateData«	Initializes or retrieves data from a dialog box.
Update/Painting Functions — Public Members

»BeginPaint«	Prepares CWnd for painting.
»EndPaint«	Marks the end of painting.
»LockWindowUpdate«	Disables or reenables drawing in the given window.
»GetDC«	Retrieves a display context for the client area.
»GetDCEx«	Retrieves a display context for the client area, and enables clipping while drawing.
»RedrawWindow«	Updates the specified rectangle or region in the client area.
»GetWindowDC«	Retrieves the display context for the whole window, including the caption bar, menus, and scroll bars.
»ReleaseDC«	Releases client and window device contexts, freeing them for use by other applications.
»UpdateWindow«	Updates the client area.
»SetRedraw«	Allows changes in CWnd to be redrawn or prevents changes from being redrawn.
»GetUpdateRect«	Retrieves the coordinates of the smallest rectangle that completely encloses the CWnd update region.
»GetUpdateRgn«	Retrieves the CWnd update region.
»Invalidate«	Invalidates the entire client area.
»InvalidateRect«	Invalidates the client area within the given rectangle by adding that rectangle to the current update region.
»InvalidateRgn«	Invalidates the client area within the given region by adding that region to the current update region.
»ValidateRect«	Validates the client area within the given rectangle by removing the rectangle from the current update region.
»ValidateRgn«	Validates the client area within the given region by removing the region from the current update region.
»ShowWindow«	Shows or hides the window.
»IsWindowVisible«	Determines if the window is visible.
»ShowOwnedPopups«	Shows or hides all pop-up windows owned by the window.
»EnableScrollBar«	Enables or disables one or both arrows of a scroll bar.
Coordinate Mapping Functions — Public Members

»MapWindowPoints«	Converts (maps) a set of points from the coordinate space of the CWnd to the coordinate space of another window.
»ClientToScreen«	Converts the client coordinates of a given point or rectangle on the display to screen coordinates.
»ScreenToClient«	Converts the screen coordinates of a given point or rectangle on the display to client coordinates.
Window Text Functions — Public Members

»SetWindowText«	Sets the window text or caption title (if it has one) to the specified text.
»GetWindowText«	Returns the window text or caption title (if it has one).
»GetWindowTextLength«	Returns the length of the window's text or caption title.
»SetFont«	Sets the current font.
»GetFont«	Retrieves the current font.
Scrolling Functions — Public Members

»GetScrollPos«	Retrieves the current position of a scroll box.
»GetScrollRange«	Copies the current minimum and maximum scroll-bar positions for the given scroll bar.
»ScrollWindow«	Scrolls the contents of the client area.
»ScrollWindowEx«	Scrolls the contents of the client area. Similar to ScrollWindow, with additional features.
»SetScrollPos«	Sets the current position of a scroll box and, if specified, redraws the scroll bar to reflect the new position.
»SetScrollRange«	Sets minimum and maximum position values for the given scroll bar.
»ShowScrollBar«	Displays or hides a scroll bar.
»EnableScrollBarCtrl«	Enables or disables a sibling scroll-bar control.
»GetScrollBarCtrl«	Returns a sibling scroll-bar control.
»RepositionBars«	Repositions control bars in the client area.
Drag-Drop Functions — Public Members

»DragAcceptFiles«	Indicates the window will accept dragged files.
Caret Functions — Public Members

»CreateCaret«	Creates a new shape for the system caret and gets ownership of the caret.
»CreateSolidCaret«	Creates a solid block for the system caret and gets ownership of the caret.
»CreateGrayCaret«	Creates a gray block for the system caret and gets ownership of the caret.
»GetCaretPos«	Retrieves the client coordinates of the caret's current position.
»SetCaretPos«	Moves the caret to a specified position.
»HideCaret«	Hides the caret by removing it from the display screen.
»ShowCaret«	Shows the caret on the display at the caret's current position. Once shown, the caret begins flashing automatically.
Dialog-Box Item Functions — Public Members

»CheckDlgButton«	Places a check mark next to or removes a check mark from a button control.
»CheckRadioButton«	Checks the specified radio button and removes the check mark from all other radio buttons in the specified group of buttons.
»GetCheckedRadioButton«	Returns the ID of the currently checked radio button in a group of buttons.
»DlgDirList«	Fills a list box with a file or directory listing.
»DlgDirListComboBox«	Fills the list box of a combo box with a file or directory listing.
»DlgDirSelect«	Retrieves the current selection from a list box.
»DlgDirSelectComboBox«	Retrieves the current selection from the list box of a combo box.
»GetDlgItemInt«	Translates the text of a control in the given dialog box to an integer value.
»GetDlgItemText«	Retrieves the caption or text associated with a control.
»GetNextDlgGroupItem«	Searches for the next (or previous) control within a group of controls.
»GetNextDlgTabItem«	Retrieves the first control with the »WS_TABSTOP« style that  follows (or precedes) the specified control.
»IsDlgButtonChecked«	Determines whether a button control is checked.
»SendDlgItemMessage«	Sends a message to the specified control.
»SetDlgItemInt«	Sets the text of a control to the string that represents an integer value.
»SetDlgItemText«	Sets the caption or text of a control in the specified dialog box.
»SubclassDlgItem«	Attaches a Windows control to a CWnd object and makes it route messages through the CWnd's message map.
Menu Functions — Public Members

»GetMenu«	Retrieves a pointer to the specified menu.
»SetMenu«	Sets the menu to the specified menu.
»DrawMenuBar«	Redraws the menu bar.
»GetSystemMenu«	Allows the application to access the Control menu for copying and modification.
»HiliteMenuItem«	Highlights or removes the highlighting from a top-level (menu-bar) menu item.
Timer Functions — Public Members

»SetTimer«	Installs a system timer that sends a »WM_TIMER« message when triggered.
»KillTimer«	Kills a system timer.
Alert Functions — Public Members

»FlashWindow«	Flashes the window once.
»MessageBox«	Creates and displays a window that contains an application-supplied message and caption.
Window Message Functions — Public Members

»PreTranslateMessage«	Used by CWinApp to filter window messages before they are dispatched to the TranslateMessage and DispatchMessage Windows functions.
»SendMessage«	Sends a message to the CWnd object and does not return until it has processed the message.
»PostMessage«	Places a message in the application queue, then returns without waiting for the window to process the message.
Clipboard Functions — Public Members

»ChangeClipboardChain«	Removes CWnd from the chain of Clipboard viewers.
»SetClipboardViewer«	Adds CWnd to the chain of windows that are notified whenever the contents of the Clipboard are changed.
»OpenClipboard«	Opens the Clipboard. Other applications will not be able to modify the Clipboard until the Windows CloseClipboard function is called.
»GetClipboardOwner«	Retrieves a pointer to the current owner of the Clipboard.
»GetOpenClipboardWindow«	Retrieves a pointer to the window that currently has the Clipboard open.
»GetClipboardViewer«	Retrieves a pointer to the first window in the chain of Clipboard viewers.
Initialization — Protected Members

»CreateEx«	Creates a Windows overlapped, pop-up, or child window and attaches it to a CWnd object.
Operations — Protected Members

»GetCurrentMessage«	Returns a pointer to the message this window is currently processing. Should only be called when in an OnMessage message-handler member function.
»Default«	Calls the default window procedure, which provides default processing for any window messages that an application does not process.
Overridables — Protected Members

»GetSuperWndProcAddr«	Accesses the default WndProc of a subclassed window.
»WindowProc«	Provides a window procedure for a CWnd. The default dispatches messages through the message map.
»DefWindowProc«	Calls the default window procedure, which provides default processing for any window messages that an application does not process.
»PostNcDestroy«	This virtual function is called by the default »OnNcDestroy« function after the window has been destroyed.
»OnChildNotify«	Called by a parent window to give a notifying control a chance to respond to a control notification.
»DoDataExchange«	For dialog data exchange and validation. Called by UpdateData.
Initialization Message Handlers — Protected Members

»OnInitMenu«	Called when a menu is about to become active.
»OnInitMenuPopup«	Called when a pop-up menu is about to become active.
System Message Handlers — Protected Members

»OnSysChar«	Called when a keystroke translates to a system character.
»OnSysCommand«	Called when the user selects a command from the Control menu, or when the user selects the Maximize or Minimize button.
»OnSysDeadChar«	Called when a keystroke translates to a system dead character (such as accent characters).
»OnSysKeyDown«	Called when the user holds down the ALT key and then presses another key.
»OnSysKeyUp«	Called when the user releases a key that was pressed while the ALT key was held down.
»OnCompacting«	Called when Windows detects that system memory is low.
»OnDevModeChange«	Called for all top-level windows when the user changes device-mode settings.
»OnFontChange«	Called when the pool of font resources changes.
»OnPaletteIsChanging«	Informs other applications when an application is going to realize its logical palette.
»OnPaletteChanged«	Called to allow windows that use a color palette to realize their logical palettes and update their client areas.
»OnSysColorChange«	Called for all top-level windows when a change is made in the system color setting.
»OnWindowPosChanging«	Called when the size, position, or Z-order is about to change as a result of a call to »SetWindowPos« or another window-management function.
»OnWindowPosChanged«	Called when the size, position, or Z-order has changed as a result of a call to »SetWindowPos« or another window-management function.
»OnDropFiles«	Called when the user releases the left mouse button over a window that has registered itself as the recipient of dropped files.
»OnSpoolerStatus«	Called from Print Manager whenever a job is added to or removed from the Print Manager queue.
»OnTimeChange«	Called for all top-level windows after the system time changes.
»OnWinIniChange«	Called for all top-level windows after the Windows initialization file, WIN.INI, is changed.
General Message Handlers — Protected Members

»OnCommand«	Called when the user selects a command.
»OnActivate«	Called when CWnd is being activated or deactivated.
»OnActivateApp«	Called when the application is about to be activated or deactivated.
»OnCancelMode«	Called to allow CWnd to cancel any internal modes, such as mouse capture.
»OnChildActivate«	Called for multiple document interface (MDI) child windows whenever the size or position of CWnd changes or CWnd is activated.
»OnClose«	Called as a signal that CWnd should be closed.
»OnCreate«	Called as a part of window creation.
»OnCtlColor«	Called if CWnd is the parent of a control when the control is about to be drawn.
»OnDestroy«	Called when CWnd is being destroyed.
»OnEnable«	Called when CWnd is enabled or disabled.
»OnEndSession«	Called when the session is ending.
»OnEnterIdle«	Called to inform an application's main window procedure that a modal dialog box or a menu is entering an idle state.
»OnEraseBkgnd«	Called when the window background needs erasing.
»OnGetMinMaxInfo«	Called whenever Windows needs to know the maximized position or dimensions, or the minimum or maximum tracking size.
»OnIconEraseBkgnd«	Called when CWnd is minimized (iconic) and the background of the icon must be filled before painting the icon.
»OnKillFocus«	Called immediately before CWnd loses the input focus.
»OnMenuChar«	Called when the user presses a menu mnemonic character that doesn't match any of the predefined mnemonics in the current menu.
»OnMenuSelect«	Called when the user selects a menu item.
»OnMove«	Called after the position of the CWnd has been changed.
»OnPaint«	Called to repaint a portion of the window.
»OnParentNotify«	Called when a child window is created or destroyed, or when the user clicks a mouse button while the cursor is over the child window.
»OnQueryDragIcon«	Called when a minimized (iconic) CWnd is about to be dragged by the user.
»OnQueryEndSession«	Called when the user chooses to end the Windows session.
»OnQueryNewPalette«	Informs CWnd that it is about to receive the input focus.
»OnQueryOpen«	Called when CWnd is an icon and the user requests that the icon be opened.
»OnSetFocus«	Called after CWnd gains the input focus.
»OnShowWindow«	Called when CWnd is to be hidden or shown.
»OnSize«	Called after the size of CWnd has changed.
Control Message Handlers — Protected Members

»OnCharToItem«	Called by a child list box with the »LBS_WANTKEYBOARDINPUT« style in response to a »WM_CHAR« message.
»OnCompareItem«	Called to determine the relative position of a new item in a child sorted owner-draw combo box or list box.
»OnDeleteItem«	Called when an owner-draw child list box or combo box is destroyed or when items are removed from the control.
»OnDrawItem«	Called when a visual aspect of an owner-draw child button control, combo-box control, list-box control, or menu needs to be drawn.
»OnGetDlgCode«	Called for a control so the control can process arrow-key and TAB-key input itself.
»OnMeasureItem«	Called for an owner-draw child combo box, list box, or menu item when the control is created. CWnd informs Windows of the dimensions of the control.
»OnVKeyToItem«	Called by a list box owned by CWnd in response to a »WM_KEYDOWN« message.
Input Message Handlers — Protected Members

»OnChar«	Called when a keystroke translates to a nonsystem character.
»OnDeadChar«	Called when a keystroke translates to a nonsystem dead character (such as accent characters).
»OnHScroll«	Called when the user clicks the horizontal scroll bar of CWnd.
»OnKeyDown«	Called when a nonsystem key is pressed.
»OnKeyUp«	Called when a nonsystem key is released.
»OnLButtonDblClk«	Called when the user double-clicks the left mouse button.
»OnLButtonDown«	Called when the user presses the left mouse button.
»OnLButtonUp«	Called when the user releases the left mouse button.
»OnMButtonDblClk«	Called when the user double-clicks the middle mouse button.
»OnMButtonDown«	Called when the user presses the middle mouse button.
»OnMButtonUp«	Called when the user releases the middle mouse button.
»OnMouseActivate«	Called when the cursor is in an inactive window and the user presses a mouse button.
»OnMouseMove«	Called when the mouse cursor moves.
»OnRButtonDblClk«	Called when the user double-clicks the right mouse button.
»OnRButtonDown«	Called when the user presses the right mouse button.
»OnRButtonUp«	Called when the user releases the right mouse button.
»OnSetCursor«	Called if mouse input is not captured and the mouse causes cursor movement within a window.
»OnTimer«	Called after each interval specified in »SetTimer«.
»OnVScroll«	Called when the user clicks the window's vertical scroll bar.
Nonclient-Area Message Handlers — Protected Members

»OnNcActivate«	Called when the nonclient area needs to be changed to indicate an active or inactive state.
»OnNcCalcSize«	Called when the size and position of the client area need to be calculated.
»OnNcCreate«	Called prior to »OnCreate« when the nonclient area is being created.
»OnNcDestroy«	Called when the nonclient area is being destroyed.
»OnNcHitTest«	Called by Windows every time the mouse is moved if CWnd contains the cursor or has captured mouse input with SetCapture.
»OnNcLButtonDblClk«	Called when the user double-clicks the left mouse button while the cursor is within a nonclient area of CWnd.
»OnNcLButtonDown«	Called when the user presses the left mouse button while the cursor is within a nonclient area of CWnd.
»OnNcLButtonUp«	Called when the user releases the left mouse button while the cursor is within a nonclient area of CWnd.
»OnNcMButtonDblClk«	Called when the user double-clicks the middle mouse button while the cursor is within a nonclient area of CWnd.
»OnNcMButtonDown«	Called when the user presses the middle mouse button while the cursor is within a nonclient area of CWnd.
»OnNcMButtonUp«	Called when the user releases the middle mouse button while the cursor is within a nonclient area of CWnd.
»OnNcMouseMove«	Called when the cursor is moved within a nonclient area of CWnd.
»OnNcPaint«	Called when the nonclient area needs painting.
»OnNcRButtonDblClk«	Called when the user double-clicks the right mouse button while the cursor is within a nonclient area of CWnd.
»OnNcRButtonDown«	Called when the user presses the right mouse button while the cursor is within a nonclient area of CWnd.
»OnNcRButtonUp«	Called when the user releases the right mouse button while the cursor is within a nonclient area of CWnd.
MDI Message Handlers — Protected Members

»OnMDIActivate«	Called when an MDI child window is activated or deactivated.
Clipboard Message Handlers — Protected Members

»OnAskCbFormatName«	Called by a Clipboard viewer application when a Clipboard owner will display the Clipboard contents.
»OnChangeCbChain«	Notifies that a specified window is being removed from the chain.
»OnDestroyClipboard«	Called when the Clipboard is emptied through a call to the Windows EmptyClipboard function.
»OnDrawClipboard«	Called when the contents of the change.
»OnHScrollClipboard«	Called when a Clipboard owner should scroll the Clipboard image, invalidate the appropriate section, and update the scroll-bar values.
»OnPaintClipboard«	Called when the client area of the Clipboard viewer needs repainting.
»OnRenderAllFormats«	Called when the owner application is being destroyed and needs to render all its formats.
»OnRenderFormat«	Called for the Clipboard owner when a particular format with delayed rendering needs to be rendered.
»OnSizeClipboard«	Called when the size of the client area of the Clipboard-viewer window has changed.
»OnVScrollClipboard«	Called when the owner should scroll the Clipboard image, invalidate the appropriate section, and update the scroll-bar values.


CWnd Member Functions
  Member Functions

To get information on a particular member function, double-click it in the Contents window.


  CWnd::ArrangeIconicWindows

UINT ArrangeIconicWindows();

Remarks

Arranges all the minimized (iconic) child windows.

This member function also arranges icons on the desktop window, which covers the entire screen. The »GetDesktopWindow« member function retrieves a pointer to the desktop window object.

To arrange iconic MDI child windows in an MDI client window, call »CMDIFrameWnd::MDIIconArrange«.

Return Value

The height of one row of icons if the function is successful; otherwise 0.

See Also

»CWnd::GetDesktopWindow«, »CMDIFrameWnd::MDIIconArrange«,  ::ArrangeIconicWindows


  CWnd::Attach

BOOL Attach( HWND hWndNew );

hWndNew    Specifies a handle to a Windows window.

Remarks

Attaches a Windows window to a CWnd object.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWnd::Detach«, »CWnd::m_hWnd«, »CWnd::SubclassWindow«


  CWnd::BeginPaint

CDC* BeginPaint( LPPAINTSTRUCT lpPaint );

lpPaint    Points to the »PAINTSTRUCT« structure that is to receive painting information.

Remarks

Prepares CWnd for painting and fills a PAINTSTRUCT data structure with information about the painting.

The paint structure contains a »RECT« data structure that has the smallest rectangle that completely encloses the update region and a flag that specifies whether the background has been erased.

The update region is set by the »Invalidate«, »InvalidateRect«, or »InvalidateRgn« member functions and by the system after it sizes, moves, creates, scrolls, or performs any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends an »WM_ONERASEBKGND« message.

Do not call the BeginPaint member function except in response to a »WM_PAINT« message. Each call to the BeginPaint member function must have a matching call to the »EndPaint« member function. If the caret is in the area to be painted, the BeginPaint member function automatically hides the caret to prevent it from being erased.

Return Value

Identifies the device context for CWnd. The pointer may be temporary and should not be stored beyond the scope of EndPaint.

See Also

»CWnd::EndPaint«, »CWnd::Invalidate«, »CWnd::InvalidateRgn«, ::BeginPaint, »CPaintDC«


  CWnd::BringWindowToTop

void BringWindowToTop();

Remarks

Brings CWnd to the top of a stack of overlapping windows. In addition, BringWindowToTop activates pop-up, top-level, and MDI child windows. The BringWindowToTop member function should be used to uncover any window that is partially or completely obscured by any overlapping windows.

Calling this function is similar to calling the SetWindowPos function to change a window's position in the Z order. The BringWindowToTop function does not change the window style to make it a top-level window of the desktop.

See Also

 ::BringWindowToTop


  CWnd::CalcWindowRect

virtual void CalcWindowRect( LPRECT lpClientRect );

lpClientRect    The client rectangle.

Remarks

Call this member function to compute the required size of the window rectangle based on the desired client-rectangle size. The resulting window rectangle (contained in lpClientRect) can then be passed to the Create member function to create a window whose client area is the desired size.

Called by the framework to size windows prior to creation.

A client rectangle is the smallest rectangle that completely encloses a client area. A window rectangle is the smallest rectangle that completely encloses the window.

See Also

 ::AdjustWindowRect


  CWnd::ChangeClipboardChain

BOOL ChangeClipboardChain( HWND hWndNext );

hWndNext    Identifies the window that follows CWnd in the Clipboard-viewer chain.

Remarks

Removes CWnd from the chain of Clipboard viewers and makes the window specified by hWndNext the descendant of the CWnd ancestor in the chain.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWnd::SetClipboardViewer«,  ::ChangeClipboardChain


  CWnd::CheckDlgButton

void CheckDlgButton( int nIDButton, UINT nCheck );

nIDButton    Specifies the button to be modified.

nCheck    Specifies the action to take. If nCheck is nonzero, the CheckDlgButton member function places a check mark next to the button; if 0, the check mark is removed. For three-state buttons, if nCheck is 2, the button state is indeterminate.

Remarks

Selects (places a check mark next to) or clears (removes a check mark from) a button, or it changes the state of a three-state button.

The CheckDlgButton function sends a BM_SETCHECK message to the specified button.

See Also

»CWnd::IsDlgButtonChecked«, »CButton::SetCheck«,  ::CheckDlgButton


  CWnd::CheckRadioButton

void CheckRadioButton( int nIDFirstButton, int nIDLastButton,
int nIDCheckButton );

nIDFirstButton    Specifies the integer identifier of the first radio button in the group.

nIDLastButton    Specifies the integer identifier of the last radio button in the group.

nIDCheckButton    Specifies the integer identifier of the radio button to be checked.

Remarks

Selects (adds a check mark to) a given radio button in a group and clears (removes a check mark from) all other radio buttons in the group.

The CheckRadioButton function sends a BM_SETCHECK message to the specified radio button.

See Also

»CWnd::GetCheckedRadioButton«, »CButton::SetCheck«,  ::CheckRadioButton


  CWnd::ChildWindowFromPoint

CWnd* ChildWindowFromPoint( POINT point ) const;

point    Specifies the client coordinates of the point to be tested.

Remarks

Determines which, if any, of the child windows belonging to CWnd contains the specified point.

Return Value

Identifies the child window that contains the point. It is NULL if the given point lies outside of the client area. If the point is within the client area but is not contained within any child window, CWnd is returned.

This member function will return a hidden or disabled child window that contains the specified point.

More than one window may contain the given point. However, this function returns only the CWnd* of the first window encountered that contains the point.

The CWnd* that is returned may be temporary and should not be stored for later use.

See Also

»CWnd::WindowFromPoint«,  ::ChildWindowFromPoint


  CWnd::ClientToScreen

void ClientToScreen( LPPOINT lpPoint ) const;

void ClientToScreen( LPRECT lpRect ) const;

lpPoint    Points to a »POINT« structure or CPoint object that contains the client coordinates to be converted.

lpRect    Points to a »RECT« structure or CRect object that contains the client coordinates to be converted.

Remarks

Converts the client coordinates of a given point or rectangle on the display to screen coordinates. The ClientToScreen member function uses the client coordinates in the POINT or RECT structure or the CPoint or CRect object pointed to by lpPoint or lpRect to compute new screen coordinates; it then replaces the coordinates in the structure with the new coordinates. The new screen coordinates are relative to the upper-left corner of the system display.

The ClientToScreen member function assumes that the given point or rectangle is in client coordinates.

See Also

»CWnd::ScreenToClient«,  ::ClientToScreen


  CWnd::Create

virtual BOOL Create( LPCSTR lpszClassName, LPCSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);

lpszClassName    Points to a null-terminated character string that names the Windows class (a WNDCLASS structure). The class name can be any name registered with the global AfxRegisterWndClass function or any of the predefined control-class names. If NULL, uses the default CWnd attributes.

lpszWindowName    Points to a null-terminated character string that contains the window name.

dwStyle    Specifies the »window style« attributes.

rect    The size and position of the window, in client coordinates of pParentWnd.

pParentWnd    The parent window.

nID    The ID of the child window.

pContext    The create context of the window.

Remarks

Creates a Windows child window and attaches it to the CWnd object.

You construct a child window in two steps. First, invoke the constructor, which constructs the CWnd object. Then call Create, which creates the Windows child window and attaches it to CWnd. Create initializes the window's class name and window name and registers values for its style, parent, and ID.

Return Value

Nonzero if successful; otherwise 0.

 Window Styles

•	WS_BORDER    Creates a window that has a border.

•	WS_CAPTION    Creates a window that has a title bar (implies the WS_BORDER style). This style cannot be used with the WS_DLGFRAME style.

•	WS_CHILD    Creates a child window. Cannot be used with the WS_POPUP style.

•	WS_CLIPCHILDREN    Excludes the area occupied by child windows when you draw within the parent window. Used when you create the parent window.

•	WS_CLIPSIBLINGS    Clips child windows relative to each other; that is, when a particular child window receives a paint message, the WS_CLIPSIBLINGS style clips all other overlapped child windows out of the region of the child window to be updated. (If WS_CLIPSIBLINGS is not given and child windows overlap, when you draw within the client area of a child window, it is possible to draw within the client area of a neighboring child window.) For use with the WS_CHILD style only.

•	WS_DISABLED    Creates a window that is initially disabled.

•	WS_DLGFRAME    Creates a window with a double border but no title.

•	WS_GROUP    Specifies the first control of a group of controls in which the user can move from one control to the next with the arrow keys. All controls defined with the WS_GROUP style after the first control belong to the same group. The next control with the WS_GROUP style ends the style group and starts the next group (that is, one group ends where the next begins).

•	WS_HSCROLL    Creates a window that has a horizontal scroll bar.

•	WS_MAXIMIZE    Creates a window of maximum size.

•	WS_MAXIMIZEBOX    Creates a window that has a Maximize button.

•	WS_MINIMIZE    Creates a window that is initially minimized. For use with the WS_OVERLAPPED style only.

•	WS_MINIMIZEBOX    Creates a window that has a Minimize button.

•	WS_OVERLAPPED    Creates an overlapped window. An overlapped window usually has a caption and a border.

•	WS_OVERLAPPEDWINDOW    Creates an overlapped window with the WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles.

•	WS_POPUP    Creates a pop-up window. Cannot be used with the WS_CHILD style.

•	WS_POPUPWINDOW    Creates a pop-up window with the WS_BORDER, WS_POPUP, and WS_SYSMENU styles. The WS_CAPTION style must be combined with the WS_POPUPWINDOW style to make the Control menu visible.

•	WS_SYSMENU    Creates a window that has a Control-menu box in its title bar. Used only for windows with title bars.

•	WS_TABSTOP    Specifies one of any number of controls through which the user can move by using the TAB key. The TAB key moves the user to the next control specified by the WS_TABSTOP style.

•	WS_THICKFRAME    Creates a window with a thick frame that can be used to size the window.

•	WS_VISIBLE    Creates a window that is initially visible.

•	WS_VSCROLL    Creates a window that has a vertical scroll bar.

See Also

»CWnd::CWnd«, »CWnd::CreateEx«


  CWnd::CreateCaret

void CreateCaret( CBitmap* pBitmap );

pBitmap    Identifies the bitmap that defines the caret shape.

Remarks

Creates a new shape for the system caret and claims ownership of the caret.

The bitmap must have previously been created by the »CBitmap::CreateBitmap« member function, the CreateDIBitmap Windows function, or the »CBitmap::LoadBitmap« member function.

CreateCaret automatically destroys the previous caret shape, if any, regardless of which window owns the caret. Once created, the caret is initially hidden. To show the caret, the »ShowCaret« member function must be called.

The system caret is a shared resource. CWnd should create a caret only when it has the input focus or is active. It should destroy the caret before it loses the input focus or becomes inactive.

See Also

»CBitmap::CreateBitmap«, ::CreateDIBitmap, ::DestroyCaret,  »CBitmap::LoadBitmap«, »CWnd::ShowCaret«, ::CreateCaret


  CWnd::CreateEx

Protected

BOOL CreateEx( DWORD dwExStyle, LPCSTR lpszClassName, LPCSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu,
LPSTR lpParam = NULL ); ♦

dwExStyle    Specifies the extended style of the CWnd being created.

See »Extended Window Styles« below for a description of the possible values.

lpszClassName    Points to a null-terminated character string that names the Windows class (a WNDCLASS structure). The class name can be any name registered with the global »AfxRegisterWndClass« function or any of the predefined control-class names. It must not be NULL.

lpszWindowName    Points to a null-terminated character string that contains the window name.

dwStyle    Specifies the window style attributes.

See »CWnd::Create« for a description of the possible values.

x    Specifies the initial x-position of the CWnd window.

y    Specifies the initial top position of the CWnd window.

nWidth    Specifies the width (in device units) of the CWnd window.

nHeight    Specifies the height (in device units) of the CWnd window.

hwndParent    Identifies the parent or owner window of the CWnd window being created. Use NULL for top-level windows.

nIDorHMenu    Identifies a menu or a child-window identifier. The meaning depends on the style of the window.

lpParam     Points to a value that is passed to the window through the CREATESTRUCT structure.

Remarks

Creates an overlapped, pop-up, or child window with the extended style specified in dwExStyle.

The CreateEx parameters specify the WNDCLASS, window title, window style, and (optionally) initial position and size of the window. CreateEx also specifies the window's parent (if any) and ID.

When CreateEx executes, Windows sends the »WM_GETMINMAXINFO«, »WM_NCCREATE«, »WM_NCCALCSIZE«, and »WM_CREATE« messages to the window.

To extend the default message handling, derive a class from CWnd, add a message map to the new class, and provide member functions for the above messages. Override OnCreate, for example, to perform needed initialization for a new class.

Override further OnMessage message handlers to add further functionality to your derived class.

If the WS_VISIBLE style is given, Windows sends the window all the messages required to activate and show the window. If the window style specifies a title bar, the window title pointed to by the lpszWindowName parameter is displayed in the title bar.

The dwStyle parameter can be any combination of »window styles«.

Return Value

Nonzero if successful; otherwise 0.

 Extended Window Styles

•	WS_EX_DLGMODALFRAME    Designates a window with a double border that may (optionally) be created with a title bar when you specify the WS_CAPTION style flag in the dwStyle parameter.

•	WS_EX_NOPARENTNOTIFY    Specifies that a child window created with this style will not send the WM_PARENTNOTIFY message to its parent window when the child window is created or destroyed.

Windows 3.1 Only

•	WS_EX_ACCEPTFILES    Specifies that a window created with this style accepts drag-and-drop files.

•	WS_EX_TOPMOST    Specifies that a window created with this style should be placed above all nontopmost windows and stay above them even when the window is deactivated. An application can use the SetWindowPos member function to add or remove this attribute.

•	WS_EX_TRANSPARENT    Specifies that a window created with this style is to be transparent. That is, any windows that are beneath the window are not obscured by the window. A window created with this style receives WM_PAINT messages only after all sibling windows beneath it have been updated. ♦

See Also

::CreateWindowEx


  CWnd::CreateGrayCaret

void CreateGrayCaret( int nWidth, int nHeight );

nWidth    Specifies the width of the caret (in logical units). If this parameter is 0, the width is set to the system-defined window-border width.

nHeight    Specifies the height of the caret (in logical units). If this parameter is 0, the height is set to the system-defined window-border height.

Remarks

Creates a gray rectangle for the system caret and claims ownership of the caret. The caret shape can be a line or a block.

The parameters nWidth and nHeight specify the caret's width and height (in logical units); the exact width and height (in pixels) depend on the mapping mode.

The system's window-border width or height can be retrieved by the GetSystemMetrics Windows function with the SM_CXBORDER and SM_CYBORDER indexes. Using the window-border width or height ensures that the caret will be visible on a high-resolution display.

The CreateGrayCaret member function automatically destroys the previous caret shape, if any, regardless of which window owns the caret. Once created, the caret is initially hidden. To show the caret, the »ShowCaret« member function must be called.

The system caret is a shared resource. CWnd should create a caret only when it has the input focus or is active. It should destroy the caret before it loses the input focus or becomes inactive.

See Also

::DestroyCaret, ::GetSystemMetrics, »CWnd::ShowCaret«, ::CreateCaret


  CWnd::CreateSolidCaret

void CreateSolidCaret( int nWidth, int nHeight );

nWidth    Specifies the width of the caret (in logical units). If this parameter is 0, the width is set to the system-defined window-border width.

nHeight    Specifies the height of the caret (in logical units). If this parameter is 0, the height is set to the system-defined window-border height.

Remarks

Creates a solid rectangle for the system caret and claims ownership of the caret. The caret shape can be a line or block.

The parameters nWidth and nHeight specify the caret's width and height (in logical units); the exact width and height (in pixels) depend on the mapping mode.

The system's window-border width or height can be retrieved by the GetSystemMetrics Windows function with the SM_CXBORDER and SM_CYBORDER indexes. Using the window-border width or height ensures that the caret will be visible on a high-resolution display.

The CreateSolidCaret member function automatically destroys the previous caret shape, if any, regardless of which window owns the caret. Once created, the caret is initially hidden. To show the caret, the »ShowCaret« member function must be called.

The system caret is a shared resource. CWnd should create a caret only when it has the input focus or is active. It should destroy the caret before it loses the input focus or becomes inactive.

See Also

::DestroyCaret, ::GetSystemMetrics, »CWnd::ShowCaret«, ::CreateCaret


  CWnd::CWnd

CWnd();

Remarks

Constructs a CWnd object. The Windows window is not created and attached until the CreateEx or Create member function is called.

See Also

»CWnd::CreateEx«, »CWnd::Create«


  CWnd::Default

Protected

LRESULT Default(); ♦

Remarks

Calls the default window procedure. The default window procedure provides default processing for any window message that an application does not process. This member function ensures that every message is processed.

Return Value

Depends on the message sent.

See Also

»CWnd::DefWindowProc«,  ::DefWindowProc


  CWnd::DefWindowProc

Protected

virtual LRESULT DefWindowProc( UINT message, WPARAM wParam, LPARAM lParam ); ♦

message    Specifies the Windows message to be processed.

wParam    Specifies additional message-dependent information.

lParam    Specifies additional message-dependent information.

Remarks

Calls the default window procedure, which provides default processing for any window message that an application does not process. This member function ensures that every message is processed. It should be called with the same parameters as those received by the window procedure.

Return Value

Depends on the message sent.

See Also

»CWnd::Default«,  ::DefWindowProc


  CWnd::DeleteTempMap

static void PASCAL DeleteTempMap();

Remarks

Called automatically by the idle time handler of the CWinApp object. Deletes any temporary CWnd objects created by the FromHandle member function.

See Also

»CWnd::FromHandle«


  CWnd::DestroyWindow

virtual BOOL DestroyWindow();

Remarks

Destroys the Windows window attached to the CWnd object. The DestroyWindow member function sends appropriate messages to the window to deactivate it and remove the input focus. It also destroys the window's menu, flushes the application queue, destroys outstanding timers, removes Clipboard ownership, and breaks the Clipboard-viewer chain if CWnd is at the top of the viewer chain. It sends »WM_DESTROY« and »WM_NCDESTROY« messages to the window. It does not destroy the CWnd object.

If the window is the parent of any windows, these child windows are automatically destroyed when the parent window is destroyed. The DestroyWindow member function destroys child windows first and then the window itself.

The DestroyWindow member function also destroys modeless dialog boxes created by »CDialog::Create«.

If the CWnd being destroyed is a child window and does not have the »WS_EX_NOPARENTNOTIFY« style set, then the WM_PARENTNOTIFY message is sent to the parent.

Return Value

Nonzero if the window is destroyed; otherwise 0.

See Also

»CWnd::OnDestroy«, »CWnd::Detach«, ::DestroyWindow


  CWnd::Detach

HWND Detach();

Remarks

Detaches a Windows handle from a CWnd object and returns the handle.

Return Value

A HWND to the Windows object.

See Also

»CWnd::Attach«


  CWnd::DlgDirList

int DlgDirList( LPSTR lpPathSpec, int nIDListBox, int nIDStaticPath,
UINT nFileType );

lpPathSpec    Points to a null-terminated string that contains the path or filename. DlgDirList modifies this string, which should be long enough to contain the modifications. For more information, see the following "Remarks" section.

nIDListBox    Specifies the identifier of a list box. If nIDListBox is 0, DlgDirList assumes that no list box exists and does not attempt to fill one.

nIDStaticPath    Specifies the identifier of the static-text control used to display the current drive and directory. If nIDStaticPath is 0, DlgDirList assumes that no such text control is present.

nFileType    Specifies the attributes of the files to be displayed. It can be any combination of the following values:

•	DDL_READWRITE    Read-write data files with no additional attributes.

•	DDL_READONLY    Read-only files.

•	DDL_HIDDEN    Hidden files.

•	DDL_SYSTEM    System files.

•	DDL_DIRECTORY    Directories.

•	DDL_ARCHIVE    Archives.

•	DDL_POSTMSGS    LB_DIR flag. If the LB_DIR flag is set, Windows places the messages generated by DlgDirList in the application's queue; otherwise, they are sent directly to the dialog-box procedure.

•	DDL_DRIVES    Drives. If the DDL_DRIVES flag is set, the DDL_EXCLUSIVE flag is set automatically. Therefore, to create a directory listing that includes drives and files, you must call DlgDirList twice: once with the DDL_DRIVES flag set and once with the flags for the rest of the list.

•	DDL_EXCLUSIVE    Exclusive bit. If the exclusive bit is set, only files of the specified type are listed; otherwise normal files and files of the specified type are listed.

Remarks

Fills a list box with a file or directory listing. DlgDirList sends LB_RESETCONTENT and LB_DIR messages to the list box. It fills the list box specified by nIDListBox with the names of all files that match the path given by lpPathSpec.

The lpPathSpec parameter has the following form:

[drive:] [ [\u]directory[\idirectory]...\u] [filename]

In this example, drive is a drive letter, directory is a valid directory name, and filename is a valid filename that must contain at least one wildcard. The wildcards are a question mark (?), which means match any character, and an asterisk (*), meaning match any number of characters.

If you specify a 0-length string for lpPathSpec, or if you specify only a directory name but do not include any file specification, the string will be changed to "*.*".

If lpPathSpec includes a drive and/or directory name, the current drive and directory are changed to the designated drive and directory before the list box is filled. The text control identified by nIDStaticPath is also updated with the new drive and/or directory name.

After the list box is filled, lpPathSpec is updated by removing the drive and/or directory portion of the path.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::DlgDirListComboBox«,  ::DlgDirList


  CWnd::DlgDirListComboBox

int DlgDirListComboBox( LPSTR lpPathSpec, int nIDComboBox,
int nIDStaticPath, UINT nFileType );

lpPathSpec    Points to a null-terminated string that contains the path or filename. DlgDirListComboBox modifies this string, which should be long enough to contain the modifications. For more information, see the following "Remarks" section.

nIDComboBox    Specifies the identifier of a combo box in a dialog box. If nIDComboBox is 0, DlgDirListComboBox assumes that no combo box exists and does not attempt to fill one.

nIDStaticPath    Specifies the identifier of the static-text control used to display the current drive and directory. If nIDStaticPath is 0, DlgDirListComboBox assumes that no such text control is present.

nFileType    Specifies DOS file attributes of the files to be displayed. It can be any combination of the following values:

•	DDL_READWRITE    Read-write data files with no additional attributes.

•	DDL_READONLY    Read-only files.

•	DDL_HIDDEN    Hidden files.

•	DDL_SYSTEM    System files.

•	DDL_DIRECTORY    Directories.

•	DDL_ARCHIVE    Archives.

•	DDL_POSTMSGS    CB_DIR flag. If the CB_DIR flag is set, Windows places the messages generated by DlgDirListComboBox in the application's queue; otherwise, they are sent directly to the dialog-box procedure.

•	DDL_DRIVES    Drives. If the DDL_DRIVES flag is set, the DDL_EXCLUSIVE flag is set automatically. Therefore, to create a directory listing that includes drives and files, you must call DlgDirListComboBox twice: once with the DDL_DRIVES flag set and once with the flags for the rest of the list.

•	DDL_EXCLUSIVE    Exclusive bit. If the exclusive bit is set, only files of the specified type are listed; otherwise normal files and files of the specified type are listed.

Remarks

Fills the list box of a combo box with a file or directory listing. DlgDirListComboBox sends CB_RESETCONTENT and CB_DIR messages to the combo box. It fills the list box of the combo box specified by nIDComboBox with the names of all files that match the path given by lpPathSpec.

The lpPathSpec parameter has the following form:

[drive:] [ [\u]directory[\idirectory]...\u] [filename]

In this example, drive is a drive letter, directory is a valid directory name, and filename is a valid filename that must contain at least one wildcard. The wildcards are a question mark (?), which means match any character, and an asterisk (*), which means match any number of characters.

If you specify a zero-length string for lpPathSpec, or if you specify only a directory name but do not include any file specification, the string will be changed to "*.*".

If lpPathSpec includes a drive and/or directory name, the current drive and directory are changed to the designated drive and directory before the list box is filled. The text control identified by nIDStaticPath is also updated with the new drive and/or directory name.

After the combo-box list box is filled, lpPathSpec is updated by removing the drive and/or directory portion of the path.

Return Value

Specifies the outcome of the function. It is nonzero if a listing was made, even an empty listing. A 0 return value implies that the input string did not contain a valid search path.

See Also

»CWnd::DlgDirList«, »CWnd::DlgDirSelect«,  ::DlgDirListComboBox


  CWnd::DlgDirSelect

BOOL DlgDirSelect( LPSTR lpString, int nIDListBox );

lpString    Points to a buffer that is to receive the current selection in the list box.

nIDListBox    Specifies the integer ID of a list box in the dialog box.

Remarks

Retrieves the current selection from a list box. It assumes that the list box has been filled by the »DlgDirList« member function and that the selection is a drive letter, a file, or a directory name.

The DlgDirSelect member function copies the selection to the buffer given by lpString. If there is no selection, lpString does not change.

DlgDirSelect sends LB_GETCURSEL and LB_GETTEXT messages to the list box

It does not allow more than one filename to be returned from a list box. The list box must not be a multiple-selection list box.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWnd::DlgDirList«, »CWnd::DlgDirListComboBox«, »CWnd::DlgDirSelectComboBox«, ::DlgDirSelect


  CWnd::DlgDirSelectComboBox

BOOL DlgDirSelectComboBox( LPSTR lpString, int nIDComboBox );

lpString    Points to a buffer that is to receive the selected path.

nIDComboBox    Specifies the integer ID of the combo box in the dialog box.

Remarks

Retrieves the current selection from the list box of a combo box. It assumes that the list box has been filled by the »DlgDirListComboBox« member function and that the selection is a drive letter, a file, or a directory name.

The DlgDirSelectComboBox member function copies the selection to the specified buffer. If there is no selection, the contents of the buffer are not changed.

DlgDirSelectComboBox sends CB_GETCURSEL and CB_GETLBTEXT messages to the combo box.

It does not allow more than one filename to be returned from a combo box.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWnd::DlgDirListComboBox«, ::DlgDirSelectComboBox


  CWnd::DoDataExchange

Protected

virtual void DoDataExchange( CDataExchange* pDX );

pDX    A pointer to a CDataExchange object.

Remarks

Called by the framework to exchange and validate dialog data.

Never call this function directly. It is called by the UpdateData member function. Call UpdateData to initialize a dialog box's controls or retrieve data from a dialog box.

When you derive an application-specific dialog class from CDialog, you need to override this member function if you wish to utilize the framework's automatic data exchange and validation. ClassWizard will write an overridden version of this member function for you containing the desired "data map" of dialog data exchange (DDX) and validation (DDV) global function calls.

To automatically generate an overridden version of this member function, first create a dialog resource with App Studio, then derive an application-specific dialog class. Then invoke ClassWizard and use it associate variables, data, and validation ranges with various controls in the new dialog box. ClassWizard then writes the overridden DoDataExchange, which contains a data map. The following is an example DDX/DDV code block generated by ClassWizard:

void CPenWidthsDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CPenWidthsDlg)

DDX_Text(pDX, IDC_THIN_PEN_WIDTH, m_nThinWidth);

DDV_MinMaxInt(pDX, m_nThinWidth, 1, 20);

DDX_Text(pDX, IDC_THICK_PEN_WIDTH, m_nThickWidth);

DDV_MinMaxInt(pDX, m_nThickWidth, 1, 20);

//}}AFX_DATA_MAP

}

ClassWizard will maintain the code within the \\{{ and \\}} delimiters. You should not modify this code.

The DoDataExchange overridden member function must precede the macro statements in your source file.

For more information on dialog data exchange and validation, see Chapter 7 of the Class Library User's Guide, or see Chapter 9 of the App Studio User's Guide. For a description of the DDX_ and DDV_ macros generated by ClassWizard, see Technical Note 26 in MSVCNT\HELP\MFCNOTES.HLP.

See Also

»CWnd::UpdateData«


  CWnd::DragAcceptFiles

Windows 3.1 Only

void DragAcceptFiles( BOOL bAccept = TRUE ); ♦

bAccept    Flag that indicates whether dragged files are accepted.

Remarks

Call this member function from within the main window in your application's CWinApp::InitInstance function to indicate that your main window and all child windows accept dropped files from the Windows File Manager.

To discontinue receiving dragged files, call the member function with bAccept equal to FALSE.

See Also

::DragAcceptFiles, WM_DROPFILES


  CWnd::DrawMenuBar

void DrawMenuBar();

Remarks

Redraws the menu bar. If a menu bar is changed after Windows has created the window, call this function to draw the changed menu bar.

See Also

 ::DrawMenuBar


  CWnd::EnableScrollBar

Windows 3.1 Only

BOOL EnableScrollBar( int nSBFlags, UINT nArrowFlags = ESB_ENABLE_BOTH ); ♦

nSBFlags    Specifies the scroll-bar type. Can have one of the following values:

•	SB_BOTH    Enables or disables the arrows of the horizontal and vertical scroll bars associated with the window.

•	SB_HORZ    Enables or disables the arrows of the horizontal scroll bar associated with the window.

•	SB_VERT    Enables or disables the arrows of the vertical scroll bar associated with the window.

nArrowFlags    Specifies whether the scroll-bar arrows are enabled or disabled and which arrows are enabled or disabled. Can have one of the following values:

•	ESB_ENABLE_BOTH    Enables both arrows of a scroll bar (default).

•	ESB_DISABLE_LTUP    Disables the left arrow of a horizontal scroll bar or the up arrow of a vertical scroll bar.

•	ESB_DISABLE_RTDN    Disables the right arrow of a horizontal scroll bar or the down arrow of a vertical scroll bar.

•	ESB_DISABLE_BOTH    Disables both arrows of a scroll bar.

Remarks

Enables or disables one or both arrows of a scroll bar.

Return Value

Nonzero if the arrows are enabled or disabled as specified. Otherwise it is 0, which indicates that the arrows are already in the requested state or that an error occurred.

See Also

»CWnd::ShowScrollBar«, »CScrollBar::EnableScrollBar«


  CWnd::EnableScrollBarCtrl

void EnableScrollBarCtrl( int nBar, BOOL bEnable = TRUE );

nBar    The scroll-bar identifier.

bEnable    Specifies whether the scroll-bar is to be enabled or disabled.

Remarks

Call this member function to enable or disable the scroll bar for this window. If the window has a sibling scroll-bar control, that scroll bar is used; otherwise the window's own scroll bar is used.

See Also

»CWnd::GetScrollBarCtrl«


  CWnd::EnableWindow

BOOL EnableWindow( BOOL bEnable = TRUE );

bEnable    Specifies whether the given window is to be enabled or disabled. If this parameter is TRUE, the window will be enabled. If this parameter is FALSE, the window will be disabled.

Remarks

Enables or disables mouse and keyboard input. When input is disabled, input such as mouse clicks and keystrokes is ignored. When input is enabled, the window processes all input.

If the enabled state is changing, the »WM_ENABLE« message is sent before this function returns.

If disabled, all child windows are implicitly disabled, although they are not sent WM_ENABLE messages.

A window must be enabled before it can be activated. For example, if an application is displaying a modeless dialog box and has disabled its main window, the main window must be enabled before the dialog box is destroyed. Otherwise, another window will get the input focus and be activated. If a child window is disabled, it is ignored when Windows tries to determine which window should get mouse messages.

By default, a window is enabled when it is created. An application can specify the WS_DISABLED style in the Create or CreateEx member function to create a window that is initially disabled. After a window has been created, an application can also use the EnableWindow member function to enable or disable the window.

An application can use this function to enable or disable a control in a dialog box. A disabled control cannot receive the input focus nor can a user access it.

Return Value

Indicates the state before the EnableWindow member function was called. The return value is nonzero if the window was previously disabled. The return value is 0 if the window was previously enabled or an error occurred.

See Also

::EnableWindow, »CWnd::OnEnable«


  CWnd::EndPaint

void EndPaint( LPPAINTSTRUCT lpPaint );

lpPaint    Points to a »PAINTSTRUCT« structure that contains the painting information retrieved by the BeginPaint member function.

Remarks

Marks the end of painting in the given window. The EndPaint member function is required for each call to the »BeginPaint« member function, but only after painting is complete.

If the caret was hidden by the BeginPaint member function, EndPaint restores the caret to the screen.

See Also

»CWnd::BeginPaint«, ::EndPaint, »CPaintDC«


  CWnd::FindWindow

static CWnd* PASCAL FindWindow( LPCSTR lpszClassName,
LPCSTR lpszWindowName );

lpszClassName    Points to a null-terminated string that specifies the window's class name (a WNDCLASS structure). If lpClassName is NULL, all class names match.

lpszWindowName    Points to a null-terminated string that specifies the window name (the window's title). If lpWindowName is NULL, all window names match.

Remarks

Returns the top-level CWnd whose window class is given by lpszClassName and whose window name, or title, is given by lpszWindowName. This function does not search child windows.

Return Value

Identifies the window that has the specified class name and window name. It is NULL if no such window is found.

The CWnd* may be temporary and should not be stored for later use.

See Also

::FindWindow


  CWnd::FlashWindow

BOOL FlashWindow( BOOL bInvert );

bInvert    Specifies whether the CWnd is to be flashed or returned to its original state. The CWnd is flashed from one state to the other if bInvert is TRUE. If bInvert is FALSE, the window is returned to its original state (either active or inactive).

Remarks

Flashes the given window once. For successive flashing, create a system timer and repeatedly call FlashWindow. Flashing the CWnd means changing the appearance of its title bar as if the CWnd were changing from inactive to active status, or vice versa. (An inactive title bar changes to an active title bar; an active title bar changes to an inactive title bar.)

Typically, a window is flashed to inform the user that it requires attention but that it does not currently have the input focus.

The bInvert parameter should be FALSE only when the window is getting the input focus and will no longer be flashing; it should be TRUE on successive calls while waiting to get the input focus.

This function always returns nonzero for minimized windows. If the window is minimized, FlashWindow will simply flash the window's icon; bInvert is ignored for minimized windows.

Return Value

Nonzero if the window was active before the call to the FlashWindow member function; otherwise 0.

See Also

::FlashWindow


  CWnd::FromHandle

static CWnd* PASCAL FromHandle( HWND hWnd );

hWnd    An HWND of a Windows window.

Return Value

Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, a temporary CWnd object is created and attached.

The pointer may be temporary and should not be stored beyond immediate use.

See Also

»CWnd::DeleteTempMap«


  CWnd::FromHandlePermanent

static CWnd* PASCAL FromHandlePermanent( HWND hWnd );

hWnd     An HWND of a Windows window.

Remarks

Returns a pointer to a CWnd object when given a handle to a window. If a CWnd object is not attached to the handle, NULL is returned.

This function, unlike FromHandle, does not create temporary objects.

Return Value

A pointer to a CWnd object.

See Also

»CWnd::FromHandle«


  CWnd::GetActiveWindow

static CWnd* PASCAL GetActiveWindow();

Remarks

Retrieves a pointer to the active window. The active window is either the window that has the current input focus or the window explicitly made active by the »SetActiveWindow« member function.

Return Value

The active window or NULL if no window was active at the time of the call. The pointer may be temporary and should not be stored for later use.

See Also

»CWnd::SetActiveWindow«, ::GetActiveWindow


  CWnd::GetCapture

static CWnd* PASCAL GetCapture();

Remarks

Retrieves the window that has the mouse capture. Only one window has the mouse capture at any given time. A window receives the mouse capture when the »SetCapture« member function is called. This window receives mouse input whether or not the cursor is within its borders.

Return Value

Identifies the window that has the mouse capture. It is NULL if no window has the mouse capture.

The return value may be temporary and should not be stored for later use.

See Also

»CWnd::SetCapture«, ::GetCapture


  CWnd::GetCaretPos

static CPoint PASCAL GetCaretPos();

Remarks

Retrieves the client coordinates of the caret's current position and returns them as a CPoint.

The caret position is given in the client coordinates of the CWnd window.

Return Value

CPoint object containing the coordinates of the caret's position.

See Also

::GetCaretPos


  CWnd::GetCheckedRadioButton

int GetCheckedRadioButton( int nIDFirstButton, int nIDLastButton );

nIDFirstButton    Specifies the integer identifier of the first radio button in the group.

nIDLastButton    Specifies the integer identifier of the last radio button in the group.

Remarks

Retrieves the ID of the currently checked radio button in the specified group.

Return Value

ID of the checked radio button, or 0 if none is selected.

See Also

»CWnd::CheckRadioButton«


  CWnd::GetClientRect

void GetClientRect( LPRECT lpRect ) const;

lpRect    Points to a »RECT« structure or a CRect object to receive the client coordinates. The left and top members will be 0. The right and bottom members will contain the width and height of the window.

Remarks

Copies the client coordinates of the CWnd client area into the structure pointed to by lpRect. The client coordinates specify the upper-left and lower-right corners of the client area. Since client coordinates are relative to the upper-left corners of the CWnd client area, the coordinates of the upper-left corner are (0,0).

See Also

»CWnd::GetWindowRect«, ::GetClientRect


  CWnd::GetClipboardOwner

static CWnd* PASCAL GetClipboardOwner();

Remarks

Retrieves the current owner of the Clipboard.

The Clipboard can still contain data even if it is not currently owned.

Return Value

Identifies the window that owns the Clipboard if the function is successful. Otherwise, it is NULL.

The returned pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetClipboardViewer«, ::GetClipboardOwner


  CWnd::GetClipboardViewer

static CWnd* PASCAL GetClipboardViewer();

Remarks

Retrieves the first window in the Clipboard-viewer chain.

Return Value

Identifies the window currently responsible for displaying the Clipboard if successful; otherwise NULL (for example, if there is no viewer).

The returned pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetClipboardOwner«, ::GetClipboardViewer


  CWnd::GetCurrentMessage

Protected

static const MSG* PASCAL GetCurrentMessage(); ♦

Return Value

Returns a pointer to the message the window is currently processing. Should only be called when in an OnMessage handler.


  CWnd::GetDC

CDC* GetDC();

Remarks

Retrieves a pointer to a common, class, or private device context for the client area depending on the class style specified for the CWnd. For common device contexts, GetDC assigns default attributes to the context each time it is retrieved. For class and private contexts, GetDC leaves the previously assigned attributes unchanged. The device context can be used in subsequent graphics device interface (GDI) functions to draw in the client area.

Unless the device context belongs to a window class, the »ReleaseDC« member function must be called to release the context after painting. Since only five common device contexts are available at any given time, failure to release a device context can prevent other applications from accessing a device context.

A device context belonging to the CWnd class is returned by the GetDC member function if CS_CLASSDC, CS_OWNDC, or CS_PARENTDC was specified as a style in the WNDCLASS structure when the class was registered.

Return Value

Identifies the device context for the CWnd client area if successful; otherwise, the return value is NULL. The pointer may be temporary and should not be stored for later use.

See Also

»CWnd::ReleaseDC«, ::GetDC, »CClientDC«


  CWnd::GetDCEx

Windows 3.1 Only

CDC* GetDCEx( CRgn* prgnClip, DWORD flags ); ♦

prgnClip    Identifies a clipping region that may be combined with the visible region of the client window.

flags    Can have one of the following preset values:

•	DCX_CACHE    Returns a device context from the cache rather than the OWNDC or CLASSDC window. Overrides CS_OWNDC and CS_CLASSDC.

•	DCX_CLIPCHILDREN    Excludes the visible regions of all child windows below the CWnd window.

•	DCX_CLIPSIBLINGS    Excludes the visible regions of all sibling windows above the CWnd window.

•	DCX_EXCLUDERGN    Excludes the clipping region identified by prgnClip from the visible region of the returned device context.

•	DCX_INTERSECTRGN    Intersects the clipping region identified by prgnClip within the visible region of the returned device context.

•	DCX_LOCKWINDOWUPDATE    Allows drawing even if there is a LockWindowUpdate call in effect that would otherwise exclude this window. This value is used for drawing during tracking.

•	DCX_PARENTCLIP    Uses the visible region of the parent window and ignores the parent window's WS_CLIPCHILDREN and WS_PARENTDC style bits. This value sets the device context's origin to the upper-left corner of the CWnd window.

•	DCX_WINDOW    Returns a device context that corresponds to the window rectangle rather than the client rectangle.

Remarks

Retrieves the handle of a device context for the CWnd window. The device context can be used in subsequent GDI functions to draw in the client area.

This function, which is an extension to the GetDCfunction, gives an application more control over how and whether a device context for a window is clipped.

Unless the device context belongs to a window class, the ReleaseDCfunction must be called to release the context after drawing. Since only five common device contexts are available at any given time, failure to release a device context can prevent other applications from gaining access to a device context.

In order to obtain a cached device context, an application must specify DCX_CACHE If DCX_CACHE is not specified and the window is neither CS_OWNDC nor CS_CLASSDC, this function returns NULL.

A device context with special characteristics is returned by the GetDCEx function if the CS_CLASSDC, CS_OWNDC, or CS_PARENTDCstyle was specified in the WNDCLASSstructure when the class was registered.

For more information about these characteristics, see the description of the WNDCLASS structure in the Windows Programmer's Reference, Volume 3.

For more information about these characteristics, see the description of the WNDCLASS structure.

Return Value

The device context for the specified window if the function is successful; otherwise NULL.

See Also

»CWnd::BeginPaint«, »CWnd::GetDC«, »CWnd::GetWindowDC«, »CWnd::ReleaseDC«, ::GetDCEx


  CWnd::GetDescendantWindow

CWnd* GetDescendantWindow( int nID ) const;

nID    Specifies the identifier of the control or child window to be retrieved.

Remarks

Call this member function to find the descendant window specified by the given ID. This member function searches the entire tree of child windows, not just those that are immediate children.

Return Value

A pointer to a CWnd object, or NULL if no child window is found.

See Also

»CWnd::GetParentFrame«, »CWnd::IsChild«, »CWnd::GetDlgItem«


  CWnd::GetDesktopWindow

static CWnd* PASCAL GetDesktopWindow();

Remarks

Returns the Windows desktop window. The desktop window covers the entire screen and is the area on top of which all icons and other windows are painted.

Return Value

Identifies the Windows desktop window. This pointer may be temporary and should not be stored for later use.

See Also

::GetDesktopWindow


  CWnd::GetDlgCtrlID

int GetDlgCtrlID() const;

Remarks

Returns the window or control ID value for any child window, not just that of a control in a dialog box. Since top-level windows do not have an ID value, the return value of this function is invalid if the CWnd is a top-level window.

Return Value

The numeric identifier of the CWnd child window if the function is successful; otherwise 0.

See Also

::GetDlgCtrlID


  CWnd::GetDlgItem

CWnd* GetDlgItem( int nID ) const;

nID    Specifies the identifier of the control or child window to be retrieved.

Remarks

Retrieves a pointer to the specified control or child window in a dialog box or other window. The pointer returned is usually cast to the type of control identified by nID.

Return Value

A pointer to the given control or child window. If no control with the integer ID given by the nID parameter exists, the value is NULL.

The returned pointer may be temporary and should not be stored.

See Also

»CWnd::Create«, »CWnd::GetWindow«, »CWnd::GetDescendantWindow«, »CWnd::GetWindow«, ::GetDlgItem


  CWnd::GetDlgItemInt

UINT GetDlgItemInt( int nID, BOOL* lpTrans = NULL,
BOOL bSigned = TRUE ) const;

nID    Specifies the integer identifier of the dialog-box control to be translated.

lpTrans    Points to the Boolean variable that is to receive the translated flag.

bSigned    Specifies whether the value to be retrieved is signed.

Remarks

Retrieves the text of the control identified by nID. It translates the text of the specified control in the given dialog box into an integer value by stripping any extra spaces at the beginning of the text and converting decimal digits. It stops the translation when it reaches the end of the text or encounters any nonnumeric character.

If bSigned is TRUE, GetDlgItemInt checks for a minus sign (−) at the beginning of the text and translates the text into a signed number. Otherwise, it creates an unsigned value.

It sends a WM_GETTEXTmessage to the control.

Return Value

Specifies the translated value of the dialog-box item text. Since 0 is a valid return value, lpTrans must be used to detect errors. If a signed return value is desired, cast it as an int type.

The function returns 0 if the translated number is greater than 32,767 (for signed numbers) or 65,535 (for unsigned).

When errors occur, such as encountering nonnumeric characters and exceeding the above maximum, GetDlgItemInt copies 0 to the location pointed to by lpTrans. If there are no errors, lpTrans receives a nonzero value. If lpTrans is NULL, GetDlgItemInt does not warn about errors.

See Also

»CWnd::GetDlgItemText«, ::GetDlgItemInt


  CWnd::GetDlgItemText

int GetDlgItemText( int nID, LPSTR lpStr, int nMaxCount ) const;

nID    Specifies the integer identifier of the control whose title is to be retrieved.

lpStr    Points to the buffer to receive the control's title or text.

nMaxCount    Specifies the maximum length (in bytes) of the string to be copied to lpStr. If the string is longer than nMaxCount, it is truncated.

Remarks

Retrieves the title or text associated with a control in a dialog box. The GetDlgItemText member function copies the text to the location pointed to by lpStr and returns a count of the number of bytes it copies.

Return Value

Specifies the actual number of bytes copied to the buffer, not including the terminating null character. The value is 0 if no text is copied.

See Also

»CWnd::GetDlgItem«, »CWnd::GetDlgItemInt«, ::GetDlgItemText, WM_GETTEXT


  CWnd::GetExStyle

DWORD GetExStyle() const;

Return Value

The window's extended style.

See Also

»CWnd::GetStyle«, ::GetExStyle, ::GetWindowLong


  CWnd::GetFocus

static CWnd* PASCAL GetFocus();

Remarks

Retrieves a pointer to the CWnd that currently has the input focus.

Return Value

A pointer to the window that has the current focus, or NULL if there is no focus window.

The pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetActiveWindow«, »CWnd::GetCapture«, »CWnd::SetFocus«, ::GetFocus


  CWnd::GetFont

CFont* GetFont() const;

Remarks

Gets the current font for this window.

Return Value

A pointer to the current font.

The pointer may be temporary and should not be stored for later use.

See Also

»CWnd::SetFont«, WM_GETFONT, »CFont«


  CWnd::GetLastActivePopup

CWnd* GetLastActivePopup() const;

Remarks

Determines which pop-up window owned by CWnd was most recently active.

Return Value

Identifies the most recently active pop-up window. The return value will be the window itself if any of the following conditions are met:

•	The window itself was most recently active

•	The window does not own any pop-up windows

•	The window is not a top-level window or is owned by another window

The pointer may be temporary and should not be stored for later use.

See Also

::GetLastActivePopup


  CWnd::GetMenu

CMenu* GetMenu() const;

Remarks

Retrieves a pointer to the menu for this window. This function should not be used for child windows because they do not have a menu.

Return Value

Identifies the menu. The value is NULL if CWnd has no menu. The return value is undefined if CWnd is a child window.

The returned pointer may be temporary and should not be stored for later use.

See Also

::GetMenu


  CWnd::GetNextDlgGroupItem

CWnd* GetNextDlgGroupItem( CWnd* pWndCtl, BOOL bPrevious = FALSE ) const;

pWndCtl    Identifies the control to be used as the starting point for the search.

bPrevious    Specifies how the function is to search the group of controls in the dialog box. If TRUE, the function searches for the previous control in the group; if FALSE, it searches for the next control in the group.

Remarks

Searches for the previous (or next) control within a group of controls in a dialog box. A group of controls begins with a control that was created with the »WS_GROUP« style and ends with the last control that was not created with the WS_GROUP style.

By default, the GetNextDlgGroupItem member function returns a pointer to the next control in the group. If pWndCtl identifies the first control in the group and bPrevious is TRUE, GetNextDlgGroupItem returns a pointer to the last control in the group.

Return Value

Pointer to the previous (or next) control in the group if the member function is successful.

The returned pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetNextDlgTabItem«, ::GetNextDlgGroupItem


  CWnd::GetNextDlgTabItem

CWnd* GetNextDlgTabItem( CWnd* pWndCtl, BOOL bPrevious = FALSE ) const;

pWndCtl    Identifies the control to be used as the starting point for the search.

bPrevious    Specifies how the function is to search the dialog box. If TRUE, the function searches for the previous control in the dialog box; if FALSE, it searches for the next control.

Remarks

Retrieves a pointer to the first control that was created with the »WS_TABSTOP« style and that precedes (or follows) the specified control.

Return Value

Pointer to the previous (or next) control that has the WS_TABSTOP style, if the member function is successful.

The returned pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetNextDlgGroupItem«, ::GetNextDlgTabItem


  CWnd::GetNextWindow

CWnd* GetNextWindow( UINT nFlag = GW_HWNDNEXT ) const;

nFlag    Specifies whether the function returns a pointer to the next window or the previous window. It can be either GW_HWNDNEXT, which returns the window that follows the CWnd object on the window manager's list, or GW_HWNDPREV, which returns the previous window on the window manager's list.

Remarks

Searches for the next (or previous) window in the window manager's list. The window manager's list contains entries for all top-level windows, their associated child windows, and the child windows of any child windows.

If CWnd is a top-level window, the function searches for the next (or previous) top-level window; if CWnd is a child window, the function searches for the next (or previous) child window.

Return Value

Identifies the next (or the previous) window in the window manager's list if the member function is successful.

The returned pointer may be temporary and should not be stored for later use.

See Also

::GetNextWindow


  CWnd::GetOpenClipboardWindow

Windows 3.1 Only

static CWnd* PASCAL GetOpenClipboardWindow(); ♦

Remarks

Retrieves the handle of the window that currently has the Clipboard open.

Return Value

The handle of the window that currently has the Clipboard open if the function is successful; otherwise NULL.

See Also

»CWnd::GetClipboardOwner«, »CWnd::GetClipboardViewer«, »CWnd::OpenClipboard«, ::GetOpenClipboardWindow


  CWnd::GetParent

CWnd* GetParent() const;

Remarks

Retrieves the parent window (if any).

Return Value

Identifies the parent window if the member function is successful. Otherwise, the value is NULL, which indicates an error or no parent window.

The returned pointer may be temporary and should not be stored for later use.

See Also

::GetParent


  CWnd::GetParentFrame

CFrameWnd* GetParentFrame() const;

Remarks

Call this member function to retrieve the parent frame window. The member function searches up the parent chain until a CFrameWnd (or derived class) object is found.

Return Value

A pointer to a frame window if successful; otherwise NULL.

See Also

»CWnd::GetDescendantWindow«, »CWnd::GetParent«, »CFrameWnd::GetActiveView«


  CWnd::GetSafeHwnd

HWND GetSafeHwnd() const;

Return Value

Returns the window handle for a window. Returns NULL if the CWnd is not attached to a window or if it is used with a NULL CWnd pointer.


  CWnd::GetScrollBarCtrl

virtual CScrollBar* GetScrollBarCtrl( int nBar ) const;

nBar    Specifies the type of scroll bar. The parameter can take one of the following values:

•	SB_HORZ    Retrieves the position of the horizontal scroll bar.

•	SB_VERT    Retrieves the position of the vertical scroll bar.

Remarks

Call this member function to obtain a pointer to the specified sibling scroll bar or splitter window.

This member function does not operate on scroll bars created when the WS_HSCROLL or WS_VSCROLL bits are set during the creation of a window. The CWnd implementation of this function simply returns NULL. Derived classes, such as CView, implement the described functionality.

Return Value

A sibling scroll-bar control, or NULL if none.

See Also

»CWnd::EnableScrollBarCtrl«


  CWnd::GetScrollPos

int GetScrollPos( int nBar ) const;

nBar    Specifies the scroll bar to examine. The parameter can take one of the following values:

•	SB_HORZ    Retrieves the position of the horizontal scroll bar.

•	SB_VERT    Retrieves the position of the vertical scroll bar.

Remarks

Retrieves the current position of the scroll box of a scroll bar. The current position is a relative value that depends on the current scrolling range. For example, if the scrolling range is 50 to 100 and the scroll box is in the middle of the bar, the current position is 75.

Return Value

Specifies the current position of the scroll box in the scroll bar if successful; otherwise 0.

See Also

::GetScrollPos, »CScrollBar::GetScrollPos«


  CWnd::GetScrollRange

void GetScrollRange( int nBar, LPINT lpMinPos, LPINT lpMaxPos ) const;

nBar    Specifies the scroll bar to examine. The parameter can take one of the following values:

•	SB_HORZ    Retrieves the position of the horizontal scroll bar.

•	SB_VERT    Retrieves the position of the vertical scroll bar.

lpMinPos    Points to the integer variable that is to receive the minimum position.

lpMaxPos    Points to the integer variable that is to receive the maximum position.

Remarks

Copies the current minimum and maximum scroll-bar positions for the given scroll bar to the locations specified by lpMinPos and lpMaxPos. If CWnd does not have a scrollbar, then the GetScrollRange member function copies 0 to lpMinPos and lpMaxPos.

The default range for a standard scroll bar is 0 to 100. The default range for a scroll-bar control is empty (both values are 0).

See Also

::GetScrollRange


  CWnd::GetStyle

DWORD GetStyle() const;

Return Value

The window's style.

See Also

::GetWindowLong, »CWnd::CreateEx«


  CWnd::GetSuperWndProcAddr

Protected

virtual WNDPROC* GetSuperWndProcAddr(); ♦

Return Value

The address in which to store the default WndProc for this class.


  CWnd::GetSystemMenu

CMenu* GetSystemMenu( BOOL bRevert ) const;

bRevert    Specifies the action to be taken. If bRevert is FALSE, GetSystemMenu returns a handle to a copy of the Control menu currently in use. This copy is initially identical to the Control menu but can be modified. If bRevert is TRUE, GetSystemMenu resets the Control menu back to the default state. The previous, possibly modified, Control menu, if any, is destroyed. The return value is undefined in this case.

Remarks

Allows the application to access the Control menu for copying and modification.

Any window that does not use GetSystemMenu to make its own copy of the Control menu receives the standard Control menu.

The pointer returned by the GetSystemMenu member function can be used with the »CMenu::AppendMenu«, »CMenu::InsertMenu«, or »CMenu::ModifyMenu« functions to change the Control menu.

The Control menu initially contains items identified with various ID values such as SC_CLOSE, SC_MOVE, and SC_SIZE. Items on the Control menu generate »WM_SYSCOMMAND« messages. All predefined Control-menu items have ID numbers greater than 0xF000. If an application adds items to the Control menu, it should use ID numbers less than F000.

Windows may automatically dim items on the standard Control menu. CWnd can carry out its own checking or dimming by responding to the »WM_INITMENU« messages, which are sent before any menu is displayed.

Return Value

Identifies a copy of the Control menu if bRevert is FALSE. If bRevert is TRUE, the return value is undefined.

The returned pointer may be temporary and should not be stored for later use.

See Also

»CMenu::AppendMenu«, »CMenu::InsertMenu«, »CMenu::ModifyMenu«, ::GetSystemMenu


  CWnd::GetTopWindow

CWnd* GetTopWindow() const;

Remarks

Searches for the top-level child window that belongs to CWnd. If CWnd has no children, this function returns NULL.

Return Value

Identifies the top-level child window in a CWnd linked list of child windows. If no child windows exist, the value is NULL.

The returned pointer may be temporary and should not be stored for later use.

See Also

::GetTopWindow


  CWnd::GetUpdateRect

BOOL GetUpdateRect( LPRECT lpRect, BOOL bErase = FALSE );

lpRect    Points to a CRect object or »RECT« structure that is to receive the client coordinates of the update that encloses the update region.

Windows 3.1 Only

Set this parameter to NULL to determine whether an update region exists within the CWnd. If lpRect is NULL, the GetUpdateRect member function returns nonzero if an update region exists and 0 if one does not. This provides a way to determine whether a WM_PAINT message resulted from an invalid area. Do not set this parameter to NULL in Window version 3.0 and earlier. ♦

bErase    Specifies whether the background in the update region is to be erased.

Remarks

Retrieves the coordinates of the smallest rectangle that completely encloses the update region. If CWnd was created with the CS_OWNDC style and the mapping mode is not MM_TEXT, the GetUpdateRect member function gives the rectangle in logical coordinates. Otherwise, GetUpdateRect gives the rectangle in client coordinates. If there is no update region, GetUpdateRect sets the rectangle to be empty (sets all coordinates to 0).

The bErase parameter specifies whether GetUpdateRect should erase the background of the update region. If bErase is TRUE and the update region is not empty, the background is erased. To erase the background, GetUpdateRect sends the »WM_ERASEBKGND« message.

The update rectangle retrieved by the »BeginPaint« member function is identical to that retrieved by the GetUpdateRect member function.

The BeginPaint member function automatically validates the update region, so any call to GetUpdateRect made immediately after a call to BeginPaint retrieves an empty update region.

Return Value

Specifies the status of the update region. The value is nonzero if the update region is not empty; otherwise 0.

If the lpRect parameter is set to NULL, the return value is nonzero if an update region exists; otherwise 0.

See Also

»CWnd::BeginPaint«, ::GetUpdateRect, »CWnd::OnPaint«, »CWnd::RedrawWindow«


  CWnd::GetUpdateRgn

int GetUpdateRgn( CRgn* pRgn, BOOL bErase = FALSE );

pRgn    Identifies the update region.

bErase    Specifies whether the background will be erased and nonclient areas of child windows will be drawn. If the value is FALSE, no drawing is done.

Remarks

Retrieves the update region into a region identified by pRgn. The coordinates of this region are relative to the upper-left corner (client coordinates).

The »BeginPaint« member function automatically validates the update region, so any call to GetUpdateRgn made immediately after a call to BeginPaint retrieves an empty update region.

Return Value

Specifies a short-integer flag that indicates the type of resulting region. The value can take any one of the following:

•	SIMPLEREGION    The region has no overlapping borders.

•	COMPLEXREGION    The region has overlapping borders.

•	NULLREGION    The region is empty.

•	ERROR    No region was created.

See Also

»CWnd::BeginPaint«, ::GetUpdateRgn


  CWnd::GetWindow

CWnd* GetWindow( UINT nCmd ) const;

nCmd    Specifies the relationship between CWnd and the returned window. It can take one of the following values:

•	GW_CHILD    Identifies the CWnd first child window.

•	GW_HWNDFIRST    If CWnd is a child window, returns the first sibling window. Otherwise, it returns the first top-level window in the list.

•	GW_HWNDLAST    If CWnd is a child window, returns the last sibling window. Otherwise, it returns the last top-level window in the list.

•	GW_HWNDNEXT    Returns the next window on the window manager's list.

•	GW_HWNDPREV    Returns the previous window on the window manager's list.

•	GW_OWNER    Identifies the CWnd owner.

Return Value

Returns a pointer to the window requested, or NULL if none.

The returned pointer may be temporary and should not be stored for later use.

See Also

»CWnd::GetParent«, »CWnd::GetNextWindow«, ::GetWindow


  CWnd::GetWindowDC

CDC* GetWindowDC();

 Remarks

Retrieves the display context for the entire window, including caption bar, menus, and scroll bars. A window display context permits painting anywhere in CWnd, since the origin of the context is the upper-left corner of CWnd instead of the client area.

Default attributes are assigned to the display context each time it retrieves the context. Previous attributes are lost.

GetWindowDC is intended to be used for special painting effects within the CWnd nonclient area. Painting in nonclient areas of any window is not recommended.

The GetSystemMetricsWindows function can be used to retrieve the dimensions of various parts of the nonclient area, such as the caption bar, menu, and scroll bars.

After painting is complete, the »ReleaseDC« member function must be called to release the display context. Failure to release the display context will seriously affect painting requested by applications due to limitations on the number of device contexts that can be open at the same time.

Return Value

Identifies the display context for the given window if the function is successful; otherwise NULL.

The returned pointer may be temporary and should not be stored for later use.

See Also

::GetSystemMetrics, »CWnd::ReleaseDC«, ::GetWindowDC, »CWnd::GetDC«, »CWindowDC«


  CWnd::GetWindowPlacement

Windows 3.1 Only

BOOL GetWindowPlacement( WINDOWPLACEMENT FAR* lpwndpl ) const; ♦

lpwndpl    Points to the WINDOWPLACEMENT structure that receives the show state and position information.

Remarks

Retrieves the show state and the normal (restored), minimized, and maximized positions of a window.

The flags member of the »WINDOWPLACEMENT« structure retrieved by this function is always 0. If CWnd is maximized, the showCmd member of WINDOWPLACEMENT is SW_SHOWMAXIMIZED. If the window is minimized, it is SW_SHOWMINIMIZED. It is SW_SHOWNORMAL otherwise.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::SetWindowPlacement«, ::GetWindowPlacement


  CWnd::GetWindowRect

void GetWindowRect( LPRECT lpRect ) const;

lpRect    Points to a CRect object or a »RECT« structure that will receive the screen coordinates of the upper-left and lower-right corners.

Remarks

Copies the dimensions of the bounding rectangle of the CWnd object to the structure pointed to by lpRect. The dimensions are given in screen coordinates relative to the upper-left corner of the display screen. The dimensions of the caption, border, and scroll bars, if present, are included.

See Also

»CWnd::GetClientRect«, »CWnd::MoveWindow«, »CWnd::SetWindowPos«, ::GetWindowRect


  CWnd::GetWindowText

int GetWindowText( LPSTR lpszStringBuf, int nMaxCount ) const;

void GetWindowText( CString& rString ) const;

lpszStringBuf    Points to the buffer that is to receive the copied string of the window's title.

nMaxCount    Specifies the maximum number of characters to be copied to the buffer. If the string is longer than the number of characters specified in nMaxCount, it is truncated.

rString    A CString object that is to receive the copied string of the window's title.

Remarks

Copies the CWnd caption title (if it has one) into the buffer pointed to by lpszStringBuf or into the destination string rString. If the CWnd object is a control, the GetWindowText member function copies the text within the control instead of copying the caption.

This member function causes the WM_GETTEXT message to be sent to the CWnd object.

Return Value

Specifies the length, in bytes, of the copied string, not including the terminating null character. It is 0 if CWnd has no caption or if the caption is empty.

See Also

»CWnd::SetWindowText«, WM_GETTEXT, »CWnd::GetWindowTextLength«


  CWnd::GetWindowTextLength

int GetWindowTextLength() const;

Remarks

Returns the length of the CWnd object caption title. If CWnd is a control, the GetWindowTextLength member function returns the length of the text within the control instead of the caption.

This member function causes the WM_GETTEXTLENGTH message to be sent to the CWnd object.

Return Value

Specifies the text length, not including any null-termination character. The value is 0 if no such text exists.

See Also

::GetWindowTextLength, WM_GETTEXTLENGTH, »CWnd::GetWindowText«


  CWnd::HideCaret

void HideCaret();

Remarks

Hides the caret by removing it from the display screen. Although the caret is no longer visible, it can be displayed again by using the »ShowCaret« member function. Hiding the caret does not destroy its current shape.

Hiding is cumulative. If HideCaret has been called five times in a row, the ShowCaret member function must be called five times before the caret will be shown.

See Also

»CWnd::ShowCaret«, ::HideCaret


  CWnd::HiliteMenuItem

BOOL HiliteMenuItem( CMenu* pMenu, UINT nIDHiliteItem,
UINT nHilite );

pMenu    Identifies the top-level menu that contains the item to be highlighted.

nIDHiliteItem    Specifies the menu item to be highlighted, depending on the value of the nHilite parameter.

nHilite    Specifies whether the menu item is highlighted or the highlight is removed. It can be a combination of MF_HILITE or MF_UNHILITE with MF_BYCOMMAND or MF_BYPOSITION. The values can be combined using the bitwise-OR operator. These values have the following meanings:

•	MF_BYCOMMAND    Interprets nIDHiliteItem as the menu-item ID (the default interpretation).

•	MF_BYPOSITION    Interprets nIDHiliteItem as the zero-based offset of the menu item.

•	MF_HILITE    Highlights the item. If this value is not given, the highlight is removed from the item.

•	MF_UNHILITE    Removes the highlight from the item.

Remarks

Highlights or removes the highlight from a top-level (menu-bar) menu item.

The MF_HILITE and MF_UNHILITE flags can be used only with this member function; they cannot be used with the ModifyMenu member function.

Return Value

Specifies whether the menu item was highlighted. Nonzero if the item was highlighted; otherwise 0.

See Also

»CMenu::ModifyMenu«, ::HiliteMenuItem


  CWnd::Invalidate

void Invalidate( BOOL bErase = TRUE );

bErase    Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the entire client area of CWnd. The client area is marked for painting when the next »WM_PAINT« message occurs. The region can also be validated before a WM_PAINT message occurs by the »ValidateRect« or »ValidateRgn« member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the »BeginPaint« member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased.

Windows sends a »WM_PAINT« message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

See Also

»CWnd::BeginPaint«, »CWnd::ValidateRect«, »CWnd::ValidateRgn«, ::InvalidateRect


  CWnd::InvalidateRect

void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE );

lpRect    Points to a CRect object or a »RECT« structure that contains the rectangle (in client coordinates) to be added to the update region. If lpRect is NULL, the entire client area is added to the region.

bErase    Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the client area within the given rectangle by adding that rectangle to the CWnd update region. The invalidated rectangle, along with all other areas in the update region, is marked for painting when the next »WM_PAINT« message is sent. The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT call occurs, or until the region is validated by the »ValidateRect« or »ValidateRgn« member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the »BeginPaint« member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region is erased, not just in the given part.

Windows sends a »WM_PAINT« message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

See Also

»CWnd::BeginPaint«, »CWnd::ValidateRect«, »CWnd::ValidateRgn«, ::InvalidateRect


  CWnd::InvalidateRgn

void InvalidateRgn( CRgn* pRgn, BOOL bErase = TRUE );

pRgn    Identifies the region to be added to the update region. The region is assumed to have client coordinates. If this parameter is NULL, the entire client area is added to the update region.

bErase    Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the client area within the given region by adding it to the current update region of CWnd. The invalidated region, along with all other areas in the update region, is marked for painting when the »WM_PAINT« message is next sent. The invalidated areas accumulate in the update region until the region is processed when a WM_PAINT message is next sent, or until the region is validated by the »ValidateRect« or »ValidateRgn« member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the »BeginPaint« member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased.

Windows sends a »WM_PAINT« message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

The given region must have been previously created by one of the region functions.

See Also

»CWnd::BeginPaint«, »CWnd::ValidateRect«, »CWnd::ValidateRgn«, ::InvalidateRgn


  CWnd::IsChild

BOOL IsChild( const CWnd* pWnd ) const;

pWnd    Identifies the window to be tested.

Remarks

Indicates whether the window specified by pWnd is a child window or other direct descendant of CWnd. A child window is the direct descendant of CWnd if the CWnd object is in the chain of parent windows that leads from the original pop-up window to the child window.

Return Value

Specifies the outcome of the function. The value is nonzero if the window identified by pWnd is a child window of CWnd; otherwise 0.

See Also

::IsChild


  CWnd::IsDlgButtonChecked

UINT IsDlgButtonChecked( int nIDButton ) const;

nIDButton    Specifies the integer identifier of the button control.

Remarks

Determines whether a button control has a check mark next to it. If the button is a three-state control, the member function determines if it is dimmed, checked, or neither.

Return Value

Nonzero if the given control is checked, and 0 if it is not checked. Only radio buttons and check boxes can be checked. For three-state buttons, the return value can be 2 if the button is indeterminate. This member function returns 0 for a pushbutton.

See Also

::IsDlgButtonChecked, »CButton::GetCheck«


  CWnd::IsIconic

BOOL IsIconic() const;

Remarks

Specifies whether CWnd is minimized (iconic).

Return Value

Nonzero if CWnd is minimized; otherwise 0.

See Also

::IsIconic


  CWnd::IsWindowEnabled

BOOL IsWindowEnabled() const;

Remarks

Specifies whether CWnd is enabled for mouse and keyboard input.

Return Value

Nonzero if CWnd is enabled; otherwise 0.

See Also

::IsWindowEnabled


  CWnd::IsWindowVisible

BOOL IsWindowVisible() const;

Remarks

Determines the visibility state of the given window.

A window possesses a visibility state indicated by the WS_VISIBLE style bit. When this style bit is set with a call to the »ShowWindow« member function, the window is displayed and subsequent drawing to the window is displayed as long as the window has the style bit set.

Any drawing to a window that has the WS_VISIBLE style will not be displayed if the window is covered by other windows or is clipped by its parent window.

Return Value

Nonzero if CWnd is visible (has the WS_VISIBLE style bit set, and parent window is visible). Since the return value reflects the state of the WS_VISIBLE style bit, the return value may be nonzero even though CWnd is totally obscured by other windows.

See Also

»CWnd::ShowWindow«, ::IsWindowVisible


  CWnd::IsZoomed

BOOL IsZoomed() const;

Remarks

Determines whether CWnd has been maximized.

Return Value

Nonzero if CWnd is maximized; otherwise 0.

See Also

::IsZoomed


  CWnd::KillTimer

BOOL KillTimer( int nIDEvent );

nIDEvent    The value of the timer event passed to SetTimer.

Remarks

Kills the timer event identified by nIDEvent from the earlier call to SetTimer. Any pending »WM_TIMER« messages associated with the timer are removed from the message queue.

Return Value

Specifies the outcome of the function. The value is nonzero if the event was killed. It is 0 if the KillTimer member function could not find the specified timer event.

See Also

»CWnd::SetTimer«, ::KillTimer


  CWnd::LockWindowUpdate

Windows 3.1 Only

BOOL LockWindowUpdate(); ♦

Remarks

Disables or reenables drawing in the given window. A locked window cannot be moved. Only one window can be locked at a time.

If an application with a locked window (or any locked child windows) calls the GetDC, GetDCEx, or BeginPaintWindows function, the called function returns a device context whose visible region is empty. This will occur until the application unlocks the window by calling the LockWindowUpdate member function.

While window updates are locked, the system keeps track of the bounding rectangle of any drawing operations to device contexts associated with a locked window. When drawing is reenabled, this bounding rectangle is invalidated in the locked window and its child windows to force an eventual WM_PAINTmessage to update the screen. If no drawing has occurred while the window updates were locked, no area is invalidated.

The LockWindowUpdate member function does not make the given window invisible and does not clear the »WS_VISIBLE« style bit.

Return Value

Nonzero if the function is successful. It is 0 if a failure occurs or if the LockWindowUpdate function has been used to lock another window.

See Also

»CWnd::GetDCEx«, ::LockWindowUpdate


  CWnd::MapWindowPoints

Windows 3.1 Only

void MapWindowPoints( CWnd* pwndTo, LPRECT lpRect ) const; ♦

void MapWindowPoints( CWnd* pwndTo, LPPOINT lpPoint, UINT nCount ) const;

pwndTo    Identifies the window to which points are converted. If this parameter is NULL, the points are converted to screen coordinates.

lpRect    Specifies the rectangle whose points are to be converted.

lpPoint    A pointer to an array of POINT structures that contain the set of points to be converted.

nCount    Specifies the number of POINT structures in the array pointed to by lpPoint.

Remarks

Converts (maps) a set of points from the coordinate space of the CWnd to the coordinate space of another window.

See Also

»CWnd::ClientToScreen«, »CWnd::ScreenToClient«, ::MapWindowPoints


  CWnd::MessageBox

int MessageBox( LPCSTR lpszText, LPCSTR lpszCaption = NULL,
UINT nType = MB_OK );

lpszText    Points to a CString object or null-terminated string containing the message to be displayed.

lpszCaption    Points to a CString object or null-terminated string to be used for the message-box caption. If lpszCaption is NULL, the default caption "Error" is used.

nType    Specifies the contents and behavior of the message box.

Remarks

Creates and displays a window that contains an application-supplied message and caption, plus a combination of the predefined icons and pushbuttons described in the "Message-Box Styles" list. This manual shows this list in the AfxMessageBox global function description. Use the global function AfxMessageBox instead of this member function to implement a message box in your application.

The following shows the various system icons that can be used in a message box:

MB_ICONHAND and MB_ICONSTOP

MB_ICONQUESTION

MB_ICONEXCLAMATION

MB_ICONASTERISK and MB_ICONINFORMATION

Return Value

Specifies the outcome of the function. It is 0 if there is not enough memory to create the message box.

See Also

::MessageBox, »AfxMessageBox«


  CWnd::MoveWindow

void MoveWindow( int x, int y, int nWidth, int nHeight,
BOOL bRepaint = TRUE );

void MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );

x    Specifies the new position of the left side of the CWnd.

y    Specifies the new position of the top of the CWnd.

nWidth    Specifies the new width of the CWnd.

nHeight    Specifies the new height of the CWnd.

bRepaint    Specifies whether CWnd is to be repainted. If TRUE, CWnd receives a WM_PAINT message in its OnPaint message handler as usual. If this parameter is FALSE, no repainting of any kind occurs. This applies to the client area, to the nonclient area (including the title and scroll bars), and to any part of the parent window uncovered as a result of Cwnd's move. When this parameter is FALSE, the application must explicitly invalidate or redraw any parts of CWnd and parent window that must be redrawn.

lpRect    The CRect object or »RECT« structure that specifies the new size and position.

Remarks

Changes the position and dimensions.

For a top-level CWnd object, the x and y parameters are relative to the upper-left corner of the screen. For a child CWnd object, they are relative to the upper-left corner of the parent window's client area.

The MoveWindow function sends the »WM_GETMINMAXINFO« message. Handling this message gives CWnd the opportunity to modify the default values for the largest and smallest possible windows. If the parameters to the MoveWindow member function exceed these values, the values can be replaced by the minimum or maximum values in the WM_GETMINMAXINFO handler.

See Also

»CWnd::SetWindowPos«, »WM_GETMINMAXINFO«, ::MoveWindow


  CWnd::OnActivate

nState    Specifies whether the CWnd is being activated or deactivated. It can be one of the following values:

•	WA_INACTIVE    The window is being deactivated.

•	WA_ACTIVE    The window is being activated through some method other than a mouse click (for example, by use of the keyboard interface to select the window).

•	WA_CLICKACTIVE    The window is being activated by a mouse click.

pWndOther    Pointer to the CWnd being activated or deactivated. The pointer can be NULL, and it may be temporary.

bMinimized    Specifies the minimized state of the CWnd being activated or deactivated. A value of TRUE indicates the window is minimized.

If TRUE, the CWnd is being activated; otherwise deactivated.

Remarks

Called when a CWnd object is being activated or deactivated. First, the main window being deactivated has OnActivate called, and then the main window being activated has OnActivate called.

If the CWnd object is activated with a mouse click, it will also receive an »OnMouseActivate« member function call.

See Also

»WM_MOUSEACTIVATE«, »WM_NCACTIVATE«,WM_ACTIVATE


  CWnd::OnActivateApp

Protected

afx_msg void OnActivateApp( BOOL  bActive, HTASK  hTask ); ♦

bActive    Specifies whether the CWnd is being activated or deactivated. TRUE means the CWnd is being activated. FALSE means the CWnd is being deactivated.

hTask    Specifies a task handle. If bActive is TRUE, the handle identifies the task that owns the CWnd being deactivated. If bActive is FALSE, the handle identifies the task that owns the CWnd being activated.

Remarks

Called for all top-level windows of the task being activated and for all top-level windows of the task being deactivated.

See Also

WM_ACTIVATEAPP


  CWnd::OnAskCbFormatName

Protected

afx_msg void OnAskCbFormatName( UINT nMaxCount, LPSTR lpszString ); ♦

nMaxCount    Specifies the maximum number of bytes to copy.

lpszString    Points to the buffer where the copy of the format name is to be stored.

Remarks

Called when the Clipboard contains a data handle for the CF_OWNERDISPLAY format (that is, when the Clipboard owner will display the Clipboard contents). The Clipboard owner should provide a name for its format.

Override this member function and copy the name of the CF_OWNERDISPLAY format into the specified buffer, not exceeding the maximum number of bytes specified.

See Also

WM_ASKCBFORMATNAME


  CWnd::OnCancelMode

Protected

afx_msg void OnCancelMode(); ♦

Remarks

Called to inform CWnd to cancel any internal mode. If the CWnd object has the focus, its OnCancelMode member function is called when a dialog box or message box is displayed. This gives the CWnd the opportunity to cancel modes such as mouse capture.

The default implementation responds by calling the ReleaseCaptureWindows function. Override this member function in your derived class to handle other modes.

See Also

»CWnd::Default«, ::ReleaseCapture, WM_CANCELMODE


  CWnd::OnChangeCbChain

Protected

afx_msg void OnChangeCbChain( HWND hWndRemove, HWND hWndAfter ); ♦

hWndRemove    Specifies the window handle that is being removed from the Clipboard-viewer chain.

hWndAfter    Specifies the window handle that follows the window being removed from the Clipboard-viewer chain.

Remarks

Called for each window in the Clipboard-viewer chain to notify it that a window is being removed from the chain.

Each CWnd object that receives an OnChangeCbChain call should use the SendMessageWindows function to send the WM_CHANGECBCHAINmessage to the next window in the Clipboard-viewer chain (the handle returned by SetClipboardViewer). If hWndRemove is the next window in the chain, the window specified by hWndAfter becomes the next window, and Clipboard messages are passed on to it.

See Also

»CWnd::ChangeClipboardChain«, ::SendMessage


  CWnd::OnChar

Protected

afx_msg void OnChar( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Contains the virtual-key code value of the key.

nRepCnt    Contains the repeat count, the number of times the keystroke is repeated when user holds down the key.

nFlags    Contains the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Description of nFlags
0−7	Scan code (OEM-dependent value).
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the call; 0 if the key is up).
15	Transition state (1 if the key is being released; 0 if the key is being pressed).
Remarks

Called when a keystroke translates to a nonsystem character. This function is called before the »OnKeyUp« member function and after the »OnKeyDown« member function are called. OnChar contains the value of the keyboard key being pressed or released.

Since there is not necessarily a one-to-one correspondence between keys pressed and OnChar calls generated, the information in nFlags is generally not useful to applications. The information in nFlags applies only to the most recent call to the OnKeyUp member function or the OnKeyDown member function that precedes the call to OnChar.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

WM_CHAR, »WM_KEYDOWN«, »WM_KEYUP«


  CWnd::OnCharToItem

Protected

afx_msg int OnCharToItem( UINT nChar, CListBox* pListBox, UINT nIndex ); ♦

nChar    Specifies the value of the key pressed by the user.

pListBox    Specifies a pointer to the list box. It may be temporary.

nIndex    Specifies the current caret position.

Remarks

Called when a list box with the »LBS_WANTKEYBOARDINPUT« style sends its owner a WM_CHARTOITEM message in response to a »WM_CHAR« message.

Return Value

Specifies the action that the application performed in response to the call. A return value of −2 indicates that the application handled all aspects of selecting the item and wants no further action by the list box. A return value of −1 indicates that the list box should perform the default action in response to the keystroke. A return value of 0 or greater specifies the zero-based index of an item in the list box and indicates that the list box should perform the default action for the keystroke on the given item.

See Also

»WM_CHAR«, WM_CHARTOITEM


  CWnd::OnChildActivate

Remarks

If the CWnd object is a multiple document interface (MDI) child window, OnChildActivate is called when the user clicks the window's title bar or when the window is activated, moved, or sized.

See Also

»CWnd::SetWindowPos«, WM_CHILDACTIVATE


  CWnd::OnChildNotify

Protected

virtual BOOL OnChildNotify( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult );

message    A Windows message number sent to a parent window.

wParam    The wparam associated with the message.

lParam    The lparam associated with the message.

pLResult    A pointer to a value to be returned from the parent's window procedure. This pointer will be NULL if no return value is expected.

Remarks

Called by this window's parent window when it receives a notification message that applies to this window.

Never call this member function directly.

The default implementation of this member function returns 0, which means that the parent should handle the message.

Override this member function to extend the manner in which a control responds to notification messages.

Return Value

Nonzero if this window handles the message sent to its parent; otherwise 0.


  CWnd::OnClose

Protected

afx_msg void OnClose(); ♦

Remarks

Called as a signal that the CWnd or an application is to terminate. The default implementation calls DestroyWindow.

See Also

»CWnd::DestroyWindow«, WM_CLOSE


  CWnd::OnCommand

Protected

virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam ); ♦

wParam    Identifies the command ID of the menu item or control.

lParam    The low-order word of lParam identifies the control that sends the message if the message is from a control. Otherwise, the low-order word is 0. The high-order word of lParam specifies the notification message if the message is from a control. If the message is from an accelerator, the high-order word is 1. If the message is from a menu, the high-order word is 0.

Remarks

Called when the user selects an item from a menu, when a child control sends a notification message, or when an accelerator keystroke is translated.

OnCommand processes the message map for control notification and ON_COMMAND entries, and calls the appropriate member function.

Override this member function in your derived class to handle the WM_COMMAND message. An override will not process the message map unless the base class OnCommand is called.

Return Value

An application returns nonzero if it processes this message; otherwise 0.

See Also

WM_COMMAND »CCmdTarget::OnCmdMsg«


  CWnd::OnCompacting

Protected

afx_msg void OnCompacting( UINT nCpuTime ); ♦

nCpuTime    Specifies the ratio of CPU time currently spent by Windows compacting memory to CPU time spent performing other operations. For example, 8000h represents 50 percent of CPU time spent compacting memory.

Remarks

Called for all top-level windows when Windows detects that more than 12.5 percent of system time over a 30- to 60-second interval is being spent compacting memory. This indicates that system memory is low.

When a CWnd object receives this call, it should free as much memory as possible, taking into account the current level of activity of the application and the total number of applications running in Windows. The application can call the Windows function to determine how many applications are running.

See Also

 WM_COMPACTING


  CWnd::OnCompareItem

Protected

afx_msg int OnCompareItem( int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct ); ♦

Windows 3.1 Only

nIDCtl    The identifier of the control that sent the WM_COMPAREITEM message. ♦

lpCompareItemStruct    Contains a long pointer to a »COMPAREITEMSTRUCT« data structure that contains the identifiers and application-supplied data for two items in the combo or list box.

Remarks

Specifies the relative position of a new item in a child sorted owner-draw combo or list box.

If a combo or list box is created with the »CBS_SORT« or »LBS_SORT« style, Windows sends the combo-box or list-box owner a WM_COMPAREITEM message whenever the application adds a new item.

Two items in the combo or list box are reformed in a COMPAREITEMSTRUCT structure pointed to by lpCompareItemStruct. OnCompareItem should return a value that indicates which of the items should appear before the other. Typically, Windows makes this call several times until it determines the exact position for the new item.

If the hwndItem member of the COMPAREITEMSTRUCT structure belongs to a »CListBox« or »CComboBox« object, then the CompareItem virtual function of the appropriate class is called. Override CComboBox::CompareItem or CListBox::CompareItem in your derived CListBox or CComboBox class to do the item comparison.

Return Value

Indicates the relative position of the two items. It may be any of the following values:

Value	Meaning
−1	Item 1 sorts before item 2.
0	Item 1 and item 2 sort the same.
1	Item 1 sorts after item 2.
COMPAREITEM-
STRUCT Structure

A COMPAREITEMSTRUCT data structure has this form:

typedef struct tagCOMPAREITEMSTRUCT {
    UINT   CtlType;
    UINT   CtlID;
    HWND   hwndItem;
    UINT   itemID1;
    DWORD  itemData1;
    UINT   itemID2;
    DWORD  itemData2;
} COMPAREITEMSTRUCT;

Members

The COMPAREITEMSTRUCT members are as follows:

CtlType    ODT_LISTBOX (which specifies an owner-draw list box) or ODT_COMBOBOX (which specifies an owner-draw combo box).

CtlID    The control ID for the list box or combo box.

hwndItem    The window handle of the control.

itemID1    The index of the first item in the list box or combo box being compared.

itemData1    Application-supplied data for the first item being compared. This value was passed in the call that added the item to the combo or list box.

itemID2    Index of the second item in the list box or combo box being compared.

itemData2    Application-supplied data for the second item being compared. This value was passed in the call that added the item to the combo or list box.

See Also

»COMPAREITEMSTRUCT«, WM_COMPAREITEM, »CListBox::CompareItem«, »CComboBox::CompareItem«


  CWnd::OnCreate

Protected

afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct ); ♦

lpCreateStruct    Points to a »CREATESTRUCT« structure that contains information about the CWnd object being created.

Remarks

Called when an application requests that the Windows window be created by calling the »Create« or »CreateEx« member function. The CWnd object receives this call after the window is created but before it becomes visible. OnCreate is called before the Create or CreateEx member function returns.

Override this member function to perform any needed initialization of a derived class.

The CREATESTRUCT structure contains copies of the parameters used to create the window.

Return Value

OnCreate must return 0 to continue the creation of the CWnd object. If the application returns −1, the window will be destroyed.

 CREATESTRUCT Structure

A CREATESTRUCT structure has the following form:

typedef struct tagCREATESTRUCT {
   void FAR* lpCreateParams;
   HINSTANCE hInstance;
   HMENU     hMenu;
   HWND      hwndParent;
   int       cy;
   int       cx;
   int       y;
   int       x;
   LONG      style;
   LPCSTR    lpszName;
   LPCSTR    lpszClass;
   DWORD     dwExStyle;
} CREATESTRUCT;

Members

The CREATESTRUCT members are as follows:

lpCreateParams    Points to data to be used to create the window.

hInstance    Identifies the module-instance handle of the module that owns the new window.

hMenu    Identifies the menu to be used by the new window. If a child window, contains the integer ID.

hwndParent    Identifies the window that owns the new window. This member is NULL if the new window is a top-level window.

cy    Specifies the height of the new window.

cx    Specifies the width of the new window.

y    Specifies the y-coordinate of the upper-left corner of the new window. Coordinates are relative to the parent window if the new window is a child window; otherwise coordinates are relative to the screen origin.

x    Specifies the x-coordinate of the upper-left corner of the new window. Coordinates are relative to the parent window if the new window is a child window; otherwise coordinates are relative to the screen origin.

style    Specifies the new window's style.

lpszName    Points to a null-terminated string that specifies the new window's name.

lpszClass    Points to a null-terminated string that specifies the new window's Windows class name (a WNDCLASS structure).

dwExStyle    Specifies the extended style for the new window.

See Also

»CWnd::CreateEx«, »CWnd::OnNcCreate«, WM_CREATE, »CWnd::Default«, »CWnd::FromHandle«


  CWnd::OnCtlColor

Protected

afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd,
UINT nCtlColor ); ♦

pDC    Contains a pointer to the display context for the child window. May be temporary.

pWnd    Contains a pointer to the control asking for the color. May be temporary.

nCtlColor    Contains one of the following values, specifying the type of control:

•	CTLCOLOR_BTN    Button control

•	CTLCOLOR_DLG    Dialog box

•	CTLCOLOR_EDIT    Edit control

•	CTLCOLOR_LISTBOX    List-box control

•	CTLCOLOR_MSGBOX    Message box

•	CTLCOLOR_SCROLLBAR    Scroll-bar control

•	CTLCOLOR_STATIC    Static control

Remarks

Called when a child control is about to be drawn. Most controls send this message to their parent (usually a dialog box) to prepare the pDC for drawing the control using the correct colors.

To change the text color, call the SetTextColor member function with the desired red, green, and blue (RGB) values.

To change the background color of a single-line edit control, set the brush handle in both the CTLCOLOR_EDIT and CTLCOLOR_MSGBOX message codes, and call the CDC::SetBkColorfunction in response to the CTLCOLOR_EDIT code.

OnCtlColor will not be called for the list box of a drop-down combo box because the drop-down list box is actually a child of the combo box and not a child of the window. To change the color of the drop-down list box, create a CComboBox with an override of OnCtlColor that checks for CTLCOLOR_LISTBOX in the nCtlColor parameter. In this handler, the SetBkColor member function must be used to set the background color for the text.

Return Value

OnCtlColor must return a handle to the brush that is to be used for painting the control background.

See Also

CDC::SetBkColor,


  CWnd::OnDeadChar

Protected

afx_msg void OnDeadChar( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Specifies the dead-key character value.

nRepCnt    Specifies the repeat count.

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Description
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the call, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
Remarks

Called when the »OnKeyUp« member function and the »OnKeyDown« member functions are called. This member function can be used to specify the character value of a dead key. A dead key is a key, such as the umlaut (double-dot) character, that is combined with other characters to form a composite character. For example, the umlaut-O character consists of the dead key, umlaut, and the O key.

An application typically uses OnDeadChar to give the user feedback about each key pressed. For example, an application can display the accent in the current character position without moving the caret.

Since there is not necessarily a one-to-one correspondence between keys pressed and OnDeadChar calls, the information in nFlags is generally not useful to applications. The information in nFlags applies only to the most recent call to the »OnKeyUp« member function or the »OnKeyDown« member function that precedes the OnDeadChar call.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

WM_DEADCHAR


  CWnd::OnDeleteItem

Protected

afx_msg void OnDeleteItem( int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct ); ♦

nIDCtl    The identifier of the control that sent the WM_DELETEITEM message.

lpDeleteItemStruct    Specifies a long pointer to a »DELETEITEMSTRUCT« data structure that contains information about the deleted list box item. This structure is described later.

Remarks

Called to inform the owner of an owner-draw list box or combo box that the list box or combo box is destroyed or that items have been removed by »CComboBox::DeleteString«, »CListBox::DeleteString«, »CComboBox::ResetContent«, or »CListBox::ResetContent«.

If the hwndItem member of the DELETEITEMSTRUCT structure belongs to a combo box or list box, then the DeleteItem virtual function of the appropriate class is called. Override the DeleteItem member function of the appropriate control's class to delete item-specific data.

DELETEITEMSTRUCT Structure

A DELETEITEMSTRUCT data structure has this form:

typedef struct tagDELETEITEMSTRUCT {
    UINT  CtlType
    UINT  CtlID;
    UINT  itemID;
    HWND  hwndItem;
    DWORD itemData;
} DELETEITEMSTRUCT;

Members

The DELETEITEMSTRUCT members are as follows:

CtlType    Contains ODT_LISTBOX (which specifies an owner-draw list box) or ODT_COMBOBOX (which specifies an owner-draw combo box).

CtlID    Contains the control ID for the list box or combo box.

itemID    Contains the index of the item in the list box or combo box being removed.

hwndItem    Contains the window handle of the control.

itemData    Contains the value passed to the control by »CComboBox::AddString«, »CComboBox::InsertString«, »CListBox::AddString«, or »CListBox::InsertString«.

See Also

»CComboBox::DeleteString«, »CListBox::DeleteString«, »CComboBox::ResetContent«, »CListBox::ResetContent«, WM_DELETEITEM, »CListBox::DeleteItem«, »CComboBox::DeleteItem«


  CWnd::OnDestroy

Protected

afx_msg void OnDestroy(); ♦

Remarks

Called to inform the CWnd object that it is being destroyed. OnDestroy is called after the CWnd object is removed from the screen.

OnDestroy is called first for the CWnd being destroyed, then for the child windows of CWnd as they are destroyed. It can be assumed that all child windows still exist while OnDestroy runs.

If the CWnd object being destroyed is part of the Clipboard-viewer chain (set by calling the »SetClipboardViewer« member function), the CWnd must remove itself from the Clipboard-viewer chain by calling the »ChangeClipboardChain« member function before returning from the OnDestroy function.

See Also

»CWnd::ChangeClipboardChain«, »CWnd::DestroyWindow«, »CWnd::SetClipboardViewer«


  CWnd::OnDestroyClipboard

Protected

afx_msg void OnDestroyClipboard(); ♦

Remarks

Called for the Clipboard owner when the Clipboard is emptied through a call to the EmptyClipboardWindows function.

See Also

::EmptyClipboard, WM_DESTROYCLIPBOARD


  CWnd::OnDevModeChange

Protected

afx_msg void OnDevModeChange( LPSTR lpDeviceName ); ♦

lpDeviceName    Points to the device name specified in the Windows initialization file, WIN.INI.

Remarks

Called for all top-level CWnd objects when the user changes device-mode settings.

Applications that handle the WM_DEVMODECHANGE message may reinitialize their device-mode settings. Applications that use the Windows ExtDeviceMode function to save and restore device settings typically do not process this function.

This function is not called when the user changes the default printer from Control Panel. In this case, the OnWinIniChange function is called.

See Also

WM_DEVMODECHANGE


  CWnd::OnDrawClipboard

Protected

afx_msg void OnDrawClipboard(); ♦

Remarks

Called for each window in the Clipboard-viewer chain when the contents of the Clipboard change. Only applications that have joined the Clipboard-viewer chain by calling the »SetClipboardViewer« member function need to respond to this call.

Each window that receives an OnDrawClipboard call should call the SendMessageWindows function to pass a WM_DRAWCLIPBOARD message on to the next window in the Clipboard-viewer chain. The handle of the next window is returned by the »SetClipboardViewer« member function; it may be modified in response to an »OnChangeCbChain« member function call.

See Also

»::SendMessage«, »CWnd::SetClipboardViewer«, »WM_CHANGECBCHAIN«, WM_DRAWCLIPBOARD


  CWnd::OnDrawItem

Protected

afx_msg void OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct ); ♦

Windows 3.1 Only

nIDCtl    Contains the identifier of the control that sent the WM_DRAWITEM message. If a menu sent the message, nIDCtl contains 0. ♦

lpDrawItemStruct    Specifies a long pointer to a DRAWITEMSTRUCT data structure that contains information about the item to be drawn and the type of drawing required.

Remarks

Called for the owner of an owner-draw button control, combo-box control, list-box control, or menu when a visual aspect of the control or menu has changed.

The itemAction member of the »DRAWITEMSTRUCT« structure defines the drawing operation that is to be performed. The data in this member allows the owner of the control to determine what drawing action is required.

Before returning from processing this message, an application should ensure that the device context identified by the hDC member of the DRAWITEMSTRUCT structure is restored to the default state.

If the hwndItem member belongs to a »CButton«, »CMenu«, »CListBox« or »CComboBox« object, then the DrawItem virtual function of the appropriate class is called. Override the DrawItem member function of the appropriate control's class to draw the item.

DRAWITEMSTRUCT Structure

A DRAWITEMSTRUCT structure has this form:

typedef struct tagDRAWITEMSTRUCT {
    UINT   CtlType;
    UINT   CtlID;
    UINT   itemID;
    UINT   itemAction;
    UINT   itemState;
    HWND   hwndItem;
    HDC    hDC;
    RECT   rcItem;
    DWORD  itemData;
} DRAWITEMSTRUCT;

Members

The DRAWITEMSTRUCT members are as follows:

CtlType    The control type. The values for control types are as follows:

•	ODT_BUTTON    Owner-draw button

•	ODT_COMBOBOX    Owner-draw combo box

•	ODT_LISTBOX    Owner-draw list box

•	ODT_MENU    Owner-draw menu

CtlID    The control ID for a combo box, list box, or button. This member is not used for a menu.

itemID    The menu-item ID for a menu or the index of the item in a list box or combo box. For an empty list box or combo box, this member is a negative value, which allows the application to draw only the focus rectangle at the coordinates specified by the rcItem member even though there are no items in the control. The user can thus be shown whether the list box or combo box has the input focus. The setting of the bits in the itemAction member determines whether the rectangle is to be drawn as though the list box or combo box has input focus.

itemAction    Defines the drawing action required. This will be one or more of the following bits:

•	ODA_DRAWENTIRE    This bit is set when the entire control needs to be drawn.

•	ODA_FOCUS    This bit is set when the control gains or loses input focus. The itemState member should be checked to determine whether the control has focus.

•	ODA_SELECT    This bit is set when only the selection status has changed. The itemState member should be checked to determine the new selection state.

itemState    Specifies the visual state of the item after the current drawing action takes place. That is, if a menu item is to be dimmed, the state flag ODS_GRAYED will be set. The state flags are as follows:

•	ODS_CHECKED    This bit is set if the menu item is to be checked. This bit is used only in a menu.

•	ODS_DISABLED    This bit is set if the item is to be drawn as disabled.

•	ODS_FOCUS    This bit is set if the item has input focus.

•	ODS_GRAYED    This bit is set if the item is to be dimmed. This bit is used only in a menu.

•	ODS_SELECTED    This bit is set if the item's status is selected.

hwndItem    Specifies the window handle of the control for combo boxes, list boxes, and buttons. Specifies the handle of the menu (HMENU) that contains the item for menus.

hDC    Identifies a device context. This device context must be used when performing drawing operations on the control.

rcItem    A rectangle in the device context specified by the hDC member that defines the boundaries of the control to be drawn. Windows automatically clips anything the owner draws in the device context for combo boxes, list boxes, and buttons, but it does not clip menu items. When drawing menu items, the owner must not draw outside the boundaries of the rectangle defined by the rcItem member.

itemData    For a combo box or list box, this member contains the value that was passed to the list box by one of the following:

»CComboBox::AddString«
»CComboBox::InsertString«
»CListBox::AddString«
»CListBox::InsertString«

For a menu, this member contains the value that was passed to the menu by one of the following:

»CMenu::AppendMenu«
»CMenu::InsertMenu«
»CMenu::ModifyMenu«

See Also

»DRAWITEMSTRUCT«, WM_DRAWITEM, »CButton::DrawItem«, »CMenu::DrawItem«, »CListBox::DrawItem«, »CComboBox::DrawItem«


  CWnd::OnDropFiles

Windows 3.1 Only

Protected

afx_msg void OnDropFiles( HDROP hDropInfo ); ♦

hDropInfo    A pointer to an internal data structure that describes the dropped files. This handle is used by the DragFinish, DragQueryFile, and DragQueryPoint Windows functions to retrieve information about the dropped files.

Remarks

Called when the user releases the left mouse button over a window that has registered itself as the recipient of dropped files.

Typically, a derived class will be designed to support dropped files and it will register itself during window construction.

See Also

»CWnd::DragAcceptFiles«, WM_DROPFILES, ::DragAcceptFiles, ::DragFinish, ::DragQueryFile, ::DragQueryPoint


  CWnd::OnEnable

Protected

afx_msg void OnEnable( BOOL bEnable ); ♦

bEnable    Specifies whether the CWnd object has been enabled or disabled. This parameter is TRUE if the CWnd has been enabled; it is FALSE if the CWnd has been disabled.

Remarks

Called when an application changes the enabled state of the CWnd object. OnEnable is called before the »EnableWindow« member function returns, but after the window enabled state (»WS_DISABLED« style bit) has changed.

See Also

»CWnd::EnableWindow«, WM_ENABLE


  CWnd::OnEndSession

Protected

afx_msg void OnEndSession( BOOL bEnding ); ♦

bEnding    Specifies whether or not the session is being ended. It is TRUE if the session is being ended; otherwise FALSE.

Remarks

Called after the CWnd object has returned a nonzero value from a »OnQueryEndSession« member function call. The OnEndSession call informs the CWnd object whether the session is actually ending.

If bEnding is TRUE, Windows can terminate any time after all applications have returned from processing this call. Consequently, have an application perform all tasks required for termination within OnEndSession.

You do not need to call the »DestroyWindow« member function or PostQuitMessageWindows function when the session is ending.

See Also

»CWnd::DestroyWindow«, »CWnd::OnQueryEndSession«, ::ExitWindows, ::PostQuitMessage, »WM_QUERYENDSESSION«, »CWnd::Default«, WM_ENDSESSION


  CWnd::OnEnterIdle

Protected

afx_msg void OnEnterIdle( UINT nWhy, CWnd* pWho ); ♦

nWhy    Specifies whether the message is the result of a dialog box or a menu being displayed. This parameter can be one of the following values:

•	MSGF_DIALOGBOX    The system is idle because a dialog box is being displayed.

•	MSGF_MENU    The system is idle because a menu is being displayed.

pWho    Specifies a pointer to the dialog box (if nWhy is MSGF_DIALOGBOX), or the window that contains the displayed menu (if nWhy is MSGF_MENU). This pointer may be temporary and should not be stored for later use.

Remarks

A call to OnEnterIdle informs an application's main window procedure that a modal dialog box or a menu is entering an idle state. A modal dialog box or menu enters an idle state when no messages are waiting in its queue after it has processed one or more previous messages.

See Also

WM_ENTERIDLE


  CWnd::OnEraseBkgnd

Protected

afx_msg BOOL OnEraseBkgnd( CDC* pDC ); ♦

pDC    Specifies the device-context object.

Remarks

Called when the CWnd object background needs erasing (for example, when resized). It is called to prepare an invalidated region for painting.

The default implementation erases the background using the window class background brush specified by the hbrBackground member of the window class structure.

If the hbrBackground member is NULL, your overridden version of OnEraseBkgnd should erase the background color. Your version should also align the origin of the intended brush with the CWnd coordinates by first calling UnrealizeObjectfor the brush, and then selecting the brush.

An overridden OnEraseBkgnd should return nonzero in response to WM_ERASEBKGND if it processes the message and erases the background; this indicates that no further erasing is required. If it returns 0, the window will remain marked as needing to be erased. (Typically, this means that the fErase member of the PAINTSTRUCT structure will be TRUE.)

Windows assumes the background is computed with the MM_TEXT mapping mode. If the device context is using any other mapping mode, the area erased may not be within the visible part of the client area.

Return Value

Nonzero if it erases the background; otherwise 0.

See Also

»WM_ICONERASEBKGND«, »CGdiObject::UnrealizeObject«, WM_ERASEBKGND


  CWnd::OnFontChange

Protected

afx_msg void OnFontChange(); ♦

Remarks

All top-level windows in the system receive an OnFontChange call after the application changes the pool of font resources.

An application that adds or removes fonts from the system (for example, through the AddFontResourceor RemoveFontResourceWindows function) should send the WM_FONTCHANGEmessage to all top-level windows.

To send this message, use the SendMessageWindows function with the hWnd parameter set to 0xFFFF.

See Also

::AddFontResource, ::RemoveFontResource, ::SendMessage, WM_FONTCHANGE


  CWnd::OnGetDlgCode

Protected

afx_msg UINT OnGetDlgCode(); ♦

Remarks

Normally, Windows handles all arrow-key and TAB-key input to a CWnd control. By overriding OnGetDlgCode, a CWnd control can choose a particular type of input to process itself.

The default OnGetDlgCode functions for the predefined control classes return a code appropriate for each class.

Return Value

One or more of the following values, indicating which type of input the application processes:

•	DLGC_BUTTON    Button (generic).

•	DLGC_DEFPUSHBUTTON    Default pushbutton.

•	DLGC_HASSETSEL    EM_SETSEL messages.

•	DLGC_UNDEFPUSHBUTTON    No default pushbutton processing. (An application can use this flag with DLGC_BUTTON to indicate that it processes button input but relies on the system for default pushbutton processing.)

•	DLGC_RADIOBUTTON    Radio button.

•	DLGC_STATIC    Static control.

•	DLGC_WANTALLKEYS    All keyboard input.

•	DLGC_WANTARROWS    Arrow keys.

•	DLGC_WANTCHARS    WM_CHAR messages.

•	DLGC_WANTMESSAGE    All keyboard input. The application passes this message on to the control.

•	DLGC_WANTTAB    TAB key.

See Also

WM_GETDLGCODE


  CWnd::OnGetMinMaxInfo

Protected

afx_msg void OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI ); ♦

lpMMI    Points to a MINMAXINFO structure that contains information about a window's maximized size and position and its minimum and maximum tracking size. For more about this structure, see the "MINMAXINFO structure" section below.

Remarks

Called whenever Windows needs to know the maximized position or dimensions, or the minimum or maximum tracking size. The maximized size is the size of the window when its borders are fully extended. The maximum tracking size of the window is the largest window size that can be achieved by using the borders to size the window. The minimum tracking size of the window is the smallest window size that can be achieved by using the borders to size the window.

Windows fills in an array of points specifying default values for the various positions and dimensions. The application may change these values in OnGetMinMaxInfo.

MINMAXINFO Structure

The MINMAXINFO structure has the following form:

typedef struct tagMINMAXINFO {
    POINT ptReserved;
    POINT ptMaxSize;
    POINT ptMaxPosition;
    POINT ptMinTrackSize;
    POINT ptMaxTrackSize;
} MINMAXINFO;

ptReserved    Reserved for internal use.

ptMaxSize    Specifies the maximized width (point.x) and the maximized height (point.y) of the window.

ptMaxPosition    Specifies the position of the left side of the maximized window (point.x) and the position of the top of the maximized window (point.y).

ptMinTrackSize    Specifies the minimum tracking width (point.x) and the minimum tracking height (point.y) of the window.

ptMaxTrackSize    Specifies the maximum tracking width (point.x) and the maximum tracking height (point.y) of the window.

See Also

WM_GETMINMAXINFO


  CWnd::OnHScroll

Protected

afx_msg void OnHScroll( UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar ); ♦

nSBCode    Specifies a scroll-bar code that indicates the user's scrolling request. This parameter can be one of the following:

•	SB_LEFT    Scroll to far left.

•	SB_ENDSCROLL    End scroll.

•	SB_LINELEFT    Scroll left.

•	SB_LINERIGHT    Scroll right.

•	SB_PAGELEFT    Scroll one page left.

•	SB_PAGERIGHT    Scroll one page right.

•	SB_RIGHT    Scroll to far right.

•	SB_THUMBPOSITION    Scroll to absolute position. The current position is specified by the nPos parameter.

•	SB_THUMBTRACK    Drag scroll box to specified position. The current position is specified by the nPos parameter.

nPos    Specifies the scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise, not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.

pScrollBar    If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window's scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.

Remarks

Called when the user clicks a window's horizontal scroll bar.

The SB_THUMBTRACK scroll-bar code typically is used by applications that give some feedback while the scroll box is being dragged.

If an application scrolls the contents controlled by the scroll bar, it must also reset the position of the scroll box with the »SetScrollPos« member function.

See Also

»CWnd::SetScrollPos«, »WM_VSCROLL«, WM_HSCROLL


  CWnd::OnHScrollClipboard

Protected

afx_msg void OnHScrollClipboard( CWnd* pClipAppWnd, UINT nSBCode, UINT nPos ); ♦

pClipAppWnd    Specifies a pointer to a Clipboard-viewer window. The pointer may be temporary and should not be stored for later use.

nSBCode    Specifies one of the following scroll-bar codes in the low-order word:

•	SB_BOTTOM    Scroll to lower right.

•	SB_ENDSCROLL    End scroll.

•	SB_LINEDOWN    Scroll one line down.

•	SB_LINEUP    Scroll one line up.

•	SB_PAGEDOWN    Scroll one page down.

•	SB_PAGEUP    Scroll one page up.

•	SB_THUMBPOSITION    Scroll to the absolute position. The current position is provided in nPos.

•	SB_TOP    Scroll to upper left.

nPos    Contains the scroll-box position if the scroll-bar code is SB_THUMBPOSITION; otherwise not used.

Remarks

The Clipboard owner's OnHScrollClipboard member function is called by the Clipboard viewer when the Clipboard data has the CF_OWNERDISPLAY format and there is an event in the Clipboard viewer's horizontal scroll bar. The owner should scroll the Clipboard image, invalidate the appropriate section, and update the scroll-bar values.

See Also

»CWnd::OnVScrollClipboard«, WM_HSCROLLCLIPBOARD


  CWnd::OnIconEraseBkgnd

Protected

afx_msg void OnIconEraseBkgnd( CDC* pDC ); ♦

pDC    Specifies the device-context object of the icon. May be temporary and should not be stored for later use.

Remarks

Called for a minimized (iconic) CWnd object when the background of the icon must be filled before painting the icon. CWnd receives this call only if a class icon is defined for the window default implementation; otherwise OnEraseBkgnd is called.

The DefWindowProc member function fills the icon background with the background brush of the parent window.

See Also

»CWnd::OnEraseBkgnd«, WM_ICONERASEBKGND


  CWnd::OnInitMenu

Protected

afx_msg void OnInitMenu( CMenu* pMenu ); ♦

pMenu    Specifies the menu to be initialized. May be temporary and should not be stored for later use.

Remarks

Called when a menu is about to become active. The call occurs when the user clicks an item on the menu bar or presses a menu key. Override this member function to modify the menu before it is displayed.

OnInitMenu is only called when a menu is first accessed; OnInitMenu is called only once for each access. This means, for example, that moving the mouse across several menu items while holding down the button does not generate new calls. This call does not provide information about menu items.

See Also

»CWnd::OnInitMenuPopup«, WM_INITMENU


  CWnd::OnInitMenuPopup

Protected

afx_msg void OnInitMenuPopup( CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu ); ♦

pPopupMenu    Specifies the menu object of the pop-up menu. May be temporary and should not be stored for later use.

nIndex    Specifies the index of the pop-up menu in the main menu.

bSysMenu    TRUE if the pop-up menu is the Control menu; otherwise FALSE.

Remarks

Called when a pop-up menu is about to become active. This allows an application to modify the pop-up menu before it is displayed without changing the entire menu.

See Also

»CWnd::OnInitMenu«, WM_INITMENUPOPUP


  CWnd::OnKeyDown

Protected

afx_msg void OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Specifies the virtual-key code of the given key.

nRepCnt    Repeat count (the number of times the keystroke is repeated as a result of the user holding down the key).

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Description
0−7	Scan code (OEM-dependent value).
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the call, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
For a WM_KEYDOWN message, the key-transition bit (bit 15) is 0 and the context-code bit (bit 13) is 0.

Remarks

Called when a nonsystem key is pressed. A nonsystem key is a keyboard key that is pressed when the ALT key is not pressed or a keyboard key that is pressed when CWnd has the input focus.

Because of auto-repeat, more than one OnKeyDown call may occur before an »OnKeyUp« member function call is made. The bit that indicates the previous key state can be used to determine whether the OnKeyDown call is the first down transition or a repeated down transition.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

»WM_CHAR«, »WM_KEYUP«, WM_KEYDOWN


  CWnd::OnKeyUp

Protected

afx_msg void OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Specifies the virtual-key code of the given key.

nRepCnt    Repeat count (the number of times the keystroke is repeated as a result of the user holding down the key).

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Description
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the call, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
For a WM_KEYUP message, the key-transition bit (bit 15) is 1 and the context-code bit (bit 13) is 0.

Remarks

Called when a nonsystem key is released. A nonsystem key is a keyboard key that is pressed when the ALT key is not pressed or a keyboard key that is pressed when the CWnd has the input focus.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

»WM_CHAR«, WM_KEYUP, »CWnd::Default«, WM_KEYDOWN


  CWnd::OnKillFocus

Protected

afx_msg void OnKillFocus( CWnd* pNewWnd ); ♦

pNewWnd    Specifies a pointer to the window that receives the input focus (may be NULL or may be temporary).

Remarks

Called immediately before losing the input focus.

If the CWnd object is displaying a caret, the caret should be destroyed at this point.

See Also

»CWnd::SetFocus«, WM_KILLFOCUS


  CWnd::OnLButtonDblClk

Protected

afx_msg void OnLButtonDblClk( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user double-clicks the left mouse button.

Only windows that have the CS_DBLCLKS WNDCLASS style will receive OnLButtonDblClk calls. This is the default for Microsoft Foundation class windows. Windows calls OnLButtonDblClk when the user presses, releases, and then presses the left mouse button again within the system's double-click time limit. Double-clicking the left mouse button actually generates four events: »WM_LBUTTONDOWN«, »WM_LBUTTONUP« messages, the WM_LBUTTONDBLCLK call, and another WM_LBUTTONUP message when the button is released.

See Also

»CWnd::OnLButtonDown«, »CWnd::OnLButtonUp«, WM_LBUTTONDBLCLK


  CWnd::OnLButtonDown

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the Ctrl key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user presses the left mouse button.

See Also

»CWnd::OnLButtonDblClk«, »CWnd::OnLButtonUp«, WM_LBUTTONDOWN


  CWnd::OnLButtonUp

Protected

afx_msg void OnLButtonUp( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user releases the left mouse button.

See Also

»CWnd::OnLButtonDblClk«, »CWnd::OnLButtonDown«, WM_LBUTTONUP


  CWnd::OnMButtonDblClk

Protected

afx_msg void OnMButtonDblClk( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user double-clicks the middle mouse button.

Only windows that have the CS_DBLCLKS WNDCLASS style will receive OnMButtonDblClk calls. This is the default for all Microsoft Foundation class windows. Windows generates an OnMButtonDblClk call when the user presses, releases, and then presses the middle mouse button again within the system's double-click time limit. Double-clicking the middle mouse button actually generates four events: »WM_MBUTTONDOWN« and »WM_MBUTTONUP« messages, the WM_MBUTTONDBLCLK call, and another WM_MBUTTONUP message.

See Also

»CWnd::OnMButtonDown«, »CWnd::OnMButtonUp«, WM_MBUTTONDBLCLK


  CWnd::OnMButtonDown

Protected

afx_msg void OnMButtonDown( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user presses the middle mouse button.

See Also

»CWnd::OnMButtonDblClk«, »CWnd::OnMButtonUp«, WM_MBUTTONDOWN


  CWnd::OnMButtonUp

Protected

afx_msg void OnMButtonUp( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user releases the middle mouse button.

See Also

»CWnd::OnMButtonDblClk«, »CWnd::OnMButtonDown«, WM_MBUTTONUP


  CWnd::OnMDIActivate

Protected

afx_msg void OnMDIActivate( BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd ); ♦

bActivate    TRUE if the child is being activated and FALSE if it is being deactivated.

pActivateWnd    Contains a pointer to the MDI child window to be activated. When received by an MDI child window, pActivateWnd contains a pointer to the child window being activated. This pointer may be temporary and should not be stored for later use.

pDeactivateWnd    Contains a pointer to the MDI child window being deactivated. This pointer may be temporary and should not be stored for later use.

Remarks

Called for the child window being deactivated and the child window being activated.

An MDI child window is activated independently of the MDI frame window. When the frame becomes active, the child window that was last activated with a OnMDIActivate call receives an »WM_NCACTIVATE« message to draw an active window frame and caption bar, but it does not receive another OnMDIActivate call.

See Also

»CMDIFrameWnd::MDIActivate«, WM_MDIACTIVATE


  CWnd::OnMeasureItem

Protected

afx_msg void OnMeasureItem( int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct ); ♦

Windows 3.1 Only

nIDCtl    The ID of the control. ♦

lpMeasureItemStruct    Points to a »MEASUREITEMSTRUCT« data structure that contains the dimensions of the owner-draw control.

Remarks

Called by the framework for the owner of an owner-draw button, combo box, list box, or menu item when the control is created.

Override this member function and fill in the MEASUREITEMSTRUCT data structure pointed to by lpMeasureItemStruct and return; this informs Windows of the dimensions of the control and allows Windows to process user interaction with the control correctly.

If a list box or combo box is created with the »LBS_OWNERDRAWVARIABLE« or »CBS_OWNERDRAWVARIABLE« style, the framework calls this function for the owner for each item in the control; otherwise this function is called once.

Windows initiates the call to OnMeasureItem for the owner of combo boxes and list boxes created with the OWNERDRAWFIXED style before sending the WM_INITDIALOGmessage. As a result, when the owner receives this call, Windows has not yet determined the height and width of the font used in the control; function calls and calculations that require these values should occur in the main function of the application or library.

If the item being measured is a CMenu, CListBox or CComboBox object, then the MeasureItem virtual function of the appropriate class is called. Override the MeasureItem member function of the appropriate control's class to calculate and set the size of each item.

MEASUREITEM-STRUCT Structure

A MEASUREITEMSTRUCT data structure has the following form:

typedef struct tagMEASUREITEMSTRUCT {
    UINT   CtlType;
    UINT   CtlID;
    UINT   itemID;
    UINT   itemWidth;
    UINT   itemHeight;
    DWORD  itemData
} MEASUREITEMSTRUCT;

Failure to fill out the proper members in the MEASUREITEMSTRUCT structure will cause improper operation of the control.

Members

The MEASUREITEMSTRUCT members are as follows:

CtlType    Contains the control type. The values for control types are as follows:

•	ODT_COMBOBOX    Owner-draw combo box

•	ODT_LISTBOX    Owner-draw list box

•	ODT_MENU    Owner-draw menu

CtlID    Contains the control ID for a combo box, list box, or button. This member is not used for a menu.

itemID    Contains the menu-item ID for a menu or the list-box-item ID for a variable-height combo box or list box. This member is not used for a fixed-height combo box or list box, or for a button.

itemWidth    Specifies the width of a menu item. The owner of the owner-draw menu item must fill this member before it returns from the message.

itemHeight    Specifies the height of an individual item in a list box or a menu. Before it returns from the message, the owner of the owner-draw combo box, list box, or menu item must fill out this member. The maximum height of a list box item is 255.

itemData    For a combo box or list box, this member contains the value that was passed to the list box by one of the following:

»CComboBox::AddString«
»CComboBox::InsertString«
»CListBox::AddString«
»CListBox::InsertString«

For a menu, this member contains the value that was passed to the menu by one of the following:

»CMenu::AppendMenu«
»CMenu::InsertMenu«
»CMenu::ModifyMenu«

See Also

»CMenu::MeasureItem«, »CListBox::MeasureItem«, »CComboBox::MeasureItem«, WM_MEASUREITEM


  CWnd::OnMenuChar

Protected

afx_msg LRESULT OnMenuChar( UINT nChar, UINT nFlags,
CMenu* pMenu ); ♦

nChar    Specifies the ASCII character that the user pressed.

nFlags    Contains the MF_POPUP flag if the menu is a pop-up menu. It contains the MF_SYSMENU flag if the menu is a Control menu.

pMenu    Contains a pointer to the selected CMenu. The pointer may be temporary and should not be stored.

Remarks

Called when the user presses a menu mnemonic character that doesn't match any of the predefined mnemonics in the current menu. It is sent to the CWnd that owns the menu. OnMenuChar is also called when the user presses ALT and any other key, even if the key does not correspond to a mnemonic character. In this case, pMenu points to the menu owned by the CWnd, and nFlags is 0.

Return Value

The high-order word of the return value should contain one of the following command codes:

Value	Description
0	Tells Windows to discard the character that the user pressed and creates a short beep on the system speaker.
1	Tells Windows to close the current menu.
2	Informs Windows that the low-order word of the return value contains the item number for a specific item. This item is selected by Windows.
The low-order word is ignored if the high-order word contains 0 or 1. Applications should process this message when accelerator (shortcut) keys are used to select bitmaps placed in a menu.

See Also

WM_MENUCHAR


  CWnd::OnMenuSelect

Protected

afx_msg void OnMenuSelect( UINT nItemID, UINT nFlags,
HMENU hSysMenu ); ♦

nItemID    Identifies the item selected. If the selected item is a menu item, nItemID contains the menu-item ID. If the selected item contains a pop-up menu, nItemID contains the pop-up menu handle.

nFlags    Contains a combination of the following menu flags:

•	MF_BITMAP    Item is a bitmap.

•	MF_CHECKED    Item is checked.

•	MF_DISABLED    Item is disabled.

•	MF_GRAYED    Item is dimmed.

•	MF_MOUSESELECT    Item was selected with a mouse.

•	MF_OWNERDRAW    Item is an owner-draw item.

•	MF_POPUP    Item contains a pop-up menu.

•	MF_SEPARATOR    Item is a menu-item separator.

•	MF_SYSMENU    Item is contained in the Control menu.

hSysMenu    If nFlags contains MF_SYSMENU, identifies the menu associated with the message; otherwise unused.

Remarks

If the CWnd object is associated with a menu, OnMenuSelect is called when the user selects a menu item.

If nFlags contains 0xFFFF and hSysMenu contains 0, Windows has closed the menu because the user pressed the ESC key or clicked outside the menu.

See Also

WM_MENUSELECT


  CWnd::OnMouseActivate

Protected

afx_msg int OnMouseActivate( CWnd* pDesktopWnd, UINT nHitTest, UINT message ); ♦

pDesktopWnd    Specifies a pointer to the top-level parent window of the window being activated. The pointer may be temporary and should not be stored.

nHitTest    Specifies the »hit-test« area code. A hit test is a test that determines the location of the cursor.

message    Specifies the mouse message number.

Remarks

Called when the cursor is in an inactive window and the user presses a mouse button.

The default implementation passes this message to the parent window before any processing occurs. If the parent window returns TRUE, processing is halted.

Return Value

Specifies whether to activate the CWnd and whether to discard the mouse event. It must be one of the following values:

Windows 3.1 Only

•	MA_ACTIVATE    Activate CWnd object.

•	MA_NOACTIVATE    Do not activate CWnd object.

•	MA_ACTIVATEANDEAT    Activate CWnd object and discard the mouse event.

•	MA_NOACTIVATEANDEAT    Do not activate CWnd object and discard the mouse event. ♦

See Also

»CWnd::OnNcHitTest«, WM_MOUSEACTIVATE


  CWnd::OnMouseMove

Protected

afx_msg void OnMouseMove( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if the CTRL key is down.

•	MK_LBUTTON    Set if the left mouse button is down.

•	MK_MBUTTON    Set if the middle mouse button is down.

•	MK_RBUTTON    Set if the right mouse button is down.

•	MK_SHIFT    Set if the SHIFT key is down.

point    Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the mouse cursor moves. If the mouse is not captured, the WM_MOUSEMOVE message is received by the CWnd object beneath the mouse cursor; otherwise, the message goes to the window that has captured the mouse.

See Also

»CWnd::SetCapture«, »CWnd::OnNCHitTest«, WM_MOUSEMOVE


  CWnd::OnMove

Protected

afx_msg void OnMove( int x, int y ); ♦

x    Specifies the new x-coordinate location of the upper-left corner of the client area. This new location is given in screen coordinates for overlapped and pop-up windows, and parent-client coordinates for child windows.

y    Specifies the new y-coordinate location of the upper-left corner of the client area. This new location is given in screen coordinates for overlapped and pop-up windows, and parent-client coordinates for child windows.

Remarks

Called after the CWnd object has been moved.

See Also

WM_MOVE


  CWnd::OnNcActivate

Protected

afx_msg BOOL OnNcActivate( BOOL bActive ); ♦

bActive    Specifies when a caption bar or icon needs to be changed to indicate an active or inactive state. The bActive parameter is TRUE if an active caption or icon is to be drawn. It is FALSE for an inactive caption or icon.

Remarks

Called when the nonclient area needs to be changed to indicate an active or inactive state. The default implementation draws the title bar and title-bar text in their active colors if bActive is TRUE and in their inactive colors if bActive is FALSE.

Return Value

Nonzero if Windows should proceed with default processing; 0 to prevent the caption bar or icon from being deactivated.

See Also

»CWnd::Default«, WM_NCACTIVATE


  CWnd::OnNcCalcSize

Protected

afx_msg void OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp ); ♦

bCalcValidRects    Specifies whether the application should specify which part of the client area contains valid information. Windows will copy the valid information to the specified area within the new client area. If this parameter is TRUE, the application should specify which part of the client area is valid.

lpncsp    Points to a »NCCALCSIZE_PARAMS« data structure that contains information an application can use to calculate the new size and position of the CWnd rectangle (including client area, borders, caption, scroll bars, and so on).

Remarks

Called when the size and position of the client area needs to be calculated. By processing this message, an application can control the contents of the window's client area when the size or position of the window changes.

Regardless of the value of bCalcValidRects, the first rectangle in the array specified by the rgrc structure member of the NCCALCSIZE_PARAMS structure contains the coordinates of the window. For a child window, the coordinates are relative to the parent window's client area. For top-level windows, the coordinates are screen coordinates. An application should modify the rgrc[0] rectangle to reflect the size and position of the client area.

The rgrc[1] and rgrc[2] rectangles are valid only if bCalcValidRects is TRUE. In this case, the rgrc[1] rectangle contains the coordinates of the window before it was moved or resized. The rgrc[2] rectangle contains the coordinates of the window's client area before the window was moved. All coordinates are relative to the parent window or screen.

The default implementation calculates the size of the client area based on the window characteristics (presence of scroll bars, menu, and so on), and places the result in lpncsp.

NCCALCSIZE_
PARAMS Structure

Windows 3.1 Only

An NCCALCSIZE_PARAMS structure has this form:

typedef struct tagNCCALCSIZE_PARAMS {
    RECT           rgrc[3];
    WINDOWPOS FAR* lppos;
} NCCALCSIZE_PARAMS;

The NCCALCSIZE_PARAMS structure contains information that an application can use while processing the WM_NCCALCSIZE message to calculate the size, position, and valid contents of the client area of a window.

Members

An NCCALCSIZE_PARAMS structure has the following members:

rgrc    Specifies an array of rectangles. The first contains the new coordinates of a window that has been moved or resized. The second contains the coordinates of the window before it was moved or resized. The third contains the coordinates of the client area of a window before it was moved or resized. If the window is a child window, the coordinates are relative to the client area of the parent window. If the window is a top-level window, the coordinates are relative to the screen.

lppos    Points to a WINDOWPOS structure that contains the size and position values specified in the operation that caused the window to be moved or resized. ♦

See Also

WM_NCCALCSIZE, »CWnd::MoveWindow«, »CWnd::SetWindowPos«


  CWnd::OnNcCreate

Protected

afx_msg BOOL OnNcCreate( LPCREATESTRUCT lpCreateStruct ); ♦

lpCreateStruct    Points to the »CREATESTRUCT« data structure for CWnd.

Remarks

Called prior to the »WM_CREATE« message when the CWnd object is first created.

Return Value

Nonzero if the nonclient area is created. It is 0 if an error occurs; the Create function will return failure in this case.

See Also

»CWnd::CreateEx«,  WM_NCCREATE


  CWnd::OnNcDestroy

Protected

afx_msg void OnNcDestroy(); ♦

Remarks

Called by the framework when the nonclient area is being destroyed, and is the last member function called when the Windows window is destroyed. The default implementation performs some cleanup, then calls the virtual member function PostNcDestroy.

Override PostNcDestroy if you want to perform your own cleanup, such as a delete this operation. If you override OnNcDestroy, you must call OnNcDestroy in your base class to ensure that any memory internally allocated for the window is freed.

See Also

»CWnd::DestroyWindow«, »CWnd::OnNcCreate«, WM_NCDESTROY, »CWnd::Default«, »CWnd::PostNcDestroy«


  CWnd::OnNcHitTest

Protected

afx_msg UINT OnNcHitTest( CPoint point ); ♦

point    Contains the x- and y-coordinates of the cursor. These coordinates are always screen coordinates.

Remarks

Called for the CWnd object that contains the cursor (or the CWnd object that used the »SetCapture« member function to capture the mouse input) every time the mouse is moved.

Return Value

One of the mouse »hit-test« enumerated values:

Mouse Enumerated Values

•	HTBORDER    In the border of a window that does not have a sizing border.

•	HTBOTTOM    In the lower horizontal border of the window.

•	HTBOTTOMLEFT    In the lower-left corner of the window border.

•	HTBOTTOMRIGHT    In the lower-right corner of the window border.

•	HTCAPTION    In a title-bar area.

•	HTCLIENT    In a client area.

•	HTERROR    On the screen background or on a dividing line between windows (same as HTNOWHERE except that the DefWndProc Windows function produces a system beep to indicate an error).

•	HTGROWBOX    In a size box.

•	HTHSCROLL    In the horizontal scroll bar.

•	HTLEFT    In the left border of the window.

•	HTMAXBUTTON    In a Maximize button.

•	HTMENU    In a menu area.

•	HTMINBUTTON    In a Minimize button.

•	HTNOWHERE    On the screen background or on a dividing line between windows.

•	HTREDUCE    In a Minimize button.

•	HTRIGHT    In the right border of the window.

•	HTSIZE    In a size box (same as HTGROWBOX).

•	HTSYSMENU    In a Control menu or in a Close button in a child window.

•	HTTOP    In the upper horizontal border of the window.

•	HTTOPLEFT    In the upper-left corner of the window border.

•	HTTOPRIGHT    In the upper-right corner of the window border.

•	HTTRANSPARENT    In a window currently covered by another window.

•	HTVSCROLL    In the vertical scroll bar.

•	HTZOOM    In a Maximize button.

See Also

»CWnd::GetCapture«, WM_NCHITTEST


  CWnd::OnNcLButtonDblClk

Protected

afx_msg void OnNcLButtonDblClk( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user double-clicks the left mouse button while the cursor is within a nonclient area of CWnd.

If appropriate, the »WM_SYSCOMMAND« message is sent.

See Also

WM_NCLBUTTONDBLCLK, »CWnd::OnNcHitTest«


  CWnd::OnNcLButtonDown

Protected

afx_msg void OnNcLButtonDown( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user presses the left mouse button while the cursor is within a nonclient area of the CWnd object.

If appropriate, the »WM_SYSCOMMAND« is sent.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcLButtonDblClk«, »CWnd::OnNcLButtonUp«, »CWnd::OnSysCommand«, WM_NCLBUTTONDOWN, »CWnd::Default«


  CWnd::OnNcLButtonUp

Protected

afx_msg void OnNcLButtonUp( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user releases the left mouse button while the cursor is within a nonclient area.

If appropriate, »WM_SYSCOMMAND« is sent.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcLButtonDown«, »CWnd::OnSysCommand«, WM_NCLBUTTONUP


  CWnd::OnNcMButtonDblClk

Protected

afx_msg void OnNcMButtonDblClk( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user double-clicks the middle mouse button while the cursor is within a nonclient area.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcMButtonDown«, »CWnd::OnNcMButtonUp«, WM_NCMBUTTONDBLCLK


  CWnd::OnNcMButtonDown

Protected

afx_msg void OnNcMButtonDown( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user presses the middle mouse button while the cursor is within a nonclient area.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcMButtonDblClk«, »CWnd::OnNcMButtonUp«, WM_NCMBUTTONDOWN


  CWnd::OnNcMButtonUp

Protected

afx_msg void OnNcMButtonUp( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user releases the middle mouse button while the cursor is within a nonclient area.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcMButtonDblClk«, »CWnd::OnNcMButtonDown«, WM_NCMBUTTONUP


  CWnd::OnNcMouseMove

Protected

afx_msg void OnNcMouseMove( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the cursor is moved within a nonclient area. If appropriate, the »WM_SYSCOMMAND« message is sent.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnSysCommand«, WM_NCMOUSEMOVE


  CWnd::OnNcPaint

Protected

afx_msg void OnNcPaint(); ♦

Remarks

Called when the nonclient area needs to be painted. The default implementation paints the window frame.

An application can override this call and paint its own custom window frame. The clipping region is always rectangular, even if the shape of the frame is altered.

See Also

WM_NCPAINT


  CWnd::OnNcRButtonDblClk

Protected

afx_msg void OnNcRButtonDblClk( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user double-clicks the right mouse button while the cursor is within a nonclient area of CWnd.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcRButtonDown«, »CWnd::OnNcRButtonUp«, WM_NCRBUTTONDBLCLK


  CWnd::OnNcRButtonDown

Protected

afx_msg void OnNcRButtonDown( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user presses the right mouse button while the cursor is within a nonclient area.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcRButtonDblClk«, »CWnd::OnNcRButtonUp«,


  CWnd::OnNcRButtonUp

Protected

afx_msg void OnNcRButtonUp( UINT nHitTest, CPoint point ); ♦

nHitTest    Specifies the »hit-test code«. A hit test is a test that determines the location of the cursor.

point    Specifies a CPoint object that contains the x- and y-screen coordinates of the cursor position. These coordinates are always relative to the upper-left corner of the screen.

Remarks

Called when the user releases the right mouse button while the cursor is within a nonclient area.

See Also

»CWnd::OnNcHitTest«, »CWnd::OnNcRButtonDblClk«, »CWnd::OnNcRButtonDown«, WM_NCRBUTTONUP


  CWnd::OnPaint

Protected

afx_msg void OnPaint(); ♦

Remarks

Called when Windows or an application makes a request to repaint a portion of an application's window. The WM_PAINT message is sent when the UpdateWindow or RedrawWindow member function is called.

Windows 3.1 Only

A window may receive internal paint messages as a result of calling the RedrawWindow member function with the RDW_INTERNALPAINT flag set. In this case, the window may not have an update region. An application should call the GetUpdateRect member function to determine whether the window has an update region. If GetUpdateRect returns 0, the application should not call the BeginPaint and EndPaint member functions.

It is an application's responsibility to check for any necessary internal repainting or updating by looking at its internal data structures for each WM_PAINT message because a WM_PAINT message may have been caused by both an invalid area and a call to the RedrawWindow member function with the RDW_INTERNALPAINT flag set.

An internal WM_PAINT message is sent only once by Windows. After an internal WM_PAINT message is sent to a window by the UpdateWindow member function, no further WM_PAINT messages will be sent or posted until the window is invalidated or until the RedrawWindow member function is called again with the RDW_INTERNALPAINT flag set. ♦

See Also

»CWnd::BeginPaint«, »CWnd::EndPaint«, »CWnd::RedrawWindow«, »CPaintDC«


  CWnd::OnPaintClipboard

Protected

afx_msg void OnPaintClipboard( CWnd* pClipAppWnd,
HGLOBAL hPaintStruct ); ♦

pClipAppWnd    Specifies a pointer to the Clipboard-application window. The pointer may be temporary and should not be stored for later use.

hPaintStruct    Identifies a »PAINTSTRUCT« data structure that defines what part of the client area to paint.

Remarks

A Clipboard owner's OnPaintClipboard member function is called by a Clipboard viewer when the Clipboard owner has placed data on the Clipboard in the CF_OWNERDISPLAY format and the Clipboard viewer's client area needs repainting.

To determine whether the entire client area or just a portion of it needs repainting, the Clipboard owner must compare the dimensions of the drawing area given in the rcpaint member of the PAINTSTRUCT structure to the dimensions given in the most recent »OnSizeClipboard« member function call.

OnPaintClipboard should use the GlobalLockWindows function to lock the memory that contains the PAINTSTRUCT data structure and unlock that memory with the GlobalUnlockWindows function before it exits.

See Also

::GlobalLock::GlobalUnlock, »CWnd::OnSizeClipboard«, WM_PAINTCLIPBOARD


  CWnd::OnPaletteChanged

pFocusWnd    Specifies a pointer to the window that caused the system palette to change. The pointer may be temporary and should not be stored.

Remarks

Called for all top-level windows after the window with input focus has realized its logical palette thereby changing the system palette. This call allows a window without the input focus that uses a color palette to realize its logical palettes and update its client area.

The OnPaletteChanged member function is called for all top-level and overlapped windows, including the one that changed the system palette and caused the WM_PALETTECHANGED message to be sent. If any child window uses a color palette, this message must be passed on to it.

To avoid an infinite loop, the window shouldn't realize its palette unless it determines that pFocusWnd does not contain a pointer to itself.

See Also

::RealizePalette, WM_PALETTECHANGED, »CWnd::OnPaletteIsChanging«, »CWnd::OnQueryNewPalette«


  CWnd::OnPaletteIsChanging

Windows 3.1 Only

Protected

afx_msg void OnPaletteIsChanging( CWnd* pRealizeWnd ); ♦

pRealizeWnd    Specifies the window that is about to realize its logical palette.

Remarks

Informs applications that an application is going to realize its logical palette.

See Also

»CWnd::OnPaletteChanged«, »CWnd::OnQueryNewPalette«, ::OnPaletteIsChanging


  CWnd::OnParentNotify

Protected

afx_msg void OnParentNotify( UINT message, LPARAM lParam ); ♦

message    Specifies the event for which the parent is being notified. It can be any of these values:

•	WM_CREATE    The child window is being created.

•	WM_DESTROY    The child window is being destroyed.

•	WM_LBUTTONDOWN    The user has placed the mouse cursor over the child window and clicked the left mouse button.

•	WM_MBUTTONDOWN    The user has placed the mouse cursor over the child window and clicked the middle mouse button.

•	WM_RBUTTONDOWN    The user has placed the mouse cursor over the child window and clicked the right mouse button.

lParam    If message is WM_CREATE or WM_DESTROY specifies the window handle of the child window in the low-order word and the identifier of the child window in the high-order word; otherwise lParam contains the x- and y-coordinates of the cursor. The x-coordinate is in the low-order word and the y-coordinate is in the high-order word.

Remarks

A parent's OnParentNotify member function is called when its child window is created or destroyed, or when the user clicks a mouse button while the cursor is over the child window. When the child window is being created, the system calls OnParentNotify just before the »Create« member function that creates the window  returns. When the child window is being destroyed, the system calls OnParentNotify before any processing takes place to destroy the window.

OnParentNotify is called for all ancestor windows of the child window, including the top-level window.

All child windows except those that have the »WS_EX_NOPARENTNOTIFY« style send this message to their parent windows. By default, child windows in a dialog box have the WS_EX_NOPARENTNOTIFY style unless the child window was created without this style by calling the »CreateEx« member function.

See Also

»CWnd::OnCreate«, »CWnd::OnDestroy«, »CWnd::OnLButtonDown«, »CWnd::OnMButtonDown«, »CWnd::OnRButtonDown«, WM_PARENTNOTIFY


  CWnd::OnQueryDragIcon

Protected

afx_msg HCURSOR OnQueryDragIcon(); ♦

Remarks

Called by a minimized (iconic) window that does not have an icon defined for its class. The system makes this call to obtain the cursor to display while the user drags the minimized window.

If an application returns the handle of an icon or cursor, the system converts it to black-and-white.

If an application returns a handle, the handle must identify a monochrome cursor or icon compatible with the display driver's resolution. The application can call the »CWinApp::LoadCursor« or »CWinApp::LoadIcon« member functions to load a cursor or icon from the resources in its executable file and to obtain this handle.

Return Value

A doubleword value that contains a cursor or icon handle in the low-order word. The cursor or icon must be compatible with the display driver's resolution. If the application returns NULL, the system displays the default cursor. The default return value is NULL.

See Also

»CWinApp::LoadCursor«, »CWinApp::LoadIcon«, WM_QUERYDRAGICON


  CWnd::OnQueryEndSession

Protected

afx_msg BOOL OnQueryEndSession(); ♦

Remarks

Called when the user chooses to end the Windows session or when an application calls the ExitWindowsWindows function. If any application returns 0, the Windows session is not ended. Windows stops calling OnQueryEndSession as soon as one application returns 0 and sends the »WM_ENDSESSION« message with a parameter value of FALSE for any application that has already returned nonzero.

Return Value

Nonzero if an application can be conveniently shut down; otherwise 0.

See Also

::ExitWindows, »CWnd::OnEndSession«, WM_QUERYENDSESSION


  CWnd::OnQueryNewPalette

Protected

afx_msg BOOL OnQueryNewPalette(); ♦

Remarks

Called when the CWnd object is about to receive the input focus, giving the CWnd an opportunity to realize its logical palette when it receives the focus.

Return Value

Nonzero if the CWnd realizes its logical palette; otherwise 0.

See Also

»CWnd::Default«, »CWnd::OnPaletteChanged«, »WM_QUERYNEWPALETTE«


  CWnd::OnQueryOpen

Protected

afx_msg BOOL OnQueryOpen(); ♦

Remarks

Called when the CWnd object is minimized and the user requests that the CWnd be restored to its preminimized size and position.

While in OnQueryOpen, CWnd should not perform any action that would cause an activation or focus change (for example, creating a dialog box).

Return Value

Nonzero if the icon can be opened, or 0 to prevent the icon from being opened.

See Also

WM_QUERYOPEN


  CWnd::OnRButtonDblClk

Protected

afx_msg void OnRButtonDblClk( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if ctRl key is down.

•	MK_LBUTTON    Set if left mouse button is down.

•	MK_MBUTTON    Set if middle mouse button is down.

•	MK_RBUTTON    Set if right mouse button is down.

•	MK_SHIFT    Set if shift key is down.

point    Specifies the x- and y-coordinates of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user double-clicks the right mouse button.

Only windows that have the CS_DBLCLKS WNDCLASS style can receive OnRButtonDblClk calls. This is the default for windows within the Microsoft Foundation Class Library. Windows calls OnRButtonDblClk when the user presses, releases, and then again presses the right mouse button within the system's double-click time limit. Double-clicking the right mouse button actually generates four events: »WM_RBUTTONDOWN« and »WM_RBUTTONUP« messages, the OnRButtonDblClk call, and another WM_RBUTTONUP message when the button is released.

See Also

»CWnd::OnRButtonDown«, »CWnd::OnRButtonUp«, WM_RBUTTONDBLCLK


  CWnd::OnRButtonDown

Protected

afx_msg void OnRButtonDown( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if CONTROL key is down.

•	MK_LBUTTON    Set if left mouse button is down.

•	MK_MBUTTON    Set if middle mouse button is down.

•	MK_RBUTTON    Set if right mouse button is down.

•	MK_SHIFT    Set if SHIFT key is down.

point    Specifies the x- and y-coordinates of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user presses the right mouse button.

See Also

»CWnd::OnRButtonDblClk«, »CWnd::OnRButtonUp«, WM_RBUTTONDOWN


  CWnd::OnRButtonUp

Protected

afx_msg void OnRButtonUp( UINT nFlags, CPoint point ); ♦

nFlags    Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

•	MK_CONTROL    Set if ctrl key is down.

•	MK_LBUTTON    Set if left mouse button is down.

•	MK_MBUTTON    Set if middle mouse button is down.

•	MK_SHIFT    Set if shift key is down.

point    Specifies the x- and y-coordinates of the cursor. These coordinates are always relative to the upper-left corner of the window.

Remarks

Called when the user releases the right mouse button.

See Also

»CWnd::OnRButtonDblClk«, »CWnd::OnRButtonDown«, WM_RBUTTONUP


  CWnd::OnRenderAllFormats

Protected

afx_msg void OnRenderAllFormats(); ♦

Remarks

The Clipboard owner's OnRenderAllFormats member function is called when the owner application is being destroyed.

The Clipboard owner should render the data in all the formats it is capable of generating and pass a data handle for each format to the Clipboard by calling the SetClipboardDataWindows function. This ensures that the Clipboard contains valid data even though the application that rendered the data is destroyed. The application should call the »OpenClipboard« member function before calling the SetClipboardDataWindows function and call the CloseClipboardWindows function afterward.

See Also

::CloseClipboard, »CWnd::OpenClipboard«, ::SetClipboardData, »CWnd::OnRenderFormat«, »WM_RENDERALLFORMATS«


  CWnd::OnRenderFormat

Protected

afx_msg void OnRenderFormat( UINT nFormat ); ♦

nFormat    Specifies the Clipboard format.

Remarks

The Clipboard owner's OnRenderFormat member function is called when a particular format with delayed rendering needs to be rendered. The receiver should render the data in that format and pass it to the Clipboard by calling the SetClipboardDataWindows function.

Do not call the OpenClipboard member function or the CloseClipboard Windows function from within OnRenderFormat.

See Also

::CloseClipboard, »CWnd::OpenClipboard«, ::SetClipboardData, WM_RENDERFORMAT


  CWnd::OnSetCursor

Protected

afx_msg BOOL OnSetCursor( CWnd* pWnd, UINT nHitTest,
UINT message ); ♦

pWnd    Specifies a pointer to the window that contains the cursor. The pointer may be temporary and should not be stored for later use.

nHitTest    Specifies the »hit-test« area code. The hit test determines the cursor's location.

message    Specifies the mouse message number.

Remarks

Called if mouse input is not captured and the mouse causes cursor movement within the CWnd object.

The default implementation calls the parent window's OnSetCursor before processing. If the parent window returns TRUE, further processing is halted. Calling the parent window gives the parent window control over the cursor's setting in a child window.

The default implementation sets the cursor to an arrow if it is not in the client area or to the registered-class cursor if it is.

 If nHitTest is HTERROR and message is a mouse button-down message, the MessageBeep member function is called.

The message parameter is 0 when CWnd enters menu mode.

Return Value

Nonzero to halt further processing, or 0 to continue.

See Also

»CWnd::OnNcHitTest«, WM_SETCURSOR


  CWnd::OnSetFocus

Protected

afx_msg void OnSetFocus( CWnd* pOldWnd ); ♦

pOldWnd    Contains the CWnd object that loses the input focus (may be NULL). The pointer may be temporary and should not be stored for later use.

Remarks

Called after gaining the input focus. To display a caret, CWnd should call the appropriate caret functions at this point.

See Also

WM_SETFOCUS


  CWnd::OnShowWindow

Protected

afx_msg void OnShowWindow( BOOL bShow, UINT nStatus ); ♦

bShow    Specifies whether a window is being shown. It is TRUE if the window is being shown; it is FALSE if the window is being hidden.

nStatus    Specifies the status of the window being shown. It is 0 if the message is sent because of a ShowWindow member function call; otherwise nStatus is one of the following:

•	SW_PARENTCLOSING    Parent window is closing (being made iconic) or a pop-up window is being hidden.

•	SW_PARENTOPENING    Parent window is opening (being displayed) or a pop-up window is being shown.

Remarks

Called when the CWnd object is about to be hidden or shown. A window is hidden or shown when the ShowWindow member function is called, when an overlapped window is maximized or restored, or when an overlapped or pop-up window is closed (made iconic) or opened (displayed on the screen). When an overlapped window is closed, all pop-up windows associated with that window are hidden.

See Also

WM_SHOWWINDOW


  CWnd::OnSize

Protected

afx_msg void OnSize( UINT nType, int cx, int cy ); ♦

nType    Specifies the type of resizing requested. This parameter can be one of the following values:

•	SIZE_MAXIMIZED    Window has been maximized.

•	SIZE_MINIMIZED    Window has been minimized.

•	SIZE_RESTORED    Window has been resized, but neither SIZE_MINIMIZED nor SIZE_MAXIMIZED applies.

•	SIZE_MAXHIDE    Message is sent to all pop-up windows when some other window is maximized.

•	SIZE_MAXSHOW    Message is sent to all pop-up windows when some other window has been restored to its former size.

cx    Specifies the new width of the client area.

cy    Specifies the new height of the client area.

Remarks

Called after the window's size has changed.

If the »SetScrollPos« or »MoveWindow« member function is called for a child window from OnSize, the bRedraw parameter of SetScrollPos or MoveWindow should be nonzero to cause the CWnd to be repainted.

See Also

»CWnd::MoveWindow«, »CWnd::SetScrollPos«, WM_SIZE


  CWnd::OnSizeClipboard

Protected

afx_msg void OnSizeClipboard( CWnd* pClipAppWnd, HGLOBAL hRect ); ♦

pClipAppWnd    Identifies the Clipboard-application window. The pointer may be temporary and should not be stored.

hRect    Identifies a global memory object. The memory object contains a »RECT« data structure that specifies the area for the Clipboard owner to paint.

Remarks

The Clipboard owner's OnSizeClipboard member function is called by the Clipboard viewer when the Clipboard contains data with the CF_OWNERDISPLAY attribute and the size of the client area of the Clipboard-viewer window has changed.

The OnSizeClipboard member function is called with a null rectangle (0,0,0,0) as the new size when the Clipboard application is about to be destroyed or minimized. This permits the Clipboard owner to free its display resources.

Within OnSizeClipboard, an application must use the GlobalLockWindows function to lock the memory that contains the »RECT« data structure. Have the application unlock that memory with the GlobalUnlockWindows function before it yields or returns control.

See Also

::GlobalLock,  ::GlobalUnlock, ::SetClipboardData,»CWnd::SetClipboardViewer«, WM_SIZECLIPBOARD


  CWnd::OnSpoolerStatus

Protected

afx_msg void OnSpoolerStatus( UINT nStatus, UINT nJobs ); ♦

nStatus    Specifies the SP_JOBSTATUS flag.

nJobs    Specifies the number of jobs remaining in the Print Manager queue.

Remarks

Called from Print Manager whenever a job is added to or removed from the Print Manager queue.

This call is for informational purposes only.

See Also

WM_SPOOLERSTATUS


  CWnd::OnSysChar

Protected

afx_msg void OnSysChar( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Specifies the ASCII-character key code of a Control-menu key.

nRepCnt    Specifies the repeat count (the number of times the keystroke is repeated as a result of the user holding down the key).

nFlags    The nFlags parameter can have these values:

Value	Meaning
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the message is sent, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
Remarks

Called if CWnd has the input focus and the »WM_SYSKEYUP« and »WM_SYSKEYDOWN« messages are translated. It specifies the virtual-key code of the Control-menu key.

When the context code is 0, WM_SYSCHAR can pass the WM_SYSCHARmessage to the TranslateAcceleratorWindows function, which will handle it as though it were a normal key message instead of a Control-menu key message. This allows accelerator keys to be used with the active window even if the active window does not have the input focus.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

::TranslateAccelerator, »WM_SYSKEYDOWN«, »WM_SYSKEYUP«, WM_SYSCHAR


  CWnd::OnSysColorChange

Protected

afx_msg void OnSysColorChange(); ♦

Remarks

Called for all top-level windows when a change is made in the system color setting.

Windows calls OnSysColorChange for any window that is affected by a system color change.

Applications that have brushes that use the existing system colors should delete those brushes and re-create them with the new system colors.

See Also

::SetSysColors, WM_SYSCOLORCHANGE


  CWnd::OnSysCommand

Protected

afx_msg void OnSysCommand( UINT nID, LPARAM lParam ); ♦

nID    Specifies the type of system command requested. This parameter can be one of the following values, with meanings as given:

•	SC_CLOSE    Close the CWnd object.

•	SC_HOTKEY    Activate the CWnd object associated with the application-specified hot key. The low-order word of lParam identifies the HWND of the window to activate.

•	SC_HSCROLL    Scroll horizontally.

•	SC_KEYMENU    Retrieve a menu through a keystroke.

•	SC_MAXIMIZE (or SC_ZOOM)    Maximize the CWnd object.

•	SC_MINIMIZE (or SC_ICON)    Minimize the CWnd object.

•	SC_MOUSEMENU    Retrieve a menu through a mouse click.

•	SC_MOVE    Move the CWnd object.

•	SC_NEXTWINDOW    Move to the next window.

•	SC_PREVWINDOW    Move to the previous window.

•	SC_RESTORE    Restore window to normal position and size.

•	SC_SCREENSAVE    Executes the screen-saver application specified in the [boot] section of the SYSTEM.INI file.

•	SC_SIZE    Size the CWnd object.

•	SC_TASKLIST    Execute or activate the Windows Task Manager application.

•	SC_VSCROLL    Scroll vertically.

lParam    If a Control-menu command is chosen with the mouse contains the cursor coordinates. The low-order word contains the x-coordinate, and the high-order word contains the y-coordinate. Otherwise this parameter is not used.

Windows 3.1 Only

•	SC_HOTKEY    Activate the window associated with the application-specified hot key. The low-order word of lParam identifies the window to activate.

•	SC_SCREENSAVE    Execute the screen-save application specified in the Desktop section of Control Panel. ♦

Remarks

Called when the user selects a command from the Control menu, or when the user selects the Maximize or the Minimize button.

By default, OnSysCommand carries out the Control-menu request for the predefined actions specified in the preceding table.

In WM_SYSCOMMAND messages, the four low-order bits of the nID parameter are used internally by Windows. When an application tests the value of nID, it must combine the value 0xFFF0 with the nID value by using the bitwise-AND operator to obtain the correct result.

The menu items in a Control menu can be modified with the GetSystemMenu, AppendMenu, InsertMenu, and ModifyMenu member functions. Applications that modify the Control menu must process WM_SYSCOMMAND messages, and any WM_SYSCOMMAND messages not handled by the application must be passed on to OnSysCommand. Any command values added by an application must be processed by the application and cannot be passed to OnSysCommand.

An application can carry out any system command at any time by passing a WM_SYSCOMMAND message to OnSysCommand.

Accelerator (shortcut) keystrokes that are defined to select items from the Control menu are translated into OnSysCommand calls; all other accelerator keystrokes are translated into »WM_COMMAND« messages.

See Also

WM_SYSCOMMAND


  CWnd::OnSysDeadChar

Protected

afx_msg void OnSysDeadChar( UINT nChar, UINT nRepCnt,
UINT nFlags ); ♦

nChar    Specifies the dead-key character value.

nRepCnt    Specifies the repeat count.

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Meaning
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed; otherwise 0).
14	Previous key state (1 if the key is down before the call, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
Remarks

Called if the CWnd object has the input focus when the »OnSysKeyUp« or »OnSysKeyDown« member function is called. It specifies the character value of a dead key.

See Also

»CWnd::OnSysKeyDown«, »CWnd::OnSysKeyUp«, WM_SYSDEADCHAR, »CWnd::OnDeadChar«


  CWnd::OnSysKeyDown

Protected

afx_msg void OnSysKeyDown( UINT nChar, UINT nRepCnt,
UINT nFlags ); ♦

nChar    Specifies the virtual-key code of the key being pressed.

nRepCnt    Specifies the repeat count.

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Meaning
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed, 0 otherwise).
14	Previous key state (1 if the key is down before the message is sent, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
For OnSysKeyDown calls, the key-transition bit (bit 15) is 0. The context-code bit (bit 13) is 1 if the ALT key is down while the key is pressed; it is 0 if the message is sent to the active window because no window has the input focus.

Remarks

If the CWnd object has the input focus, the OnSysKeyDown member function is called when the user holds down the ALT key and then presses another key. If no window currently has the input focus, the active window's OnSysKeyDown member function is called. The CWnd object that receives the message can distinguish between these two contexts by checking the context code in nFlags.

When the context code is 0, the WM_SYSKEYDOWN message received by OnSysKeyDown can be passed to the TranslateAcceleratorWindows function, which will handle it as though it were a normal key message instead of a system-key message. This allows accelerator keys to be used with the active window even if the active window does not have the input focus.

Because of auto-repeat, more than one OnSysKeyDown call may occur before the »WM_SYSKEYUP« message is received. The previous key state (bit 14) can be used to determine whether the OnSysKeyDown call indicates the first down transition or a repeated down transition.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

See Also

::TranslateAccelerator, »WM_SYSKEYUP«, WM_SYSKEYDOWN


  CWnd::OnSysKeyUp

Protected

afx_msg void OnSysKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags ); ♦

nChar    Specifies the virtual-key code of the key being pressed.

nRepCnt    Specifies the repeat count.

nFlags    Specifies the scan code, key-transition code, previous key state, and context code, as shown in the following list:

Value	Meaning
0−7	Scan code (OEM-dependent value). Low byte of high-order word.
8	Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0).
9−10	Not used.
11−12	Used internally by Windows.
13	Context code (1 if the ALT key is held down while the key is pressed, 0 otherwise).
14	Previous key state (1 if the key is down before the message is sent, 0 if the key is up).
15	Transition state (1 if the key is being released, 0 if the key is being pressed).
For OnSysKeyUp calls, the key-transition bit (bit 15) is 1. The context-code bit (bit 13) is 1 if the ALT key is down while the key is pressed; it is 0 if the message is sent to the active window because no window has the input focus.

Remarks

If the CWnd object has the focus, the OnSysKeyUp member function is called when the user releases a key that was pressed while the ALT key was held down. If no window currently has the input focus, the active window's OnSysKeyUp member function is called. The CWnd object that receives the call can distinguish between these two contexts by checking the context code in nFlags.

When the context code is 0, the WM_SYSKEYUP message received by OnSysKeyUp can be passed to the TranslateAcceleratorWindows function, which will handle it as though it were a normal key message instead of a system-key message. This allows accelerator (shortcut) keys to be used with the active window even if the active window does not have the input focus.

For IBM Enhanced 101- and 102-key keyboards, enhanced keys are the right ALT and the right CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the slash (/) and ENTER keys in the numeric keypad. Some other keyboards may support the extended-key bit in nFlags.

For non-U.S. Enhanced 102-key keyboards, the right ALT key is handled as the CTRL+ALT key combination. The following shows the sequence of messages and calls that result when the user presses and releases this key:

Sequence	Function Accessed	Message Passed
1.	»WM_KEYDOWN«	VK_CONTROL
2.	»WM_KEYDOWN«	VK_MENU
3.	»WM_KEYUP«	VK_CONTROL
4.	WM_SYSKEYUP	VK_MENU
See Also

::TranslateAccelerator, »WM_SYSKEYDOWN«, WM_SYSKEYUP


  CWnd::OnTimeChange

Protected

afx_msg void OnTimeChange(); ♦

Remarks

Called after the system time is changed.

Have any application that changes the system time send this message to all top-level windows. To send the WM_TIMECHANGE message to all top-level windows, an application can use the SendMessageWindows function with its hwnd parameter set to HWND_BROADCAST.

See Also

::SendMessage, WM_TIMECHANGE


  CWnd::OnTimer

Protected

afx_msg void OnTimer( UINT  nIDEvent ); ♦

nIDEvent    Specifies the identifier of the timer.

Remarks

Called after each interval specified in the »SetTimer« member function used to install a timer.

The DispatchMessage Windows function sends a WM_TIMER message when no other messages are in the application's message queue.

See Also

»CWnd::SetTimer«,  WM_TIMER


  CWnd::OnVKeyToItem

Protected

afx_msg int OnVKeyToItem( UINT nKey, CListBox* pListBox,
UINT nIndex ); ♦

nKey    Specifies the virtual-key code of the key that the user pressed.

pListBox    Specifies a pointer to the list box. The pointer may be temporary and should not be stored for later use.

nIndex    Specifies the current caret position.

Remarks

If the CWnd object owns a list box with the »LBS_WANTKEYBOARDINPUT« style, the list box will send the WM_VKEYTOITEM message in response to a WM_KEYDOWN message.

This member function is called only for list boxes that have the LBS_HASSTRINGS style.

Return Value

Specifies the action that the application performed in response to the message. A return value of −2 indicates that the application handled all aspects of selecting the item and requires no further action by the list box. A return value of −1 indicates that the list box should perform the default action in response to the keystroke. A return value of 0 or greater specifies the zero-based index of an item in the list box and indicates that the list box should perform the default action for the keystroke on the given item.

See Also

»WM_KEYDOWN«, WM_VKEYTOITEM


  CWnd::OnVScroll

Protected

afx_msg void OnVScroll( UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar ); ♦

nSBCode    Specifies a scroll-bar code that indicates the user's scrolling request. This parameter can be one of the following:

•	SB_BOTTOM    Scroll to bottom.

•	SB_ENDSCROLL    End scroll.

•	SB_LINEDOWN    Scroll one line down.

•	SB_LINEUP    Scroll one line up.

•	SB_PAGEDOWN    Scroll one page down.

•	SB_PAGEUP    Scroll one page up.

•	SB_THUMBPOSITION    Scroll to the absolute position. The current position is provided in nPos.

•	SB_THUMBTRACK    Drag scroll box to specified position. The current position is provided in nPos.

•	SB_TOP    Scroll to top.

nPos    Contains the current scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.

pScrollBar    If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window's scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.

Remarks

Called when the user clicks the window's vertical scroll bar.

OnVScroll typically is used by applications that give some feedback while the scroll box is being dragged.

If OnVScroll scrolls the contents of the CWnd object, it must also reset the position of the scroll box with the »SetScrollPos« member function.

See Also

»CWnd::SetScrollPos«, »CWnd::OnHScroll«, WM_VSCROLL


  CWnd::OnVScrollClipboard

Protected

afx_msg void OnVScrollClipboard( CWnd* pClipAppWnd, UINT nSBCode, UINT nPos ); ♦

pClipAppWnd    Specifies a pointer to a Clipboard-viewer window. The pointer may be temporary and should not be stored for later use.

nSBCode    Specifies one of the following scroll-bar values:

•	SB_BOTTOM    Scroll to bottom.

•	SB_ENDSCROLL    End scroll.

•	SB_LINEDOWN    Scroll one line down.

•	SB_LINEUP    Scroll one line up.

•	SB_PAGEDOWN    Scroll one page down.

•	SB_PAGEUP    Scroll one page up.

•	SB_THUMBPOSITION    Scroll to the absolute position. The current position is provided in nPos.

•	SB_TOP    Scroll to top.

nPos    Contains the scroll-box position if the scroll-bar code is SB_THUMBPOSITION; otherwise nPos is not used.

Remarks

The Clipboard owner's OnVScrollClipboard member function is called by the Clipboard viewer when the Clipboard data has the CF_OWNERDISPLAY format and there is an event in the Clipboard viewer's vertical scroll bar. The owner should scroll the Clipboard image, invalidate the appropriate section, and update the scroll-bar values.

See Also

»CWnd::Invalidate«, »CWnd::OnHScrollClipboard«, »CWnd::InvalidateRect«, WM_VSCROLLCLIPBOARD, »CWnd::Default«


  CWnd::OnWindowPosChanged

Windows 3.1 Only

Protected

afx_msg void OnWindowPosChanged( WINDOWPOS FAR* lpwndpos ); ♦

lpwndpos    Points to a »WINDOWPOS« data structure that contains information about the window's new size and position.

Remarks

Called when the size, position, or Z-order has changed as a result of a call to the SetWindowPosmember function or another window-management function.

The default implementation sends the WM_SIZEand WM_MOVEmessages to the window. These messages are not sent if an application handles the OnWindowPosChanged call without calling its base class. It is more efficient to perform any move or size change processing during the call to OnWindowPosChanged without calling its base class.

See Also

WM_WINDOWPOSCHANGED


  CWnd::OnWindowPosChanging

Windows 3.1 Only

Protected

afx_msg void OnWindowPosChanging( WINDOWPOS FAR* lpwndpos ); ♦

lpwndpos    Points to a WINDOWPOS data structure that contains information about the window's new size and position.

Remarks

Called when the size, position, or Z-order is about to change as a result of a call to the SetWindowPosmember function or another window-management function.

An application can prevent changes to the window by setting or clearing the appropriate bits in the flags member of the »WINDOWPOS« structure.

For a window with the »WS_OVERLAPPED« or »WS_THICKFRAME« style, the default implementation sends a WM_GETMINMAXINFOmessage to the window. This is done to validate the new size and position of the window and to enforce the CS_BYTEALIGNCLIENT and CS_BYTEALIGN client styles. An application can override this functionality by not calling its base class.

WINDOWPOS Structure

Windows 3.1 Only

A WINDOWPOS data structure has this form:

typedef struct tagWINDOWPOS { /* wp */
    HWND    hwnd;
    HWND    hwndInsertAfter;
    int     x;
    int     y;
    int     cx;
    int     cy;
    UINT    flags;
} WINDOWPOS;

The WINDOWPOS structure contains information about the size and position of a window. ♦

Members

A WINDOWPOS structure has the following members:

hwnd    Identifies the window.

hwndInsertAfter    Identifies the window behind which this window is placed.

x    Specifies the position of the left edge of the window.

y    Specifies the position of the right edge of the window.

cx    Specifies the window width.

cy    Specifies the window height.

flags    Specifies window-positioning options. This member can be one of the following values:

•	SWP_DRAWFRAME    Draws a frame (defined in the class description for the window) around the window. The window receives a WM_NCCALCSIZE message.

•	SWP_HIDEWINDOW    Hides the window.

•	SWP_NOACTIVATE    Does not activate the window.

•	SWP_NOMOVE    Retains current position (ignores the x and y members).

•	SWP_NOOWNERZORDER    Does not change the owner window's position in the Z-order.

•	SWP_NOSIZE    Retains current size (ignores the cx and cy members).

•	SWP_NOREDRAW    Does not redraw changes.

•	SWP_NOREPOSITION    Same as SWP_NOOWNERZORDER.

•	SWP_NOZORDER    Retains current ordering (ignores the hwndInsertAfter member).

•	SWP_SHOWWINDOW    Displays the window.

See Also

»CWnd::OnWindowPosChanged«, WM_WINDOWPOSCHANGING


  CWnd::OnWinIniChange

Protected

afx_msg void OnWinIniChange( LPCSTR lpszSection ); ♦

lpszSection    Points to a string that specifies the name of the section that has changed. (The string does not include the square brackets that enclose the section name.)

Remarks

Called after a change has been made to the Windows initialization file, WIN.INI.

The SystemParametersInfoWindows function calls OnWinIniChange after an application uses the function to change a setting in the WIN.INI file.

To send the WM_WININICHANGE message to all top-level windows, an application can use the SendMessageWindows function with its hwnd parameter set to HWND_BROADCAST.

If an application changes many different sections in WIN.INI at the same time, the application should send one WM_WININICHANGE message with lpszSection set to NULL. Otherwise, an application should send WM_WININICHANGE each time it makes a change to WIN.INI.

If an application receives an OnWinIniChange call with lpszSection set to NULL, the application should check all sections in WIN.INI that affect the application.

See Also

::SendMessage, ::SystemParametersInfo, WM_WININICHANGE


  CWnd::OpenClipboard

BOOL OpenClipboard();

Remarks

Opens the Clipboard. Other applications will not be able to modify the Clipboard until the CloseClipboardWindows function is called.

The current CWnd object will not become the owner of the Clipboard until the EmptyClipboardWindows function is called.

Return Value

Nonzero if the Clipboard is opened via CWnd, or 0 if another application or window has the Clipboard open.

See Also

::CloseClipboard, ::EmptyClipboard::OpenClipboard


  CWnd::PostMessage

BOOL PostMessage( UINT message, WPARAM wParam = 0,
LPARAM lParam = 0 );

message    Specifies the message to be posted.

wParam    Specifies additional message information. The content of this parameter depends on the message being posted.

lParam    Specifies additional message information. The content of this parameter depends on the message being posted.

Remarks

Places a message in the window's message queue and then returns without waiting for the corresponding window to process the message. Messages in a message queue are retrieved by calls to the GetMessageor PeekMessageWindows function.

The Windows PostMessage function can be used to access another application.

Return Value

Nonzero if the message is posted; otherwise 0.

See Also

::GetMessage, ::PeekMessage, ::PostMessage, ::PostAppMessage, »CWnd::SendMessage«


  CWnd::PostNcDestroy

Remarks

Called by the default OnNcDestroy member function after the window has been destroyed. Derived classes can use this function for custom cleanup such as the deletion of the this pointer.

See Also

»CWnd::OnNcDestroy«


  CWnd::PreCreateWindow

virtual BOOL PreCreateWindow( CREATESTRUCT& cs );

cs    A »CREATESTRUCT« structure.

Remarks

Called by the framework before the creation of the Windows window attached to this CWnd object.

Never call this function directly.

The default implementation of this function checks for a NULL window class name and substitutes an appropriate default.

Override this member function to modify the CREATESTRUCT structure before the window is created. If you override this member function, you should examine the source code to determine whether or not you need to invoke the base class implementation.

Return Value

Nonzero if the window creation should continue; 0 to indicate creation failure.

See Also

»CWnd::Create«, »CREATESTRUCT«


  CWnd::PreTranslateMessage

virtual BOOL PreTranslateMessage( MSG* pMsg );

pMsg    Points to a MSG structure that contains the message to process.

Remarks

Used by class »CWinApp« to translate window messages before they are dispatched to the TranslateMessage and DispatchMessageWindows functions.

Return Value

Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.

See Also

::TranslateMessage, ::IsDialogMessage, »CWinApp::PreTranslateMessage«


  CWnd::RedrawWindow

Windows 3.1 Only

BOOL RedrawWindow( LPCRECT lpRectUpdate = NULL,
CRgn* prgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE ); ♦

lpRectUpdate    Points to a RECT structure containing the coordinates of the update rectangle. This parameter is ignored if prgnUpdate contains a valid region handle.

prgnUpdate    Identifies the update region. If both prgnUpdate and lpRectUpdate are NULL, the entire client area is added to the update region.

flags    The following flags are used to invalidate the window:

•	RDW_ERASE    Causes the window to receive a WM_ERASEBKGND message when the window is repainted. The RDW_INVALIDATE flag must also be specified; otherwise RDW_ERASE has no effect.

•	RDW_FRAME    Causes any part of the nonclient area of the window that intersects the update region to receive a WM_NCPAINT message. The RDW_INVALIDATE flag must also be specified; otherwise RDW_FRAME has no effect.

•	RDW_INTERNALPAINT    Causes a WM_PAINT message to be posted to the window regardless of whether the window contains an invalid region.

•	RDW_INVALIDATE    Invalidate lpRectUpdate or prgnUpdate (only one may be not NULL). If both are NULL, the entire window is invalidated.

The following flags are used to validate the window:

•	RDW_NOERASE    Suppresses any pending WM_ERASEBKGND messages.

•	RDW_NOFRAME    Suppresses any pending WM_NCPAINT messages. This flag must be used with RDW_VALIDATE and is typically used with RDW_NOCHILDREN. This option should be used with care, as it could prevent parts of a window from painting properly.

•	RDW_NOINTERNALPAINT    Suppresses any pending internal WM_PAINT messages. This flag does not affect WM_PAINT messages resulting from invalid areas.

•	RDW_VALIDATE    Validates lpRectUpdate or prgnUpdate (only one may be not NULL). If both are NULL, the entire window is validated. This flag does not affect internal WM_PAINT messages.

The following flags control when repainting occurs. Painting is not performed by the RedrawWindow function unless one of these bits is specified.

•	RDW_ERASENOW    Causes the affected windows (as specified by the RDW_ALLCHILDREN and RDW_NOCHILDREN flags) to receive WM_NCPAINT and WM_ERASEBKGND messages, if necessary, before the function returns. WM_PAINT messages are deferred.

•	RDW_UPDATENOW    Causes the affected windows (as specified by the RDW_ALLCHILDREN and RDW_NOCHILDREN flags) to receive WM_NCPAINT, WM_ERASEBKGND, and WM_PAINT messages, if necessary, before the function returns.

By default, the windows affected by the RedrawWindow function depend on whether the specified window has the WS_CLIPCHILDREN style. The child windows of WS_CLIPCHILDREN windows are not affected. However, those windows that are not WS_CLIPCHILDREN windows are recursively validated or invalidated until a WS_CLIPCHILDREN window is encountered. The following flags control which windows are affected by the RedrawWindow function:

•	RDW_ALLCHILDREN    Includes child windows, if any, in the repainting operation.

•	RDW_NOCHILDREN    Excludes child windows, if any, from the repainting operation.

Remarks

Updates the specified rectangle or region in the given window's client area.

When the RedrawWindow member function is used to invalidate part of the desktop window, that window does not receive a WM_PAINTmessage. To repaint the desktop, an application should use »CWnd::ValidateRgn«, »CWnd::InvalidateRgn«, »CWnd::UpdateWindow«, or ::RedrawWindow


  CWnd::ReleaseDC

int ReleaseDC( CDC* pDC );

pDC    Identifies the device context to be released.

Remarks

Releases a device context, freeing it for use by other applications. The effect of the ReleaseDC member function depends on the device-context type.

The application must call the ReleaseDC member function for each call to the »GetWindowDC« member function and for each call to the »GetDC« member function.

Return Value

Nonzero if successful; otherwise 0.

See Also

»CWnd::GetDC«, »CWnd::GetWindowDC«, ::ReleaseDC


  CWnd::RepositionBars

void RepositionBars( UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver );

nIDFirst    Specifies ID of first of a range of control bars to reposition and resize.

nIDLast    Specifies ID of last of a range of control bars to reposition and resize.

nIDLeftOver    Specifies ID of pane that fills the rest of the client area.

Remarks

Called to reposition and resize control bars in the client area of a window. The nIDFirst and nIDLast parameters define a range of control bar ID's to be repositioned in the client area. nIDLeftOver specifies the ID of the child window (normally the view) which is repositioned and resized to fill the rest of the client area not filled by control bars.

See Also

»CFrameWnd::RecalcLayout«


  CWnd::ScreenToClient

void ScreenToClient( LPPOINT lpPoint ) const;

void ScreenToClient( LPRECT lpRect ) const;

lpPoint    Points to a CPoint object or »POINT« structure that contains the screen coordinates to be converted.

lpRect    Points to a CRect object or »RECT« structure that contains the screen coordinates to be converted.

Remarks

Converts the screen coordinates of a given point or rectangle on the display to client coordinates.

The ScreenToClient member function replaces the screen coordinates given in lpPoint or lpRect with client coordinates. The new coordinates are relative to the upper-left corner of the CWnd client area.

See Also

»CWnd::ClientToScreen,« ::ScreenToClient


  CWnd::ScrollWindow

void ScrollWindow( int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL );

xAmount    Specifies the amount, in device units, of horizontal scrolling. This parameter must be a negative value to scroll to the left.

yAmount    Specifies the amount, in device units, of vertical scrolling. This parameter must be a negative value to scroll up.

lpRect    Points to a CRect object or »RECT« structure that specifies the portion of the client area to be scrolled. If lpRect is NULL, the entire client area is scrolled. The caret is repositioned if the cursor rectangle intersects the scroll rectangle.

lpClipRect    Points to a CRect object or RECT structure that specifies the clipping rectangle to scroll. Only bits inside this rectangle are scrolled. Bits outside this rectangle are not affected even if they are in the lpRect rectangle. If lpClipRect is NULL, no clipping is performed on the scroll rectangle.

Remarks

Scrolls the contents of the client area of the current CWnd object.

If the caret is in the CWnd being scrolled, ScrollWindow automatically hides the caret to prevent it from being erased and then restores the caret after the scroll is finished. The caret position is adjusted accordingly.

The area uncovered by the ScrollWindow member function is not repainted but is combined into the current CWnd object's update region. The application will eventually receive a WM_PAINT message notifying it that the region needs repainting. To repaint the uncovered area at the same time the scrolling is done, call the »UpdateWindow« member function immediately after calling ScrollWindow.

If lpRect is NULL, the positions of any child windows in the window are offset by the amount specified by xAmount and yAmount, and any invalid (unpainted) areas in the CWnd are also offset. ScrollWindow is faster when lpRect is NULL.

If lpRect is not NULL, the positions of child windows are not changed, and invalid areas in CWnd are not offset. To prevent updating problems when lpRect is not NULL, call the UpdateWindow member function to repaint CWnd before calling ScrollWindow.

See Also

»CWnd::UpdateWindow«, ::ScrollWindow


  CWnd::ScrollWindowEx

Windows 3.1 Only

int ScrollWindowEx( int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, CRgn* prgnUpdate, LPRECT lpRectUpdate, UINT flags ); ♦

dx    Specifies the amount, in device units, of horizontal scrolling. This parameter must have a negative value to scroll to the left.

dy    Specifies the amount, in device units, of vertical scrolling. This parameter must have a negative value to scroll up.

lpRectScroll    Points to a RECT structure that specifies the portion of the client area to be scrolled. If this parameter is NULL, the entire client area is scrolled.

lpRectClip    Points to a RECT structure that specifies the clipping rectangle to scroll. This structure takes precedence over the rectangle pointed to by lpRectScroll. Only bits inside this rectangle are scrolled. Bits outside this rectangle are not affected even if they are in the lpRectScroll rectangle. If this parameter is NULL, no clipping is performed on the scroll rectangle.

prgnUpdate    Identifies the region that is modified to hold the region invalidated by scrolling. This parameter may be NULL.

lpRectUpdate    Points to a RECT structure that will receive the boundaries of the rectangle invalidated by scrolling. This parameter may be NULL.

flags    Can have one of the following values:

•	SW_ERASE    When specified with SW_INVALIDATE, erases the newly invalidated region by sending a WM_ERASEBKGND message to the window.

•	SW_INVALIDATE    Invalidates the region identified by prgnUpdate after scrolling.

•	SW_SCROLLCHILDREN    Scrolls all child windows that intersect the rectangle pointed to by lpRectScroll by the number of pixels specified in dx and dy. Windows sends a WM_MOVE message to all child windows that intersect lpRectScroll, even if they do not move. The caret is repositioned when a child window is scrolled and the cursor rectangle intersects the scroll rectangle.

Remarks

Scrolls the contents of a window's client area. This function is similar to the ScrollWindowfunction, with some additional features.

If SW_INVALIDATEand SW_ERASEare not specified, the ScrollWindowEx member function does not invalidate the area that is scrolled away from. If either of these flags is set, ScrollWindowEx invalidates this area. The area is not updated until the application calls the UpdateWindowmember function, calls the RedrawWindowmember function (specifying RDW_UPDATENOWor RDW_ERASENOW), or retrieves the WM_PAINTmessage from the application queue.

If the window has the WS_CLIPCHILDRENstyle, the returned areas specified by prgnUpdate and lpRectUpdate represent the total area of the scrolled window that must be updated, including any areas in child windows that need updating.

If the SW_SCROLLCHILDRENflag is specified, Windows will not properly update the screen if part of a child window is scrolled. The part of the scrolled child window that lies outside the source rectangle will not be erased and will not be redrawn properly in its new destination. Use the »DeferWindowPos«Windows function to move child windows that do not lie completely within the lpRectScroll rectangle. The cursor is repositioned if the SW_SCROLLCHILDREN flag is set and the caret rectangle intersects the scroll rectangle.

All input and output coordinates (for lpRectScroll, lpRectClip, lpRectUpdate, and prgnUpdate) are assumed to be in client coordinates, regardless of whether the window has the CS_OWNDCor CS_CLASSDCclass style. Use the LPtoDP and DPtoLPWindows functions to convert to and from logical coordinates, if necessary.

Return Value

The return value is SIMPLEREGION (rectangular invalidated region), COMPLEXREGION (nonrectangular invalidated region; overlapping rectangles), or NULLREGION (no invalidated region), if the function is successful; otherwise the return value is ERROR.

See Also

»CWnd::RedrawWindow«, »CDC::ScrollDC«, »CWnd::ScrollWindow«, »CWnd::UpdateWindow«, ::DeferWindowPos, ::ScrollWindowEx


  CWnd::SendDlgItemMessage

LRESULT SendDlgItemMessage( int nID, UINT message,
WPARAM wParam = 0, LPARAM lParam = 0 );

nID    Specifies the identifier of the dialog control that will receive the message.

message    Specifies the message to be sent.

wParam    Specifies additional message-dependent information.

lParam    Specifies additional message-dependent information.

Remarks

Sends a message to a control.

The SendDlgItemMessage member function does not return until the message has been processed.

Using SendDlgItemMessage is identical to obtaining a CWnd* to the given control and calling the »SendMessage« member function.

Return Value

Specifies the value returned by the control's window procedure, or 0 if the control was not found.

See Also

»CWnd::SendMessage«, ::SendDlgItemMessage


  CWnd::SendMessage

LRESULT SendMessage( UINT message, WPARAM wParam = 0,
LPARAM lParam = 0 );

message    Specifies the message to be sent.

wParam    Specifies additional message-dependent information.

lParam    Specifies additional message-dependent information.

Remarks

Sends the specified message to this window. The SendMessage member function calls the window procedure directly and does not return until that window procedure has processed the message. This is in contrast to the »PostMessage« member function, which places the message into the window's message queue and returns immediately.

Return Value

The result of the message processing; its value depends on the message sent.

See Also

::InSendMessage, »CWnd::PostMessage«, »CWnd::SendDlgItemMessage«, ::SendMessage


  CWnd::SendMessageToDescendants

void SendMessageToDescendants( UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE );

message    Specifies the message to be sent.

wParam    Specifies additional message-dependent information.

lParam    Specifies additional message-dependent information.

bDeep    Specifies the level to which to search. If TRUE, search all children; if FALSE, search only immediate children.

Remarks

Call this member function to send the specified Windows message to all descendant windows. If the bDeep parameter is FALSE, the message is sent just to the immediate children of the window; otherwise the message is sent to all descendant windows.


  CWnd::SetActiveWindow

CWnd* SetActiveWindow();

Remarks

Makes CWnd the active window.

The SetActiveWindow member function should be used with care since it allows an application to arbitrarily take over the active window and input focus. Normally, Windows takes care of all activation.

Return Value

The window that was previously active.

The returned pointer may be temporary and should not be stored for later use.

See Also

::SetActiveWindow, »CWnd::GetActiveWindow«


  CWnd::SetCapture

CWnd* SetCapture();

Remarks

Causes all subsequent mouse input to be sent to the current CWnd object regardless of the position of the cursor.

When CWnd no longer requires all mouse input, the application should call the ReleaseCapturefunction so that other windows can receive mouse input.

Return Value

A pointer to the window object that previously received all mouse input. It is NULL if there is no such window. The returned pointer may be temporary and should not be stored for later use.

See Also

::ReleaseCapture, ::SetCapture, »CWnd::GetCapture«


  CWnd::SetCaretPos

static void PASCAL SetCaretPos( POINT point );

point    Specifies the new x- and y-coordinates (in client coordinates) of the caret.

Remarks

Sets the position of the caret.

The SetCaretPos member function moves the caret only if it is owned by a window in the current task. SetCaretPos moves the caret whether or not the caret is hidden.

The caret is a shared resource. A window should not move the caret if it does not own the caret.

See Also

»CWnd::GetCaretPos«, ::SetCaretPos


  CWnd::SetClipboardViewer

HWND SetClipboardViewer();

Remarks

Adds this window to the chain of windows that are notified (by means of the WM_DRAWCLIPBOARD message) whenever the content of the Clipboard is changed.

A window that is part of the Clipboard-viewer chain must respond to »WM_DRAWCLIPBOARD«, »WM_CHANGECBCHAIN«, and »WM_DESTROY« messages and pass the message to the next window in the chain.

This member function sends a WM_DRAWCLIPBOARD message to the window. Since the handle to the next window in the Clipboard-viewer chain has not yet been returned, the application should not pass on the WM_DRAWCLIPBOARD message that it receives during the call to SetClipboardViewer.

To remove itself from the Clipboard-viewer chain, an application must call the »ChangeClipboardChain« member function.

Return Value

A handle to the next window in the Clipboard-viewer chain if successful. Applications should save this handle (it can be stored as a member variable) and use it when responding to Clipboard-viewer chain messages.

See Also

»CWnd::ChangeClipboardChain«, ::SetClipboardViewer


  CWnd::SetDlgItemInt

void SetDlgItemInt( int nID, UINT nValue, BOOL bSigned = TRUE );

nID    Specifies the integer ID of the control to be changed.

nValue    Specifies the integer value used to generate the item text.

bSigned    Specifies whether the integer value is signed or unsigned. If this parameter is TRUE, nValue is signed. If this parameter is TRUE and nValue is less than 0, a minus sign is placed before the first digit in the string. If this parameter is FALSE, nValue is unsigned.

Remarks

Sets the text of a given control in a dialog box to the string representation of a specified integer value.

SetDlgItemInt sends a WM_SETTEXT message to the given control.

See Also

»CWnd::GetDlgItemInt«, ::SetDlgItemInt, WM_SETTEXT


  CWnd::SetDlgItemText

void SetDlgItemText( int nID, LPCSTR lpszString );

nID    Identifies the control whose text is to be set.

lpszString    Points to a CString object or null-terminated string that contains the text to be copied to the control.

Remarks

Sets the caption or text of a control owned by a window or dialog box.

SetDlgItemText sends a WM_SETTEXT message to the given control.

See Also

::SetDlgItemText, WM_SETTEXT, »CWnd::GetDlgItemText«


  CWnd::SetFocus

CWnd* SetFocus();

Remarks

Claims the input focus. The input focus directs all subsequent keyboard input to this window. The window, if any, that previously had the input focus loses it.

The SetFocus member function sends a WM_KILLFOCUSmessage to the window that loses the input focus and a WM_SETFOCUSmessage to the window that receives the input focus. It also activates either the window or its parent.

If the current window is active but doesn't have the focus (that is, no window has the focus), any key pressed will produce the messages »WM_SYSCHAR«, »WM_SYSKEYDOWN«, or »WM_SYSKEYUP«.

Return Value

A pointer to the window object that previously had the input focus. It is NULL if there is no such window. The returned pointer may be temporary and should not be stored.

See Also

::SetFocus»CWnd::GetFocus«


  CWnd::SetFont

void SetFont( CFont* pFont, BOOL bRedraw = TRUE );

pFont    Specifies the new font.

bRedraw    If TRUE, redraw the CWnd object.

Remarks

Sets the window's current font to the specified font. If bRedraw is TRUE, the window will also be redrawn.

See Also

»CWnd::GetFont«, WM_SETFONT


  CWnd::SetMenu

BOOL SetMenu( CMenu* pMenu );

pMenu    Identifies the new menu. If this parameter is NULL, the current menu is removed.

Remarks

Sets the current menu to the specified menu. Causes the window to be redrawn to reflect the menu change.

SetMenu will not destroy a previous menu. An application should call the »CMenu::DestroyMenu« member function to accomplish this task.

Return Value

Nonzero if the menu is changed; otherwise 0.

See Also

»CMenu::DestroyMenu«, »CMenu::LoadMenu«, ::SetMenu, »CWnd::GetMenu«


  CWnd::SetParent

CWnd* SetParent( CWnd* pWndNewParent );

pWndNewParent    Identifies the new parent window.

Remarks

Changes the parent window of a child window.

If the child window is visible, Windows performs the appropriate redrawing and repainting.

Return Value

A pointer to the previous parent window object if successful. The returned pointer may be temporary and should not be stored for later use.

See Also

::SetParent, »CWnd::GetParent«


  CWnd::SetRedraw

void SetRedraw( BOOL bRedraw = TRUE );

bRedraw    Specifies the state of the redraw flag. If this parameter is TRUE, the redraw flag is set; if FALSE, the flag is cleared.

Remarks

An application calls SetRedraw to allow changes to be redrawn or to prevent changes from being redrawn.

This member function sets or clears the redraw flag. While the redraw flag is cleared, the contents will not be updated after each change and will not be repainted until the redraw flag is set. For example, an application that needs to add several items to a list box can clear the redraw flag, add the items, and then set the redraw flag. Finally, the application can call the »Invalidate« or »InvalidateRect« member function to cause the list box to be repainted.

See Also

WM_SETREDRAW


  CWnd::SetScrollPos

int SetScrollPos( int nBar, int nPos, BOOL bRedraw = TRUE );

nBar    Specifies the scroll bar to be set. This parameter can be one of the following:

•	SB_HORZ    Sets the position of the scroll box in the horizontal scroll bar of the window.

•	SB_VERT    Sets the position of the scroll box in the vertical scroll bar of the window.

nPos    Specifies the new position of the scroll box. It must be within the scrolling range.

bRedraw    Specifies whether the scroll bar should be repainted to reflect the new scroll-box position. If this parameter is TRUE, the scroll bar is repainted; if FALSE, the scroll bar is not repainted.

Remarks

Sets the current position of a scroll box and, if requested, redraws the scroll bar to reflect the new position of the scroll box.

Setting bRedraw to FALSE is useful whenever the scroll bar will be redrawn by a subsequent call to another function.

Return Value

The previous position of the scroll box.

See Also

::SetScrollPos, »CWnd::GetScrollPos«, »CScrollBar::SetScrollPos«


  CWnd::SetScrollRange

void SetScrollRange( int nBar, int nMinPos, int nMaxPos,
BOOL bRedraw = TRUE );

nBar    Specifies the scroll bar to be set. This parameter can be one of the following values:

•	SB_HORZ    Sets the range of the horizontal scroll bar of the window.

•	SB_VERT    Sets the range of the vertical scroll bar of the window.

nMinPos    Specifies the minimum scrolling position.

nMaxPos    Specifies the maximum scrolling position.

bRedraw    Specifies whether the scroll bar should be redrawn to reflect the change. If bRedraw is TRUE, the scroll bar is redrawn; if FALSE, the scroll bar is not redrawn.

Remarks

Sets minimum and maximum position values for the given scroll bar. It can also be used to hide or show standard scroll bars.

An application should not call this function to hide a scroll bar while processing a scroll-bar notification message.

If the call to SetScrollRange immediately follows a call to the »SetScrollPos« member function, the bRedraw parameter in the SetScrollPos member function should be 0 to prevent the scroll bar from being drawn twice.

The default range for a standard scroll bar is 0 through 100. The default range for a scroll bar control is empty (both the nMinPos and nMaxPos values are 0). The difference between the values specified by nMinPos and nMaxPos must not be greater than INT_MAX.

See Also

»CWnd::SetScrollPos«, ::SetScrollRange, »CWnd::GetScrollRange«


  CWnd::SetTimer

UINT SetTimer( UINT nIDEvent, UINT nElapse, void
(CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );

nIDEvent    Specifies a nonzero timer identifier.

nElapse    Specifies the time-out value, in milliseconds.

lpfnTimer    Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application's message queue and handled by the CWnd object.

Remarks

Installs a system timer. A time-out value is specified, and every time a time-out occurs, the system posts a WM_TIMERmessage to the installing application's message queue or passes the message to an application-defined TimerProc callback function.

The lpfnTimer callback function need not be named TimerProc, but it must be defined as follows and return 0.

void CALLBACK EXPORT TimerProc(
HWND hWnd,	//handle of CWnd that called SetTimer
UINT nMsg,	//WM_TIMER
UINT nIDEvent	//timer identification
DWORD dwTime	//system time
);

Timers are a limited global resource; therefore it is important that an application check the value returned by the SetTimer member function to verify that a timer is actually available.

Return Value

The timer identifier of the new timer if the function is successful. An application passes this value to the KillTimer member function to kill the timer. Nonzero if successful; otherwise 0.

See Also

WM_TIMER, »CWnd::KillTimer«, ::SetTimer, »CWnd::FromHandle«


  CWnd::SetWindowPlacement

Windows 3.1 Only

BOOL SetWindowPlacement( const WINDOWPLACEMENT FAR*
lpwndpl ); ♦

lpwndpl    Points to a »WINDOWPLACEMENT« structure that specifies the new show state and positions. For a full description of this structure, see the Microsoft Windows Programmer's Reference, Volume 3.

Remarks

Sets the show state and the normal (restored), minimized, and maximized positions for a window.

Return Value

Nonzero if the function is successful; otherwise 0.

WINDOWPLACE-MENT Structure

Windows 3.1 Only

A WINDOWPLACEMENT data structure has this form:

typedef struct tagWINDOWPLACEMENT {     /* wndpl */

    UINT  length;

    UINT  flags;

    UINT  showCmd;

    POINT ptMinPosition;

    POINT ptMaxPosition;

    RECT  rcNormalPosition;

} WINDOWPLACEMENT;

The WINDOWPLACEMENT structure contains information about the placement of a window on the screen. ♦

The WINDOWPLACEMENT structure has the following members:

length    Specifies the length, in bytes, of the structure.

flags    Specifies flags that control the position of the minimized window and the method by which the window is restored. This member can be one or both of the following flags:

•	WPF_SETMINPOSITION    Specifies that the x- and y-positions of the minimized window may be specified. This flag must be specified if the coordinates are set in the ptMinPosition member.

•	WPF_RESTORETOMAXIMIZED    Specifies that the restored window will be maximized, regardless of whether it was maximized before it was minimized. This setting is valid only the next time the window is restored. It does not change the default restoration behavior. This flag is valid only when the SW_SHOWMINIMIZED value is specified for the showCmd member.

showCmd    Specifies the current show state of the window. This member may be one of the following values:

•	SW_HIDE    Hides the window and passes activation to another window.

•	SW_MINIMIZE    Minimizes the specified window and activates the top-level window in the system's list.

•	SW_RESTORE    Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position (same as SW_SHOWNORMAL).

•	SW_SHOW    Activates a window and displays it in its current size and position.

•	SW_SHOWMAXIMIZED    Activates a window and displays it as a maximized window.

•	SW_SHOWMINIMIZED    Activates a window and displays it as an icon.

•	SW_SHOWMINNOACTIVE    Displays a window as an icon. The window that is currently active remains active.

•	SW_SHOWNA    Displays a window in its current state. The window that is currently active remains active.

•	SW_SHOWNOACTIVATE    Displays a window in its most recent size and position. The window that is currently active remains active.

•	SW_SHOWNORMAL    Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position (same as SW_RESTORE).

ptMinPosition    Specifies the position of the window's top-left corner when the window is minimized.

ptMaxPosition    Specifies the position of the window's top-left corner when the window is maximized.

rcNormalPosition    Specifies the window's coordinates when the window is in the normal (restored) position.

See Also

»CWnd::GetWindowPlacement«, ::SetWindowPlacement


  CWnd::SetWindowPos

BOOL SetWindowPos( const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags );

pWndInsertAfter    Identifies the CWnd object that will precede this CWnd object in the Z-order. This parameter can be a pointer to a CWnd or one of the following values:

•	wndBottom    Places the window at the bottom of the Z-order. If this CWnd is a topmost window, the window loses its topmost status; the system places the window at the bottom of all other windows.

•	wndTop    Places the window at the top of the Z-order.

Windows 3.1 Only

•	wndTopMost    Places the window above all nontopmost windows. The window maintains its topmost position even when it is deactivated.

•	wndNoTopMost    Repositions the window to the top of all nontopmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a nontopmost window. »

See the following "Remarks" section for rules about how this parameter is used.

x    Specifies the new position of the left side of the window.

y    Specifies the new position of the top of the window.

cx    Specifies the new width of the window.

cy    Specifies the new height of the window.

nFlags    Specifies sizing and positioning options. This parameter can be a combination of the following:

•	SWP_DRAWFRAME    Draws a frame (defined when the window was created) around the window.

•	SWP_HIDEWINDOW    Hides the window.

•	SWP_NOACTIVATE    Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or the nontopmost group (depending on the setting of the pWndInsertAfter parameter).

•	SWP_NOMOVE    Retains current position (ignores the x and y parameters).

•	SWP_NOREDRAW    Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title and scroll bars), and any part of the parent window uncovered as a result of the moved window. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that must be redrawn.

•	SWP_NOSIZE    Retains current size (ignores the cx and cy parameters).

•	SWP_NOZORDER    Retains current ordering (ignores pWndInsertAfter).

•	SWP_SHOWWINDOW    Displays the window.

Remarks

Call this member function to change the size, position, and Z-order of child, pop-up, and top-level windows.

Windows are ordered on the screen according to their Z-order; the window at the top of the Z-order appears on top of all other windows in the order.

All coordinates for child windows are client coordinates (relative to the upper-left corner of the parent window's client area).

A window can be moved to the top of the Z-order either by setting the pWndInsertAfter parameter to &wndTopMost and ensuring that the SWP_NOZORDER flag is not set or by setting a window's Z-order so that it is above any existing topmost windows. When a nontopmost window is made topmost, its owned windows are also made topmost. Its owners are not changed.

A topmost window is no longer topmost if it is repositioned to the bottom (&wndBottom) of the Z-order or after any nontopmost window. When a topmost window is made nontopmost, all of its owners and its owned windows are also made nontopmost windows.

If neither SWP_NOACTIVATE nor SWP_NOZORDER is specified (that is, when the application requests that a window be simultaneously activated and placed in the specified Z-order), the value specified in pWndInsertAfter is used only in the following circumstances:

•	Neither &wndTopMost nor &wndNoTopMost is specified in the pWndInsertAfter parameter.

•	This window is not the active window.

An application cannot activate an inactive window without also bringing it to the top of the Z-order. Applications can change the Z-order of an activated window without restrictions.

A nontopmost window may own a topmost window, but not vice versa. Any window (for example, a dialog box) owned by a topmost window is itself made a topmost window to ensure that all owned windows stay above their owner.

Windows 3.1 Only

With Windows versions 3.1 and later, windows can be moved to the top of the Z-order and locked there by setting their WS_EX_TOPMOST styles. Such a topmost window maintains its topmost position even when deactivated. For example, selecting the WinHelp Always On Top command makes the Help window topmost, and it then remains visible when you return to your application.

To create a topmost window, call SetWindowPos with the pWndInsertAfter parameter equal to &wndTopMost, or set the WS_EX_TOPMOST style when you create the window.

If the Z-order contains any windows with the WS_EX_TOPMOST style, a window moved with the &wndTopMost value is placed at the top of all nontopmost windows, but below any topmost windows. When an application activates an inactive window without the WS_EX_TOPMOST bit, the window is moved above all nontopmost windows but below any topmost windows.

If SetWindowPos is called when the pWndInsertAfter parameter is &wndBottom and CWnd is a topmost window, the window loses its topmost status (WS_EX_TOPMOST is cleared), and the system places the window at the bottom of the Z-order. »

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

::DeferWindowPos, ::SetWindowPos


  CWnd::SetWindowText

void SetWindowText( LPCSTR lpszString );

lpszString    Points to a CString object or null-terminated string to be used as the new title or control text.

Remarks

Sets the window's title to the specified text. If the window is a control, the text within the control is set.

This function causes a WM_SETTEXTmessage to be sent to this window.

See Also

»CWnd::GetWindowText«, ::SetWindowText


  CWnd::ShowCaret

void ShowCaret();

Remarks

Shows the caret on the screen at the caret's current position. Once shown, the caret begins flashing automatically.

The ShowCaret member function shows the caret only if it has a current shape and has not been hidden two or more times consecutively. If the caret is not owned by this window, the caret is not shown.

Hiding the caret is cumulative. If the »HideCaret« member function has been called five times consecutively, ShowCaret must be called five times to show the caret.

The caret is a shared resource. The window should show the caret only when it has the input focus or is active.

See Also

»CWnd::HideCaret«, ::ShowCaret


  CWnd::ShowOwnedPopups

void ShowOwnedPopups( BOOL bShow = TRUE );

bShow    Specifies whether pop-up windows are to be shown or hidden. If this parameter is TRUE, all hidden pop-up windows are shown. If this parameter is FALSE, all visible pop-up windows are hidden.

Remarks

Shows or hides all pop-up windows owned by this window.

See Also

::ShowOwnedPopups


  CWnd::ShowScrollBar

void ShowScrollBar( UINT nBar, BOOL bShow = TRUE );

nBar    Specifies whether the scroll bar is a control or part of a window's nonclient area. If it is part of the nonclient area, nBar also indicates whether the scroll bar is positioned horizontally, vertically, or both. It must be one of the following:

•	SB_BOTH    Specifies the  horizontal and vertical scroll bars of the window.

•	SB_HORZ    Specifies that the window is a horizontal scroll bar.

•	SB_VERT    Specifies that the window is a vertical scroll bar.

bShow    Specifies whether Windows shows or hides the scroll bar. If this parameter is TRUE, the scroll bar is shown; otherwise the scroll bar is hidden.

Remarks

Shows or hides a scroll bar.

An application should not call ShowScrollBar to hide a scroll bar while processing a scroll-bar notification message.

See Also

::ShowScrollBar, »CScrollBar::ShowScrollBar«


  CWnd::ShowWindow

BOOL ShowWindow( int nCmdShow );

nCmdShow    Specifies how the CWnd is to be shown. It must be one of the following values:

•	SW_HIDE    Hides this window and passes activation to another window.

•	SW_MINIMIZE    Minimizes the window and activates the top-level window in the system's list.

•	SW_RESTORE    Activates and displays the window. If the window is minimized or maximized, Windows restores it to its original size and position.

•	SW_SHOW    Activates the window and displays it in its current size and position.

•	SW_SHOWMAXIMIZED    Activates the window and displays it as a maximized window.

•	SW_SHOWMINIMIZED    Activates the window and displays it as an icon.

•	SW_SHOWMINNOACTIVE    Displays the window as an icon. The window that is currently active remains active.

•	SW_SHOWNA    Displays the window in its current state. The window that is currently active remains active.

•	SW_SHOWNOACTIVATE    Displays the window in its most recent size and position. The window that is currently active remains active.

•	SW_SHOWNORMAL    Activates and displays the window. If the window  is minimized or maximized, Windows restores it to its original size and position.

Remarks

Sets the visibility state of the window.

ShowWindow must be called only once per application for the main window with CWinApp::m_nCmdShow. Subsequent calls to ShowWindow must use one of the values listed above instead of the one specified by m_nCmdShow.

Return Value

Nonzero if the window was previously visible; 0 if the CWnd was previously hidden.

See Also

::ShowWindow, »CWnd::OnShowWindow«, »CWnd::ShowOwnedPopups«,


  CWnd::SubclassDlgItem

BOOL SubclassDlgItem( UINT nID, CWnd* pParent );

nID    The control's ID.

pParent    The control's parent (usually a dialog box).

Remarks

Call this member function to "dynamically subclass" a control created from a dialog template and attach it to this CWnd object. When a control is dynamically subclassed, windows messages will route through the CWnd's message map and call message handlers in the CWnd's class first. Messages that are passed to the base class will be passed to the default message handler in the control.

This member function attaches the Windows control to a CWnd object and replaces the control's WndProc and AfxWndProc functions. The function stores the old WndProc in the location returned by the GetSuperWndProcAddr member function. You must override the GetSuperWndProcAddr member function for every unique window class to provide a place to store the old WndProc.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::GetSuperWndProcAddr«, »CWnd::DefWindowProc«,  »CWnd::SubclassWindow«, »CWnd::Attach«


  CWnd::SubclassWindow

BOOL SubclassWindow( HWND hWnd );

hWnd    A handle to the window.

Remarks

Call this member function to "dynamically subclass" a window and attach it to this CWnd object. When a window is dynamically subclassed, windows messages will route through the CWnd's message map and call message handlers in the CWnd's class first. Messages that are passed to the base class will be passed to the default message handler in the window.

This member function attaches the Windows control to a CWnd object and replaces the window's WndProc and AfxWndProc functions. The function stores the old WndProc in the location returned by the GetSuperWndProcAddr member function. You must override the GetSuperWndProcAddr member function for every unique window class to provide a place to store the old WndProc.

Return Value

Nonzero if the function is successful; otherwise 0.

See Also

»CWnd::GetSuperWndProcAddr«, »CWnd::DefWindowProc«,  »CWnd::SubclassDlgItem«, »CWnd::Attach«


  CWnd::UpdateData

BOOL UpdateData( BOOL bSaveAndValidate = TRUE );

bSaveAndValidate    Flag that indicates whether dialog box is being initialized (FALSE) or data is being retrieved (TRUE).

Remarks

Call this member function to initialize data in a dialog box, or to retrieve and validate dialog data.

The framework automatically calls UpdateData with bSaveAndValidate set to FALSE when a modal dialog box is created in the default implementation of »CDialog::OnInitDialog«. The call occurs before the dialog box is visible. The default implementation of »CDialog::OnOK« calls this member function with bSaveAndValidate set to TRUE to retrieve the data, and if successful, will close the dialog box. (If the Cancel button is clicked in the dialog box, the dialog box is closed without the data being retrieved.)

Return Value

Nonzero if the operation is successful; otherwise 0. If bSaveAndValidate is TRUE, then a return value of nonzero means that the data is successfully validated.

See Also

»CWnd::DoDataExchange«


  CWnd::UpdateDialogControls

void UpdateDialogControls( CCmdTarget* pTarget, BOOL bDisableIfNoHndler );

pTarget   Points to the main frame window of the application, and used for routing update messages.

bDisableIfNoHndler    Flag that indicates whether a control that has no update handler should be automatically displayed as disabled.

Remarks

Call this member function to update the state of dialog buttons and other controls in a dialog box or window that uses the ON_UPDATE_COMMAND_UI callback mechanism.

If a child control does not have a handler and bDisableIfNoHndler is TRUE, then the child control will be disabled.

The framework calls this member function for controls in dialog bars or toolbars as part of the application's idle processing.

See Also

»CFrameWnd::m_bAutoMenuEnable«


  CWnd::UpdateWindow

void UpdateWindow();

Remarks

Updates the client area by sending a WM_PAINT message if the update region is not empty. The UpdateWindow member function sends a WM_PAINTmessage directly, bypassing the application queue. If the update region is empty, WM_PAINT is not sent.

See Also

::UpdateWindow, »CWnd::RedrawWindow«


  CWnd::ValidateRect

void ValidateRect( LPCRECT lpRect );

lpRect    Points to a CRect object or »RECT« structure that contains client coordinates of the rectangle to be removed from the update region. If lpRect is NULL, the entire window is validated.

Remarks

Validates the client area within the given rectangle by removing the rectangle from the update region of the window. The »BeginPaint« member function automatically validates the entire client area. Neither the ValidateRect nor »ValidateRgn« member function should be called if a portion of the update region needs to be validated before WM_PAINT is next generated.

Windows continues to generate WM_PAINT messages until the current update region is validated.

See Also

»CWnd::BeginPaint«, ::ValidateRect, »CWnd::ValidateRgn«


  CWnd::ValidateRgn

void ValidateRgn( CRgn* pRgn );

pRgn    Identifies a region that defines the area to be removed from the update region. If this parameter is NULL, the entire client area is removed.

Remarks

Validates the client area within the given region by removing the region from the current update region of the window. The given region must have been created previously by a region function. The region coordinates are assumed to be client coordinates.

The BeginPaint member function automatically validates the entire client area. Neither the ValidateRect nor the ValidateRgn member function should be called if a portion of the update region must be validated before the next WM_PAINT message is generated.

See Also

::ValidateRgn, CWnd::ValidateRect


  CWnd::WindowFromPoint

static CWnd* PASCAL WindowFromPoint( POINT point );

point    Specifies a CPoint object or »POINT« data structure that defines the point to be checked.

Remarks

Retrieves the window that contains the specified point; point must specify the screen coordinates of a point on the screen.

WindowFromPoint does not retrieve a hidden, disabled, or transparent window, even if the point is within the window. An application should use the ChildWindowFromPoint member function for a nonrestrictive search.

Return Value

A pointer to the window object in which the point lies. It is NULL if no window exists at the given point. The returned pointer may be temporary and should not be stored for later use.

See Also

::WindowFromPoint, »CWnd::ChildWindowFromPoint«


  CWnd::WindowProc

message    Specifies the Windows message to be processed.

wParam    Provides additional information used in processing the message. The parameter value depends on the message.

lParam    Provides additional information used in processing the message. The parameter value depends on the message.

Remarks

Provides a Windows procedure (WindowProc) for a CWnd object. It dispatches messages through the window's message map.

Return Value

The return value depends on the message.


CWnd Data Members
  Data Members

To get information on a particular data member, double-click it in the Contents window.


  CWnd::m_hWnd

Remarks

The handle of the Windows window attached to this CWnd. The m_hWnd data member is a public variable of type HWND.

See Also

»CWnd::Attach«, »CWnd::Detach«, »CWnd::FromHandle«


CWordArray
  class CWordArray : public CObject

The CWordArray class supports arrays of 16-bit words.

The member functions of CWordArray are similar to the member functions of class »CObArray«. Because of this similarity, you can use the CObArray reference documentation for member function specifics. Wherever you see a CObject pointer as a function parameter or return value, substitute a WORD.

CObject* CObArray::GetAt( int <nIndex> ) const;

for example, translates to

WORD CWordArray::GetAt( int <nIndex> ) const;

CWordArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of words is stored to an archive, either with an overloaded insertion operator or with the Serialize member function, each element is, in turn, serialized.

If you need a dump of individual elements in the array, you must set the depth of the dump context to 1 or greater.

#include <afxcoll.h>


CWordArray Class Members
  Class Members

Construction/Destruction — Public Members

»CWordArray«	Constructs an empty array for words.
»~CWordArray«	Destroys a CWordArray object.
Bounds — Public Members

»GetSize«	Gets number of elements in this array.
»GetUpperBound«	Returns the largest valid index.
»SetSize«	Sets the number of elements to be contained in this array.
Operations — Public Members

»FreeExtra«	Frees all unused memory above the current upper bound.
»RemoveAll«	Removes all the elements from this array.
Element Access — Public Members

»GetAt«	Returns the value at a given index.
»SetAt«	Sets the value for a given index; array is not allowed to grow.
»ElementAt«	Returns a temporary reference to the element pointer within the array.
Growing the Array — Public Members

»SetAtGrow«	Sets the value for a given index; grows the array if necessary.
»Add«	Adds an element to the end of the array; grows the array if necessary.
Insertion/Removal — Public Members

»InsertAt«	Inserts an element (or all the elements in another array) at a specified index.
»RemoveAt«	Removes an element at a specific index.
Operators — Public Members

»operator []«	Sets or gets the element at the specified index.


  Macros and Globals

The Microsoft Foundation Class Library can be divided into two major sections: 1) the Foundation classes and 2) macros and globals. If a function or variable is not a member of a class, it is a global function or variable.

The Microsoft Foundation macros and globals, which are designed to assist both MS-DOS and Windows programmers, offer functionality in the following categories:

•	Data types

•	Run-time object-model services

•	Diagnostic services

•	Exception processing

•	CString formatting and message-box display

•	Message maps

•	Application information and management

•	Support for Object Linking and Embedding (OLE)

•	Standard commands and window IDs

The first part of this section briefly discusses each of the above categories and lists each global and macro in the category, along with a brief description of what it does. Following this is a complete alphabetical listing of all the global functions, global variables, and macros in the Microsoft Foundation classes.

The main supporting reference for the "Macros and Globals" section is the Class Library User's Guide. This is usually the first place you will look to find more information on macros and globals. When necessary, the appropriate chapter of the Class Library User's Guide is mentioned with the function or macro description.

Note  All global functions start with the prefix "Afx." All global variables start with the prefix "afx." Macros do not start with any particular prefix, but they are all uppercase.


  Data Types

This section lists the data types most commonly used in the Microsoft Foundation Class Library. Most of these data types are exactly the same as those in the Windows Software Development Kit (SDK) version 3.1, while others are unique to the Microsoft Foundation Class Library.

Commonly used Windows SDK and Microsoft Foundation class data types are as follows:

•	BOOL    A boolean value.

•	BYTE    An 8-bit unsigned integer.

•	COLORREF    A 32-bit value used as a color value.

•	DWORD    A 32-bit unsigned integer or the address of a segment and its associated offset.

•	LONG    A 32-bit signed integer.

•	LPARAM    A 32-bit value passed as a parameter to a window procedure or callback function.

•	LPCSTR    A 32-bit pointer to a constant character string.

•	LPSTR    A 32-bit pointer to a character string.

•	LPVOID    A 32-bit pointer to an unspecified type.

•	LRESULT    A 32-bit value returned from a window procedure or callback function.

•	UINT    A 16-bit unsigned integer on Windows versions 3.0 and 3.1; a 32-bit unsigned integer on Win32.

•	WNDPROC    A 32-bit pointer to a window procedure.

•	WORD    A 16-bit unsigned integer.

•	WPARAM    A value passed as a parameter to a window procedure or callback function; 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32.

Data types unique to the Microsoft Foundation Class Library include:

•	POSITION    A value used to denote the position of an element in a collection; Used by Microsoft Foundation collection classes.

•	LPCRECT    A 32-bit pointer to a constant (nonmodifiable) RECT structure.

For a list of the less common data types, see the Windows SDK reference.


  Run-Time Object Model Services

The classes CObject and CRuntimeClass encapsulate several object services, including access to run-time class information, serialization, and dynamic object creation. All classes derived from CObject inherit this functionality.

Access to run-time class information enables you to determine information about an object's class at run time. The ability to determine the class of an object at run time is useful when extra type-checking of function arguments is needed and when you must write special-purpose code based on the class of an object. Run-time class information is not supported directly by the C++ language.

Serialization is the process of reading or writing an object's contents to and from a file. You can use serialization to store an object's contents even after the application exits. The object can then be read from the file when the application is restarted. Such data objects are said to be "persistent."

Dynamic object creation enables you to create an object of a specified class at run time. For example, document, view, and frame objects must support dynamic creation because the framework needs to create them dynamically.

The following table lists the Microsoft Foundation Class Library macros that support run-time class information, serialization, and dynamic creation. For more information on these run-time object services, see Chapter 12 of the Class Library User's Guide. For more information on serialization, see Chapter 14 of the Class Library User's Guide.

Run-Time Object Model Services

»DECLARE_DYNAMIC«	Enables access to run-time class information (must be used in the class declaration).
»DECLARE_DYNCREATE«	Enables dynamic creation and access to run-time class information (must be used in the class declaration).
»DECLARE_SERIAL«	Enables serialization and access to run-time class information (must be used in the class declaration).
»IMPLEMENT_DYNAMIC«	Enables access to run-time class information (must be used in the class implementation).
»IMPLEMENT_DYNCREATE«	Enables dynamic creation and access to run-time information (must be used in the class implementation).
»IMPLEMENT_SERIAL«	Permits serialization and access to run-time class information (must be used in the class implementation).
»RUNTIME_CLASS«	Returns the CRuntimeClass structure that corresponds to the named class.


  Diagnostic Services

The Microsoft Foundation Class Library provides a range of diagnostic services that make debugging your programs easier. These diagnostic services include macros and global functions that allow you to track your program's memory allocations, dump the contents of objects during run time, and print debugging messages during runtime. The macros and global functions for diagnostic services are grouped into the following categories:

•	»General diagnostic macros«

•	»General diagnostic functions and variables«

•	»Object diagnostic functions«

These macros and functions are available for all classes derived from CObject in the Debug and Release versions of the Microsoft Foundation Class Library. However, all except DEBUG_NEW and VERIFY do nothing in the Release version.

In the Debug library, all allocated memory blocks are bracketed with a series of "guard bytes." If these bytes are disturbed by an errant memory write, then the diagnostic routines can report a problem. If you include the line

#define new DEBUG_NEW

in your implementation file, all calls to new will store the filename and line number where the memory allocation took place. The function »CMemoryState::DumpAllObjectsSince« will display this extra information, allowing you to identify memory leaks. Refer also to the class »CDumpContext« for additional information on diagnostic output.

General Diagnostic Macros

»ASSERT«	Prints a message and then aborts the program if the specified expression evaluates to FALSE in the Debug version of the library.
»ASSERT_VALID«	Tests the internal validity of an object by calling its AssertValid member function; typically overridden from CObject.
»DEBUG_NEW«	Provides a filename and line number for all object allocations in Debug mode to help find memory leaks.
»TRACE«	Provides printf-like capability in the Debug version of the library.
»TRACE0«	Similar to TRACE but takes a format string with no arguments.
»TRACE1«	Similar to TRACE but takes a format string with a single argument.
»TRACE2«	Similar to TRACE but takes a format string with two arguments.
»TRACE3«	Similar to TRACE but takes a format string with three arguments.
»VERIFY«	Similar to ASSERT but evaluates the expression in the Release version of the library as well as in the Debug version.
General Diagnostic Functions and Variables

»afxDump«	Global variable that sends »CDumpContext« information to the debugger output window or to the debug terminal.
»afxMemDF«	Global variable that controls the behavior of the debugging memory allocator.
»afxTraceEnabled«	Global variable used to enable or disable output from the TRACE macro
»afxTraceFlags«	Global variable used to turn on the built-in reporting features of the Microsoft Foundation Class Library.
»AfxCheckMemory«	Checks the integrity of all currently allocated memory.
»AfxDump«	Call this function while in the debugger to dump the state of an object while debugging.
»AfxEnableMemoryTracking«	Turns memory tracking on and off.
»AfxIsMemoryBlock«	Verifies that a memory block has been properly allocated.
»AfxIsValidAddress«	Verifies that a memory address range is within the program's bounds.
»AfxIsValidString«	Determines whether a pointer to a string is valid.
»AfxSetAllocHook«	Enables the calling of a function on each memory allocation.
Object Diagnostic Functions

»AfxDoForAllClasses«	Performs a specified function on all CObject-derived classes that support run-time type checking.
»AfxDoForAllObjects«	Performs a specified function on all CObject-derived objects that were allocated with new.


  Exception Processing

When a program executes, a number of abnormal conditions and errors called "exceptions" can occur. These may include running out of memory, resource allocation errors, and failure to find files.

The Microsoft Foundation Class Library uses an exception-handling scheme that is modeled closely after the one proposed by the ANSI standards committee for C++. This involves setting up an exception handler before calling a function that may encounter an abnormal situation. If the function encounters an abnormal condition, it throws an exception and control is passed to the exception handler.

Several macros included with the Microsoft Foundation Class Library set up exception handlers. A number of other global functions help to throw specialized exceptions and terminate programs, if necessary. These macros and global functions fall into the following categories:

•	Exception macros, which structure your exception handler

•	Exception-throwing functions, which generate exceptions of specific types

•	Termination functions, which cause program termination

For examples and more details, see Chapter 16, "Exceptions," in the Class Library User's Guide. You can also refer to class »CException«.

See Also

»CException«

Exception Macros

»TRY«	Designates a block of code for exception processing.
»CATCH«	Designates a block of code for catching an exception from the preceding TRY block.
»AND_CATCH«	Designates a block of code for catching additional exception types from the preceding TRY block.
»END_CATCH«	Ends the last CATCH or AND_CATCH code block.
»THROW«	Throws a specified exception.
»THROW_LAST«	Throws the currently handled exception to the next outer handler.
Exception-Throwing Functions

»AfxThrowArchiveException«	Throws an archive exception.
»AfxThrowFileException«	Throws a file exception.
»AfxThrowMemoryException«	Throws a memory exception.
»AfxThrowNotSupportedException«	Throws a not-supported exception.
»AfxThrowOleException«	Throws an OLE exception.
»AfxThrowResourceException«	Throws a Windows resource-not-found exception.
»AfxThrowUserException«	Throws an exception in a user-initiated program action.
Termination Functions

»AfxAbort«	Called to terminate an application when a fatal error occurs.


CString Formatting and Message Box
  CString Formatting and Message-Box Display

A number of functions are provided to format and parse CString objects. You can use these functions in any situation where you have to manipulate CString objects, but they are particularly useful for formatting strings that will appear in message-box text.

This group of functions also includes a global routine for displaying a message box.

Refer to class »CString« for more information about CString objects.

See Also

»CString«

CString Functions

»AfxFormatString1«	Substitutes a given string for the format characters "%1" in a string contained in the string table.
»AfxFormatString2«	Substitutes two strings for the format characters "%1" and "%2" in a string contained in the string table.
»AfxMessageBox«	Displays a message box.


  Message Maps

Since Windows is a message-oriented operating system, a large portion of programming for the Windows environment involves message handling. Each time an event such as a keystroke or mouse click occurs, a message is sent to the application, which must then handle the event.

The Microsoft Foundation Class Library offers a programming model optimized for message-based programming. In this model, "message maps" are used to designate which functions handle which messages for a particular class. Message maps contain one or more macros that specify which messages are handled by which functions. For example, a message-map containing an ON_COMMAND macro might look something like the following:

BEGIN_MESSAGE_MAP( CMyDoc, CDocument )
    //{{AFX_MSG_MAP( CMyDoc )
    ON_COMMAND( ID_MYCMD, OnMyCommand )
    // ... More entries to handle additional commands
    //}}AFX_MSG_MAP
END_MESSAGE_MAP( )

The ON_COMMAND macro is used to handle command messages generated by menus, buttons, and accelerator keys. Macros are available to map the following:

Windows Messages

•	Control notifications

•	User-defined messages

Command Messages

•	Registered user-defined messages

•	User-interface update messages

Although message-map macros are important, you generally won't have to use them directly. This is because ClassWizard automatically creates message-map entries in your source files when you use it to associate message-handling functions with messages. Any time you want to edit or add a message-map entry, you can use ClassWizard.

However, since message maps are such an important part of the Microsoft Foundation Class Library, you should understand what they do, and documentation is therefore provided for them.

To support message maps, the Microsoft Foundation Class Library provides the following macros:

Message-Map Declaration and Demarcation

»DECLARE_MESSAGE_MAP«	Declares that a message map will be used in a class to map messages to functions (must be used in the class declaration).
»BEGIN_MESSAGE_MAP«	Begins the definition of a message map (must be used in the class implementation).
»END_MESSAGE_MAP«	Ends the definition of a message map (must be used in the class implementation).
Message-Mapping Macros

»ON_COMMAND«	Indicates which function will handle a specified command message.
»ON_CONTROL«	Indicates which function will handle a specified control-notification message.
»ON_MESSAGE«	Indicates which function will handle a user-defined message.
»ON_REGISTERED_MESSAGE«	Indicates which function will handle a registered user-defined message.
»ON_UPDATE_COMMAND_UI«	Indicates which function will handle a specified user-interface update command message.
For more information on message maps and the above message-map macros, see Chapter 6 of the Class Library User's Guide. For more information on how to use ClassWizard, see Chapter 9 of the App Studio User's Guide.


Application Management
  Application Information and Management

When you write an application, you create a single »CWinApp«-derived object. At times, you may wish to get information about this object outside of the CWinApp-derived object.

See Also

»CWinApp«

The Microsoft Foundation Class Library provides the following global functions to help you accomplish these tasks:

Application Information and Management

»AfxGetApp«	Returns a pointer to the application's single CWinApp object.
»AfxGetAppName«	Returns a string containing the application's name.
»AfxGetInstanceHandle«	Returns an HINSTANCE representing this instance of the application.
»AfxGetResourceHandle«	Returns an HINSTANCE where the application loads its default resources. Use this to access the application's resources directly.
»AfxRegisterWndClass«	Registers a Windows window class to supplement those registered automatically by the library.
»AfxSetResourceHandle«	Sets the HINSTANCE handle where the default resources of the application are loaded.


  OLE Support

A number of functions are provided to help you write programs that use the Windows Object Linking and Embedding (OLE) mechanism. You can use these functions to provide the standard OLE user interface for client applications as well as a helper for automatic server registration.

In addition to these global functions, the Microsoft Foundation Class Library contains several classes that help you implement OLE functionality in your program. See Chapter 18 of the Class Library User's Guide and Techical Note 8 (which can be found in MSVCNT\HELP\MFCNOTES.HLP) for more information on using the OLE classes.

To use these macros and global functions, add the following directive at the top of your program, or in your STDAFX.H header file:

#include <afxole.h>

See Also

»CWinApp«

OLE Client Functions

»AfxOleInsertDialog«	Allows the user to choose an item type from a list of registered server applications.
»AfxOleLinksDialog«	Allows the user to update the client's OLE links.
»AfxOleSetEditMenu«	Implements the user interface for the typename Object command, allowing users to invoke verbs on OLE items.
OLE Server Functions

»AfxOleRegisterServerName«	Registers an application as an OLE server.


Standard Command and Window IDs
  Standard Commands and Window IDs

The Microsoft Foundation Class Library defines a number of standard command and window IDs in AFXRES.H. These IDs are most commonly used within App Studio and ClassWizard to map messages to your handler functions. All standard commands have an ID_ prefix. For example, when you use App Studio's menu editor, you normally bind the File Open menu item to the standard ID_FILE_OPEN command ID.

For most standard commands, application code does not need to refer to the command ID because the framework itself handles the commands through message-maps in its primary framework classes (CWinApp, CView, CDocument, and so forth).

In addition to standard command IDs, a number of other standard IDs are defined which have a prefix of AFX_ID. These IDs include standard window IDs (prefix AFX_IDW_), string IDs (prefix AFX_IDS_), and several other types.

IDs that begin with the AFX_ID prefix are rarely used by programmers, but you might, however, need to refer to these IDs when overriding framework functions which themselves refer to the AFX_IDs.

IDs are not individually documented in this reference. However, you can find more information on them in Technical Notes 20, 21, and 22, which can be found in MSVCNT\HELP\MFCNOTES.HLP

Note  The header file AFXRES.H is indirectly included in AFXWIN.H. You must explicitly include the statement

#include afxres.h

in your application's resource script (.RC) file.


Global Functions and Variables

To get information on a particular macro, global, or variable function, double-click it in the Contents window.


  AfxAbort

void AfxAbort();

Remarks

The default termination function supplied by the Microsoft Foundation Class Library. AfxAbort is called internally by Microsoft Foundation Class Library member functions when there is a fatal error, such as an uncaught exception that cannot be handled. You can call AfxAbort in the rare case when you encounter a catastrophic error from which you cannot recover.


  AfxCheckMemory

BOOL AfxCheckMemory();

Remarks

This function validates the free memory pool and prints error messages as required. If the function detects no memory corruption, it prints nothing.

All memory blocks currently allocated on the heap are checked, including those allocated by new but not those allocated by direct calls to underlying memory allocators such as the malloc function or the GlobalAlloc Windows function. If any block is found to be corrupted, a message is printed to the debugger output.

If you include the line

#define new DEBUG_NEW

in a program module, then subsequent calls to AfxCheckMemory show the filename and line number where the memory was allocated.

Note  If your module contains one or more implementations of serializable classes, then you must put the #define line after the last IMPLEMENT_SERIAL macro invocation.

Return Value

Nonzero if no memory errors; otherwise 0.

 Example

// example for AfxCheckMemory

CAge* pcage = new CAge( 21 ); // CAge is derived from CObject.
Age* page = new Age( 22 );	    // Age is NOT derived from CObject.
*(((char*) pcage) - 1) = 99;  // Corrupt preceding guard byte
*(((char*) page) - 1) = 99;   // Corrupt preceding guard byte
AfxCheckMemory();

The results from the program are as follows:

memory check error at $0067495F = $63, should be $FD
DAMAGE: before Non-Object block at $00674960
Non-Object allocated at file test02.cxx(48)
Non-Object located at $00674960 is 2 bytes long
memory check error at $00674905 = $63, should be $FD
DAMAGE: before Object block at $00674906
Object allocated at file test02.cxx(47)
Object located at $00674906 is 6 bytes long

Note  This function only works in the Debug version of the Microsoft Foundation Class Library.


  AfxDoForAllClasses

void AfxDoForAllClasses( void (*pfn)(const CRuntimeClass* pClass, void* pContext), void* pContext );

pfn    Points to an iteration function to be called for each class. The function arguments are a pointer to a CRuntimeClass object and a void pointer to extra data that the caller supplies to the function.

pContext    Points to optional data that the caller can supply to the iteration function. This pointer can be NULL.

Remarks

Calls the specified iteration function for all CObject-derived classes in the application's memory space that support run-time type checking using the macros DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL. The pointer that is passed to AfxDoForAllClasses in pContext is passed to the specified iteration function each time it is called.

Note  This function only works in the Debug version of the Microsoft Foundation Class Library.


  AfxDoForAllObjects

void AfxDoForAllObjects( void (*pfn)(CObject* pObject, void* pContext), void* pContext );

pfn    Points to an iteration function to execute for each object. The function arguments are a pointer to a CObject and a void pointer to extra data that the caller supplies to the function.

pContext    Points to optional data that the caller can supply to the iteration function. This pointer can be NULL.

Remarks

Executes the specified iteration function for all objects derived from CObject that have been allocated with new. Stack, global, or embedded objects are not enumerated. The pointer passed to AfxDoForAllObjects in pContext is passed to the specified iteration function each time it is called.

Note  This function only works in the Debug version of the Foundation library.


  afxDump

CDumpContext afxDump;

Remarks

Use this variable to provide basic object-dumping capability in your application. afxDump is a predefined »CDumpContext« object that allows you to send CDumpContext information to the debugger output window or to a debug terminal. Typically, you supply afxDump as a parameter to CObject::Dump.

In Windows versions 3.0 and 3.1, afxDump output is sent to the debugger, if present. In MS-DOS, afxDump output is sent to stderr.

In Windows NT, afxDump output is sent to the Output-Debug window of Visual Workbench when you debug your application. In Console applications, afxDump output is sent to stderr.

This variable is defined only in the Debug version of the Microsoft Foundation Class Library. For more information on afxDump, see Chapter 15 of the Class Library User's Guide, and Technical Notes 7 and 12, in MFCNOTES.HLP.

Note  This function works only in the Debug version of the Microsoft Foundation Class Library.

See Also

»CObject::Dump«

 Example

// example for afxDump

CPerson myPerson = new CPerson;
// set some fields of the CPerson object...
//..
// now dump the contents
#ifdef _DEBUG

afxDump << "Dumping myPerson:\n";
myPerson->Dump( afxDump );

afxDump << "\n";
#endif


  AfxDump

void AfxDump( const CObject* pOb );

pOb    A pointer to an object of a class derived from CObject.

Remarks

Call this function while in the debugger to dump the state of an object while debugging. AfxDump calls an object's Dump member function and sends the information to the location specified by the afxDump variable. AfxDump is available only in the Debug version of the Microsoft Foundation Class Library.

Your program code should not call AfxDump, but should instead call the Dump member function of the appropriate object.

For example, the following command prints the state of the current object when you enter it at the > prompt in the CodeView command window:

? AfxDump(this)

See Also

»CObject::Dump«, »afxDump«


  AfxEnableMemoryTracking

BOOL AfxEnableMemoryTracking( BOOL bTrack );

bTrack    Setting this value to TRUE turns on memory tracking; FALSE turns it off.

Remarks

Diagnostic memory tracking is normally enabled in the Debug version of the Microsoft Foundation Class Library. Use this function to disable tracking on sections of your code that you know are allocating blocks correctly.

For more information on AfxEnableMemoryTracking, see Chapter 15 of the Class Library User's Guide.

Note  This function only works in the Debug version of the Microsoft Foundation Class Library.

Return Value

The previous setting of the tracking-enable flag.


  AfxFormatString1

void AfxFormatString1( CString& rString, UINT nIDS, LPCSTR lpsz1 );

rString    A reference to a CString object that will contain the resultant string after the substitution is performed.

nIDS    The resource ID of the template string on which the substitution will be performed.

lpsz1    A string that will replace the format characters "%1" in the template string.

Remarks

Loads the specified string resource and substitutes the characters "%1" for the string pointed to by lpsz1. The newly formed string is stored in rString. For example, if the string in the string table is "File %1 not found", and lpsz1 is equal to "C:\MYFILE.TXT", then rString will contain the string "File C:\MYFILE.TXT not found". This function is useful for formatting strings sent to message boxes and other windows.

If the format characters "%1" appear in the string more than once, multiple substitutions will be made.

See Also

»AfxFormatString2«


  AfxFormatString2

void AfxFormatString2( CString& rString, UINT nIDS, LPCSTR lpsz1, LPCSTR lpsz2 );

rString    A reference to the CString that will contain the resultant string after the substitution is performed.

nIDS    The string table ID of the template string on which the substitution will be performed.

lpsz1    A string that will replace the format characters "%1" in the template string.

lpsz2    A string that will replace the format characters "%2" in the template string.

Remarks

Loads the specified string resource and substitutes the characters "%1" and "%2" for the strings pointed to by lpsz1 and lpsz2. The newly formed string is stored in rString. For example, if the string in the string table is "File %1 not found in directory %2", lpsz1 points to "MYFILE.TXT", and lpsz2 points to "C:\MYDIR", then rString will contain the string "File MYFILE.TXT not found in directory C:\MYDIR".

If the format characters "%1" or "%2" appear in the string more than once, multiple substitutions will be made. They do not have to be in numerical order.

See Also

»AfxFormatString1«


   AfxGetApp

CWinApp* AfxGetApp( );

Remarks

The pointer returned by this function can be used to access application information such as the main message-dispatch code or the topmost window.

Return Value

A pointer to the single CWinApp object for the application.


  AfxGetAppName

const char* AfxGetAppName( );

Remarks

The string returned by this function can be used for diagnostic messages or as a root for temporary string names.

Return Value

A null-terminated string containing the application's name.


  AfxGetInstanceHandle

HINSTANCE AfxGetInstanceHandle( );

Remarks

This function allows you to retrieve the instance handle of the current application. Unlike AfxGetResourceHandle, AfxGetInstanceHandle always returns the HINSTANCE of your executable (.EXE). AfxGetResourceHandle can return an instance handle to either your application's .EXE or a resource dynamic-link library (DLL).

Return Value

An HINSTANCE to the current instance of the application.

See Also

»AfxGetResourceHandle«, »AfxSetResourceHandle«


  AfxGetResourceHandle

HINSTANCE AfxGetResourceHandle( );

Remarks

Use the HINSTANCE handle returned by this function to access the application's resources directly, for example, in calls to the Windows function FindResource.

Return Value

An HINSTANCE handle where the default resources of the application are loaded.

See Also

»AfxGetInstanceHandle«, »AfxSetResourceHandle«


  AfxIsMemoryBlock

BOOL AfxIsMemoryBlock( const void* p, UINT nBytes, LONG* plRequestNumber = NULL );

p    Points to the block of memory to be tested.

nBytes    Contains the length of the memory block in bytes.

plRequestNumber    Points to a long integer that will be filled in with the memory block's allocation sequence number. The variable pointed to by plRequestNumber will only be filled in if AfxIsMemoryBlock returns nonzero.

Remarks

Tests a memory address to make sure it represents a currently active memory block that was allocated by the diagnostic version of new. It also checks the specified size against the original allocated size. If the function returns nonzero, the allocation sequence number is returned in plRequestNumber. This number represents the order in which the block was allocated relative to all other new allocations.

Return Value

Nonzero if the memory block is currently allocated and the length is correct; otherwise 0.

See Also

»AfxIsValidAddress«


 Example

// example for AfxIsMemoryBlock

CAge* pcage = new CAge( 21 ); // CAge is derived from CObject.
ASSERT( AfxIsMemoryBlock( pcage, sizeof( CAge ) ) )


  AfxIsValidAddress

BOOL AfxIsValidAddress( const void FAR* lp,
UINT nBytes, BOOL bReadWrite = TRUE );

lp    Points to the memory address to be tested.

nBytes    Contains the number of bytes of memory to be tested.

bReadWrite    Specifies whether the memory is both for reading and writing (TRUE) or just reading (FALSE).

Remarks

Tests any memory address to ensure that it is contained entirely within the program's memory space. The address is not restricted to blocks allocated by new.

Return Value

Nonzero if the specified memory block is contained entirely within the program's memory space; otherwise 0.

See Also

»AfxIsMemoryBlock«, »AfxIsValidString«


  AfxIsValidString

BOOL AfxIsValidString( LPCSTR lpsz, int nLength = −1 );

lpsz    The pointer to test.

nLength    Specifies the length of the string to be tested, in bytes. A value of −1 indicates that the string will be null-terminated.

Remarks

Use this function to determine whether a pointer to a string is valid.

Return Value

Nonzero if the specified pointer does not point to a string of the specified size; otherwise 0.

See Also

»AfxIsMemoryBlock«, »AfxIsValidAddress«


  afxMemDF

int afxMemDF;

Remarks

This variable is accessible from a debugger or your program and allows you to tune allocation diagnostics. It can have the following values as specified by the enumeration afxMemDF:

•	allocMemDF    Turns on debugging allocator (default setting in Debug library).

•	delayFreeMemDF    Delays freeing memory. While your program frees a memory block, the allocator does not return that memory to the underlying operating system. This will place maximum memory stress on your program.

•	checkAlwaysMemDF    Calls AfxCheckMemory every time memory is allocated or freed. This will significantly slow memory allocations and deallocations.


 Example

// example for afxMemDF

afxMemDF = allocMemDF | checkAlwaysMemDF;


  AfxMessageBox

int AfxMessageBox( LPCSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );

int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) −1 );

lpszText    Points to a CString object or null-terminated string containing the message to be displayed in the message box.

nType    The style of the message box (see the list of »message-box styles«).

nIDHelp    The Help-context ID for the message; 0 indicates no Help context.

nIDPrompt    A unique ID used to reference a string in the string table.

Remarks

Displays a message box on the screen. The first form of this overloaded function displays a text string pointed to by lpszText in the message box and uses nIDHelp to describe a Help context. The Help context is used to jump to an associated Help topic when the user presses the Help key (typically F1).

The second form of the function uses the string resource with the ID nIDPrompt to display a message in the message box. The associated Help page is found through the value of nIDHelp. If nIDHelp is not specified, the string resource ID, nIDPrompt, is used for the Help context. For more information about defining Help contexts, see Chapter 10 of the Class Library User's Guide and Technical Note 28, which can be found in MSVCNT\HELP\MFCNOTES.HLP.

Return Value

Zero if there is not enough memory to display the message box; otherwise one of the following values is returned:

•	IDABORT    The Abort button was selected.

•	IDCANCEL    The Cancel button was selected.

•	IDIGNORE    The Ignore button was selected.

•	IDNO    The No button was selected.

•	IDOK    The OK button was selected.

•	IDRETRY    The Retry button was selected.

•	IDYES    The Yes button was selected.

If a message box has a Cancel button, the IDCANCEL value will be returned if either the ESC key is pressed or the Cancel button is selected. If the message box has no Cancel button, pressing the ESC key has no effect.

The message-box style given in the nType parameter can be any one of the following predefined constants:

 Message-Box Styles

Message-Box Types

•	MB_ABORTRETRYIGNORE    The message box contains three pushbuttons: Abort, Retry, and Ignore.

•	MB_OK    The message box contains one pushbutton: OK.

•	MB_OKCANCEL    The message box contains two pushbuttons: OK and Cancel.

•	MB_RETRYCANCEL    The message box contains two pushbuttons: Retry and Cancel.

•	MB_YESNO    The message box contains two pushbuttons: Yes and No.

•	MB_YESNOCANCEL    The message box contains three pushbuttons: Yes, No, and Cancel.

Message-Box Modality

•	MB_APPLMODAL    The user must respond to the message box before continuing work in the current window. However, the user can move to the windows of other applications and work in those windows. MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified.

•	MB_SYSTEMMODAL    All applications are suspended until the user responds to the message box. System-modal message boxes are used to notify the user of serious, potentially damaging errors that require immediate attention and should be used sparingly.

•	MB_TASKMODAL    Similar to MB_APPLMODAL, but not useful within a Microsoft Foundation class application. This flag is reserved for a calling application or library that does not have a window handle available.

Message-Box Icons

•	MB_ICONEXCLAMATION    An exclamation-point icon appears in the message box.

•	MB_ICONINFORMATION    An icon consisting of an "i" in a circle appears in the message box.

•	MB_ICONQUESTION    A question-mark icon appears in the message box.

•	MB_ICONSTOP    A stop-sign icon appears in the message box.

Message-Box Default Buttons

•	MB_DEFBUTTON1    The first button is the default. Note that the first button is always the default unless MB_DEFBUTTON2 or MB_DEFBUTTON3 is specified.

•	MB_DEFBUTTON2    The second button is the default.

•	MB_DEFBUTTON3    The third button is the default.

The functions »AfxFormatString1« and »AfxFormatString2« can be useful to format text that appears in a message box.

See Also

»CWnd::MessageBox«


  AfxOleInsertDialog

BOOL AfxOleInsertDialog( CString& name );

name    A reference to a CString object that will store the type name chosen by the user.

Remarks

Displays the Insert Object dialog box, which allows the user to insert a new embedded OLE item in a document. The dialog prompts the user to choose an OLE object or item type from a list of registered server applications and then invokes the specified application for the user to create the item. When the user exits the server application, an embedded item is inserted into the document. Call this function to implement the Insert Object command.

You must have the following statement in your client's application resource script (.RC) file:

#include <afxolecl.rc>

To add this include file to your .RC file, you should choose the Set Include item on App Studio's File menu and add "#include <afxolecl.rc>" to the list of compile-time directives.

Return Value

Nonzero if the user selected an item type; otherwise 0.


  AfxOleLinksDialog

BOOL AfxOleLinksDialog( COleClientDoc* pDoc );

pDoc    A pointer to the OLE client document that contains the links.

Remarks

Displays the Links dialog box, which displays all the OLE linked objects in the document and allows the user to update, cancel, or modify linked items. Call this function to implement the edit links command. Allows the user to update this client's OLE links.

You must have the following statement in your client's application resource script (.RC) file:

#include <afxolecl.rc>

To add this include file to your .RC file, you should choose the Set Include item on App Studio's File menu and add "#include <afxolecl.rc>" to the list of compile-time directives.

Return Value

Nonzero if successful; otherwise 0.


  AfxOleRegisterServerName

BOOL AfxOleRegisterServerName( LPCSTR lpszTypeName, LPCSTR lpszLocalTypeName );

lpszTypeName    The internal name of the document type supported by the OLE server. This name is used internally by the OLE system DLLs and the Windows registration database. This name cannot contain spaces.

lpszLocalTypeName    A user-visible name of the document type supported by the OLE server. This name may be displayd by applications using the registration database. This name can contain spaces.

Remarks

Registers the application as an OLE server with the Windows registration database and allows the server to be launched if a client application requests it. This function updates the registration database with the current location of the application's executable file and, if the server has no registered verbs, specifies Edit as the primary verb.

You typically call this function only if you are writing a mini-server; if you are writing a full server, use the COleTemplateServer class to perform the registration for you. Call this function from the InitInstance member function of your CWinApp-derived class.

Return Value

Nonzero if successful; otherwise 0.

See Also

»COleTemplateServer::RunEmbedded«


  AfxOleSetEditMenu

void AfxOleSetEditMenu( COleClientItem* pClient, CMenu* pMenu, UINT iMenuItem, UINT nIDVerbMin );

pClient    A pointer to the client OLE item.

pMenu    A pointer to the menu object that is to be updated.

iMenuItem    The index of the menu item that is to be updated.

nIDVerbMin    The command ID that corresponds to the primary verb.

Remarks

Implements the user interface for the typename Object command. If the server recognizes only a primary verb, the menu item becomes "verb typename Object" and the nIDVerbMin command is sent when the user chooses the command. If the server recognizes several verbs, then the menu item becomes "typename bject" and a submenu listing all the verbs appears when the user chooses the command. When the user chooses a verb from the submenu, nIDVerbMin is sent if the first verb is chosen, nIDVerbMin + 1 is sent if the second verb is chosen, and so forth.

The default »COleClientDoc« implementation automatically handles this feature.

You must have the following statement in your client's application resource script (.RC) file:

#include <afxolecl.rc>

To add this include file to your .RC file, you should choose the Set Include item on App Studio's File menu and add "#include <afxolecl.rc>" to the list of compile-time directives.


  AfxRegisterWndClass

const char* AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 );

nClassStyle    Specifies the Windows class style or combination of styles for the window class. This parameter can be any valid window style or control style, or a combination of styles created by using the bitwise-OR (|) operator. For a list of class styles, see the WNDCLASS structure in the Windows SDK documentation.

hCursor    Specifies a handle to the cursor resource to be installed in each window created from the window class.

hbrBackground    Specifies a handle to the brush resource to be installed in each window created from the window class.

hIcon    Specifies a handle to the icon resource to be installed in each window created from the window class.

Remarks

The Microsoft Foundation Class Library automatically registers several standard window classes for you. Call this function if you want to register your own window classes.

Return Value

A null-terminated string containing the class name. You can pass this class name to the Create member function in CWnd or other CWnd-derived classes to create a window. The name is generated by the Microsoft Foundation Class Library.

Note  The return value is a pointer to a static buffer. To save this string, assign it to a CString variable.

See Also

»CWnd::Create«, »CWnd::PreCreateWindow«


  AfxSetAllocHook

AFX_ALLOC_HOOK AfxSetAllocHook( AFX_ALLOC_HOOK pfnAllocHook );

pfnAllocHook    Specifies the name of the function to call. See below for the prototype of an allocation function.

Remarks

Sets a hook that enables calling of the specified function before each memory block is allocated. The hook function is described below.

Hook Function

The Microsoft Foundation Class Library debug-memory allocator can call a user-defined hook function to allow the user to monitor a memory allocation and to control whether the allocation is permitted. Allocation hook functions are prototyped as:

BOOL AllocHook( size_t nSize, BOOL bObject, LONG lRequestNumber );

nSize    The size of the proposed memory allocation.

bObject    TRUE if the allocation is for a CObject-derived object.

lRequestNumber    The memory allocation's sequence number.

Return Value

Nonzero if you want to permit the allocation; otherwise 0.


  AfxSetResourceHandle

void AfxSetResourceHandle( HINSTANCE hInstResource );

hInstResource    The instance or module handle to an .EXE or DLL file from which the application's resources are loaded.

Remarks

Use this function to set the HINSTANCE handle that determines where the default resources of the application are loaded.

See Also

»AfxGetInstanceHandle«, »AfxGetResourceHandle«


  AfxThrowArchiveException

void AfxThrowArchiveException( int cause );

cause    Specifies an integer that indicates the reason for the exception. For a list of the possible values, see »CArchiveException::m_cause«.

Remarks

Throws an archive exception.

See Also

»CArchiveException«, »THROW«


  AfxThrowFileException

void AfxThrowFileException( int cause, LONG lOsError = −1 );

cause    Specifies an integer that indicates the reason for the exception. For a list of the possible values, see »CFileException::m_cause«.

lOsError    Contains the operating-system error number (if available) that states the reason for the exception. See your operating-system manual for a listing of error codes.

Remarks

Throws a file exception. You are responsible for determining the cause based on the operating-system error code.

See Also

»CFileException::ThrowOsError«, »THROW«


  AfxThrowMemoryException

void AfxThrowMemoryException();

Remarks

Throws a memory exception. Call this function if calls to underlying system memory allocators (such as malloc and the GlobalAlloc Windows function) fail. You do not need to call it for new because new will throw a memory exception automatically if the memory allocation fails.

See Also

»CMemoryException«, »THROW«


  AfxThrowNotSupportedException

void AfxThrowNotSupportedException();

Remarks

Throws an exception that is the result of a request for an unsupported feature.

See Also

»CNotSupportedException«, »THROW«


  AfxThrowOleException

void AfxThrowOleException( OLESTATUS status );

status    Indicates the reason for the exception. For a list of the possible values, see »COleException::m_status«.

Remarks

Throws an OLE exception.

See Also

»COleException«, »THROW«


  AfxThrowResourceException

void AfxThrowResourceException();

Remarks

Throws a resource exception. This function is normally called when a Windows resource cannot be loaded.

See Also

»CResourceException«, »THROW«


  AfxThrowUserException

void AfxThrowUserException();

Remarks

Throws an exception to stop an end-user operation. This function is normally called immediately after AfxMessageBox has reported an error to the user.

See Also

»CUserException«, »THROW«, »AfxMessageBox«


  afxTraceEnabled

BOOL afxTraceEnabled;

Remarks

A global variable used to enable or disable output from the TRACE macro.

By default, output from the TRACE macro is disabled. Set afxTraceEnabled to a nonzero value if you want TRACE macros in your program to produce output. Set it to 0 if you don't want TRACE macros in your program to produce output.

Usually, the value of afxTraceEnabled is set in your afx.ini file. Alternately, you can set the value of afxTraceEnabled with the TRACER.EXE utility. For more information on afxTraceEnabled, see Technical Note 7, which can be found in MSVCNT\HELP\MFCNOTES.HLP.

See Also

»afxTraceFlags«, »TRACE«


  afxTraceFlags

int afxTraceFlags;

Remarks

Used to turn on the built-in reporting features of the Microsoft Foundation Class Library.

This variable can be set under program control or while using the debugger. Each bit of afxTraceFlags selects a trace reporting option. You can turn any one of these bits on or off as desired using TRACER.EXE. There is never a need to set these flags manually.

The following is a list of the bit patterns and the resulting trace report option:

•	0x01    Multiapplication debugging. This will prefix each TRACE output with the name of the application and affects both the explicit TRACE output of your program as well as the additional report options described below.

•	0x02    Main message pump. Reports each message received in the main CWinApp message-handling mechanism. Lists the window handle, the message name or number, wParam, and lParam.

The report is made after the Windows GetMessage call but before any message translation or dispatch occurs.

Dynamic data exchange (DDE) messages will display additional data that can be used for some debugging scenarios in OLE.

This flag only displays messages that are posted — not those that are sent.

•	0x04    Main message dispatch. Like option 0x02 above but applies to messages dispatched in CWnd::WindowProc, and therefore handles both posted and sent messages that are about to be dispatched.

•	0x08    WM_COMMAND dispatch. A special case used for extended WM_COMMAND/OnCommand handling to report progress of the command-routing mechanism.

Also reports which class receives the command (when there is a matching message-map entry), and when classes don't receive a command (when there is no matching message map entry). This report is especially useful to track the flow of command messages in multiple document interface (MDI) applications.

•	0x10    OLE tracing. Reports significant OLE notifications or requests.

Turn this option on for an OLE client or server to track communication between the OLE DLLs and an OLE application.

For more information, see Technical Note 7, which can be found in MSVCNT\HELP\MFCNOTES.HLP.

See Also

»afxTraceEnabled«, »TRACE«


AND_CATCH macro
  AND_CATCH

AND_CATCH( exception_class, exception_object_pointer_name )

exception_class    Specifies the exception type to test for. For a list of standard exception classes, see class »CException«.

exception_object_pointer_name    A name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the AND_CATCH block. This variable is declared for you.

Remarks

Defines a block of code for catching additional exception types thrown in a preceding TRY block. Use the CATCH macro to catch one exception type, then the AND_CATCH macro to catch each subsequent type.

The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Invoke the THROW_LAST macro within the AND_CATCH block to shift processing to the next outer exception frame. AND_CATCH marks the end of the preceding CATCH or AND_CATCH block.

Note  The AND_CATCH block is defined as a C++ scope (delineated by curly braces). If you declare variables in this scope, remember that they are accessible only within that scope. This also applies to the exception_object_pointer_name variable.

See Also

»TRY«, »CATCH«, »THROW«, »END_CATCH«, »THROW_LAST«, »CException«


ASSERT macro
  ASSERT

ASSERT( booleanExpression )

booleanExpression    Specifies an expression (including pointer values) that evaluates to nonzero or 0.

Remarks

Evaluates its argument. If the result is 0, the macro prints a diagnostic message and aborts the program. If the condition is nonzero, it does nothing.

The diagnostic message has the form:

assertion failed in file <name> in line <num>

where name is the name of the source file, and num is the line number of the assertion that failed in the source file.

In the Release version of the Microsoft Foundation Class Library, ASSERT does not evaluate the expression and thus will not interrupt the program. If the expression must be evaluated regardless of environment, use the VERIFY macro in place of ASSERT.

Note  This function is available only in the Debug version of the Microsoft Foundation Class Library.

See Also

»VERIFY«

 Example

// example for ASSERT

CAge* pcage = new CAge( 21 ); // CAge is derived from CObject.

ASSERT( pcage!= NULL )
ASSERT( pcage->IsKindOf( RUNTIME_CLASS( CAge ) ) )
// Terminates program only if pcage is NOT a CAge*.


ASSERT_VALID macro
  ASSERT_VALID

ASSERT_VALID( pObject )

pObject    Specifies an object of a class derived from CObject that has an overriding version of the AssertValid member function.

Remarks

Use to test your assumptions about the validity of an object's internal state. ASSERT_VALID calls the AssertValid member function of the object passed as its argument.

In the Release version of the Microsoft Foundation Class Library, ASSERT_VALID does nothing. In the Debug version, it validates the pointer, checks against NULL, and calls the object's own AssertValid member functions. If any of these tests fails, this displays an alert message in the same manner as ASSERT.

Note  This function is available only in the Debug version of the Microsoft Foundation Class Library.

See Also

»ASSERT«, »VERIFY«, »CObject«, »CObject::AssertValid«


BEGIN_MESSAGE_MAP macro
  BEGIN_MESSAGE_MAP

BEGIN_MESSAGE_MAP( theClass, baseClass )

theClass    Specifies the name of the class whose message map this is.

baseClass    Specifies the name of the base class of theClass.

Remarks

Use the BEGIN_MESSAGE_MAP macro to begin the definition of your message map.

In the implementation (.CPP) file that defines the member functions for your class, start the message map with the BEGIN_MESSAGE_MAP macro, then add macro entries for each of your message-handler functions (see the listing under "»Message Maps«"), and complete the message map with the END_MESSAGE_MAP macro.

For more information on message maps and the BEGIN_MESSAGE_MAP macro, see Chapter 6 of the Class Library User's Guide.

See Also

»DECLARE_MESSAGE_MAP«, »END_MESSAGE_MAP«

 Example

// example for BEGIN_MESSAGE_MAP

BEGIN_MESSAGE_MAP( CMyWindow, CFrameWnd )
//{{AFX_MSG_MAP( CMyWindow )

    ON_WM_PAINT()
    ON_COMMAND( IDM_ABOUT, OnAbout )

//}}AFX_MSG_MAP
END_MESSAGE_MAP( )


CATCH macro
  CATCH

CATCH( exception_class, exception_object_pointer_name )

exception_class    Specifies the exception type to test for. For a list of standard exception classes, see class »CException«.

exception_object_pointer_name    Specifies a name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the CATCH block. This variable is declared for you.

Remarks

Use this macro to define a block of code that catches the first exception type thrown in the preceding TRY block. The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Invoke the THROW_LAST macro to shift processing to the next outer exception frame.

If exception_class is the class CException, then all exception types will be caught. You can use the »CObject::IsKindOf« member function to determine which specific exception was thrown. A better way to catch several kinds of exceptions is to use sequential AND_CATCH statements, each with a different exception type.

The exception object pointer is created by the macro. You do not need to declare it yourself.

Note  The CATCH block is defined as a C++ scope (delineated by curly braces). If you declare variables in this scope, remember that they are accessible only within that scope. This also applies to exception_object_pointer_name.

For more information on exceptions and the CATCH macro, see Chapter 16 of the Class Library User's Guide.

See Also

»TRY«, »AND_CATCH«, »END_CATCH«, »THROW«, »THROW_LAST«, »CException«


DEBUG_NEW macro
  DEBUG_NEW

#define new DEBUG_NEW

Remarks

Assists in finding memory leaks. You can use DEBUG_NEW everywhere in your program that you would ordinarily use the new operator to allocate heap storage.

In Debug mode (when the _DEBUG symbol is defined), DEBUG_NEW keeps track of the filename and line number for each object that it allocates. Then, when you use the CMemoryState::DumpAllObjectsSince member function, each object allocated with DEBUG_NEW is shown with the filename and line number where it was allocated.

To use DEBUG_NEW, insert the following directive into your source files:

#define new DEBUG_NEW

Once you insert this directive, the preprocessor will insert DEBUG_NEW wherever you use new, and the Microsoft Foundation Class Library does the rest. When you compile a release version of your program, DEBUG_NEW resolves to a simple new operation, and the filename and line number information is not generated.

Note  You must place the #define statement after all statements that call the IMPLEMENT_DYNCREATE or IMPLEMENT_SERIAL macros in your module, or you will get a compile-time error.

For more information on the DEBUG_NEW macro, see Chapter 15 of the Class Library User's Guide.


DECLARE_DYNAMIC macro
  DECLARE_DYNAMIC

DECLARE_DYNAMIC( class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

Remarks

When deriving a class from CObject, this macro adds the ability to access run-time information about an object's class.

Add the DECLARE_DYNAMIC macro to the header (.H) module for the class, then include that module in all .CPP modules that need access to objects of this class.

If you use the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros as described, you can then use the RUNTIME_CLASS macro and the CObject::IsKindOf function to determine the class of your objects at run time.

If DECLARE_DYNAMIC is included in the class declaration, then IMPLEMENT_DYNAMIC must be included in the class implementation.

For more information on the DECLARE_DYNAMIC macro, see Chapter 12 of the Class Library User's Guide.

See Also

»IMPLEMENT_DYNAMIC«, »DECLARE_DYNCREATE«, »DECLARE_SERIAL«, »RUNTIME_CLASS«, »CObject::IsKindOf«


DECLARE_DYNCREATE macro
  DECLARE_DYNCREATE

DECLARE_DYNCREATE( class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

Remarks

Use the DECLARE_DYNCREATE macro to enable objects of CObject-derived classes to be created dynamically at run time. The framework uses this ability to create new objects dynamically, for example, when it reads an object from disk during serialization. Document, view, and frame classes should support dynamic creation because the framework needs to create them dynamically.

Add the DECLARE_DYNCREATE macro in the .H module for the class, then include that module in all .CPP modules that need access to objects of this class.

If DECLARE_DYNCREATE is included in the class declaration, then IMPLEMENT_DYNCREATE must be included in the class implementation.

For more information on the DECLARE_DYNCREATE macro, see Chapter 12 of the Class Library User's Guide.

See Also

»DECLARE_DYNAMIC«, »IMPLEMENT_DYNAMIC«, »IMPLEMENT_DYNCREATE«, »RUNTIME_CLASS«, »CObject::IsKindOf«


DECLARE_MESSAGE_MAP macro
  DECLARE_MESSAGE_MAP

DECLARE_MESSAGE_MAP()

Remarks

Each CCmdTarget-derived class in your program must provide a message map to handle messages. Use the DECLARE_MESSAGE_MAP macro at the end of your class declaration. Then, in the .CPP file that defines the member functions for the class, use the BEGIN_MESSAGE_MAP macro, macro entries for each of your message-handler functions (see the listing under »Message Maps«), and the END_MESSAGE_MAP macro.

For more information on message maps and the DECLARE_MESSAGE_MAP macro, see Chapter 6 of the Class Library User's Guide.

See Also

»BEGIN_MESSAGE_MAP«, »END_MESSAGE_MAP«

 Example

// example for DECLARE_MESSAGE_MAP

class CMyWnd : public CFrameWnd

{
    // Member declarations

    DECLARE_MESSAGE_MAP( )
};

Note  If you declare any member after DECLARE_MESSAGE_MAP, you must specify a new access type (public, private, protected) for them.


DECLARE_SERIAL macro
  DECLARE_SERIAL

DECLARE_SERIAL( class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

Remarks

DECLARE_SERIAL generates the C++ header code necessary for a CObject-derived class that can be serialized. Serialization is the process of writing or reading the contents of an object to and from a file.

Use the DECLARE_SERIAL macro in a .H module, then include that module in all .CPP modules that need access to objects of this class. For more information, see Chapter 12 of the Class Library User's Guide.

If DECLARE_SERIAL is included in the class declaration, then IMPLEMENT_SERIAL must be included in the class implementation.

The DECLARE_SERIAL macro includes all the functionality of DECLARE_DYNAMIC and DECLARE_DYNCREATE.

For more information on the DECLARE_SERIAL macro, see Chapter 12 of the Class Library User's Guide.

See Also

»DECLARE_DYNAMIC«, »IMPLEMENT_SERIAL«, »RUNTIME_CLASS«, »CObject::IsKindOf«


END_CATCH macro
  END_CATCH

END_CATCH

Remarks

Marks the end of the last CATCH or AND_CATCH block.

For more information on the END_CATCH macro, see Chapter 16 of the Class Library User's Guide.

See Also

»TRY«, »CATCH«, »THROW«, »AND_CATCH«, »THROW_LAST«


END_MESSAGE_MAP macro
  END_MESSAGE_MAP

END_MESSAGE_MAP()

Remarks

Use the END_MESSAGE_MAP macro to end the definition of your message map.

For more information on message maps and the END_MESSAGE_MAP macro, see Chapter 6 of the Class Library User's Guide.

See Also

»DECLARE_MESSAGE_MAP«, »BEGIN_MESSAGE_MAP«, »Message Map Function Categories«


IMPLEMENT_DYNAMIC macro
  IMPLEMENT_DYNAMIC

IMPLEMENT_DYNAMIC( class_name, base_class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

base_class_name    The name of the base class (not enclosed in quotation marks).

Remarks

Generates the C++ code necessary for a dynamic CObject-derived class with run-time access to the class name and position within the hierarchy. Use the IMPLEMENT_DYNAMIC macro in a .CPP module, then link the resulting object code only once.

For more information, see Chapter 12 of the Class Library User's Guide.

See Also

»DECLARE_DYNAMIC«, »RUNTIME_CLASS«, »CObject::IsKindOf«


IMPLEMENT_DYNCREATE macro
  IMPLEMENT_DYNCREATE

IMPLEMENT_DYNCREATE( class_name, base_class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

base_class_name    The actual name of the base class (not enclosed in quotation marks).

Remarks

Use the IMPLEMENT_DYNCREATE macro with the DECLARE_DYNCREATE macro to enable objects of CObject-derived classes to be created dynamically at run time. The framework uses this ability to create new objects dynamically, for example, when it reads an object from disk during serialization. Add the IMPLEMENT_DYNCREATE macro in the class implementation file. For more information, see Chapter 12 of the Class Library User's Guide.

If you use the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE macros, you can then use the RUNTIME_CLASS macro and the CObject::IsKindOf member function to determine the class of your objects at run time.

If DECLARE_DYNCREATE is included in the class declaration, then IMPLEMENT_DYNCREATE must be included in the class implementation.

See Also

»DECLARE_DYNCREATE«, »RUNTIME_CLASS«, »CObject::IsKindOf«


IMPLEMENT_SERIAL macro
   IMPLEMENT_SERIAL

IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )

class_name    The actual name of the class (not enclosed in quotation marks).

base_class_name    The name of the base class (not enclosed in quotation marks).

wSchema    A UINT "version number" that will be encoded in the archive to enable a deserializing program to identify and handle data created by earlier program versions. The class schema number must not be −1.

Remarks

Generates the C++ code necessary for a dynamic CObject-derived class with run-time access to the class name and position within the hierarchy. Use the IMPLEMENT_SERIAL macro in a .CPP module; then link the resulting object code only once.

For more information, see Chapter 12 of the Class Library User's Guide.

See Also

»DECLARE_SERIAL«, »RUNTIME_CLASS«, »CObject::IsKindOf«


ON_COMMAND macro
  ON_COMMAND

ON_COMMAND( id, memberFxn )

id    The command ID.

memberFxn    The name of the message-handler function to which the command is mapped.

Remarks

This macro is usually inserted in a message map by ClassWizard or manually. It indicates which function will handle a command message from a command user-interface object such as a menu item or toolbar button.

When a command-target object receives a Windows WM_COMMAND message with the specified ID, ON_COMMAND will call the member function memberFxn to handle the message.

There should be exactly one ON_COMMAND macro statement in your message map for every menu or accelerator command that must be mapped to a message-handler function.

For more information and examples, see Chapter 6 of the Class Library User's Guide.

See Also

»ON_UPDATE_COMMAND_UI«

 Example

// example for ON_COMMAND

BEGIN_MESSAGE_MAP( CMyDoc, CDocument )

    //{{AFX_MSG_MAP( CMyDoc )

    ON_COMMAND( ID_MYCMD, OnMyCommand )

    // ... More entries to handle additional commands

    //}}AFX_MSG_MAP

END_MESSAGE_MAP( )


ON_CONTROL macro
  ON_CONTROL

ON_CONTROL( wNotifyCode, id, memberFxn )

wNotifyCode    The notification code of the control.

id    The command ID.

memberFxn    The name of the message-handler function to which the command is mapped.

Remarks

Indicates which function will handle a custom-control notification message. Control notification messages are those sent from a control to its parent window.

There should be exactly one ON_CONTROL macro statement in your message map for every control notification message that must be mapped to a message-handler function.

For more information and examples, see Chapter 6 of the Class Library User's Guide.

See Also

»ON_MESSAGE«, »ON_REGISTERED_MESSAGE«


ON_MESSAGE macro
  ON_MESSAGE

ON_MESSAGE( message, memberFxn )

message    The message ID.

memberFxn    The name of the message-handler function to which the message is mapped.

Remarks

Indicates which function will handle a user-defined message. User-defined messages are usually defined in the range WM_USER to 0x7FFF. User-defined messages are any messages that are not standard Windows WM_MESSAGE messages. There should be exactly one ON_MESSAGE macro statement in your message map for every user-defined message that must be mapped to a message-handler function.

For more information and examples, see Chapter 6 of the Class Library User's Guide.

See Also

»ON_UPDATE_COMMAND_UI«, »ON_CONTROL«, »ON_REGISTERED_MESSAGE«, »ON_COMMAND«

 Example

// example for ON_MESSAGE

#define WM_MYMESSAGE (WM_USER + 1)

BEGIN_MESSAGE_MAP( CMyWnd, CMyParentWndClass )

    //{{AFX_MSG_MAP( CMyWnd

    ON_MESSAGE( WM_MYMESSAGE, OnMyMessage )

    // ... Possibly more entries to handle additional messages

    //}}AFX_MSG_MAP

END_MESSAGE_MAP( )


ON_REGISTERED_MESSAGE macro
  ON_REGISTERED_MESSAGE

ON_REGISTERED_MESSAGE( nMessageVariable, memberFxn )

nMessageVariable    The registered window-message ID variable.

memberFxn    The name of the message-handler function to which the message is mapped.

Remarks

The Windows RegisterWindowMessage function is used to define a new window message that is guaranteed to be unique throughout the system. This macro indicates which function will handle the registered message.

The variable nMessageVariable should be declared with the near modifier.

See Also

»ON_MESSAGE«, »ON_UPDATE_COMMAND_UI«, »ON_CONTROL«, »ON_COMMAND«, ::RegisterWindowMessage

 Example

// example for ON_REGISTERED_MESSAGE

const UINT NEAR	 wm_Find = RegisterWindowMessage( FINDMSGSTRING )
BEGIN_MESSAGE_MAP( CMyWnd, CMyParentWndClass )
    //{{AFX_MSG_MAP( CMyWnd )
    ON_REGISTERED_MESSAGE( wm_Find, OnFind )
    // ... Possibly more entries to handle additional messages
    //}}AFX_MSG_MAP
END_MESSAGE_MAP( )


ON_UPDATE_COMMAND_UI macro
  ON_UPDATE_COMMAND_UI

ON_UPDATE_COMMAND_UI( id, memberFxn )

id    The message ID.

memberFxn    The name of the message-handler function to which the message is mapped.

Remarks

This macro is usually inserted in a message map by ClassWizard to indicate which function will handle a user-interface update command message.

There should be exactly one ON_UPDATE_COMMAND_UI macro statement in your message map for every user-interface update command that must be mapped to a message-handler function.

See Also

»ON_MESSAGE«, »ON_REGISTED_MESSAGE«, »ON_CONTROL«, »ON_COMMAND«, »CCmdUI«


RUNTIME_CLASS macro
  RUNTIME_CLASS

RUNTIME_CLASS( class_name )

class_name    The actual name of the class (not enclosed in quotation marks).

Remarks

Use this macro to get the run-time class structure from the name of a C++ class.

RUNTIME_CLASS returns a pointer to a »CRuntimeClass« structure for the class specified by class_name. Only CObject-derived classes declared with DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL will return pointers to a CRuntimeClass structure.

For more information, see Chapter 12 of the Class Library User's Guide.

See Also

»DECLARE_DYNAMIC«, »DECLARE_DYNCREATE«, »DECLARE_SERIAL«, »CObject::GetRuntimeClass«, »CRuntimeClass«

 Example

// example for RUNTIME_CLASS

CRuntimeClass* prt = RUNTIME_CLASS( CAge );
ASSERT( lstrcmp( prt->m_lpszClassName, "CAge" )  == 0 );


THROW macro
  THROW

THROW( exception_object_pointer )

exception_object_pointer    Points to an exception object derived from CException.

Remarks

Throws the specified exception. THROW interrupts program execution, passing control to the associated CATCH block in your program. If you have not provided the CATCH block, then control is passed to a Microsoft Foundation Class Library module that prints an error message and exits.

For more information, see Chapter 16 of the Class Library User's Guide.

See Also

»TRY«, »CATCH«, »THROW«, »THROW_LAST«, »AND_CATCH«, »END_CATCH«, »AfxThrowArchiveException«, »AfxThrowFileException«, »AfxThrowMemoryException«, »AfxThrowNotSupportedException«, »AfxThrowOleException«, »AfxThrowResourceException«, »AfxThrowUserException«


THROW_LAST macro
  THROW_LAST

THROW_LAST()

Remarks

Throws the exception back to the next outer CATCH block.

This macro allows you to throw a locally created exception. If you try to throw an exception that you have just caught, it will normally go out of scope and be deleted. With THROW_LAST, the exception is passed correctly to the next CATCH handler.

For more information, see Chapter 16 of the Class Library User's Guide.

See Also

»TRY«, »CATCH«, »THROW«, »AND_CATCH«, »END_CATCH«


TRACE macro
  TRACE

TRACE( exp )

exp    Specifies a variable number of arguments that are used in exactly the same way that a variable number of arguments are used in the run-time function printf.

Remarks

Provides similar functionality to the printf function by sending a formatted string to a dump device such as a file or debug monitor. Like printf for C programs under MS-DOS, the TRACE macro is a convenient way to track the value of variables as your program executes. In the Debug environment, the TRACE macro output goes to afxDump. In the Release environment, it does nothing.

Note  This macro is available only in the Debug version of the Microsoft Foundation Class Library.

For more information, see Chapter 15 of the Class Library User's Guide.

See Also

»TRACE0«, »TRACE1«, »TRACE2«, »TRACE3«, »AfxDump«, »afxTraceEnabled«

 Example

// example for TRACE

int i = 1;
char sz[] = "one";
TRACE( "Integer = %d, String = %s\n", i, sz );
// Output: 'Integer = 1, String = one'


TRACE0 macro
  TRACE0

TRACE0( exp )

exp    A format string as used in the run-time function printf.

Remarks

Similar to TRACE, but places the trace string in a code segment rather than DGROUP, thus using less DGROUP space. TRACE0 is one variant of a group of trace macros that you can use for debug output. This group includes TRACE0, TRACE1, TRACE2, and TRACE3. The difference between these macros is the number of parameters taken. TRACE0 only takes a format string and can be used for simple text messages. TRACE1 takes a format string plus one argument — a variable to be dumped. Likewise, TRACE2 and TRACE3 take two and three parameters after the format string, respectively.

TRACE0 does nothing if you have compiled a release version of your application. As with TRACE, it only dumps data to afxDump if you have compiled a debug version of your application.

Note  This macro is available only in the Debug version of the Microsoft Foundation Class Library.

 Example

// example for TRACE0

TRACE0( "Start Dump of MyClass members:" );

See Also

»TRACE«, »TRACE1«, »TRACE2«, »TRACE3«


TRACE1 macro
  TRACE1

TRACE1( exp, param1 )

exp    A format string as used in the run-time function printf.

param1    The name of the variable whose value should be dumped.

Remarks

See TRACE0 for a description of the TRACE1 macro.

 Example

// example for TRACE1

int i = 1;
TRACE1( "Integer = %d\n", i );
// Output: 'Integer = 1'


TRACE2 macro
  TRACE2

TRACE2( exp, param1, param2 )

exp    A format string as used in the run-time function printf.

param1    The name of the variable whose value should be dumped.

param2    The name of the variable whose value should be dumped.

Remarks

See TRACE0 for a description of the TRACE2 macro.

 Example

// example for TRACE2

int i = 1;
char sz[] = "one";
TRACE2( "Integer = %d, String = %s\n", i, sz );
// Output: 'Integer = 1, String = one'


TRACE3 macro
  TRACE3

TRACE3( exp, param1, param2, param3 )

exp    A format string as used in the run-time function printf.

param1    The name of the variable whose value should be dumped.

param2    The name of the variable whose value should be dumped.

param3    The name of the variable whose value should be dumped.

Remarks

See TRACE0 for a description of the TRACE3 macro.


TRY macro
  TRY

TRY

Remarks

Use this macro to set up a TRY block. A TRY block identifies a block of code that might throw exceptions. Those exceptions are handled in the following CATCH and AND_CATCH blocks. Recursion is allowed: exceptions may be passed to an outer TRY block, either by ignoring them or by using the THROW_LAST macro.

For more information, see Chapter 16 of the Class Library User's Guide.

See Also

»THROW«, »CATCH«, »AND_CATCH«, »END_CATCH«


VERIFY macro
  VERIFY

VERIFY( booleanExpression )

booleanExpression    Specifies an expression (including pointer values) that evaluates to nonzero or 0.

Remarks

In the Debug version of the Microsoft Foundation Class Library, the VERIFY macro evaluates its argument. If the result is 0, the macro prints a diagnostic message and halts the program. If the condition is nonzero, it does nothing.

The diagnostic message has the form:

assertion failed in file <name> in line <num>

where name is the name of the source file and num is the line number of the assertion that failed in the source file.

In the Release version of the Microsoft Foundation Class Library, VERIFY evaluates the expression but does not print or interrupt the program. For example, if the expression is a function call, the call will be made.

See Also

»ASSERT«


Figure 2.1    Objects in a Running SDI Application


Figure 2.2    Sequence of Execution


Figure 2.3    The Message Loop


Figure 2.4    An MDI Application with Two Document Types


Figure 2.5    Sequence in Creating a Document


Figure 2.6    Sequence in Creating a Frame Window


Figure 2.7    Sequence in Creating a View


Figure 2.8    Window Object and Windows Window


Figure 2.9    An MDI Frame Window with Children


Figure 3.1    Commands in the Framework


Figure 3.2    A View Hierarchy


Figure 3.3    ClassWizard


Figure 3.4    A Command Prompt in the Status Bar


Figure 4.1    Frame Window and View


Figure 4.2    MDI Frame Windows and Children


Figure 4.3    Document and View


Figure 4.4    Multiple-View User Interfaces


Figure 5.1    Dialog Data Exchange


Figure 5.2    Bitmap Buttons


Figure 5.3    The Standard Toolbar Bitmap


Figure 5.4    A Toolbar with Separators


Figure 5.5    A Status Bar


Figure 5.6    A Dialog Bar


Figure 5.7    Preparing Help Files


Introduction
CodeView Debugger User's Guide

Introduction

The Microsoft® CodeView® debugger is a powerful diagnostic tool for finding errors in your programs. You can examine code and data and control your program's execution.

This manual is organized as follows:

•	»Chapter 1, Getting Started with CodeView,« introduces the CodeView debugger. It tells how to prepare programs for debugging and how to customize CodeView.

•	»Chapter 2, The CodeView Environment,« presents the menus, windows, commands, and other features of CodeView.

•	»Chapter 3, Debugging Win32s Applications,« explains how to debug programs for the Microsoft Windows™ ( ) operating system.

•	»Chapter 4, Using Expressions in CodeView,« discusses the C and C++ expression evaluators.

•	»Chapter 5, CodeView Reference,« describes the Command-window command format, explains common elements in CodeView expressions, and contains an alphabetic reference of CodeView commands.

•	»Appendix A, Shortcut Key Summaries,« lists keyboard shortcuts for CodeView tasks.

Note  For information on Microsoft product support, see the chapter "Microsoft Support Services" in Getting Started, or choose Obtaining Technical Support from the Help menu.


Book Location
CodeView Debugger User's Guide


  Document Conventions

This book uses the following typographic conventions.

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
expression	Words in italics indicate placeholders for information you must supply, such as a filename. Italic type is also occasionally used for emphasis in the text.
char, _ftime, __cdec	Bold type indicates keywords, operators, language-specific characters, and library routines. Within discussions of syntax, bold type indicates the text must be entered exactly as shown.
	Many functions and constants begin with either a single or double underscore. These are part of the name and are mandatory. For example, to have the __cplusplus manifest constant be recognized by the compiler, you must enter the leading double underscore.
[option]	Items inside square brackets are optional.
#pragma pack {1 | 2}	Braces and a vertical bar indicate a choice among two or more items. You must choose one of these items unless square brackets ([ ]) surround the braces.
#include <io.h>	This font is used for examples, user input, program output, and error messages in text.
CL [option...]  file...	Three dots (an ellipsis) following an item indicate that more items having the same form can appear.
while() {    .    .    . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second.  The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
"argument"	Quotation marks enclose a new term the first time it is defined in text.
"C string"	Some C constructs, such as strings, require quotation marks. Quotation marks required by the language are bold and have the form " " and ' ' rather than " " and ' '.
Dynamic Link Library (DLL)	The first time an acronym is used, it is usually spelled out.


  Chapter 1  Getting Started with CodeView

The Microsoft CodeView debugger version 4.25 is a window-oriented tool that helps you find and correct errors in Microsoft Visual C++™ and Microsoft Macro Assembler (MASM) programs for Win32s. With CodeView, you can examine source-level code and the corresponding compiled code at the same time. You can execute your code in increments and view and modify data in memory as your program runs. The names "CodeView," "CodeView debugger," and "the debugger" refer to CodeView unless the discussion indicates otherwise.

To debug applications for Windows NT use the Visual Workbench debugger.

This chapter shows you how to:

•	Write programs to make debugging easier.

•	Formulate a debugging strategy.

•	Compile and link your programs to include Microsoft CodeView Symbolic Debugging Information.

•	Set up the files CodeView needs.

•	Configure CodeView with TOOLS.INI.

•	Start CodeView and load a program.

•	Use the CodeView command-line options.

•	Use or disable the CURRENT.STS state file.


  Preparing Programs for Debugging

You can use CodeView to debug any Microsoft Windows Win32s executable file produced from Visual C++ or MASM source code. "Compiling" means producing object code from source files. All references to compiling also apply to assembling unless stated otherwise.


  General Programming Considerations

This section describes programming practices that make debugging with CodeView easier and more efficient.


  Multiple Statements on a Line

CodeView treats each source-code line as a unit. For this reason, you cannot trace or set a breakpoint on more than one statement per line. You can change from Source display mode to Mixed or Assembly display mode (see »The Source Windows«) and then set breakpoints at individual assembly instructions. If a single statement is broken across multiple lines, you may be able to set breakpoints on only the ending line of the statement.


  Macros and Inline Code

Microsoft C, C++, and MASM support macro expansion. Microsoft C and C++ also support inline code generation. These features pose a debugging problem because a macro or an inline function is expanded where it is used, and CodeView has no information about the source code. This means that you cannot trace or set breakpoints in a macro or inline function when debugging at the source level.

To work around this condition, you can:

•	Manually expand the macro to its corresponding source code.

•	Rewrite the macro as a function.

•	Suppress inline code generation with the /Ob0 compiler option.

You can often rewrite macros as inline functions, then selectively disable inlining with a compiler option or pragma so that you can step and trace the routine. Rewriting macros as inline functions can have additional benefits such as argument type checking. However, in some cases the best solution for debugging macros or inline code is to use Assembly or Mixed display mode.


  Programs That Alter the Environment

Programs that run under CodeView can read the environment table, but they cannot permanently change it. When you exit CodeView, changes to the environment are lost.


  Processing Command Line Arguments

CodeView processes the command-line argument the same way as the C/C++ run-time library does. Quotation marks are removed, and exactly one space is left between command-line arguments.


  Compiling and Linking

After you compile and link your program into a running executable file, you can begin debugging with CodeView. To take full advantage of CodeView, however, you must compile and link with the options that generate CodeView Symbolic Debugging Information. This book refers to this information as "CodeView information," "debugging information," or "symbolic information."

The CodeView information tells CodeView about:

•	All program symbols, including locals, globals, and publics

•	Data types

•	Line numbers

•	Modules

Without this information, you cannot refer to any source-level names, and you can view the program only in Assembly display mode. When CodeView loads a module that does not contain symbolic information, CodeView starts in Assembly mode and displays the message:

CV0101 Warning: No symbolic information for PROGRAM.EXE

You get this message if you try to debug an executable file that you did not compile and link with CodeView options, if you use a compiler that does not generate CodeView information, or if you link your program with an old version of the linker. If you retain an old linker version and it is first in your path, the proper information may not be generated for CodeView.

You can specify CodeView compiler and linker options from the command line, in a makefile, or from within the Microsoft Visual Workbench. To compile and link your program with CodeView options from the Visual Workbench, choose Build Options from the Options menu, and turn on Use Debug Options. By default, all project templates enable the generation of CodeView information for debug builds.


  Compiler Options

Compile with /Zi for full CodeView information.

You can specify CodeView options when you compile a source file of a program you want to debug. Specify the /Zi option on the command line or in a makefile to instruct the compiler to include line-number and complete symbolic information in the object file.

Compile with /Zd to save space.

Symbolic information takes up a large amount of space in the executable file and in memory while debugging. If you do not need full symbolic information in some modules, compile those modules with the /Zd option. The /Zd option specifies that only line numbers and public symbols are included in the object file. In such modules you can view the source file and examine and modify global variables. However, type information and names with local scope are not available.

You can also limit the amount of debugging information included in your program by using precompiled headers that do not include debugging information. For more information on generating and using precompiled headers, see Chapter 1 of Programming Techniques.

For modules that are compiled with the /Zd option, all names in that module are displayed and can only be referred to using their "decorated name." The decorated name is the form of the name in the object code produced by the compiler. With full debugging information, CodeView can translate between the source form of the name and the decorated name.

Name decoration encodes additional information into a symbol's name by adding prefixes and suffixes. For example, the C compiler prefixes with an underscore the names of functions that use the C calling convention. You often see decorated names for library routines in disassembly or output from the Examine Symbols (X) command. For more information on decorated names, see »Symbol Formats« and Appendix C in C++ Language Reference.

Disable optimizations with /Od.

All Microsoft high-level-language compilers are optimizing compilers that may rearrange and remove source code. As a result, optimizations destroy the correspondence between source lines and generated machine code, and this can make debugging especially difficult. While you are debugging, you should disable optimizations with the /Od compiler option. When you finish debugging, you can compile a final version of your program with full optimizations.

Note  The /Od option does not pertain to MASM.


  Linker Options

When you are using Visual C++, you must use the Microsoft 32-Bit Executable Linker (LINK) version 1.00 or later to generate an executable file with CodeView information. If you include debugging options when you compile, the compiler automatically invokes the linker with the appropriate options. In turn, LINK runs the CVPACK utility, which compresses the symbolic information.

Link with /DEBUG.

When compiling, you can specify the compile-only option (/c) to avoid running LINK. To include debugging information when you link the object modules separately, specify the LINK /DEBUG option. LINK automatically runs CVPACK when you specify /DEBUG.

An executable file that includes debugging information can be executed from the command line like any other program. However, to minimize the size of the final version of the program, compile and link without the CodeView options.

Examples

The following command sequence assembles and links two files:

ML /C /Zi MOD1
ML /c /Zd MOD2
LINK /DEBUG MOD1 MOD2

This example produces the object file MOD1.OBJ, which contains line-number and complete symbolic information, and the object file MOD2.OBJ, which contains only line-number and public-symbol information. The object files are then linked to produce a smaller file than the file that is produced when both modules are assembled with the /Zi option.

The following commands produce a mixed-language executable file:

CL /Zi /c PROG.CPP
CL /Zi /Od /c SUB1.C
ML /c /Zi /Cx SUB2.ASM
LINK /DEBUG PROG SUB1 SUB2

You can use CodeView to trace through C, C++, and MASM source files in the same session.


  Debugging Strategies

The process of debugging a program varies from programmer to programmer and program to program. This section offers some guidelines for detecting bugs. If you are familiar with symbolic, source-level debuggers, you can skip this section.


  Identifying the Bug

If your program crashes or yields incorrect output, it has a bug. There are times, however, when a program runs correctly with some input but produces incorrect output or crashes with different input. You can assume a bug exists, but finding it may be difficult.


  Locating the Bug

You may not need to use CodeView to find bugs in simple programs. For more complex programs, however, using CodeView can save you debugging time and effort.


  Setting Breakpoints

When you debug with CodeView, you usually cycle between two activities:

•	Running a small part of the program.

•	Stopping the program to check its status.

You use breakpoints to switch between these tasks. CodeView runs your program until it reaches a breakpoint. At that time, CodeView gives you control. You can then enter CodeView commands in the Command window or use the menus and shortcut keys to proceed.

To find an error, try the following:

•	Set breakpoints around the place you think the bug might be. Execute the program with the Go command so that it runs at full speed until it reaches the area that you suspect harbors the bug. You can then execute the program step by step with the Program Step and Trace commands to see if there is a program execution error.

•	Set breakpoints when certain conditions become true. You can, for example, set a breakpoint to check a range of memory starting at the base of your program's data. If your program writes to memory using a null pointer, the breakpoint is taken, and you can see what statement or what variables within the statement are in error.


  Setting Watch Expressions

Watch expressions constantly display the values of variables in the Watch window. By setting a watch expression, you can see how a variable or an expression changes as your program executes.

Try using watch expressions as follows:

•	Set a watch expression on an important variable. Then step through a part of the program where you suspect there is a bug. When you see a variable in the Watch window take on an unexpected value, you know that there is probably a bug in the line you just executed.

•	Explore watch expressions. A bug can appear when your program builds complex data structures. Both the Watch window and the Quick Watch dialog box allow you to explore the data structure by expanding arrays and pointers. Use this feature to make sure the program creates the data structure correctly. As soon as you execute code that destroys the structure, you have probably found a bug.


  Arranging Your Display

Your display can be more effective if you arrange your windows so that they display the information you need. You will need at least one Source window. You can open a second Source window to see each assembly-language instruction.

You may also need one or more Memory windows to examine ranges of memory in various formats. You may want to change values in memory. For example, a program that does its own dynamic memory allocation may need an initialized block of memory. You can edit memory directly in the Memory window or fill the block with zeros using the Memory Fill command. If a certain value is required for a mathematical function, you can type over values displayed in the Memory window or assign the value in the Command window. If you expect a value to appear at a certain location and it does not, you can use the Memory Search command to find it.

Use the Register window to see the CPU registers and the Locals and Watch windows to keep track of changing variable values. Open the Calls menu to examine your program's stack to see what routines have been called.

You can set up CodeView's windows to display the information you want to see by using keyboard commands or the commands in the Windows menu. For example, when you press SHIFT+F5 or choose Tile from the Windows menu, CodeView arranges all open windows to fill the entire window area. When the windows are tiled, you can press ALT+F5 or choose Arrange from the Windows menu. You can also move open windows by dragging the title bar with the mouse, or choosing Move from the Windows menu and using the arrow keys.

If you prefer a more compact CodeView display, you can specify a smaller font size. For more information on changing the font CodeView uses, see »Set Line-Display Mode«.


  Setting up CodeView

The Win32s SETUP program installs all the necessary CodeView files and correctly configures CodeView for your selected environment. Make sure that all of the CodeView executable files (.EXE and .DLL files) are in a directory listed in the PATH environment variable.

The TOOLS.INI file contains the recommended settings to run CodeView. For more information on the entries in TOOLS.INI, see »Configuring CodeView with TOOLS.INI«.

The CodeView debugger uses a flexible architecture. It is made up of a main executable program, CVW.EXE, and a collection of dynamic-link libraries (DLLs). Each DLL implements an aspect of the debugging process.

The following table summarizes CodeView's component DLLs.

TOOLS.INI Entry	Component	Setting
Eval	Expression evaluator	C++
Native	Native execution model	Windows
Symbolhandler	Symbol handler	Windows
Transport	Transport layer	Local


  CodeView Files

CodeView uses several files besides CVW.EXE, as detailed below. One of these is the executable program file that you are debugging. CodeView requires one executable (.EXE) file to load for debugging.

program.EXE

An .EXE-format program to debug. CodeView assumes the .EXE extension when you specify the program to load for debugging.

source.ext

A program source file. Your program may consist of more than one source file. When CodeView needs to load a source file for a module at startup or when you step into a new module, it searches directories in the following order:

1.	The "compiled directory." This is the source-file path specified when you invoke the compiler.

2.	The directory where the program is located.

If CodeView cannot find the source file in one of these directories, it prompts you for a directory. You can enter a new directory or press ENTER to indicate that you do not want a source file to be loaded for the module. If you do not specify a source file, you can debug only in Assembly mode.

CV.HLP

Help file for CodeView. This file is required to use Help during a CodeView session. It must be in a directory listed in the HELPFILES environment variable or in the Helpfiles entry of TOOLS.INI.

TOOLS.INI

Specifies paths for CodeView .DLL files and other files that CodeView uses.

If CodeView cannot find the modules it needs in its own directory, it looks for entries in TOOLS.INI that specify paths for the modules it needs. You can include other settings for CodeView in TOOLS.INI.


  Configuring CodeView with TOOLS.INI

You can configure CodeView by specifying entries in the TOOLS.INI file. You must have separate sections in TOOLS.INI for each tool. TOOLS.INI sections begin with a "tag" — a line containing the base name of the executable file enclosed in brackets ([]). The tag must appear in column one. The CVW section tag looks like this:

[CVW32S]
;        Windows CodeView entries
. . .

In the TOOLS.INI file, a line beginning with a semicolon (;) is a comment.

CodeView looks for certain entries following the tag. Each entry may be preceded by any number of spaces, but the entire entry must fit on one line. You may want to indent each entry for readability.


  CodeView TOOLS.INI Entries

You may want to specify or change entries in TOOLS.INI to customize CodeView. Table 1.1 summarizes the TOOLS.INI entries.

Table 1.1    CodeView TOOLS.INI Entries

Entry	Description
Autostart	Commands to execute on startup
Cvdllpath	Path to CodeView .DLL files
Eval	Expression evaluator
Helpbuffer	Size of help buffer
Helpfiles	List of help files
Native	Native execution model
Printfile	Default name for print command or file
Statefileread	Read or ignore CURRENT.STS state file
Symbolhandler	Symbol handler
Transport	Transport layer


  Autostart

The Autostart entry specifies a list of Command-window commands that CodeView executes on startup.

Syntax

Autostart:command[ ;command ] ...

command

A command for CodeView to execute at startup. Separate multiple commands with a semicolon (;).

Example

The following entry automatically executes the program's run-time startup code. It specifies that CodeView always starts with the Screen Swap option off and the Trace Speed option set to fast.

Autostart:OF-;TF;Gmain


  Color

The Color entry is retained only for compatibility with previous versions of CodeView. You should set screen colors with the Colors command on the Options menu.


  Cvdllpath

The Cvdllpath entry specifies the default path for CodeView's dynamic-link libraries (DLLs). CodeView searches this path before searching the current directory or along the PATH environment variable. This entry is recommended.

Syntax

Cvdllpath:path

path

The path to the CodeView .DLL files.


  Eval

The Eval entry specifies the expression evaluator. The expression evaluator looks up symbols, parses, and evaluates expressions that you enter as arguments to CodeView commands.

Syntax

Eval:[path\]EEW0CXX.DLL extension...

path

The path to the specified expression evaluator.

extension

A source-file extension. CodeView will use the expression evaluator when it loads a source file with the .C??, .H??, .INC, or .ASM extension. Specify your source file extension in the Eval entry if it is not recognized by CodeView.

For more information about using expressions in CodeView, see »Chapter 4, Using Expressions in CodeView.«


  Helpbuffer

The Helpbuffer entry specifies the size of the buffer CodeView uses to decompress help files. You can set Helpbuffer to 0 to disable Help and maximize the amount of memory available for debugging. Otherwise, specify a value between 1 and 256.

Syntax

Helpbuffer:size

size

The number of kilobytes (K) of memory to use for decompressing help files. The default help buffer size is 24K. Specify 0 to disable help.

The following table shows values you can specify and the actual size of the buffer that is allocated:

Value Specified	Help Buffer Size
1−24	24K
25−128	128K
129−256	256K
The smallest buffer size is 24K, and the largest is 256K.


  Helpfiles

The Helpfiles entry lists help files for CodeView to load. These files are loaded before any files listed in the HELPFILES environment variable.

Syntax

Helpfiles:file[;file]...

file

A directory or help file. If you list a directory, CodeView loads all files with the .HLP extension in that directory. Separate multiple files or directories with a semicolon (;).


  Native

The Native entry specifies the native execution model. This DLL handles tasks that are specific to the machine and operating system you are using (the host) and specific to the native code (the target).

Syntax

Native:[path\]EMW0WS.DLL

path

The path to the specified native execution model.


  Printfile

The Printfile entry lists the default device name or filename used by the Print command on the File menu. This can be a printer port (for example, LPT1 or COM2) or an output file. If Printfile is omitted, CodeView prints to a file named CODEVIEW.LST in the current directory.

Syntax

Printfile:path

path

The path to the specified output file or the name of a device.


  Statefileread

The Statefileread entry tells CodeView to read or ignore the CodeView state file (CURRENT.STS) on startup. You can toggle this setting from the command line using the /TSF (Toggle State File) option. These options have no effect on writing CURRENT.STS. CodeView always saves its state on exit.

Syntax

Statefileread:[y | n]

y (yes)

CodeView reads CURRENT.STS on startup.

n (no)

CodeView ignores CURRENT.STS on startup.


  Symbolhandler

The Symbolhandler entry specifies a symbol handler. The symbol handler manages the CodeView symbol and type information.

Syntax

Symbolhandler:[path\]SHW0.DLL

path

The path to the symbol handler.


  Transport

The Transport entry specifies a transport layer. A transport layer provides the data link for communication between the host and target during debugging.

Syntax

Transport:[path\]TLWSLOC.DLL

path

The path to the specified transport layer.

Example

Transport:C:\MSVCNT\DLL\TLWSLOC.DLL


  The CodeView Command Line

When you start CVW from the command line, you can specify options. You can also specify commands from within the CodeView environment to modify these startup arguments.

Syntax

CVW [options] [program [arguments] ]

CVW @file [program [arguments] ]

options

One or more options. The CodeView options are described in the »Command-Line Options« section following.

program

Program to be debugged. Specifies the name of an executable file to be loaded by the debugger. If you specify program as a filename with no extension, CodeView searches for a file with the extension .EXE. If you do not specify a program, CodeView starts up and displays the Load dialog box, where you can specify a program and its command-line arguments.

arguments

The program's command-line arguments. All remaining text on the CodeView command line is passed to the program you are debugging as its command line. If the program you are debugging does not accept command-line arguments, you do not need to specify any. Once you've started debugging, you can change the program's command-line arguments.

@file

File of command-line arguments. You can also specify arguments in a text file. The file contains a list of arguments, one per line. An argument file lets you specify a large number of arguments without exceeding the operating-system limit on the length of a command line. This is especially useful when starting a session that uses many DLLs.

After CodeView loads its DLLs, processes the debugging information, and loads the source file, the CodeView display appears. If you do not specify a program to debug or CodeView cannot find all of its required DLLs, it prompts for the necessary files.

After starting up, CodeView is at the beginning of the program startup code, and you are ready to start debugging. At this point, you can enter an execution command (such as Trace or Program Step) to execute through the startup code to the beginning of your program.


  Exiting CodeView

To exit CodeView at any time, choose the Exit command from the File menu. You can also press ALT+F4, or type Q (for "Quit") in the Command window.


  Command-Line Options

The rest of this chapter describes each command-line option in detail, then continues with a description of how CodeView uses the CURRENT.STS file. If you do not need this information you may want to skip ahead to »Chapter 2, The CodeView Environment,« for information on CodeView's menus and windows.

Table 1.2 summarizes the CodeView command-line options.

Table 1.2    CodeView Command-Line Options

Option	Description
/2	Use two displays
/8	Use 8514 and VGA displays
/25, /43, /50	Set 25-line, 43-line, or 50-line mode
/B	Use black-and-white display
/Ccommands	Execute commands
/I[[0 | 1]]	Trap nonmaskable interrupts (NMIs) and 8259 interrupts
/Ldll	Load DLL or application symbols
/M	Disable mouse
/N[[0 | 1]]	Trap nonmaskable interrupts (NMIs)
/TSF	Read or ignore state file
The remainder of this section describes each option in detail.


  Use Two Displays

Option

/2

The /2 option permits the use of two monitors. The program display appears on the default monitor, while CodeView displays on the secondary monitor. You must have two monitors and two adapters to use the /2 option. The secondary display must be a monochrome adapter.

If you have an IBM PS/2 with an 8514 primary display and a Video Graphics Adapter (VGA) secondary display, use the /8 option.


  43-line Mode on a Secondary Display Monitor

You can run CodeView in 43-line mode on a Hercules Graphics Card Plus or compatible monochrome RamFont capable adapter. The monochrome display must be the secondary display.

To use a 43-line mode, start CodeView with the /2 and /43 options. CodeView must be started in a full screen MS-DOS session. You cannot start using 43-line mode from a windowed MS-DOS box.


  Use 8514 and VGA Displays (CVW)

Option

/8

If your system is an IBM PS/2, you can configure it with an 8514  as the primary display and a VGA as the secondary display. To use this configuration, specify the /8 (8514) option on the CVW command line.

If your VGA monitor is monochrome, it is recommended that you use the /B (black-and-white) option. The 8514 serves as the Windows screen and the VGA as the debugging screen.

By default, the debugging screen operates in 50-line mode in this configuration. If you specify the /8 option, you can specify /25 or /43 for 25-line or 43-line mode on the debugging screen.


  Set Line-Display Mode

Options

/25

/43

/50

CodeView can be run in 25-, 43-, or 50-line mode on a VGA monitor, and in 25- or 43-line mode on an EGA monitor. The mode you specify is saved in the CURRENT.STS file so that it is still in effect the next time you run CodeView.

If your monitor cannot display 43- or 50-line mode using the default font, you can use the OEM fonts supplied with CodeView. These fonts make the CodeView display more compact, leaving space to display more lines. There are two OEM font files: OEM08.FON and OEM10.FON. On a standard VGA display using the OEM10.FON font, CodeView can display 43 lines; using the OEM08.FON font it can display 50 lines.

To use these fonts, change the OEMFONTS.FON entry in your SYSTEM.INI file and restart Windows. For example, to make the CodeView display as compact as possible, change the SYSTEM.INI line

OEMFONTS.FON=VGAOEM.FON

to

OEMFONTS.FON=C:\MSVCNT\BIN\OEM08.FON

If you specify a mode that is not supported by your adapter and your monitor, CodeView displays 25 lines.

Start CVW.EXE with the /43 or /50 switch to use the extended-line modes.


  Use Black-and-White Display

Option

/B

When you start CodeView, it checks the kind of display adapter that is installed in your computer. If the debugger detects a monochrome adapter, it displays in black and white; if it finds a color adapter, it displays in color. The /B option tells CodeView to display in black and white even if it detects a color adapter.

If you use a monochrome display or laptop computer that simulates a color display, you many want to disable color. These displays may be difficult to read with CodeView's color display.

You can also customize CodeView's colors by choosing the Colors command from the Preferences dialog box in the Options menu. For more information, see »Preferences«.


  Execute Commands

Option

/Ccommands

You type commands in the CodeView Command window. You can also specify Command-window commands when you start CodeView. The /C option allows you to specify one or more CodeView Command-window commands to be executed upon startup. If you specify more than one command, you must separate each one with a semicolon (;).

If the commands contain spaces or redirection symbols (< or >), enclose the entire option in double quotation marks ("). Otherwise, the debugger interprets each argument as a separate CodeView command-line argument rather than as a Command-window command.

For complete information on CodeView Command-window commands, see »Chapter 5, CodeView Reference.«

Examples

The following example loads CVW with CALCPR as the executable file and /p TST.DAT as the program's command line:

CVW /CGWinMain CALCPR /p TST.DAT

Upon startup, CVW executes the high-level language startup code with the command GWinMain. Since no space is required between the command (G) and its argument (WinMain), there is no need to enclose the option in double quotation marks.

The next example loads CVW with CALCPR as the executable file and /p TST.DAT as the program's command line. It starts CodeView with a long list of startup commands.

CVW "/C VS&;G signal_lpd;MDA print_buffer L 20" CALCPR /p TST.DAT

CodeView starts with the Source window displaying in Mixed mode (VS&). Then it executes up to the function signal_lpd with the command G signal_lpd. Next, it dumps 20 characters starting at the address of print_buffer with the command MDA print_buffer L 20. Since some of the commands use spaces, the entire /C option is enclosed in quotation marks.

In the example below, the command directs CVW to take Command-window input from the file SCRIPT.TXT rather than from the keyboard:

CVW "/C<SCRIPT.TXT" CALCPR TST.DAT

Although the option does not include any spaces, you must enclose it in quotation marks so that the less-than symbol (<) is read by CodeView rather than by the operating-system command processor.


  Specify Interrupt Trapping

Options

/I[0 | 1]

/N[0 | 1]

The /I option tells CVW whether to handle nonmaskable-interrupt (NMI) and 8259-interrupt trapping. The /N option controls only CodeView's handling of NMIs and does not affect handling of interrupts generated by the 8259 chip. The following table summarizes the options and their effects:

Option	Effect
/I0	Trap NMIs and 8259 interrupts
/I1	Do not trap NMIs or 8259 interrupts
/N0	Trap NMIs
/N1	Do not trap NMIs
You may need to force CodeView to trap interrupts with /I0 on computers that CodeView does not recognize as IBM compatible. Using /I0 enables the CTRL+C and CTRL+BREAK interrupts on such computers.


  Load Other Files

Options

/L[path\]dll

/L[path\]exe

To load symbolic information from a dynamic-link library (DLL) or from another application, use the /L option when you start CodeView. Specify /L for each DLL or application that you want to debug.

When you place a module in a DLL, neither code nor debugging information for that module is stored in an application executable (.EXE) file. Instead, the code and symbols are stored in the library and are not linked to the main program until run time. The same is true for symbols in another application running with Windows. Thus, CVW needs to search the DLL or other application for symbolic information. Because the debugger does not automatically know which libraries to look for, use the /L option to preload the symbolic information.

Example

The following command starts CodeView for Windows:

CVW /LC:\SOURCE\PRIORITY.DLL /LC:\SOURCE\CAPPARSE.DLL PRINTSYS

CVW is used to debug the program PRINTSYS.EXE. CVW loads symbolic information for the dynamic-link libraries PRIORITY.DLL and CAPPARSE.DLL, as well as the file PRINTSYS.EXE.


  Disable Mouse

Option

/M

If you have a mouse installed on your system, you can tell CodeView to ignore it by using the /M option. You may need to use this option if you are debugging a program that uses the mouse and there is a usage conflict between the program and CodeView.


  Nonmaskable-Interrupt Trapping

Option

/N

For information on the /N option, see »Specify Interrupt Trapping«.


  Toggle State-File Reading

Option

/TSF

The Toggle State File (/TSF) option either reads or ignores CodeView's state file and color files, depending on the Statefileread entry in the CodeView sections of TOOLS.INI. The /TSF option reverses the effect of the Statefileread entry. The Statefileread entry is set to yes by default.

These options have no effect on writing the files. CodeView always saves its state on exit.

The effect of different combinations of Statefileread and /TSF are summarized in the following table:

/TSF	Statefileread	CodeView Result
Specified	y (or omitted)	Do not read files
Specified	n	Read files
Not specified	y (or omitted)	Read files
Not specified	n	Do not read files
The state file is CURRENT.STS. The color file is CLRFILE.CVW.


  The CURRENT.STS State File

CodeView saves settings and state information in the CURRENT.STS file. The file contains information about the current state of the environment. When you restart CodeView, it reads CURRENT.STS and restores its previous state. CodeView uses additional files to save your most recent color settings in the CLRFILE.CVW file.

CodeView searches for these files in the directory specified by the INIT environment variable. If no INIT environment variable exists, CodeView searches the current directory. If the state file is not found, new CURRENT.STS and CLRFILE.CVW files are created in the INIT directory, or in the current directory if no INIT variable is set.

Information about CodeView stored in CURRENT.STS includes:

•	Window layout

•	Breakpoints

•	Watch expressions

•	Source, Locals, and Memory display options

•	Global CodeView options such as case sensitivity, screen-exchange method, radix, and expression evaluator

•	Exception handling state.

You can set CodeView options in TOOLS.INI or on the command line and then modify them during a session. They are saved in CURRENT.STS when you exit CodeView. During each session, CodeView sets these features in the following order:

1.	From TOOLS.INI

2.	From CURRENT.STS

3.	From the CodeView command line

4.	During the debugging session

The following items are not saved between sessions:

•	The current location EIP.

•	The expansion state of watch expressions.

All watch expressions and their format specifiers are restored, but they appear in their contracted state.

•	Absolute-address breakpoints.

Breakpoints set at an absolute address are not saved. CodeView saves breakpoints only at specific line numbers or symbols.

•	Memory window addresses.

Each memory window is restored with its display type and options, but CodeView does not save the starting address.


  Chapter 2  The CodeView Environment

CodeView provides a powerful environment in which to debug programs and dynamic-link libraries (DLLs). Its rich set of commands helps you track program execution and changing data values.

In CodeView you can "point-and-click" your source code to start and stop execution or modify bytes in memory. You can also use more traditional keyboard commands. You can use function keys to execute common commands, such as tracing and stepping through a program. When you quit CodeView, it remembers your breakpoints, window arrangement, watch expressions, and option settings.

This chapter describes the CodeView display, and shows you how to use the menu commands and how to interact with the different types of windows.


  The CodeView Display

The CodeView screen is divided into three parts:

•	The menu bar across the top of the screen.

•	The window area between the menu bar and status bar.

•	The removable status bar across the bottom of the screen.

»Figure 2.1« shows a typical CodeView screen with several open windows. The figure shows selected elements of the display, which are described in the sections that follow.


  The Menu Bar

The menu bar displays the names of the CodeView menus. To open a menu, use one of the following methods:

•	Click a menu name with the mouse.

•	Press ALT plus the menu name's highlighted letter.

•	Press and release ALT, use the arrow keys to select a menu, and then press down arrow or enter to open it.

Each command in a menu has a highlighted letter. To choose that command, press the highlighted letter. Many commands also list a shortcut key that you can press at any time instead of opening a menu and choosing a command.

A command that does not apply to a particular situation is dimmed on the menu. When you press the corresponding shortcut key, no action is performed.


  The Window Area

Most of your debugging takes place in the window area, where you can open, close, move, size, and overlap the various types of CodeView windows. Although each window serves a different function for debugging, the windows have a number of common features. The Minimize, Maximize, and Restore boxes work in the same way as they do in Microsoft Windows. The Close box, clicked once, closes a CodeView window; similarly, the Control-menu box, double-clicked, closes a Windows-based document or application. The scroll features and Move bar also work the same as in Windows.

»Figure 2.2« shows a CodeView window. The table that follows it describes each of a window's elements.

Name	Description
Window border	Moves window. Drag to move the window.
Close box	Closes the window. Click to close the window.
Window number	Identifies window. Press ALT+number to move to that window.
Window title	Identifies window. Active window title is highlighted. Double- click to maximize window.
Minimize box	Shrinks window to an icon. Click to minimize the window.
Maximize/Restore box	Enlarges window to maximum size or restores window to its original size. Click to maximize or restore the window.
Scroll up arrow	Scrolls up by lines. Click to scroll up.
Page up area	Scrolls up by pages. Click to page up.
Scroll box	Indicates relative position in the file. Drag to change position.
Page down area	Scrolls down by pages. Click to page down.
Scroll down arrow	Scrolls down by lines. Click to scroll down.
Size area	Sizes window. Drag to size the window.
Move bar	Moves window. Drag to move the window.
Only one window can be active at a time. You always use the currently active window, which appears with a highlighted border and a shadow on the screen. The text cursor always appears in the active window.


  The Status Bar

The status bar, which occupies the bottom line of the screen, contains information about the active window. It usually includes a row of buttons you can click to execute commands. You can also use the shortcut keys shown on the buttons.

To remove the status bar and gain an extra line for the window area, choose Status Bar from the Options menu, or type the OA −  command in the Command window. You must resize a window to take advantage of the extra line. To restore the status bar, choose Status Bar from the Options menu, or type the OA+ command in the Command window. For more information on this command, see the »Options« command.


  CodeView Windows

CodeView windows organize and display information about your program. This section describes each CodeView window, the information you can display, and how you can change information and enter commands in the Command window. It also explains how to move among the windows and manipulate them.


  How to Use CodeView Windows

Each CodeView window has a different function and operates independently of the others. Only one window can be active at a time. Commands you choose from the menus or by using shortcut keys affect the active window. The following list briefly describes each window's function:

Source

Displays the source or assembly code for the program you are debugging. You can open a second Source window to view an include file or any ASCII text file.

Watch

Displays the values of variables and expressions you select. You can modify the value of watched variables, browse the contents of structures and arrays, and follow pointers through memory.

Command

Accepts debugging commands from the keyboard. CodeView displays the results, including error messages, in the Command window. When you enter a command in a dialog box, CodeView displays any resulting errors in a pop-up window.

Locals

Lists the values of all variables local to the current scope. You can set Locals window options to show other scopes. You can modify the values of variables displayed in the Locals window.

Register

Displays the contents of the machine's registers and flags. You can directly edit the values in the registers, and you can toggle flags with a single keystroke or mouse click.

8087

Displays the registers of the hardware math coprocessor or the software emulator.

Memory

Displays the contents of memory. You can open a second Memory window to view a different section of memory. You can set Memory window options to select the format and address of displayed memory. You can directly change the displayed memory by typing in the Memory window.

Help

Displays the CodeView Help system.

The first time you run CodeView, it displays three windows. The Locals window is at the top, the Source window fills the middle of the screen, and the Command window is at the bottom. The Locals window is empty until you trace into the main part of the program. To open a window, choose a window from the Windows menu. Some operations, such as setting a watch expression or requesting help, open the appropriate window automatically.

You can open or close any CodeView window. However, at least one Source window must remain open.

When you close a CodeView window you lose the state of the window. However, if you minimize a CodeView window the state information is retained. The following table describes state information that is lost when a CodeView window is closed.

Window Closed	State Information Lost
Command Window	Previous commands and results
Watch and Locals Window	Expansion state of structures and classes
8087, Register, and Memory Window	Undo information and hightlighting
You can change how CodeView displays information in the Source, Memory, and Locals windows. Choose the appropriate window options command from the Options menu. When the cursor is in one of these windows, you can press CTRL+O to display that window's options dialog box.

CodeView automatically updates the windows as you debug your program. To interact with a particular window (such as entering a command or modifying a variable), you must select it. The selected window is the "active" window. The active window is marked in the following ways:

•	The window's frame is highlighted.

•	The window casts a shadow over other windows.

•	The cursor appears in the window.

•	The horizontal and vertical scroll bars move to the window.

To make a window active, click anywhere in the window or in the window frame. You can also press F6 or SHIFT+F6 to cycle through the open windows, making each one active in turn. You can also choose a window from the Windows menu or press ALT plus a window number. In addition, some CodeView commands make a certain window active.

When you exit CodeView, it records which windows are open and how they are positioned, along with their display options. These settings become the default the next time you run CodeView.


  Moving Around in CodeView Windows

To move the cursor to a specific location in a window, click that location. You can also use the keyboard to move the cursor and navigate the windows, as shown in Table 2.1.

Table 2.1    Moving Around with the Keyboard

Action	Keyboard
Move cursor up, down, left, and right	UP ARROW, DOWN ARROW, LEFT ARROW, RIGHT ARROW
Move cursor left and right by words	CTRL+LEFT, CTRL+RIGHT
Move cursor to beginning of line	HOME
Move cursor to end of line	END
Page up and down	PAGE UP, PAGE DOWN
Page left and right	CTRL+PAGE UP, CTRL+PAGE DOWN
Move cursor to beginning of window	CTRL+HOME
Move cursor to end of window	CTRL+END
Move to next window	F6
Move to previous window	SHIFT+F6
Restore window	CTRL+F5
Move window	CTRL+F7
Size window	CTRL+F8
Minimize window	CTRL+F9
Maximize window	CTRL+F10
Close window	CTRL+F4
Tile windows	SHIFT+F5
Arrange windows	ALT+F5


  The Source Windows

The Source windows display the source code. You can open a second Source window to view other source files, header files, the same source file at a different location, or any ASCII text file. To open a Source window, use one of the following methods:

•	From the Windows menu, choose Source 1 or Source 2.

•	In the Command window, type the View Source (VS) command.

•	Press ALT+3 to open Source window 1.

•	Press ALT+4 to open Source window 2.

You cannot edit source code in CodeView, but you can temporarily modify the machine code in memory using the Assemble (A) command. For more information, see the »Assemble« command.

Source windows can display three different views of your program code in three different modes:

•	Source mode shows your source file with numbered lines.

•	Assembly mode shows a disassembly of your program's machine code.

•	Mixed mode shows each numbered source line followed by a disassembly of the machine code for each line.

To cycle through the display formats, click the <F3=S1 Fmt> or <F3=S2 Fmt> buttons on the status bar, or press F3. Pressing CTRL+F3 displays the cycle in reverse order.

CodeView automatically switches to Assembly mode when you trace into routines for which no source is available, such as library or system code. The debugger switches back to the original display mode when you continue tracing into code for which source code is available.

Invalid or unreadable source code is represented by question marks.

For more information on setting display modes, see the »View Source« command. Detailed information about the Source window display options is also in this section.


  The Watch Window

The Watch window displays the value of program variables or the value of expressions you specify in a high-level language. For each expression or variable, you can change the format of the data that is displayed. You can expand aggregate variables, such as structures and arrays, to show all the elements of an aggregate and contract them to save space in the Watch window. You can follow chains of pointers to display and help debug more complex structures, such as linked lists or binary trees.

To open a Watch window, use one of the following methods:

•	From the Windows menu, choose Watch.

•	In the Command window, type the Add Watch (W?) command followed by the variable or expression name.

•	Press ALT+2.

To add expressions to the Watch window, use the Add Watch command from the Data menu or the Quick Watch dialog box (SHIFT+F9). You can also add watch expressions using the Add Watch (W?) and Quick Watch (??) commands.

Note  Do not edit a string in the Watch window.

Type new values for variables in the Watch window.

To change the value of any variable displayed in the Watch window, move the cursor to the value, delete the old value, and type the new value. To change the format in which a variable is displayed or to specify a new format, move the cursor to the end of the variable name and type a new format specifier.

To toggle between insert and overtype modes, press the INS key.

For information on expanding and contracting aggregate types and following pointers, see the »Quick Watch« command. For detailed information on specifying and using watch expressions, see »CodeView Expressions«, and »Chapter 4, Using Expressions in CodeView.«


  The Command Window

You type CodeView commands in the Command window to execute code, set breakpoints, and perform other debugging tasks. You can use the menus, mouse, and keyboard for many debugging tasks, but you can use some CodeView commands only in the Command window.

When you first start the debugger, the Command window is active, and the cursor is at the CodeView prompt (>). To return to the Command window after you make another window active, click the Command window, or press ALT+9.

Using the Command window is similar to using an operating-system prompt, except that you can scroll back to view previous results and edit or reuse previous commands or parts of commands.


  How to Enter Commands and Arguments

You enter commands in the Command window at the CodeView prompt when the Command window is active. Type the command followed by any arguments and press ENTER. Some commands, such as the Assemble (A) command, prompt for an indefinite series of arguments until you enter an empty response. CodeView may display errors, warnings, or other messages in response to commands you enter in the Command window.

You can type commands when the Source window or the Command window is active.

If a Source window is active and the Command window is open, you can still type Command-window commands. When you begin typing, the cursor moves to the Command window and remains there until you press ENTER. The cursor returns to the Source window, and CodeView executes the command. If you have begun typing but do not want to execute a command, press ESC to clear the text and place the cursor at the prompt. After you press ESC, the Command window becomes active.


  Command Format

The format for CodeView commands is:

command [arguments] [;command2]

The command is the command name, and arguments are control options or expressions that represent values or addresses to be used by the command. The first argument can usually be placed immediately after command with no intervening spaces. Arguments may be separated by spaces or commas, depending on the command. For more information, see »Chapter 5, CodeView Reference.«

To specify additional commands on the same line, separate each command with a semicolon (;).

Commands are always one, two, or three characters long. They are not case sensitive, so you can use any combination of uppercase and lowercase letters. Arguments to commands may be case sensitive, depending on the command.

Example

The following example shows three commands separated by semicolons:

>MDB 809BC000 L 10 ; G .178 ; MDB 809BC000 L 10

The first command (MDB 809BC000 L 10) dumps 10 bytes of memory starting at address 809BC000. The second command (G .178) executes the program up to line 178 in the current module. The third command is the same as the first and is used to see if the executed code changed memory.

Example

This example demonstrates the Comment (*) command:

>U extract_velocity    ;* Unassemble at this routine

The first command is the Unassemble (U) command, given the argument extract_velocity. The next command is the Comment command. Comment commands are used throughout the CodeView examples in this book.


  How to Copy Text for Use with Commands

Copy and paste text instead of retyping.

Text that appears in any CodeView window can be copied and used in a command. For example, an address that is displayed in a Memory window or the Register window can be copied and used in a breakpoint command.

To copy and use text:

1.	Select the text with the mouse or the keyboard.

To select text with the mouse, move the mouse pointer to the beginning of the desired text, hold down the left mouse button, and drag the mouse. When you have selected the desired text, release the button.

To select text with the keyboard, move the cursor to the desired text, hold down the SHIFT key, and move the cursor with the ARROW keys.

2.	Choose the Copy command from the Edit menu or press CTRL+INS.

3.	Move the cursor to the location where you want to use the text and choose the Paste command from the Edit menu, or press SHIFT+INS.

4.	Edit the command if desired, and press ENTER to execute the command.

Because all input to CodeView windows is line oriented, you cannot copy more than a single line. If you select more than a single line, the Copy command in the Edit menu is unavailable, and CTRL+INS has no effect.

When editing a command, you can toggle between insert and overtype modes by pressing the INS key.


  How to Use the Command Buffer

CodeView keeps the last several screens of commands and output in the Command window. You can scroll the Command window to view the commands you entered earlier in the session. This is particularly useful for viewing the output from commands, such as Memory Dump (MD) or Examine Symbols (X), whose output exceeds the size of the window.

Press TAB to visit previous commands.

The TAB key provides a convenient way to move among the previously entered commands. Press TAB to move the cursor to the beginning of the next command, and press SHIFT+TAB to move to the beginning of the previous command. If the cursor is at the beginning or the end of the command buffer, the cursor wraps around to the other end. To return to the current command prompt, you can press CTRL+END or press TAB repeatedly.

You can also reuse any command that appears in the Command window without copying and pasting. Move the cursor to the command or press TAB, edit the command if desired, and press ENTER to execute it. When you press ENTER, CodeView restores the original command, copies the new command to the current prompt, and executes the command. If you make a mistake while editing a command, press ESC to restore the line.


  The Locals Window

You can enter new values for variables in the Locals window.

The Locals window shows all local variables in the current scope. The Locals window is similar to the Watch window, except that the variables that are displayed change as the local scope changes. A variable in the Locals window is always shown in its default type format. When you edit in the Locals window, you can toggle between insert and overtype modes by pressing the INS key.

You can expand and contract pointers, structures, and arrays the same way you do in the Watch window. You can also change the values of the variables as in the Watch window.

The keyboard shortcut to open or switch to the Locals window is ALT+1.

You can see the local variables of each active routine in the stack by selecting the routine from the Calls menu. For more information on this feature, see »The Calls Menu«.

By default, the Locals window shows the addresses of the local variables on the left side of the window. You can turn this address display on or off using the Options (O) command. For more information, see the »Options« command.


  The Register Window

The Register window displays the names and current values of the CPU registers and flags. You can change the value of any register or flag directly in the Register window.

To open the Register window, choose Register from the Windows menu, or press ALT+7 or F2. You can also view and modify registers by using the Register (R) command. For more information, see the »Register« command.

When a register value changes after a program step or trace, CodeView highlights the new value so you can see how your program uses the CPU registers. Depending on the current instruction, the Register window also displays the effective address at the bottom of the window. This display shows the location of an operand in physical memory and its value.

If your program has taken an unexpected turn, you may be able to compensate for the problem and continue debugging if you change the value of a register or a flag. You can change a flag value before a dump or looping instruction to test a different branch of code, for example. You can change the instruction pointer EIP to jump to any code in your program or to execute code you have assembled elsewhere in memory.

To change the value of any register, move the cursor to the register value you want to change and overtype the old value with the new value. The cursor automatically moves to the next register.

Although you cannot change the value of the flag register numerically in the Register window, you can conveniently toggle the values of each flag using either the mouse or the keyboard:

•	To toggle a flag with the mouse, double-click the flag.

•	To toggle a flag using the keyboard, move the cursor to the flag and press any key except ENTER, TAB, or ESC. After toggling a flag, CodeView moves the cursor to the next flag.

To restore the values of flags or registers that you have changed, choose Undo from the Edit menu or press ALT+BACKSPACE. You can undo all edits up to the last execution of a child process. If you happen to lose the cursor somewhere in the Register window, press TAB or SHIFT+TAB. The TAB key moves the cursor to the next register or flag that can be changed.


  The 8087 Window

The 8087 window displays the current status of the math coprocessor's registers and flags. If you are debugging a program that uses the software-emulated coprocessor, the emulated registers are displayed. To open the 8087 window, choose 8087 from the Windows menu or press ALT+8.

The display in the 8087 window is the same as the display produced by the 8087 (7) command, except that the window is continually updated to show the current status of the math coprocessor. For more information about the display, see the »8087« command.

If your program uses floating-point libraries provided by several Microsoft languages, or if your program does not use floating-point arithmetic, the 8087 window and 8087 command display the message:

Floating point not loaded

CodeView displays this message until at least one floating-point instruction has been executed.


  The Memory Windows

Memory windows display memory in a number of formats. CodeView allows two Memory windows to be open at the same time. You can open a Memory window in several ways:

•	From the Windows menu, choose Memory 1 or Memory 2.

•	From the Options menu, choose Memory1 Window when no Memory windows are open.

•	In the Command window, enter the View Memory (VM) command.

•	At the keyboard, press ALT+5 or ALT+6 for Memory 1 or Memory 2, respectively.

By default, memory is displayed as bytes or as the last type specified by a View Memory (VM) command. The byte display shows hexadecimal byte values followed by an ASCII representation of those byte values. For values that are outside the range of printable ASCII characters (decimal 32 to 127), CodeView displays the OEM character set equivalent, or a period (.) for zero.


  How to Change Memory Display Format

It is not always convenient to view memory as byte values. If an area of memory contains character strings or floating-point values, you might prefer to view them in a directly readable form.

To change the display format of a Memory window, choose Memory1 Window or Memory2 Window from the Options menu. CodeView displays a dialog box where you can choose from a variety of display options. When the cursor is in a Memory window, you can press CTRL+O to display the corresponding Memory Window

Options dialog box. You can also set memory display options using the View Memory (VM) command. For detailed information about the display options, see »View Memory«.

To cycle through the display formats, click the <Sh+F3=M1 Fmt> button or the <Sh+F3=M2 Fmt> button on the status bar, or press SHIFT+F3. Pressing CTRL+SHIFT+F3 displays the cycle in reverse order.

When you first open the Memory window, it displays memory starting at address 0x00000000. To change the starting address, use one of the commands that set Memory window options. You can specify the starting address or enter an expression to use as the starting address.

Unreadable memory is represented as a question mark.

You can also type over the addresses shown in the left column of the Memory window to change the displayed addresses. Move the cursor to an address in the window, or repeatedly press TAB until the cursor is on an address, and type a new address.


  How to Change Memory Directly

To change the values in memory, overtype the value you want to change. To move quickly from field to field in the Memory window, press TAB or SHIFT+TAB. You can change memory by entering new values for the format that is displayed or by typing over the raw bytes in the window. CodeView ignores the input if you press a key that does not make sense for the current format (for example, if you type the letter X in anything but ASCII format).

To undo a change to memory, choose Undo from the Edit menu, or press ALT+BACKSPACE.


  How to View Memory at a Dynamic Address

Live expressions make it easy for you to watch a dynamic view of an array or pointer in the Memory window. "Live" means that the starting address of memory in the window changes to reflect the current value of an address expression.

To create a live expression, choose the Memory1 Window or Memory2 Window command from the Options menu. In the Memory Window Options dialog box, type in an address expression, then turn on the Re-evaluate Expression Always (live) option.

It is usually more convenient to view an item in the Watch window than in the Memory window. However, some items are more easily viewed using live expressions. For example, you can examine what is currently on top of the stack by entering ESP as the live expression.


  The Help Window

In CodeView, you can request Help:

•	From the Help menu.

•	By pressing F1 when the cursor is on the keyword, menu, or dialog box for which you want Help.

•	By clicking the right mouse button on a Help keyword.

•	Using the Help (H) command.

•	By choosing Help from the Windows menu. You can also press ALT+0 for Help on CodeView windows.

The Help window is displayed whenever you request Help for CodeView.


  CodeView Menus

Many commands that you are likely to use frequently are in the CodeView menus. This section describes the menus and the commands or options in each menu.


  The File Menu

The File menu contains commands to load source files and other ASCII text files into the Source window, print from the active window, and end the debugging session.

The following table summarizes the commands on the File menu.

Command	Purpose
Open Source	Opens a source, include, or other text file
Open Module	Opens a source file for a module in the program
Print	Prints all or part of the active window
Exit	Exits CodeView


  Open Source

The Open Source command displays the Open Source File dialog box. You can select the name of the source file, include file, or other text file to display in the active Source window.


  Open Module

The Open Module command displays the Open Module dialog box. This dialog box provides an easy way to load the source file for any module in your program. Choose All in the Exe/Dll field to display a list of all source files used by your program. Choose a specific .EXE or .DLL in the Exe/Dll field to display a list of modules used by the .EXE or .DLL. Only those modules that include line-number or full symbolic information are listed.

CodeView displays the source file you choose in the active Source window.


  Print

The Print command displays the Print dialog box, which offers several options to write information in the active window to a device or a file. You can print text in the active window in the following ways:

•	Window view, which prints text that currently appears in the active window.

•	Complete window contents, which prints the contents of the active window, including what has scrolled out of the window.

To print to a file, specify a filename in the dialog box. To append the printed text to the end of the file, select Append. To overwrite a file that already exists, select Overwrite. If you specify a device instead of a file, you can choose either Append or Overwrite.

To print directly to a printer, specify the name of the printer port, such as LPT1 or COM2. You must specify a filename or a device name. CodeView reports an error if you omit a name.


  Exit

The Exit command saves the current CodeView environment and returns to the program that called CodeView. CodeView saves the window arrangement, watch expressions, option settings, and most breakpoints in the state file, CURRENT.STS. It saves current color settings in CLRFILE.CVW.

When you start the debugger at a later time, CodeView restores these settings. To prevent CodeView from restoring the information it stores in CURRENT.STS, start the debugger with the /TSF option, or use the Statefileread entry in your TOOLS.INI file.


  The Edit Menu

The Edit menu contains commands to undo changes to a window's fields, copy selected text to the CodeView clipboard (not the Windows clipboard), and paste the contents of the clipboard into a window. For more details on editing in CodeView's windows, see »CodeView Windows«.

The following table summarizes the commands on the Edit menu.

Command	Purpose
Undo	Reverses the last editing change
Copy	Copies selected text to the clipboard
Paste	Inserts the contents of the clipboard at the cursor


  Undo

The Undo command (ALT+BACKSPACE) reverses the last editing action.


  Copy

The Copy command (CTRL+INS) copies selected text to the CodeView clipboard. Because input to CodeView is restricted to single lines, you can copy only a single line of text. If you select more than a single line of text, the Copy command is disabled and pressing CTRL+INS has no effect.


  Paste

The Paste command (SHIFT+INS) inserts text from the CodeView clipboard at the cursor in the Command window. The Command window must have focus before text can be pasted into it.


  The Search Menu

The Search menu provides commands to find strings and regular expressions in source files and to locate the definitions of labels and routines.

The following table summarizes the commands on the Search menu.

Command	Purpose
Find	Searches for a text string or pattern in the source file
Selected Text	Searches for the selected text in the source file
Repeat Last Find	Repeats the last text search
Label/Function	Searches for a label or function definition in the program


  Find

The Find command (CRTL+F) displays the Find dialog box. In the Find What text box, type the text or pattern you want to find. You can also select text in a window and then choose Find. The text you selected is shown in the dialog box.

You can select options in the dialog box to modify the way CodeView searches for text. The following options are available:

Whole Word

CodeView matches the text only when it occurs as a word by itself. For example, when you search for the pattern print with the Whole Word option, CodeView finds print("eeep"), but not error_print("eeep").

Match Case

CodeView matches the text when each letter in the pattern has the same case as the source file. For example, the pattern fish matches fish, but not Fish.

Regular Expression

CodeView treats the text as a regular expression. Regular expressions provide a powerful way to specify patterns that match several different sections of text.

To search for a regular expression in the active Source window using the Command window, you can type the Search (/) command followed by the string. CodeView searches the file starting at the current position. CodeView places the cursor on the next occurrence of the search pattern. If the end of the file is reached without finding a match, CodeView wraps around and continues searching from the beginning of the file.

CodeView uses a subset of the UNIX regular-expression syntax. You can use regular expressions as arguments to the Search (/) command and Examine Symbols (X) command. Table 2.2 summarizes CodeView regular expressions.

Table 2.2 CodeView Regular Expressions

Character	Syntax	Meaning
Backslash	\c	Matches a literal character c. (Escape)
Period	.	Matches any single character. (Wildcard)
Caret	^	Matches the beginning of a line. The caret must appear at the beginning of the pattern.
Dollar sign	$	Matches the end of a line. The dollar sign must appear at the end of the pattern.
Asterisk	c*	Matches zero or more occurrences of c.
Brackets	[...]	Matches any one character in the set of the characters within the brackets.
Within the brackets, you can specify a negated set and ranges of characters by using the following notation:

Character	Syntax	Meaning
Dash	−	Specifies a range of characters in the ASCII order between the characters on either side, inclusive. For example, [a-z] matches the lowercase alphabet, and [a-z,A-Z] matches any letter in the alphabet.
Caret	^	Matches any one character not within the brackets. The caret must be the first character within the brackets. For example, [^0-9] matches any character except a digit.


  Selected Text

The Selected Text command (CTRL+\) searches for the next occurrence of the selected text in the Source window.


  Repeat Last Find

The Repeat Last Find command searches for the next occurrence of the search pattern, including search options, you last specified. To use this command press CTRL+R.


  Label/Function

The Label/Function command lets you search the program's symbolic information for the definition of a label or routine. When you choose Label/Function, the Find Label/Function dialog box appears. The currently selected text or the word at the cursor comes up in the Label/Function Name text box. You can search for this name or type in a different label or routine name.

When you choose OK, CodeView searches the symbolic information in the program for the name. When the label or routine name is found, CodeView positions the cursor at the name in the source file.

To view the current program location after searching, choose the first item in the Calls menu or type the Current Location (.) command in the Command window.


  The Run Menu

The Run menu consists of commands to restart the program, animate the program in slow motion, change the program's arguments, or load a new program.

The following table summarizes the commands on the Run menu.

Command	Purpose
Restart	Restarts the program
Set Runtime Arguments	Changes the program's run-time arguments and restarts the program
Animate	Executes the program in slow motion
Load	Loads additional symbols to debug and set run-time arguments
Go	Starts execution at the current address
Step	Executes a single line of code
Trace	Executes a single line of code, stepping into functions
Go To Cursor	Executes the program forward to the cursor location
Stop After Return	Executes the return of the current function and halts


  Restart

The Restart command resets execution to start at the beginning of the program. After you issue the command, CodeView:

•	Initializes all program variables.

•	Resets the pass counts for all breakpoints.

•	Preserves existing breakpoints, watch expressions, and the program's command-line arguments.

You can use Restart any time after execution stops: at a breakpoint, while stepping or tracing, or when your program ends. If your program redefines interrupts, Restart may not work correctly because it does not execute any cleanup or exit-list code in the program. If your program requires this code to be executed, let the program run to the end before restarting, or use the Display Expression (?) command in the Command window to call the cleanup routines. For more information on calling program routines, see »Display Expression«.


  Set Runtime Arguments

The Set Runtime Arguments command lets you change your program's command-line arguments. When you set new arguments, CodeView restarts the program.


  Animate

The Animate command executes your program in slow motion. CodeView highlights each statement in the Source window as your program executes. This allows you to see the flow of execution. To stop animation, press any key.

You can set the animation speed with the Trace Speed command from the Options menu or with the Trace Speed (T) Command-window command.


  Load

The Load command displays the Load dialog box, which you can use to:

•	Load symbols for executable (.EXE or .DLL) files.

•	Specify the program's command-line arguments when it is loaded.

Loading Programs or DLLs

To load program or DLL symbols into the debugger, type a filename in the File to Debug text box, or use the mouse or keyboard to select a file from the File List box. Use the Drives/Dirs list box to change to a different drive or directory.

Set Command-Line Arguments

Use the Arguments text box to change the command-line arguments to the program you are debugging or to set entirely new arguments. Type the arguments to your program as you would on the command line.


  Go

The Go command starts execution at the current address. CodeView executes the program until you interrupt it, until it reaches a breakpoint, or until the program terminates.

Another way to start execution is to press F5, type G in the Command window, or click the Go button in the status bar. Clicking the Go button with the right mouse button turns off screen flipping for the duration of the Go command.


  Step

The Step command tells CodeView to execute a single instruction or line of source code depending on the Source window display mode. (In the Command window, the same command is issued by typing P for Program Step.) If a line contains more than one executable statement, CodeView executes all the statements on the line. The next line to be executed is displayed in reverse video.

Step displays and executes each line of the current function but does not step into function calls. If this command is used when you reach a function call, the function is executed without stepping through the function instructions.

Another way to step through your program is to press F10, type P (for Program Step) in the command Window, or click the Step button in the status bar. Clicking the Step button with the right mouse button turns off screen flipping during execution.


  Trace

The Trace command is similar to the Step command, except it follows execution into every function for which CodeView has symbolic information. Each line of the function is a separate step. If CodeView does not have symbolic information for a function, the function runs in a single step.

Another way to trace through your program is to press F8, type T in the Command window, or click the Trace button in the status bar. Clicking the Trace button with the right mouse button disables screen flipping during execution.


  Go To Cursor

Choosing Go To Cursor executes your program to the location of the hardware cursor in the Source window. Execution will halt at a breakpoint or termination encountered before the cursor location. You can use this command to move quickly through your program by clicking a line you want to execute to and issuing a Go To Cursor command. The effect is similar to double-clicking the left mouse button on a source line and issuing a Go command, except that the Go To Cursor command doesn't set a breakpoint on the line.

This command has an effect only if there is a path of execution from the current program location to the location of the cursor.

Another way to execute to the cursor is to press F7, or type G! in the Command window, or click the right mouse button on the source line.


  Stop After Return

If you want to execute out of a function you have traced into, choose Stop After Return. Your program will execute the return of the current function and then halt. This can be useful if you trace into a function by mistake.

Another way to issue a Stop After Return command is to press SHIFT+F7 or click the After Return button on the status bar. Clicking the Stop After Return button with the right mouse button disables screen flipping during execution.


  The Data Menu

The Data menu provides commands to add and delete watch expressions and breakpoints. Watch expressions allow you to observe how variables change as your program executes and also to expand arrays and dereference pointers. Breakpoints allow you to stop execution of your program to check the values of your variables, determine execution flow, and change how your program executes.

For more information about watch expressions, see »Chapter 4, Using Expressions in CodeView,« and the »Add Watch Expression« command.

The following table summarizes the commands on the Data menu.

Command	Purpose
Add Watch	Adds an expression to the Watch window
Delete Watch	Deletes an expression from the Watch window
Quick Watch	Displays a quick view of a variable or expression
Breakpoints	Sets, modifies, or removes a breakpoint in the program


  Add Watch

The Add Watch command (CTRL+W) displays the Add Watch dialog box, which shows the selected text or the word at the cursor in the Expression text box. You can enter a different expression or add a format specifier to the expression. When you choose OK, the expression is added to the end of the Watch window.


  Delete Watch

The Delete Watch command (CTRL+U) displays the Delete Watch dialog box, which displays a list of the watch expressions in the Watch window. Select the expression you want to delete from the list and choose OK. Click the Clear All button to remove all expressions from the Watch window.

You can also delete expressions directly from the Watch window. Use the mouse or the cursor keys to move the cursor to the expression you want removed, and press CTRL+Y.


  Quick Watch

The Quick Watch command (SHIFT+F9) displays the Quick Watch dialog box, which shows the variable at the cursor position or the selected expression. The Quick Watch dialog box is similar to the Watch window. However, you mainly use Quick Watch for a quick exploration of the current values in an array or a pointer-based data structure, rather than as a method to constantly display the values.

The Quick Watch dialog box automatically expands structures, arrays, and pointers to their first level. You can expand or contract an element just as you can in the Watch window. If the expanded item needs more lines than the Quick Watch dialog box can display, you can scroll the view up and down.

Choose the Add Watch button to add a Quick Watch item to the Watch window. Expanded items appear in the Watch window as they are displayed in the Quick Watch dialog box.

You can also display the Quick Watch dialog box by typing ?? in the Command window.

For complete information on using the Quick Watch dialog box, see the »Quick Watch« command.


  Breakpoints

The Breakpoints command (CTRL+B) displays the Breakpoints dialog box, which allows you to set, modify, and delete breakpoints. To change the list of breakpoints in a program, follow some or all of the following steps:

1.	Select a breakpoint from the breakpoint list in the Breakpoints dialog box.

2.	Set the breakpoint type and options.

3.	Use one of the command buttons to change the breakpoint list.

Breakpoint Options

All breakpoint options can be set from the Command window or the Breakpoints dialog box. The following list describes options available in the Breakpoints dialog box:

Types

You can specify the type of breakpoint as an option, but you must choose one of five types. The following types of breakpoint are provided:

•	Break at Location

This is the simplest type of breakpoint and is the default setting. You specify an address or a line number where you want execution to pause. To specify a line number, precede it with a period (.); otherwise, CodeView will interpret it as an address. When your program's execution reaches the breakpoint location, your program stops temporarily, and you can enter CodeView commands.

•	Break at Location if Expression is True

You specify a location and an expression. Whenever execution reaches that location, CodeView checks the expression. If the expression is true (nonzero), the breakpoint is taken. Otherwise, execution continues.

•	Break at Location if Expression has Changed

You specify a location and an expression that represents a variable or any portion of memory. To specify a range of memory, enter the length of the range in the Length text box. CodeView checks the variable or the range of memory when execution reaches the breakpoint location. If the value of any byte has changed since the last time CodeView checked, the breakpoint is taken. Otherwise, execution continues.

•	Break When Expression is True

This type of breakpoint is taken whenever the expression becomes true. CodeView evaluates the expression after every line or every instruction, instead of only at a certain location. As a result, this type of breakpoint can greatly slow your program's execution.

•	Break When Expression has Changed

CodeView checks the variable or the range of memory as each line or each instruction is executed. You can also specify a range with the Length text box. This type of breakpoint can also slow your program's execution.

Location

Specifies where CodeView should evaluate the breakpoint.

Expression

Specifies an expression that causes a break when it becomes true, or specifies a location that is to be watched for changes. An expression should not contain a dereferenced pointer.

Pass Count

Specifies the number of times to pass over the breakpoint when it otherwise would be taken. For example, a pass count of 10 tells CodeView to ignore the first nine breakpoints and break on the tenth.

Length

Specifies a range of memory (starting at the address in the Expression text box) to watch for changes.

Enable

Specifies whether CodeView should evaluate or ignore the breakpoint. A breakpoint that is enabled appears on the breakpoint list preceded by an "E". Disabled breakpoints are indicated by a "D".

Commands

Specifies a list of Command-window commands, separated by semicolons, that are executed when the breakpoint is taken. If several breakpoints with commands are taken, the commands are queued and executed in first-in, first-out order.

Messages

You can set a breakpoint on a Windows message or an entire class of Windows messages. CodeView halts execution of your program when it receives a message you have specified. By using this feature, you can track your application's response to user input and window-management messages. The Message field in the Breakpoints dialog box shows the current setting.

As shortcuts, you can also set simple (Break at Location) breakpoints with the following methods:

•	Double-click the line in the Source window.

•	Move the cursor to the breakpoint location in the Source window and press F9.

A line with a breakpoint is highlighted. In the Mixed and Assembly modes, an assembly-language comment that displays the breakpoint number appears; for example:

80b35000 57       push edi                     ;BK0

In this example, breakpoint number 0 is set at the address 80B35000.

You can also set breakpoints with the Breakpoint Set (BP) command. See the »Breakpoint Set« command.

Setting Breakpoints

When you have set the options you want for a breakpoint, use one of the command buttons in the Breakpoints dialog box to add, remove, or change the breakpoint. These command buttons are located on the right side of the dialog box under the Messages button. (The function of each command button is described in the list following.)

The Breakpoints dialog box shows a list that describes the state of each breakpoint in your program. The New, Delete, and Modify buttons all act on the breakpoint that is selected in the breakpoint list. For more information on the format of the breakpoint list, see the »Breakpoint List« command.

The following list describes the function of each command button in the Breakpoints dialog box:

New

The New command button resets the breakpoint fields to the default values. The default breakpoint type is Break at Location, and the location is set at the location of the cursor in the Source window. The Enable field is selected and all other options are cleared. Use the New command button when you want to set a new breakpoint that is not based on an existing breakpoint.

Add

The Add command button adds a new breakpoint to the breakpoint list. If no options have been specified, a Break at Location breakpoint will be added to the breakpoint list. The breakpoint will be set at the position of the cursor in the source window.

Delete

The Delete command button deletes the currently selected breakpoint from the breakpoint list.

Sometimes it may be useful to disable a breakpoint rather than remove it. (To disable a breakpoint, deselect the Enable option.) A breakpoint may not be practical when you are debugging a routine nested deeply in your program. You can reenable the breakpoint later when you really need it. Also, conditional breakpoints are evaluated at every program step and can slow execution. You can disable some conditional breakpoints in areas of your program where you're certain you won't need them.

Modify

The Modify command button changes the currently selected breakpoint so it takes the currently specified options. To change a breakpoint, select it on the breakpoint list, specify the new options, and then use the Modify command.

Clear All

The Clear All command button clears all of the breakpoints currently set in the source file.


  The Options Menu

The Options menu contains commands to change the default behavior of CodeView commands and the display status of CodeView windows. You can also set display options with various Command-window commands. When the cursor is in one of the Source, Memory, or Local windows, you can press CTRL+O to display the window's Options dialog box.

For menu items that are toggles, a bullet appears to the left of the item when the option is turned on. No bullet appears when it is turned off.

The following table summarizes the commands on the Options menu.

Command	Purpose
Source1 Window	Sets Source window 1 display options
Source2 Window	Sets Source window 2 display options
Memory1 Window	Sets Memory window 1 display options
Memory2 Window	Sets Memory window 2 display options
Locals Options	Sets Locals window display options
Preferences	Sets display options for all CodeView windows


  Source Window

The Source Window command displays the Source Window Options dialog box. In this dialog box, you can set the source display mode and other options for the current Source window. These options are described below.

Option	Description
Source	Displays the source code for the program
Mixed Source and Assembly	Displays each source line followed by the disassembly of the code generated for that line
Assembly	Displays a disassembly of the machine code in your program
Show Machine Code	Shows the address and hexadecimal representation of the machine code in Mixed and Assembly modes
Show Addresses	Displays the address of each instruction on the left side of the window
Lower Case Instructions	Displays machine code instructions in lower case
Show Symbolic Name	Shows the symbol name in assembly-language displays instead of the numeric value of the symbol
Follow Program Counter	Keeps the current program location visible in the active Source window
Tab Length	Sets the number of spaces to which tab characters expand in the source file
Mixed Mode Order	Specifies whether source code lines are displayed above or below corresponding machine code


  Memory Window

The Memory Window command displays the Memory Window Options dialog box, where you can set the starting address and display format of the active Memory window. You can also toggle live expression evaluation between the dynamic and static setting in this dialog box. For details, see »The Memory Windows«, and the »View Memory« command.


  Locals Options

You can specify the scope of variables to be displayed in the Locals window. When you select Locals Options from the Options menu, a dialog box appears in which you can select any combination of lexical, function, module, executable, and global scopes. You can also toggle the display of addresses in the Locals window from the Locals Options dialog box. When you turn Show Addresses on, the BP-relative address of each Locals variable is shown in the Locals window. Otherwise, the Locals window shows only the names of the variables.

You can also use the Options (OL) command in the Command window to specify the scope of variables to be displayed in the Locals window. For information, see the »Options« command.


  Preferences

The Preferences command displays the Preferences dialog box, which you can use to change settings, such as display options, in the CodeView environment.

The following table summarizes the fields on the Preferences dialog box.

Option	Description
Horizontal Scrollbars	Toggles horizontal scroll bars on windows
Vertical Scrollbars	Toggles vertical scroll bars on windows
Display Radix	Changes the radix (base) used to display numeric values
Animate Speed	Sets animation speed
Status Bar	Toggles the status bar display
Call-Stack Parameters	Toggles display of call-stack parameters
Case Sensitivity	Toggles case sensitivity of symbols
Colors	Brings up dialog box to change colors of CodeView screen elements
Horizontal Scrollbars

The Horizontal Scrollbars check box toggles the horizontal scroll bars on and off. When scroll bars are off, you can drag the bottom window frame, as well as the size box, to resize the window.

Vertical Scrollbars

The Vertical Scrollbars check box toggles the vertical scroll bars on and off. When scroll bars are off, you can drag the right window frame, as well as the size area, to resize the window.

Display Radix

The Display Radix list box presents a list of the three radix values CodeView can use to display numeric values. Changing the radix from the Preferences dialog box has the same effect as changing the radix using the N command in the Command window. For more information on the Radix command, see »Radix«.

Animate Speed

The Animate Speed list box presents a list of three speeds from which you can select.

When you use the Animate command to run your program in slow motion, CodeView pauses execution between each step. The duration of the pause is set with the Trace Speed command. Slow pauses for 1/2 second. Medium pauses for 1/4 second. Fast runs the program as fast as possible while still updating CodeView windows and evaluating breakpoints and watch expressions.

Status Bar

The Status Bar check box toggles the status bar on and off. When the status bar is off, you gain an extra line of space for windows.

Call-Stack Parameters

The Call-Stack Parameters check box toggles the Call-Stack Parameters display mode. When this option is enabled, parameters will be listed for functions displayed by the Calls menu. Parameters for functions with no CodeView information are not displayed.

Case Sensitivity

The Case Sensitivity command toggles case sensitivity on or off. When Case Sensitivity is on, CodeView treats symbol names as case sensitive (that is, a lowercase letter is different from its corresponding uppercase letter).

Colors

The Colors command button displays a dialog box that lets you change the colors of CodeView screen elements. The Item list box displays all the elements of the debugging screen. The Foreground and Background list boxes show the current color settings for the highlighted element in the Item list box.

To change the color of a screen element, choose an element in the Item list box, then choose foreground and background colors. When you are done, click the OK button. Your new color settings take effect as soon as you exit the dialog box.

If you make a number of changes and want to go back to your previous color settings, click the Reset button. You can then start changing colors again. To close the dialog box without making any changes, click the Cancel button. To reset to the standard CodeView colors, click the Use Default button.

When you specify colors using the Colors command in CodeView, the colors are saved in CLRFILE.CVW. CodeView saves these files in the directory specified by the INIT environment variable or in the current directory if no INIT environment variable is set. These settings become the new default colors.


  The Calls Menu

The Calls lists the call tree for the current function. Its contents change to reflect their current status. The current routine is at the top of the menu; the routine that called it appears just below. Routines are listed in the reverse order in which they were called. Near the bottom of the list is your program's WinMain routine.

If the Call Stack Parameters option is selected, the arguments to each routine in parentheses are listed with each routine name. Arguments are shown in the current radix, except for pointers, which are always shown in hexadecimal.

When you choose a routine from the Calls menu, CodeView displays the source code for that routine and updates the Locals window to show the local variables in that routine. The cursor moves to the return location to show the next line or instruction that will be executed when control returns to that routine.

To step out of deeply nested code, choose a routine and then press F7.

Choosing a routine from the Calls menu does not affect program execution; it provides you with a convenient way to view a routine's source code and local variables. However, since the cursor is positioned at the return location, you can press F7 to execute through the stack of nested calls to that line. This is especially convenient when you find you've accidentally traced into a deeply nested set of routines which you know to be bug-free. Rather than continue a tedious trace until you work your way out of the stack of routines, you can choose a routine from the Calls menu and press F7. CodeView executes through the nested routines until control returns to the point you chose.

A routine may not be visible in the Calls menu under the following circumstances:

•	You have not reached the program's initial entry point.

•	The stack has been corrupted.

•	CodeView cannot give a stack trace through the Win32s thunking layer in a callback function.


  The Windows Menu

If you get lost among your windows, try the Arrange command.

The Windows menu contains commands that activate, open, close, tile, arrange, and manipulate CodeView windows. There is also a command to view your program's output screen. When you open this menu, a bullet appears to the left of the active window. All the windows are numbered. You can quickly open or switch to a window by pressing ALT plus the window's number.

The following table summarizes the commands on the Windows menu and the corresponding shortcut keys.

Command	Shortcut Key	Purpose
Restore	CTRL+F5	Restores the active window to its size and position before it was maximized or minimized
Move	CTRL+F7	Moves the active window using the keyboard
Size	CTRL+F8	Sizes the active window using the keyboard
Minimize	CTRL+F9	Shrinks the active window to an icon
Maximize	CTRL+F10	Enlarges the active window to full screen
Close	CTRL+F4	Closes the active window
Tile	SHIFT+F5	Arranges all open windows to fill the entire window area
Arrange	ALT+F5	Arranges all open windows to an effective layout for debugging
Help	ALT+0	Opens or switches to the Help window
Locals	ALT+1	Opens or switches to the Locals window
Watch	ALT+2	Opens or switches to the Watch window
Source 1	ALT+3	Opens or switches to Source window 1
Source 2	ALT+4	Opens or switches to Source window 2
Memory 1	ALT+5	Opens or switches to Memory window 1
Memory 2	ALT+6	Opens or switches to Memory window 2
Register	ALT+7	Opens or switches to the Register window
8087	ALT+8	Opens or switches to the 8087 window
Command	ALT+9	Opens or switches to the Command window
View Output	F4	Swaps the CodeView screen for the program's output screen


  Source and Memory Windows

You can open as many as two Source and two Memory windows. At least one Source window must be open at all times. To close a window, use the Close command (CTRL+F4).


  Help, Locals, Watch, Register, 8087, and Command Windows

CodeView can display one of each of these windows. The Register window has an additional shortcut key (F2) you can use to open or close it.

When you open the Help window, CodeView displays the last Help screen you viewed. If you have not yet viewed Help during the session, CodeView displays the CodeView Help contents screen.


  View Output

To view your program's output screen, choose View Output or press F4. CodeView displays the output screen until you press a key.


  The Help Menu

The Help menu contains commands to access the Help system. When you choose a Help command, CodeView opens the Help window if it is not already open and displays the appropriate information.

When the Help window is open, you can browse through Help with mouse and keyboard commands.

The following table summarizes the commands on the Help menu.

Command	Purpose
Index	Displays the index of CodeView Help topics
Contents	Displays the CodeView Help contents screen
Topic	Displays Help on the current word
Help on Help	Displays Help on using CodeView Help
Technical Support	Describes how to obtain technical support
About	Displays CodeView copyright and version information


  Index

The Index command displays a table of available indexes. Each part of the Help system has its own index.


  Contents

The Contents command (SHIFT+F1) displays the contents for the entire Help system. This screen lists the table of contents for each Help system component.


  Topic

The Topic command (F1) displays help on the word at the cursor or the selected text. When you open the Help menu, CodeView displays the topic in the menu. When you choose the Topic command, CodeView displays information on the indicated topic in the Help window.


  Help on Help

The Help on Help command displays information on how the system is organized, how the mouse and keyboard commands are used to browse through Help, and how to use the various kinds of buttons you encounter.


  Technical Support

The Technical Support command displays information on the types of product support that are available, and how to contact Product Support.


  About

The About command displays the CodeView copyright and version information in a dialog box.


  Chapter 3  Debugging Win32s Applications

This chapter covers techniques for debugging Win32s executables with CodeView.


  Choosing the Right Debugger

Two different debuggers are provided with Microsoft Visual C++: the integrated debugger in the Microsoft Visual Workbench, and CodeView. The Visual Workbench debugger is a Windows NT-hosted debugger used to debug applications for Windows NT. CodeView is a Windows 3.1 hosted debugger used to debug applications for Win32s.

You can run CodeView to debug a single application and the dynamic-link libraries (DLLs) it uses. CodeView cannot be used to debug 32-bit code that is accessed using universal thinking layers or to debug device drivers.


  Starting a Debugging Session

Like most Windows-based applications, CVW can be started in several ways. You can double-click the CVW icon and respond to CVW's prompts for arguments, or you can run CVW by using the Run command from the Program Manager's File menu.

To specify CVW options, choose the Run command from the Program Manager's File menu. Windows displays a dialog box where you can enter the appropriate options for your debugging session. For more information on CodeView command-line syntax and options, see »The CodeView Command Line«.

This section describes the methods you use to perform these tasks and summarizes the syntax of the CVW command line for each task.


  Starting CVW for Single Applications

After you start CVW from Windows, CodeView displays the Load dialog box.

To start debugging a single application:

1.	Type the name of the application in the File to Debug text box.

CVW assumes the .EXE filename extension if you do not include an extension for the application name. You can also pick the program that you want to debug by choosing it from the Files List box.

2.	If you want to specify command-line arguments, move the cursor to the Arguments text box and type the program's command line.

3.	Choose OK.

CVW loads the application and displays the source code for the application's WinMain routine.

4.	Set breakpoints in the code if you desire.

5.	Use the Go (G) command (F5) to begin executing the application.

To avoid the startup dialog boxes:

1.	Choose the Run command from the Windows File menu.

2.	Type the application name and arguments on the CVW command line. Use the following syntax to start debugging a single application:

CVW [options] appname[.EXE] [arguments]

3.	Choose OK.


  Starting CVW for DLLs

You can debug one or more DLLs while debugging an application.

To debug a DLL used by an application:

1.	Start CVW as usual for the application.

2.	From the Run menu, choose Load and type the name of the DLL if the DLL is dynamically loaded by the application.

3.	Set breakpoints in the application or DLL. You can use the Open Module command from the CVW File menu to display the source code for the different modules.

4.	Use the Go (G) command (F5) to continue executing the application.

5.	Any breakpoints you have set will be instantiated when the application loads the DLL.

You can also use the /L option on the CVW command line to specify the DLLs, as shown in this example:

CVW /Lappdll appname

The /L option must precede the name of the application. Repeat the /L option for each DLL you want to debug.


  Debugging Techniques

In CVW, all of the CodeView execution commands (Go, Program Step, Trace, and Animate) can be used to control your application's execution. However, you should keep these restrictions in mind while using CVW:

•	Attempting to use the Program Step or Trace commands to execute Windows startup code in Assembly mode causes unpredictable results. To step through your application in Assembly mode, first set a breakpoint at the WinMain routine, go to the breakpoint and then begin stepping through the program.

•	Directly calling a Windows-based application procedure or dialog routine in the Watch window, in the Quick Watch dialog box, or with the Display Expression (?) command can have unpredictable results.

The rest of this section describes techniques and special considerations for controlling program execution in CVW.

Interrupting Your Program

There may be times when you want to halt your program immediately. You can interrupt your program by pressing CTRL+ALT+F11 when your application has focus. After you press CTRL+ALT+F11, CVW gains control and displays code corresponding to the current EIP location. You then have the opportunity to examine registers and memory, set breakpoints and watch expressions, and modify variables. To resume execution, use the Go command.

Terminating Your Program

When your application is executing an infinite loop, you may have to terminate the application. The Windows Kill Application (WKA) command terminates the application being debugged. Since this task is not necessarily your application, you should use the WKA command only when your application is the currently executing task.

The WKA command does not perform all the cleanup tasks associated with the normal termination of a Windows-based application. For example, global objects created during program execution but not destroyed before you terminated the program remain allocated in the system-wide global heap. This reduces the amount of memory available during the rest of the Windows session. For this reason, you should use the WKA command to terminate the application only if you cannot terminate it normally.

Handling Abnormal Termination of the Application

An unhandled exception can cause your application can terminate abnormally. If CVW gains control, you can examine the state of the system when your application terminated. CVW allows you to view registers, display the global and local heaps, display memory, and examine your source code.


  Restarting a Debugging Session

You can terminate your application without leaving CVW. Windows notifies CVW that it is terminating the application, and CVW displays the following message:

Program terminated normally (n)

Where n is the value in EAX on termination.

You can restart the application by using the Restart command on the Run menu.


  Chapter 4  Using Expressions in CodeView

The arguments to most CodeView commands are expressions. A source-level expression is a reference to a variable or a function call, or one or more operations involving constants, variables, addresses, or function calls. A physical location is a register, a memory address or range, or a source-code line number that CodeView maps to an address.

To interpret expressions while maintaining its own programming language independence, CodeView uses a dynamic-link library (DLL) to look up symbols, parse, and evaluate expressions. This DLL is called an "expression evaluator."

The expression evaluator recognizes most C and C++ operators and provides additional debugging operators that are not part of the languages. It places certain restrictions on C++ expressions. Although there is no expression evaluator for the Microsoft Macro Assembler (MASM), expression evaluator supports operators that simulate essential assembly-language operations. You use the same expression evaluator when debugging MASM code.


  Common Elements

When debugging, you use a few common elements in arguments to CodeView commands that are independent of the source language or the current expression evaluator. You often refer to line numbers in source files, and, less often, to lines in text files. You also specify registers and addresses. Some CodeView commands such as Memory Fill (MF) accept address ranges.

This section presents the ways to specify line numbers, refer to objects in memory, and use values stored in the processor registers. It also describes the syntax for memory ranges.


  Line Numbers

Line numbers are useful for source-level debugging. In Source mode, you see a program displayed with each line numbered consecutively. CodeView allows you to use line numbers to specify the address of code generated for a line or to specify a certain line in a text file.

Syntax

[context] .linenumber

[context] @linenumber

The optional context is the context operator used to specify a certain file. When it is omitted, CodeView assumes that the line is in the current source file. The linenumber specifies the line in the file (numbered starting at 1). Some commands, such as the Breakpoint Set (BP) command, display an error message if the compiler does not generate code for the specified line. For more information on the context operator, see »The Context Operator«.

With most CodeView commands, the two forms are interchangeable because CodeView automatically maps between source lines and code addresses. The .linenumber form specifies a line offset from the beginning of a file. Use this form with the View Source (VS) command to display any text file, including files that are not source files for the program you are debugging. The @linenumber form specifies the address of the beginning of the code generated by the compiler for the specified line. Use this form with the Breakpoint Set (BP) command.

Examples

The following example uses the Go (G) command to execute the program from the current location up to line 100. Since no file is indicated, CodeView assumes the current source file.

>G @100

The following commands use the View Source (VS) command to display text files at line 10 of the current file, line 301 of EXAMPLE.CPP, and line 22 of TESTFILE.TXT:

>VS .10
>VS {,EXAMPLE.CPP}.301
>VS {,TESTFILE.TXT}.22


  Registers

Syntax

[@]register

The register is the name of a register. You can specify a register name if you want to use the current value stored in the register. Registers are rarely needed in source-level debugging. However, they are frequently used for lower-level debugging.

When you specify an identifier, CodeView first checks the program's symbol table for the name. If the debugger does not find the name, it checks to see if the name is a register. If you want the identifier to name a register regardless of any name in the symbol table, use an at sign (@) before the register name.

For example, if your program has a symbol called EAX, specify @EAX to refer to the EAX register. You can avoid this conflict by making sure that your program does not use register names as identifiers.

Table 4.1 lists the registers known to CodeView.

Table 4.1    Registers

Register Type	Register Names
8-bit high byte	AH, BH, CH, DH
8-bit low byte	AL, BL, CL, DL
16-bit general purpose	AX, BX, CX, DX
16-bit segment	CS, DS, SS, ES
16-bit segment	FS, GS
16-bit pointer	SP, BP
16-bit program counter	IP
16-bit index	SI, DI
16-bit flags	FL
32-bit general purpose	EAX, EBX, ECX, EDX
32-bit flags	EFL
32-bit pointer	ESP, EBP
32-bit program counter	EIP
32-bit index	ESI, EDI


  Addresses

Syntax

[context][symbol]

The context is the context operator and specifies the point at which to begin searching for symbol. If context is omitted, the current location is used. The symbol is a label, variable, or function name.

Syntax

[context][@linenumber]

The linenumber is the number of a line in the specified file. If context is omitted, CodeView assumes the current file. Line numbers start at 1.

Syntax

address

In source-level debugging, addresses are seldom necessary. Occasionally they may be convenient for referring to addresses outside the program, such as display memory.

Examples

In the following example, the Memory Dump Bytes (MDB) command dumps memory starting at address 80B35000.

>MDB 80B35000

In the following example, the MDB command dumps memory starting at the address of the element array[COUNT].

>MDB array[count]

In the following example, the Unassemble (U) command shows a disassembly of memory starting at a point 10 bytes beyond the symbol label.

>U label+10

In this example, the MDB command dumps memory at the given address in the current radix.

>MDB 80B35000


  Address Ranges

Syntax

start end

A range is a pair of addresses that defines the boundary of a sequence of contiguous memory locations. You can specify a range by giving the starting address and the ending address. In this case, the range covers start to end, inclusively. If a command takes a range but you do not supply a second address, CodeView displays enough data to fill the current size of the window.

Syntax

start L length

You can also specify a range by giving its starting point and the number of objects you want included in the range. This type of range is called a "length range." In a length range, start is the address of the first object, L indicates that this is a length range, and length specifies the number of objects in the range.

The size of the object is the size taken by the command. For example, the Memory Dump Bytes (MDB) command dumps bytes, the Memory Dump Words (MDW) command dumps words, the Unassemble (U) command unassembles instructions (which can vary in size), and so on.

Examples

The following example dumps a range of memory starting at the buffer symbol. Since the end of the range is not given, the default size is assumed. In this example, it is 128 bytes for the Memory Dump Bytes (MDB) command.

>MDB buffer

The following example dumps a range of memory starting at buffer and ending at buffer+20 (the point 20 bytes beyond buffer).

>MDB buffer buffer+20

The following example uses a length range to dump the same range of memory as in the previous example.

>MDB buffer L 20

The following example uses the Memory Fill (MF) command to fill memory with dollar sign ($) characters starting 30 bytes before right_half and continuing to right_half.

>MF right_half-30 right_half '$'


  Using the C and C++ Expression Evaluators

CodeView evaluates C and C++ expressions according to the same rules as the compiler, including operator associativity and order of precedence. However, there are a few additional operators and some exceptions to the standard syntax. See the C Language Reference and C++ Language Reference for descriptions of C and C++ expression syntax.


  Additional Operators

The expression evaluator supports the following additional operators:

•	The "context" operator ({ }) to specify the context of a symbol.

•	The memory operators (BY, WO, and DW) to access memory. Each of the memory operators has the same precedence, which is the lowest of any operator recognized by the expression evaluators.

The memory operators are used mostly to debug assembly-language code. The memory operators are described in »Memory Operators«. For more information about using the context operator, see »The Context Operator«.


  Unsupported Operators

The conditional (?:) operator, the bitwise shift (>> and <<) operators, and the comma (,) operator are not supported by the expression evaluator. The C++ operators .* and  − >* are also unsupported.

The ampersand (&) is not supported as a bitwise AND operator. However, the expression evaluator recognizes the ampersand (&) as an address-of operator. It also recognizes the ampersand in type casts to create a reference type. For example, (int &)curIndex casts the curIndex variable to an int reference type.


  Restrictions and Special Considerations

When you are debugging C and C++ programs, the following general restrictions apply:

•	When you use an expression as an argument to a CodeView command that takes multiple arguments, such as the Memory Fill (MF) command, the expression cannot contain spaces. For example, &count+6 is allowed, but &count + 6 is interpreted as three separate arguments. Some commands, such as the Display Expression (?) command, permit spaces in expressions.

•	CodeView command names are not case sensitive, but C and C++ identifiers are case sensitive unless you turn off case sensitivity with the commands on the Options menu or the Options (O) command.

•	You cannot call an intrinsic function or an inline function in a CodeView expression unless it appears at least once as a normal function.

•	CodeView limits casts of pointer types to one level of indirection. For example, (char *)sym is accepted, but (char **)sym is not.

•	The C++ scope operator (::) has lower precedence in CodeView expressions than in the C++ language. In CodeView, its precedence falls between the base (:>) and postfix (++,  −  − ) operators and the unary operators (!, &, *, for example). In C++, it has the highest precedence.

CodeView imposes additional restrictions on C++ expressions. These restrictions and other special considerations when debugging C++ are described in »Using C++ Expressions«.


  The Context Operator

The context operator ({ }) is unique to CodeView. It is not part of the C or C++ languages. You use it to specify the exact context of an expression or line number that appears in more than one place in your source code. For example, you might use this operator to specify a symbol defined in an include file when the file is included more than once or to specify a name in an outer scope that is otherwise hidden by a local name.

When you use a symbol in a CodeView expression, the expression evaluator searchs for that symbol in the following order:

1.	Lexical scope outward. The expression evaluator searches for the symbol starting with the current block (a series of statements enclosed in curly braces) and continuing with the enclosing block. The current block is the code containing the current location (EIP address).

2.	Function scope. The expression evaluator searches for the symbol in the current function.

3.	Class scope. If debugging C++ and within the scope of a member function, the expression evaluator searches symbols of that member function's class and all its base classes, using the normal dominance rules.

4.	Current module. The expression evaluator searches all symbols in the current module.

5.	Global symbols. The expression evaluator searches all global symbols in the program.

6.	Other modules. The expression evaluator searches the global symbols in all other modules in the program.

7.	Public symbols in the program.

If the name is not found in any of these places and the name is not the name of a register, CodeView displays an error message.

The context operator lets you specify the starting point of the search and bypass the current location. Note that you cannot specify a block because a block has no name. You cannot specify a class, but you can specify a member function of the class and let the expression evaluator search outward.

Syntax

{[function] ,[module] ,[dllexe]} [object]

function

The name of a function in the program.

module

The name of a source file. You must specify a source file if the function is outside the current scope. If the file is not in the current directory, you must specify the path.

dllexe

The path of a program's DLL or .EXE file.

object

A line number or symbol.

The context operator has the same precedence and associativity as the type-cast operator. You can omit function, module, or dllexe, but you must specify all leading commas. You can omit trailing commas. If a name contains a comma, you must enclose the name in parentheses.

Example

The following example displays the value of the variable Pos, which is local to the function make_box, which is defined in the source file DRAWBOX.C. Assuming that there is more than one source file called DRAWBOX.C, the third parameter specifies that the source file containing the function make_box is the one used by DISPTXT.DLL.

? {make_box,C:\TREE1\DRAWBOX.C,C:\TREE2\DISPTXT.DLL}Pos


  Numeric Constants

Numbers used in CodeView commands represent integer constants. They are expressed in octal, decimal, or hexadecimal radix; the default is the current radix. However, you can use the Radix (N) command to specify a different radix, as explained in »Radix«. CodeView displays the current radix in the lower-right corner of the status bar.

To override the current radix, you can use the C and C++ syntax for entering a constant of a different radix. In addition, CodeView supports the 0ndigits syntax to specify decimal numbers independently of the current radix.

The following table summarizes the syntax for different radixes.

Syntax	Radix
digits	Current radix
0digits	Octal (base 8)
0ndigits	Decimal (base 10)
0xdigits	Hexadecimal (base 16)
Symbols take priority over numbers.

When hexadecimal is the current radix, it is possible to enter a value that could be either a symbol or a hexadecimal number. CodeView resolves the ambiguity by first searching for a symbol with that name. If no symbol is found, the value is a number. If you want to enter a number that is the same as a symbol in your program, use the explicit hexadecimal format (0xdigits).

For example, if the program contains a variable named abc and you enter abc, CodeView interprets the argument as the symbol. If you want to enter it as a number, enter it as 0xabc.


  String Literals

Syntax

"string"

Strings can be specified as expressions in the C format. You can use all ANSI C escape sequences within strings. For example, double quotation marks within a string are specified with the escape sequence \".

A string that you specify in a CodeView command is volatile, and you cannot rely on its existence for longer than the execution of the command. This means that you can pass a string to a function, but you cannot assign a string to a character pointer variable. For example, the command

? pChar = "string"

is not valid. However, you can change a pointer to refer to a different string in your program. Also, if the pointer addresses a section of memory large enough to accommodate the string, you can use the Memory Enter (ME) command to fill the memory with a new string.


  Symbol Formats

For modules that are compiled with full CodeView debugging information (-Zi), the expression evaluators automatically translate the decorated names into source form. You specify and view names as they appear in your source. Therefore, debugging is easier when all modules in the program are compiled with full CodeView debugging information. For large programs, however, you may need to compile some modules to include only line numbers and public symbols (-Zd).

CodeView accepts and displays public symbol names as "decorated" names. The decorated name is the form of the name in the object code produced by the compiler. Public symbols are names in library routines or names in modules compiled without CodeView information (that is, compiled with the -Zd option, or compiled without any line or symbolic information and linked with the -DEBUG option).

To get a listing of all names in their decorated and undecorated forms, use the DUMPBIN utility.

Name decoration is the mechanism used to enforce type-safe linkage. This means that only the names and references with precisely matching spelling, case, calling convention, and type are linked together.

Names declared with the C calling convention (either implicitly or explicitly using the _cdecl keyword) begin with an underscore (_). For example, the function func can be displayed as _func. Names declared as _fastcall are converted to uppercase and begin with an at sign (@). Names declared as _stdcall are preceeded by an underscore, and followed by an @, followed by a count of the bytes of parameters, for example, _WinMain@16.

For C++, the decorated name encodes the type of the symbol in addition to the calling convention. This form of the name can be long and difficult to read. The name begins with at least one question mark (?). For C++ functions, the decoration includes the function's scope, the types of the function's parameters, and the function's return type.

For more information on decorated names, see Appendix C in the C++ Language Reference.


  Using C++ Expressions

The expression evaluator accepts almost all C++ expressions, with some restrictions and some additions. This section describes these special considerations.


  Access Control

All class members are accessible.

You can examine any member of a class object, including base classes and embedded member objects. In CodeView, all members are available without regard to access control (public, protected, or private visibility). For example, if myDate has a private data member named month, you can examine it with the following command:

>? myDate.month
3


  Ambiguous References

If an expression makes an ambiguous reference to a member name, you must use the class name to qualify it. For example, suppose that class C inherits from both class A and class B, and that A and B define a member function named expand. If Cthing is an instance of class C, the following expression is ambiguous:

Cthing.expand()

The following expression resolves the ambiguity and uses B's expand function:

Cthing.B::expand()

The expression evaluator applies normal dominance rules regarding member names to resolve ambiguities.

If two member functions have the same name you must provide a function signature to resolve the ambiguity.


  Inheritance

When you display a class object that has virtual base classes, the members of the virtual base class are displayed for each inheritance path, even though only one instance of those members is stored. You can access members of an object through a pointer to the object, and you can call virtual functions through a pointer.

For example, when the Employee class defines a virtual function named computePay, which is redefined in the derived class Employee, you can call computePay through a pointer to Employee and have the proper function executed:

>? empPtr->computePay()

You can cast a pointer to a derived class object into a pointer to a base class object. However, the reverse conversion is not permitted. For example, if the class List is derived from the class Collection, the cast (Collection *)pListCustomer is valid, but the cast (List *)pCollectClients is illegal.


  Constructors, Destructors, and Conversions

You can set a breakpoint on a class's constructor or destructor (unless it is an inline function). The breakpoint is taken whenever an object of that class is created or destroyed. You can specify a breakpoint that halts execution so that you can examine your program's status. You can also specify a breakpoint that executes a command, such as displaying a message in the Command window or incrementing a counter, and then continues execution. This technique is especially useful for monitoring the creation and destruction of temporary objects created by the compiler.

You cannot call a constructor or destructor for an object, either explicitly or implicitly, by using an expression that calls for construction of a temporary object. For example, the following illegal command explicitly calls a constructor and results in an error message:

>? Date( 2, 3, 1985 )

You cannot call a conversion function if the destination of the conversion is a class because such a conversion involves the construction of an object. For example, suppose that myFraction is an instance of the Fraction class, which defines the conversion function operator FixedPoint. The following command results in an error:

>? (FixedPoint)myFraction

However, you can call a conversion function if the destination of the conversion is a built-in type. For example, suppose that the Fraction class defines a conversion function named operator float. The following command is legal:

>? (float)myFraction

You can also call functions that return an object or that declare local objects.

You cannot call the new or delete operators. The command

? pDate = new Date(2,3,1985)

is illegal and CodeView displays an error message.

You cannot evaluate an expression that implicitly calls the new or delete operators, such as a copy constructor.


  Overloading

You can call overloaded functions as long as there is an exact match or a match that does not require a conversion involving the construction of an object. For example, if the calc function takes a Fraction object as a parameter, and the Fraction class defines a single-argument constructor that accepts an integer, the following command results in an error:

>? calc( 23 )

Even though a legal conversion exists to convert the integer into the Fraction object that the calc function expects, such a conversion involves the creation of an object and is not supported.


  Operator Functions

Operator functions for a class can be invoked implicitly or explicitly. For example, suppose that myFraction and yourFraction are instances of a class that defines operator+. You can display the sum of those two objects using expression syntax:

>? myFraction + yourFraction

You can also use the functional notation to call an operator function:

>? myFraction.operator+( yourFraction )

If an operator function is defined as a friend, you can call it implicitly using the same syntax as for a member function, or you can invoke it explicitly, as follows:

>? operator+( myFraction, yourFraction )

Note that operator functions, like ordinary functions, cannot be called with arguments that require a conversion involving the construction of an object.


Visiblility of the this Pointer
  Visibility of the this Pointer

By default the calling convention for C++ member functions is "thiscall." The this pointer for a C++ member function will be enregistered and passed in the ECX register while the other parameters are passed on the stack from right to left.The this pointer will be visble in the Registers or Locals window depending on the code and the code optimizations you have chosen. It may remain enregistered throughout the function, visible in the Registers window, or once the function is entered it may be pushed onto the stack and become visible in the Locals window. In other cases, such as when using the Disable Optimizations (/Od) option, the this pointer will always be pushed onto the stack, and will therefore be visible in the Locals window.


  Debugging Assembly Language

The Microsoft Macro Assembler (MASM) versions 5.0 and later provide type and size information for CodeView. With this information, CodeView can correctly evaluate expressions derived from assembly code (except for arrays, which require a different syntax, as discussed later in this section).

You cannot always specify an expression in CodeView exactly as it would appear in assembly-language source code. You have to write an equivalent CodeView expression. This section describes the CodeView equivalents for MASM expressions.


  Memory Operators

A memory operator is a unary operator that returns the result of a direct memory operation. The memory operators are BY, WO, and DW. The expression evaluator add the memory operators to the operators in the C and C++ languages. The memory operators are used mainly to debug assembly-language code.

Syntax

{BY | WO | DW} address

The BY operator returns a short integer that contains the first byte at address. This operator simulates BYTE PTR.

The WO operator returns a short integer that contains the value of the word (two bytes) at address. This operator simulates the MASM WORD PTR operation. The DW operator returns a long integer that contains the value of the first four bytes at address. This operator simulates DWORD PTR.

The examples that follow use the »Display Expression« (?) command. The x format specifier used in some of these examples causes the result to be displayed in hexadecimal.

Examples

The following example displays the first byte at the address of the variable sum.

>? BY sum
101

The following example displays the byte pointed to by the EBP register with a displacement of 6.

>? BY ebp+6,x

The following example displays the first word at the address of the variable new_set.

>? WO new_set
13120

The following example displays the word pointed to by the stack pointer.

>? WO esp,x
2F38

The following example displays the doubleword at the address of sum.

>? DW sum
132120365

The following example displays the doubleword pointed to by the SI index register. The ESI index register is used without specifying a segment address.

>? DW esi,x
3F880000


  Register Indirection

The expression evaluator does not recognize brackets ([ ]) to indicate a memory location pointed to by a register. Instead, you use the BY, WO, and DW operators to reference the corresponding byte, word, or doubleword values.

MASM Expression	CodeView Equivalent
BYTE PTR [ebx]	BY ebx
WORD PTR [ebp]	WO ebp
DWORD PTR [ebp]	DW ebp


  Register Indirection with Displacement

To perform based, indexed, or based-indexed indirection with a displacement, use the BY, WO, and DW operators with addition.

MASM Expression	CodeView Equivalent
BYTE PTR [edi+6]	BY edi+6
BYTE PTR Test[ebx]	BY &Test+ebx
WORD PTR [esi+ebp+6]	WO esi+ebp+6
DWORD PTR [ebx+esi]	DW ebx+esi


  Address of a Variable

Use the C address-of operator (&) instead of the MASM OFFSET operator.

MASM Expression	CodeView Equivalent
OFFSET Var	&Var


  PTR Operator

Use type casts or the BY, WO, and DW operators with the address-of operator (&) to replace the assembly-language PTR operator.

MASM Expression	CodeView Equivalents
BYTE PTR Var	BY &Var  *(unsigned char*)&Var
WORD PTR Var	WO &Var *(unsigned *)&Var
DWORD PTR Var	DW &Var *(unsigned long*)&Var


  Strings

Add the string format specifier ,s after the variable name.

MASM Expression	CodeView Equivalent
String	String,s
Because C strings end with a null (ASCII 0) character, CodeView displays all characters from the first byte of the variable up to the next null byte in memory when you request a string display. If you intend to debug an assembly-language

program, and you want to view strings in the Watch window or with the Display Expression (?) command, you should delimit string variables with a null character. You can also view null-terminated or unterminated strings in a Memory window or with the Memory Dump ASCII (MDA) command.


  Array and Structure Elements

Prefix an array name with the address-of operator (&) and add the desired offset. The offset can be an expression, number, register name, or variable.

The following examples (using byte, word, and doubleword arrays) show how to do this.

MASM Expression	CodeView Equivalents
String[12]	BY &String+12 *(&String+12)
aWords[ebx+edi]	WO &aWords+ebx+edi *(unsigned*)(&aWords+ebx+edi)
aDWords[ebx+4]	DW &aDWords+ebx+4 *(unsigned long*)(&aDWords+ebx+4)


  Chapter 5  CodeView Reference

This chapter describes the CodeView Command-window command format, explains the common items in CodeView expressions, then lists all Command-window commands in a convenient table and describes each in an alphabetic reference. The nonalphabetic commands appear at the end of the chapter.


  Command-Window Command Format

Syntax

command [arguments] [; command [arguments] ]

Parameters

command

A command name. The command is not case sensitive; any combination of uppercase and lowercase letters can be used.

arguments

Expressions that represent values or addresses used by the command. Source-level expressions used as arguments may or may not be case sensitive, depending on the source language and the setting of the case sensitivity option. The first argument can be placed immediately after command with no space separating the two fields.

If a command takes more than one argument, you must separate the arguments with spaces.

Remarks

Additional commands may be specified on the same line. A semicolon (;) must separate each command from the next.


  CodeView Expressions

When debugging, you use a few common elements in arguments to CodeView commands that are independent of the source language. You often refer to line numbers in source files and, less often, to lines in text files. You also specify registers and addresses. Some CodeView commands such as Memory Fill (MF) accept address ranges.

This section presents the ways to specify line numbers, refer to objects in memory, and use values stored in the processor registers. It also describes the syntax for memory ranges. Moreover, the context operator, which you use to specify the point at which to begin searching for a symbol, is summarized. For detailed information on the context operator and CodeView expressions, see »Chapter 4, Using Expressions in CodeView.«


  Line Numbers

Syntax

[context]@linenumber

[context].linenumber

Description

Line numbers are useful for source-level debugging. They correspond to the lines in source-code files. In Source mode, a program is displayed with each line numbered sequentially. The CodeView debugger allows you to use these numbers to access parts of a program.

The memory address of the code corresponding to a source-line number is specified as:

@linenumber

This is equivalent to:

[context].linenumber

CodeView assumes that the source line is in the current source file. To specify a source line in a different file, you must specify the line's context using the context operator:

{,file}@linenumber

CodeView displays an error message if file does not exist or no source line exists for linenumber.

Examples

The following example uses the View Source (VS) command to display code starting at source line 100. Since no file is indicated, the current source file is assumed.

>VS @100

This next example uses VS to display source code starting at line 301 of the file DEMO.C.

>VS {,demo.c}.301


  Registers

Syntax

[@]register

A register name represents the current value stored in the register. Table 5.1 summarizes the register names known to the CodeView debugger.

Table 5.1    Registers

Register Type	Register Names
8-bit high byte	AH, BH, CH, DH
8-bit low byte	AL, BL, CL, DL
16-bit general purpose	AX, BX, CX, DX
16-bit segment	CS, DS, SS, ES
16-bit segment	FS, GS
16-bit pointer	SP, BP
16-bit program counter	IP
16-bit index	SI, DI
16-bit flags	FL
32-bit general purpose	EAX, EBX, ECX, EDX
32-bit flags	EFL
32-bit pointer	ESP, EBP
32-bit program counter	EIP
32-bit index	ESI, EDI
To force a symbol to represent a register, prefix the symbol with an at sign (@). For example, to make EAX represent a register rather than a variable, use @EAX.


  Addresses

Syntax

address

[context]@linenumber

[context]function

[context]symbol

Description

The Display Expression (?) and Add Watch Expression (W?) commands interpret numeric arguments as constants rather than as offsets. However, if you cast the argument to a pointer, as in

>W? (char *)0


  Address Ranges

Syntax

start end

start L count

Description

An address range is a pair of memory addresses that specify the higher and lower boundaries of contiguous memory. You can specify a range in two ways:

•	Give the starting and ending addresses:

start end

The range covers start to end, inclusively. If you don't supply an ending address, CodeView assumes the default range. Each command has its own default range; the most common default range is 128 bytes.

•	Give the starting address and the number of objects you want included in the range:

start L count

This type of range is called an "object range." The starting address is the address of the first object in the list, and count specifies the number of objects in the range. The way the size of an object is measured depends on the command. For example, the Memory Dump Bytes (MDB) command has byte objects, the Memory Dump Words (MDW) command has words, the Unassemble (U) command has instructions, and so on.

Examples

This example dumps a range of memory starting at the symbol buffer. Since the end of the range is not given, the default size (128 bytes for the Memory Dump Bytes command) is assumed.

>MDB buffer

The following example dumps 21 bytes starting at buffer and ending at buffer+20 (the point 20 bytes beyond buffer).

>MDB buffer buffer+20

The following example uses an object range to dump a range of memory. The L indicates that the range is an object range, and 20 indicates the number of objects in the range.

>MDB buffer L 20

Here, each object has a size of 1 byte because that is the size of objects dumped by the Memory Dump Bytes (MDB) command.


  Context Operator ({})

Syntax

{ [function] , [module] , [dllexe] } [object]

Parameters

function

The name of a function or procedure in the program. Case is significant for case-sensitive languages.

module

The name of a source file. If the file is not in the current directory, you must specify the path.

dllexe

The full path of a dynamic-link library (DLL) or .EXE file.

object

A variable name, line number, or expression.

Description

The context operator specifies the exact starting point to search for a symbol or line. You apply it the same way as a type cast is applied in C. When you do not use the context operator, the current context (EIP) is used.

You can omit function, module, or dllexe, but all leading commas must be given. Trailing commas can be omitted. If a name contains a comma, the name must be enclosed in parentheses.

For complete information on the context operator, see »The Context Operator«.

Example

This example displays the value of the variable Pos, which is local to the function make_box defined in the source file BOXDRAW.C.

? {make_box,C:\PROJ\boxdraw.c}Pos


  CodeView Command Reference

The rest of this chapter is an alphabetic reference to all CodeView Command-window commands. It begins with Table 5.2, a summary of the commands. Following the table, each command is described in detail. Nonalphabetic commands, such as the Pause (") command, are listed after alphabetized terms, in the same order as in the table.

Table 5.2    CodeView Command Summary

Command	Name	Description
A	Assemble	Inserts assembly-language instructions
BC	Breakpoint Clear	Clears one or more breakpoints
BD	Breakpoint Disable	Disables one or more breakpoints
BE	Breakpoint Enable	Enables one or more breakpoints
BL	Breakpoint List	Lists one or more breakpoints
BP	Breakpoint Set	Sets a breakpoint
E	Animate	Executes the program in slow motion
G	Go	Executes the program
GZ	Pass Exception	Pass an exception to an application
H	Help	Provides CodeView Help information
I	Port Input	Reads a byte from a hardware port
K	Stack Trace	Displays active routines
L	Restart	Restarts the program
MC	Memory Compare	Compares two blocks of memory byte by byte
MD	Memory Dump	Displays contents of memory in the Command window in various formats
ME	Memory Enter	Modifies memory
MF	Memory Fill	Fills a block of memory
MM	Memory Move	Copies one block of memory to another
MS	Memory Search	Scans memory for specified byte values
N	Radix	Changes current radix for entering arguments and displaying values
O	Options	Views or sets options
O	Port Output	Outputs a byte to a hardware port
P	Program Step	Executes the current line and steps over  functions
PR	Stop After Return	Executes the return of the current function and then halts
Q	Quit	Terminates CodeView
R	Register	Displays the values of registers and flags and optionally changes them
SXD	Disable Exception	Disables handling of a specified exception
SXE	Enable Exception	Enables handling of a specified exception
SXL	List Exceptions	Displays the state of exception handling
T	Trace	Executes the current line and traces into functions
T	Trace Speed	Specifies speed for the Animate command
U	Unassemble	Displays assembly-language instructions
VM	View Memory	Displays sections of memory in a Memory window in various formats
VS	View Source	Displays source code in varying formats in a Source window
W?	Add Watch Expression	Sets an expression to be watched
WC	Delete Watch Expression	Deletes one or more watch expressions
WKA	Windows Kill Application	Terminates the current task by simulating a fatal error
WL	List Watch Expressions	Lists current watch expressions
X	Examine Symbols	Displays the addresses and types of symbols
"	Pause	Interrupts execution of redirected commands and waits for keystroke
#	Tab Set	Sets number of spaces for each tab character
*	Comment	Displays explanatory text during redirection
.	Current Location	Displays the current location
/	Search	Searches for a regular expression in the source
7	8087	Shows the values of the 8087 or emulator registers and flags
:	Delay	Delays execution of redirected commands
<	Redirect Input	Reads input from specified device
>	Redirect Output	Sends output to specified device
=	Redirect Input and Output	Sends output and reads input from specified device
?	Display Expression	Evaluates and displays expressions  or symbols
??	Quick Watch	Displays variables and data structures in a dialog box
@	Redraw	Redraws the screen


  A (Assemble)

Syntax

A [address]

Parameter

address

Assembly begins at this address. If address is not given, assembly begins at the current assembly address (see below).

Description

The Assemble (A) command assembles 8086-family instruction mnemonics and places the resulting instruction code into memory at a specified address.

If address is specified, the assembly starts at that address; otherwise, the current assembly address is assumed.

The assembly address is normally the current address or the address pointed to by EIP. However, when you use the Assemble command, the assembly address is set to the address immediately following the last assembled instruction.

When you enter any command that executes code (Trace, Program Step, Go, or Animate), the assembly address is reset to the current address.

Entering Instructions

Use the following procedure to assemble instructions:

1.	Type the Assemble (A) command in the Command window and press ENTER. CodeView displays the assembly address and waits for you to enter a new instruction.

2.	Type a mnemonic and press ENTER. CodeView assembles the instruction into memory and displays the next available address. If an instruction you enter contains a syntax error, CodeView displays the message:

^ Syntax error

Then CodeView redisplays the current assembly address and waits for you to enter a correct instruction. The caret (^) in the message points to the first character that CodeView could not interpret.

3.	Continue entering new instructions until you have assembled all the instructions you want.

4.	Press ENTER without entering any mnemonic to conclude assembly and return to the CodeView prompt.

Remarks

Consider the following principles when you enter instruction mnemonics:

•	String mnemonics must explicitly state the string size. For example, MOVSW must be used to move word strings and MOVSB must be used to move byte strings.

•	CodeView cannot determine whether some operands refer to a word memory location or to a byte memory location. In these cases, the data type must be explicitly stated with the prefix WORD PTR or BYTE PTR. Acceptable abbreviations are WO and BY.

•	CodeView cannot determine whether an operand refers to a memory location or to an immediate operand. CodeView uses the convention that operands enclosed in square brackets ([]) refer to memory.

•	CodeView supports all forms of indirect register instructions.

•	All instruction-name synonyms are supported. If you assemble instructions and then examine them with the Unassemble (U) command, CodeView may show synonymous instructions, rather than the ones you have assembled.

Any instructions that you assemble are lost as soon as you exit the program. The instructions you assemble are also lost when you restart the program with the Restart command. The original code is reloaded, possibly writing over parts of memory that you have changed.

Example

This example places two new instructions in a program, replacing any instructions already there.

>a 8000B900
8000B900  mov eax,eip
8000B903  mov esi,00000000

You can modify a portion of code for testing, as in the example, but you cannot save the modified program. You must modify your source code and recompile.


  BC (Breakpoint Clear)

Syntax

BC [list | start-end | *]

Parameters

list

List of breakpoints to be removed, with breakpoint numbers separated by spaces. A number identifies each breakpoint. You can use the Breakpoint List (BL) command to display currently set breakpoints and their numbers.

start-end

Range of breakpoints to clear. The command clears breakpoints numbered from start to end, inclusive.

*

Removes all currently set breakpoints.

Description

The Breakpoint Clear (BC) command permanently removes one or more previously set breakpoints.

Mouse and Keyboard

In addition to typing the BC command, you can clear breakpoints with the following shortcuts:

•	From the Data menu, choose Edit Breakpoints.

•	Double-click the line containing the breakpoint.

•	Using the keyboard, move to the line containing the breakpoint, and press F9.

Examples

The following example removes breakpoints 0, 4, and 8:

>BC 0 4 8

The following example removes all breakpoints:

>BC *

The following example removes breakpoints 4, 5, 6, and 7:

>BC 4-7


  BD (Breakpoint Disable)

Syntax

BD [list | start-end | *]

Parameters

list

List of breakpoints to be disabled, with breakpoint numbers separated by spaces. A number identifies each breakpoint. You can use the Breakpoint List (BL) command to display currently set breakpoints and their numbers.

start-end

Range of breakpoints to disable. The command disables breakpoints numbered from start to end, inclusive.

*

Disables all currently set breakpoints.

Description

The Breakpoint Disable (BD) command temporarily disables one or more existing breakpoints. The breakpoints are not deleted; they can be restored at any time using the Breakpoint Enable (BE) command.

A disabled breakpoint can be cleared using the Breakpoint Clear (BC) command.

In the Source window, enabled breakpoints are highlighted. However, the highlighting disappears once the breakpoint is disabled.

Mouse and Keyboard

As an alternative to typing the BD command, choose Edit Breakpoints from the Data menu. There is no keyboard shortcut.

Examples

The following example temporarily disables breakpoints 0, 4, and 8:

>BD 0 4 8

The following example temporarily disables all breakpoints:

>BD *

The following example disables breakpoints 4, 5, 6, and 7:

>BD 4-7


  BE (Breakpoint Enable)

Syntax

BE [list | start-end | *]

Parameters

list

List of breakpoints to be enabled, with breakpoint numbers separated by spaces. A number identifies each breakpoint. You can use the Breakpoint List (BL) command to display currently set breakpoints and their numbers.

start-end

Range of breakpoints to enable. The command enables breakpoints numbered from start to end, inclusive.

*

Enables all currently disabled breakpoints.

Description

The Breakpoint Enable (BE) command enables breakpoints that have been temporarily disabled with the Breakpoint Disable (BD) command.

Mouse and Keyboard

In addition to typing the BE command, you can also enable breakpoints from the Data menu, by choosing Breakpoints. There is no keyboard shortcut.

Examples

The following example reenables breakpoints 0, 4, and 8:

>BE 0 4 8

The following example enables all disabled breakpoints:

>BE *

The following example enables breakpoints 4, 5, 6, and 7:

>BE 4-7


  BL (Breakpoint List)

Syntax

BL [list | start-end | *]

Description

The Breakpoint List (BL) command lists current information about all breakpoints.

For each breakpoint, the command displays the following:

•	The breakpoint number.

•	The breakpoint status, where "E" is for enabled, "D" is for disabled, and "V" is for "virtual." A virtual breakpoint is a breakpoint set in a DLL that is not currently loaded. A virtual breakpoint may be enabled or disabled.

•	The address, function, file, and line number where the breakpoint is set.

•	The expression, pass count, and break commands, if set.

Mouse and Keyboard

In addition to typing the BL command, you can also list breakpoints from the Data menu, by choosing Breakpoints. There is no keyboard shortcut.

Examples

The following example lists breakpoints 0, 4, and 8:

>BL 0 4 8

The following example lists all breakpoints:

>BL *

The following lists breakpoints 4, 5, 6, and 7:

>BL 4-7


  BP (Breakpoint Set)

Syntax

BP [address] [ [=expression [/Rrange] ] | [?expression] ] [/Ppasscount] [/C"commands"] [/Mmsgname|msgclass [/D] ]

Parameters

address

An expression giving the address at which to set the breakpoint. If omitted, sets a breakpoint on the current line, unless =expression is also specified.

=expression

Breaks program execution when the value of expression changes. If address is given, the expression is checked for changes only at that address. The expression is usually the name of a variable.

/Rrange

Watches all addresses in the given range for changes. The range is determined by multiplying range with the size of expression.

?expression

Breaks program execution when expression becomes true (nonzero). If address is given, the breakpoint expression is evaluated only at that address. You cannot specify both =expression and ?expression in the same breakpoint. Also, you cannot have more than one local context in expression. If the expression contains spaces, it must be enclosed in double quotation marks ("expression").

/Ppasscount

Specifies the first time the breakpoint is to be taken. For example, if passcount is 5, the breakpoint will be ignored the first four times it is encountered and taken the fifth time. From that point on, the breakpoint is always taken until the program is restarted.

/C"commands"

A list of Command-window commands to be executed when the breakpoint is encountered. The commands must be enclosed in double quotation marks (" ") and separated by semicolons (;).

/Mmsgname

Breaks program execution whenever the specified message is received. When /D is also specified, the message received is displayed, but the breakpoint is not taken.

/Mmsgclass

Breaks program execution whenever a message belonging to one of the specified classes is received. When /D is also specified, the message received is displayed but the breakpoint is not taken. Can be one or more of the following:

Message Class	Type of Windows Message
m	Mouse
w	Window management
n	Input
s	System
i	Initialization
c	Clipboard
d	DDE
z	Nonclient
Description

The Breakpoint Set (BP) command creates a breakpoint at a specified address. Whenever a breakpoint is encountered during program execution, the program halts and waits for a new command.

You can set breakpoints at source lines, functions, explicit addresses, or labels in any module of a program. If no arguments are given, BP sets a breakpoint at the current line.

Breakpoints in Windows

Use of the /M options requires that address be the name or address of a window function ("WndProc").

When the /D option is specified, CVW displays each message in the Command window as it is sent to the application's window function. The message is displayed in the following format:

HWND:wh wParm:wp lParm:lp msg:msgnum msgname

where wh is the window handle, wp is the message's wparam, lp is the message's lparam, msgnum is the message number, and msgname is the name of the message. The following is a typical display:

HWND:00003F9C wParm:00000000 lParm:00000000 msg:0000000F WM_PAINT

Breakpoints in Windows appear in the list of breakpoints and may be enabled, disabled, and cleared with the usual CodeView breakpoint commands.

Breakpoint Options

For any breakpoint, you can also specify:

•	A pass count to tell CodeView how many times to pass over the breakpoint.

•	Commands to be executed after the program reaches the breakpoint.

Breakpoints are numbered, beginning with the number 0. Each new breakpoint is assigned the next available number. Breakpoints remain in memory until you explicitly delete them. Breakpoints are saved in the CURRENT.STS file when you exit CodeView and are restored the next time you debug the program.

Types of Breakpoints

You can set breakpoints to break execution when any of the following conditions is true:

•	The program reaches a given source line, function, label, or address.

•	An expression becomes true (nonzero). The CodeView expression evaluator evaluates this type of expression based on the currently visible function.

•	The value of an expression or memory range changes. CodeView references this type of expression by memory location. As a result, the original value of the expression is checked no matter which function is currently visible.

Mouse and Keyboard

In addition to typing the BP command, you can also set a breakpoint with the following shortcuts:

•	From the Data menu, choose Breakpoints.

•	Double-click a source line.

•	Move the cursor to a source line and press F9.

Examples

Command	Action
BP @47	Set a breakpoint at line 47 of the currently executing module.
BP 0x80b35000	Set a breakpoint at address 80b35000.
BP =curr_sum	Halt execution whenever the value in curr_sum changes.
BP =myint /R8	Halt execution whenever a change occurs in the range of eight integers that begins at myint. If myint is a 2-byte value, the range is 16 bytes in size.
BP @47 =int_array[0] /R20	Set a breakpoint at line 47 of the currently executing module. The breakpoint will be taken at that line if any 20 elements of the array int_array changes. Since int_array is a 2-byte value, the range is 40 bytes in size.
BP {,mymod}@47 ?myptr==0	Set a breakpoint at line 47 of the module mymod. The breakpoint is taken only if myptr is zero.
BP stats /P10 /C"?counter+=1"	Set a breakpoint at the address of the function stats but ignore the breakpoint the first nine times the function is executed. On the tenth and later call to stats, stop execution, and use the Display Expression (?) command to increment the value of counter. If counter is set to 0 when the breakpoint is set, counter can be used to count the number of times the breakpoint is taken.


  E (Animate)

Syntax

E

Description

The Animate (E) command traces through a program one step at a time, with a user-selectable pause between each step, beginning at the current instruction. In the Source mode, CodeView pauses after each line of source text. In the Mixed or Assembly mode, CodeView pauses after each instruction. The Animate command allows you to see how execution proceeds in your program.

You can set the time the command pauses with the Trace Speed (T) command or by choosing Trace Speed from the Options menu.

Press ESC to stop animation.

Mouse and Keyboard

To begin animating, you can also choose Animate from the Run menu. There is no keyboard shortcut.


  G (Go)

Syntax

G [address]

Parameters

address

Address at which to stop execution.

Description

The Go (G) command starts execution at the current address. If address is given, CodeView executes the program until it reaches that address. If the specified address is never reached, the program executes until it terminates. If no address is given, CodeView executes the program until it terminates, until it reaches a breakpoint, or until you interrupt execution.

Mouse and Keyboard

In addition to typing the G command, you can start execution using the following shortcuts:

•	Click the <Go> button in the status bar.

•	Press F5.

•	From the Run menu, select Go .

To execute up to a certain location, you can use the following shortcuts:

•	Click the right mouse button on the source line.

•	Move the cursor to the source line and press F7.

•	From the Run menu, select Go To Cursor.

Example

The following example executes up to the label panic_exit in the winmain function. Because labels are always local to a procedure, you must specify the context (procedure or function name) if the label is not in the current function.

>G {winmain}panic_exit


  GZ (Pass Exception To Application)

Syntax

GZ

Description

The Pass Exception To Application (GZ) command causes CodeView to pass an exception on to the application being debugged.

The GZ command is useful when the handler for a specific exception has been enabled (using the SXE command). When the exception arises CodeView will issue a message and halt, allowing you to terminate your application, or to examine the state of the system before passing the exception to your application. Your application will be terminated if it does not have a handler for the exception.


  H (Help)

Syntax

H [topic]

Parameter

topic

Provides help on topic, which can be a Command-window command. If no topic is given, the table of contents is displayed.

Description

The Help (H) command displays help information in a separate window. You can get help on CodeView commands and error messages.

Mouse and Keyboard

In addition to typing the H command, you can get help using the following shortcuts:

•	With the right mouse button, click the keyword to display the corresponding Help topic. This method works in all CodeView windows except the Source, Memory, and 8087 windows.

•	Move the cursor to a topic and press F1 to display the corresponding help topic.

•	Choose one of the commands on the Help menu.


  I (Port Input)

Syntax

I port

Parameter

port

A 16-bit port address.

Description

The Port Input (I) command reads and displays a byte from a specified hardware port. The specified port can be any 16-bit address. CodeView displays the byte read in the Command window.

This command is often used in conjunction with the Port Output (O) command. Use this command to write and debug hardware-specific programs in Assembly mode.

Note  This command may affect the status of the hardware using the port.

Example

The following example reads the input port numbered 2F8 and displays the result, E8. You can enter the port address using any radix, but the result is always displayed in current radix.

>I 2F8 ;* hexadecimal radix assumed
E8


  K (Stack Trace)

Syntax

K [frame]

Description

The Stack Trace (K) command displays functions that have been called during program execution in the Command window. Functions are displayed along with their arguments if Call-Stack Parameters has been enabled in the Preferences dialog box from the Options menu. The command also displays the address of the instruction that will be executed when control returns to each function.

If all options are enabled, the output from the Stack Trace command gives you the following information:

•	Functions listed in the reverse order in which they were called.

•	Arguments to each function, listed in parentheses.

•	The address or line number of the next instruction to be executed when control returns to that function.

Thus, the current function is listed first, and the address of the next instruction to be executed is the current EIP address. At the bottom is the main function of your program and the address of the next instruction to be executed when execution returns to the main function.

For each function, the command shows argument values in the current radix in parentheses after the function name.

You can use the address displayed for each line of the stack trace as an argument to the View Source (VS) or Unassemble (U) commands to see the code at the point where each function is called.

If a call stack frame is provided as an argument, CodeView will navigate back to the specified stack frame. Providing a zero argument navigates back to the current EIP location.

Mouse and Keyboard

In addition to typing the (K) command, you can use the Calls menu to see the stack trace.

Remarks

The term "stack trace" is used because as each function is called, its address and arguments are stored on or pushed onto the program stack. CodeView traces through the program stack to find out which functions were called.

If the main module is written in assembly language, the program must execute at least to the beginning of the first procedure called. In addition, your procedures must follow the standard Microsoft calling conventions.

Example

The following example shows the functions executed in a program so far, where hexadecimal is the current radix under CodeView:

>K
*0) InitInstance(0x000044d6,10) line 146
 1) WinMain(0x000044d6,0x00000000,0x87c10263,10) line 61 + 13 bytes
 2) WinMainCRTStartup address 0x81115c1a
 3) W32SKRNL!(499f) 80fb0db8() address 0x80fb0db8
 4) W32SKRNL!(499f) 80fb5ca6() address 0x80fb5ca6
>

Here, InitInstance is the currently executing function, at line 146. It is passed two parameters: a pointer and an integer. When it returns control to WinMain, the program is executing at line 61 plus 13 bytes.


  L (Restart)

Syntax

L [arguments]

Parameter

arguments

New arguments to the program. No other CodeView commands may be specified after the Restart command. They are interpreted as additional program arguments.

Description

The Restart (L) command resets execution to the beginning of the program and optionally sets a new program command line.

After you issue the Restart command:

•	The program's variables are reinitialized.

•	The program's instructions are reset. Any modifications you may have made to the code with the Assemble (A), Memory Enter (ME), Memory Fill (MF), or View Memory (VM) commands are lost.

•	Any existing breakpoints or watch statements are retained. The pass counts for all breakpoints are reset.

Used alone, the Restart command keeps the previous command-line arguments specified for your program. You can change the command-line arguments using the Restart command followed by any new arguments to your program.

You can use Restart any time execution has stopped: at any kind of breakpoint, while single-stepping, or when execution is complete.

Mouse and Keyboard

In addition to typing the L command, you can also restart from the Run menu by choosing Restart. To set a new command line and restart the program, choose Set Runtime Arguments from the Run menu. There is no keyboard shortcut.

Remarks

The Restart command does not reset system resources, such as open files or video mode, and does not free allocated system objects. If the application redefines interrupts, the system may no longer work correctly.


  MC (Memory Compare)

Syntax

MC range address

Parameters

range

Range of first block of memory.

address

Starting address of second block of memory.

Description

The Memory Compare (MC) command compares the bytes in a given range of memory with the corresponding bytes beginning at another address. If one or more pairs of corresponding bytes do not match, the command displays each pair of mismatched bytes.

You can enter arguments to the Memory Compare (MC) command in any radix, but the output of the command is always in hexadecimal.

Examples

The following example compares the block of memory from 80000000 to 80001000 with the block from 80002000 to 80003000. CodeView reports that the third and ninth bytes differ in the two ranges.

>MC 80000000 80001000 80002000 ;* hexadecimal radix assumed
80001002 0A 00 80002002
80001008 0A 01 80002008
>

The following example compares the 100 bytes starting at the address of arr1[0] with the 100 bytes starting at the address of arr2[0].

>MC arr1[0] L 100 arr2[0] ;* decimal radix assumed
>

Because CodeView produced no output, the first 100 bytes of each array are identical.


  MD (Memory Dump)

Syntax

MD[format] [address|range]

Parameters

format

Specifies the format in which to dump data. The format can be one of the following:

Specifier	Format
A	ASCII characters
B	Byte (hexadecimal)
C	Code (instructions)
I	Integer (2-byte decimal)
IU	Integer unsigned (2-byte decimal)
IX	Integer hex (2-byte hexadecimal)
L	Long (4-byte decimal)
LU	Long unsigned (4-byte decimal)
LX	Long hex (4-byte hexadecimal)
R	Real (4-byte float)
RL	Real long (8-byte float)
RT	Real ten-byte (10-byte float)
SU	Short unsigned (2-byte decimal)
SX	Short hex (2-byte hexadecimal)
W	Word (hexadecimal)
If format is not given, the Memory Dump command defaults to the format last used. If never used before, it defaults to an 8-bit dump.

address

Starting address of memory to be dumped. This can be any expression that evaluates to an address. The amount of memory dumped depends on the format specified. If address is omitted, the Memory Dump command defaults to the byte immediately following the last byte in the previous dump command. If the Memory Dump command was never used before, it defaults to 0x00000000.

range

Range of memory to be dumped.

Description

The Memory Dump (MD) command displays the contents of memory in the command window, using the format you specify. This command can be used with the Redirection commands to send the contents of memory to another device. Use the View Memory (VM) command to display the contents of memory in a separate window.

The Memory Dump Code (MDC) command is like the Unassemble (U) command, except that MDC displays instructions in the Command window instead of the active Source window. Although you normally specify a range with the L character, you can also use the I character with MDC to specify a range of instructions rather than bytes.

Examples

The following example displays 12 instructions starting from the address at line number 32 in the source code:

>mdc .32 I 12

The following example displays the byte values in the range between 0x87000000 and 0x8700001B. ASCII characters are shown on the right.

>mdb 0x87000000 0x8700001b
87000000  00 00 00 00 00 00 00 00 4D 53 20 52 75 6E  ........MS Run
8700000E  2D 54 69 6D 65 20 4C 69 62 72 61 72 79 20  -Time Library
>

The following example displays seven elements of float_array as 4-byte real values:

>mdr float_array[0]
87000D56  DC 0F 49 40  +3.141593E+000
87000D5A  A0 17 CE 3F  +1.610096E+000
87000D5E  66 66 5B C2  -5.485000E+001
87000D62  00 00 C0 3F  +1.500000E+000
87000D66  FF FF 1F 41  +9.999999E+000
87000D6A  00 00 00 00  +0.000000E+000
87000D6E  00 00 00 00  +0.000000E+000
>


  ME (Memory Enter)

Syntax

ME type address [list]

Parameters

type

Specifies the type of the data to be entered into memory.

Specifier	Type
A	ASCII characters
B	Byte (hexadecimal)
D	DWORD
I	Integer (2-byte decimal)
IU	Integer unsigned (2-byte decimal)
IX	Integer hex (2-byte hexadecimal)
L	Long (4-byte decimal)
LU	Long unsigned (4-byte decimal)
LX	Long hex (4-byte hexadecimal)
R	Real (4-byte float)
RL	Real long (8-byte float)
RT	Real ten-byte (10-byte float)
SU	Short unsigned (2-byte decimal)
SX	Short hex (2-byte hexadecimal)
W	Word (hexadecimal)
If no type is given, the command defaults to the last type used by a Memory Enter (ME), a Memory Dump (MD), or a View Memory (VM) command. If no such commands were used, it defaults to byte-sized data.

address

Indicates where the data will be entered.

list

List of data to enter into memory at address. These expressions must evaluate to data of the size specified by type. If list is not given, CodeView prompts for new values.

Description

The Memory Enter (ME) command enters one or more byte values into memory at a given address.

The command may include a list of expressions separated by spaces. The expressions are evaluated and entered in the current radix. If an invalid value appears in the list, CodeView refuses to enter the invalid value and ignores remaining values. If no list is given, CodeView prompts for new values.

Because it can modify any part of your program's memory, the Memory Enter command can change your program's instructions. However, the Assemble (A) command is better suited to that purpose.

Mouse and Keyboard

There is no keyboard shortcut to enter items into memory. However, you can use the Memory window to alter items in memory.

Entering Values

If you do not give a list of expressions in a Memory Enter (ME) command, CodeView prompts for a new value at the address you specify by displaying the address and its current value. At this point, you can do one of the following:

•	Replace the value by typing a new value.

•	Skip to the next value by pressing the SPACEBAR. Once you have skipped to the next value, you can change its value or skip again. CodeView will automatically prompt with new addresses as necessary.

•	Return to the preceding value by typing a backslash (\). When you return to the preceding value, CodeView starts a new display line and prompts with the address and current value.

•	Stop entering values and return to the command prompt by pressing ENTER.

Example

The following example replaces the byte at 0x80001000 with 66 (42 hexadecimal).

>MEB 0x80001000
800010001  41  A. 66
>


  MF (Memory Fill)

Syntax

MF range list

Parameters

range

Specifies the range of memory to be filled.

list

List of byte values used to fill range.

Description

The Memory Fill (MF) command fills the addresses in the specified range with the byte values specified in the argument list. You can enter byte values using any radix.

The values in the list are repeated until the whole range is filled. Thus, if you specify only one value, the entire range is filled with that same value. If the list has more values than the number of bytes in the range, the command ignores any extra values.

The Memory Fill command provides an efficient way to fill up a block of memory with any values you specify. You can use it to initialize large data areas, such as arrays or structures. Because it can modify any part of your program's memory, the Memory Fill command can change your program's instructions. However, the Assemble (A) command is better suited to that purpose.

Examples

The following example fills 256 (100 hexadecimal) bytes of memory starting at 0x80001000 with the value 0; hexadecimal radix is assumed. This command could be used to reinitialize the program's data without having to restart the program.

>MF 0x80001000e L 100 0
>

The next example fills the 100 (64 hexadecimal) bytes starting at table with the following hexadecimal byte values: 42, 79, 74. These three values are repeated (42, 79, 74, 42, 79, 74, ... ) until all 100 bytes are filled; hexadecimal radix is assumed.

>MF table L 64 42 79 74
>


  MM (Memory Move)

Syntax

MM range address

Parameters

range

Specifies the range of memory to copy.

address

Destination address to copy the range.

Description

The Memory Move (MM) command copies all the values in one block of memory directly to another block of memory of the same size. All data in the source block is guaranteed to be copied completely over the destination block, even if the two blocks overlap.

When the source is at a higher address than the destination, the Move Memory command copies data starting at the source block's lowest address. When the source is at a lower address, the Memory Move command copies data beginning at the source block's highest address.

You use the Memory Move command to program in Assembly mode (to copy function fragments, for example) or to copy large amounts of data.

Examples

In the following example, the block of memory to copy begins with the first element of array1 and is array_size bytes long. It is copied directly to a block of the same size, beginning at the address of the first element of array2.

>MM array1[0] L array_size array2[0]
>


  MS (Memory Search)

Syntax

MS range list

Parameters

range

The range of memory to search.

list

A list of byte values separated by spaces or commas or an ASCII string delimited by quotation marks.

Description

The Memory Search (MS) command scans a range of memory for specific byte values. Use this command to test for the presence of certain values within a range of data.

You can specify any number of byte values to the Memory Search command. Unless the list is an ASCII string, each byte value must be separated by a space or a comma.

If the list contains more than one byte value, the Memory Search command looks for a series of bytes that precisely match the order and value of bytes in the list. If the command finds such a series of bytes, it displays the beginning address of that series.

Examples

The following example displays the address of each memory location containing the string error. The command searched the first 1500 bytes at the address specified by the variable buffer. CodeView found the string at three addresses.

>MS buffer L 1500 "error"
811B8AA8
811B8AE2
811B91E8
>

The following example displays the address of each memory location that contains the byte value 0A in the range 86000000 to 86000200; hexadecimal is assumed to be the default radix. CodeView found the value at two addresses.

>MS 0x86000000 200 A ;* hexadecimal radix assumed
86000008
86000020
>


  N (Radix)

Syntax

N [radix]

Parameter

radix

New radix while running CodeView. Can be 8 (octal), 10 (decimal), or 16 (hexadecimal). If omitted, the command displays the current radix.

Description

The Radix (N) command changes the current radix for entering arguments and displaying the values of expressions. The new radix number can be 8 (octal), 10 (decimal), or 16 (hexadecimal). Binary and other radixes are not allowed. With no arguments, the command displays the current operating radix.

Note  Changing the radix does not convert the l-value of displayed expressions, only the r-value.

When you start up CodeView, the default radix is 10 (decimal), unless your main program is written with the Microsoft Macro Assembler (MASM). In this case, the default radix is 16 (hexadecimal).

Remarks

The following conditions are not affected by the Radix command:

•	The radix for entering a new radix is always decimal.

•	Format specifiers given with the Display Expression (?) command override the current radix.

•	Addresses are always shown in hexadecimal.

•	In Assembly mode, all values are shown in hexadecimal.

•	The display radix for the Memory Dump (MD) and Breakpoint Set (BP) commands is always hexadecimal if the size is bytes, words, or doublewords; it is always decimal if the size is integers, unsigned integers, short reals, long reals, or 10-byte reals.

•	The input radix for the Memory Enter (ME) command's prompt is always hexadecimal if the size is bytes, words, or doublewords; it is always decimal if the size is integers, unsigned integers, short reals, long reals, or 10-byte reals.

•	The current radix is used for all values given as part of a list, except real numbers, which must be entered in decimal.

•	The register display is always in hexadecimal.

Example

The following example shows the decimal equivalents of the number 14 in octal and in hexadecimal.

>N8
>? 14,i
12
>N16
>? 14,i
20
>

Here, the Display Expression (?) command uses the i format specifier, which prints a number in decimal regardless of the current radix.


  O (Options)

Syntax

O[option[+| − ] ]
OL[ [scope][+| − ] ]

Parameters

option

Character indicating the option to be turned on or off.

Letter	Option	Display
A	Show Status bar	If on, the status bar appears at the bottom of the screen. If off, the bottommost line becomes part of the window area.
B	Bytes Coded	If on, instruction addresses and machine code are displayed for assembly instructions.
C	Case Sense	If on, symbols are case sensitive; if off, they are not.
H	Horizontal Scroll Bar	If on, windows have a horizontal scroll bar.
K	Call Stack Parameters	If on, parameters passed to functions are shown on call-stack list.
L	Show Address	If on, addresses relative to EBP for all local variables are displayed in the Locals window.
S	Symbols	If on, symbols in assembly instructions appear in symbolic form. If off, they appear as addresses.
3	Show 32-bit Registers	If on, registers appear in wide 80386 format.
V	Vertical Scroll Bar	If on, windows have a vertical scroll bar.
scope

For the OL command, you can specify a scope of variables to display in the Locals window using one or more of the following:

Specifier	Scope
L	Lexical
F	Function
M	Module
E	Executable
G	Global
*	All of the above
+ Turns option(s) on.

− Turns option(s) off.

Description

The Options (O) command allows you to view or set the state of CodeView options:

The Locals window always displays variables local to the current routine. You can specify a scope of additional variables to display in the Locals window with the OL form of the Options command. Using OL with no options displays the current scope setting for the Locals window.

The O form of the command (all options) takes no arguments; it displays the state of all options. The other forms of the command (OB, OC, OS, OL, OA, OH, and OV) can be used as follows:

•	With no arguments. The state of the option is displayed.

•	With the + or − argument. The + argument turns the option on; the − argument turns the option off.

Mouse and Keyboard

As an alternative to typing the O command, you can view and set options on the Options menu.

Remarks

Use the Options (O) command to set options when you first start CodeView. You can set these options in the following ways:

•	Give one or more O commands with the /C option on the CodeView command line or include a similar command line in the CodeView response file.

•	Give one or more O commands as the Autostart entry in the TOOLS.INI file.

Example

In the following example, the O command is used to display current option settings. Then, the OC command is used to display and set options for symbol case sensitivity. Finally, the OL command turns on symbol addresses in the Locals window and displays not only local variables but global variables as well.

>O
Bytes Coded On
Case Sense On
Show Symbol Address On
Symbols Off
Vertical scroll bar On
Horizontal scroll bar On
Status bar On
Call-Stack Display Parameters on
>OC
Case Sense On
>OC-
Case Sense Off
OLG+


  O (Port Output)

Syntax

O port byte

Parameters

port

A 16-bit port address.

byte

Byte to send to port.

Description

The Port Output (O) command sends a byte value to a hardware port. You use this command to debug a program that interacts directly with hardware.

The Port Output command is often used with the Port Input (I) command.

Example

In the following example, the byte value 4F hexadecimal is sent to output port 2F8.

>O 2F8 4F ;* hexadecimal radix assumed
>


  P (Program Step)

Syntax

P [count]

Parameters

count

Repeat stepping count times.

Description

The Program Step (P) command executes the current line (in Source mode) or instruction (in Mixed or Assembly mode), stepping over functions. To trace into functions, use the Trace (T) command. If a value for count is specified, CodeView steps through count lines or instructions. If not, only the current line or instruction is executed.

In Source mode, if the current source line contains a function call, CodeView executes the entire function and is ready to execute the line after the call.

In Mixed or Assembly mode, if the current instruction is CALL, INT, or REP, CodeView executes the entire procedure, interrupt, or repeated string sequence.

You cannot step or trace into the operating system kernel.

Mouse and Keyboard

In addition to typing the P command, you can step through a program using the following shortcuts:

•	From the Run menu, choose Step.

•	Click the <Step> button in the status bar to step once.

•	Press F10 to step once.


  PR (Stop After Return)

Syntax

PR

Description

The Stop After Return (PR) command executes the current function and halts after executing the return statement.

You cannot step out of a wndproc.

Mouse and Keyboard

As an alternative to typing the PR command, choose Stop After Return from the Run menu or click the After Return button in the status bar.


  Q (Quit)

Syntax

Q

Description

The Quit (Q) command terminates CodeView and returns control to the environment from which CodeView was invoked: Microsoft Windows or Visual Workbench.

CodeView always saves state information on exit.

Mouse and Keyboard

As an alternative to typing the Q command, choose Exit from the File menu or press ALT+F4.


  R (Register)

Syntax

R [register [ [=]expression] ]

Parameters

register

Change the contents of the given register. If omitted, displays the values of all registers and flags and the current machine instruction.

[=]expression

Assign the value of the expression to the specified register. The equal sign (=) is optional; a space has the same effect.

Description

The Register (R) command displays and changes the values in the CPU registers. To display register contents without changing them, type the Register (R) command without any arguments. This form of the command shows the current values of all registers and flags. Flags are shown symbolically. It also shows the current instruction at the address given by EIP.

If an operand of the instruction contains memory expressions or immediate data, CodeView evaluates the operand and indicates the value to the right of the instruction. This value is referred to as the "effective address" and is also displayed at the bottom of the Register window.

Changing Registers

You can use the R command to change the values in CPU registers. Also, you can change the bits in the flag register symbolically without having to compute a value of the register.

To change the value in a register:

1.	Type the command letter R followed by the name of a register. The register name can be any of the following: AX, BX, CX, DX, CS, DS, SS, ES, SP, BP, SI, DI, IP, FL (for flags), EAX, EBX, ECX, EDX, ESP, EBP, ESI, EFL, EIP, or EDI.

2.	CodeView displays the current value of the register and prompts for a new value with a colon (:).

•	If you only want to examine the value, press ENTER.

•	If you want to change the value, type an expression (in the current radix) for the value and press ENTER.

•	As an alternative, you can use the Display Expression (?) command to change the value in a register:

?register=expression

To change a flag value:

1.	Type the command letter R followed by the letters EFL.

2.	The command displays the value of each flag as a two-letter name. At the end of the list of values, the command prompts for new flags with a dash (−).

3.	Type the new values after the dash for the flags you wish to change, then press ENTER. Use the flag symbols listed in the following table.

•	You can enter flag values in any order. If you do not enter a new value for a flag, it remains unchanged.

•	If you do not want to change any flags, press ENTER.

Note  If you enter an illegal flag name, CodeView displays an error message. The flags preceding the error are changed; flags at and following the error are not changed.

The flag values are:

Flag	Set Symbol	Clear Symbol
Overflow	OV	NV
Direction	DN	UP
Interrupt	EI	DI
Sign	NG	PL
Zero	ZR	NZ
Auxiliary carry	AC	NA
Parity	PE	PO
Carry	CY	NC
Mouse and Keyboard

As an alternative to typing the R command, you can use the Register window to display CPU values. To change CPU values with the Register window, type over the old values.

Example

In the following example, the R command displays the current registers and CPU flags. Then the R command changes the value in the EAX register.

>r

EAX=00000000  EBX=80E70001  ECX=00000000  EDX=81000001

ESP=81147F4C  EBP=81147FB4  ESI=810DE7E6  EDI=0007DF86

DS=29A7  ES=29A7  FS=51DF  GS=0000  SS=29A7  CS=299F EIP=80E7CD9F

NV UP EI PL ZR NA PE NC

80E7CD9F CC             INT       3

>r eax

EAX 00000000

:1

>r eax

EAX 00000001
>


  SXD (Disable Exception Handler)

Syntax

SXD {list | *}

Parameters

list

List of exception handlers to be disabled, with exception numbers separated by spaces. A number identifies each exception handler. You can use the List Exceptions (SXL) command to display the current state of exception handling.

*

Disables all currently enabled exception handlers.

Description

The Disable Exception Handler (SXD) command disables CodeView's first-chance handling of the specified exception. When debugger exception handling is disabled, the exception is passed to the application being debugged. If the application does not have a handler for the exception, the exception is passed back to CodeView for second-chance handling. CodeView will stop so you can examine the state of your application, and terminate the application. You can also pass the exception back to your application using the Pass Exception (GZ) command, which will cause Windows to terminate your application.

To find the number of an exception you want to disable, use the List Exceptions (SXL) command to display a list of the names and numbers of common exceptions.

Example

The following example disables CodeView first-chance handling the Integer Overflow exception.

>SXD 0xC0000095
>


  SXE (Enable Exception Handler)

Syntax

SXE {list | *}

Parameters

list

List of exception handlers to be disabled, with exception numbers separated by spaces. A number identifies each exception handler. You can use the List Exceptions (SXL) command to display the current state of exception handling.

*

Disables all currently enabled exception handlers.

Description

The Enable Exception Handler (SXE) command enables CodeView's first-chance handling of the specified exception. When debugger exception handling is enabled, CodeView traps the exception before it is passed to the application being debugged. You can examine the state of your application, or terminate the application. You can also pass the exception to your application using the Pass Exception (GZ) command. If the application does not have a handler for the exception, the exception is passed back to CodeView for second-chance handling. If you use the Pass Exception command a second time, Windows will terminate your aplication.

To find the number of an exception you want to disable, use the List Exceptions (SXL) command to display a list of the names and numbers of common exceptions.

Example

The following example enables CodeView first-chance handling of the Integer Overflow exception.

>SXE 0xC0000095
>


SX (List Exception Handling Status)
  SXL (List Exception Handling Status)

Syntax

SXL {list | *}

Parameters

list

List of exception handlers to be displayed, with exception numbers separated by spaces. A number identifies each exception handler.

*

Disables all currently enabled exception handlers.

Description

The List Exceptions (SXL) command displays a list of common exceptions. The exception is listed as enabled if it is passed to CodeView for first-chance handling. If the exception is passed directly to the application, it is listed as disabled.


  T (Trace)

Syntax

T [count]

Parameters

count

Repeat tracing count times. If omitted, trace once.

Description

The Trace (T) command executes the current line (in Source mode) or instruction (in Assembly or Mixed mode), tracing into functions or assembly-language CALL instructions. Use the Program Step (P) command to execute function calls without tracing into them.

In Source mode, the Trace command traces into functions whose source code is available and executes through those functions whose source is unavailable.

In Assembly or Mixed mode, CodeView always traces into functions. If the current instruction is CALL or INT, CodeView executes the first instruction of the procedure or interrupt. If the current instruction is REP, CodeView executes one iteration of the repeated string sequence.

CodeView executes MS-DOS function calls without tracing into them. CodeView can trace through BIOS calls in Assembly or Mixed mode.

Since the Trace command uses the hardware trace mode of the 8086 family of processors, you can also trace instructions stored in read-only memory (ROM). However, the Program Step command does not work in ROM; in this case, it has the same effect as the Go (G) command.

Mouse and Keyboard

In addition to typing the T command, you can trace once with the following shortcuts:

•	Click the <Trace> button in the status bar.

•	Press F8.

•	From the Run menu, choose Trace.


  T (Trace Speed)

Syntax

T{S|M|F}

Parameter

{S|M|F}

Specifies the trace speed for the Animate (E) command. You can specify the following speeds:

Specifier	Speed
S	Slow (1/2 second between steps)
M	Medium (1/4 second between steps; default)
F	Fast (no wait between steps)
Description

The Trace Speed command controls the speed at which CodeView executes a program with the Animate (E) command.

Mouse and Keyboard

In addition to typing the TS, TM, or TF commands, you can also set the trace speed in the Preferences dialog box from the Options menu. There is no keyboard shortcut.


  U (Unassemble)

Syntax

U [context][address]

Parameters

context

Any legal context operator.

address

Shows unassembled instructions starting at this address. If omitted, unassemble at the current EIP address.

Description

The Unassemble (U) command displays assembly-language code beginning at the specified address in the active Source window. If you omit an address, the command uses the current EIP address. The command changes the Source window to Assembly mode.

Setting the Source window display mode to Assembly and giving the Unassemble command with no arguments causes the code to scroll to the next page of assembly-language instructions.

Note  If you specify an address that is within an instruction or within program data, CodeView will still attempt to disassemble and display instructions. Instructions that CodeView cannot disassemble are shown as ???.

Mouse and Keyboard

As an alternative to typing the U command, you can display assembly-language instructions using the following shortcuts:

•	Click the <F3=Src1 Fmt> or <F3=Src2 Fmt> buttons until the active Source window is in Assembly mode.

•	Press F3 until the Source window is in Assembly mode.

•	From the Options menu, choose Source Window. Then set the display mode to Assembly.

Note that with these shortcuts, you cannot specify an address to start showing unassembled instructions.

Example

The following example sets the mode of the Source window to Assembly and displays assembly-language instructions beginning at address 0x80c113aa.

>U 0x80c113aae
>


  VM (View Memory)

Syntax

VM[window] [type] [address] [options]

Parameters

window

Specifies the memory window to display or change (1 or 2). If a value for window is omitted, the command defaults to the active Memory window or Memory window 1 if no Memory windows are open.

type

Specifies the data-type format of the window's display.

Specifier	Type
A	ASCII characters
B	Byte (hexadecimal)
D	DWord
I	Integer (2-byte decimal)
IU	Integer unsigned (2-byte decimal)
IX	Integer hex (2-byte hexadecimal)
L	Long (4-byte decimal)
LU	Long unsigned (4-byte decimal)
LX	Long hex (4-byte hexadecimal)
R	Real (4-byte float)
RL	Real long (8-byte float)
RT	Real ten-byte (10-byte float)
SU	Short unsigned (2-byte decimal)
SX	Short hex (2-byte hexadecimal)
W	Word (hexadecimal)
If format is omitted, the command defaults to the last type used by a View Memory (VM) command or to byte-display format if the VM command was never used.

address

Starting address of memory to display or any expression that evaluates to an address. If address is omitted, the command defaults to the current address in the active Memory window or 0x00000000 if no Memory windows are open.

options

Specifies how to display and update the Memory window's contents.

/R[+|−]

Raw data display

Option	Description
+	CodeView displays formatted data along with the corresponding bytes in hexadecimal format.
− (default)	CodeView displays only formatted data.
/L[+|−]

Live expression

Option	Description
+	Dynamic: CodeView evaluates address at each step and adjusts the Memory window accordingly.
− (default)	Static: CodeView evaluates address only when the command is entered.
/F[*| length]

Fixed-width data display

Option	Description
* (default)	CodeView displays as many items as will fit in the window.
length	CodeView displays a fixed number of items on each line. Must be in the range 1 − 125.
Description

The View Memory (VM) command displays the contents of memory in a Memory window using the type and format you specify. The Memory window is updated whenever you execute a command. You can modify memory in the window directly by typing over the displayed memory.

If you enter the VM command with no arguments and no Memory windows are open, CodeView opens Memory window 1 in the default display format (variable-width byte display at a static address). If you enter the VM command with no arguments and at least one Memory window is open, CodeView displays the current settings for the Memory windows in the Command window.

You can directly modify memory using the Memory window. Type over the values displayed in the active Memory window.

To display the contents of memory in the Command window, use the Memory Dump (MD) command.

Mouse and Keyboard

In addition to typing the VM command, you can open and manipulate Memory windows with the following shortcuts:

•	To open a Memory window from the Windows menu, choose Memory 1 or Memory 2.

•	To set display format and enter expressions for a Memory window, choose Memory Window from the Options menu.

You can cycle through the display formats with the following shortcuts:

•	Click the <Sh+F3=M1 Fmt> or <Sh+F3=M2 Fmt> buttons in the status bar.

•	Press SHIFT+F3 to cycle forward.

•	Press CTRL+SHIFT+F3 to cycle backward.

•	When the cursor is in the Memory window, press CTRL+O to display the Memory Window Options dialog box.

Examples

The following example opens Memory window 2 and displays memory in integer format plus the raw bytes that make up the integers, beginning at the address of the variable myint.

>VM2I myint /R

The following example specifies ASCII format for the current Memory window. The memory displayed begins at the string referred to by element i of the array argv. The expression is live, so the display is updated as i changes.

>VMA *argv[i] /L


  VS (View Source)

Syntax

VS[window] [format] [address] [/option[+| − ] ]

Parameters

If no parameters are specified, the VS command displays the currently enabled options.

window

Specifies the Source window (1 or 2) to open or make active.

format

Specifies the way to display source code as one of the following:

Specifier	Format
+	Display source lines from the source file
−	Display assembly-language instructions
&	Display both source lines and assembly-language instructions
address

Address or line number at which to start displaying source code. The address must fall within the executable portion of your program.

[/option[+|−] ]

Zero or more source display options. The option can be any of the following specifiers:

Specifier	Option
a	Address
	When turned on (/a[+]), displays the address of each instruction. When turned off (/a − ), does not display addresses.
b	Bytes coded
	When turned on (/b[+]), displays the hexadecimal form of the instructions. When turned off (/b − ), does not display the encoded bytes.
c	Case of disassembly
	When turned on (/c[+]), displays instruction mnemonics and registers in uppercase. When turned off (/c − ), displays instruction mnemonics and registers in lowercase.
l	Line-oriented display
	When turned on (/l[+]), displays mixed source and assembly in source-line order. When turned off (/l − ), displays mixed source and assembly in instruction-code order.
s	Symbols in disassembly
	When turned on (/s[+]), symbols in instructions appear in symbolic form. If turned off (/s − ), they appear as addresses.
t	Track current location (EIP)
	When turned on (/t[+]), the Source window follows the thread of execution (EIP). When turned off (/t − ), the Source window does not automatically scroll to follow the current location.
Description

CodeView can display two Source windows at the same time. At least one Source window must always be open. You can type the VS 1 or VS 2 command to make Source window 1 or 2 active. If the Source window you request is not open, CodeView opens it and makes it active.

The Source windows can show code in a number of display modes:

Source

CodeView displays the lines from your program's source files.

Assembly

CodeView displays the assembly instructions that make up your program.

Mixed

CodeView displays each line of your program's source file, followed by the assembly instructions for that line. This ordering can be reversed by turning the Line-Oriented Display option off (/l − ).

Source and Mixed modes are available only if the executable file contains debugging information.

Note  Programs that do not contain debugging information are always displayed in Assembly mode.

In the Source and Mixed modes, tracing into a function for which no source lines are available, such as a library function, switches the Source window to Assembly mode. Once program execution returns to an area where source lines are available again, CodeView automatically switches back to Source or Mixed mode.

If you specify a line number or an address with the VS command, CodeView draws the Source window so that the source line corresponding to the given address appears in the middle of the Source window. If the address is in another file, CodeView loads that file into the Source window. If you specify an address for which there is no corresponding source text (in your program's data, for example), CodeView will respond with an error message.

You can view the current options by typing the VS command with no arguments.

Mouse and Keyboard

To make a Source window active or to open a Source window:

•	Click anywhere in an open Source window to make it active.

•	Press ALT+3 or ALT+4 to activate or open Source window 1 or 2.

•	From the Windows menu, choose Source 1 or Source 2.

To change the source display mode:

•	Click the <F3=S1 Fmt> or <F3=S2 Fmt> buttons in the status bar to cycle through the three modes.

•	Press F3 to cycle forward.

•	Press CTRL+F3 to cycle backward.

•	From the Options menu, choose Source Window to open the Source Window Options dialog box. Under Display Mode, select one of the option buttons.

•	When the cursor is in the Source window, press CTRL+O to display the Source Window Options dialog box.

Examples

The following example opens Source window 2 in the mixed mode. The display will start at the function toss_token.

>VS2& toss_token

The next example changes the display format in Source window 2 to source lines only.

>VS2+


  W? (Add Watch Expression)

Syntax

W? expression [, format]

Parameters

expression

Expression to add to the Watch window.

format

A CodeView format specifier that indicates the format in which expression is displayed.

Description

The Add Watch Expression (W?) command displays one or more specified values in the Watch window. Watch expressions allow you to watch how a variable changes as your program executes. CodeView updates the Watch window each time the value of the watch expression changes during program execution.

The Watch window shows variables in the default format for their types. To display a watch expression in a different format, type a comma after the expression, followed by a CodeView format specifier. You can also cast the expression to the format you want to use.

CodeView always evaluates watch expressions according to the current radix and reevaluates watch expressions if the radix changes.

For relational expressions, the Watch window shows 0 if the expression is false and 1 if the expression is true.

Mouse and Keyboard

As an alternative to typing the W? command, choose the Add Watch command from the Data menu or type CTRL+W.

Examples

Command	Action
W? n	Display the value of the variable n in the Watch window.
W? high * 100	Display the value of 100 times the variable high in the Watch window.
W? (char *) 0	Display the byte at 0x00000000. Because 0 is explicitly cast to a pointer type, CodeView treats it as an offset rather than a constant.


  WC (Delete Watch Expression)

Syntax

WC number|*

Parameters

number

Deletes the watch expression with this number.

*

Deletes all watch expressions.

Description

The Delete Watch Expression (WC) command removes a watch expression from the Watch window.

When you set a watch expression, CodeView automatically assigns it a number, starting with 0 for the first watch expression in the window. Use the List Watch (WL) command to view the numbers of current watch statements.

Mouse and Keyboard

In addition to typing the WC command, you can use the following shortcuts to delete watch expressions:

•	From the Data menu, choose Delete Watch.

•	Select the Watch window, move the cursor to the watch expression, and press CTRL+Y.

Examples

The following example deletes watch expression 2 from the Watch window:

>WC 2

The following example deletes all watch expressions from the Watch window:

>WC *


  WKA (Windows Kill Application)

Syntax

WKA

Description

The Windows Kill Application (WKA) command terminates the application being debugged.

The WKA command does not perform all the cleanup tasks associated with the normal termination of a Windows-based application.

For example, global objects created during the execution of the program but not destroyed before you terminated the program remain allocated in the global heap. This reduces the amount of memory available during the rest of the Windows session. For this reason, you should use the WKA command to terminate the application only if you cannot terminate it normally.


  WL (List Watch Expressions)

Syntax

WL

Description

The List Watch Expressions (WL) command lists all currently set watch expressions along with their numbers and values.

Mouse and Keyboard

As an alternative to typing the WL command, you can use the Watch window to view the current watch expressions.

Example

The following example displays watch expressions and their values:

>WL
0) code  :  17
1) (float)letters/words  :  4.777778
2) lines==11  :  0
>

In the example, three watch expressions are set:

1.	The variable code, which is 17.

2.	The arithmetic expression letters divided by words as a floating point number, currently 4.777778.

3.	The conditional expression lines==11, currently false (zero).


  X (Examine Symbols)

Syntax

Xscope [context][regex]

Parameters

scope

Specifies the scope in which to search for symbols. Can be one or more of the following:

Specifier	Scope
L	Lexical
F	Function
M	Module
E	Executable
P	Public
G	Global
*	All of the above
context

Specifies context under which to search with the context operator.

regex

Specifies a CodeView regular expression.

Description

The Examine Symbols (X) command displays the names and addresses of symbols and the names of modules defined within a program. You can specify the scope in which to search and a regular expression against which to match symbols. You can further specify a context using the context operator.

For more information on regular expressions, see »The Search Menu«.

Examples

The following example shows all the symbols and their addresses in the current lexical scope. The command uses the regular expression .* to match any symbol.

>XL .*

The following example displays all symbols and their addresses in the program that start with s_:

>XE ^s_.*


  " (Pause)

Syntax

"

Description

The Pause (") command interrupts the execution of commands from a redirected file and waits for the user to press a key. Execution of the redirected commands begins as soon as a key is pressed.

Example

The following example is from a text file redirected to the CodeView debugger. A Comment (*) command is used to prompt the user to press a key. The Pause (") command is then used to halt execution until the user responds.

* Press any key to continue
"


  # (Tab Set)

Syntax

#number

Parameter

number

Number of characters for new tab stops. The valid range for number is 1 − 19.

Description

The Tab Set (#) command sets the width in spaces that the CodeView debugger fills for each tab character. The default tab is eight spaces. You can specify values in the range 1 − 19.

You may want to set a smaller tab size if your source code has so many levels of indentation that source lines extend beyond the edge of the screen.

This command has no effect if your source code contains no tab characters.


  * (Comment)

Syntax

*comment

Description

The Comment command is an asterisk (*) followed by text. The CodeView debugger echoes the text of the comment to the screen or other output device. Use this command in combination with the redirection commands when you are:

•	Saving a commented session.

•	Writing a commented session that will be redirected to the debugger.

Example

In the following example, the user is sending a copy of a CodeView session to the file OUTPUT.TXT. Comments are added to explain the purpose of the command. The text file will contain commands, comments, and command output.

> T>OUTPUT.TXT
> * Dump first 20 bytes of screen buffer
> MDB 0x80000000 L 20
80000000 54 17 6F 17 20 17 72 17 65 17 74 17 75 17 72 17
80000010 6E 17 20 17
> >CON


  . (Current Location)

Syntax

.

Description

The Current Location (.) command displays the source line or assembly-language instruction corresponding to the current program location. It puts the current program location in the center of the active Source window.

Use this command if you have scrolled the current source line or assembly instruction out of the active Source window.

The Current Location (.) command is equivalent to the command:

VS .


  / (Search)

Syntax

/ [regexp]

Parameter

regexp

Searches for the first line containing this regular expression. If omitted, the command searches for the next occurrence of the last regular expression given.

Description

The Search (/) command searches for a regular expression in a source file.

"Regular expressions" are patterns of characters that may match one or many different strings. The use of patterns to match more than one string is similar to the MS-DOS method of using wildcard characters in filenames.

CodeView's regular expressions use a subset of the UNIX syntax. For a list of regular expressions in CodeView, see »Find«.

When you enter the Search command with a regular expression, CodeView searches the source file for the first line containing the expression. If you do not give a regular expression, CodeView searches for the next occurrence of the last regular expression specified.

Even if you do not understand regular expressions, you can still use the Search command with plain text strings, since text strings are the simplest form of regular expressions. For example, you can enter

>/ COUNT

to search for the word COUNT in the source file.

To find strings containing a special regular expression character ( .\^$*[] ), you must precede the character with a backslash (\); this cancels the character's special meaning. For example, use the command:

>/ x\*y

to find the string x*y.

In Source windows, CodeView starts searching at the current cursor position and places the cursor at the line containing the regular expression. The search wraps to the beginning of the file if necessary.

Mouse and Keyboard

In addition to typing the / command, you can also search for regular expressions by choosing Find from the Search menu.

Remarks

When you search for the next occurrence of a regular expression, CodeView searches to the end of the file, then wraps around and begins again at the start of the file. This search can have unexpected results if the expression occurs only once. For example, when you give the command repeatedly, there is no activity on the screen. Actually, CodeView is repeatedly wrapping around and finding the same expression each time.

The Case Sensitivity command on the Options menu and the Options Case Sense (OC) command affect regular expression searches.

If you want to find a label in your source code, you can also use the View Source (VS) command.


  7 (8087)

Syntax

7

Description

The 8087 (7) command dumps the contents of the math processor registers. If you do not have an 80387 or equivalent math processor chip, this command dumps the contents of the software-emulated registers.

Example

The following example shows and describes the output from the 7 command:

cControl 037F  (Closure=Projective  Round=nearest, Precision=64-bit   )
                         IEM=0 PM=1 UM=1 OM=1 ZM=1 DM=1 IM=1
cStatus  6004  cond=1000 top=4 PE=0 UE=0 OE=0 ZE=1 DE=0 IE=0
Tag     A1FF   instruction=59380  operand=59360  op-code=D9EE
Stack          Exp  Mantissa           Value
cST(3) special 7FFF 8000000000000000 = + Infinity
cST(2) special 7FFF 0101010101010101 = + Not A Number
cST(1) valid   4000 C90FDAA22168C235 = +3.141592265110390E+000
cST(0) zero    0000 0000000000000000 = +0.000000000000000E+000

Here, the lowercase c that precedes several lines of the output indicates that the coprocessor is in use. If this command had been used with an emulated coprocessor, an e would precede the lines. The following is a line-by-line description of the output from the 7 command:

Line 1  This line shows the value in the control register, 037F. The rest of the line interprets the bits represented by the number in the control register:

•	The closure method, which can be projective or affine.

•	The rounding method, which can be nearest (even), down, up, or chop (truncate to zero).

•	The precision, which can be 64, 53, or 24 bits.

Line 2  This line lists the status of the exception-mask bits, described in the following table.

Name	Description
IEM	Interrupt enable
PM	Precision
UM	Underflow
OM	Overflow
ZM	Zero divide
DM	Denormalized operand
IM	Invalid operation
Line 3   This line lists the value in the status register (6004 hexadecimal), the condition code (1000 binary), and the top of stack register (4 decimal). It then lists the exception flags, described in the following table.

Flag	Meaning
PE	Precision
UE	Underflow
OE	Overflow
ZE	Zero divide
DE	Denormalized operand
IE	Invalid operation
Line 4  This line lists the 20-bit address of the tag register, the offset of the instruction, the offset of the operand, and the offset of the op-code, all in hexadecimal. When you are debugging software-emulated coprocessor routines, this line does not appear.

Lines 5−9  The rest of the output from the 8087 command lists the contents of the stack register. In this example, ST(3) contains the value infinity, ST(2) contains a value that cannot be interpreted as any number, ST(1) contains a real number, and ST(0) contains zero.


  : (Delay)

Syntax

:

Description

The Delay (:) command interrupts execution of commands from a redirected file and waits about half a second before continuing. You can put multiple Delay commands on a single line to increase the length of delay. The delay is the same length regardless of the processing speed of the computer.

Example

In the following example, the Delay (:) command is used to slow execution of the redirected file into CodeView.

: ;* That was a short delay...
::::: ;* That was a longer delay...


  < (Redirect CodeView Input)

Syntax

<device

Parameter

device

Device or file from which to read commands.

Description

The Redirect Input (<) command causes CodeView to read all subsequent command input from a file or device.

Example

The following example redirects command input from the file INFILE.TXT to CodeView. Use this method to run "scripts" of CodeView commands that you have prepared in advance.

> <INFILE.TXT

You can also start up CodeView with redirected input by typing the following at the operating-system prompt:

CVW /C"<infile.txt"


  > (Redirect CodeView Output)

Syntax

[T]>[>] device

Parameter

device

Device or file to which to write output.

Description

The Redirect Output (>) command causes CodeView to write all subsequent command output to a device, such as another terminal, a printer, or a file. The term "output" includes not only output from commands but also the command characters that are echoed as you type them.

The optional T indicates that the output should be echoed to the CodeView screen. If you do not give a T, CodeView echoes only commands that you enter. Use the T option if you are redirecting output to a file to see output from the commands that you are typing.

Note  If you are redirecting output to another terminal, you may not want to see the output on the CodeView terminal.

If you specify an existing file, CodeView truncates the file and then starts writing output. To preserve the contents of the file, use a second greater-than symbol (>>), which appends output to the file.

Example

In the following example, output is redirected to the device designated as COM1 (for example, a remote terminal). Enter this command when you are debugging a graphics program and you want CodeView commands to be displayed on a remote terminal while the program display appears on the originating terminal.

> >COM1

In the following example, output is redirected to the file OUTFILE.TXT. Use this command to keep a permanent record of a CodeView session.

> T>OUTFILE.TXT
  . . .
> >CON
  . . .

Note  The optional T is used so that the session is echoed to the CodeView screen as well as to the file. After redirecting some commands to a file, use the command >CON to return output to the terminal.


  = (Redirect CodeView Input and Output)

Syntax

= device

Parameter

device

Device to which to redirect input and output. Specify >CON for the CodeView Command window.

Description

The Redirect Input and Output (=) command causes the CodeView debugger to read all subsequent command input from the device and write all subsequent output to the device. You cannot redirect both input and output to a file.

To reset the input and output for CodeView after you have entered one of the other redirection commands, use the command:

>= con


  ? (Display Expression)

Syntax

? expression[ , format]

Parameters

expression

The expression to display. This can be any valid CodeView expression.

, format

A CodeView format specifier that indicates the format in which to display expression.

Description

The Display Expression (?) command displays the value of a CodeView expression. The simplest form of expression is a symbol representing a single variable or function. An expression may also call functions that are part of the executable file.

The Display Expression command can also set values. For example, with the expression evaluator, you can increment the variable n by using an assignment expression:

? n=n+1

The command displays the value after incrementing n.

You can specify the format in which the values of expressions are displayed by using the Display Expression command. After the expression, type a comma, followed by a CodeView format specifier.

Example

The following example displays the value stored in the variable amount, an integer. This value is first displayed in the system radix (in this case, decimal), then in hexadecimal, then in 4-byte hexadecimal, and then in octal.

>? amount
500
>? amount,x
0x01f4
>? amount,lx
0x000001f4
>? amount,o
764
>


  ?? (Quick Watch)

Syntax

?? symbol

Parameter

symbol

Displays the given variable, array, or structure in the Quick Watch dialog box.

Description

The Quick Watch (??) command displays the value of any selected expression in the Quick Watch dialog box. You can use Quick Watch to quickly check the value of a variable or structure and expand or contract items in a structure.

Expanding/Contracting Items

The Quick Watch dialog box allows you to:

•	Expand or contract nested structures and arrays.

•	View variables, structures, or arrays addressed by pointers.

•	Add any structure or array to the Watch window.

Expandable items appear with a plus sign (+) in the Quick Watch dialog box. Once expanded, an item appears with a minus sign ( − ).

Expanding an item has the following effects:

Item	Action
Nested structure	Expands the structure so that the dialog box displays each member of the nested structure.
Pointer	Dereferences the pointer; that is, displays the data that the pointer addresses.
Array	Expands the array so that the dialog box displays each element of the array.
Contracting an item reverses the effects of expanding described above.

Note  You can add any expression in the Quick Watch dialog box to the Watch window by choosing the Add Watch button.

Mouse and Keyboard

After opening the Quick Watch dialog box, you can expand or contract an item using the following methods:

•	Double-click the left mouse button on the item.

•	Select the item, then choose the Expand/Contract button at the bottom of the dialog box.

•	Use the arrow keys to select the item, and press ENTER.


  @ (Redraw)

Syntax

@

Description

The Redraw (@) command redraws the CodeView screen. Use this command if the output of the program being debugged disturbs the CodeView display.


  Appendix A  Shortcut Key Summaries

The tables in this appendix list keyboard shortcuts for CodeView tasks. They are grouped according to function.


  Editing Keys

Table A.1    Insertion Point Movement Keys

To move the insertion point	Press
One character left	LEFT ARROW
One character right	RIGHT ARROW
One word left	CTRL+LEFT ARROW
One word right	CTRL+RIGHT ARROW
One line up	UP ARROW
One line down	DOWN ARROW
To the end of line	END
To the beginning of file	CTRL+HOME
To the end of file	CTRL+END
Table A.2    Text Selection Keys

To select	Press
Character to the left	SHIFT+LEFT ARROW
Character to the right	SHIFT+RIGHT ARROW
One word to the left	CTRL+SHIFT+LEFT ARROW
One word to the right	CTRL+SHIFT+RIGHT ARROW
Current line	SHIFT+DOWN ARROW
Line above	SHIFT+UP ARROW
To end of line	SHIFT+END
To beginning of line	SHIFT+HOME
One screen up	SHIFT+PAGE UP
One screen down	SHIFT+PAGE DOWN
To beginning of file	CTRL+SHIFT+HOME
To end of file	CTRL+SHIFT+END
Table A.3    Insert, Copy, Undo, and Delete Keys

To	Press
Insert contents of Clipboard	SHIFT+INS
Copy selected text to Clipboard	CTRL+INS
Undo the last edit	ALT+BACKSPACE
Delete one character to the left	BACKSPACE
Delete one character to the right	DEL
Table A.4    Text Scrolling Keys

To scroll	Press
Up one line at a time	CTRL+UP ARROW
Down one line at a time	CTRL+DOWN ARROW
Up one page at a time	PAGE UP
Down one page at a time	PAGE DOWN
Left one window width	CTRL+page up
Right one window width	CTRL+page down
Table A.5    Search Keys

To	Press
Find the selected text (forwards)	CTRL+\
Repeat the last find	CTRL+R
Open the Find dialog box	CTRL+F


  Window Management Keys

Table A.6    CodeView Window Management Keys

To	Press
Switch to the next window (includes all windows)	F6
Switch to the previous window (includes all windows)	SHIFT+F6
Close the active window	CTRL+F4
Restore window	CTRL+F5
Move window	CTRL+F7
Size window	CTRL+F8
Minimize window	CTRL+F9
Maximize window	CTRL+F10
Tile window	SHIFT+F5
Arrange window	ALT+F5
View Output	F4
In a Register Window:
Move to next register	TAB
Move to previous register	SHIFT+TAB
Move to the first register of the line	HOME
Move to the last register of the line	END
Move to the first register	CTRL+HOME
Move to the last register	CTRL+END
Activate Help window	ALT+0
Activate Locals window	ALT+1
Activate Watch window	ALT+2
Activate Source1 window	ALT+3
Activate Source2 window	ALT+4
Activate Memory1 window	ALT+5
Activate Memory2 window	ALT+6
Activate Registers window	ALT+7
Activate 8087 window	ALT+8
Activate Command window	ALT+9


  Debugging Keys

Table A.7    Debugging Keys

To	Press
Continue execution from current statement (Go)	F5
Execute program to insertion point position (Go To Cursor)	F7
Execute next statement, tracing into function calls (Trace)	F8
Single-step, stepping over functions calls (Step)	F10
Execute program out of current function and stop on first line after function call (Stop After Return)	SHIFT+F7
Open QuickWatch dialog box	SHIFT+F9
Open Breakpoints dialog box	CTRL+B
Toggle breakpoint	F9
Toggle mixed mode	CTRL+F7
Add Watch dialog box	CTRL+W
Delete Watch dialog box	CTRL+U


CodeView Display


CodeView Window Elements


Introduction
32-Bit Source Profiler User's Guide

Introduction

The Microsoft® 32-Bit Source Profiler is a powerful analysis tool that you can use to examine the run-time behavior of your programs. By using the information given by the profiler, you can find out which sections of your code are working efficiently and which need to be examined more carefully. The 32-Bit Source Profiler can also give you diagnostic information that shows areas of code that are not being executed.

The 32-Bit Source Profiler fully supports Microsoft Windows ( ) NT™. Both 32-bit window-oriented programs and 32-bit console applications can be profiled at the function level without modification. Microsoft CodeView® debugging information is necessary only for line-level profiling.


Book Locations
32-Bit Source Profiler User's Guide


   About This User's Guide

The 32-Bit Source Profiler User's Guide begins with a »Profiler Tutorial« chapter  that is based on a Microsoft Foundation Class C++ application. A »Profiler Basics« chapter describes the batch processing flow and highlights the differences among profiling options. The last chapter, »Special Topics,« covers the profiling of inline functions, dynamic link libraries, console programs, and multithreaded applications. Reference information is contained in the appendixes.

Note  For information on Microsoft product support, see the chapter Microsoft Support Services, in the Visual Workbench User's Guide.


   Document Conventions

This book uses the following typographic conventions:

Examples	Description
BSORT.EXE, COPY,  PREP, /FS	Uppercase letters indicate filenames and console commands. Uppercase is also used for command-line options.
PREP	Bold letters indicate required program names in syntax statements.
expression	Words in italic indicate placeholders for information that you must supply (for example, a function argument).
[option]	Items inside square brackets are optional.
{choice1 | choice2}	Braces and a vertical bar indicate a choice between two or more items. You must choose one of the items unless all the items are also enclosed in square brackets.
FCOUNT BSORT	This font is used for user-defined program variables, program examples, user input, program output, and error messages within the text.
Repeating elements...	Three dots (an ellipsis) following an item indicate that more items having the same form may be entered.
F1, ALT+A	Small capital letters indicate the names of keys and key sequences, such as ENTER and CTRL+C. A plus sign (+) indicates a combination of keys. For example, CTRL+E means to hold down the CTRL key while pressing the  E key.
page up/page down	The cursor-movement keys on the numeric keypad are called ARROW keys. Individual ARROW keys are referred to by the direction of the arrow on the top of the key (LEFT, RIGHT, UP, DOWN) or the name on the top of the key (PAGE UP, PAGE DOWN).
"defined term"	Quotation marks usually indicate a new term defined in the text.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  New Features in the 32-Bit Version

The 32-Bit Source Profiler provides features including:

•	A visual user interface that integrates with the Visual Workbench.

•	A faster, more efficient function-level profiling technique.

•	Streamlined syntax for specifying source lines to be profiled.

•	Full support for the C++ language and the Microsoft Foundation Classes.


   16-Bit/32-Bit Considerations

The profiler described in this book is the 32-Bit Source Code Profiler for use with Windows NT and 32-bit programs. With some adjustments, as described in »Profiling Win32s Applications on Windows 3.x,« Appendix C, this profiler can be used in the Win32s (™)  environment.

Visual C++ for Windows 3.x includes a separate profiler  ( ) that profiles 16-bit programs for MS-DOS and Windows 3.x . There are similarities and differences between the two profilers. Be careful not to assume that any feature of one applies to the other.


   Installing the Profiler

The Microsoft Visual C++ Setup program (SETUP.EXE) installs all the necessary 32-Bit Source Profiler files and configures the profiler for your selected environment.

If the profiler files have been deleted, you must run the Setup program again to reinstall all Visual C++ components. For further information on the Setup program, see the Visual Workbench User's Guide.

You must run the Setup program to install the Microsoft 32-Bit Source Profiler. The files on the distribution disks are compressed; the Setup program uncompresses the files and copies them to your hard disk.


  Chapter 1  Profiler Tutorial

This chapter shows how to profile a Windows NT Microsoft Foundation Classes program with the Microsoft 32-Bit Source Profiler. By following this tutorial, you will learn the steps for successfully profiling your programs.

The chapter should take about an hour to complete. Because the profiler saves intermediate data in files instead of RAM, you can stop after any step in the tutorial without losing data.

This chapter uses the sample files installed by the Setup program when you installed the profiler. Also, the Microsoft Foundation Classes must be installed. If you did not copy these files, you must run Setup again to copy them for use in the tutorial.

When you are finished working through this chapter, you should be able to:

•	Select the proper profiling method to obtain the information you want.

•	Run the profiler interactively from the Visual Workbench.

•	Write batch files that exploit advanced profiler options.


  Introduction to BSORT

The program used in this chapter is called BSORT.  BSORT is a C++ Microsoft Foundation Classes program that sorts text lines in a window. You can type text directly into the window, or you can paste the text from the Clipboard.  After you enter the text, you can "update" the underlying document, sort the document (which refreshes the window), and then save the document to disk. Saved documents can be retrieved for further processing.


  The Bubble Sort Algorithm

BSORT sorts a list of strings using the bubble sort algorithm, a simple but effective sorting method that works by:

1.	Comparing each element in the list, starting at the top, with the following element; if the second is greater than the first, swapping the elements.

2.	Repeating step 1 until there is a complete pass through the list with no swapping.

This algorithm is useful for sorting data in list structures that provide no indexed access to elements.


  The CSortStringList Class

The BSORT program uses a special string list class derived from the standard framework CStringList class.  This derived class has the added member functions Sort and CompareAndSwap.  The public Sort function sorts the strings in ascending order, and the private CompareAndSwap function, called by Sort, compares adjacent strings and swaps them if necessary.  You will be profiling the Sort and CompareAndSwap functions, together with all the framework, Windows NT, and run-time functions they call.

The CSortStringList class is declared as:

// sortstr.h -- sortable string list class declaration

class CSortStringList : public CStringList

{

public:

void Sort();

private:

BOOL CompareAndSwap(POSITION& pos);

};

The Sort function looks like this:

void CSortStringList::Sort()

{

POSITION pos;

BOOL bNotDone = TRUE;

while(bNotDone) {

bNotDone = FALSE;

for(pos = GetHeadPosition(); pos != NULL;) {

bNotDone |= CompareAndSwap(pos);

}

}

}

and the CompareAndSwap function looks like this:

BOOL CSortStringList::CompareAndSwap(POSITION& pos)

{   // slow version

CString temp;

POSITION posFirst = pos;

GetNext(pos);

if(pos != NULL) {

if(GetAt(posFirst) > GetAt(pos)) {

temp = GetAt(posFirst);

SetAt(posFirst, GetAt(pos));

SetAt(pos, temp);

return TRUE;

}

}

return FALSE;

}


  The BSORT Program

You don't need to fully understand the BSORT program to complete the profiling exercise.  In summary, BSORT is a standard Multiple Document Interface (MDI) framework application that uses a view class derived from CEditView.  The document class,  CStringDoc, contains an embedded list m_lines of class CSortStringList.  The Update choice in the Data menu, handled by the view class, copies the edit window contents to the document.  The Sort choice, handled by the document class, sorts the list and updates the view.  Here is the code for the Sort command handler:

void CStringDoc::OnSort()

{

BeginWaitCursor();

m_lines.Sort();

SetModifiedFlag();

EndWaitCursor();

UpdateAllViews(NULL);

}


  Selecting the Sample Directory

The example code used in this tutorial is contained in the MSVCNT\SAMPLES\PROFILER directory. The location of this directory may vary depending on whether you used the default during installation.


  Building BSORT

The PROFILER directory contains a Visual Workbench project makefile, BSORT.MAK, that builds the executable BSORT program.  The project file specifies full debugging information, which is necessary only for line-level profiling.  The makefile also specifies no optimizations, which makes profiling more accurate.

To build BSORT, open the BSORT project in Visual Workbench, and then choose Build from the Project menu.


  Testing BSORT

Before profiling BSORT, verify that the program works by running it.  You can run it from Visual Workbench or from Program Manager.  Type 10 lines as shown in »Figure 1.1,« and then choose Update from the Data menu.  Save the document on your hard disk (with the Save As choice from the File menu), and then choose Sort from the Data menu.


  Modifying TOOLS.INI for Profiling BSORT

The Visual C++ Setup program creates a TOOLS.INI file in the install directory (\MSVCNT by default). The Profiler section of this file contains the following lines:

[profiler]

exclude:comdlg32.lib

exclude:gdi32.lib

exclude:nt.lib

exclude:ntdll.lib

exclude:pwin32.lib

exclude:user32.lib

exclude:kernel32.lib

exclude:libfps.lib

exclude:oldnames.lib

exclude:shell32.lib

exclude:userrtl.lib

exclude:nafxcw.lib

exclude:nafxcwd.lib

exclude:libc.lib

exclude:libcmt.lib

exclude:msvcrt.lib

exclude:crtdll.lib

These TOOLS.INI lines exclude all library functions from profiling. To make the BSORT profiling exercise work correctly, you must eliminate these lines, thereby including all library functions for profiling. (If you insert a semicolon at the start of a TOOLS.INI line, that line will be treated as a comment.)


  Running the Profiler

You are now ready to profile the BSORT program. From the Visual Workbench, choose Profile from the Debug menu. A dialog box appears as shown in »Figure 1.2.«

In the remainder of this chapter, you will experiment with the profiler options that are accessible from this dialog box.


  Function Sampling

Function sampling is the easiest profiling option because you don't have to specify parameters; you profile the entire BSORT program with all its functions.  Just follow these steps to try function sampling:

1.	Select the Function Sampling radio button.

2.	Choose the OK button. Do not type anything in the Options edit control.

3.	After a 10-second pause, BSORT starts. Sort some strings, and then exit the program.

4.	Study the output report that appears in the Visual Workbench Output-Profile window.  Here is the beginning of the report:

Profile: Function sampling, sorted by count

Date:    Wed Apr 21 08:37:14 1993

Program Statistics

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

    Command line at 1993 Apr 21 08:36: BSORT

    Total functions: 3237

    Total hits: 14976

    Function coverage: 14.0%

Module Statistics for c:\bsort\bsort.exe

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

    Functions in module: 3237

    Hits in module: 14976

    Module function coverage: 14.0%

   Hit

  Count    %   Function

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

    1494  10.0 _AfxIsValidAddress@12 (validadd.obj)

    1389   9.3 _AfxFindMessageEntry(struct AFX_MSGMAP_ENTRY *,unsigned int,unsigned int)

     941   6.3 _AfxAssertValidObject@12 (objcore.obj)

     647   4.3 CCmdTarget::OnCmdMsg(unsigned int,int,void *,struct AFX_CMDHANDLERINFO *)

     565   3.8 CWnd::AssertValid() (wincore.obj)

     458   3.1 CMapPtrToPtr::GetAssocAt(void *,unsigned int &) (map_pp.obj)

     336   2.2 CObject::IsKindOf(struct CRuntimeClass const *) (objcore.obj)

     329   2.2 CMapPtrToPtr::Lookup(void *,void * &) (map_pp.obj)

 	..............

How does this report relate to the function sampling process? With function sampling, the profiler uses a timer to inspect the program counter. It's similar to using a strobe light to view a moving object. In the previous test case, the timer fired 14,976 times, and 9.3 percent of the time (1389 times) the program was executing the function AfxFindMessageEntry. This is the framework function that processes Windows messages.

The AfxFindMessageEntry function calls Windows NT functions, but those functions are inside dynamic link libraries (DLLs) that are not prepared for profiling. The time spent in those DLLs is not included in the profile.


  Selective Profiling

It doesn't make much sense to profile an entire Windows NT program. As you've already seen in the previous test, most of the application's time is spent waiting for messages. That's not very useful information. Often, only one section of a program, such as repagination, might be performing poorly. Your strategy will be to select the slow section and profile it alone. Selective profiling doesn't apply to function sampling, but it does apply to the other profiling options. For the remainder of this tutorial, you'll be doing selective profiling.


  Function Timing

As you'll see, function timing is one of the more useful profiling options.  It's fast, and it doesn't require debugging information. (The BSORT makefile specifies debugging information to accommodate this chapter's other examples.) You'll now selectively apply function timing to the CSortStringList::Sort function. Follow these steps:

1.	Select the Function Timing radio button.

2.	Enter /SF ?Sort@CSortStringList@@QAEXXZ in the adjacent Options window.

3.	Choose the OK button.

Note  When you specify a C++ function name to the profiler, you must provide its decorated name (?Sort@CSortStringList@@QAEXXZ, for example).  The easiest way to get that name is to look it up in the project's .MAP file.  Most other function names (that follow the stdcall convention) are preceded by an underscore and followed by the size of their argument list in bytes ('@8,' for example, means that 8 bytes are required on the stack).

4.	After BSORT starts, (in about a minute), use a larger text sample for sorting. You can copy one of the README files using the Clipboard.

5.	Observe the output report that appears in the Visual Workbench Output-Profile window. Here is the whole report:

Profile: Function timing, sorted by time

Date:    Wed Apr 21 08:37:14 1993

Program Statistics

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

    Command line at 1993 Apr 21 08:36: BSORT

    Start function: ?Sort@CSortStringList@@QAEXXZ

    Total time: 7667.448 milliseconds

    Time outside of functions: 68.967 milliseconds

    Call depth: 10

    Total functions: 3237

    Total hits: 266802

    Function coverage: 1.1%

Module Statistics for c:\bsort\bsort.exe

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

    Time in module: 7598.481 milliseconds

    Percent of time in module: 100.0%

    Functions in module: 3237

    Hits in module: 266802

    Module function coverage: 1.1%

        Func         Func+Child          Hit

        Time   %        Time      %     Count  Function

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

    1709.199  22.5     1709.199  22.5     7426 _lstrcmpA@8 (kernel32.def)

    1000.005  13.2     1885.709  24.8    30605 _AfxIsValidAddress@12 (validadd.obj)

     746.538   9.8     7495.842  98.6     7505 CSortStringList::CompareAndSwap(void * &)

     445.156   5.9      445.156   5.9    30605 _IsBadWritePtr@8 (kernel32.def)

     440.548   5.8      440.548   5.8    30605 _IsBadReadPtr@8 (kernel32.def)

     390.014   5.1     1526.425  20.1    18976 CStringList::GetAt(void *) (afxinl1.obj)

     220.597   2.9     2161.482  28.4     7426 operator>(class CString const &,class

     215.131   2.8      503.777   6.6     2315 AllocMemoryDebug(unsigned int,int,char const

     186.319   2.5     1012.635  13.3     6186 CString::AssignCopy(int,char const *)

     168.077   2.2      667.942   8.8     7505 CStringList::GetNext(void * &) (afxinl1.obj)

     166.165   2.2     1875.364  24.7     7426 CString::Compare(char const *) (afxinl2.obj)

     147.286   1.9      413.488   5.4     7505 CString::~CString() (strcore.obj)

     139.330   1.8      906.955  11.9     4124 CStringList::SetAt(void *,char const *)

     137.123   1.8      214.767   2.8     7505 CString::CString() (strcore.obj)

     128.394   1.7      518.192   6.8     4124 CString::operator=(char const *)

     114.246   1.5      309.176   4.1     9820 SafeDelete(char *) (strcore.obj)

     105.203   1.4      105.203   1.4     9260 _memset (memset.obj)

     103.433   1.4      103.433   1.4    11550 CString::operator`char const *' ()

     101.873   1.3     7598.481 100.0        1 CSortStringList::Sort() (sortstr.obj)

     101.365   1.3      101.365   1.3     9820 CString::Init() (strcore.obj)

      87.331   1.1      151.496   2.0     2315 FreeMemoryDebug(void *,int) (afxmem.obj)

      85.984   1.1      149.178   2.0     4124 SafeStrlen(char const *) (strcore.obj)

      81.676   1.1       81.676   1.1     6186 _memcpy (memcpy.obj)

      73.917   1.0      140.612   1.9     2315 CString::Empty() (strcore.obj)

      73.582   1.0      140.788   1.9     2315 _malloc (malloc.obj)

      63.194   0.8       63.194   0.8     4124 _strlen (strlen.obj)

      55.216   0.7       55.216   0.7     6945 CBlockHeader::pbData() (afxmem.obj)

      55.129   0.7      604.028   7.9     2315 CString::AllocBuffer(int) (strcore.obj)

      48.318   0.6      820.333  10.8     2062 CString::operator=(class CString const &)

      45.122   0.6      548.899   7.2     2315 operator new(unsigned int,char const *,int)

      43.434   0.6      194.930   2.6     2315 operator delete(void *) (afxmem.obj)

      38.690   0.5       38.690   0.5     2315 __heap_search (heapsrch.obj)

      34.212   0.5       34.212   0.5     2315 _free (free.obj)

      28.516   0.4       28.516   0.4     2158 __heap_split_block (malloc.obj)

      17.392   0.2       17.392   0.2     2315 _AfxDefaultAllocHook(unsigned int,int,long)

       0.766   0.0        0.766   0.0       79 CStringList::GetHeadPosition() (afxinl1.obj)

This shows you all the functions called between the entry and exit of the CSortStringList::Sort function (excluding functions called within DLLs). Note the second column, which shows that 22.5 percent of the total sort time was spent in lstrcmpA, the single-byte-character lexical string compare function (lstrcmpW is the multi-byte equivalent). Because "Func Time" and "Func+Child Time" are both 22.5 percent, you can assume that lstrcmpA doesn't call any other functions.


  Improving the Sort Process

The purpose of profiling is to identify and eliminate code bottlenecks. The first place to look is lstrcmpA. Maybe you can get by with a numerical string comparison instead of the lexical comparison provided by the CString class. It's easy to substitute a strcmp call for the CString "less than" operator.

That's not all. The heavy use of operator new and the CString constructor and assignment operators indicates that the sort function is doing unnecessary processing. Analysis of the CompareAndSwap function shows that the CStringList::SetAt function, with the assignment of temp, is calling the CString assignment operator, which must free and allocate character memory each time it is called. You can increase efficiency by replacing CString assignments with memcpy calls.

The improved version of CompareAndSwap shown here uses numerical string comparison and accesses some of the CStringList protected members.

BOOL CSortStringList::CompareAndSwap(POSITION& pos)

{

char szTemp[sizeof(CString)];

POSITION posFirst = pos;

GetNext(pos);

if(pos != NULL) {

if(strcmp(GetAt(posFirst), GetAt(pos)) > 0) {

CNode* pNode1 = (CNode*) posFirst;

CNode* pNode2 = (CNode*) pos;

memcpy(&szTemp, &pNode1->data, sizeof(CString));

memcpy(&pNode1->data, &pNode2->data, sizeof(CString));

memcpy(&pNode2->data, &szTemp, sizeof(CString));

return TRUE;

}

}

return FALSE;

}

If you want to run the test yourself, you can switch to the new function by removing the comment characters from the line

#define FAST

in the file SORTSTR.CPP.  A new profile run with the same text input data gives the following results:

Profile: Function timing, sorted by time

Date:    Thu Apr 08 12:21:05 1993

Program Statistics

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

    Command line at 1993 Apr 16 17:54: BSORT

    Start function: ?Sort@CSortStringList@@QAEXXZ

    Total time: 2148.077 milliseconds

    Time outside of functions: 45.865 milliseconds

    Call depth: 5

    Total functions: 3238

    Total hits: 125459

    Function coverage: 0.3%

Module Statistics for c:\bsort\bsort.exe

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

    Time in module: 2102.212 milliseconds

    Percent of time in module: 100.0%

    Functions in module: 3238

    Hits in module: 125459

    Module function coverage: 0.3%

        Func         Func+Child          Hit

        Time   %        Time      %     Count  Function

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

     537.957  25.6     1039.982  49.5    22357 _AfxIsValidAddress@12 (validadd.obj)

     390.296  18.6     2048.490  97.4     7505 CSortStringList::CompareAndSwap(void * &)

     269.646  12.8      269.646  12.8    22357 _IsBadWritePtr@8 (kernel32.def)

     232.379  11.1      232.379  11.1    22357 _IsBadReadPtr@8 (kernel32.def)

     214.281  10.2      891.088  42.4    14852 CStringList::GetAt(void *) (afxinl1.obj)

     126.939   6.0      126.939   6.0    14852 CString::operator`char const *' ()

     118.575   5.6      481.750  22.9     7505 CStringList::GetNext(void * &) (afxinl1.obj)

     111.725   5.3      111.725   5.3     7426 _strcmp (strcmp.obj)

      53.096   2.5     2102.212 100.0        1 CSortStringList::Sort() (sortstr.obj)

      46.692   2.2       46.692   2.2     6168 _memcpy (memcpy.obj)

       0.626   0.0        0.626   0.0       79 CStringList::GetHeadPosition() (afxinl1.obj)

Note that the strcmp hit count matches the lstrcmpA hit count, and that far fewer framework functions are being called. The switch to strcmp saves 1600 milliseconds, and the reduced function overhead saves another 4000 milliseconds. Now the sort function runs almost four times faster.


  Line Count Profiling

Up to now, you've been profiling at the function level. Function profiling is good for detecting inefficient code, but line profiling can be useful for checking the validity of an algorithm. You see how many times each line is executed in response to certain input data, and you see which lines aren't executed at all. Let's do a line count profile of the Sort function.

Because there isn't a Line Count radio button in the Profiler dialog box, you must use a custom batch file that specifies the source module and lines to profile.  You'll learn about these batch files in the next chapter. For now, just use the LCDEMO.BAT file provided in the PROFILER\BSORT sample directory.  Here are the steps:

1.	Select the Custom radio button.

2.	Select LCDEMO.BAT.

3.	Choose the OK button.

4.	When BSORT starts (after several minutes), enter the "one, two,...ten" text again for sorting.

5.	Look at the output report that appears in the Visual Workbench Output-Profile window:

Profile: Line counting, sorted by line

Date:    Thu Apr 08 12:49:31 1993

Program Statistics

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

    Command line: (1993 Apr 09 20:53) C:\MSVCNT\SAMPLES\BSORT.EXE

    Total lines: 22

    Total hits: 883

    Line coverage: 100.0%

Module Statistics for c:\bsort\bsort.exe

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

    Lines in module: 22

    Hits in module: 883

    Module line coverage: 100.0%

Source file: c:\bsort\sortstr.cpp

        Hit

  Line Count   %    Source

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

    1:              // sortstr.cpp

    2:              #define FAST

    3:

    4:              #include "stdafx.h"

    5:

    6:              #include "sortstr.h"

    7:

    8:              void CSortStringList::Sort()

    9:     1   0.1  {

   10:                  POSITION pos;

   11:     1   0.1      BOOL bNotDone = TRUE;

   12:     9   1.0      while(bNotDone) {

   13:     8   0.9          bNotDone = FALSE;

   14:     8   0.9          for(pos = GetHeadPosition(); pos != NULL;) {

   15:    80   9.1              bNotDone |= CompareAndSwap(pos);

   16:    80   9.1          }

   17:     8   0.9      }

   18:     1   0.1  }

   19:

   20:              #ifdef FAST

   21:              BOOL CSortStringList::CompareAndSwap(POSITION& pos)

   22:    80   9.1  {

   23:                  char szTemp[sizeof(CString)];

   24:    80   9.1      POSITION posFirst = pos;

   25:    80   9.1      GetNext(pos);

   26:    80   9.1      if(pos != NULL) {

   27:    72   8.2          if(strcmp(GetAt(posFirst), GetAt(pos)) > 0) {

   28:    27   3.1              CNode* pNode1 = (CNode*) posFirst;

   29:    27   3.1              CNode* pNode2 = (CNode*) pos;

   30:    27   3.1              memcpy(&szTemp, &pNode1->data, sizeof(CString));

   31:    27   3.1              memcpy(&pNode1->data, &pNode2->data, sizeof(CString));

   32:    27   3.1              memcpy(&pNode2->data, &szTemp, sizeof(CString));

   33:    27   3.1              return TRUE;

   34:                      }

   35:                  }

   36:    53   6.0      return FALSE;

   37:    80   9.1  }

   38:

...........

If you examine the Sort function, you'll see that the outer loop was executed eight times, which indicates that the input strings were far out of sequence.  As the strings were compared in the CompareAndSwap function, they were swapped only a third of the time.  All code lines were executed at least once.


  Chapter 2  Profiler Basics

This chapter explains the profiler batch processing flow and its interaction with the Visual Workbench, and then describes the following profiling methods in detail:

•	Function sampling

•	Function profiling, including timing, counting, and coverage

•	Line profiling, including counting and coverage

Remember that profiling is a tuning process; you should use the profiler to make your programs run better, not to find bugs. Once your program is fairly stable, you should start profiling to find out where to devote your attention to optimize your code. Use the profiler to determine whether an algorithm is effective, a function is being called frequently (or at all), or a piece of code is being covered by software testing procedures.

Note  See Appendix A for a description of the »PREP,« »PROFILE,« and »PLIST« command-line options used in this chapter.


  Three Ways to Profile

There are three ways to run the 32-bit Source Profiler:

•	From the Visual Workbench Profile dialog box, using the radio buttons for

Function Timing
Function Sampling
Function Coverage
Line Coverage

•	From a batch file, initiated using the Profile dialog box Custom option

•	From a batch file, initiated from the command line


  Profiler Batch Processing

Profiling requires three separate programs, PREP, PROFILE, and PLIST. If you choose a standard option (other than Custom) from the Visual Workbench Profile dialog box, Visual Workbench executes these programs for you automatically, passing the arguments from the Options window to the PREP program.

If you want maximum profiling flexibility, including the ability to format your output and to specify function and line count profiling, you must write your own batch files that invoke PREP, PROFILE, and PLIST. You can run these batches from either the Profile dialog box or from the Windows NT command prompt. If you run the batch from the dialog, the PLIST output will, by default, be routed to a Visual Workbench output window. Command-line batch output can be routed to a file.

It is essential that you understand the profiler batch processing flow to write and edit profiler batch files. »Figure 2.1« is a diagram of this flow.

The flow diagram may seem complex, but you will begin to understand it when you explore the various profiling options that are described in this chapter. In the meantime, notice that the PREP program is called twice -- once before the actual profiling and again afterward. The command-line arguments govern PREP's behavior.

The .PBI, .PBO, and .PBT files are intermediate files that are used to transfer information between profiling steps. The broken lines indicate connections that depend on the PREP (Phase I) command-line switches.

A typical profiler batch file might look like this:

PREP /OM /FT /EXC nafxcwd.lib %1

if errorlevel == 1 goto done

PROFILE %1 %2 %3 %4 %5 %6 %7 %8 %9

if errorlevel == 1 goto done

PREP /M %1

if errorlevel == 1 goto done

PLIST /SC %1 >%1.lst

:done

Note  When you run a profiler batch from the Profiler dialog box Custom option, the PLIST standard output is routed to the Output - Profiler window. In the preceding batch, the PLIST output is redirected to a file, as it would normally be in a batch run from the command line.

Appendix A lists the command-line parameters for »PREP,« »PROFILE,« and »PLIST.« When the batch is executed using the Custom option in the Profile dialog box, the Visual Workbench substitutes the project's program name for the %1 parameter.  You can specify your program's command-line arguments through the Options Debug dialog box.

If the preceding batch file was named FTIME.BAT, and you wanted to profile the program TEST from the Profile dialog box, you would select the Custom radio button, and then specify FTIME.BAT in the adjacent edit window. If you wanted to profile the TEST program from the command prompt, you would type:

FTIME \MSVCNT\SAMPLES\PROFILER\TEST.EXE

or:

FTIME TEST

Note  If you are running a profiler batch from the Visual Workbench, you can use the Visual Workbench to edit your batch file. Remember to save your batch files after editing, because the Visual Workbench will not save them automatically.


  Profiler Batch Response Files

Like the linker, all three profiler programs accept response files.  Thus the command line

PREP /OM /FT /EXC nafxcwd.lib %1

can be replaced by the line

PREP @opts.rsp %1

if you create a file OPTS.RSP that contains this text

/OM /FT /EXC nafxcwd.lib    # this is a comment

Use of the '#' character in a response file defines a comment that runs through the end of the line.


  Standard Batch Files

There are six standard batch files shipped with the 32-bit Source Profiler:

Filename	Description
FSAMPLE.BAT	Function sampling
FTIME.BAT	Function timing
FCOUNT.BAT	Function counting
FCOVER.BAT	Function coverage
LCOUNT.BAT	Line counting
LCOVER.BAT	Line coverage
These batch files contain only the minimum parameters for PREP Phase I. Use them as prototypes for your own batches, which should contain selection parameters. If you ran an unmodified LCOVER batch for a Microsoft Foundation Classses application, for example, the output report could be thousands of lines long.


  Function Sampling

Function sampling is the simplest form of profiling. The profiler starts your program. Then, on a timer frequency, which can be set through a PROFILE command-line parameter, the profiler interrupts the program to inspect the program counter. After the program ends, the resulting statistics are output by PLIST. A typical function sampling output report is shown in the »Profiler Tutorial.« Here is a sample detail line with column headings:

Hit

count   %   Function

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

  513   1.4 _memcpy (memcpy.obj)


  Excluding Functions from Sampling

You generally shouldn't exclude functions, modules, and whole libraries from sampling, even though you can do so. The default TOOLS.INI excludes all library functions. If the timer fires while the computer is executing an excluded function, the profiler ignores the event. There is no performance penalty for sampling all functions.

Suppose you are profiling a module that contains the following function (with the C run-time library excluded from profiling):

void Concatenate(char* szA, char* szB, char* szC)

{

strcpy(szC, szA);

strcat(szC, szB);

}

The chances are slim that you would get any hits in Concatenate.	 Most of the execution time will be spent in run-time functions strcpy and strcat, which are excluded from the profile. If you included the run-time library but excluded other top-level functions outside Concatenate, the results would be skewed by strcopy and strcat hits that resulted from calls by the excluded functions. You could not determine the percentage of time spent in Concatenate and its child functions.

To reiterate, function sampling is useful if you want to profile an entire executable unit, a DLL for example. If you need selective function profiling or line-level profiling, use the other profiling options.

Debugging information is not required for function sampling. Phase I of PREP reads the project's .MAP file to match addresses with function names. PROFILE directly accesses the code in the .EXE file being profiled.


  Function Profiling

The 32-Bit Source Profiler has three closely related function profiling options that are quite different from function sampling. "Function timing" lists time spent in functions together with "hit count" —  the number of times the function was called. "Function counting" lists only hit counts, but it is faster than function timing. "Function coverage" lists functions that are, and are not executed.

Debugging information is not required for function timing, function counting, or function coverage. Phase I of PREP reads the project's .MAP file to match addresses with function names. PREP also creates a modified executable module, which is stored in a temporary file with a _XE or _LL extension.  This modified executable contains "thunks" (substitutions for function calls), thus enabling the PROFILE program to count and time the functions.


  Excluding and Including Functions from Profiling

You can exclude and include functions from function profiling just as you can from function sampling. Look at the Concatenate function again. Suppose you accepted the default TOOLS.INI file to exclude all functions in the standard C run-time library. Now the strcpy and strcat functions are excluded, but you will still get accurate timing and hit count information for Concatenate itself. The profiling will be faster too.

If you want to include only the strcpy and strcat run-time functions, use these PREP options:

/INC _strcpy /INC _strcat

Note  The functions strcpy and strcat are standard run-time library functions that are written in assembly language. These and most other run-time functions are included for profiling unless you specifically exclude them. If you write your own assembly-language functions, or if you use another library that contains assembly-language functions, you must specifically include those functions in the profile or those functions must be declared stdcall.  This restriction prevents the profiler from modifying data that is included in code pages.


  Choosing Starting Functions for Profiling

The PREP /SF option starts and stops profiling on a selected function. This enables you to isolate a section of code for profiling.

If you wanted a function profile for the Concatenate function previously listed, you would specify the following Phase I PREP option:

/SF _Concatenate@12

Now you would see the time spent in Concatenate and in its strcpy and strcat child functions, but you wouldn't see the time used in  strcpy and strcat when called from other functions. Starting function selection is generally more useful than function exclusion/inclusion, but function exclusion can make the profiled program run faster.


  Function Timing

Function timing is perhaps the most useful function profiling mode. You see how many times the function was called (hit count), and you learn how much time was spent in (1) each function, and (2) in the function and the functions it calls (child functions). A typical function timing output report is shown in the »Profiler Tutorial.«  Here is a sample line with column headings:

        Func         Func+Child          Hit

        Time   %        Time      %     Count  Function

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

       2.606  48.1        2.606  48.1        2 _SetCursor@4 (user32.def)


  Function Counting

Function counting is similar to function timing. The same selection options (start function, function exclusion/inclusion) apply. Only hit counts (greater than zero) are listed, and profiled program execution is faster. Here is the format for a function count report from PLIST:

  Hit

  Count    %   Function

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

       1  25.0 _LoadCursorA@8 (user32.def)


  Function Coverage

Function coverage profiling is useful for determining which sections of your code are not being executed. You see all the included functions listed, with an asterisk marking those that were executed. The profiling overhead for function coverage matches the overhead for function counting. Here is a sample function coverage report:

Covered Function

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

    .    _InitInstance (generic.obj)

    .    _LoadAcceleratorsA@8 (user32.def)

    *    _LoadCursorA@8 (user32.def)

    .    _LoadIconA@8 (user32.def)

    .    _MessageBoxA@16 (user32.def)

    .    _PostQuitMessage@4 (user32.def)

    .    _RegisterClassA@4 (user32.def)

    .    _ReleaseDC@8 (user32.def)

    .    _RtlUnwind@16 (kernel32.def)

    .    _SendMessageA@16 (user32.def)

    *    _SetCursor@4 (user32.def)

    .    _SetDlgItemTextA@12 (user32.def)

Often, you will need to specify both a starting function and exclude/include criteria for function coverage.  The starting function specifies which code will be profiled, but if you don't specify the exclude/include range, the PLIST report shows all linked library functions, regardless of whether they are executed during profiling.  If you exclude the libraries (as specified in the default TOOLS.INI), then the coverage report lists only those functions in your application.


  Line Profiling

With the profiler's two line profiling options, you can see which source lines are being executed. "Line counting" shows you how many times each line was executed, and "line coverage" shows you which lines were executed at least once.

Because the profiler needs to set breakpoints in the code, and because PLIST prints individual program source lines, your .EXE file must contain debugging information. From the Visual Workbench compiler Debug Options dialog box, select Partial or Full Debug Information. From the linker Debug options dialog box, select Full Debugging Information. The .MAP file is not necessary.


  Specifying Lines to Profile

If you have accepted the default TOOLS.INI file, all library source lines will be excluded from profiling. If you do not use any /EXC or /INC options to PREP Phase I, then all source lines in your application will be listed. You can use the /INC, /EXC, and /EXCALL options to specify individual source modules and even selected lines within those modules.

If you want all lines in the TEST module, specify the object-file name with these options:

/EXCALL /INC test.obj

If you need specific lines, specify the source module with line numbers like this:

/EXCALL /INC test.c(5-14)

Be careful not to insert extra spaces in the text following /INC.


  Line Counting

The »Profiler Tutorial« shows the output from a typical line count profile run. Here is a shorter example:

        Hit

  Line count   %   Source

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

    1:             // test.c

    2:

    3:             #include <windows.h>

    4:

    5:             void WasteTime(HANDLE hInstance, HWND hWnd)

    6:     1   0.0 {

    7:                     LONG lCount, lX;

    8:                     HCURSOR hOldCursor;

    9:     1   0.0         hOldCursor = SetCursor(LoadCursor(NULL,

IDC_WAIT));

   10:     1   0.0         for(lCount = 0; lCount < 1000L; lCount++) {

   11:  1000  49.9                 lX = 57L;

   12:  1000  49.9         }

   13:     1   0.0         SetCursor(hOldCursor);

   14:     1   0.0 }

Note that all included source lines are printed, even if they're not executed.

Line count profiling is very slow because the PROFILE program inserts a debugging breakpoint for every source code line, and these breakpoints remain for the duration of the profile session.


  Line Coverage

The profiler's line coverage report denotes executed lines with an asterisk and skipped lines with a dot. Here's an example:

  Line Covered  Source

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

    1:          // waste.c

    2:

    3:          #include <windows.h>

    4:

    5:          void WasteTime(HANDLE hInstance, HWND hWnd)

    6:    *     {

    7:              LONG lCount, lX;

    8:              HCURSOR hOldCursor;

    9:    *         hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));

   10:    *         for(lCount = 0; lCount < 1000L; lCount++) {

   11:    *             lX = 57L;

   12:    *         }

   13:    *         if(lCount == 0) {

   14:    .             lCount = 1; // should never execute

   15:              }

   16:    *         SetCursor(hOldCursor);

   17:    *     }

Note that all included source lines are printed, even if they're not executed.

Line coverage profiling is much faster than line count profiling because PROFILE can remove the inserted breakpoints when those lines are first executed.


  Chapter 3  Special Topics

This chapter gives you additional information about the 32-Bit Source Code Profiler. The following topics are covered:

•	Combining profiling sessions

•	Profiling dynamic-link libraries

•	Profiling inline functions

•	Profiling console applications

•	Profiling multithreaded, multi-process applications

•	Miscellaneous profiler restrictions

Note  See Appendix A for a description of the »PREP,«  »PROFILE,« and »PLIST« command-line options used in this chapter.


  Combining PROFILE Sessions

With the profiler's modular design, you can make several profiling runs without having to run PREP each time (see »Figure 3.1«). After PREP has created .PBI and .PBT files, you can reuse these files with PROFILE to create multiple .PBO files. You can then merge the .PBO files using the PREP /IO command-line option with multiple .PBO files. The Visual Workbench Profile dialog box contains a Merge radio button that automates this process.


  Using the Profile Dialog Box Merge Option

You can use the Merge radio button in the Profile dialog box (shown in »Figure 1.2«) if you have already run the profiler at least once, generating the .PBI, .PBO, and .PBT files for the project. Each time you choose the Merge button, PROFILE is executed, and PREP Phase II adds the result to the existing .PBT file. When the profiled program exits each time, PLIST prints the cumulative results.


  Using Batch Files

If you use the Merge radio button, you will get a PLIST report after each invocation of PROFILE. If, instead, you need a single PLIST report from multiple profile runs, you must write and execute a batch file like this:

PREP /LV myprog.exe myfuncs.dll
PROFILE /O myprog1 myprog.exe

PROFILE /O myprog2 myprog.exe

PROFILE /O myprog3 myprog.exe

PREP /IT myprog /IO myprog1 /IO myprog2 /IO myprog3 /OT myprog
PLIST myprog >myprog.out

Or, alternatively, because PREP Phase II adds data to an existing .PBT file:

PREP /LV myprog.exe myfuncs.dll

PROFILE myprog

PREP /M myprog

PROFILE myprog

PREP /M myprog

PROFILE myprog

PREP /M myprog

PLIST myprog >myprog.out

Note  You can merge only eight .PBO files from the command line with each PREP invocation. To overcome this limitation, use PREP Phase II to merge groups of .PBO files into .PBT files. Then, merge the resulting .PBT files to yield a single .PBT file that contains statistics from the constituent .PBO files.

You cannot merge .PBO or .PBT files that come from different .PBI files. PREP can combine information only from profiling sessions that use the same .EXE and .PBI files (and therefore have identical profiling characteristics). You cannot, for example, merge the results of a timing session with the results of a coverage session.


  Reusing .PBT and .PBI Files

For a large program, PREP can take considerable time to create .PBT and .PBI files from scratch. You must rebuild these files if you change your source code or the profiling method, but you can reuse the files if you only need another profile run with different program input data. Just copy the .PBT file after the initial Phase I PREP run. The .PBI file is never changed, so you don't need to copy it.


  Profiling Dynamic-Link Libraries

Profiling a dynamic-link library (DLL) is similar to profiling an .EXE file. When you profile a DLL, you follow the same steps and use the same commands that you would for an .EXE file. The same profiling rules that apply to .EXE files (such as the need to include debugging information and to supply a .MAP file) apply to DLLs.

For function profiling, the DLL is typically renamed with a _LL extension, but the .EXE file looks for a file with a .DLL extension when it executes. Therefore the prepared DLL must be renamed prior to profiling.

The following batch file (PROFDLL.BAT) profiles a DLL with the assumption that the .EXE file has not been prepared for profiling:

COPY %1.dll save

PREP /OM %1.dll

COPY %1._ll %1.dll

PROFILE /I %1 /O %1 %2 %3 %4 %5 %6

COPY save %1.dll

PREP /M %1

PLIST %1

Note  The preceding batch generates a warning message that alerts you to the fact the main program has not been prepared for profiling.

If you had a main program HEARTS.EXE that used a DLL called CARDS.DLL, and you wanted to profile only CARDS.DLL, you would run the preceding batch as:

PROFDLL cards hearts


  Profiling Multiple .DLL and .EXE Files

The profiler can profile several DLLs and their calling executable file in a single profiler run. With phase I PREP command-line options, you can specify more than one .DLL or .EXE.

The following commands demonstrate how to profile an executable file and two DLLs from the command line:

PREP /OM /FC wingame.exe aliens.dll hiscore.dll
PROFILE wingame.exe
PREP /M  wingame
PLIST wingame >wingame.out

The first line causes PREP to create WINGAME.PBI and WINGAME.PBT files that include information on WINGAME.EXE, ALIENS.DLL, and HISCORE.DLL. The next line causes PROFILE to run WINGAME.EXE (actually WINGAME._XE, as generated by PREP Phase I). During the execution of WINGAME, PROFILE collects statistics for WINGAME.EXE as well as ALIENS.DLL and HISCORE.DLL, if they are called. The final two lines process the information from the profiling session and store the results in WINGAME.OUT.


  Program Statistics vs. Module Statistics

PLIST reports always start with a "Program Statistics" section followed by a "Module Statistics" section. The Tutorial examples show only one "Module Statistics" section because there was only one .EXE file involved. If there are several DLLs involved, as in the previous example, there is one "Module Statistics" section per .EXE or .DLL. The  "Program Statistics" section lists totals for the entire program, including DLLs. Total time includes time in functions and modules not being profiled.


  Profiling Inlined Code

If you specify, the Visual C++ compiler will perform inlining, which is the replacement of a function call with an actual copy of the code. Profiling inlined code requires special attention.


  Function Profiling for Inlined Functions

Because inlined functions don't generate .MAP file entries or CALL instructions, the profiler cannot tell when the computer is executing one of these functions. The sample, time, hit, and coverage data will be attributed to the "calling" function.

Note  In many cases there are .MAP file entries for "inlined" functions because the functions are not necessarily inlined everywhere in the application.  Take this into account when you analyze profiler results.


  Line Profiling for Inlined Functions

The profiler can provide line-level hit count and coverage information for inlined functions. You must be sure to include the source lines in the Phase I PREP command-line options, just as you would include source lines in the calling program.


  Profiling Windows NT Console Applications

Windows NT console applications do not use the graphical user interface; they run from the command line, often doing console input/output. You can easily use the profiler with these applications. If the application does do console I/O, you should run the profiling batch from the command prompt rather than from the Visual Workbench Profile dialog box.


  Profiling Multithreaded Applications

For multithreaded applications, profiler behavior depends on the profiling method.

For function sampling, line counting, and line coverage, the profiler does not discriminate among threads. The hit counts encompass all the program's threads.

For function timing, function counting, and function coverage, profiling is thread-dependent. You can profile an individual thread by (1) declaring the thread's main function as the starting function (PREP/SF option), and (2) including all functions in the program (don't use the PREP/EXC option).

The profile results will be difficult to interpret if you do not specify a starting function, if you specify a starting function that is called from multiple threads, or if you don't include all functions.


Profiling on a Quiet Computer
  Profiling on a "Quiet" Computer

For maximum profiler accuracy, close as many other applications as possible during profiling. In particular, do not run programs such as electronic mail that execute at random intervals.


  Miscellaneous Profiler Restrictions

Function-level profiling works only with ordinary functions that return with the stack pointer unchanged. Profiling should be turned off for functions that do change the stack pointer or store the return address for later use. The profiler automatically turns off profiling for the functions alloca and setjmp. If you write your own similar functions, you must write them in assembly language. By default, assembly-language functions are excluded from profiling.  Do not use these functions with the PREP /INC option.


  Appendix A  Command-Line Options

This appendix provides reference information for using the components of the Microsoft 32-Bit Source Profiler from the command line. Included are the syntax and command-line options for PREP, PROFILE, and PLIST.

Refer to »Figure 2.1« to see how the profiler components interact.


  PREP

The PREP program runs twice during a normal profiling operation. In Phase I, it reads an .EXE file then creates .PBI and .PBT files.  In Phase II, it reads .PBT and .PBO files then writes a new .PBT file for PLIST. An 'X' in the following Options table indicates that a PREP command line option applies to a particular phase.

Syntax

PREP [options] [programname1] [programname2......programname8]

PREP reads the command line from left to right, so the rightmost options override contradictory options to the left. None of the options is case sensitive. You must prefix options with a forward slash ( / ) or a dash (−).

Parameter	Description
options	See "Options."
programname1	Filename of primary program to profile (.DBG, .EXE, or .DLL). PROFILE adds the .EXE extension if no extension is given. This parameter must be specified for PREP Phase I and not for Phase II.
programname2 ....... programname8	Additional programs to profile.  These parameters may be specified for PREP Phase I only.
Options

Option	I	II	Description
/EXC	X		Excludes a specified module from the profile (see Remarks).
/EXCALL	X		Excludes all modules from the profile (see Remarks).
/FC	X		Selects function count profiling.
/FS	X		Selects function sampling profiling.
/FT	X		Selects function timing profiling. This option causes the profiler to generate count information as well.
/FV	X		Selects function coverage profiling.
/INC	X		Includes in profile (see Remarks).
/H[ELP]	X	X	Provides a short summary of PREP options.
/IO filename		X	Merges an existing .PBO file. Up to eight .PBO files can be merged at a time. The default extension is .PBO.
/IT filename		X	Merges an existing .PBT file. Up to eight .PBT files can be merged at a time. You cannot merge .PBT files from different profiling methods. The default extension is .PBT.
/LC	X		Selects line count profiling.
/LV	X		Selects line coverage profiling.
/M filename		X	Substitutes for /IT, /IO, and /OT options.
/NOLOGO	X	X	Suppresses the PREP copyright message.
/OI filename	X		Creates a .PBI file. The default extension is .PBI.  If /OI is not specified, the output .PBI file is  programname1.PBI.
/OM	X		Creates a self-profiling file with _XE or _LL extension for function timing, function counting, and function coverage. Without this option, the executable code is stored in the .PBI file.  This option speeds up profiling and is used by Visual Workbench.
/OT filename	X	X	Specifies the output .PBT file. The default extension is .PBT.  If /OT is not specified, the output .PBT file is  programname1.PBT.
/SF function	X		Starts profiling with function. Function name must correspond to an entry in the .MAP file.
/?	X	X	Provides a short summary of PREP options.
Environment Variable

PREP	Specifies default command-line options.
If a value for the PREP environment variable is not specified, the default options for PREP are

/FT /OI filename /OT filename

where filename is set to the programname1 parameter value.

Remarks

The /INC and /EXC options specify individual .LIB, .OBJ and .C (.CPP or .CXX) files. For line counting and line coverage, you can specify line numbers with source files as in:

/EXCALL /INC test.cpp(3-41,50-67)

Here we are including only lines 3-41 and lines 50-67 from the source file TEST.CPP. Note the absence of spaces in the source specification.

To specify all source lines in a particular module, specify the .OBJ file like this:

/EXCALL /INC test.obj

or by using the source file name with zero line numbers like this:

/EXCALL /INC test.cpp(0-0)

The following statement profiles from line 50 to the end of the file:

/EXCALL /INC test.cpp(50-0)


  PROFILE

PROFILE profiles an application and generates a .PBO file of the results. Use PROFILE after creating a .PBI file with PREP.

Syntax

PROFILE [options] programname [programargs]

PROFILE reads the command line from left to right, so the rightmost options will override contradictory options to the left. None of the options are case sensitive. You must prefix options with a forward slash ( / ) or a dash (−).

If you do not specify a .PBO filename on the command line, PROFILE uses the base name of the .PBI file with a .PBO extension. If you do not specify a .PBI or a .PBO file, PROFILE uses the base name of programname with the .PBI and .PBO extensions.

Parameter	Description
options	See "Options."
programname	Filename of program to profile. PROFILE adds the .EXE extension if no extension is given. See "Remarks."
programargs	Optional command-line arguments for programname. See "Remarks."
Options

Option	Description
/A	Appends any redirected error messages to an existing file. If the /E command-line option is used without /A, the file is overwritten. This option is valid only with the /E option.
/E filename	Sends profiler-generated error messages to filename.
/H[ELP]	Provides a short summary of PROFILE options.
/I filename	Specifies a .PBI file to be read. This file is generated by PREP.
/NOLOGO	Suppresses the PROFILE copyright message.
/O filename	Specifies a .PBO file to be generated. Use the PREP utility to merge with other .PBO files or to create a .PBT file for use with PLIST.
/S frequency	Sets the sampling frequency (samples per second). Ignored unless the .PBI file is set for sampling. The frequency parameter must be an integer between 18 and 10,000. The default sampling frequency is 1,000 samples per second. This option is valid only with MS-DOS.
/X	Returns the exit code of the program being profiled.
/?	Provides a short summary of PROFILE options.
Remarks

You must specify the filename of the program to profile on the PROFILE command line. PROFILE assumes the .EXE extension, if no extension is given.

You can follow the program name with command-line arguments; these arguments are passed to the profiled program unchanged.

If you are profiling code in a .DLL file, give the name of an executable file that calls it. For example, if you want to profile SAMPLE.DLL, which is called by CALLER.EXE, you can type:

PROFILE CALLER.EXE

assuming that CALLER.PBI has SAMPLE.DLL selected for profiling. See »Profiling Dynamic-Link Libraries.«

Environment Variable

PROFILE	Specifies default command-line options.
If the PROFILE environment variable is not specified, there are no other defaults.


  PLIST

PLIST converts results from a .PBT file into a formatted text file.

Syntax

PLIST [options] inputfile

PLIST reads the command line from left to right, so the rightmost options override contradictory options to the left. None of the options are case sensitive. You must prefix options with a forward slash ( / ) or a dash (−).

PLIST results are sent to STDOUT by default. Use the greater-than (>) redirection character to send these results to a file or device.

PLIST must be run from the directory in which the profiled program was compiled.

Parameter	Description
options	See "Options."
inputfile	The .PBT file to be converted by PLIST.
Options

Option	Description
/C count	Specifies the minimim hit count to appear in the listing.
/D directory	Specifies an additional directory for PLIST to search for source files. Use multiple /D command-line options to specify multiple directories. Use this option when PLIST cannot find a source file.
/F	Lists full paths in tab-delimited report.
/H[ELP]	Provides a short summary of PLIST options.
/NOLOGO	Suppresses the PLIST copyright message.
/PL length	Sets page length (in lines) of output. The length must be 0 or 15−255. A length of 0 suppresses page breaks. The default length is 0.
/PW width	Sets page width (in characters) of output. The width must be 1−511. The default width is 511.
/SC	Sorts output by counts, highest first.
/SL	Sorts output in the order that the lines appear in the file. This is the default. This option is available only when profiling by line.
/SLS	Forces line count profile output to be printed in coverage format.
/SN	Sorts output in alphabetical order by function name. This option is available only when profiling by function.
/SNS	Displays function timing or function counting information in function coverage format. Sorts output in alphabetical order by function name.
/ST	Sorts output by time, highest first.
/T	Tab-separated output. Generates a tab-delimited database from the .PBT file for export to other applications. All other options, including sort specifications, are ignored when using this option. For more information, see Appendix B , »Exporting Data from the Profiler.«
/?	Provides a summary of PLIST options.
Environment Variable

PLIST	Specifies default command-line options.
If the PLIST environment variable is not specified, the default options for PLIST depend on the profile type as shown.

Profile type	Sort option	Hit count option
Function timing	/ST	/C 1
Function counting	/SC	/C 1
Function sampling	/SC	/C 1
Function coverage	/SN	/C 0
Line counting	/SL	/C 0
Line coverage	/SL	/C 0


  Appendix B  Exporting Data from the Profiler

In addition to formatted reports, the PLIST report-generation utility can produce a tab-delimited report of profiler output. This appendix describes the data format of the tab-delimited report and how to extract information from this output file. It also describes a Microsoft Excel macro that uses this report format.

The PLIST /T command-line option causes PLIST to dump the contents of a .PBT file into a tab-delimited format suitable for import into a spreadsheet or database. This format can also be used by user-written programs.

To create a tab-delimited file called BSORT.TXT from BSORT.PBT, type:

PLIST /T BSORT > BSORT.TXT

Note  The ASCII tab-delimited format was designed to be read by other programs; it was not intended for general reporting.


  Tab-Delimited Record Format

Every piece of data stored by the profiler is available through the tab-delimited report. Because not all aspects of the database are recorded by every profiling method, unused fields within a record may be zero. For example, the total time of the program will be zero if the program was profiled for counts only.  Also, all included functions will be listed for function counting and timing profiles, even if those functions were not executed.

The tab-delimited format is arranged with one record per line and two to eight fields per record . »Figure B.1« shows how a database looks when loaded into Microsoft Excel. The database was produced using the PLIST /T command-line option.

The first item in each record is a format tag number. These tags range from 0 to 7 and indicate the kind of data given in the other fields of the record. The fields in each record are described in the next two sections.

Tab-delimited reports are generated with global information records first, organized in numerical order by format tag. The local information records, containing information about specific lines or functions, are generated last. Local information records are organized by line number.

If the .PBT file contains information from more than one .EXE or .DLL file, the global information will cover them all. Local information records include the EXE field, which specifies the name of the executable file that each record pertains to.


  Global Information Records

The global information records contain information about the entire executable file. The format tag numbers for global information records are 0 through 5. The record formats are as follows:

Profiler Banner

0	Version	Banner
Field	Explanation
0	Format tag number
Version	PLIST version number
Banner	PLIST banner
Profiling Method

1	Method	Description
Field	Explanation
1	Format tag number
Method	Numeric value that indicates the profiling type (see Table B.1)
Description	ASCII description of the profiling type given by the method field
The profiling types are listed in Table B.1.

Table B.1    Profiling Types

Method	Description
321	Profile: Line counting, sorted by line
324	Profile: Line coverage, sorted by line
521	Profile: Function counting, sorted by function name
522	Profile: Function timing, sorted by function name
523	Profile: Function sampling, sorted by function name
524	Profile: Function coverage, sorted by function name
Profiling Time and Depth

2	Total Time	Outside  Time	Call Depth
Field	Explanation
2	Format tag number.
Total Time	Total amount of time used by the program being profiled. This field is zero for counting and coverage profiles.
Outside Time	Amount of time spent before the first profiled function (with function profiling) or line (with line profiling) was executed. This field is zero for counting and coverage profiles.
Call Depth	Maximum number of nested functions found while profiling. Only profiled functions are counted. This field is zero for a line-level profiling and function sampling.
Hit Counts

3	Total Hits	Lines/Funcs	Lines/Funcs Hit
Field	Explanation
3	Format tag number
Total Hits	Total number of times the profiler detected a profiled line or function being executed
Lines/Funcs	Total number of lines or functions marked for profiling
Lines/Funcs Hit	Number of marked lines or functions executed at least once while profiling
Date/Command Line

4	Date	Command Line
Field	Explanation
4	Format tag number
Date	The date/time the profile was run (ASCII format)
Command Line	The PLIST command-line arguments
Starting Function Name

5	Starting Function Name
Field	Explanation
5	Format tag number
Starting Function Name	The decorated name of the starting function identified by the PREP /SF parameter


  Local Information Records

The local information records contain information about specific lines or functions that were profiled. The format tag numbers for local information records are 6 and 7. A report can have only one kind of local information record. The record formats are as follows:

Function Information

6	Exe	Source	Count	Time	Child	Func
Field	Explanation
6	Format tag number.
Exe	ASCII name of the executable that contains this function.
Source	ASCII name of the object module (including the .OBJ extension)  that contains this function.
Count	Number of times this function has been executed.
Time	Amount of time spent executing this function in milliseconds. This field is zero with profiling by counting or coverage.
Child	Amount of time spent executing the function and any child functions it may call. This field is zero with profiling by counting or coverage.
Func	ASCII name of the function.
Line Information

7	Exe	Source	Line	Count
Field	Explanation
7	Format tag number.
Exe	ASCII name of the executable that contains this function.
Source	ASCII name of the source that contains the first line of this function.
Line	Line number of this line.
Count	Number of times this line has been executed. With coverage, this field is 1 if the line has been executed and 0 otherwise.


  Steps to Analyze Statistics

The profiler tab-delimited report format can contain a great deal of information. You can use the following steps to process this data in a spreadsheet, database, or user-written program:

1.	Collect the cumulative data from the global information records. These lines begin with the numbers 0 through 5. Each of these lines appears only once, and always in ascending order.

2.	Determine the type of database by finding the value of the "Method" field. This field is the second field of record type 1.

If the value in the "Method" field is greater than 400, the report comes from function profiling. If it is less than 400, the report comes from line profiling. The type of information in the local information records given later is directly related to this value.

In any one report, the local information records are always of the same type, either line information or function information.

3.	Process data from the local information records. For example, to calculate the percentage of hits on a given function, divide the value of the "Count" field in record type 6 by the total number of hits from the "Total Hits" field of record type 3.

Remember that there can be only one type of local information record (either line or function information) in a report.

4.	Send the results to a file or STDOUT.


  Processing Profiler Output with Excel

PROFILER.XLM is an example Microsoft Excel 4.0 macro that processes the tab-delimited report and creates a graph based on the results. You will find this macro in the \MSVCNT\SAMPLES\PROFILER directory.

Note  The Profiler sample code is installed when you set up Visual C++. If, for some reason, the Excel macro and other sample code is not on your disk, you must run Setup again to reinstall Visual C++.


  Using the PROFILER.XLM Macro

To run the macro, follow these steps from within Excel:

1.	Open PROFILER.XLM by choosing Open from the File menu.

2.	Open the tab-delimited report that was created by PLIST by choosing Open from the File menu.

3.	If you have several open worksheets, activate the one containing the profiler data by selecting it with the mouse or by choosing its title from the Windows menu.

4.	Run the macro:

•	Press CTRL+C for a chart based on hit counts.

•	Press CTRL+T for a chart based on timing.

You cannot get a timing chart if the report contains only counting or coverage information.

The macro typically takes only a few seconds to execute. When it is complete, Excel displays a 3-D bar chart based on the results contained in the report (see »Figure B.2«). You can change the chart type by using the Gallery menu.

Note  This macro copies the data in the report to another worksheet before processing it. The original tab-delimited report is left untouched.


Inside the PROFILER.XLM Macro
  Changing the PROFILER.XLM Selection Criteria

The standard PROFILER.XLM macros displays hit counts greater than 0 (for CTRL+C) and times greater than .01 millisecond (for CTRL+T).  If you need to narrow the selections without analyzing the macro, edit the formulas in cells C10 and D10.


  Appendix C  Profiling Win32s Applications on Windows 3.x

This appendix provides reference information for profiling 32-bit applications on Windows 3.x with the Win32s dynamic link library.

The Need for Profiling under Win32s

If you develop a 32-bit Windows application, you should profile the programs first under Windows NT, using the 32-bit Source Profiler as described in this document. The program being profiled may, however, behave differently when running under Win32s and Windows 3.x. Sometimes you may need to profile the program in its target environment to pinpoint problems. Thus there is a special version of the profiler that runs under Win32s.

Installing the Win32s Profiler

The Microsoft Win32s Setup program (SETUP.EXE) installs all the necessary Win32S profiler files and correctly configures the profiler for your selected environment. Some of the files and samples are duplicates of the Windows NT profiler files.

If you have already installed Win32s but did not choose to install the profiler at that time, you can run the Setup program again and choose to install only the profiler components.

You must run the Setup program to install the Win32s profiler. The files on the distribution disks are compressed; the Setup program both uncompresses the files and copies them to your hard disk.

The Win32s Profiling Procedure

The Visual Workbench Profiler dialog box is not supported under Win32s, and you cannot run PROFILE from the command line. Therefore, you must execute PREP and PLIST directly from the command line, but you must run the Win32s profiler, PROFW32S, from Program Manager or File Manager. PREP and PLIST use the command-line arguments described in »Appendix A,« and PROFW32S uses the same command-line arguments as PROFILE, also described in Appendix A.

The profiling steps are as follows:

1.	Execute PREP (Phase I) from the command line, using command-line arguments similar to those used in the batch files described in this document. This generates the .BPT, .PBI and ._XE files necessary for profiling.

2.	From Program Manager, execute PROFW32S with the program name specified as an argument.

3.	After the profiling is finished, execute PREP (Phase II) and PLIST from the command line.


Figure 1.1 The BSORT Program in Operation


Figure 1.2 Visual Workbench Profiler Dialog Box


Figure 2.1 Profiler Batch Processing Flow


Figure 3.1 Combining PROFILE Sessions


Figure B.1 Tab-Delimited Report in Microsoft Excel


Figure B.2 Graph Created with Excel CreateColumnChart Macro


Introduction
Spy++ Users Guide

Introduction

Microsoft® Spy++ (SPYXX.EXE) is a Windows NT (™)  utility that gives you a graphical view of the system's processes, threads, windows, and window messages. Spy++ offers the following features:

•	The familiar multiple document interface (MDI) for Windows

•	Three outline views that show relationships among system "objects," including processes, threads, and windows

•	Window selection from the outline view or by direct mouse positioning

•	"Hot key" access to detailed information on selected objects

•	Online Help for window style codes, message parameters, and so forth

•	A variety of easy-to-use message viewing options with parameter decoding

Remember that Spy++ is a "read-only" program. Using Spy++ does not change program operation, but can slow program execution.


Book Location
Spy ++ User's Guide


Spy++ User's Guide Document Conventions
  Document Conventions

This book uses the following typographic conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
char, _setcolor, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. Within discussions of syntax, bold type indicates that the text must be entered exactly as shown.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second.
	The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
Dynamic-Link Library (DLL)	The first time an acronym is used, it is usually spelled out.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


Other Spy Programs
  Other "Spy" Programs

Spy++ supersedes two earlier "spy" programs: SPY.EXE versions 3.1 and 3.2. Version 3.1, delivered with the Windows 3.x Software Development Kit (SDK) and with Visual C++ for Windows 3.x, works inside the "Windows on Win32" (WOW) subsystem. Use SPY.EXE version 3.1 only on Windows 3.x programs when you need to see hexadecimal 16-bit message parameters. You can use SPYXX.EXE with Windows 3.x programs, but the messages you see will have been converted (by WOW) to 32-bit Windows NT messages.

SPY.EXE version 3.2, delivered with the Win32 SDK but not included with Visual C++, works with all Windows NT and Windows 3.x applications. If you have been using SPY.EXE version 3.2, you should switch to the newer version, which has many new features.

SPYXX.EXE also includes many of the features of PVIEW.EXE, a Win32 SDK utility that is included with Visual C++. PVIEW can update process information; SPYXX cannot.

Another utility included with Visual C++, DDESPY.EXE, is a monitoring program for Dynamic Data Exchange (DDE) messages. There is no overlap between SPYXX.EXE and DDESPY.EXE.


  Installing Spy++

If you chose the complete Visual C++ for Windows NT installation, then SPYXX.EXE and its associated files should already be installed in your \MSVCNT\BIN directory. If you did not, then rerun the Setup program and check the "Spy++" option in the Tools dialog box. When Setup installs Spy++, it places a Spy++ icon in the Program Manager group "Visual C++ for Windows NT."

The required files include:

Filename	Description
SPYXX.EXE	Spy++ executable program
SPYXXHK.DLL	Spy++ DLL that supports message hooks
SPYXXEXT.DLL	Spy++ DLL that supports extension DLLs
SPYXXVK.DLL	Spy++ view support DLL
WINDOW.SPE	Window extension DLL
TASK.SPE	Task extension DLL
SYSTEM.SPE	System extension DLL
WINDOW.SPH	Window hierarchy description data file
PROCESS.SPH	Process hierarchy description data file
THREAD.SPH	Thread hierarchy description data file


  Three Spy++ System Views

When Spy++ executes for the first time, it immediately displays three MDI child windows, each containing a different Windows NT "system view." With these windows, you have options for examining the relationship among system objects including processes, threads and windows. The views and their uses are explained in the following sections, beginning with the most complete system view, the System Process Tree.


  The System Process Tree

If you've studied the architecture of Windows NT, you'll know that the system supports multiple "processes." Each process can have one or more "threads," and each thread can have one or more associated top-level "windows." Each top-level window can have a series of child windows arranged in hierarchical order. »Figure 1« shows the Spy++ representation of the System Process Tree with selected levels expanded.

If you've used outlining software, you'll understand the concept of expanding and collapsing levels. Although you can use the Tree menu to control the display, it's often easier to click the minus sign (−) to collapse a level. A plus sign (+) indicates that a level is already collapsed. Click the + sign to expand the level. You can use the Tree menu Collapse All choice if you want to collapse all levels. This collapsed view consists of one line per process.

Use the System Process Tree if you want to examine a particular system process, which usually corresponds to an executing program. Processes are identified by .EXE names, or they are designated "system processes." To find a process, collapse the tree and search through the list.


  The System Thread Tree

The System Thread Tree is a flat listing of all threads with associated windows. Processes are not included. You'll see later that you can easily navigate to the process that owns a selected thread.

Use the System Thread Tree to search for a particular thread.


  The System Window Tree

The System Window Tree shows only windows. »Figure 2« shows the Spy++ representation of the System Window Tree with all levels expanded.

The current desktop window is at the top of the window tree. All other windows are children of the desktop. You can collapse and expand the whole tree by clicking the  − or + signs for the top-level window.

The Window Tree view is most useful if you need to find a particular window. If you start with a tree expanded at the second level (all windows that are children of the desktop), then you can identify a desired desktop-level window by its class name and title. Once you've found the desktop-level window, you can expand the level to find a specific child window.


  Working with Views

You've already seen how Spy++ lets you collapse and expand view levels. Now you'll see how refreshing works, and learn how Spy++ saves and restores the view window positions.


  Saving System View Positions and Opening
New System Views

Spy++ "remembers" the presence and positions of your system view windows. For example, if you delete the System Thread Tree, and you tile the System Process Tree and System Window Tree, Spy++ will save that information when you exit. The next time you run Spy++, you will see the same window layout.

How do you bring back a system view you've deleted? Use the Open System View choice on the Object menu. Choose the view type from the list box that is displayed. It's possible to display multiple system views of the same type, perhaps to display different objects.


  View Refresh

Spy++ takes a "snapshot" of the system tables and refreshes a view based on this information. You can control this refresh process from the menu as follows:

Menu choice	Function key	Description
Refresh	F5	Refresh only the selected view.
Auto Refresh	CTRL+R	Turn on auto refresh for this view. The refresh rate is controlled from the Options menu.
Refresh All	CTRL+F5	Refresh all views.
It is important that you periodically refresh your system views. If you open a Spy++ system view with auto refresh turned off, then you won't see those processes, threads, and windows that are subsequently initialized. Also, you will see items that no longer exist. If you turn on auto refresh for a system view, Spy++ will save the auto-refresh state and restore it the next time you run the program.


  Process Details

You've seen process summary lines in the System Process Tree view window. Note the underlined "hot link" fields that normally appear in green. If you double-click a hexadecimal process ID, like the one highlighted in »Figure 1«, Spy++ creates a Process Details window as shown in »Figure 3«.

Note  The mouse double-click is one way to open a Process Details window. You can also open the window by (1) single-clicking the process ID and then (2) choosing Open Process Details from the Object menu or pressing ENTER.

The Process Details entries include:

Entry	Description
ID Process	The unique ID of this process. Process ID numbers are reused, so they identify a process only for the lifetime of that process. The Process object type is created when a program is run. All the threads in a process share the same address space and have access to the same data.
Executable	The name of the executable program.
ID Parent Process	Process ID for the parent process.
Priority Base	The current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process's base priority.
User Time	The cumulative elapsed time that this process's threads have spent executing code in User Mode in non-idle threads. Applications execute in User Mode, as do subsystems such as the window manager and the graphics engine. Code executing in User Mode cannot damage the integrity of the Windows NT Executive, Kernel, and device drivers.
Privileged Time	The total elapsed time this process has been running in Privileged Mode in non-idle threads. The Windows NT service layer, the Executive routines, and the Windows NT Kernel execute in Privileged Mode. Device drivers for most devices other than graphics adapters and printers also execute in Privileged Mode. Some work that Windows NT does for your application may appear in other subsystem processes in addition to Privileged Time.
Elapsed Time	The total elapsed time this process has been running.
Virtual Bytes	The current size (in bytes) of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. However, virtual space is finite, and using too much may limit the ability of the process to load libraries.
Virtual Bytes Peak	The maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. However, virtual space is finite, and using too much may limit the ability of the process to load libraries.
Page Faults	The number of Page Faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in it's working set in main memory. Thus, the page will not be retrieved from disk if it is on the standby list and hence already in main memory, or if it is being used by another process with whom the page is shared.
Working Set	The set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the Working Set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from Working Sets. If they are needed, they will be soft-faulted back into the Working Set before they leave main memory.
Working Set Peak	The maximum number of pages in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process.
Read Operations	The total number of read operations on file system devices issued by the threads in this process.
Write Operations	The total number of write operations on file system devices issued by threads in this process.
Other Operations	The total number of non-read and non-write operations on file system devices issued by threads in this process. Peripheral control and status calls fall into this category.
Read Transfers	The total number of bytes transferred by read operations issued by threads of this process on file system devices.
Write Transfers	The total number of bytes transferred by write operations issued by threads in this process to file system devices.
Other Transfers	The total number of bytes transferred to file system devices by non-read and non-write operations issued by threads in this process. Peripheral control and status calls fall into this category.
Pool Paged Bytes	The current amount of paged pool the process has allocated. Paged pool is a system memory area where space is acquired by operating system components as they accomplish their appointed tasks. Paged pool pages can be paged out to the paging file when not accessed by the system for sustained periods of time.
Pool Paged Peak	The maximum amount of paged pool the process had allocated at any one time. Paged pool is a system memory area where space is acquired by operating system components as they accomplish their appointed tasks. Paged pool pages can be paged out to the paging file when not accessed by the system for sustained periods of time.
Pool Nonpaged Bytes	The current amount of nonpaged pool allocated by the process. Nonpaged pool is a system memory area where space is acquired by operating system components as they accomplish their appointed tasks. Nonpaged pool pages cannot be paged out to the paging file; they remain in main memory as long as they are allocated.
Pool Nonpaged Peak	The maximum amount of nonpaged pool the process had allocated at any one time. Nonpaged pool is a system memory area where space is acquired by operating system components as they accomplish their appointed tasks. Nonpaged pool pages cannot be paged out to the paging file; they remain in main memory as long as they are allocated.
Page File Bytes	The current number of pages that this process is using in the paging file. The paging file stores pages of data used by the process but not contained in other files. The paging file is used by all processes, and lack of space in the paging file can cause errors while other processes are running.
Page File Bytes Peak	The maximum number of pages that this process has used in the paging file. The paging file stores pages of memory used by the process but not contained in other files. All processes use the paging file, and lack of space in the paging file can cause errors while other processes are running.
Private Bytes	The current number of pages this process has allocated that cannot be shared with other processes.


  Thread Details

You've seen thread summary lines in the System Process Tree window. Note the underlined "hot link" fields that normally appear in green. If you double-click a hexadecimal thread ID, Spy++ creates a Thread Details window as shown in »Figure 4«.

Note  The mouse double-click is one way to open a Thread Details window. You can also open the window by (1) single-clicking the thread ID and then (2) choosing Open Thread Details from the Object menu or pressing Enter.

The Thread Details entries include:

Entry	Description
ID Thread	The unique ID of this thread. Note that thread ID numbers are reused; they identify a thread only for the lifetime of that thread.
ID Process	The process ID for the owner of this thread.
Executable	The name of the executable program.
Priority Current	The current dynamic priority of this thread. Threads within a process can raise and lower their own base priority relative to the base priority of the process.
Priority Base	The current base priority of this process.
Thread State	The current state of the thread. It is 0 for Initialized, 1 for Ready, 2 for Running, 3 for Standby, 4 for Terminated, 5 for Wait, 6 for Transition, 7 for Unknown. A Running thread is using a processor; a Standby thread is about to use one. A Ready Thread is waiting to use a processor because none is free. A thread in Transition is waiting for a resource to execute, such as waiting for its execution stack to be paged in from disk. A Waiting thread does not need the processor because it is waiting for a peripheral operation to complete or a resource to become free.
Thread Wait Reason	This is applicable only when the thread is in the Wait state. It is 0 or 7 when the thread is waiting for the Executive, 1 or 8 for a Free Page, 2 or 9 for a Page In, 3 or 10 for a Pool Allocation, 4 or 11 for an Execution Delay, 5 or 12 for a Suspended condition, 6 or 13 for a User Request, 14 for an Event Pair High, 15 for an Event Pair Low, 16 for an LPC Receive, 17 for an LPC Reply, 18 for Virtual Memory, 19 for a Page Out; 20 and higher were not assigned at the time of this writing. Event Pairs are used to communicate with protected subsystems.
Context Switches	The number of switches from one thread to another. Thread switches can occur either inside a single process or across processes. A thread switch may be caused by one thread asking another for information, or by a thread being preempted when a higher priority thread becomes ready to run.
Start Address	Starting virtual address for this thread.
User PC	Current virtual address for this thread.
User Time	The total elapsed time that this thread has spent executing code in User Mode. Applications execute in User Mode, as do subsystems like the window manager and the graphics engine.
Privileged Time	The total elapsed time that this thread has spent executing code in Privileged Mode. When a Windows NT system service is called, the service will often run in Privileged Mode to gain access to system-private data. Such data is protected from access by threads executing in User Mode. Calls to the system may be explicit, or they may be implicit, such as when a page fault or an interrupt occurs.
Elapsed Time	The total elapsed time (in seconds) this thread has been running.


  Window Details

You've seen window summary lines in the System Window Tree window. Note the underlined "hot link" fields that normally appear in green. If you double-click a hexadecimal window ID, Spy++ creates a Window Details window as shown in »Figure 5«.

Note  The mouse double-click is one way to open a Window Details window. You can also open the window by (1) single-clicking the window handle and then (2) choosing Open Window Details from the Object menu or pressing ENTER. Once a Window Details window is open, you can navigate to other windows with the View menu choices Next Window, Previous Window, First Child, Parent Window, and Owner Window.

The Window Details entries include:

Entry	Description
Window Handle	The unique ID of this window. Window handle numbers are reused; they identify a window only for the lifetime of that window.
Text	The window caption.
Window Class	The name of the window class associated with this window.
Window Procedure	The virtual address of the window procedure function for this window. This field also indicates whether this window is a Unicode window.
Style	A combination of window style codes.
Extended Style	A combination of extended window style codes.
Rectangle	The bounding rectangle for the window. The size of the rectangle is also displayed. Units are pixels in screen coordinates.
Restored Rectangle	This field appears only if the window has been maximized. Units are pixels in screen coordinates.
Client Rectangle	The bounding rectangle for the window client area. The size of the rectangle is also displayed. Units are pixels relative to the top left of the window.
Window Extra Bytes	The number of extra bytes associated with this window. The meaning of these bytes is determined by the application. Expand the level to see the byte values in DWORD format.
Next Window	The handle of the next sibling window in the same sequence shown in the system view (null if no next window).
Previous Window	The handle of the previous sibling window in the same sequence shown in the system view (null if no previous window).
First Child	The handle of this window's first child window, in the sequence shown in the System Window Tree window (null if no child windows).
Parent Window	The handle of this window's parent window (null if no parent).
Owner Window	The handle of this window's owner window. An application main window typically owns system-modal dialog windows, for example.
ID Process	The ID of the process that owns the thread that created this window.
ID Thread	The ID of the thread that created this window.
Control ID or Menu Handle	If the window being displayed is a child window, the Control ID label is displayed. Control ID is an integer that identifies this child windows control ID (0 if the window is a top-level window). If window being displayed is not a child window, the Menu Handle label is displayed. Menu Handle is an integer that identifies this windows control ID (0 if the window is a top-level window).
User Data	Application-specific data that is attached to this window structure.
Instance Handle	The instance handle of the application. Instance handles are not unique.


  Window Class Details

You can navigate from the system views and from the Window Details window to the Window Class Details window. Note the underlined "hot link" fields that normally appear in green. If you double-click a window class name, Spy++ creates a Window Class Details window as shown in »Figure 6«.

Note  The mouse double-click is one way to open a Window Class Details window. You can also open the window by (1) single-clicking the window class name and then (2) choosing Open Window Class Details from the Object menu or pressing ENTER.

The Window Class detail entries include:

Entry	Description
Window Class	The name (and identifier) for this window class.
ID Process	See note, following.
Style	The style code for this window class.
Window Procedure	The current address of the WndProc function for windows of this class.
Class Extra Bytes	Application-specific data associated with this window class.
Window Extra Bytes	Application-specific data associated with windows of this class.
Instance Handle	The instance handle of the module that registered the class. Instance handles are not unique.
Icon Handle	The handle for the icon that is associated with windows of this class.
Cursor Handle	The handle for the cursor that is associated with windows of this class.
Background Brush	The handle for the background brush that is associated with windows of this class, or one of the predefined COLOR_* colors for painting the window background.
Menu Name	The name of the main menu that is associated with windows of this class.
Note  In Windows NT, a process gets a copy of a window class on startup. The process can then modify this copy without affecting other applications. Thus the class structure contains a pointer (Process ID) back to its process.


  Selecting a Window by Mouse Positioning

You've already seen the use of hot links to open a Window Details window from a system view. For a more direct way to select a window, use the following procedure.

To select a visible window with the mouse:

1.	Make sure that Spy++ is loaded.

2.	Arrange your windows so that both Spy++ and the subject window are visible.

3.	From the Spy++ Object menu, choose Find Window to get the dialog box shown in »Figure 7«.

4.	Drag the Finder Tool to the desired window. The dialog box shows window details as you drag the tool.

Finder Tool:

5.	Choose the OK button to bring up the corresponding Window Details window.

Note  If you check the Hide Spy++ option in the Find Window dialog box, the main Spy++ window disappears. This makes it easier to use the Finder Tool to select another window. The Spy++ window reappears when you choose the OK button.


  Viewing a Window Message Stream

Each window has an associated message stream. With Spy++, you can view this message stream in a Window Message Stream window. You can use any of three methods for selecting windows for message stream viewing, and you can apply filtering and formatting specifications to the messages.


  Opening a Window Message Stream Window

You can use one of the following three methods to select a window for message stream viewing:

•	Hold down Shift and double-click a hexadecimal window handle hot link in a Spy++ system view or Window Details window.

•	Single-click to select a window handle hot link, followed by the selection of the Open Window Message Stream choice from the Object menu.

•	Use of the Find Window dialog box, shown in »Figure 7«, with the Window Message Stream option set.

The resulting Window Message Stream window is shown in »Figure 8«. Note that the first column contains the window handle, and the second column contains a message code (explained in »Message Line Coding«,). Decoded message parameters and return values are on the right.

With Spy++, you have considerable control over the content of the Window Message Stream window. You can start and stop the message stream at any time, and you can specify:

•	Which message types you want to see.

•	Which windows you want to monitor.

•	The display format for message lines.

These settings are available from the View menu and apply only to the select Window Message Stream window.


  Starting and Stopping the Message Stream

When a Window Message Stream window is active, a Stop! choice appears in the Spy++ top-level menu. Choosing Stop! suspends the message stream, and the menu item is replaced with a Start! choice. Choosing Start! restarts the message stream.


  Message Filters

When you choose Message Filters from the View menu (this choice is present only when a Window Message Stream window is active), Spy++ opens the Message Filters dialog box as shown in »Figure 9«.

You use this dialog box to select message types for viewing. You first select message groups, then you can fine-tune the selection by selecting individual message types. The All button selects all message groups, and the None button clears all groups.

Note that the last three entries in the Message Group area do not map to specific entries in the Messages to View area. These include:

•	WM_USER − with code greater than WM_USER

•	Registered − registered with the RegisterWindowMessage call

•	Undocumented − unknown messages in the range 0 to (WM_USER - 1)

If you select these "groups," the selection is applied directly to the message stream.

When you create a new Window Message Stream window, the message filter is open for all messages. When you specify a message filter, that selection specification only applies to new messages, not messages that have already been displayed in the Window Message Stream window.

A gray (indeterminate state) in a Message Groups check box indicates that the Messages to View list box has been modified for messages in that group.


  Window Filters

When you choose Window Filters from the View menu, Spy++ displays the Window Filters dialog box with the default settings as shown in »Figure 10«.

The options include:

Option	Description
All Windows	Display messages for all windows.
Specified Window	Display messages for the selected window only.
Include Parent	Display messages for the selected window and its immediate parent window.
Include Children	Display messages for the selected window and all its child windows, including nested child windows.
Include Windows of Same Process	Display messages for the selected window and all other windows owned by the same process.
Save Settings as Default	Save the preceding settings for new message stream windows. These settings are saved when Spy++ exits.
When you create a new Window Message Stream window, the window filter is set for the specified window only. When you specify a different window filter, that selection specification takes effect for new messages, not for messages that have already been displayed in the Window Message Stream window.


  Output Filters

When you choose Output Filters from the View menu, Spy++ displays the Output Filters dialog box with the default settings, as shown in »Figure 11«.

The options include:

Option	Description
Message Nesting Level	Indent nested messages showing one period per level. See »Message Line Coding«.
Raw Message Parameters	Display the hexadecimal wParam and lParam values.
Decoded Message Parameters	Display the results of message-specific decoding of the wParam and lParam values.
Raw Return Values	Display the hexadecimal lResult return value.
Decoded Return Values	Display the results of message-specific decoding of the lResult return value.
Save Settings as Default	Save the preceding settings for new message stream windows. These settings are saved when Spy++ exits.


  Message Line Coding

Notice that the message lines shown in »Figure 8« contain a 'P,' 'S,' or 'R' code. These codes have the following meanings:

Code	Meaning
P	The message was posted to the queue with the PostMessage function. No information is available concerning the ultimate disposition of the message. These message lines list message parameters.
S	The message was sent with the SendMessage function. This means that the sender doesn't regain control until the receiver processes and returns the message. The receiver can, therefore, pass a return value back to the sender. These message lines list message parameters.
s	The message was sent, but Windows NT security prevents access to the return value.
R	Each 'S' line has a corresponding 'R' (return) line that lists the message return value. Sometimes message calls are nested, which means that one message handler sends another message.
In »Figure 8«, the WM_NCACTIVATE and WM_GETTEXT lines illustrate nested messages. The handler for WM_NCACTIVATE sends the WM_GETTEXT message, which returns the number of characters copied. The WM_GETTEXT message lines are marked with a single period because they are nested one level below the WM_NCACTIVATE pair.


  Window Message Stream Control Options

The Lines choice in the View menu (active only for Window Message Stream windows) opens a dialog box that enables you to limit the number of lines that are retained in the message stream view. The line limit applies only to the selected Window Message Stream window. The initial default value is 750, and you can specify that the value be saved as a new default.

Use the Clear choice in the same menu to clear all message lines.


  WinHelp Hot Links

Many Spy++ windows have WinHelp hot-link words, as indicated by underlined text, usually displayed in green. When the mouse is positioned over a hot-link word, the cursor changes to a hand symbol. These Help hot links are visually indistinguishable from the Spy++ detail hot links. Unlike standard Winhelp jumps, which depend on a single-click, both Help and detail links require a double-click for activation. The Window Details Window, shown in »Figure 5«, shows hot links for the window styles WS_CHILD, WS_VISIBLE, and so forth. The Window Message Stream window, shown in »Figure 8«, shows more WinHelp hot links.


  Font and Refresh Rate Options

The Options menu contains Font and Auto Refresh Rate options. With the first choice, you can set the font for all Spy++ windows. With the second, you can specify the refresh rate (in tenths of a second) for all windows that have Auto Refresh turned on.


Figure 1 Maximized Spy++ System Process Tree Window


Figure 2 Maximized Spy++ Window Tree


Figure 3 Process Details Window


Figure 4 Thread Details Window


Figure 5 Window Details Window


Figure 6 Window Class Details Window


Figure 7 Find Window Dialog Box with a Window Selected


Figure 8 Window Message Stream Window


Figure 9 Message Filters Dialog Box


Figure 10 Window Filters Dialog Box


Figure 11 Output Filters Dialog Box


Programming Techniques: Introduction
Programming Techniques

Introduction

The Windows NT™ operating system provides many new challenges for programmers. You may need to port Windows 3.x applications. You may also want to start exploring new areas of functionality provided by Windows NT.

Visual C++™ for Windows NT is designed to make these new features easy to use. The product includes new language elements that support areas of functionality such as exception handling, DLLs, and multithread applications.

This manual, Programming Techniques, is a guide to these advanced language features. Most are directly relevant to services provided by Windows NT or are at least different from Windows 3.x. Therefore, almost all chapters in this manual deal with porting or use of advanced features for Windows NT. In addition, there are a few chapters that describe some feature (such as precompiled headers) inherited with little or no change from Windows 3.x.


Book Location
Programming Techniques


  About This Manual

To understand the basic use of Visual C++, you should refer to other manuals in this documentation set. Despite its name, Programming Techniques does not attempt to teach the basics of C, C++, or programming in Windows. Instead, it covers advanced topics.

However, the first few chapters may be immediately useful to you if you port existing applications from Windows 3.x. Although not divided into parts, the ordering of the manual reflects the different ways you can use it. The following table suggests which chapters you should turn to, depending on your reason for using the manual.

To do this	Refer to chapters
»Port 16-bit applications«	1 - 3
»Port DLL source code«	4
»Use language features of Visual C++ that support new functionality of Windows NT«	5 - 8
»Make sure code runs on the Win32s extension«	9
»Learn about advanced topics, such as inline assembly code and mixed-language programming«	10 - 13


  Document Conventions

This book uses the following typographic conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
char, _setcolor, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. Within discussions of syntax, bold type indicates that the text must be entered exactly as shown.
	Many functions and constants begin with either a single or double underscore. These are part of the name and are mandatory. For example, to have the __cplusplus manifest constant be recognized by the compiler, you must enter the leading double underscore.
expression	Words in italics indicate placeholders for information you must supply, such as a filename. Italic type is also used occasionally for emphasis in the text.
[option]	Items inside double square brackets are optional.
#pragma pack {1 | 2}	Braces and a vertical bar indicate a choice among two or more items. You must choose one of these items unless double square brackets ([ ]  ) surround the braces.
#include <io.h>	This font is used for examples, user input, program output, and error messages in text.
CL [option...]  file...	Three dots (an ellipsis) following an item indicate that more items having the same form may appear.
while() {  .  .  . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second.
	The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
"argument"	Quotation marks enclose a new term the first time it is defined in text.
"C string"	Some C constructs, such as strings, require quotation marks. Quotation marks required by the language have the form " " and ' ' rather than " " and ' '.
Color Graphics Adapter (CGA)	The first time an acronym is used, it is usually spelled out.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  Development Strategies for Windows NT

Windows NT is a complete operating system, not just a graphical user interface (GUI), so you can use it to run simple console applications. In fact, you can use any technique described in this manual without writing for a graphical user interface, as long as no GUI objects are involved. The rest of this section describes how to approach development when porting a traditional program for Windows, which does involve GUI objects such as window handles, window procedures, and messages.

Although Windows NT has many powerful features not present in previous versions of Windows, use of the new features is usually optional. A general process recommended for application developers is:

1.	Focus on porting existing code for Win32™, without using new areas of functionality.

2.	If you plan to distribute the application widely, test it for running under the Win32s™ extension.

3.	After the program runs correctly as a 32-bit application, consider using the new features of Windows NT. Design the program so that it can recover if the feature is not supported (in case the application is running under Win32s).

To successfully use Windows NT, it isn't necessary to start out using new areas of functionality. Instead, you can concentrate on adapting code for Windows 3.x to compile and run correctly on Windows NT. Chapters 1 through 3 discuss porting issues for applications written for Windows. Chapter 4 describes the new programming model for DLLs.

After you've successfully created a 32-bit application, you may want to market it to users of Windows 3.x, not just Windows NT. Visual C++ for Windows NT includes an extension to Windows 3.x called Win32s. This extension lets your application take advantage of the 32-bit architecture and memory layout, while at the same time being usable by people who haven't upgraded to Windows NT. Chapter 9 describes the Win32s extension.

Note  This manual frequently refers to "Win32." This term refers to the common feature-set and architecture of Win32s and Windows NT. There are certain features (such as multithread operations) supported by Windows NT only, not Win32s.

Finally, you may want to start using some of the new features that are most useful to your application. For example, if your application has a number of operations that would be best handled as background tasks, then you can make use of threads. The application can determine whether it is running under Windows NT or Win32s by the API function-return values. For example, if thread creation fails, the application should assume it is running under Win32s, which does not support threads, and alter behavior accordingly. Chapters 5 through 8 explain how to take advantage of these features using Visual C++ language keywords and attributes.


  Advanced Features of Visual C++ for Windows NT

Several features of Windows NT are reflected in language features of Visual C++:

•	Enhanced dynamic link library (DLL) support. (Win32.) The programming model for DLLs does not differ radically from that for Windows 3.x, but some changes to code are necessary. Visual C++ for Windows NT handles the implementation details in an optimal way, and the run-time library provides improved support, especially for C++ objects.

•	Multithread applications. (Windows NT only.) Applications for Windows NT can launch operations of the program (for example, printing output) as separate threads of execution. A thread is different from a process in that it can be created without allocating new resources and data segments, so a thread is much less expensive.

•	Structured exception handling. (Win32.) You can improve the reliability of a program through structured exception handling, a robust and easily maintained approach designed for C language modules. (But note that a specification which better supports C++ objects will be added in a future version.)

•	Other features. (Windows NT only.) Windows NT has a number of other advanced features, such as security levels, that are fully compatible with Visual C++ but not supported through specific features such as new keywords. Refer to Windows NT SDK documentation for information.

Although some features aren't realized specifically with new Visual C++ keywords, they may affect the API in a general way. For example, because of the need to support user security levels and other features, code that writes directly to WIN.INI is no longer valid. Instead, you must use the profile-string API, which is portable between Windows NT and Windows 3.x.

Despite the number of new features, Windows NT is in some respects a simpler system from the programmer's point of view. The following aspects of Windows NT should make development easier, though at first they may present some porting considerations:

•	Memory model. Win32 supports only a flat memory model, in which all of memory is available without having to reload segment registers. This eliminates having to choose between different models.

•	Floating point packages. All floating-point operations are carried out through coprocessor instructions, which the operating system emulates if necessary. From the standpoint of the programmer, there is only one floating-point package.

•	Calling conventions. The fortran and pascal calling conventions are replaced by the system calling convention, __stdcall. Win32 supports several other useful conventions as well. Parameters can only be passed by value or by reference (not near or far), which helps simplify mixed-language programming.


Chapter 1: Porting 16-Bit Code to32-Bit Windows
  Chapter 1  Porting 16-Bit Code to 32-Bit Windows

When you begin writing applications for 32-bit Windows, you probably already have existing applications for 16-bit Windows. Porting these applications is the quickest way to start producing 32-bit software.

This chapter describes how to create a 32-bit version of an application written for Windows 3.x in C, as well as how to make the code portable between versions of Windows. Portable code can be recompiled as either a 16-bit application or a 32-bit application by setting an option.

This chapter includes the following topics:

•	Overview of 32-bit programming

•	Using PORTTOOL to automate porting

•	General steps in porting applications

•	Special considerations for advanced applications


  Overview of 32-Bit Programming

The Application Program Interface (API) for Win32 uses the flat 32-bit addressing mode, supports source code portability with RISC processors, and supports high-end capabilities such as security and true multitasking.

One of the major design goals of the 32-bit API was to minimize the impact on existing code so that 16-bit applications could be adapted as easily as possible. However, some changes were mandated by the larger address space. Pointers are all 32 bits wide and no longer near or far, and your code cannot make assumptions based on segmented memory.

Items which have increased to 32 bits include the following:

•	Pointers

•	Window handles

•	Handles to other objects, such as pens, brushes, and menus

•	Graphics coordinates

These size differences are generally resolved in WINDOWS.H or by the C language, but some changes to source code are necessary. Because the different sizes cause some message parameters to be packed with information differently, you must rewrite code that handles these messages. The larger size of graphics coordinates also affects a number of function calls.

Some source code changes are required because Win32 uses higher-level mechanisms for certain operations, such as MS-DOS calls. These mechanisms make the 32-bit API adaptable to a wide number of platforms, and it supports powerful new features such as multiple threads of execution.

Although Windows 3.x and Win32 were designed to be as compatible as possible, you may need to look carefully over a large amount of source code. Where do you start? The top-down approach is recommended:

1.	Compile the application for 32 bits, and note the errors generated by the compiler.

2.	Replace complex procedures that are difficult to port, as well as procedures written in assembly language, with stub procedures (which do nothing except return).

3.	Fix errors in the main portion of the application, using the techniques described in this chapter.

4.	Fill in each of the stub procedures, one at a time, with portable code after the main portion of the application compiles and runs correctly.


  Using PORTTOOL to Automate Porting

You can use the PORTTOOL utility (PORTTOOL.EXE) to help port applications more easily. This utility finds locations in your code, such as references to certain API functions and messages, that are likely to need revision. You should use PORTTOOL in conjunction with the information in this chapter.

The source code for the PORTTOOL utility is located in the following directory: \MSVCNT\SAMPLES\SDKTOOLS\PORTTOOL. You can examine this code to better understand how PORTTOOL works, or modify it and rebuild it for your own needs. An executable version of the PORTTOOL utility is included in the \MSVCNT\BIN directory.

PORTTOOL uses settings in the file PORT.INI to determine what items to look for. This file is based on the »Summary of API and Message Differences« table .

Use the following steps to start using the PORTTOOL utility:

1.	Run PORTTOOL and load a Windows 3.x source file.

2.	From the Search menu, select the SearchAPI option to search for occurrences of problematic API functions and messages.

When an occurrence of either is found, a dialog box appears that specifies the message or function and briefly suggests what change needs to be made. Although the porting tool is not intended to replace your primary editor, it does support basic editing capabilities (such as Cut, Paste, and Search).


  Steps in Porting Applications

The following sections describe general steps you should take each time you port a 16-bit application to Win32. If your application uses advanced techniques, such as manipulating the WIN.INI file, focus, and mouse capture, you may need to consult the section, »Special Considerations for Advanced Applications«.

The basic steps to porting an application include rewriting the Windows procedure, replacing WORD with proper data types, handling 32-bit messages, and adjusting some of the API calls.


  Removing Near and Far Type Declarations

Windows NT does not recognize near and far addresses, so you may need to remove near and far type declarations from your code. Because the types NEAR and FAR are defined in WINDEF.H, they are automatically handled by the include file, which redefines them as empty strings for Windows NT. This in effect causes NEAR and FAR to be ignored.

A program using any of the keywords _near, _far, __near, and __far is less portable, because these keywords are not defined by include files. A convenient solution is to use the /D command-line option to replace the keywords by empty strings. For example:

/D_near=  /D_far= /D__near=  /D__far=

This approach solves the problem without actually editing the source code.


  Revising the Window Procedure Declaration

The first step in porting a Windows 3.x application is to revise the declaration of the window procedure. The following is a declaration of a window procedure for a Windows 3.x application. Note the use of FAR PASCAL, unsigned, and WORD, respectively, in the first three lines:

LONG FAR PASCAL MainWndProc(	HWND hWnd,
unsigned message,
WORD wParam,
LONG lParam)

To revise the declaration for Win32, replace the data types used in Windows 3.x (FAR PASCAL, unsigned, and WORD) with CALLBACK, WPARAM, LPARAM, and UINT. The revised version, following, can be compiled as a 32-bit application, but it can still be used to compile 16-bit applications as before:

LRESULT CALLBACK MainWndProc(	HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)

FAR PASCAL, shown in the Windows 3.x version of this code, produces the correct results because FAR is ignored and PASCAL is defined as stdcall. But the use of the CALLBACK function type is more portable, because the WINDOWS.H file always defines it as appropriate for the target platform. Currently, Win32 uses the stdcall calling convention, but future versions of the Win32 Development Kit may use different conventions to optimize for more advanced processors.

Table 1.1 summarizes the changes to the declaration noted in the previous example.

Table 1.1    Changes to the Window Procedure Declaration

Windows 3.x	Win32 (portable code)	Reason for changing
FAR PASCAL	CALLBACK	CALLBACK is guaranteed to use whatever calling convention is appropriate for windows and dialog procedures.
unsigned	UINT	Meaning is the same, but UINT guarantees portability for future platforms.
WORD	WPARAM	WORD is always 16 bits. The WPARAM type grows to 32 bits.
LONG	LPARAM	Meaning is the same, but LPARAM guarantees portability for future platforms.
A significant difference between the Windows 3.x declaration and the portable version involves the wParam parameter, which under Win32 grows to 32 bits in size. Therefore, replacing the WORD type with WPARAM is critical. The WPARAM type varies with the operating system, as does UINT: these types are 16 bits wide under Windows 3.x and 32 bits wide under Win32.

The other changes are optional (at least for Intel 80x86 processors) but recommended. For example, WPARAM and LPARAM are automatically defined to be the correct types for message parameters, and CALLBACK will always be the correct declaration for window procedures.

The combination of a 32-bit wParam message parameter, along with the fact that addresses and handles grow to 32 bits, means that a number of messages must be repacked, as described in the section »Handling 32-Bit Messages«.


  Using Proper Data Types

Windows 3.x source code often uses the type WORD interchangeably with types such as HWND and HANDLE. For example, the type cast (WORD) might be used to cast a data type to a handle:

hWnd = (WORD) SendMessage( hWnd, WM_GETMDIACTIVATE, 0, 0 );

This code compiles Windows 3.x applications correctly because both the WORD type and handles are 16 bits. But the code produces errors when compiled for Win32 because handles (such as HWND types) grow to 32 bits while the WORD type is still 16 bits.

To write portable code, examine each occurrence of WORD casts and data definitions in your code, and revise as follows:

•	If a variable or expression is to hold a handle, replace WORD with HWND, HPEN, HINSTANCE, or another handle type.

•	If a variable or expression is a graphics coordinate or some other integer value that grows from 16 to 32 bits, replace WORD with UINT, and short with int.

•	Maintain use of the WORD type only if the data type needs to be 16 bits for all versions of Windows (usually because it is a function argument or structure member).

•	If in doubt, check reference documentation.

UINT is defined to be the most efficient integer size for the target environment: either 16 or 32 bits. For Windows NT, a 32-bit processor is assumed. Such hardware can process 32-bit integers much more efficiently than 16-bit integers. Operations with 32-bit are therefore strongly preferred. The only legitimate reason for using 16-bit integers is the need to pack them into a structure where space is limited.

In the portable version of the previous example, the (WORD) cast is replaced by (HWND):

hWnd = (HWND) SendMessage( hWnd, WM_GETMDIACTIVATE, 0, 0 );

In general, use of the most specific type possible is recommended for writing more portable code. Avoid using a generic handle type such as HANDLE when you can. Try to use a more specific type such as HPEN. You should also define specific types for application-specific objects you might create.


  Handling 32-Bit Messages

When you move from Windows 3.x to Win32, the information packing changes for some messages. You can either:

•	Revise the code so that it works only for the 32-bit version, or

•	Make the message-handling code portable, so that you can easily compile for either the 16-bit or 32-bit environment.

The second method is strongly recommended. This chapter focuses primarily on writing portable versions of the code.

Handles grow to 32 bits under Win32 and can therefore no longer be combined with other information and still fit into a 32-bit parameter (lParam). The handle now occupies all of lParam, so information formerly in the high or low word of lParam must now move to wParam.

Because the wParam message parameter also grows to 32 bits, it can hold the information that can no longer be held in lParam. The following table shows how this repacking works for WM_COMMAND, one of the messages affected.

Environment	wParam	lParam
Windows 3.x	id	hwnd, cmd
Win32	id, cmd	hwnd (32 bits)
»Figure 1.1« illustrates how the sizes of the parameters change, as well as how information is repacked.


  Extracting Data from Messages with Portable Code

When your code handles a message that has been repacked, the cleanest way to revise the code is to first extract needed information from the message and store the information in local variables. This localizes message-packing issues to a few lines of your code.

For example, if your application was written for 16 bits, you can use the following code to handle the WM_COMMAND message:

case WM_COMMAND:
id = wParam;
hwndChild = LOWORD(lParam);
cmd = HIWORD(lParam);

Here is the portable version of the same code, which yields correct results, whether you compile for the 16-bit or 32-bit environment:

case WM_COMMAND:
id = LOWORD(wParam);
hwndChild = (HWND)(UINT)lParam;
#ifdef _WIN32
cmd = HIWORD(wParam);
#else
cmd = HIWORD(lParam);
#endif

Each of the previous examples of data extraction (id, hwndChild, and cmd) illustrates a common case of repacking problems. The following sections deal with each case in turn:

•	Data always occupying the low 16 bits

•	Handles changing size but not location

•	Data that changes in location

Data Always Occupying the Low 16 Bits

The id data, in this case, always occupies the low word of wParam and is always 16 bits. The LOWORD macro produces the correct results because it always returns a 16-bit data type. The result is either all of wParam (if 16 bits) or the low half (if 32 bits):

id = LOWORD(wParam);	 // 16-bit: id=wParam

Handles Not Changing Location

The hwndChild data is the same address as lParam; it is either in the low word or it occupies all of lParam. As long as the address of a handle is always that of lParam, using the cast (HWND)(UINT) correctly extracts the handle:

hwndChild = (HWND)(UINT)lParam;	 // 16-bit: hwnd=LOWORD(lParam);

Data Changing Location

In cases where a piece of data changes packing location under Win32, you need to use an #ifdef statement (or you can write your own conversion macros). In this case, the cmd data moves from the high word of wParam to the high word of wParam, so the portable version of the code is:

#ifdef _WIN32
cmd = HIWORD(wParam);
#else
cmd = HIWORD(lParam);
#endif

Often, LOWORD and HIWORD macros create portability problems, because you should usually not be extracting parts of data types (except as indicated here).


  Using Message Crackers to Write Portable Code

Message crackers are a set of macros that parse message parameters.  They enable you to write portable code without having to use #ifdef statements to parse messages. Some examples of macros used to parse message parameters follow:

GET_WM_COMMAND_ID  (wParam, lParam)   // Parse control ID value
GET_WM_COMMAND_HWND(wParam, lParam)   // Parse control HWND
GET_WM_COMMAND_CMD (wParam, lParam)   // Parse notification command

For each version of Windows (Windows 3.x and Win32), there is a WINDOWSX.H header file that defines these macros as appropriate. The Windows 3.x version is WINDOWSX.H16. Refer to Chapter 2, »Handling Messages with Portable Macros«, for more information.


  Summary of Windows Messages Affected

Use Table 1.2 to reference the packing of Windows messages affected by porting. The approaches discussed in the previous sections can be used for each message. Where two parameters are given, the one listed first corresponds to the least-significant 16 bits.

Except for the WM_CTLCOLOR messages, each message is given in the following table with two rows: the first row gives 16-bit Windows packing for the message, and the one following it gives Win32 packing.

Table 1.2    Windows Messages Affected by Porting

Message	Windows	wParam	lParam
WM_ACTIVATE	16-bit  Win32	state state, fMinimized	fMinimized, hwnd hwnd (32 bits)
WM_CHARTOITEM	16-bit Win32	char char, pos	pos, hwnd hwnd (32 bits)
WM_COMMAND	16-bit Win32	id id, cmd	hwnd, cmd hwnd (32 bits)
WM_CTLCOLOR	16-bit	hdc	hwnd, type
WM_CTLCOLORtype1	Win32	hdc (32 bits)	hwnd (32 bits)
WM_MENUSELECT	16-bit Win32	cmd cmd, flags	flags, hMenu hMenu (32 bits)
WM_MDIACTIVATE	16-bit Win32	fActivate hwndActivate (32 bits)	hwndDeactivate, hwndActivate hwndDeactivate (32 bits)
WM_MDISETMENU	16-bit Win32	0 hMenuFrame (32 bits)	hMenuFrame, hMenuWindow hMenuWindow (32 bits)
WM_MENUCHAR	16-bit Win32	char char, fMenu	hMenu, fMenu hMenu (32 bits)
WM_PARENTNOTIFY	16-bit Win32	msg msg, id	id, hwndChild hwndChild  (32 bits)
WM_VKEYTOITEM	16-bit Win32	code code, item	item, hwnd hwnd (32 bits)
EM_GETSEL (returns wStart, wEnd)	16-bit Win32	0 0 or lpdwStart	0 0 or lpdwEnd
EM_LINESCROLL	16-bit Win32	0 mLinesHorz (32 bits)	nLinesVert, nLinesHorz nLinesVert  (32 bits)
EM_SETSEL	16-bit Win32	0 wStart (32 bits)	wStart, wEnd wEnd (32 bits)
WM_HSCROLL, WM_VSCROLL	16-bit Win32	code code, pos	pos, hwnd hwnd (32 bits)
1  Under Win32, WM_CTLCOLOR is replaced by a series of messages, each corresponding to a different type. To write portable code, use #ifdef statements to handle this difference.


  Summary of DDE Messages Affected

DDE messages are packed differently for Win32 and Windows 3.x. These differences are shown in Table 1.3.

Table 1.3    DDE Messages Affected by Porting

Message	Windows	wParam	lParam
WM_DDE_ACK (posted form only)	16-bit	hwnd	wStatus, aItem or wStatus, hCommands
	Win32	hwnd (32 bits)	hDDEAck (see following paragraph)
WM_DDE_ADVISE	16-bit	hwnd	hOptions, aItem
	Win32	hwnd (32 bits)	hDDEAdvise (see following paragraph)
WM_DDE_DATA	16-bit	hwnd	hData, aItem
	Win32	hwnd (32 bits)	hDDEData (see following paragraph)
WM_DDE_POKE	16-bit	hwnd	hData, aItem
	Win32	hwnd (32 bits)	hDDEPoke (see following paragraph)
Because of storage limitations, some of the information in the 32-bit versions of the messages is stored in a structure, which is accessed through the handle in lParam. You can use the following API functions to extract information from these structures: PackDDElParam, UnPackDDElParam, and FreeDDElParam.

For information on how to use these structures and API functions, consult the Win32 API reference.


  Adjusting Calls to API Functions

Most of your source code is not affected by differences between the APIs of Windows 3.x and Win32. The underlying definitions in WINDOWS.H automatically adjust data to the correct size. But you may need to revise code if you call API functions in any of the following categories:

•	Graphics functions

•	Functions accessing "extra" window data

•	MS-DOS system calls

•	Far-pointer functions

•	Functions getting list and combo box contents


  Graphics Functions

Most of the Windows 3.x API functions that must be replaced return packed x- and y-coordinates.

In Windows 3.x, the x- and y-coordinates are 16 bits each and are packed into the 32-bit (DWORD) function return value, the largest valid size. In Win32, the coordinates are 32 bits each, totaling 64 bits, and are thus too large to fit into a single return value. Each Windows 3.x function is replaced by a Win32 function with the same name, but with an Ex suffix added. The Ex functions pass the x- and y-coordinates using an additional parameter instead of a return value. These new functions are supported by both Win32 and Windows 3.x.

The problematic graphics functions fall into two groups. The first group, functions that set coordinates, are shown in the following table with the Win32 versions.

Windows 3.x function	Portable version of function
MoveTo	MoveToEx
OffsetViewportOrg	OffsetViewportOrgEx
OffsetWindowOrg	OffsetWindowOrgEx
ScaleViewportExt	ScaleViewportExtEx
ScaleWindowExt	ScaleWindowExtEx
SetBitmapDimension	SetBitmapDimensionEx
SetMetaFileBits	SetMetaFileBitsEx
SetViewportExt	SetViewportExtEx
SetWindowExt	SetWindowExtEx
SetWindowOrg	SetWindowOrgEx
Each of the functions in the first column returns a value, although application code frequently ignores it. However, even if you do not care about the return value, you must still replace the old function call by the new form. The old functions are not supported under Win32.

Each Ex function includes an additional parameter that points to a location to receive data. After the function call, this data provides the same information as the corresponding function's return value. If you do not need this information, you can pass NULL to this parameter.

Under Windows 3.x, a call to the MoveTo function can be written as follows:

MoveTo( hDC, x, y );

In the portable version supported by both versions of Windows, the call to MoveTo is rewritten as follows. Note that the information returned by MoveTo under Windows 3.x is still ignored:

MoveToEx( hDC, x, y, NULL );

As a general rule, pass NULL as the last parameter unless you need to use the x- and y-coordinates returned by the Windows 3.x version. In the latter case, use the procedure outlined in the next few paragraphs for the Get functions.

The second group of functions consists of functions in which the application code normally does use the return value. They are listed in the following table.

Windows 3.x function	Portable version of function
GetAspectRatioFilter	GetAspectRatioFilterEx
GetBitmapDimension	GetBitmapDimensionEx
GetBrushOrg	GetBrushOrgEx
GetCurrentPosition	GetCurrentPositionEx
GetTextExtent	GetTextExtentPoint
GetTextExtentEx	GetTextExtentExPoint
GetViewportExt	GetViewportExtEx
GetViewportOrg	GetViewportOrgEx
GetWindowExt	GetWindowExtEx
GetWindowOrg	GetWindowOrgEx
The GetTextExtent function uses the Point suffix because there is already a Windows 3.1 extended function GetTextExtentEx. Therefore, the Point suffix is added to the functions GetTextExtent and GetTextExtentEx, to name the portable versions for each.

As with the first group of functions, the Ex (and Point) versions each add an additional parameter: a pointer to a POINT or SIZE structure to receive x- and y-coordinates. Because this structure is always the appropriate size for the environment, you can write portable code by:

•	Declaring a local variable of type POINT or SIZE, as appropriate.

•	Passing a pointer to this structure as the last parameter to the function.

•	Calling the function. The function responds by filling the structure with the appropriate information.

For example, the Windows 3.x version call to GetTextExtent extracts the x- and y-coordinates from a DWORD return value (stored in a temporary variable, dwXY):

DWORD	dwXY;

dwXY = GetTextExtent( hDC, szLabel1, strlen( szLabel1 ) );
rect.left = 0; rect.bottom = 0;
rect.right = LOWORD(dwXY);
rect.top = HIWORD(dwXY);
InvertRect( hDC, &rect );

The portable version passes a pointer to a temporary SIZE structure, and then it extracts data from the structure:

SIZE sizeRect;

GetTextExtentPoint( hDC, szLabel1, strlen( szLabel1 ), &sizeRect );
rect.left = 0; rect.bottom = 0;
rect.right = sizeRect.cx;
rect.top = sizeRect.cy;
InvertRect( hDC, &rect );


  Functions That Access the Extra Window Data

The functions described in this section manipulate the "extra" data area of a window structure. This structure can contain system information as well as user-defined data. You specify the size of this data area by using the cbClsExtra and cbWndExtra members of the WNDCLASS structure when you register the window class.

The following Windows 3.x functions get or set 16 bits during each call: GetClassWord, GetWindowWord, SetClassWord, and SetWindowWord.

You can use these functions in Windows 3.x to access system information, stored as 16-bit items. But in Win32, each of these system-information items grows to 32 bits. Therefore, in Win32, you would use the following functions which access 32 bits at a time: GetClassLong, GetWindowLong, SetClassLong, and SetWindowLong.

Each of these functions take two parameters: a window handle and an offset into the data area. These offsets differ depending on whether you are compiling for Windows 3.x or Win32.

The index values specifying these offsets correspond to each other as follows. Note that neither version is portable.

Windows 3.x	Win32 (nonportable)
GCW_CURSOR	GCL_CURSOR
GCW_HBRBACKGROUND	GCL_HBRBACKGROUND
GCW_HICON	GCL_HICON
GWW_HINSTANCE	GWL_HINSTANCE
GWW_HWNDPARENT	GWL_HWNDPARENT
GWW_ID	GWL_ID
GWW_USERDATA	GWL_USERDATA
To create portable code using these offsets, you need to use #ifdef statements as follows. Both the function and the value of the second parameter change:

#ifdef _WIN32
hwndParent = (HWND)GetWindowLong(hWnd, GWL_HWNDPARENT);
#else
hwndParent = (HWND)GetWindowWord(hWnd, GWW_HWNDPARENT);
#endif

In the case of GWW_HWNDPARENT, you can avoid calls to GetWindowLong and GetWindowWord altogether, and instead use a single call to a new API function, GetParent. This API function returns a handle of the appropriate size. The following example illustrates a call to GetParent that has the same results as the #ifdef statements shown in the previous example:

hwndParent = GetParent( hWnd );

Remember that offsets may change for private data that you store in the window structure. You should review this code carefully and recalculate offsets for Win32, noting that some data types, such as handles, increase in size.


  Porting MS-DOS System Calls

The DOS3Call API function in Windows 3.0 must be called from assembly language. It is typically used to perform file I/O. In Win32, assembly language code that calls DOS3Call should be replaced by the appropriate Win32 file I/O calls. Other (non-file) INT 21H functions should be replaced with the portable Windows API call as shown in the following table.

INT 21H subfunction	MS-DOS operation	Win32 API equivalent
0EH	Select Disk	SetCurrentDirectory
19H	Get Current Disk	GetCurrentDirectory
2AH	Get Date	GetDateAndTime
2BH	Set Date	SetDateAndTime
2CH	Get Time	GetDateAndTime
2DH	Set Time	SetDateAndTime
36H	Get Disk Free Space	GetDiskFreeSpace
39H	Create Directory	CreateDirectory
3AH	Remove Directory	RemoveDirectory
3BH	Set Current Directory	SetCurrentDirectory
3CH	Create Handle	CreateFile
3DH	Open Handle	CreateFile
3EH	Close Handle	CloseHandle
3FH	Read Handle	ReadFile
40H	Write Handle	WriteFile
41H	Delete File	DeleteFile
42H	Move File Pointer	SetFilePointer
43H	Get File Attributes	GetAttributesFile
43H	Set File Attributes	SetAttributesFile
47H	Get Current Directory	GetCurrentDirectory
4EH	Find First File	FindFirstFile
4FH	Find Next File	FindNextFile
56H	Change Directory Entry	MoveFile
57H	Get Date/Time of File	GetDateAndTimeFile
57H	Set Date/Time of File	SetDataAndTimeFile
59H	Get Extended Error	GetLastError
5AH	Create Unique File	GetTempFileName
5BH	Create New File	CreateFile
5CH	Lock	LockFile
5CH	Unlock	UnlockFile
67H	Set Handle Count	SetHandleCount


  File Operations

Fixed-length buffers for filenames and environment strings may need to be increased in size. Windows NT (one of the forms of Win32) supports filenames of up to 256 characters, rather than the 8.3 format supported by MS-DOS. You can make code more portable by allocating longer buffers or by using dynamic memory allocation. If you want to conserve memory under Windows 3.x, you can use #ifdef statements to allocate buffers of the proper length for the environment. You can also use macros such as _MAX_PATH and _MAX_FNAME, defined in STDLIB.H.

Windows NT requires a stricter use of file open and close operations than Windows 3.x does. There are some combinations of open and close functions (for example, mixing _open with _lclose) that may work in code for Windows 3.x, but require revision to work correctly with Windows NT.

Another area in which you might need to make changes is low-level file I/O. In porting Windows 3.x code, some developers have chosen to change from using the Windows API file I/O functions (such as _lopen and  _lread) to using the C run-time low-level I/O functions (such as _open and _read). All versions of the Windows API support binary mode only, not text mode, but the C run-time calls use text mode by default. Therefore, when changing from the Windows file I/O to the C run-time versions, open files in binary mode by doing one of the following:

•	Link with BINMODE.OBJ, which changes the default mode for all file-open operations.

•	Open the individual files with _O_BINARY flag set.

•	Use setmode to change an open file to _O_BINARY.


  Far-Pointer Functions

Windows 3.x provides functions for memory and file manipulation using far pointers, which have the form _fxxxx. In Win32, these functions are replaced by similarly-named functions of the form xxxx, because there is no need for far pointers in Win32. (The _f prefix is dropped from the name.)

The WINDOWSX.H file defines the _fxxxx function names so that in Win32, the _fxxxx function names are equated to the corresponding functions that are still supported. This means that as long as you include WINDOWSX.H, you don't have to rewrite calls to these functions. Some of the definitions are:

#define _fmemcpy    	memcpy
#define _fstrcpy      	strcpy
#define _fstrcmp      	strcmp
#define _fstrcat      	strcat


  Functions Getting List and Combo Box Contents

The Win32 API contains two new functions, shown in the following table, that provide an improved means of extracting list and combo box contents. In each case, you use the portable version of the function to specify a buffer size for a string that receives the information.

Windows 3.x function	Portable version of the function
DlgDirSelect	DlgDirSelectEx
DlgDirSelectComboBox	DlgDirSelectComboBoxEx
For example, Windows 3.x code might contain the following function call:

DlgDirSelect( hDlg, lpString, nIDListBox );

This line of code should be replaced by the following call to DlgDirSelectEx:

DlgDirSelectEx( hDlg, lpString, strlen(lpString), nIDListBox );


  Revising the WinMain Function

You need to revise the WinMain function if either of the following conditions is true:

•	Your application needs to know when another instance of the application is running, or

•	You need to access the command line.

Otherwise, the code in this function generally needs no change.

The parameter list for WinMain is the same for Win32 and Windows 3.x:

int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)

However, under Win32, there are two differences in the values passed through these parameters:

•	Unlike Windows 3.x, hPrevInstance is always passed NULL.

•	The lpCmdLine parameter points to a string containing the entire command line, not just the parameters.

The following two sections discuss each of these differences.


  Initializing Instances

The hPrevInstance parameter is always passed NULL in Win32. This causes each instance of an application to act as though it were the only instance running. The application must register the window class, and it cannot access data used by other instances, except through standard interprocess communication techniques such as shared memory or DDE. Calls to GetInstanceData must be replaced with these techniques.

Source code for Windows 3.x normally tests hPrevInstance to see if another instance of the application is already running; if the value is NULL (indicating there is no previous instance), the code registers the window class. This code is automatically portable to Win32 and needs no change: the result under Win32 is simply that it always registers the window class, which is correct behavior.

Some applications must know if other instances are running. Sometimes this is because data sharing is required. More frequently, it is because only one instance of the application should run at a time. Examples of this latter case include Control Panel and Task Manager.

Applications cannot use hPrevInstance to test for previous instances under Win32. An alternative method must be used, such as creating a unique named pipe, creating or testing for a named semaphore, broadcasting a unique message, or calling FindWindow.


  Accessing the Command Line Through LpCmdLine

In Windows 3.x, the lpCmdLine parameter points to a string containing the command line starting with the first parameter. The name of the application is not included. In Win32, lpCmdLine points to a string containing the entire command line, including the application itself.


  Special Considerations for Advanced Applications

If you have applied the guidelines and procedures described in the preceding sections, you may well have been able to revise your entire application so that it is portable. However, problems specific to applications that use advanced API calls or C coding tricks require additional revision. If your application is fairly complex, you should scan through this section to make sure that you don't need additional changes.


  Revising Advanced API Calls

Applications may need further revision if they use API calls dealing with any of the following: accessing .INI files, setting focus and active window, capturing the mouse, and sharing graphical objects.


  Profile Strings and .INI Files

Although Windows NT and Win32s are both examples of Win32, Windows NT presents some additional features not present in Win32s.

Windows 3.x applications can access .INI files directly. In Windows NT, however, such code doesn't work because the information in .INI files is replaced by a registration database. This database offers a number of advantages, including security controls that prevent an application from corrupting system information, error logging, remote software updating, and remote administration of workstation software.

You can write portable code by using the profile API supported by Windows 3.x and all versions of Win32, including Windows NT. Call the GetProfileString and WriteProfileString API functions instead of accessing .INI files directly. These functions use whichever underlying mechanism (.INI file or registration database) is supported by the environment you are compiling for.


  Focus, Mouse Capture, and Localized Input

The Windows NT environment differs from Windows 3.x in that each thread of execution has its own message pump. This change affects window focus and mouse capture.

Window Focus

In Windows NT, each thread of execution can set or get the focus only to windows created by the current thread. This behavior prevents applications from interfering with each other. One application's delay in responding cannot cause other applications to suspend their response to user actions, as often happens in Windows 3.x.

Consequently, the following API functions work differently under Windows NT:

GetActiveWindow( VOID )	SetActiveWindow( HWND )
GetCapture( VOID )	SetCapture( HWND )
GetFocus( VOID )	SetFocus( HWND )
ReleaseCapture( VOID )
Get functions can now return NULL, which could not happen in Windows 3.x. Therefore, it's important to test the return value of GetFocus before using it. Instead of returning the window handle of another thread, the function returns NULL. For example, you call GetFocus and another thread has the focus. Note that it's possible for a call to GetFocus to return NULL even though an earlier call to SetFocus successfully set the focus. Similar considerations apply to GetCapture and GetActiveWindow.

The Set functions can only specify a window created by the current thread. If you attempt to pass a window handle created by another thread, the call to the Set function fails.

Mouse Capture

Mouse capture is also affected by the Windows NT localized input queues. If the mouse is captured on mouse down, the window capturing the mouse receives mouse input until the mouse button is released, as in Windows 3.x. But if the mouse is captured while the mouse button is up, the window receives mouse input only as long as the mouse is over that window or another window created by the same thread.


  Shared Graphical Objects

Win32 applications run in separate address spaces. Graphical objects are specific to the application and cannot be manipulated by other processes as in Windows 3.x. A handle to a bitmap passed to another process cannot be used because the original process retains ownership.

Each process should create its own pens and brushes. A cooperative process may access the bitmap data in shared memory (by way of standard interprocess communications) and create its own copy of the bitmap. Alterations to the bitmap must be communicated between the cooperative processes by way of interprocess communication, such as DDE.

Win32 adds an explicit ownership transfer API function for graphical objects to explicitly allow cooperative applications to share graphical objects.


  Solving Problems Due to C Coding Techniques

Some portability problems can be caused by C coding techniques that do not translate successfully to other memory models and processors. You can avoid these problems if your code doesn't attempt to exploit the fact that you know about segmented memory. Standard pointer and memory management techniques will be correctly resolved by the header files.

The coding techniques most likely to cause porting problems are described in the following sections. For a more thorough general treatment of this subject, see Chapter 13, »Writing Portable C Programs«.


  Memory and Pointers

To be portable, source code must avoid any techniques that rely on the 16-bit segment:offset address structure, because all pointers are 32 bits in size under Win32 and use flat rather than segmented memory.

This difference in pointer structure is usually not a problem unless the code uses HIWORD, LOWORD, or similar macros to manipulate portions of the pointer.

For example, in Windows 3.x, memory is allocated to align on a segment boundary, which makes memory allocation functions return a pointer with an offset of 0x0000. The following code exploits this fact to run successfully under Windows 3.x:

ptr2 = ptr1 = malloc();                 // ptr2 = xxxx:0000
LOWORD( ptr2 ) = index * elementsize;   // Place offset of array element
                                        //   into ptr2 low word

Such code does not work properly under Win32. But standard pointer constructs, such as the following, always result in portable code:

ptr1 = malloc();            // Set ptr1 to start of memory block
ptr2 = &ptr1[i];             // Place offset of array element

Here are some other guidelines for dealing with pointers:

•	All pointers, including those that access the local heap, are 32 bits under Win32.

•	Addresses never wrap, as they can with the low word in segmented addressing. For example, in Windows 3.x, an address can wrap from 1000:FFFF to 1000:0000.

•	Structures that hold near pointers in Windows 3.x must be revised because all pointers are 32 bits in Win32. This may affect code that uses constants to access structure members, and it may also affect alignment.


  Structure Alignment

Applications should generally align structure members at addresses that are "natural" for the data type and the processor involved. For example, a 4-byte data member should have an address that is a multiple of four.

This principle is especially important when you write code for porting to multiple processors. A misaligned 4-byte data member, which is on an address that is not a multiple of four, causes a performance penalty with an 80386 processor and a hardware exception with a MIPS® RISC processor. In the latter case, although the exception is handled by the system, the performance penalty is significantly greater.

The following guidelines ensure proper alignment for processors targeted by Win32:

Type	Alignment
char	Align on byte boundaries
short (16-bit)	Align on even byte boundaries
int and long (32-bit)	Align on 32-bit boundaries
float	Align on 32-bit boundaries
double	Align on 64-bit boundaries
structures	Largest alignment requirement of any member
unions	Alignment requirement of the first member
The compiler automatically aligns data in accordance with these requirements, inserting padding in structures up to the limit (default pack size) specified by the /Zp option or #pragma pack. For example, /Zp2 permits up to 1 byte of padding, /Zp4 permits up to 3 bytes of padding, and so on. The default pack size for Windows 3.x is 2, whereas the default for Win32 is 8. As a consequence:

•	If you have specified a packing limit with /Zp or #pragma pack, you may not get the proper alignment (the default value) for Win32.

•	The different default setting for Win32 can have consequences for your source code, by causing offsets of some structure members to change. Examine your code closely to see if you have hard-coded these offsets, or if your code makes assumptions based on a certain default pack size.


  Ranges and Promotions

Occurrences of int, unsigned, and unsigned int indicate potential portability problems because size and range are not constant. Data that would not exceed its range in Win32 could exceed range in Windows 3.x. Sign extension also works differently, so exercise caution in performing bitwise manipulation of this data.

Source code that relies on wrapping often presents portability problems and should be avoided. For example, a loop should not rely on an unsigned variable wrapping at 65535 (the maximum value in Windows 3.x) back down to 0.


  Summary of API and Message Differences

Table 1.4 provides a complete list of API calls and messages that required implementation changes for Win32.

Table 1.4    API and Message Implementation Changes for Win32

API/Message	Support	Comments
AccessResource	Dropped	No Win32 API equivalent (resource API in progress)
AddFontResource	Enhanced	Must use string, not handle, for filename
AllocDSToCSAlias	Dropped	No Win32 API equivalent
AllocResource	Dropped	No Win32 API equivalent (resource API in progress)
AllocSelector	Dropped	No Win32 API equivalent
ChangeSelector	Dropped	No Win32 API equivalent
CloseComm	Dropped	Replaced by CloseFile
CloseSound	Dropped	Replaced by multimedia sound support
CountVoiceNotes	Dropped	Replaced by multimedia sound support
DeviceCapabilities	Dropped	Replaced by portable DeviceCapabilitiesEx
DeviceMode	Dropped	Replaced by portable DeviceModeEx
DlgDirSelect	Dropped	Replaced by portable DlgDirSelectEx
DlgDirSelectComboBox	Dropped	Replaced by portable DlgDirSelectComboBoxEx
DOS3Call	Dropped	Replaced by named, portable Win32 API
ExtDeviceMode	Dropped	Replaced by portable ExtDeviceModeEx
FlushComm	Dropped	Replaced by PurgeComm
FreeSelector	Dropped	No Win32 API equivalent
GetAspectRatioFilter	Dropped	Replaced by portable GetAspectRatioFilterEx
GetBitmapDimension	Dropped	Replaced by portable GetBitmapDimensionEx
GetBrushOrg	Dropped	Replaced by portable GetBrushOrgEx
GetClassWord	Enhanced	Use GetClassLong for values that grow to 32 bits in Win32
GetCodeHandle	Dropped	No Win32 API equivalent
GetCodeInfo	Dropped	No Win32 API equivalent
GetCommError	Dropped	Replaced by GetCommState
GetCurrentPDB	Dropped	No Win32 API equivalent
GetCurrentPosition	Dropped	Replaced by portable GetCurrentPositionEx
GetEnvironment	Dropped	No Win32 API equivalent
GetInstanceData	Dropped	No equivalent; use alternative supported IPC mechanism
GetKBCodePage	Dropped	No Win32 API equivalent
GetMetaFileBits	Dropped	Replaced by portable GetMetaFileBitsEx
GetModuleUsage	Enhanced	Always returns 1 on Win32
GetTempDrive	Dropped	Not applicable to Win32
GetTextExtent	Dropped	Replaced by portable GetTextExtentPoint
GetTextExtentEx	Dropped	Replaced by portable GetTextExtentExPoint
GetThresholdEvent	Dropped	Replaced by multimedia sound support
GetThresholdStatus	Dropped	Replaced by multimedia sound support
GetViewportExt	Dropped	Replaced by portable GetViewportExtEx
GetViewportOrg	Dropped	Replaced by portable GetViewportOrgEx
GetWindowExt	Dropped	Replaced by portable GetWindowExtEx
GetWindowOrg	Dropped	Replaced by portable GetWindowOrgEx
GetWindowWord	Enhanced	Use GetWindowLong for values that grow to 32 bits on Win32
GlobalDosAlloc	Dropped	No Win32 API equivalent
GlobalDosFree	Dropped	No Win32 API equivalent
GlobalPageLock	Dropped	No Win32 API equivalent
GlobalPageUnlock	Dropped	No Win32 API equivalent
LimitEMSPages	Dropped	No Win32 API equivalent
LocalNotify	Dropped	No Win32 equivalent
MoveTo	Dropped	Replaced by portable MoveToEx
NetBIOSCall	Dropped	Replaced by named, portable Win32 API
OffsetViewportOrg	Dropped	Replaced by portable OffsetViewportOrgEx
OffsetWindowOrg	Dropped	Replaced by portable OffsetWindowOrgEx
OpenComm	Dropped	Replaced by OpenFile
OpenSound	Dropped	Replaced by multimedia sound support
ProfClear	Dropped	Replaced by Win32 profile-string API
ProfFinish	Dropped	Replaced by Win32 profile-string API
ProfFlush	Dropped	Replaced by Win32 profile-string API
ProfInsChk	Dropped	Replaced by Win32 profile-string API
ProfSampRate	Dropped	Replaced by Win32 profile-string API
ProfSetup	Dropped	Replaced by Win32 profile-string API
ProfStart	Dropped	Replaced by Win32 profile-string API
ProfStop	Dropped	Replaced by Win32 profile-string API
ReadComm	Dropped	Replaced by ReadFile
RemoveFontResource	Enhanced	Must use string, not handle, for filename
ScaleViewportExt	Dropped	Replaced by portable ScaleViewportExtEx
ScaleWindowExt	Dropped	Replaced by portable ScaleWindowExtEx
SetBitmapDimension	Dropped	Replaced by portable SetBitmapDimensionEx
SetClassWord	Enhanced	Use SetClassLong for values that grow to 32 bits on Win32
SetCommEventMask	Dropped	Replaced by SetCommMask
SetEnvironment	Dropped	No Win32 API equivalent
SetMetaFileBits	Dropped	Replaced by portable SetMetaFileBitsEx
SetResourceHandler	Dropped	No Win32 API equivalent (resource API in progress)
SetSoundNoise	Dropped	Replaced by multimedia sound support
SetViewportExt	Dropped	Replaced by portable SetViewportExtEx
SetViewportOrg	Dropped	Replaced by portable SetViewportOrgEx
SetVoiceAccent	Dropped	Replaced by multimedia sound support
SetVoiceEnvelope	Dropped	Replaced by multimedia sound support
SetVoiceNote	Dropped	Replaced by multimedia sound support
SetVoiceQueueSize	Dropped	Replaced by multimedia sound support
SetVoiceSound	Dropped	Replaced by multimedia sound support
SetVoiceThreshold	Dropped	Replaced by multimedia sound support
SetWindowExt	Dropped	Replaced by portable SetWindowExtEx
SetWindowOrg	Dropped	Replaced by portable SetWindowOrgEx
SetWindowWord	Enhanced	Use SetWindowLong for values that grow to 32 bits on Win32
StartSound	Dropped	Replaced by multimedia sound support
StopSound	Dropped	Replaced by multimedia sound support
SwitchStackBack	Dropped	No Win32 API equivalent
SwitchStackTo	Dropped	No Win32 API equivalent
SyncAllVoices	Dropped	Replaced by multimedia sound support
UngetCommChar	Dropped	No Win32 equivalent
ValidateCodeSegments	Dropped	No Win32 API equivalent
ValidateFreeSpaces	Dropped	No Win32 API equivalent
WaitSoundState	Dropped	Replaced by multimedia sound support
WriteComm	Dropped	Replaced by WriteFile
EM_GETSEL	Enhanced	wParam/lParam packing changed
EM_LINESCROLL	Enhanced	wParam/lParam packing changed
EM_SETSEL	Enhanced	wParam/lParam packing changed
WM_ACTIVATE	Enhanced	wParam/lParam packing changed
WM_CHANGECBCHAIN	Enhanced	wParam/lParam packing changed
WM_CHARTOITEM	Enhanced	wParam/lParam packing changed
WM_COMMAND	Enhanced	wParam/lParam packing changed
WM_CTLCOLOR	Replaced	Replaced by WM_CTLCOLORtype messages; wParam/lParam packing changed
WM_DDE_ACK	Enhanced	wParam/lParam packing changed
WM_DDE_ADVISE	Enhanced	wParam/lParam packing changed
WM_DDE_DATA	Enhanced	wParam/lParam packing changed
WM_DDE_EXECUTE	Enhanced	wParam/lParam packing changed
WM_DDE_POKE	Enhanced	wParam/lParam packing changed
WM_HSCROLL	Enhanced	wParam/lParam packing changed
WM_MDIACTIVATE	Enhanced	wParam/lParam packing changed
WM_MDISETMENU	Enhanced	wParam/lParam packing changed
WM_MENUCHAR	Enhanced	wParam/lParam packing changed
WM_MENUSELECT	Enhanced	wParam/lParam packing changed
WM_PARENTNOTIFY	Enhanced	wParam/lParam packing changed
WM_VKEYTOITEM	Enhanced	wParam/lParam packing changed
WM_VSCROLL	Enhanced	wParam/lParam packing changed
(WORD)	16-bit	Check if incorrect cast of 32-bit value; WORD is unsigned 16-bit int
GCW_CURSOR	Dropped	Replaced by GetSetClassCursor
GCW_HBRBACKGROUND	Dropped	Replaced by GetSetClassBrBackground
GCW_HICON	Dropped	Replaced by GetSetClassIcon
GWW_HINSTANCE	Dropped	Replaced by GWL_HINSTANCE
GWW_HWNDPARENT	Dropped	Replaced by GWL_HWNDPARENT
GWW_ID	Dropped	Replaced by GWL_ID
GWW_USERDATA	Dropped	Replaced by GWL_USERDATA
HIWORD	16-bit	Check if HIWORD target is 16-bit or 32-bit
LOWORD	16-bit	Check if LOWORD target is 16-bit or 32-bit
WndProc	Widened	Define Window procedures: WndProc ( HWND hwnd, UINT msg, UINT wParam, UINT lParam )
wndproc	Widened	Define Window procedures: WndProc (HWND hwnd, UINT msg, UINT wParam, UINT lParam )
DCB	Enhanced	Changes to bitfields and additional structure members
MAKEPOINT	Dropped	Replaced by LONG2POINT


  Chapter 2  Handling Messages with Portable Macros

Instead of taking the case-by-case approach shown in the previous chapter, you can use message-cracking macros to write message handlers similar to those you'd write when using Microsoft Foundation Classes. These message handlers use the same parameter list regardless of operating system, thereby solving message-packing issues. This chapter describes these and other macros defined in WINDOWSX.H (or WINDOWSX.H16 in the case of 16-bit applications).

This chapter includes the following topics:

•	Using message crackers

•	Writing message crackers for user-defined messages

•	Adapting message crackers to special cases

•	Calling control message macros


  Using Message Crackers

Message crackers are a set of macros that extract useful information from the wParam and lParam parameters of a message and hide the details of how information is packed.

Using message crackers initially requires you to revise some of your code. Message crackers also have a minor impact on performance by involving an additional function call. However, they offer the following major advantages:

•	Portability. Message crackers free you from packing issues and guarantee proper extraction of information, regardless of which environment you're compiling for.

•	Readability. With message crackers, you can understand source code because message parameters are translated into data with meaningful names.

•	Ease of use. In addition to decoding wParam and lParam, message crackers place message-handling code in separate functions. Instead of a long switch statement, you have a separate handler for each message.


  Overview of Message Crackers

You use message crackers in your code by writing a separate message handler function for each message. Then you use a macro to call each of those functions from within your window procedure.

Use of message crackers for all messages is recommended, but you can optionally combine code that uses message crackers for some messages with code that responds to other messages directly.

Note  To use message crackers, make sure you include the file WINDOWSX.H (or WINDOWSX.H16, in the case of 16-bit applications).

Suppose you have a message, WM_THIS. The code to handle this message would look something like this:

LRESULT CALLBACK My_WndProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam )
.
.
.
switch( msg ) {
case WM_THIS:
// Place code to handle message here

To use message crackers, write a message handler, and then call it from the switch statement. Suppose that there are two pieces of information contained in the WM_THIS message: thisHdc and thisData. Message crackers unpack this information from wParam and lParam, and pass it as parameters to your message handler, MyWnd_OnThis, as depicted in »Figure 2.1.«

Note that the parameters to MyWnd_OnThis (after hwnd, which is always the first parameter) consist of information directly usable by your code: thisHdc and thisData. The macro HANDLE_WM_THIS translates wParam and lParam into thisHdc and thisData as it makes the function call.

The following general steps summarize how to use message crackers:

•	Declare a prototype for each message-handling function.

•	In the window procedure, call the message handler. Use either a message decoder (such as HANDLE_WM_CREATE) or the HANDLE_MSG macro.

•	Write the message handler. Use a message forwarder such as FORWARD_WM_CREATE to call the default message procedure.


  Declaring Message-Handler Prototypes

To use message crackers, first declare a prototype for the message handling function ("message handler" for short). Although you can give your message handlers any name you want, a recommended convention is:

WndClass_OnMsg

in which WndClass is the name of the window class, and Msg is the name of the message in mixed case, with the "WM" dropped. For example, the following code contains prototypes for functions handling WM_CREATE, WM_PAINT, and WM_MOUSEMOVE:

BOOL MyWnd_OnCreate( HWND hwnd, CREATESTRUCT FAR* lpCreateStruct );
void MyWnd_OnPaint( HWND hwnd );
void MyWnd_OnMouseMove( HWND hwnd, int x, int y, UINT keyFlags );

The first parameter to each function is always hwnd, which is a handle to the window that received the message. The rest of the parameters vary; each message handler has its own customized parameter list. To declare the appropriate parameters for a message, see the corresponding definitions in WINDOWSX.H.


  Calling the Message Handler

In your window procedure, you call a message handler by using a message-decoder macro such as HANDLE_WM_CREATE or HANDLE_WM_PAINT. The general form for using these macros is:

case msg:
return HANDLE_msg ( hwnd, wParam, lParam, handler );

You should always return the value of the macro, even if no return value is expected and the corresponding message handler has void return type.

For example, you could place the following macros in your code:

switch( msg ) {
case WM_CREATE:
return HANDLE_WM_CREATE( hwnd, wParam, lParam, MyWnd_OnCreate );
case WM_PAINT:
return HANDLE_WM_PAINT( hwnd, wParam, lParam, MyWnd_OnPaint );
case WM_MOUSEMOVE:
return HANDLE_WM_MOUSEMOVE( hwnd, wParam, lParam,
                                    MyWnd_OnMouseMove );
.
.
.

Alternatively, you can use the generic HANDLE_MSG macro, which generates the same code as the previous example, but saves space:

switch( msg ) {
HANDLE_MSG( hwnd, WM_CREATE, MyWnd_OnCreate );
HANDLE_MSG( hwnd, WM_PAINT, MyWnd_OnPaint );
HANDLE_MSG( hwnd, WM_MOUSEMOVE, MyWnd_OnMouseMove );
.
.
.

HANDLE_MSG assumes that you use the names wParam and lParam in the window procedure parameter list. You cannot use this macro if you have given these parameters other names.


  Writing the Message Handler

In the message-handling function, you respond to the message using parameters that have been translated from wParam and lParam and passed to the function. In the following example, lpCreateStruct is an example of a parameter translated from wParam and lParam:

BOOL MyCls_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct)
{
// Place message-handling code here

    return FORWARD_WM_CREATE(hwnd, lpCreateStruct, DefWindowProc);
}

Message-handling code often finishes by calling DefWindowProc or some other default message procedure. You make this function call by using a "message forwarder," which uses the following form:

return FORWARD_msg( parmlist, defaultMsgProc );

The parmlist is the same list of parameters in the message handler, and defaultMsgProc is the default message procedure, typically DefWindowProc. The message forwarder repacks the information in the parameter list into the appropriate wParam/lParam format (depending on target environment) and forwards the message to the default message procedure.


  Putting it Together: An Example

The following example demonstrates the use of several message handlers in a window procedure, showing where the various prototypes and macros fit into the code.

The header file, MYAPP.H, consists of function prototypes, including prototypes for the message handlers. Note how each message handler has its own parameter list, which is customized to best represent the information packed in the corresponding message:

// MYAPP.H

// Window procedure prototype

LRESULT CALLBACK MyWnd_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Default message handler

#define MyWnd_DefProc    DefWindowProc

// MyWnd class message handler functions, declared in a .h file:
//
void MyWnd_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags);
void MyWnd_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
void MyWnd_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags);

The rest of the code in this example is in MYAPP.C, which contains the window procedure and the individual message handlers. With message crackers, the function of the window procedure is principally to route each message to the appropriate handler.

Both the WM_LBUTTONDOWN and WM_LBUTTONDBLCLK messages map to the MyWnd_OnLButtonDown procedure. This mapping is one of the special cases of message handling described in the next section.

// MYAPP.C   ------------------------------------------------------------------------

// MyWnd window procedure implementation.
//
LRESULT CALLBACK MyWnd_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM Param)
{
    switch (msg)
    {
        HANDLE_MSG(hwnd, WM_MOUSEMOVE,MyWnd_OnMouseMove);
        HANDLE_MSG(hwnd, WM_LBUTTONDOWN, MyWnd_OnLButtonDown);
        HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK, MyWnd_OnLButtonDown);
        HANDLE_MSG(hwnd, WM_LBUTTONUP, MyWnd_OnLButtonUp);
    default:
        return MyWnd_DefProc(hwnd, msg, wParam, lParam);
    }
}

// Message handler function implementations:
//
void MyWnd_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
{
    .
.
.
return FORWARD_WM_MOUSEMOVE( hwnd, x, y, keyFlags, MyWnd_DefProc);
}

void MyWnd_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
    .
.
.
return FORWARD_WM_LBUTTONDOWN( hwnd, fDoubleClick, x, y, keyFlags, MyWnd_DefProc);
}

void MyWnd_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags)
{
    .
.
.
return FORWARD_WM_LBUTTONUP( hwnd, x, y, keyFlags, MyWnd_DefProc);
}

Note that the symbol MyWnd_DefProc is defined to represent DefWindowProc. The purpose of this definition is to make code more reusable. This approach assumes you have a similar definition in each application. For example, in an MDI child control procedure, you would have this definition:

#define MyWnd_DefProc    DefMDIChildProc

If you then copied your message handler to the MDI procedure, you would only need to change the prefix in MyWnd_DefProc to make the code you copied work correctly. Conversely, if your code used the explicit call to DefWindowProc, it could create a bug that would be difficult to track down when copied to the MDI code.


  Handling Special Cases of Messages

As a general rule, there is one set of message crackers for each message: a message decoder and a message forwarder. Another rule is that each message handler you write should return the same value that your code would normally return for that message. The following messages present exceptions to these rules.

Message handler	Comment
OnCreate, OnNCCreate	BOOL return type: returns TRUE if there are no errors. If FALSE is returned, a window will not be created.
OnKey	Handles both key up and key down messages. The extra parameter fDown indicates whether the key is down or up.
OnLButtonDown, OnRButtonDown	Handles both click (button down) and double-click messages. The extra parameter fDoubleClick indicates whether the message received is a double-click message.
OnChar	This handler is passed only by character, and not the virtual key or key flags information.


  Writing Message Crackers for User-Defined Messages

You can use message crackers with window messages that you define, but you must write your own macros. The easiest way to do this is to copy and modify existing macros from WINDOWSX.H.

To understand how to write these macros, consider some of the message crackers defined in WINDOWSX.H:

/* BOOL Cls_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct) */

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) \

    ((fn)(hwnd, (CREATESTRUCT FAR*)lParam) ? 0L : (LRESULT)-1L)

#define FORWARD_WM_CREATE(hwnd, lpCreateStruct, fn) \
    (BOOL)(DWORD)(fn)(hwnd, WM_CREATE, 0, (LPARAM)lpCreateStruct)

The message decoder (HANDLE_msg) should be defined as a function call, (fn), followed by hwnd and other parameters derived from wParam and lParam. The message forwarder (FORWARD_msg) performs the reverse operation on the parameters, putting information back together to restore wParam and lParam before making the function call (fn). Each of these macros must cast the return value so that the correct type is returned.

When calling the message crackers you write, be careful about variable message values. If your message value is a constant (such as WM_USER+100), you can use HANDLE_MSG with the message in a switch statement. However, if the message is registered with RegisterWindowMessage, it assigns a number at run time. In this situation, you can't use HANDLE_MSG, because variables cannot be used as case values. You must handle the message separately, in an if statement:

// In MyWnd class initialization code:
//
UINT WM_NEWMESSAGE= 0;

WM_NEWMESSAGE= RegisterWindowMessage("WM_NEWMESSAGE");
.
.
.
// In MyWnd_WndProc(): window procedure:
//
LRESULT CALLBACK MyWnd_WndProc(HWND hwnd, WORD msg, WPARAM wParam,
                          LPARAM lParam)
{
    if (msg == WM_NEWMESSAGE)
        HANDLE_WM_NEWMESSAGE(hwnd, wParam, lParam, MyWnd_OnNewMessage);

    switch (msg)
    {
        HANDLE_MSG(hwnd, WM_MOUSEMOVE, MyWnd_OnMouseMove);
    	.

.

.

}
}


  Adapting Message Crackers to Special Cases

Message crackers can generally be used with all types of application code. However, certain situations require modifications in coding style.

The next few sections show how to adapt message-cracker coding techniques for dialog procedures, window subclassing, and window instance data.


  Dialog Procedures

Dialog procedures return a BOOL value to indicate whether the message was processed. (Window procedures, in contrast, return a LONG value rather than a BOOL.) Therefore, to adapt a message cracker to dialog-procedure code, you must call the message handler and cast the value to BOOL.

Because you have to insert the (BOOL) cast, you can't use HANDLE_MSG. You must invoke the message-decoder macro explicitly. Here's an example that shows how you'd use message crackers in a dialog procedure:

BOOL MyDlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam);
void MyDlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);

BOOL CALLBACK MyDlg_DlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    //
    // Since HANDLE_WM_INITDIALOG returns an LRESULT,
    // we must cast it to a BOOL before returning.
    //
    case WM_INITDIALOG:
        return (BOOL)HANDLE_WM_INITDIALOG(hwndDlg, wParam, lParam, MyDlg_OnInitDialog);

    case WM_COMMAND:
        HANDLE_WM_COMMAND(hwndDlg, wParam, lParam, MyDlg_OnCommand);
        return TRUE;
        break;

    default:
        return FALSE;
    }
}


  Window Subclassing

When you use message crackers with a subclassed window procedure, the strategy described earlier for using message forwarders does not work. Recall that this strategy involves the following macro call:

return FORWARD_msg( parmlist, defaultMsgProc );

This use of a message forwarder (FORWARD_msg) calls defaultMsgProc directly. But in a subclassed window procedure, you must call the window procedure of the superclass by using the API function CallWindowProc. The problem is that FORWARD_msg calls defaultMsgProc with four parameters, but CallWindowProc needs five parameters.

The solution is to write an intermediate procedure. For example, the intermediate procedure could be named test_DefProc:

        FORWARD_WM_CHAR(hwnd, ch, cRepeat, test_DefProc);

The test_DefProc function calls CallWindowProc and prepends the address of the superclass function (in this case, test_lpfnwpDefProc) to the parameter list:

LRESULT test_DefProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return CallWindowProc(test_lpfnwpDefProc, hwnd, msg, wParam,
lParam);

}

You need to write just one such procedure for each subclassed window in your application. Each time you use a message forwarder, you give this intermediate procedure as the function address instead of DefWindowProc. The following example code shows the complete context:

// Global variable that holds the previous window proc address of
// the subclassed window:
//
WNDPROC test_lpfnwpDefProc = NULL;

// Code fragment to subclass a window and store previous wndproc value:
//
void Subclasstest(HWND hwndtest)
{
    extern HINSTANCE g_hinsttest;    // Global application instance handle

    // SubclassWindow() is a macro API that calls SetWindowLong()
    // as appropriate to change the window proc of hwndtest.
    //
    test_lpfnwpDefProc = SubclassWindow(hwndtest,
            (WNDPROC)MakeProcInstance( (FARPROC)test_WndProc, g_hinsttest));
.
.
.
}

// Default message handler function
//
// This function invokes the superclasses' window procedure.  It
// must be declared with the same signature as any window proc,
// so it can be used with the FORWARD_WM_* macros.
//
LRESULT test_DefProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return CallWindowProc(test_lpfnwpDefProc, hwnd, msg, wParam, lParam);
}
// test window procedure.  Everything here is the same as in the
// normal non-subclassed case: the differences are encapsulated in
// test_DefProc.
//
LRESULT CALLBACK test_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        HANDLE_MSG(hwnd, WM_CHAR, test_OnChar);
        .
.
.
    default:
        //
        // Be sure to call test_DefProc(), NOT DefWindowProc()!
        //
        return test_DefProc(hwnd, msg, wParam, lParam);
    }
}

// Message handlers
//
void test_OnChar(HWND hwnd, UINT ch, int cRepeat)
{
    if (ch == testvalue)
    {
        // handle it here
    }
    else
    {
        // Forward the message on to test_DefProc
        //
        FORWARD_WM_CHAR(hwnd, ch, cRepeat, test_DefProc);
    }
}


  Window Instance Data

It is common for a window to have user-declared state variables (or "instance data") kept in a separate data structure allocated by the application. You associate this data structure with its corresponding window by storing a pointer to the structure in a specially named window property or in a window word (allocated by setting the cbWndExtra field of the WNDCLASS structure when the class is registered).

Message crackers can be adapted to work with this use of instance data. Place the hwnd of the window in the first member of the structure. Then, in the message decoders (HANDLE_msg macros), pass the address of the structure instead of the hwnd. The message handler now gets a pointer to the structure instead of the hwnd, but it can access the hwnd through indirection. You may need to rewrite some of the message handler to make it use indirection to access the window handle.

The following example illustrates this technique:

// Window instance data structure.  Must include window handle field.
//
typedef struct _test
{
    HWND hwnd;
    int otherStuff;
} test;

// "test" window class was registered with cbWndExtra = sizeof(test*), so we
// can use a window word to store back pointer.  Window properties can also
// be used.
//
// These macros get and set the pointer to the instance data corresponding to the
// window.  Use GetWindowWord or GetWindowLong as appropriate based on the default
// size of data pointers.
//
#ifdef _WIN32
#define test_GetPtr(hwnd)        (test*)GetWindowLong((hwnd), 0)
#define test_SetPtr(hwnd, ptest)  (test*)SetWindowLong((hwnd), 0, (LONG)(ptest))
#else
#define test_GetPtr(hwnd)        (test*)GetWindowWord((hwnd), 0)
#define test_SetPtr(hwnd, ptest)  (test*)SetWindowWord((hwnd), 0, (WORD)(ptest))
#endif

// Default message handler

#define test_DefProc DefWindowProc

// Message handler functions, declared with a test* as their first argument,
// rather than an HWND.  Other than that, their signature is identical to
// that shown in WINDOWSX.H.
//
BOOL test_OnCreate(test* ptest, CREATESTRUCT FAR* lpcs);
void test_OnPaint(test* ptest);
//
// Code to register the test window class:
//
BOOL test_Init(HINSTANCE hinst)
{
    WNDCLASS cls;

    cls.hCursor         = ...;
    cls.hIcon           = ...;
    cls.lpszMenuName    = ...;
    cls.hInstance       = hinst;
    cls.lpszClassName   = "test";
    cls.hbrBackground   = ...;
    cls.lpfnWndProc     = test_WndProc;
    cls.style           = CS_DBLCLKS;
    cls.cbWndExtra      = sizeof(test*);  // room for instance data ptr
    cls.cbClsExtra      = 0;

    return RegisterClass(&cls);
}

// The window proc for class "test".  This demonstrates how instance data is
// attached to a window and passed to the message handler functions.
//
LRESULT CALLBACK test_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    test* ptest = test_GetPtr(hwnd);

    if (ptest == NULL)
    {
    // If we're creating the window, try to allocate it.
    //
    	if (msg == WM_NCCREATE)
    	{
        	// Create the instance data structure, set up the hwnd backpointer
        	// field, and associate it with the window.
        	//
        	ptest = (test*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(test));

        	// If an error occurred, return 0L to fail the CreateWindow call.
        	// This will cause CreateWindow() to return NULL.
        	//
        	if (ptest == NULL)
        	return 0L;
        	ptest->hwnd = hwnd;
        	test_SetPtr(hwnd, ptest);

        	// NOTE: the rest of the test structure should be initialized
        	// inside Template_OnCreate() (or Template_OnNCCreate()).  Further
        	// creation data may be accessed through the CREATESTRUCT FAR* parameter.
        	//
    	}
    	else
    	{
        	// It turns out WM_NCCREATE is NOT necessarily the first message
        	// received by a top-level window (WM_GETMINMAXINFO is).
        	// Pass messages that precede WM_NCCREATE on through to
        	// test_DefProc
        	//
        	return test_DefProc(hwnd, msg, wParam, lParam);
    	}
    }

    if (msg == WM_NCDESTROY)
    {
    	LocalFree((HLOCAL)ptest);

   	ptest = NULL;
    	test_SetPtr(hwnd, NULL);

    }

    switch (msg)
    {
    HANDLE_MSG(ptest, WM_CREATE, test_OnCreate);
    HANDLE_MSG(ptest, WM_PAINT, test_OnPaint);
    ...

    default:
    	return test_DefProc(hwnd, msg, wParam, lParam);
    }
}


  Using Control Message Functions

The control message API functions perform a role that is the converse of message crackers: instead of handling messages sent to your window, they send messages to other windows (controls).

Each of the control message functions packs parameters into the appropriate wParam/lParam format and then calls SendMessage. These functions offer the same portability advantages that message crackers do; they free you from having to know how the current operating system packs wParam and lParam.

The function calls also improve readability of code and support better type checking. When used with the STRICT enhancements, the control message functions help prevent incorrect passing of message parameters.

To see how the control message functions work, first look at the following source code, which makes two calls to SendMessage to print all the lines in an edit control:

void PrintLines(HWND hwndEdit, WHND hwndDisplay)
{
    int line;

    int lineLast = (int)SendMessage(hwndEdit, EM_GETLINECOUNT, 0, 0L);

    for (line = 0; line < lineLast; line++)
    {
        int cch;
        char ach[80];

        *((LPINT)ach) = sizeof(ach);
        cch = (int)SendMessage(hwndEdit, EM_GETLINE,
                line, (LONG)(LPSTR)ach);

        PrintInWindow(ach, hwndDisplay);
    }
}

The following source code uses two control message functions, Edit_GetLineCount and Edit_GetLine, to perform the same task. This version of the code is shorter, easier to read, doesn't generate compiler warnings, and doesn't have any non-portable casts:

void PrintLines(HWND hwndEdit, WHND hwndDisplay)
{
    int line;
    int lineLast = Edit_GetLineCount(hwndEdit);

    for (line = 0; line < lineLast; line++)
    {
        int cch;
        char ach[80];

        cch = Edit_GetLine(hwndEdit, line, ach, sizeof(ach));

        PrintInWindow(ach, hwndDisplay);
    }
}

The control message API functions are listed in Table 2.1. For more information, refer to the macro definitions in WINDOWSX.H and the documentation for the corresponding window message.

Table 2.1    Control Message API Functions

Control group	Functions
Static Text Controls:	Static_Enable(hwnd, fEnable)
	Static_GetIcon(hwnd, hIcon)
	Static_GetText(hwnd, lpch, cchMax)
	Static_GetTextLength(hwnd)
	Static_SetIcon(hwnd, hIcon)
	Static_SetText(hwnd, lpsz)
Button Controls:	Button_Enable(hwnd, fEnable)
	Button_GetCheck(hwnd)
	Button_GetState(hwnd)
	Button_GetText(hwnd, lpch, cchMax)
	Button_GetTextLength(hwnd)
	Button_SetCheck(hwnd, check)
	Button_SetState(hwnd, state)
	Button_SetStyle(hwnd, style, fRedraw)
	Button_SetText(hwnd, lpsz)
Edit Controls:	Edit_CanUndo(hwnd)
	Edit_EmptyUndoBuffer(hwnd)
	Edit_Enable(hwnd, fEnable)
	Edit_FmtLines(hwnd, fAddEOL)
	Edit_GetFirstVisible(hwnd)
	Edit_GetHandle(hwnd)
	Edit_GetLine(hwnd, line, lpch, cchMax)
	Edit_GetLineCount(hwnd)
	Edit_GetModify(hwnd)
	Edit_GetRect(hwnd, lprc)
	Edit_GetSel(hwnd)
	Edit_GetText(hwnd, lpch, cchMax)
	Edit_GetTextLength(hwnd)
	Edit_LimitText(hwnd, cchMax)
	Edit_LineFromChar(hwnd, ich)
	Edit_LineIndex(hwnd, line)
	Edit_LineLength(hwnd, line)
	Edit_ReplaceSel(hwnd, lpszReplace)
	Edit_Scroll(hwnd, dv, dh)
	Edit_SetHandle(hwnd, h)
	Edit_SetModify(hwnd, fModified)
	Edit_SetPasswordChar(hwnd, ch)
	Edit_SetRect(hwnd, lprc)
	Edit_SetRectNoPaint(hwnd, lprc)
	Edit_SetSel(hwnd, ichStart, ichEnd)
	Edit_SetTabStops(hwnd, cTabs, lpTabs)
	Edit_SetText(hwnd, lpsz)
	Edit_SetWordBreak(hwnd, lpfnWordBreak)
	Edit_Undo(hwnd)
Scroll Bar Controls:	ScrollBar_Enable(hwnd, flags)
	ScrollBar_GetPos(hwnd)
	ScrollBar_GetRange(hwnd, lpposMin, lpposMax)
	ScrollBar_SetPos(hwnd, pos, fRedraw)
	ScrollBar_SetRange(hwnd, posMin, posMax, fRedraw)
	ScrollBar_Show(hwnd, fShow)
List Box Controls:	ListBox_AddFile(hwnd, lpszFilename)
	ListBox_AddItemData(hwnd, data)
	ListBox_AddString(hwnd, lpsz)
	ListBox_DeleteString(hwnd, index)
	ListBox_Dir(hwnd, attrs, lpszFileSpec)
	ListBox_Enable(hwnd, fEnable)
	ListBox_FindItemData(hwnd, indexStart, data)
	ListBox_FindString(hwnd, indexStart, lpszFind)
	ListBox_GetAnchorIndex(hwnd)
	ListBox_GetCaretIndex(hwnd)
	ListBox_GetCount(hwnd)
	ListBox_GetCurSel(hwnd)
	ListBox_GetHorizontalExtent(hwnd)
	ListBox_GetItemData(hwnd, index)
	ListBox_GetItemHeight(hwnd, index)1
	ListBox_GetItemRect(hwnd, index, lprc)
	ListBox_GetSel(hwnd, index)
	ListBox_GetSelCount(hwnd)
	ListBox_GetSelItems(hwnd, cItems, lpIndices)
	ListBox_GetText(hwnd, index, lpszBuffer)
	ListBox_GetTextLen(hwnd, index)
	ListBox_GetTopIndex(hwnd)
	ListBox_InsertItemData(hwnd, lpsz, index)
	ListBox_InsertString(hwnd, lpsz, index)
	ListBox_ResetContent(hwnd)
	ListBox_SelectItemData(hwnd, indexStart, data)
	ListBox_SelectString(hwnd, indexStart, lpszFind)
	ListBox_SelItemRange(hwnd, fSelect, first, last)
	ListBox_SetAnchorIndex(hwnd, index)
	ListBox_SetCaretIndex(hwnd, index)
	ListBox_SetColumnWidth(hwnd, cxColumn)
	ListBox_SetCurSel(hwnd, index)
	ListBox_SetHorizontalExtent(hwnd, cxExtent)
	ListBox_SetItemData(hwnd, index, data)
	ListBox_SetItemHeight(hwnd, index, cy)1
	ListBox_SetSel(hwnd, fSelect, index)
	ListBox_SetTabStops(hwnd, cTabs, lpTabs)
	ListBox_SetTopIndex(hwnd, indexTop)
Combo Box Controls:	ComboBox_AddItemData(hwnd, data)
	ComboBox_AddString(hwnd, lpsz)
	ComboBox_DeleteString(hwnd, index)
	ComboBox_Dir(hwnd, attrs, lpszFileSpec)
	ComboBox_Enable(hwnd, fEnable)
	ComboBox_FindItemData(hwnd, indexStart, data)
	ComboBox_FindString(hwnd, indexStart, lpszFind)
	ComboBox_GetCount(hwnd)
	ComboBox_GetCurSel(hwnd)
	ComboBox_GetDroppedControlRect(hwnd, lprc)1
	ComboBox_GetDroppedState(hwnd)1
	ComboBox_GetEditSel(hwnd)
	ComboBox_GetExtendedUI(hwnd)1
	ComboBox_GetItemData(hwnd, index)
	ComboBox_GetItemHeight(hwnd)
	ComboBox_GetLBText(hwnd, index, lpszBuffer)
	ComboBox_GetLBTextLen(hwnd, index)
	ComboBox_GetText(hwnd, lpch, cchMax)
	ComboBox_GetTextLength(hwnd)
	ComboBox_InsertItemData(hwnd, index, data)
	ComboBox_InsertString(hwnd, index, lpsz)
	ComboBox_LimitText(hwnd, cchLimit)
	ComboBox_ResetContent(hwnd)
	ComboBox_SelectItemData(hwnd, indexStart, data)
	ComboBox_SelectString(hwnd, indexStart, lpszSelect)
	ComboBox_SetCurSel(hwnd, index)
	ComboBox_SetEditSel(hwnd, ichStart, ichEnd)
	ComboBox_SetExtendedUI(hwnd, flags)1
	ComboBox_SetItemData(hwnd, index, data)
	ComboBox_SetItemHeight(hwnd, cyItem)1
	ComboBox_SetText(hwnd, lpsz)
	ComboBox_ShowDropdown(hwnd, fShow)
(1)  Supported only for Win32, not for Windows 3.x. These APIs are not available if you define the symbol WINVER as equal to 0x0300, on the command line or with a #define statement.


Chapter 3: WINDOWS.H and STRICT Type Checking
  Chapter 3  WINDOWS.H and STRICT Type Checking

The WINDOWS.H file contains a number of type definitions, macros, and structures that aid in writing source code that is portable between versions of Microsoft Windows. Some of the WINDOWS.H features are enabled when the STRICT symbol is defined on the command line or makefile. This chapter explains how these STRICT features affect the writing of correct code and what the advantages of using them are.

This chapter discusses the following topics:

•	New types and macros

•	Using STRICT to improve type checking


  New Types and Macros

Chapter 1, »Porting 16-Bit Code to 32-Bit Windows«, introduced some new standard types for programming in Windows. Use of the old types, such as FAR PASCAL for declaring window procedures, may work in existing code but is not guaranteed to work in all future versions of Windows. Therefore, you should convert your code to use the new standards wherever appropriate.


  General Data Types

The following table summarizes the new standard types defined in WINDOWS.H. These types are polymorphic (they can contain different kinds of data) and are useful generally throughout applications. There are also other new types, handles, and function pointers that are introduced in following sections.

Typedef	Description
WINAPI	Use in place of FAR PASCAL in API declarations. If you are writing a DLL with exported API entry points, you can use this for your own APIs.
CALLBACK	Use in place of FAR PASCAL in application callback routines such as window procedures and dialog procedures.
LPCSTR	Same as LPSTR, except used for read-only string pointers. Defined as (const char FAR*).
UINT	Portable unsigned integer type whose size is determined by host environment (32 bits for Windows NT). Synonym for unsigned int. Used in place of WORD except in the rare cases where a 16-bit unsigned quantity is desired even on 32-bit platforms.
LRESULT	Type used for return value of window procedures.
LPARAM	Type used for declaration of lParam, the fourth parameter of a windows procedure.
WPARAM	Type used for declaration of wParam, the third parameter of a windows procedure (a polymorphic data type).
LPVOID	Generic pointer type, equivalent to (void *). Should be used in preference to LPSTR.


  Utility Macros

WINDOWS.H provides a series of utility macros that are useful for working with the types listed in the previous section. These macros, listed in the following table, help create and extract data from these types. The FIELDOFFSET macro is particularly useful when you need to give the numeric offset of a structure member as an argument.

Utility	Description
MAKELPARAM(low, high)	Combines two 16-bit quantities into an LPARAM.
MAKELRESULT(low, high)	Combines two 16-bit quantities into an LRESULT.
MAKELP(sel, off)	Combines a selector and an offset into a FAR VOID* pointer. Useful only for Windows 3.x.
SELECTOROF(lp)	Extracts the selector part of a far pointer. Returns a UINT. Useful only for Windows 3.x.
OFFSETOF(lp)	Extracts the offset part of a far pointer. Returns a UINT. Useful only for Windows 3.x.
FIELDOFFSET(type, field)	Calculates the offset of a member of a data structure. The type is the type of structure, and field is the name of the structure member or field.


  New Handle Types

In addition to the existing Windows handle types such as HWND, HDC, HBRUSH, and so on, WINDOWS.H defines the following new handle types. They are particularly important if STRICT type checking is enabled, but you can use these even if you do not define STRICT.

Handle	Description
HINSTANCE	Instance handle type
HMODULE	Module handle type
HBITMAP	Bitmap handle type
HLOCAL	Local handle type
HGLOBAL	Global handle type
HTASK	Task handle type
HFILE	File handle type
HRSRC	Resource handle type
HGDIOBJ	Generic GDI object handle type (except HMETAFILE)
HMETAFILE	Metafile handle type
HDWP	DeferWindowPos() handle
HACCEL	Accelerator table handle
HDRVR	Driver handle (Windows NT only)


  Using STRICT to Improve Type Checking

Defining the STRICT symbol enables features that require you to be more careful in declaring and using types. This may sound like a burden, but it is actually an aid to writing more portable code. This extra care will also reduce the time you spend debugging. Enabling STRICT redefines certain data types so that the compiler won't permit assignment from one type to another without an explicit cast. This is especially helpful with Windows code. Errors in passing data types are reported at compile time instead of causing fatal errors at run time.

When STRICT is defined, WINDOWS.H type definitions change as follows:

•	Specific handle types are defined so as to be mutually exclusive; for example, you won't be able to pass an HWND where an HDC type argument is required. Without STRICT, all handles are defined as integers, so the compiler doesn't prevent you from using one type of handle where another type is expected.

•	All callback function types (dialog procedures, window procedures, and hook procedures) are defined with full prototypes. This prevents you from declaring callback functions with incorrect parameter lists.

•	Parameter and return value types that should use a generic pointer are declared correctly as LPVOID instead of as LPSTR or another pointer type.

•	The COMSTAT structure is now declared according to the ANSI standard.


  Enabling STRICT Type Checking

To enable STRICT type checking, just define the symbol name "STRICT". You can specify this definition on the command line or in a makefile by giving /DSTRICT as a compiler option.

To define STRICT on a file-by-file basis (supported by C but not C++ as explained in the note in this section), insert a #define statement before including WINDOWS.H in files where you want to enable STRICT:

#define STRICT
#include WINDOWS.H

For best results, you should also set the warning level for error messages to at least /W3. This is a good policy with applications for Windows in any case, because a coding practice that causes a warning (for example, passing the wrong number of parameters) usually causes a fatal error at run time if it is not corrected.

Note  If you are writing a C++ application, you don't have the option of applying STRICT to only some of your source files. Because of the way C++ "type safe linking" works, mixing STRICT and non-STRICT source files in your application can cause linking errors.


  Making Your Application STRICT Compliant

Some source code that in the past compiled successfully might produce error messages when you enable STRICT type checking. The following sections describe the minimal requirements you need to follow, where applicable, to make sure your code compiles when STRICT is enabled. There are other steps not strictly required but recommended, especially if you want to produce portable code. These are covered in the section »Making Best Use of STRICT Type Checking«.

General Requirements

The principal requirement is that you must declare correct handle types and function pointers instead of relying on more general types such as unsigned int and FARPROC. You cannot use one handle type where another is expected. This requirement also means that you may have to change function declarations and use more type casts.

For best results, the generic HANDLE type should not be used except where necessary. Consult the section »New Types and Macros« for a list of new specific handle types.

Using Function Pointers

Always declare function pointers with the proper function type (such as DLGPROC or WNDPROC) rather than FARPROC. You'll need to cast function pointers to and from the proper function type when using MakeProcInstance, FreeProcInstance, and other functions that take or return a FARPROC, as shown in the following code:

BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam,
   LPARAM lParam);
DLGPROC lpfnDlg;

lpfnDlg = (DLGPROC)MakeProcInstance((FARPROC)DlgProc, hinst);
...
FreeProcInstance((FARPROC)lpfnDlg);

Declaring Functions Within Your Application

Make sure all application functions are declared. Placement of all function declarations in an include file is highly recommended because you can more easily scan through your function declarations and look for parameter and return types that should be changed.

If you use the /Zg compiler option to create header files for your functions, remember that you'll get different results depending on whether or not you have enabled STRICT type checking. With STRICT disabled, all handle types generate the same base type  (unsigned short in Windows 3.x). With STRICT enabled, they generate base types such as HWND __near * or HDC __near *. To avoid conflict, you need to either recreate the header file each time you disable or enable STRICT, or else edit the header file to use the types HWND, HDC, HANDLE, and so on, instead of the base types.

If you've copied any API function declarations from WINDOWS.H into your source code, they may have changed, and your local declaration may be out of date. Remove your local declaration.

Functions That Require Casts

Some API functions have generic return types or parameters. For example, a function like SendMessage returns data that may be any number of types, depending on the context. When you see any of these functions in your source code, make sure that you use the correct type cast and that it is as specific as possible.

The following table summarizes these functions.

API Function	Comment
LocalLock	Cast result to the proper kind of data pointer.
GlobalLock	Cast result to the proper kind of data pointer.
GetWindowWord	Cast result to appropriate data type.
GetWindowLong	Cast result to appropriate data type
SetWindowWord	Cast argument as it is passed to function.
SetWindowLong	Cast argument as it is passed to function.
SendMessage	Cast result to appropriate data type; cast to UINT before casting to a handle type.
DefWindowProc	See comment for SendMessage.
SendDlgItemMsg	See comment for SendMessage.
When you call SendMessage, DefWindowProc, or SendDlgItemMessage, you should first cast the result to type UINT. You need to take similar steps for any API function that returns LRESULT or LONG, where the result contains a handle. This is necessary for writing portable code because the size of a handle is either 16 bits or 32 bits depending on the version of Windows. The (UINT) cast ensures proper conversion. The following code shows an example in which SendMessage returns a handle to a brush:

HBRUSH hbr;

hbr = (HBRUSH)(UINT)SendMessage(hwnd, WM_CTLCOLOR, ..., ...);

The CreateWindow Function

The CreateWindow and CreateWindowEx hmenu parameter is sometimes used to pass an integer control ID. In this case, you must cast this to an HMENU type:

HWND hwnd;
int id;

hwnd = CreateWindow("Button", "Ok", BS_PUSHBUTTON,
        x, y, cx, cy, hwndParent,
        (HMENU)id,      // Cast required here
        hinst,
        NULL);


  Making Best Use of STRICT Type Checking

To get the most benefit from STRICT type checking, there are other guidelines you should follow in addition to those in the previous section. Your code will be more portable in future versions of Windows if you make the following changes:

Change	To
HANDLE	A specific handle such as HINSTANCE, HMODULE, HGLOBAL, HLOCAL, and so on
WORD	UINT, except where you want a 16-bit value even when the platform is 32 bits
WORD	WPARAM, where wParam is declared
LONG	LPARAM or LRESULT as appropriate
Anytime you need an integer data type, you should declare it as UINT except where a 16-bit value is specifically required (as in a structure or parameter). Even if a variable never exceeds the range of a 16-bit integer, it can be more efficiently handled by the processor if it is 32 bits.

The types WPARAM, LPARAM, LRESULT, and void * are "polymorphic data types." They hold different kinds of data at different times, even when STRICT type checking is enabled. To get the benefit of type checking, you should cast values of these types as soon as possible. Note that message crackers (as well as the Microsoft Foundation Classes) automatically recast wParam and lParam for you in a portable way.

Take special care to distinguish HMODULE and HINSTANCE types. Even with STRICT enabled, they are defined as the same base type. Most kernel module management functions use HINSTANCE types, but there are a few API functions that return or accept only HMODULE types.


  Accessing the New COMSTAT Structure

The Windows 3.0 declaration of the COMSTAT structure is not compatible with ANSI standards. WINDOWS.H now defines the COMSTAT structure to be compatible with ANSI compilers and so that the /W4 option does not issue warnings.

To support backward compatibility of source code, WINDOWS.H does not use the new structure definition unless the version of Windows (as indicated by WINVER) is greater than 3.0 or if STRICT is defined. When you enable STRICT, the presumption is that you are trying to write portable code. Therefore, WINDOWS.H uses the new COMSTAT structure for all versions of Windows if STRICT is enabled.

The new structure definition replaces the bit fields by flags accessing bits in a single field, named status, as shown in the following table. Each flag turns on a different bit.

Windows 3.0 field name	Flag accessing the status field
fCtsHold	CSTF_CTSHOLD
fDsrHold	CSTF_DSRHOLD
fEof	CSTF_EOF
fRlsdHold	CSTF_RLSDHOLD
fTxim	CSTF_TXIM
fXoffHold	CSTF_XOFFHOLD
fXoffSent	CSTF_XOFFSENT
If you have code that accesses any of these status fields, you need to change your code as appropriate. For example, suppose you have the following code written for Windows 3.0:

if (comstat.fEof || fCondition)
comstat.fCtsHold = TRUE;
comstat.fTxim = FALSE;

This code should be replaced by code that accesses individual bits of the status field by using flags. Note the use of bitwise operators:

if ((comstat.status & CSTF_EOF) || fCondition)
comstat.status |= CSTF_CTSHOLD;
comstat.status &= ~CSTF_TXIM;


  Interpreting Error Messages Affected by STRICT

Enabling STRICT type checking may affect the kind of error messages you receive. With STRICT enabled, all handle types are defined as pointer types. When you incorrectly use these types (for example, passing an int where an HDC is expected), you will get warning messages referring to errors in pointer indirection.

Another effect of STRICT is to require that FARPROC function pointers be recast as more specific function pointer types such as DLGPROC. However, MakeProcInstance and FreeProcInstance still work with the FARPROC type. If you fail to cast between FARPROC and the appropriate function pointer type, the compiler will warn about an error in function parameter lists.

Note that using MakeProcInstance is useful for the sake of portability, if you want to use the same source to compile for Windows 3.x. Under Win32, however, MakeProcInstance performs no operation, but just returns the function name.


Chapter 4: Creating DLLs for Windows NT
  Chapter 4  Creating DLLs for Windows NT

Microsoft Visual C++ for Windows NT offers full support for creating dynamic-link libraries (DLLs) as well as applications. Technically, a DLL is an executable file, but it usually functions as a library for applications. Multiple applications can access a DLL's contents even though only one copy of it is in memory.

The compiler supports placement of data symbols and C++ objects in DLLs, as well as functions. The compiler's run-time library initializes global C++ objects for you as needed.

The compiler and the run-time library support DLL creation in other important ways as well. If you are porting DLL source code written for Windows 3.x, you may need to revise it as described in this chapter.

This chapter discusses the following topics:

•	Overview of differences

•	Run-time library behavior

•	The DllMain function

•	The dllexport and dllimport attributes

•	Building the DLL

•	Special issues with DLLs


Overview of Differences: Creating DLLs
  Overview of Differences

If you have built DLLs for Windows 3.x, you should find that building DLLs for Windows NT is more convenient. The compiler offers more direct support, which potentially saves you several steps in DLL creation. The specific differences are:

•	There is no separate startup module. The DLL startup sequence is handled directly by C/C++ run-time library code linked into your DLL.

•	The run-time library code initializes any static non-local C++ objects you may have by calling the appropriate constructors. (Each process gets its own copy of all the DLL's static data, including objects.)

•	Other initialization and termination are handled through a single user-defined function named DllMain. You can write this function or choose not to include it.

•	You import and export symbols directly in your source code. Using the dllexport attribute (similar to __export in Windows 3.x) saves you from having to use a separate module-definition file. Using dllimport improves efficiency and enables you to import data and objects as well as code.

•	The timing of calls to routines registered with atexit can differ.

Probably the most fundamental difference is that code from the C/C++ run-time library is linked into your DLL (or linked at run time if you are using the DLL version of the run-time library), which simplifies some coding problems. The run-time library code calls the constructors and destructors as appropriate for static, non-local C++ objects in the DLL.

The run-time code also calls the user-defined DllMain function for both initialization and termination, so that you have an opportunity to allocate or release additional resources, as needed. These calls are made in four situations: process attach, process detach, thread attach, and thread detach. If you don't need to do any initialization or termination, you can omit DllMain from source code.

The rest of this chapter describes how to build a DLL, as well as how to write a DllMain function and use the dllexport and dllimport attributes.


  Run-time Library Behavior

As explained in the previous section, the C/C++ run-time library code performs the DLL startup sequence, eliminating the need for a separate module; it also calls constructors and destructors as appropriate for global C++ objects.

For example, in the following DLL source code, Equus and Sugar are two static, non-local objects of class CHorse, defined in HORSES.H. There is no function in source code that contains calls to a constructor function for CHorse or to the destructor function, because these objects are defined outside of any function. Therefore, calls to these constructors and destructors must be performed by the run-time code. (The run-time library code for applications performs this function as well.)

#include "horses.h"

CHorse	Equus( ARABIAN, MALE );
CHorse	Sugar( THOROUGHBRED, FEMALE );

BOOL	WINAPI	 DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)
...

Each time a new process attempts to use the DLL, the operating system creates a separate copy of the DLL's data: this is called process attach. The run-time library code for the DLL calls the constructors for all the global objects, if any, and then it calls your DllMain function with process attach selected. The opposite situation is process detach: the run-time library code calls DllMain with process detach selected and then calls a list of termination functions including atexit functions, destructors for the global objects, and destructors for the static objects. Note that the order of events in process attach is the reverse of that in process detach.

The run-time library code is also called during thread attach and thread detach (explained later in this chapter), but the run-time code does no initialization or termination on its own.


  The DllMain Function

Unlike Windows 3.x DLLs, which have both an initialization and a termination function, Windows NT calls one function, DllMain, for both purposes. It also makes calls on both a per-process and per-thread basis, so several initialization calls can be made if a process is multithreaded. The function is optional; if you don't provide it in source code, the compiler links in its own version, which does nothing but return TRUE.

DllMain uses the WINAPI convention and three parameters. The following code shows the first line in a DllMain definition:

BOOL	WINAPI	DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)

The function returns TRUE (1) to indicate success. If, during per-process initialization, the function returns zero, the system cancels the process.

The ul_reason_for_call parameter indicates the reason DllMain was called: initialization or termination, for a process or a thread. The following table describes the meaning of the four possible values.

Value of ul_reason_for_call	Description
DLL_PROCESS_ATTACH	A new process is attempting to access the DLL; one thread is assumed.
DLL_THREAD_ATTACH	A new thread of an existing process is attempting to access the DLL; this call is made beginning with the second thread of a process attaching to the DLL.
DLL_PROCESS_DETACH	A process is detaching from the DLL.
DLL_THREAD_DETACH	One of the additional threads (not the first thread) of a process is detaching from the DLL.
The lpReserved parameter is reserved for the system's own use and should not be manipulated by your source code.

Windows 3.x DLL initialization functions are passed the following information:

•	The DLL's instance handle

•	The DLL's data segment (DS)

•	The heap size specified in the DLL's .DEF file

•	The command line

Win32 DLL initialization functions are passed the following information:

•	The hModule parameter, a module handle.

•	The ul_reason_for_call parameter, an enumerated type that indicates which of four reasons the LibMain procedure is being called: process attach, thread attach, thread detach, or process detach.

•	The lpReserved parameter, which is unused.

The following code presents a basic skeleton showing what the definition of DllMain might look like:

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for call,
LPVOID lpReserved )
{
switch( dwReason) {
case DLL_PROCESS_ATTACH:
...
case DLL_THREAD_ATTACH:
...
case DLL_THREAD_DETACH:
...
case DLL_PROCESS_DETACH:
...
}
return TRUE;
}

The Win32 module handle has the same purpose as the Windows 3.x instance handle. Otherwise, Win32 DLL initialization functions do not include the parameters for Windows 3.x initialization, as described in the following table.

Parameter	Comment
DLL data segment	Not needed in Win32; memory model is flat, not segmented.
Size of DLL's local heap	All calls to local memory management functions operate on the default heap.
Pointer to command line	The command line can be obtained through a call to the GetCommandLine API function.


  The dllexport and dllimport Attributes

The DLL model for Windows NT is different from that for Windows 3.x. To write the most efficient DLL code and to make the transition as smooth as possible, you should use the dllexport and dllimport import attributes everywhere appropriate.

As you write a DLL, you can use dllexport to declare that a symbol (function, data, or object) is being exported to applications and other DLLs. The compiler produces the most efficient code as a result, and you no longer need a module-definition (.DEF) file to export your symbols.

When you create header files for use with your DLLs, you should include dllimport declarations for each symbol, so applications properly declare each DLL symbol to be used. The DLL users still need to be provided with an import library, but use of dllimport produces more efficient code. Also, data items and objects require use of dllimport to be imported at all.

Because they are attributes and not keywords, dllexport and dllimport must be used in conjunction with the __declspec keyword. The following procedure is recommended:

1.	Use the __declspec keyword, along with dllexport and dllimport, to define import and export macros for your source code.

2.	Use these macros you've defined to declare symbols as export or import.


  The __declspec Keyword

The Visual C++ language (including C source modules) uses the __declspec keyword to extend storage class attributes. Storage class determines how a given symbol is accessed by the compiler. For example, static is a storage class attribute in standard C/C++ specifying that a variable is not stored on the stack.

This version of Visual C++ defines four extended storage class attributes: dllexport, dllimport, thread, and naked. These are all used with __declspec rather than supported directly as keywords, to keep down the number of reserved words and because they are Microsoft-specific. This chapter introduces the dllexport and dllimport attributes. Chapter 5, »Creating Multithread Applications«, discusses the thread attribute and Chapter 8, »Using Windows NT Calling Conventions«, discusses the naked attribute.

The syntax for using __declspec is:

__declspec( attribute ) variable-declaration

For example, the following definition exports an integer, using dllexport as the attribute:

__declspec( dllexport ) int SumInterest = 0;


  Exporting Symbols

The use of dllexport (when used with __declspec as explained in the previous section) replaces the __export keyword supported in Windows 3.x. To port DLL source code, you should replace each instance of __export. The dllexport attribute eliminates the need for a .DEF file.

To export symbols, the recommended approach is to define a macro for __declspec( dllexport ) and then use the macro with each symbol:

#define	DllExport	__declspec( dllexport )

DllExport	int i = 10;	// Definition, because initialized
DllExport	int j;	// Definition, because of DllExport
DllExport	void func();	// Declaration

With uninitialized data, dllexport causes the statement to be a definition unless it is combined with extern, in which case it is a declaration. The difference is important: a definition tells the compiler to create a symbol; a declaration informs the compiler that the symbol is created somewhere else. Thus, in the previous example, j is defined rather than declared, because of DllExport. The nature of the other two statements is already clear from syntax.

You can combine the extern keyword with dllexport. This tells the compiler that the symbol is defined and exported by the DLL, but not necessarily in this source-code module. For example, the following is a data declaration, not definition:

extern	DllExport	j;	// Symbol j is declared

It should be clear that exporting a symbol is inconsistent with automatic ("stack" or "local") storage class. Therefore, the following code produces an error, because it attempts to export a symbol Sum defined on the stack:

void func()
{
DllExport	int	Sum;	// Error: cannot export local variable

However, the following code compiles correctly because Sum is only declared, not defined, within the function. This code enables Sum to be used within the scope of func, but the code does not create it:

void func()
{
extern	DllExport	int	Sum;	// Ok, because extern means Sum
//  is defined in another
//  module of this DLL.


  Importing Symbols

A program that uses public symbols defined by a DLL is said to import them. Windows 3.x required only the use of an import library, normally supplied by the DLL author, to handle the mechanics of importing. In Windows NT, the DLL user must still link with the import library, but needs to use dllimport as well.

As a DLL author, you should accommodate this requirement by using dllimport in the header files you supply. If you don't, DLL users can still access DLL functions, but their code will be less efficient. And they will not have access to DLL public data symbols and objects.

To import symbols, the recommended approach is to define a macro for __declspec( import ) and then use the macro to declare each imported symbol:

#define	DllImport	__declspec( dllimport )

DllImport	int	j;
DllImport	void	func();

The dllimport attribute must be used in a declaration, not a definition, because you obviously cannot define a new symbol and at the same time import it from another program. You also cannot declare an imported symbol as static, which implies that the symbol is defined in the current module.

DllImport	int	j = 2;	// Error: initialization implies definition

void func()
{
static DllImport	int	i;	// Error: static

It is valid to give the same symbol both the dllexport and dllimport attributes. This could happen if you are sharing header files between different programs. Otherwise, it should not happen. When both attributes are used, the dllexport attribute takes precedence:

DllImport	int	i;
DllExport	int	i;	// Warning issued, but dllexport takes
//  precedence

If you are compiling your program as a C language module, you cannot use the address of an imported symbol to initialize a global or static variable. However, in C++, you can use the address of an imported symbol to initialize any variable or object.


  Importing and Exporting Inline Functions

Imported functions can be defined as inline. The effect is roughly the same as defining a standard function inline; calls to the function are expanded into inline code, much like a macro. This is principally useful as a way of supporting C++ classes in a DLL that may inline some of their member functions for efficiency.

One of the distinctive features of an imported inline function is that in C++, you can take its address. The compiler returns the address of the copy of the inline function residing in the DLL. Another feature of imported inline functions is that unlike global imported data, you can initialize static local data of the imported function.

You should exercise care when providing imported inline functions, as they create the possibility of version conflicts. An inline function gets expanded into the application code; therefore, if you later rewrite the function, it does not get updated unless the application itself is recompiled. (Normally, DLL functions can be updated without rebuilding the applications that use them.)


  Building the DLL

There are two categories of compiler options you should know about when you build a DLL. The /LD option causes the compiler to build a DLL instead of an application. You can select it automatically by using Visual Workbench to build a DLL, or by specifying /LD on the command line. The other options that can affect building of a DLL are /MD, /MT, and /ML, which select run-time library type.


  Using Visual Workbench to Build DLLs

To build a DLL from within Visual Workbench, make sure that you select "Windows dynamic-link library" as the program type when you create a new project. Visual Workbench uses a dialog box to offer a choice of program types when you choose New from the Project menu. If you have already created the project and it does not have DLL program type, you can change the program type by choosing Project from the Options menu.

To debug a DLL, you must run an application that calls your DLL. Choose the Debug menu command from the Options menu. A dialog box appears for you to specify which application to run while debugging.


  The /LD Option

Visual Workbench automatically sets the /LD option when you choose "Windows dynamic-link library" as the program type. You can also specify /LD directly when using the command line to invoke the compiler.

When the /LD option is specified, the compiler passes the  − DLL option to the linker, causing a DLL to be built. The compiler also does the following:

•	Looks for the DllMain function in the source code.

•	Links with DLL start-up code that performs some initialization for you.

•	Produces an import library to be linked to applications that call your DLL.

•	Interprets /Fe as naming a DLL rather than an EXE file; the default program name becomes basename.DLL instead of basename.EXE.

•	Changes default for C run-time library support, as explained in the next section.


  Multithread Support and /M Options

The /MD, /ML, and /MT options determine whether the program being built has single-thread support, multithread support, or uses a dynamic-link version of the run-time library (MSVCRT10.DLL). The following table shows the purpose of each option.

Option	Links to
/MD	MSVCRT10.DLL, a dynamic-link library that is multithread aware
/ML	Single-thread-aware library (default for applications)
/MT	Multithread-aware library (default for DLLs)
Use of the /MD or /MT option is most often a good idea when building a DLL. Both of these options offer support for multithread applications. When you specify /ML, your DLL will work reliably only when called by single-thread applications. A multithread application that calls a DLL without multithread awareness is likely to fail. Therefore, don't specify /ML unless you know that it will be used only by single-thread applications.

The compiler chooses /MT by default when you build a DLL.

Note that the decision whether or not to use MSVCRT10.DLL and the decision whether to build an application or DLL are largely independent choices. You could, for example, choose to build an application that uses the DLL version of the run-time library (/MD); conversely, you could build a DLL that is statically linked to the C run-time library (/MT or /ML).


  Special Issues with DLLs

The following sections discuss issues that occur occasionally in special situations: mutual DLL imports and the effect of dynamic loading on thread-local storage. You can write a simple DLL without worrying about any of these issues, but if you make use of any of these features, it is helpful to be aware of the issues that can arise.


  Mutual Imports

Exporting or importing to another executable file presents complications when the imports are mutual (or "circular"). For example, two DLLs import symbols from each other, similar to mutually-recursive functions.

The problem with mutually-importing executable files (usually DLLs) is that neither can be built without building the other first. Each build process requires, as input, an import library produced by the other build process.

The solution is to use the LIB utility with the /DEF option, which produces an import library without building the executable file. Using this utility, you can build all the import libraries you need, no matter how many DLLs are involved or how complicated the dependencies are.

The general solution is:

1.	Take each DLL in turn. (Any order is feasible, although some orders are more optimal.) If all the needed import libraries exist and are current, run LINK to build the executable file (DLL). This produces an import library. Otherwise, run LIB to produce an import library.

Running LIB with the /DEF option produces an additional file with an .EXP extension. The .EXP file must be used later to build the executable file.

2.	After using either LINK or LIB to build all the import libraries, go back and run LINK to build any executable files that were not built in the previous step. Note that the corresponding .EXP file must be specified on the LINK line.

If you had run the LIB utility earlier to produce an import library for DLL1, LIB produced the file DLL1.EXP as well. You must use DLL1.EXP as input to LINK when building DLL1.DLL.

»Figure 4.1« illustrates a solution for two mutually-importing DLLs, DLL1 and DLL2. The first step is to run LIB, with the /DEF option set, on DLL1. This step produces DLL1.LIB, an import library, and DLL1.EXP. The import library is used to build DLL2, which in turn produces an import library for DLL2's symbols. The final step builds DLL1, by using DLL1.EXP and DLL2.LIB as input. Note that an .EXP file for DLL2 is not necessary, because LIB was not used to build DLL2's import library.

For more information on the LIB utility and the /DEF option, see Chapter 3 of the Build Tools User's Guide.


  DLL Loading and Thread-Local Storage

An executable file loads a DLL in one of two ways: statically or dynamically. The exported contents of a DLL are always dynamically bound, regardless of how it is loaded. Furthermore, these mechanisms are not mutually exclusive, as one application can statically load a DLL and another can attach to it dynamically. A statically-loaded DLL is "static" only in the sense that an application sets up imports to it at build time.

•	Static loading is the standard mechanism, invoked when a program is built with import libraries referring to the DLL. When the application builder is relatively sure that a particular DLL will be used, this method is most efficient because symbols can be accessed with the dllimport attribute.

•	Dynamic loading attaches to a DLL specified at run time. This mechanism uses LoadLibrary and other API functions such as GetProcAddress, bypassing use of imports. This technique is more efficient if it is not known at build time whether the DLL will be used, because it avoids initialization of the DLL until it is accessed.

If a DLL declares static-extent data as __declspec( thread ), it can cause a protection fault if dynamically loaded. After the DLL is loaded with LoadLibrary, it causes system failure whenever the code references this data. (Static-extent data includes both global and local static items.)

Therefore, when you create a DLL, you should either avoid this use of thread-local storage, or else advise users of the DLL as to use of this storage, in case they attempt dynamic loading.


Chapter 5: Creating Multithread Windows NT Applications
  Chapter 5  Creating Multithread Applications for Windows NT

Microsoft Visual C++ for Microsoft Windows NT provides support for creating multithread applications under Windows NT. You should consider using more than one thread if your application needs to manage multiple activities, such as simultaneous keyboard and mouse input. One thread can process keyboard input while a second thread filters mouse activities. A third thread can update the display screen based on data from the mouse and keyboard threads. At the same time, other threads can access disk files or get data from a communications port.

This chapter explains the features in Visual C++ that support the creation of multithread programs.

Note  Win32s does not support multithreading. Calls to the Win32 APIs and C run-time library functions mentioned in this chapter will return an error.


  Multithread Programs

A thread is basically a path of execution through a program. It is also the smallest unit of execution that Windows NT schedules. A thread consists of a stack, the state of the CPU registers, and an entry in the execution list of the system scheduler. Each thread shares all of the process's resources.

A process consists of one or more threads and the code, data, and other resources of a program in memory. Typical program resources are open files, semaphores, and dynamically allocated memory. A program executes when the system scheduler gives one of its threads execution control. The scheduler determines which threads should run and when they should run. Threads of lower priority may have to wait while higher priority threads complete their tasks. On multiprocessor machines, the scheduler can move individual threads to different processors to "balance" the CPU load.

All threads in a process operate independently of one another. Unless you take special steps to make them visible to each other, each thread executes while completely unaware of the existence of other threads in a process. Threads sharing common resources, however, must coordinate their work by using semaphores or another method of interprocess communication. See »Writing a Multithread Program« for more information about synchronizing threads.


Library Support: Creating Multithread Applications
  Library Support

If one thread is suspended by the Windows NT scheduler while executing the printf function, one of the program's other threads might start executing. If the second thread also calls printf, data might be corrupted. To avoid this, access to static data used by the function must be restricted to one thread at a time.

You do not need to serialize access to stack-based (automatic) variables because each thread has a different stack. Therefore, a function that uses only automatic (stack) variables is re-entrant. The standard C run-time libraries, such as LIBCE, have a limited number of re-entrant functions. A multithread program needing to use C run-time library functions that are normally not re-entrant should be built with the multithread library LIBCMT.LIB.

The Multithread C Libraries: LIBCMT.LIB and MSVCRT.LIB

The support library LIBCMT.LIB is a re-entrant library for creating multithread programs. The MSVCRT.LIB library, which calls code in the shared MSVCRT10.DLL, is also re-entrant. When your application calls functions in these libraries, the following rules may apply:

•	All library calls must use the C (__cdecl) calling convention; programs compiled using other calling conventions (such as __fastcall or __stdcall) must use the standard include files for the run-time library functions they call.

•	Variables passed to library functions must either be passed by value or cast to a pointer.

Programs built with LIBCMT.LIB do not share C run-time library code or data with any dynamic-link libraries they call.

Alternatives to LIBCMT.LIB and MSVCRT.LIB

If you choose to build a multithread program without using LIBCMT.LIB, you must do the following:

•	Use the standard C libraries and limit library calls to the set of re-entrant functions.

•	Use the Windows NT API thread management functions, such as CreateThread.

•	Provide your own synchronization for functions that are not re-entrant by using Windows NT services such as semaphores and the EnterCriticalSection and LeaveCriticalSection functions.

The C run-time library functions listed below are re-entrant and can be used in multithread programs linked with the standard libraries.

Warning  The multithread library LIBCMT.LIB includes the _beginthread and _endthread functions. The _beginthread function performs initialization without which many C run-time functions will fail. You must use _beginthread instead of CreateThread in C programs built with LIBCMT.LIB if you intend to call C run-time functions.

The Multithread Libraries Compile Option

To build a multithread application that uses the C run-time libraries, you must tell the compiler to use a special version of the libraries. To select these libraries, first choose Project from the Options menu, and then click on the Compiler button. From the compiler options dialog box, choose Runtime Libraries and then select Multithread Libraries (LIBCMT.LIB). Click OK to return to editing.

From the command line, the Multithread Library compiler option (/MT) is the best way to build a multithread program with LIBCMT.LIB. This option, automatically set when you specify a multithreaded application when creating a new project, embeds the LIBCMT library name in the object file.


  Include Files

The Microsoft Visual C++ for Windows NT include files contain conditional sections for multithread applications using LIBCMT.LIB. To compile your application with the appropriate definitions, you can:

•	Compile with the Multithread Library compiler option described in the previous section.

•	Define the symbolic constant _MT in your source file or on the command line with the /D option.

Standard include files declare C run-time library functions as they are implemented in the libraries. If you used the Maximum Optimization (/Ox) or Register Calling Convention (/Gr) option, the compiler assumes that all functions should be called using the register calling convention. The run-time library functions were compiled using the C calling convention, and the declarations in the standard include files tell the compiler to generate correct external references to these functions.

See »Compiling and Linking« for examples of how to use the _MT constant.


  C Run-Time Library Functions for Thread Control

All Windows NT programs have at least one thread. Any thread can create additional threads. A thread can complete its work very quickly and then terminate, or it can stay active for the life of the program.

The LIBCMT and MSVCRT C run-time libraries provide two functions for thread creation and termination: the _beginthread and _endthread functions.

The _beginthread function creates a new thread and returns a thread identifier if the operation is successful. The thread terminates automatically if it completes execution, or it can terminate itself with a call to _endthread.

Warning  If you are going to call C run-time routines from a program built with LIBCMT.LIB, you must start your threads with the _beginthread function. Do not use the Windows NT functions ExitThread and CreateThread. Using SuspendThread can lead to a deadlock condition when more than one thread is blocked waiting for the suspended thread to complete its access to a C run-time data structure.

The _beginthread Function

The _beginthread function creates a new thread. A thread shares the code and data segments of a process with other threads in the process but has its own unique register values, stack space, and current instruction address. The system gives CPU time to each thread, so that all threads in a process can execute concurrently. You can find a complete description of _beginthread and its arguments in Help.

The _beginthread function is similar to the CreateThread function in the Windows NT API with these differences:

•	The _beginthread function lets you easily pass multiple arguments to the thread.

•	The _beginthread function properly initializes certain C run-time library variables. This is important only if you use the C run-time library in your threads.

•	CreateThread provides control over security attributes. You can use this function to start a thread in a suspended state.

The _beginthread function returns a handle to the new thread if successful or −1 if there was an error.

The _endthread Function

The _endthread function terminates a thread created by _beginthread. Threads terminate automatically when they complete. The _endthread function is useful for conditional termination from within a thread. A thread dedicated to communications processing, for example, can quit if it is unable to get control of the communications port. You can find a complete description of _endthread in Help.


  Sample Multithread C Program

BOUNCE.C is a sample multithread program that creates a new thread each time the letter 'a' or 'A' is entered at the keyboard. Each thread bounces a "happy face" of a different color around the screen. Up to 32 threads can be created. The program's normal termination occurs when 'q' or 'Q' is entered. See »Compiling and Linking« for details on compiling and linking BOUNCE.C.

/*  Bounce - Creates a new thread each time the letter 'a' is typed.
 *  Each thread bounces a happy face of a different color around the screen.
 *  All threads are terminated when the letter 'Q' is entered.
 *
 *  This program requires the multithread library. For example, compile
 *  with the following command line:
 *      CL /MT BOUNCE.C
 */

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>

#define MAX_THREADS  32

/* getrandom returns a random number between min and max, which must be in
 * integer range.
 */
#define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

void main( void );                     /* Thread 1: main */
void KbdFunc( void  );                 /* Keyboard input, thread dispatch */
void BounceProc( char * MyID );        /* Threads 2 to n: display */
void ClearScreen( void );              /* Screen clear */
void ShutDown( void );                 /* Program shutdown */
void WriteTitle( int ThreadNum );	   /* Display title bar information */

HANDLE  hConsoleOut;	   /* Handle to the console */
HANDLE  hRunMutex;                     /* "Keep Running" mutex */
HANDLE  hScreenMutex;                  /* "Screen update" mutex  */
int	ThreadNr;	       /* Number of threads started */
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;   /* Console information */

void main()                            /* Thread One */
{
    /* Get display screen information & clear the screen.*/
    hConsoleOut = GetStdHandle( STD_OUTPUT_HANDLE );
    GetConsoleScreenBufferInfo( hConsoleOut, &csbiInfo );
    ClearScreen();
    WriteTitle( 0 );
    /* Create the mutexes and reset thread count. */
    hScreenMutex = CreateMutex( NULL, FALSE, NULL );   /* Cleared */
    hRunMutex = CreateMutex( NULL, TRUE, NULL );       /* Set */
    ThreadNr = 0;

    /* Start waiting for keyboard input to dispatch threads or exit. */
    KbdFunc();

    /* All threads done. Clean up handles. */
    CloseHandle( hScreenMutex );
    CloseHandle( hRunMutex );
    CloseHandle( hConsoleOut );
}

void ShutDown( void )                  /* Shut down threads */
{
while ( ThreadNr > 0 )
{
/* Tell thread to die and record its death. */
    ReleaseMutex( hRunMutex );
ThreadNr--;
}
    /* Clean up display when done */
    WaitForSingleObject( hScreenMutex, INFINITE );
    ClearScreen();
}

void KbdFunc( void )                   /* Dispatch and count threads. */
{
    int         KeyInfo;

    do
    {
        KeyInfo = _getch();
        if( tolower( KeyInfo ) == 'a' && ThreadNr < MAX_THREADS )
        {
            ThreadNr++;
            _beginthread( BounceProc, 0, &ThreadNr );
            WriteTitle( ThreadNr );
        }
    } while( tolower( KeyInfo ) != 'q' );

    ShutDown();
}

void BounceProc( char *MyID )
{
    char      MyCell, OldCell;
WORD	  MyAttrib, OldAttrib;
char	  BlankCell = 0x20;
    COORD     Coords, Delta;
    COORD     Old = {0,0};
DWORD	  Dummy;

/* Generate update increments and initial display coordinates. */
    srand( (unsigned) *MyID * 3 );
    Coords.X = getrandom( 0, csbiInfo.dwSize.X - 1 );
    Coords.Y = getrandom( 0, csbiInfo.dwSize.Y - 1 );
    Delta.X = getrandom( -3, 3 );
    Delta.Y = getrandom( -3, 3 );

    /* Set up "happy face" & generate color attribute from thread number.*/
    if( *MyID > 16)
        MyCell = 0x01;                 /* outline face */
    else
        MyCell = 0x02;                 /* solid face */
    MyAttrib =  *MyID & 0x0F;          /* force black background */

    do
    {
        /* Wait for display to be available, then lock it. */
        WaitForSingleObject( hScreenMutex, INFINITE );

        /* If we still occupy the old screen position, blank it out. */
        ReadConsoleOutputCharacter( hConsoleOut, &OldCell, 1, Old, &Dummy );
        ReadConsoleOutputAttribute( hConsoleOut, &OldAttrib, 1, Old, &Dummy );
        if (( OldCell == MyCell ) && (OldAttrib == MyAttrib))
            WriteConsoleOutputCharacter( hConsoleOut, &BlankCell, 1, Old, &Dummy );

        /* Draw new face, then clear screen lock */
WriteConsoleOutputCharacter( hConsoleOut, &MyCell, 1, Coords, &Dummy );
WriteConsoleOutputAttribute( hConsoleOut, &MyAttrib, 1, Coords, &Dummy );
        ReleaseMutex( hScreenMutex );

        /* Increment the coordinates for next placement of the block. */
        Old.X = Coords.X;
        Old.Y = Coords.Y;
        Coords.X += Delta.X;
        Coords.Y += Delta.Y;

/* If we are about to go off the screen, reverse direction */
        if( Coords.X < 0 || Coords.X >= csbiInfo.dwSize.X )
        {
            Delta.X = -Delta.X;
            Beep( 400, 50 );
        }
        if( Coords.Y < 0 || Coords.Y > csbiInfo.dwSize.Y )
        {
            Delta.Y = -Delta.Y;
            Beep( 600, 50 );
        }
}
    /* Repeat while RunMutex is still taken. */
while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT );

}

void WriteTitle( int ThreadNum )
{
char	NThreadMsg[80];

    sprintf( NThreadMsg, "Threads running: %02d.  Press 'A' to start a thread,'Q' to quit.", ThreadNum );
    SetConsoleTitle( NThreadMsg );
}

void ClearScreen( void )
{
DWORD	dummy;
COORD	Home = { 0, 0 };
FillConsoleOutputCharacter( hConsoleOut, ' ', csbiInfo.dwSize.X * csbiInfo.dwSize.Y, Home, &dummy );

}


  Writing a Multithread Program

When you write a program with multiple threads, you must coordinate their behavior and use of the program's resources. You must also make sure that each thread receives its own stack.

Sharing Common Resources

Each thread has its own stack and its own copy of the CPU registers. Other resources, such as files, static data, and heap memory, are shared by all threads in the process. Threads using these common resources must coordinate their work. Windows NT provides several ways to synchronize resources, including semaphores, critical sections, events, and mutexes.

When multiple threads are accessing static data, your program must provide for possible resource conflicts. Consider a program where one thread updates a static data structure containing x,y coordinates for items to be displayed by another thread. If the update thread alters the x coordinate and is preempted before it can change the y coordinate, the display thread may be scheduled before the y coordinate is updated. The item would be displayed at the wrong location. You can avoid this type of problem by using semaphores to control access to the structure.

A mutex (short for mutual exclusion) is a way of communicating among threads or processes that are executing asynchronously of one another. This communication is usually used to coordinate the activities of multiple threads or processes, typically by controlling access to a shared resource by "locking" and "unlocking" the resource. To solve the x,y coordinate update problem described previously, the update thread would set a mutex indicating that the data structure is in use before performing the update. It would then clear the mutex when both coordinates had been processed. The display thread must wait for the mutex to be clear before updating the display. This process of waiting for a mutex is often called "blocking" on a mutex because the process is blocked and cannot continue until the mutex clears.

The BOUNCE.C program shown in the previous section uses a mutex named ScreenMutex to coordinate screen updates. Each time one of the display threads is ready to write to the screen, it calls WaitForSingleObject with the handle to ScreenMutex and constant INFINITE to indicate that the WaitForSingleObject call should block on the mutex and not time out. If ScreenMutex is clear, the wait function sets the mutex so other threads cannot interfere with the display and continues executing the thread. Otherwise, the thread blocks until the mutex clears. When the thread completes the display update, it releases the mutex by calling ReleaseMutex.

Screen displays and static data are only two of the resources requiring careful management. For example, your program may have multiple threads accessing the same file. Because another thread may have moved the file pointer, each thread must reset the file pointer before reading or writing. In addition, each thread must make sure that it is not preempted between the time it positions the pointer and the time it accesses the file. These threads should use a semaphore to coordinate access to the file by bracketing each file access with WaitForSingleObject and ReleaseMutex calls. The following code fragment illustrates this technique:

HANDLE    hIOMutex= CreateMutex (NULL, FALSE, NULL);

WaitForSingleObject( hIOMutex, INFINITE );
fseek( fp, desired_position, 0L );
fwrite( data, sizeof( data ), 1, fp );
ReleaseMutex( hIOMutex);

Thread Stacks

All of an application's default stack space is allocated to the first thread of execution, which is known as thread 1. As a result, you must specify how much memory to allocate for a separate stack for each additional thread your program needs. The operating system will allocate additional stack space for the thread, if necessary, but you must specify a default value.

The first argument in the _beginthread call is a pointer to the BounceProc function, which will execute the threads. The second argument specifies the default stack size for the thread. The last argument is an ID number that is passed to BounceProc. BounceProc uses the ID number to seed the random number generator and to select the thread's color attribute and display character.

Threads that make calls to the C run-time library or to the Windows NT API must allow sufficient stack space for the library and API functions they call. The C printf function requires more than 500 bytes of stack space, and you should have 2K of stack space available when calling Windows NT API routines.

Because each thread has its own stack, you can avoid potential collisions over data items by using as little static data as possible. Design your program to use automatic stack variables for all data that can be private to a thread. The only global variables in the BOUNCE.C program are either mutexes or variables that never change after they are initialized.

Windows NT also provides Thread-Local Storage (TLS) to store per-thread data. See »Thread-Local Storage«.


  Compiling and Linking

The steps for compiling and linking the multithread program BOUNCE.C using the Visual Workbench are given below:

1.	Create a new project. Choose Console Application (.EXE) from the Project Type list, and turn off the Use Microsoft Foundation Classes box.

2.	Add the file containing the C source code to the project.

3.	In the Project Options dialog box, choose Compiler and set the Runtime Libraries to Multithread Libraries (LIBCMT.LIB).

4.	Build the project by choosing Build from the Project menu.

Note  The BOUNCE.C program appears as a sample on the Visual C++ CD-ROM. See the Sample help file for more information.

The steps for compiling and linking the multithread program BOUNCE.C from the command line are given below:

1.	Ensure that the Win32 library files and LIBCMT.LIB are in the directory specified in your LIB environment variable.

2.	Compile and link the program with the CL command-line option /MT:

CL /MT BOUNCE.C

3.	If you choose not to use the /MT option, you must take these steps:

•	Define the _MT symbol before including header files. You can do this by specifying /D _MT on the command line.

•	Specify the multithread library and suppress default library selection.

The multithread include files are used when you define the symbolic constant _MT. You can do this with the CL command line option /D _MT or within the C source file before any include statements, as follows:

#define _MT
#include <stdlib.h>


  Avoiding Problem Areas

There are several problems you might encounter in creating, linking, or executing a multithread C program. Some of the more common ones are described here.

Problem	Probable Cause
You get a message box showing that your program caused a protection violation.	Many Windows NT programming errors cause protection violations. A common cause of protection violations is the indirect assignment of data to null pointers. This results in your program trying to access memory that does not "belong" to it, so a protection violation is issued.  An easy way to detect the cause of a protection violation is to compile your program with debugging information, and then run it through the debugger in Visual Workbench. When the protection fault occurs, Windows NT transfers control to the debugger, and the cursor is positioned on the line that caused the problem.
Your program generates numerous compile and link errors.	If you attempt to compile and link a multithread  program without defining the symbolic constant _MT, many of the definitions required for the multithread library will be missing. If you are using the Visual Workbench, make sure that the C/C++ Compiler Options dialog box specifies multithread libraries. From the command line, define _MT to CL with /MT or /D _MT, or use #define _MT in your program. You can eliminate many potential problems by setting the compiler's warning level to one of its highest values and heeding the warning messages. By using the /W3 or /W4 warning level options, you can detect unintentional data conversions, missing function prototypes, and use of non-ANSI features.


  Thread Local Storage (TLS)

Thread Local Storage (TLS) is the method by which each thread in a given multi-threaded process may allocate locations in which to store thread-specific data. Dynamically bound (run-time) thread-specific data is supported by way of the TLS API (TlsAlloc, TlsGetValue, TlsSetValue, TlsFree). Windows NT and the Visual C++ compiler now support statically bound (load-time) per-thread data in addition to the existing API implementation.


  API Implementation

Thread Local Storage is implemented through the Win32 API layer as well as the compiler. For details, see the Win32 API documentation for TlsAlloc, TlsGetValue, TlsSetValue, and TlsFree.

The Visual C++ compiler includes a keyword to make thread local storage operations more automatic, rather than through the API layer. This syntax is described in the next section.


  Compiler Implementation

To support TLS, a new attribute, thread, has been added to the C and C++ languages and is supported by the Visual C++ compiler. This attibute is an extended storage class modifier, as described in the previous section. Use the __declspec keyword to declare a thread variable. For example, the following code declares an integer thread local variable and initializes it with a value:

__declspec( thread ) int tls_i = 1;


  Rules and Limitations

The following guidelines must be observed when declaring statically-bound thread local objects and variables:

•	The thread attribute can be applied only to data declarations and definitions. It cannot be used on function declarations or definitions. For example, the following code will generate a compiler error:

#define Thread	__declspec( thread )
Thread void func();	// This will generate an error.

•	The thread modifier may be specified only on data items with static extent. This includes global data objects (both static and extern), local static objects, and static data members of C++ classes. Automatic data objects may not be declared with the thread attribute. The following code will generate compiler errors:

#define Thread	__declspec( thread )
void func1()
{
Thread int tls_i;	 // This will generate an error.
}

int func2( Thread int tls_i ) // This will generate an error.
{
return tls_i;
}

•	The declarations and the definition of a thread local object must all specify the thread attribute. For example, the following code will generate an error:

#define Thread	__declspec( thread )
extern int tls_i;	// This will generate an error, since the

int Thread tls_i;	// declaration and definition differ.

•	The thread attribute cannot be used as a type modifier. For example, the following code will generate a compiler error:

char __declspec( thread ) *ch;	// Error

•	C++ classes cannot use the thread attribute. However, C++ class objects may be instantiated with the thread attribute. For example, the following code will generate a compiler error:

#define Thread	__declspec( thread )
class Thread C	// Error: classes cannot be declared Thread.
{
// Code
};

C CObject;

Because the declaration of C++ objects that utilize the thread attribute is permitted, the following two examples are semantically equivalent:

#define Thread	__declspec( thread )
Thread class B
{
// Code
} BObject;	// OK--BObject is declared thread local.

class B
{
// Code
}
Thread B BObject;	// OK--BObject is declared thread local.

•	Because C++ objects with constructors and destructors (as well as any object that utilizes some form of initialization semantics) may be allocated as thread local objects, an associated initialization routine (such as the constructor) is called to initialize that object. For example:

class tlsClass
{
private:
int x;
public:
tlsClass() { x = 1; } ;
~tlsClass();
}

__declspec( thread ) tlsClass tlsObject;
extern int func();
__declspec( thread ) int y = func();

In this case, data or objects initialized by the func routine do not necessarily belong to the same thread into which tlsObject is instantiated.

•	The address of a thread local object is not considered constant, and any expression involving such an address is not considered a constant expression. In standard C, the effect of this is to forbid the use of the address of a thread local variable as an initializer for an object or pointer. For example, the following code will be flagged as an error by the C compiler:

#define Thread	__declspec( thread )
Thread int tls_i;
int *p = &tls_i;	//This will generate an error in C.

This restriction does not apply in C++, however. Because C++ permits dynamic initialization of all objects, you can initialize an object with an expression that uses the address of a thread local variable. This is accomplished in the same way as the construction of thread local objects. For example, the code shown previously will not generate an error when compiled as a C++ source file. Note that the address of a thread local variable is only valid as long as the thread in which the address was taken still exists.

•	Standard C permits the initialization of an object or variable with an expression involving a reference to itself, but only for objects of non-static extent. Although C++ normally does permit such dynamic initialization of objects with an expression involving a reference to itself, this type of initialization is not permitted with thread local objects. For example:

#define Thread	__declspec( thread )
Thread int tls_i = tls_i;	// Error in C and C++
int j = j;	// OK in C++, error in C
Thread int tls_i = sizeof( tls_i )	// Legal in C and C++

Note that a sizeof expression that includes the object being initialized does not constitute a reference to itself, and is legal in both C and C++.

The reason that C++ does not allow such dynamic initialization of thread data is strictly for the purposes of possible future enhancements to the thread local storage facility.

•	If a DLL declares any non-local data or object as __declspec( thread ), it can cause a protection fault if dynamically loaded. After the DLL is loaded with LoadLibrary, it causes system failure whenever the code references the non-local __declspec( thread ) data.


  For More Information

You can find more information on:

•	Debugging multithreaded applications in the Visual Workbench User's Guide.

•	C run-time functions in the C Run-Time Library Reference.

•	Win32 APIs covering threads and synchronization in the Win32 Programmer's Guide.

More information is also available through Help.


Chapter 6: Floating-Point Operations in Windows NT
  Chapter 6  Floating-Point Operations in Windows NT

Windows NT offers a smaller and simpler set of choices than Windows 3.x. The differences between the two operating systems generally present no portability issues, because the same C/C++ source code is supported by both systems. However, you may need to be aware of differences in precision and floating-point options that you can expect in Windows NT.

This chapter covers the following topics:

•	Overview of differences

•	Floating-point types supported

•	Declaring variables as floating-point types

•	Library support


Overview of Differences: Floating Point Operations
  Overview of Differences

There are two important differences in floating-point support between Windows 3.x and Windows NT:

•	Visual C++ for Windows NT supports only the math-coprocessor option, not an emulator or alternate-math package.

•	The 80-bit long double type is not supported.

From the standpoint of an application, every system running Windows NT has coprocessor support.  For those systems that do not have a math coprocessor, the operating system itself has emulator routines that respond to coprocessor instructions. Visual C++ for Windows NT therefore only supports a coprocessor floating-point math package. There is no need for an emulator library, and alternate-math packages are not supported.

The other difference in floating-point support between Windows 3.x and Windows NT is that the 80-bit floating-point format is not supported. (The type long double is permitted by the compiler, but mapped to double.) The reason for this limitation is that Windows NT is designed to run on a variety of hardware configurations, and the 80-bit type is not easily supported on some hardware.


  Floating-Point Types Supported

Visual C++ supports two floating-point types that conform to the Institute of Electrical and Electronics Engineers, Inc. (IEEE) standard 754 format:

•	Type float, a 32-bit floating-point quantity

•	Type double, a 64-bit floating-point quantity

The type long double, which in Windows 3.x is an 80-bit type, is valid; it compiles without causing a syntax error. However, the compiler maps it to the 64-bit type, double. Source code is portable as long as it does not rely on the additional precision and range of the long double type.

You can declare variables as any of these types. You can also declare functions that return any of these types.


  Declaring Variables as Floating-Point Types

You can declare variables as float or double, depending on the needs of your application. The principal differences between the two types are the significance they can represent, the storage they require, and their range. Table 6.1 shows the relationship between significance and storage requirements.

Table 6.1     Floating-Point Types

Type	Significant digits	Number of bytes
float	6  − 7	4
double	15  −  16	8
Floating-point variables are represented by a mantissa, which contains the value
of the number, and an exponent, which contains the order of magnitude of the number.

Table 6.2 shows the number of bits allocated to the mantissa and the exponent for each floating-point type. The most significant bit of any float or double is always the sign bit. If it is 1, the number is considered negative; otherwise, it is considered a positive number.

Table 6.2    Lengths of Exponents and Mantissas

Type	Exponent length	Mantissa length
float	8 bits	23 bits
double	11 bits	52 bits
Because exponents are stored in an unsigned form, the exponent is biased by half its possible value. For type float, the bias is 127; for type double, it is 1023. You can compute the actual exponent value by subtracting the bias value from the exponent value.

The mantissa is stored as a binary fraction greater than or equal to one and less than two. For types float and double, there is an implied leading 1 in the mantissa in the most significant bit position, so the mantissas are actually 24 and 53 bits long, respectively, even though the most significant bit is never stored in memory.

Instead of the storage method just described, the floating-point package can store binary floating-point numbers as denormalized numbers. Denormalized numbers are nonzero floating-point numbers with reserved exponent values in which the most-significant bit of the mantissa is 0. By using the denormalized format, the range of a floating-point number can be extended at the cost of precision. You cannot control whether a floating-point number is represented in normalized or denormalized form; the floating-point package determines the representation. The floating-point package never uses denormalized form unless the exponent becomes less than the minimum that can be represented in a normalized form.

Table 6.3 shows the minimum and maximum values you can store in variables of each floating-point type. The values listed in this table apply only to normalized floating-point numbers; denormalized floating-point numbers have a smaller minimum value. Note that numbers retained in 80x87 registers are always represented in 80-bit normalized form; numbers can only be represented in denormalized form when stored in 32-bit or 64-bit floating-point variables (variables of type float and type long).

Table 6.3    Range of Floating-Point Types

Type	Minimum value	Maximum value
float	1.175494351 E − 38	3.402823466 E + 38
double	2.2250738585072014 E − 308	1.7976931348623158 E + 308
If precision is less of a concern than storage, consider using type float for floating-point variables. Conversely, if precision is the most important criterion, use type double.

Floating-point variables can be promoted to a type of greater significance (from type float to type double). Promotion often occurs when you perform arithmetic on floating-point variables. This arithmetic is always done in as high a degree of precision as the variable with the highest degree of precision. For example, consider the following type declarations:

float f_short;
double f_long;
long double f_longer;

f_short = f_short * f_long;

In the preceding example, the variable f_short is promoted to type double and multiplied by f_long; then the result is rounded to type float before being assigned to f_short.

In the following example (which uses the declarations from the preceding example), the arithmetic is done in float (32-bit) precision on the variables; the result is then promoted to type double:

f_longer = f_short * f_short;


Library Support: Floating Point Operations
  Library Support

The library options for Windows NT are much simpler than they are for Windows 3.x, because applications have only one memory model (flat) and co-processor support is assumed. The three run-time libraries supplied with Visual C++ differ only in multithread support and DLL use; they all support an identical math package.

You may want to use libraries in addition to the default library. For example, you may want to create your own libraries (or other collections of subprograms in object-file form), then link these libraries at a later time with object files that you have compiled using different options.

You must use only one standard C run-time library when you link. To specify the library from the LINK command line, use the /NODEFAULTLIBRARYSEARCH (/NOD) option and then type the name of the combined library file you want to use in the link-libinfo field of the CL command line. Doing so overrides the library names embedded in the object files.


Chapter 7: Structured Exception Handling
  Chapter 7  Structured Exception Handling

Windows NT supports a robust approach to handling exceptions, called structured exception handling, which involves cooperation of the operating system but also has direct support in the programming language.

You can write more reliable code with structured exception handling. You can ensure that resources, such as memory blocks and files, are properly closed in the event of unexpected termination. You can also handle specific problems, such as insufficient memory, with concise, structured code that doesn't rely on goto statements or elaborate testing of return codes.

Note  This chapter describes structured exception handling designed for the C programming language, but it can also be used with C++. See the section »Using Structured Exception Handling with C++« for information on special considerations.

This chapter discusses the following topics:

•	Overview of structured exception handling

•	Writing an exception handler

•	Writing a termination handler

•	Using structured exception handling with C++


  Overview of Structured Exception Handling

The term "exception" refers to an event that is unexpected or disrupts the ability of the process to proceed normally. Exceptions can be detected by both hardware and software. Hardware exceptions include dividing by zero and overflow of a numeric type. Software exceptions include those you detect yourself and signal to the system by calling the RaiseException function, as well as a few special situations detected by Windows NT.


  How Structured Exception Handling Works

The traditional approach to exception handling involves passing along error codes: one function detects an error and passes an error code to its caller. This process may continue through many levels, until the error is communicated to the function that can properly respond to the error. If there is a weak link in the chain of function calls, the whole procedure fails.

Structured exception handling avoids this propagation of error codes. Its distinctive feature is that after an exception handler is installed, it can handle the exception no matter how many other functions are called. Thus, function A can handle an exception raised inside a function called by A.


  Exception Handlers and Termination Handlers

The previous section used the term "exception handlers" in a generic sense, but there are actually two kinds:

•	Exception handlers, which can respond to the exception or dismiss it.

•	Termination handlers, which are called when an exception causes termination inside a block of code.

These two types of handlers are distinct, yet they are closely related through a process called "unwinding the stack." When an exception occurs, Windows NT looks for the most recently installed exception handler that is currently active. The handler can do one of three things:

•	Pass control to other handlers (fail to recognize exception).

•	Recognize but dismiss the exception.

•	Recognize and handle the exception.

The exception handler that recognizes the exception may be in a different function that was running when the exception occurred. In some cases it may be in a function much higher on the stack. The currently running function, as well as all functions in between, are terminated.  During this process, the stack is "unwound": local variables of terminated functions, unless they are static, are cleared from the stack.

As it unwinds the stack, the operating system calls any termination handlers you've written for each function. Use of a termination handler gives you a chance to clean up resources that otherwise would remain open due to abnormal termination. If you've entered a critical section, you can exit in the termination handler. If the program is going to shut down, you can perform other housekeeping tasks such as closing and removing temporary files.


  Writing an Exception Handler

Exception handlers are typically used to respond to specific errors. You can use the exception-handling syntax to filter out all exceptions other than those you know how to handle. Other exceptions should be passed on to other handlers (possibly in the run-time library or the operating system) written to look for those specific exceptions.


  Syntax of Exception Handlers

The structure for C exception handlers is shown in the following syntax:

__try {
statement-block-1
}
__except ( filter ) {
statement-block-2
}

The statements in statement-block-1 are executed unconditionally. During execution of statement-block-1, the exception handler defined by filter and statement-block-2 is active (it becomes the current exception handler).

If an exception occurs during execution of statement-block-1, including any function called directly or indirectly, the system gives control to the current exception handler — unless a handler with higher precedence takes control.

For example, in the following code, the first exception is handled by the outer block, because it is outside the scope of the inner __try block. The second exception is handled by the inner block, which takes precedence.

__try {
float x, y=0;
x = 5 / y;	// This exception handled by outer block
__try {
x = 0;
y = 27 / x;	// This exception handled by inner block
}
__except( GetExceptionCode() == STATUS_FLOATING_DIVIDE_BY_ZERO) {
printf("handled by inner block");
}
}
__except( GetExceptionCode() == STATUS_FLOATING_DIVIDE_BY_ZERO ) {
printf( "handled by outer block" );
}

This code shows an example of nested exception handlers. Note that calling a function that has a try-except block has the same effect as nesting; the try-except block in the most recently called function takes precedence.

When an exception handler takes control, the system first evaluates the filter. One of the powerful features of structured exception handling is that although filter is evaluated out of normal program sequence (often during execution of another function), filter can refer to local variables within its scope just as any C expression. After filter is evaluated, the next action depends on the value returned.

Value of filter	Description
EXCEPTION_CONTINUE_SEARCH (0)	Passes control to exception handler with next highest precedence. The handler has declined to recognize the exception.
EXCEPTION_CONTINUE_EXECUTION( − 1)	Dismisses exception, and continues execution at the location where the exception was raised.
EXCEPTION_EXECUTE_HANDLER (1)	Handles exception by executing statements in statement-block-2. Execution then falls through to the end of this statement block.
If the value of filter is EXCEPTION_EXECUTE_HANDLER, execution does not resume where the exception was raised, but falls through to the end of statement-block-2 after it is executed. All blocks and function calls nested inside statement-block-1 are terminated before statement-block-2 is entered.


  Writing an Exception Filter

You can handle an exception either by jumping out to the level of the exception handler or by continuing execution. Instead of using statement-block-2 to handle the exception and falling through, you can choose instead to use filter to clean up the problem and then, by returning  − 1, resume normal flow without clearing the stack.

Note  Some exceptions are not continuable. If filter evaluates to  − 1 for such an exception, the system raises a new exception. When you call RaiseException, you determine whether the exception is continuable or not.

For example, the following code uses a function call in the filter expression: this function handles the problem and then returns  − 1 to resume normal flow of control:

main ()

{
int Eval_Exception( void );

__try {
...
}
__except ( Eval_Exception( GetExceptionCode( ))) {
// No code; this block never executed.
}
...
}

int Eval_Exception ( int n_except )
{
if ( n_except != STATUS_INTEGER_OVERFLOW &&
 n_except != STATUS_FLOATING_OVERFLOW )   	// Pass on most
return EXCEPTION_CONTINUE_SEARCH;	 	//  exceptions

// Execute some code to clean up problem

ResetVars( 0 );	// ResetVars -- example function to initialize
//  data to 0
return EXCEPTION_CONTINUE_EXECUTION;
}

Use of a function call in the filter expression is a good idea whenever filter needs to do anything complex. Evaluating the expression causes execution of the function, in this case, Eval_Exception.

Note the use of GetExceptionCode to determine the exception. You must call this function inside the filter itself. Eval_Exception cannot call GetExceptionCode, but it must have the exception code passed to it.

This handler passes control to another handler unless the exception is an integer or floating-point overflow. If it is, the handler calls a function (ResetVars is only an example, not an API function) to reset some global variables. Statement-block-2, which in this example is empty, can never be executed because Eval_Exception never returns EXCEPTION_EXECUTE_HANDLER (1).

Using a function call is a good general-purpose technique for dealing with complex filter expressions. Two other C language features that are useful are:

•	The conditional operator

•	The comma operator

The conditional operator is frequently useful, because it can be used to check for a specific return code and then return one of two different values. For example, the filter in the following code recognizes the exception only if the exception is STATUS_INTEGER_OVERFLOW:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0 ) {

The purpose of the conditional operator in this case is mainly to provide clarity, because the following code produces the same results:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {

The conditional operator is more useful in situations where you might want the filter to evaluate to  − 1, EXCEPTION_CONTINUE_EXECUTION.

Another useful C language feature is the comma operator, which enables you to perform multiple, independent operations inside a single expression. The effect is roughly that of executing multiple statements and then returning the value of the last expression. For example, the following code stores the exception code in a variable and then tests it:

__except( nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW )


  Raising Software Exceptions

Some of the most common sources of program error are not flagged as exceptions by the system. For example, if you attempt to allocate a memory block but there is insufficient memory, the run-time or API function does not raise an exception but returns an error code.

However, you can treat any condition as an exception by detecting that condition in your code and then reporting it by calling the RaiseException function. By flagging errors this way, you can bring the advantages of structured exception handling to any kind of run-time error.

To use structured exception handling with errors you define:

•	Define your own exception code for the event.

•	Call RaiseException when you detect that the problem has occurred.

•	Use exception-handling filters to test for the exception code you defined.

The WINERROR.H file shows the format for exception codes. To make sure that you do not define a code that conflicts with an existing exception code, set the third most significant bit to 1. The four most-significant bits should be set as shown in the following table.

Bits	Recommended  binary setting	Description
31-30	11	These two bits describe the basic status of the code:  11 = error, 00 = success, 01 = informational, 10 = warning.
29	1	Client bit. Set to 1 for user-defined codes.
28	0	Reserved bit. (Leave set to 0.)
You can set the first two bits to a setting other than 11 binary if you want, although the "error" setting is appropriate for most exceptions. The important thing to remember is to set bits 29 and 28 as shown in the previous table.

The resulting error code should therefore have the highest four bits set to hexadecimal E. For example, the following definitions define exception codes that do not conflict with any Windows NT exception codes. (You may, however, need to check which codes are used by third-party DLLs.)

#define	STATUS_INSUFFICIENT_MEM	0xE0000001
#define STATUS_FILE_BAD_FORMAT	0xE0000002

After you have defined an exception code, you can use it to raise an exception. For example, the following code raises the STATUS_INSUFFICIENT_MEM exception in response to a memory allocation problem:

lpstr = _malloc( nBufferSize );
if (lpstr == NULL)
RaiseException( STATUS_INSUFFICIENT_MEM, 0, 0, 0);

If you want to simply raise an exception, you can set the last three parameters to 0. The three last parameters are useful for passing additional information and setting a flag that prevents handlers from continuing execution. See the Windows NT Programmer's Reference for more information on the RaiseException function.

In your exception-handling filters, you can then test for the codes you've defined. For example:

__try {
...
}
__except (GetExceptionCode() == STATUS_INSUFFICIENT_MEM ||
        GetExceptionCode() == STATUS_FILE_BAD_FORMAT )


  Hardware Exceptions

Most of the standard exceptions recognized by the operating system are hardware-defined exceptions. Windows NT recognizes a few low-level software exceptions, but these are usually best handled by Windows NT itself.

Windows NT maps the hardware errors of different processors to the exception codes in this section. In some cases, a processor may generate only a subset of these exceptions. Windows NT preprocesses information about the exception and issues the appropriate exception code.

The hardware exceptions recognized by Windows NT are summarized in the following table:

Exception code	Cause of exception
STATUS_ACCESS_VIOLATION	Reading or writing to an inaccessible memory location.
STATUS_BREAKPOINT	Encountering a hardware-defined breakpoint; used only by debuggers.
STATUS_DATATYPE_MISALIGNMENT	Reading or writing to data at an address that is not properly aligned; for example, 16-bit entities must be aligned on 2-byte boundaries. (Not applicable to Intel 80x86 processors.)
STATUS_FLOATING_DIVIDE_BY_ZERO	Dividing floating-point type by 0.0.
STATUS_FLOATING_OVERFLOW	Exceeding maximum positive exponent of floating-point type.
STATUS_FLOATING_UNDERFLOW	Exceeding magnitude of lowest negative exponent of floating-point type.
STATUS_FLOATING_RESEVERED_OPERAND	Using a reserved floating-point format (invalid use of format).
STATUS_ILLEGAL_INSTRUCTION	Attempting to execute an instruction code not defined by the processor.
STATUS_PRIVILEGED_INSTRUCTION	Executing an instruction not allowed in current machine mode.
STATUS_INTEGER_DIVIDE_BY_ZERO	Dividing an integer type by 0.
STATUS_INTEGER_OVERFLOW	Attempting an operation that exceeds the range of the integer.
STATUS_SINGLE_STEP	Executing one instruction in single-step mode; used only by debuggers.
Many of the exceptions listed in this table are intended to be handled by debuggers, the operating system, or other low-level code. Generally, you won't want your own code to attempt to handle these exceptions, except possibly for the integer and floating-point errors. For this reason, you should generally use the exception-handling filter to ignore exceptions (evaluate to 0) in most cases. Otherwise, you would possibly be preventing lower-level mechanisms from responding appropriately.

You can, however, take appropriate precautions against the potential effect of these low-level errors by writing termination handlers as described later in this chapter.


  Restrictions on Exception Handlers

The principal limitation to using exception handlers in code is that you cannot use a goto statement to jump into a __try statement block. Instead, you must enter the statement block through normal flow of control. You can jump out of a __try statement block and nest exception handlers as you choose.

You also cannot nest an exception handler or termination handler inside an __except block.


  Writing a Termination Handler

Unlike an exception handler, a termination handler is always executed, whether the protected block of code terminated normally or not. The sole purpose of the termination handler should be to ensure that resources, such as memory, handles, and files, are properly closed regardless of how a section of code finishes executing.


  Syntax of Termination Handlers

The structure of a termination handler is shown in the following syntax:

__try {
statement-block-1
}
__finally {
statement-block-2

}

The statements in statement-block-1 are executed unconditionally. The statements in statement-block-2 are always executed, in one of two ways:

•	If statement-block-1 finishes execution normally, statement-block-2 is then executed.

•	If statement-block-1 is prematurely terminated for any reason, including a jump out of the block, the system executes statement-block-2 as a part of the process of unwinding the stack.

In the second case, the AbnormalTermination function returns TRUE if called from within statement-block-2; otherwise, it returns FALSE.

If statement-block-1 was abnormally terminated, the termination handler is executed as a part of the process of unwinding the stack. If control jumps outside of several blocks of code at once, the system clears the stack frame for each block of code or function exited, starting with the lowest (most deeply-nested) stack frame. As each frame is cleared, the system executes its termination handler.

For example, suppose a series of function calls links function A to function D, as shown in »Figure 7.1.« Each function has exactly one termination handler. If an exception is raised in function D and handled in A, the termination handlers are called in this order as the system unwinds the stack: D, C, B.


  Cleaning up Resources

During termination-handler execution, you may not know which resources were actually allocated before the termination handler was called. It is possible that the __try statement block was interrupted before all resources were allocated, so that not all resources were opened.

Therefore, to be safe, you should check to see which resources are actually open before proceeding with termination-handling clean-up. A recommended procedure is to do the following:

1.	Initialize handles to NULL.

2.	In the __try statement block, allocate resources. Handles are set to positive values as the resource is allocated.

3.	In the __finally statement block, release each resource whose corresponding handle or flag variable is nonzero or not NULL.

For example, the following code uses a termination handler to close three files and a memory block that were allocated in the __try statement block. Before cleaning up a resource, the code first checks to see if the resource was allocated.

void	FileOps()
{
FILE	*fp1, *fp2, *fp3;
LPVOID	lpvoid;

lpvoid = fp1 = fp2 = fp3 = NULL;
__try {
lpvoid = malloc( BUFFERSIZE );
fp1 = fopen( "ADDRESS.DAT", "w+" );
fp2 = fopen( "NAMES.DAT", "w+" );
fp3 = fopen( "CARS.DAT", "w+" );
.
.
.
}
__finally {
if ( fp1 ) fclose( fp1 );
if ( fp2 ) fclose( fp2 );
if ( fp3 ) fclose( fp3 );
if ( lpvoid ) free( lpvoid );
}
}


  Timing of Exception Handling: A Summary

A termination handler is executed no matter how the __try statement block is terminated. Causes include jumping out of the __try block, a longjmp statement that transfers control out of the block, and unwinding the stack due to exception handling.

Note  Visual C++ for Windows NT supports two forms of the setjmp and longjmp statements. The fast version bypasses termination handling but is more efficient. To use this version, include the file SETJMP.H. The other version supports termination handling as described in the previous paragraph. To use this version, include the file SETJMPEX.H. The increase in performance of the fast version depends on hardware configuration.

The operating system executes all termination handlers in the proper order before any other code can be executed, including the body of an exception handler.

When the cause for interruption is an exception, the system must first execute the filter portion of one or more exception handlers before deciding what to terminate. The order of events is:

1.	An exception is raised.

2.	The system looks at the hierarchy of active exception handlers and executes the filter of the handler with highest precedence; this is the exception handler most recently installed and most deeply nested, in terms of blocks and function calls.

3.	If this filter passes control (returns 0), the process continues until a filter is found that does not pass control.

4.	If this filter returns  − 1, execution continues where the exception was raised, and no termination takes place.

5.	If the filter returns 1, the following events occur:

•	The system unwinds the stack, clearing all stack frames between the currently executing code (where the exception was raised) and the stack frame that contains the exception handler gaining control.

•	As the stack is unwound, each termination handler on the stack is executed.

•	The exception handler itself is executed.

•	Control passes to the line of code after the end of this exception handler.


  Restrictions on Termination Handlers

You cannot use a goto statement to jump into a __try statement block or a __finally statement block. Instead, you must enter the statement block through normal flow of control. (You can, however, jump out of a __try statement block.) You also cannot nest an exception handler or termination handler inside a __finally block.

In addition, there are some kinds of code that are permitted in a termination handler but produce questionable results, so you should use them with caution, if at all. One such situation is a goto statement that jumps out of a __finally statement block. If the block was being executed as part of normal termination, nothing unusual happens. But if the system had been unwinding the stack, that unwinding is now halted, and the current function gains control as if there had been no abnormal termination.

A return statement inside a __finally statement block presents roughly the same situation. Control returns to the immediate caller of the function containing the termination handler. If the system had been in the process of unwinding the stack, this process is now halted, and the program proceeds as if there had been no exception raised.


  Using Structured Exception Handling with C++

Structured exception handling described in this chapter works with both C and C++ source files. However, it is not specifically designed for C++ and has a limitation that can affect C++ programs: as the stack is unwound, C++ objects allocated on the stack are removed without calling their destructor functions. Consequently, if an object (such as an object of the CHDC class) allocates a handle or memory on creation and releases the handle on termination, this important clean-up of the resource is never performed if the stack is unwound.

Objects allocated on the stack include all local objects not declared as static.

The work-around is to not allocate the object on the stack, if important clean-up work is needed to be performed by a destructor function. Instead, create the object by calling the new function, and then write a termination handler that explicitly removes the object by calling delete.

A future version of Visual C++ will modify and expand support of exception handling in two respects. First, the structured exception handling described in this chapter will be enhanced to automatically handle destruction of local objects during stack unwind. In addition, support will be added to implement C++ exception handling, as set forth in the X3J16 ANSI working documents. For detailed information about C++ exception handling, see the C++ Annotated Reference Manual by Margaret Ellis and Bjarne Stroustrup.

Because the compiler's support of exception handling will change as described in the previous paragraph, you should consider the potential effects for C++ modules in any way involved with exception handling. To aid in porting code, a backward compatibility option will be added so that code compiles exactly as it does now. However, if you're working with C++ modules, a good precaution would be to carefully comment places where you use structured exception handling.


Chapter 8: Using Calling Conventions
  Chapter 8  Using Calling Conventions

The Visual C/C++ compiler provides several ways to call internal and external functions. The information in this chapter can help you when debugging your program and when interfacing your code with assembly-language routines.

This chapter covers the differences between the calling conventions, how arguments are passed, and how values are returned by functions. It also discusses naked function calls, an advanced feature that allows you to write your own prolog and epilog code.


  Argument Passing and Naming Conventions

All arguments are widened to 32 bits when they are passed. Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are pushed onto the stack from right to left.

The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they are used in the function.

Note  For information on how to define your own function prolog and epilog code see »Naked Functions«.

The following calling conventions are supported by the Visual C/C++ compiler.

Keyword	Stack clean-up	Parameter passing
__cdecl	Caller	Pushes parameters on the stack, in reverse order (right to left)
__stdcall	Callee	Pushes parameters on the stack, in reverse order (right to left)
__fastcall	Callee	Stored in registers, then pushed on stack
thiscall  (not a keyword)	Callee	Pushed on stack; this pointer stored in ECX


  __cdecl

This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack clean-up code.

All function arguments are pushed on the stack. In C, the __cdecl function names are prefixed by an underscore when decorated.

Note  See your C++ compiler documentation for information on C++ name decoration.


  __stdcall

The __stdcall calling convention is used to call Win32 API functions. The stack is cleaned up by the callee, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.

All function arguments are pushed on the stack. In C, the __stdcall function names are prefixed by an underscore and suffixed with @number when decorated, where number is the number of bytes (in decimal) used by the widened arguments pushed to the stack.


  __fastcall

The __fastcall calling convention is similar to the __stdcall calling convention, but __fastcall speeds up function calling by storing up to two arguments in the ECX and EDX registers. Any additional arguments are pushed to the stack as in the other calling conventions.

In C, the __fastcall function names are prefixed by the at sign (@) and suffixed with @number when decorated, where number is the number of bytes (in decimal) used by the widened arguments pushed to the stack plus the number of bytes taken by the widened arguments passed in registers.

Note  Future compiler versions may use different registers to store parameters.


  thiscall

This is the default calling convention used by C++ member functions that do not use variable arguments. The stack is cleaned up by the callee, so the compiler makes vararg functions __cdecl and pushes the this pointer on the stack last. The thiscall calling convention cannot be explicitly specified in a program, because thiscall is not a keyword.

All function arguments are pushed on the stack. Because this calling convention applies only to C++, there is no C name decoration scheme.


  Obsolete Calling Conventions

The __pascal, __fortran, and __syscall calling conventions are no longer supported. Their functionality can be emulated by using one of the supported calling conventions and appropriate linker options.

WINDOWS.H now supports the WINAPI macro, which translates to the appropriate calling convention for the target. Use WINAPI where you previously used PASCAL or __far __pascal.


Example
  Calling Example

The following example shows the results of making a function call using various calling conventions.


  Function Prototype and Call

This example is based on the following function skeleton. Replace calltype with the appropriate calling convention.

void	calltype MyFunc( char c, short s, int i, double f );
.
.
.
void	MyFunc( char c, short s, int i, double f )
{
.
.
.
}
.
.
.
MyFunc ('x', 12, 8192, 2.7183);


  Results

__cdecl

The C decorated function name is "_MyFunc". See your compiler documentation for the C++ decorated name.

Stack

Contents	Location
2.7183	ESP+0x14
	ESP+0x10
8192	ESP+0x0C
12	ESP+0x08
x	ESP+0x04
Return address	ESP
Registers

Contents	Register
Not used	ECX
Not used	EDX
__stdcall and thiscall

The C decorated name (__stdcall) is "_MyFunc@20". See your compiler documentation for the C++ decorated name.

Stack

Contents	Location
2.7183	ESP+0x14
	ESP+0x10
8192	ESP+0x0C
12	ESP+0x08
x	ESP+0x04
Return address	ESP
Registers

Contents	Register
this  (thiscall only)	ECX
Not used	EDX
__fastcall

The C decorated name (__stdcall) is "@MyFunc@20". See your compiler documentation for the C++ decorated name.

Stack

Contents	Location
2.7183	ESP+0x0C
	ESP+0x08
8192	ESP+0x04
Return address	ESP
Registers

Contents	Register
x	ECX
12	EDX


  Naked Functions

Functions declared with the naked attribute are emitted without prolog or epilog code, thus allowing you to write your own custom prolog/epilog sequences using inline assembler. Naked functions are provided as an advanced feature to allow you to declare a function that is being called from a context other than C/C++, and thus may make different assumptions about where parameters are or which registers are preserved. Examples include routines such as MS-DOS interrupt handlers. This feature is particularly useful for writers of virtual device drivers (VxDs).


  Syntax

Because the naked attribute is not a type modifier, naked functions use the extended attribute syntax, as described previously. For example, the following code defines a function with the naked attribute:

__declspec( naked ) int func( formal_parameters )
{
// Function body
}

Or, alternatively:

#define Naked	__declspec( naked )
Naked int func( formal_parameters )
{
// Function body
}

The naked modifier affects only the nature of the compiler's code generation for the function's prolog and epilog sequences. It does not affect the code that is generated for calling such functions. Thus, the naked attribute is not considered part of the function's type. As such, function pointers cannot have the naked attribute. Furthermore, the naked attribute has no meaning when applied to a data definition, and any attempt to do so will generate a compiler error. For example, the following code samples will generate errors:

__declspec( naked ) int i;	// Error--naked attribute not permitted on
// data declarations.

extern __declspec( naked ) int i;	// Error--naked attribute not
// permitted on data declarations.

The naked attribute is relevant only to the definition of the function. Thus it cannot be specified on the function's prototype. The following declaration will generate a compiler error:

__declspec( naked ) int func();	// Error--naked attribute not permitted
// on function declarations.

A new symbolic argument for use in the inline assembler block of function prolog code is provided by the compiler. This symbol, __LOCAL_SIZE, is used to allocate space for local variables on the stack frame in your custom prolog code. This constant contains a value determined by the compiler, and represents the number of bytes of local variables.

__LOCAL_SIZE includes all user-defined locals as well as compiler-generated temporary variables. __LOCAL_SIZE may be used as an immediate operand or in an expression. For example:

mov	eax, __LOCAL_SIZE	/* Immediate operand */
mov	eax, __LOCAL_SIZE + 4	/* Expression */
mov	eax, [ebp - __LOCAL_SIZE]	/* Expression */


  Rules and Limitations

The following rules and limitations apply to naked functions:

•	The return statement is not permitted in a naked function.

•	Structured Exception Handling constructs are not permitted because they must unwind across the stack frame.

•	For the same reason, any form of setjmp is prohibited.

•	Use of the _alloca function is prohibited in a naked function.

•	To ensure that no initialization code for local variables appears before the prolog sequence, initialized local variables are not permitted at function scope. In particular, the declaration of C++ objects is not permitted at function scope. There may, however, be initialized data in a nested scope.

•	Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically supressed for a naked function.

•	You cannot declare C++ class objects at the function lexical scope. You can, however, declare objects in a nested block.


  Naked Function Example

The following is a minimal example of a naked function containing custom prolog and epilog sequences:

__declspec ( naked ) func()
{
int i;
int j;

_asm
{
push	ebp
mov	ebp, esp
sub	esp, __LOCAL_SIZE
}

/* C and/or _asm code */

_asm
{
mov	esp, ebp
pop	ebp
ret
}
}


Chapter 9: Using the Win32s Extension
  Chapter 9  Using the Win32s Extension

Microsoft Win32s is an extension for Microsoft Windows 3.x that gives you all the benefits of Windows NT. Win32s provides the following:

•	A powerful 32-bit programming model for Windows 3.x that is binary-compatible with Windows NT.

•	Performance advantages of 32-bit mode.

•	Win32 semantics for the application programming interface (API).

•	A rich subset of the full Win32 API found on Windows NT.

•	A huge established market of Windows 3.x systems and the new Windows NT market to sell Win32 applications.

•	The ability to develop Win32 applications for Windows 3.x that will also run on Windows NT.

Win32s consists of a virtual device driver (VxD) and a set of dynamic link libraries (DLLs) that extend Windows 3.x to support Win32 applications. The Win32s files must be shipped with the Win32 application and installed on the Windows 3.x system.

Visual C++ provides the following Win32s components:

•	Win32s binaries and a setup program to install Win32s on a Windows 3.x system

•	Development files to create, debug, test, and ship your Win32 application and Win32s files

The first part of this chapter provides installation instructions for Win32s onto a Windows 3.x system using a setup program provided on the Visual C++ CD. The remainder of the chapter covers issues developers should consider when writing Win32 applications targeted for both Windows NT and Windows 3.x.


  System Requirements

To install Win32s and run Win32 applications, you need:

•	A system running Microsoft Windows for Workgroups™ or Windows 3.x in enhanced mode with paging enabled (default).

•	A 386 or greater processor (386sx and 486sx processors are also supported).

•	2MB of extended memory (4MB recommended).

•	720K of hard disk space for Win32s and another 250K for FreeCell (an optional demonstration program).


  Installing Win32s

The Win32s system files can be installed from the Visual C++ CD or from a shared CD drive over the network.


  Installing Win32s from CD-ROM or a Network

1.	Start MS-DOS with appropriate software for accessing a local CD drive or a remote CD drive over the network.

2.	Start Windows by typing win at the MS-DOS prompt.

3.	Use the File Manager to access the Visual C++ CD-ROM.

4.	In the File Manager window, display the files in the \MSVC32S\WIN32S\FLOPPY directory, and then double-click on SETUP.EXE to run the Setup program.

5.	Follow the setup instructions to complete the installation.


  Verifying Win32s Installation

In addition to installing the Win32s system components, the Win32s Setup program optionally installs the Win32 card game FreeCell, which is the same program that ships as part of Windows NT. After installing Win32s, you can run FreeCell to verify that Win32s is installed correctly. FreeCell is located in the Program Manager group Win32 Applications, which the Win32s Setup program creates.

Note  If you are installing Win32s on Windows 3.x, you must run the MS-DOS SHARE utility before starting Windows. You may want to add SHARE.EXE to your AUTOEXEC.BAT file. SHARE.EXE is not required if you are running Windows for Workgroups.


  Win32s Overview

The Win32s mapping layer allows Win32 applications to make 32-bit calls to Windows 3.x where graphics and windowing operations are done. The Windows API in Windows 3.x and Windows NT share a large common set of features.

The following list highlights Windows 3.x features available through the Win32s API:

•	Complete windowing interfaces (User)

•	All graphics functions (GDI)

•	OLE (object linking and embedding) version 1.0

•	DDE/DDEML (dynamic data exchange and DDE Management Library)

•	TrueType fonts

•	Common dialogs

In addition to supporting Windows 3.x functionality, the following Windows NT features are also supported by Win32s on Windows 3.x:

•	Structured exception handling (SEH)

•	Sparse memory (Virtual memory API)

•	Growable heaps (Heap API)

•	Named shared memory


  Architecture

»Figure 9.1« illustrates the key pieces of Win32s. The dark gray boxes represent Win32s components; the light gray boxes depict Windows 3.x components. The 32-bit Win32 application dynamically binds to Win32s versions of Win32 system DLLs such as KERNEL32.DLL, GDI32.DLL, and USER32.DLL. A large percentage of the API calls are then handled by the general 32/16 thunking DLL, WIN32S16.DLL, which is responsible for repacking the stack, truncating or expanding parameters, mapping message parameters (due to Windows 3.x/Win32 differences), and so on. The VxD is trusted ring 0 kernel code that handles low-level system services such as exception handling, floating-point trap emulation, and memory management.

Because Windows 3.x does not recognize and cannot load executables for Windows NT, Win32s provides Windows NT loader code. Loader services are handled by W32SKRNL.DLL.

The light gray User, GDI, and Kernel components are the Windows 3.x window manager, graphics engine, and kernel services DLLs, respectively. »Figure 9.1« shows the general flow of control when a Win32 application makes a Win32 call. Most calls are passed to Windows 3.x, which actually implements the call.


Coordination Between Windows 3.1 and Win32s
  Coordination Between Windows 3.x and Win32s

Win32s and Windows 3.x system-code are tightly coupled. Win32s is a true system extension to the Windows 3.x operating system code.

The first level of coordination occurs in the Windows 3.x loader. The Windows 3.x loader was designed to recognize the presence of a Win32s loader. So now, when Windows 3.x attempts to load an executable and cannot identify the image header, the Win32s loader (if present) is called to determine whether the image is an executable for Windows NT (known as PE for Portable Executable). If the image is not a PE image, Windows 3.x reports that the file cannot be executed. If the image is a PE image, the Win32s loader loads the image table (including items such as the fix-up tables) and then demand-loads the rest of the image as the program executes.

Win32s also hooks the Windows 3.x resource loader. One reason to do this is so that application icons appear correctly in the Program Manager (or other resource viewing utilities). When Windows 3.x attempts to read a resource from a PE image (something that it cannot do), Win32s fabricates the resource (such as the icon) as a 16-bit resource. In this way, Win32 applications can be added to the Program Manager and still have properly displayed icons for selection. This support is transparent to both the programmer and the user.

Win32s uses a similar method to support versioning. Versioning APIs are new to Windows 3.x and allow version-marked executables to be checked by utilities such as setup tools. Win32s hooks Windows 3.x so that version calls return valid information when a 16-bit application for Windows version-checks a Win32 application.

Messaging between applications is generally handled in a straightforward manner by the Win32s thunk layer. However, special cooperation between Win32s and Windows 3.x also allows Windows hook APIs and message subclassing to be supported. A Win32 application can install a hook to monitor all applications for Windows (16-bit and 32-bit). Win32s ensures that the Win32 hook sees a 32-bit format of all messages regardless of the message source or destination.

Windows 3.x and Win32s must also have cooperative memory management between the Win32s VxD and Win386. Win32s also manages the complex task of translating pointers passed by the Windows API between the Win32 application and 16-bit Windows system code.

For these reasons, Win32s should be considered an operating system extension to Windows 3.x that supports 32-bit programming through the Win32 API.


  Message Handling

In Win32, messaging has had few functionality additions. Therefore, message handling in a Win32 application is generally identical to message handling in an equivalent 16-bit application for Windows. A Win32 application receives messages in identical order as a Windows 3.x application because Win32s relies on Windows 3.x to deliver messages. Message order is also the same on Windows NT.


  Memory

Windows 3.x implements a shared memory design, in which all Windows processes reside in one global memory heap. Windows NT, however, isolates processes into their own private virtual address space. Win32 applications running on Windows 3.x coexist in the same shared global memory heap as other Win32 and Windows 3.x applications.

Win32s supports the following features for Win32 executables or DLLs:

•	Multiple Win32 executables and DLLs can be loaded simultaneously.

•	Multiple Win32 executables can reference the same Win32 DLL.

•	Win32 DLLs referenced by multiple Win32 applications share a single copy of the DLL code and data.

•	Win32s DLLs and VxD are shared by all Win32 applications.

•	Win32s supports executing data as code (such as dynamic code generation).

•	Win32 applications see a flat 32-bit address space. (CS, DS, SS, and ES map a single address space.)

•	Win32s supports demand-paging of executables for efficient executable, DLL, and data loading.

•	Win32s version 1.0 allocates a non-growable 128K stack for each Win32 process.

One impact of a global shared heap and not being able to use selectors for dereferencing addresses (as occurs in Windows 3.x applications) is that multiple instances of Win32 executables do not share code. The loader must fix up all 32-bit linear addresses to code and data when an executable is loaded. Win32 applications do not move in memory nor are segment registers available to switch context to a second instance while still sharing the same code. Therefore, each instance of a Win32 executable must be loaded into memory and code cannot be shared.

Note:  Win32 applications should not be designed to assume that all Win32 applications run in the same address space. Such applications do not run on Windows NT or on future versions of Windows for MS-DOS. Also, Win32s may implement sparse memory using separate address spaces in a future release.


  Processes and Tasking

Windows 3.x and Win32 applications coexist seamlessly on the same desktop (display). Win32s assures that Windows 3.x applications "see" Win32 applications as other Windows 3.x applications, and that Win32 applications see Windows 3.x applications as other Win32 applications. A Win32 application can enumerate windows in the system and receive 32-bit window handles for both Win32 and Windows 3.x applications. This means that Win32 applications can send messages to other windows or can use DDE or OLE to communicate with other processes without regard to the 16-bit or 32-bit nature of the other application.

The Windows 3.x non-preemptive, message-driven scheduler is responsible for scheduling both Windows 3.x and Win32 applications. Win32 applications operate under the same constraints as Windows 3.x applications. To keep the user interface responsive, Win32 applications must check their message queue regularly. On Windows NT, a Win32 application that does not check its message queue and handle messages in a timely manner only affects its own user interface. The user may switch away and work on other applications. Windows 3.x, however, uses messages to schedule processes. Therefore, applications (16-bit or 32-bit) must handle messages in a timely manner to keep Windows 3.x responsive.


  Win32 Dynamic Link Libraries

Windows NT supports new features for DLLs not available to 16-bit DLLs. Win32s also supports the Windows NT features as follows:

•	Win32 DLLs in Windows 3.x receive the same notifications as on
Windows NT when each process loads or links to the DLL and when each process frees the DLL or terminates (including abnormal termination).

•	DLLs are initialized in the same order as on Windows NT (applies to applications with multiple DLLs).

•	The Win32s loader searches for Win32 DLLs first in the Win32s directory and then uses the same search algorithm as Windows NT.

•	Thread local allocations (TlsAlloc) are made system-wide rather than on a per-process basis providing an instance data solution.


  File Input and Output

The Win32 API provides all functions for manipulating files (such as open, seek, move, and rename). The Win32 API is required because calling MS-DOS functions with Interrupt 21H is not supported. Many applications rely on the C run-time library, which in turn also relies on Win32 API functions for file I/O. For this reason, the C run-time library is portable and correctly calls Win32s for file I/O.


  Floating-Point Emulation

Win32s provides a floating-point trap emulator to support Win32 applications with inline math coprocessor instructions. This support allows these applications to function even if they are run on systems without coprocessor hardware. If a coprocessor is present, the trap emulator is not involved.

The same floating point emulator is used on both Windows NT and Win32s, which ensures compatible results between a Win32 application running with Windows 3.x and with Windows NT.

Win32 applications can use structured exception handling (SEH) to handle exceptions generated by the coprocessor — for example, divide by 0, overflow, and underflow. SEH allows the Win32 application to handle the exception itself and continue or allow the system to handle the exception (generally resulting in termination of the application).


  Printing

Code that supports printing in Windows can be rather complex. Fortunately, Win32 and Win32s support existing printing code quite compatibly. Win32s relies on the existing Windows 3.x printer drivers for output and does not support loading 32-bit Windows NT printer drivers.

Win32s supports all Windows 3.x escapes except those marked as obsolete in the Windows 3.x SDK documentation. Windows NT implements a small set of  fundamental escapes for ease in portability, but uses named API functions rather than device-specific escapes to support advanced hard copy output. Therefore, it is critical to query for the support of an escape rather than assume the escape will always be present. If you find that a particular escape is not supported, use an alternate method to accomplish the same task.

Windows 3.x applications use printer-specific escapes, if available, and use general-purpose code if the escape is not supported. This approach should also work in Windows NT; alternatively, you can call the new Win32 printing API functions that replace the driver-specific escapes when the application runs with Windows NT.


  Win32s Programming Considerations

There are several differences between Windows NT and Win32s that affect how programs run. By following the guidelines described below, you can avoid many potential problems.


Preemptive Multitasking‹@›
  Preemptive Multitasking

Windows NT is a preemptive multitasking operating system; Windows 3.x relies on message-driven multitasking. This difference can cause compatibility problems when Win32 applications are run on the different systems unless the applications are properly designed and tested.

Data manipulations in DLLs must be guarded by synchronization objects. A feature of  Windows 3.x is that DLL operations are atomic. For example, when an application receives a message, it is scheduled to handle that message and gain control of the CPU. The application owns the CPU until it checks its message queue. When the application checks its queue, Windows 3.x may opt to schedule another application. When an application owns the CPU, no other application for Windows is scheduled. Therefore, the application handling a message can call a DLL, update data managed in the DLL, and be assured that no other applications called the DLL at the same time.

This is not true of Win32 applications running with Windows NT. For example, a Win32 application may call a DLL which begins to update DLL-managed data; the preemptive scheduler may pass control of the processor to another process, which could call the same DLL. If the second process also updates data in the DLL, the data will be corrupted. To protect DLL data, the Win32 API provides a set of synchronization objects. These objects are supported in Win32s. Functions like EnterCriticalSection return success even though they are unnecessary in Windows 3.x.

By supporting synchronization calls in Win32s, applications can execute a common code path and simplify programming and testing. It is critical to test an application in both Windows 3.x and Windows NT to ensure correct operation.


  Message Handling

Win32 and Windows 3.x applications coexist in the system and can pass messages without knowing whether the other application is a 16-bit or 32-bit application. Win32s maps messages transparently, offering Win32 applications 16-bit Windows messages with Win32 semantics.

For private messages (messages defined by an application, not by the Win32 API), Win32s cannot determine the contents of wParam and lParam message parameters. Therefore, the following effects occur when passing private messages between applications for Windows:

•	Private message from Windows 3.x to Win32: wParam is 0 extended.

•	Private message from Win32 to Windows 3.x: high-order word of  wParam is lost.

•	Private message from Win32 to Win32: high-order word of  wParam is lost.

•	Private message from Windows 3.x to Win32 or Win32 to Win32: lParam is unaffected.

This behavior has the following impact: Passing a pointer as a private message in lParam is safe between two cooperative Win32 applications; passing a linear
32-bit pointer in lParam through a private message to a Windows 3.x application results in an invalid pointer when the Windows 3.x application uses it (because Win32s cannot translate this pointer). Because Windows 3.x is used to deliver messages, the high word of wParam is lost even when messages are being passed only between Win32 applications. Again, this is limitation of private messages, not public messages such as WM_COMMAND.

Win32s supports message hooks. Because hooks can be used to intercept messages between applications, Win32s assures that hooks installed by Windows 3.x applications can intercept messages destined for Win32 applications. Similarly, Win32 hooks can intercept messages destined for Windows 3.x applications. In each case the 16-bit or 32-bit message hook intercepts messages for Windows 3.x and Win32 applications but translated into the appropriate 16-bit or 32-bit message form.


  Memory Management

Windows 3.x uses a single 2-gigabyte (GB) address space in which all applications for Windows (16-bit and 32-bit) run. Therefore, DLL data segments are shared among all processes that call the DLL. Windows NT has separate 2-gigabyte-per-process address spaces. The default DLL behavior is to have private DLL data (known as instance data). Windows NT DLLs can be built to have shared DLL data for compatibility with applications for Windows that require this feature.

If your port of a 16-bit application for Windows to Win32 relies on shared DLL data, you should build the DLL indicating shared data. The default linker behavior is to create instance data DLLs.

Win32 DLLs on Windows 3.x always have shared DLL data regardless of how the DLLs are built. This means you can create a Win32 DLL that has instance data in Windows NT and shared data in Windows 3.x. Applications that rely on shared DLL data must be built specifying this to guarantee the same behavior on both Windows 3.x and Windows NT.


  C Run-Time Support

Win32 applications that rely on C run-time routines can choose to statically link the C run-time routines with the application or dynamically link to a C run-time DLL. Visual C++ provides a C run-time DLL called MSVCRT10.DLL, which is useful for applications that consist of multiple executables sharing a single DLL or set of application DLLs which all rely on C run-time calls. Because Win32s does not support per-process data for DLLs, MSVCRT10.DLL cannot be used reliably.


  Performance Considerations

Calls to the Win32 API are translated before being passed to Windows. This involves translating pointers and repacking parameters on the stack, among other operations. Therefore, there is an overhead associated with calling the Windows API. For functions that require a large amount of processor time to complete (such as BitBlt), the thunking overhead as a percentage of total API execution time is very small (less than one percent). Other functions — for example, functions that simply query status — have a relatively high thunking overhead. Test scenarios that call a broad selection of Win32 API functions take approximately 10 percent longer due to the thunking layer.

Therefore, an application that calls only Win32 API functions will experience a 10 percent degradation. However, real applications have a mix of system calls and time spent in the 32-bit routines of the application and generally will see a performance increase.

Win32s is a perfect candidate for applications that are data- and memory-intensive or calculation-intensive, such as CAD packages, desktop publishing packages, image manipulation tools, spreadsheet programs, and simulation software. Manipulating data and performing calculations in 32-bit mode improves the performance of these applications significantly. Win32 applications should see performance improvements when running with Windows version 3.1, despite the slight overhead resulting from 32-bit to 16-bit translation (thunking) that occurs during Windows API calls.

Several Win32 applications have been used to do initial performance analysis of Win32s by comparing performance between 16-bit and 32-bit versions of the same applications. For GDI-intensive operations used in these applications, the performance was found to be roughly the same. For numeric computation and for traversing data, the Win32s versions of the applications were up to two times faster.

The overall effect is that most Win32 applications using Win32s will see a performance gain over their 16-bit Windows counterparts, with the added benefit that these new applications are native 32-bit applications with Windows NT.

Using the following techniques can significantly improve the performance of your Win32 application on both Windows 3.x and Windows NT:

•	Use the PolyLine function rather than MoveTo/LineTo operations.

•	Local variables (stack variables) are faster to pass by reference between the Win32 application and the system.

•	Use the Microsoft Source Profiler provided with Visual C++ to tune your code.

Using PolyLine saves time in Win32s by minimizing the number of thunks that must be passed through on route from the Win32 application to Windows 3.x system code. This is beneficial on both Win32s and Windows NT.

Pointer translation from 32 bits to 16 bits can be a time-consuming operation for Win32s. Different types of memory (GlobalAlloc, LocalAlloc, VirtualAlloc, global data, and local data) take different amounts of time. In general, pointers to local variables are always translated fastest because they are on the application's stack, and Win32s has optimized translation of the stack pointer.


  Advanced Features

Because the entire Win32 API is exported by Win32s, any Win32 application can be loaded into Windows 3.x because all functions are fixed up correctly by the loader. However, applications that rely exclusively on Win32 features that cannot be implemented in Windows 3.x (such as paths, threads, transformations, or asynchronous file I/O) will find that these functions fail and return errors.

An application can selectively, and as a run-time feature, implement different functionality when the application is run with Windows 3.x through Win32s or when run with Windows NT. For example, a graphics application could offer bezier curve drawing tools when the paint program is run on Windows NT. The same tool could emulate this functionality itself or not offer the feature with Windows 3.x. The application can use the error return from these unsupported Win32 API functions in Win32s to determine the proper plan of action.

When running on Windows NT, an application can spawn background threads to complete tasks, something it cannot do when running on Windows 3.x, where it runs only as a single-threaded application. But, consider that all Win32 applications automatically benefit from the scheduler on Windows NT even if they do not use multiple threads. Win32 applications execute with an asynchronous messaging model on Windows NT, which allows users to switch away from applications that are tied up in long calculations. Therefore, taking advantage of threads when an application runs on Windows NT is not required, and most applications will just rely on the asynchronous messaging model advantage.

Unsupported APIs return error code ERROR_CALL_NOT_IMPLEMENTED. However, Win32 applications do not need to rely exclusively on error return codes but can determine which Windows platform they are running on (Windows 3.x or Windows NT) by calling the GetVersion function. The high-order bit of the DWORD return value is zero when the application is running on Windows NT and one if the application is running on Windows 3.x.


  16-bit and 32-bit Code Mixing

Windows NT does not support mixing 16-bit and 32-bit code. Such support is contrary to the portable design of Windows NT running on x86 (CISC) and R4000 (RISC) systems today. The 32-bit Visual C++ tools generate only 32-bit code, and the linker and loader have no support for fixing up 16-bit segmented addresses.

Therefore, for binary compatibility of a Win32 application running with Win32s and Windows NT, mixing is not supported by Win32s. Mixing is not limited to embedding 16-bit routines in a Win32 application (such as static library code). There is no support for Win32 applications loading 16-bit DLLs or vice versa.

Applications that rely on 16-bit DLLs (perhaps licensed DLLs for which obtaining 32-bit versions is difficult) have several choices:

•	Use a client/server architecture where all 16-bit DLLs are bound to a small, custom 16-bit server application. This custom 16-bit server can communicate with the Win32 application through DDE, shared memory, or other IPC mechanism. The client/server solution works in Win32s and Windows NT.

•	A unique solution provided by Win32s allows Win32 applications to use existing 16-bit DLLs and device drivers. Universal thunks (discussed later in this chapter) are not supported on Windows NT but are available as a stepping stone for moving applications to 32-bit on Windows 3.x.


  Device Drivers

Windows NT runs applications in user-mode, but only kernel-mode device drivers running in privileged-mode can access devices. Because of fundamental differences in architecture between Windows 3.x and Windows NT, Win32s does not support the Windows NT device-driver model. For binary compatibility with Windows NT, Win32 applications should not access hardware directly within the application.

This poses a problem similar to mixing 16-bit and 32-bit code. The general solution is to develop the architecture of your Win32 application such that the main application has a standard interface to a Win32 DLL (service provider). The Win32 DLL uses a client/server design to request or transfer data to a 16-bit server responsible for hardware access on Windows 3.x.

To support this application in Windows NT, the DLL should be replaced by a DLL specific to Windows NT that uses IOCTLs to communicate directly with the kernel-mode driver (or uses Win32 APIs for supported devices). This solution isolates the platform-specific code to a DLL, which can be correctly installed during setup.

To address concerns about bandwidth of the client/server design, Win32s provides a solution to allow Win32 DLLs to call 16-bit DLLs (or vice versa) using the universal thunk.


  Universal Thunk

Binary compatibility and the requirement to provide natural migration to Windows NT creates a portability problem for ISVs who have applications for Windows that require device drivers.

Win32s does not support the Windows NT kernel device driver model on Windows 3.x. Therefore, the only way that Win32 applications running on Windows 3.x can access devices is through existing drivers supported by Windows 3.x. However, Windows NT does not support mixing 16-bit and 32-bit code in the same process. The mixing restriction also precludes 16-bit DLLs from being called by Win32 applications.

This mixing restriction creates an interesting scenario for printing. Applications for Windows load and call printer drivers directly, by using calls such as LoadLibrary, GetProcAddress, and ExtDeviceMode. Win32s handles these printer drivers specifically by creating a mapping thunk dynamically. The address returned to the Win32 application by GetProcAddress is actually the address to the thunk that makes the 32 to 16 transition and calls the printer driver.

There are a number of interprocess communication (IPC) mechanisms, such as DDE, that allow data to be passed between Win32 and 16-bit Windows processes, but the bandwidth is not sufficiently high for some types of applications. Therefore, the solution provided for printing has been generalized by a universal thunk. The universal thunk allows a Win32 application to call a routine in a 16-bit DLL. There is also support for a 16-bit routine to call back to a 32-bit function. The simple Win32s thunk used to implement this design also translates a data pointer to shared memory, from flat to segmented form, allowing large amounts of memory to be transferred between drivers and Win32 applications.

This design allows a Win32 application to isolate driver-specific routines in a 16-bit DLL. The Win32 application remains portable across Windows 3.x and Windows NT; in Windows NT, the 16-bit DLL is replaced with a 32-bit DLL that communicates to devices using the Windows NT model.


  Universal Thunk Design

»Figure 9.2« illustrates a Win32 application using a Win32 service DLL on Windows NT.

»Figure 9.3« illustrates how the same Win32 application running on Windows 3.x uses the universal thunk (UT) mechanism to access services provided by a Windows 3.x DLL. »Figure 9.3« illustrates thunking from 32-bit to 16-bit; thunking in the reverse direction works in a similar way.

The same version of the 32-bit application runs on Windows 3.x and Windows NT. For the service provider, two different modules are required. Both provide the very same services, one using Win32 DLL on Windows NT, and the other using a 16-bit DLL through the universal thunk.

UTRegister registers a universal thunk with Win32s that can be used to access
16-bit code from a 32-bit application running on Win32s. UTRegister automatically loads the 16-bit DLL specified by name as a parameter to this function. The 16-bit DLL exports two functions: an initialization function InitFunc and function UTFunc. InitFunc is called once when UTRegister is called and is optional. UTFunc is called indirectly through a 32-bit callable stub from the Win32 application. The thunk can be destroyed by calling UTUnRegister.

Registering the universal thunk enables two capabilities for communicating between 32-bit and 16-bit routines. The first capability is to allow a Win32 application to call a 16-bit routine passing data using global memory. This is a Win32 application-initiated data transfer mechanism. The second capability is to register a callback routine by which 16-bit code can callback into a 32-bit routine in a Win32 DLL. Again, global memory is used to transfer data.

UTRegister results in Win32s loading the specified DLL (using LoadLibrary) with normal Windows 3.x DLL initialization occurring. Win32s then calls the InitFunc routine (indirectly through the UT), passing it a 16:16 alias of the 32-bit callback. The InitFunc routine can return data in a global memory buffer. UTRegister also creates a 32-bit callable stub for UTFunc and returns its address to the 32-bit DLL. Also, a 16-bit callable stub might be created to reflect the 32-bit callback and is passed to the 16-bit DLL by its InitFunc.

The universal thunk translates the 32-bit linear pointer to shared memory to a 16:16 segmented pointer for the 16-bit UTFunc routine. It is the application's responsibility to define the format and packing of the data in the global memory. Care should be taken when passing information in structures through global memory because some data types, such as int, are 32 bits in Win32 and 16 bits in Windows 3.x.

UTUnRegister allows the dynamically created universal thunk to be destroyed and the 16-bit DLL freed. Win32s cleans up these resources automatically when the Win32 process terminates (normally or abnormally).

Win32s destroys the UT and calls FreeLibrary for the 16-bit DLL when UTUnRegister is called and the Win32 application terminates (normally or abnormally).

Note that the shared memory accessed by the thunked data pointer is not freed by Win32s. The memory is freed as part of normal process cleanup if the process itself does not free the memory.

The 32-bit callback function should not be used by 16-bit interrupt handlers. The Win32 API does not support locking memory pages; therefore, an interrupt service routine that calls back into 32-bit code cannot guarantee that the code is currently paged into memory.


  Translation List

One of the parameters passed to the callable stub (either 32-bit or 16-bit) is  a translation list. If you want to pass as reference to a structure containing pointers, you should use a translation list that indirectly points to all the pointers to be translated during the thunking process. See »Figure 9.4«.

Upon a call to UT callable stub:

(*pfnMyDispatch)(lpPerson, SERVICE_ID, pTranslationList);

the thunking process translates the lpPerson pointer, scans the lpTranslationList and translates in place all the pointers, changes the stack, and calls the relevant function.


  Universal Thunk API

UTRegister

UTUnRegister

UT16INIT

UT16PROC

UT16CBPROC

UT32PROC

UT32CBPROC

UTSelectorOffsetToLinear

UTLinearToSelectorOffset


  UTRegister

BOOL UTRegister(hModule, lpsz16BITDLL, lpszInitName, lpszProcName,ppfn32Thunk,
 pfnUT32CallBack, lpBuff )

HANDLE      hModule;

LPCTSTR    lpsz16BITDLL;

LPCTSTR    lpszInitName;

LPCTSTR    lpszProcName;

UT32PROC *ppfn32Thunk;

FARPROC    pfnUT32CallBack;

LPVOID        lpBuff;

This routine registers a universal thunk that can be used to access 16-bit code from a Win32 application running under Win32s on Windows 3.x. Only one UT can be created per Win32 DLL. The thunk can be destroyed by calling UTUnRegister. UTRegister automatically loads the 16-bit DLL specified. It then calls the init routine and provides it a 16-bit callable routine. Win32s creates a 32-bit thunk that is used to call the 16-bit procedure in the 16-bit DLL.

Parameters

hModule

Handle of 32-bit DLL. The universal thunk provides a mechanism to "extend" a Win32 DLL into Windows 3.x. The thunk is owned by the DLL, and every DLL is limited to one thunk.

lpsz16BITDLL

Points to a null-terminated string that names the library file to be loaded. If the string does not contain a path, Win32s searches for the library using the same search mechanism as LoadLibrary on Windows 3.x.

lpszInitName

Points to a null-terminated string containing the function name, or specifies the ordinal value of the initialization function. If it is an ordinal value, the value must be in the low word and the high word must be zero. This parameter can be NULL if no initialization or callback is required.

lpszProcName

Points to a null-terminated string containing the function name, or specifies the ordinal value of the 16-bit function. If it is an ordinal value, the value must be in the low word and the high word must be zero.

ppfn32Thunk

Return value is a 32-bit function pointer (thunk to 16-bit routine) if UTRegister is successful. This function can be used to call the 16-bit routine indirectly.

pfnUT32CallBack

Address of the 32-bit callback routine. Win32s creates a 16-bit callable thunk to the 32-bit function and provides it to the initialization routine. The 32-bit routine does not need to be specified as an EXPORT function in the DEF file. No callback thunk is created if either this parameter or lpszInitName is NULL.

lpBuff

Pointer to globally allocated shared memory. Pointer is translated into 16:16 alias by the universal thunk and is passed to the initialization routine. This parameter is optional and ignored if NULL.

Returns

Function returns TRUE if the DLL is loaded and the UT16Init routine was successfully called or FALSE if an error occurred. Use the GetLastError function to obtain extended error information. Typical errors are:

ERROR_NOT_ENOUGH_MEMORY
ERROR_FILE_NOT_FOUND
ERROR_PATH_NOT_FOUND
ERROR_BAD_FORMAT
ERROR_INVALID_FUNCTION
ERROR_SERVICE_EXISTS (when the universal thunk is already registered)

Comments

Registering the universal thunk enables two capabilities for communicating between 32-bit and 16-bit routines. The first capability is to allow a Win32 application to call a 16-bit routine passing data using globally shared memory. This is a Win32 application-initiated data transfer mechanism. The second capability is to register a callback routine by which 16-bit code can callback into a 32-bit routine in a Win32 DLL. Again, shared global memory is used to transfer data.

The 16-bit DLL must export the initialization routine and the service routine, and use the following function prototypes:

DWORD FAR PASCAL UT16Init( FARPROC pfnUT32CallBack, LPVOID lpBuff );
DWORD FAR PASCAL UT16Proc( LPVOID lpBuff, DWORD dwUserDefined );

UTRegister results in Win32s loading the specified DLL with normal Windows 3.x DLL initialization occurring. Win32s then calls the initialization routine passing this function a 16:16 thunk to the 32-bit callback function. The initialization routine can return data in a global shared memory buffer. The initialization routine must return a nonzero value to indicate successful initialization.

The initialization routine must return a nonzero value to indicate successful initialization. If it fails, no thunk is created.

UTRegister returns a 32-bit thunk to the 16-bit UT16Proc. This pointer can be used in Win32 code to call the 16-bit routine:

dwUserDefinedReturn = (*pfnUT16Proc)( pSharedMemory, dwUserDefinedSend,
lpTranslationList );

The universal thunk translates the 32-bit linear address of the shared memory to a 16:16 segmented pointer, along with all the addresses listed by lpTranslationList, before passing it to the 16-bit UT16Proc routine.

The 16-bit code can call Win32 code using the callback mechanism:

dwUserDefinedReturn = (*pfnUT32CallBack)( pSharedMemory, dwUserDefinedSend,lpTranslationList );

The 32-bit callback routine should be defined as follows (but does not need to be exported in the DEF file):

DWORD WINAPI UT32CBPROC( LPVOID lpBuff, DWORD dwUserDefined );

See Also

»UTUnRegister«, LoadLibrary (16-bit version), GetProcAddress (16-bit version)


  UTUnRegister

VOID UTUnRegister( hModule )

HANDLE hModule

Requests Win32s to call FreeLibrary for the 16-bit DLL loaded by UTRegister. Also, destroys the dynamically-created universal thunk.

Parameter

hModule

Handle of 32-bit DLL which previously registered the universal thunk.

Returns

No return value.

Comments

This call allows the single dynamically created universal thunk to be destroyed and the 16-bit DLL de-referenced. Win32s cleans up these resources automatically when the Win32 DLL is freed (normally or abnormally).

See Also

»UTRegister«, FreeLibrary (16-bit version)


  UT16INIT

DWORD FAR PASCAL UT16INIT( pfnUT16CallBack, lpBuff);

UT16CBPROC pfnUT16CallBack

LPVOID lpBuff

UT16INIT name is a place holder for the application-defined function name. The actual name must be exported by including it in the EXPORTS statement in the DLL's module-definition file. This function is called only once upon calling UTRegister by the 32-bit DLL.

Parameters

pfnUT16CallBack

16-bit thunk to 32-bit callback routine, as specified at registration.

lpBuff

Pointer to general purpose memory buffer that was passed by the 32-bit code.

Returns

1 - Upon success.

0 - If failure. If the init function fails, no stub will be created and UTRegister will return 0.

See Also

»UTRegister«


  UT16PROC

DWORD FAR PASCAL UT16PROC( lpBuff, dwUserDefined );

LPVOID lpBuff

DWORD dwUserDefined

UT16PROC name is a place holder for the application-defined function name. The actual name must be exported by including it in the EXPORTS statement in the DLL's module-definition file.

Parameters

lpBuff

Pointer to general purpose memory buffer that is passed by the 32-bit code.

dwUserDefined

Available for application use.

Returns

User-defined.

See Also

»UTRegister«


  UT16CBPROC

typedef DWORD FAR PASCAL (*UT16CBPROC)(lpBuff, dwUserDefined, *lpTranslationList);

LPVOID lpBuff

DWORD dwUserDefined

LPVOID *lpTranslationList

Type of the 16-bit callable stub which is called by the 16-bit DLL. The stub translates the lpBuff pointer to a 32-bit pointer, scans the translation list, and translates all its pointers to 32-bit pointers, arranges the stack to be a 32-bit stack, and calls the 32-bit procedure in the 32-bit DLL.

Parameters

lpBuff

Pointer to general purpose memory buffer. This segmented pointer is translated to flat address and passed to the 32-bit callback procedure. This parameter is optional. If not used, it should be NULL.

dwUserDefined

Available for application use.

lpTranslationList

A pointer to an array of pointers that should be translated to segmented form. The list is terminated by a null pointer. No validity check is performed on the address except for null check. The translation list is used internally and is not passed to the 32-bit callback procedure. This parameter is optional.

Returns

User-defined.

See Also

»UTRegister«


  UT32PROC

typedef DWORD (* WINAPI UT32PROC)(lpBuff, dwUserDefined, *lpTranslationList);

LPVOID lpBuff

DWORD dwUserDefined

LPVOID *lpTranslationList

Prototype of the 32-bit callable stub which is called by the 32-bit DLL. The stub translates the lpBuff pointer to a 16:16 pointer, scans the translation list and translates all its pointers to 16:16 pointers, arranges the stack to be a 16-bit stack, and calls the 16-bit procedure in the 16-bit DLL.

Parameters

lpBuff

Pointer to general purpose memory buffer. This 32-bit pointer is translated to 16:16 form and passed to the 16-bit procedure. The segmented address provides addressability for objects up to 32KB. This parameter is optional.

dwUserDefined

Available for application use.

lpTranslationList

Pointer to an array of pointers that should be translated to segmented form. The list is terminated by a null pointer. No validity check is performed on the address except for null check. The translation list is used internally and not passed to the 16-bit procedure. This parameter is optional and if not used should be NULL.

Returns

User-defined.

See Also

»UTRegister«


  UT32CBPROC

DWORD WINAPI UT32CBPROC( lpBuff, dwUserDefined );

LPVOID lpBuff

DWORD dwUserDefined

UT32CBPROC name is a place holder for the application-defined function name. It does not have to be exported. The callback function is called indirectly by the 16-bit side.

Parameters

lpBuff

Pointer to general purpose memory buffer as passed to 16-bit callback thunk.

dwUserDefined

Available for application use.

Returns

User-defined.

Comments

Memory allocated by 16-bit code and passed to 32-bit must first be fixed in memory.

See Also

»UTRegister«


  Universal Thunk Auxiliary Services

The following are address translation services available for 16-bit code only:

UTSelectorOffsetToLinear

UTLinearToSelectorOffset


  UTSelectorOffsetToLinear

DWORD UTSelectorOffsetToLinear( lpByte )

LPVOID lpByte;

Parameter

lpByte

Translates a segmented address to flat form.

Returns

Equivalent flat address.

Comments

The base of the flat selectors used by Win32s process is not zero. If the memory is allocated by 16-bit API, it must be fixed before its address can be converted to flat form.

See Also

»UTLinearToSelectorOffset«


  UTLinearToSelectorOffset

LPVOID UTLinearToSelectorOffset( lpByte )

DWORD lpByte;

Translates a flat address to a segmented form.

Parameter

lpByte

Translates a flat address to segmented form.

Returns

Equivalent segmented address (16:16 far pointer).

Comments

The returned address guarantees addressability for objects up to 32K bytes.

See Also

»UTSelectorOffsetToLinear«, GlobalFix


  Universal Thunk Implementation Notes

This section lists implementation issues that impact application usage. The universal thunk headers are located in the \MSVC32S\WIN32S\UT directory.

•	The file W32SUT.H should be included when using universal thunk services. On the 32-bit side, W32SUT_32 should be defined before including the file. On the 16-bit side, W32SUT_16 should be defined.

•	A 32-bit DLL using universal thunk services should be linked with the library W32SUT32.LIB. A 16-bit DLL should be linked with the library W32SUT16.LIB.

•	UTRegister and UTUnRegister are exported by KERNEL32.DLL. UTLinearToSelectorOffset and UTSelectorOffsetToLinear are exported by WIN32S16.DLL

•	Only one universal thunk may exist for each Win32 DLL. Additional calls to UTRegister fail until UTUnRegister is called and the Win32 DLL is freed (normally or abnormally).

•	Memory allocated by 16-bit routines with GlobalAlloc should be fixed using GlobalFix. It must be translated to flat address before it can be used by 32-bit code. Translation is performed by the system if passed as lpBuff or by using the translation list. It can also be translated explicitly by using UTSelectorOffsetToLinear before it can be used by 32-bit code.

•	The 32-bit callback function should not be used by 16-bit interrupt handlers. The Win32 API does not support locking memory pages; therefore, an interrupt service routine which calls back into 32-bit code cannot guarantee that the code is currently paged into memory.

•	Exception handling can be done in 32-bit code only. Exceptions in 16-bit code are handled by the last 32-bit exception frame.

Note  The universal thunk has been tailored to Windows 3.x which provides a single address space for all processes and a necessity to access existing device drivers. Applications that use the universal thunk may have dependencies to Windows 3.x. The universal thunk should be considered a stepping stone to fully 32-bit applications. It is very important to isolate universal thunk code in separate DLLs. These DLLs can be more easily replaced if future operating systems offering preemptive multitasking and separate address spaces constrain universal thunk support or, like Windows NT, do not provide a universal thunk at all. The DLL can be replaced with platform-specific versions, isolating the application.


  Win32s Development with Visual C++

Visual C++ for Windows NT provides all the tools necessary for creating a Win32 application on Windows NT.

After a Win32 application has been debugged and fully tested on Windows NT, you are ready to install Win32s and your Win32 application on Windows 3.x for final testing and verification. For information on Win32s redistributable files, refer to the License Agreement included in the Visual C++ box.


  Installing Win32s Development Files

The Win32s system files, Setup Toolkit for Win32s, and the development files are provided on the Visual C++ CD in the \MSVC32S\WIN32S directory. These files are intended for use on a Windows 3.x system. Two versions of Win32s are provided to aid debugging:

•	A debug version with additional Win32s asserts and diagnostic messages.

•	The non-debug (end-user) version of Win32s.

Symbol files for both debug and non-debug systems are provided to obtain symbolic information in stack dumps and when using the kernel debugger. Also included are the sources to the setup program used in the Win32s setup program. These files should be used in conjunction with the Visual C++ compiler to create and customize your own setup program.

To install the Win32s development files onto a Windows 3.x system, first install Win32s with the Win32s Setup program, and then follow these steps:

1.	Start MS-DOS with appropriate software for accessing a local CD drive or a remote CD drive over the network.

2.	Access the Visual C++ CD-ROM by typing the drive letter and pressing enter. (For example — x:, where x: is the CD drive or network drive containing the Visual C++ CD.)

3.	Change directories to the Win32s files by typing cd \MSVC32S\WIN32S.

4.	Type install and press enter.

The INSTALL batch script provides usage information on how to specify the destination directory for the Win32s files.


  Porting Tool

Win32s allows applications to call any Win32 API function. Win32 functions that cannot be supported in Windows 3.x usually generate errors. A list of all Win32 functions supported in Win32s is located on the Visual C++ CD in the \MSVCNT\LIB\WIN32API.CSV spreadsheet. To help programmers determine whether they have inadvertently referenced unsupported Win32 functions, Visual C++ provides a porting tool (PORTTOOL.EXE) and a data file (WIN32S.DAT) that lists all unsupported Win32 functions. Load WIN32S.DAT into the porting tool, load your application source code, and let the porting tool scan your sources.

To load the file into the porting tool:

1.	Rename PORT.INI in \MSVCNT\BIN to PORT.DAT.

2.	Rename WIN32S.DAT in \MSVCNT\BIN to PORT.INI.

3.	Start Porting Tool (from the Visual C++ Program Group).

4.	Load a source file to be analyzed.

5.	Select Interactive or Background port to have unsupported Win32 functions found and highlighted.

For more information on using the porting tool, run PORTTOOL and bring up Help.


  Debugging and Testing

The Visual C++ tools running on Windows NT provide the primary development and debugging environment for creating Win32 applications. A Win32 application should be fully functional and debugged on Windows NT before running the application on Win32s. There are several debugging solutions available to help debug Win32 applications running on Windows 3.x, including CodeView for Win32s, the Windows 3.x kernel debugger, and the Win32s debugging kernel.


  CodeView for Win32s

Because there can be problems with code running on Win32s that does not occur under Windows NT, it can be useful to use Microsoft CodeView for Win32s (CVW32S). CVW32S is a full source-mode debugger that you can use to debug your programs directly on Win32s. For more information on CodeView for Win32s, see your tools documentation.


  Debugging Kernel

The Windows 3.x SDK provides two environments for debugging or testing your applications for Windows: a debugging version of the retail Windows product and a non-debugging version. The same is true for Win32s shipped with the Visual C++; there are debug and non-debug versions of Win32s.

The debugging version of Windows 3.x consists of a set of DLLs that replace the Windows core DLLs of the retail product. The debugging DLLs provide error checking and diagnostics messages that help you debug an application for Windows. Along with the DLLs, symbol files are also provided to help trace calls into Windows and Win32s.

During application development, you should use the debugging version of Windows. Switch to the non-debug versions for final application testing. To simplify switching between debug and non-debug Win32s binaries, use the SWITCH.BAT file located in the \MSVC32S\WIN32S\BIN directory. Usage information is provided by invoking this batch file with no parameters.

Note  Do not ship the debugging version of the Win32s files with your application. In addition to the performance overhead present in the debug versions, the license agreement on Win32s Redistributables only covers the non-debug files.

Visual C++ provides debugging versions of the Win32s DLLs. It is necessary to obtain a Windows 3.x SDK for the Windows 3.x debugging DLLs. The Windows 3.x SDK also provides additional details on how to use the debug DLLs.


  Shipping Win32s with Win32 Applications

Win32s is not built into Windows 3.x, so it is necessary for software vendors to ship and install Win32s along with the Win32 application in order to work on Windows 3.x. The key feature of Win32s is to allow software developers to ship Win32 applications today for Windows 3.x and Windows NT that will continue to install and work well on future Windows operating systems. Therefore, it is necessary to create setup programs today that properly handle various setup issues when installing on current and future operating systems.

To ship a single Win32 application that correctly installs on Windows 3.x and Windows NT, a setup program should at minimum, be able to:

•	Install Win32s files on Windows 3.x systems running in Enhanced Mode.

•	Disallow installation of Win32s files if Win32s is already installed (version check).

•	Install only Win32 applications on Windows NT (do not install Win32s files).

These minimum installation requirements assure that Win32s files are only installed on systems that require them (Windows 3.x) and not Windows NT, because Windows NT is capable of running Win32 applications as-is.

A Win32s setup program should meet the following criteria:

•	Detects Windows 3.0 or lower, provide an informative error messages, and disallows the installation of Win32s.

•	Detects Windows 3.x running in standard mode, gives informative error message, and disallows the installation of Win32s.

•	Be prepared for possible future releases of Windows. Win32s should not be installed on any Windows version 4.0 or later since such versions should be able to run Win32 applications directly.

•	Detects the presence of Windows NT and only installs the Win32 application, not Win32s, because Windows NT runs Win32 binaries directly.

•	If the setup program detects that Windows NT is running, tests whether this is a RISC-based system. If RISC-based, setup should fail with appropriate message (or install R4000 or DEC Alpha version of the Win32 application).

•	Setup should check for presence version of Win32s and only install a later version of Win32s.

•	Any future updates to Win32s will have higher version numbers, so that new versions can overwrite earlier releases.

While the list of setup issues seems long, a simple set of tests can detect these conditions. It is necessary to use a 16-bit installation program to install Win32s because Win32s isn't necessarily running yet. It is recommended that you use a Windows 3.x program (rather than MS-DOS). Several APIs can be called from a Windows 3.x program to determine the version of the system, the version of Win32s and the platform:

•	GetVersion: Determines Windows version number of Windows (for MS-DOS), Windows NT (returns 3.1), and past and future versions of Windows.

•	GetWinFlags: Flag indicates whether Windows 3.x application is running on Windows NT. Test for 0x00004000: if set, then the program is running on Windows NT.

•	GetWindowsMode: Use to determine if the program is running on a RISC-based system. Windows NT runs Windows 3.x applications in standard mode using an emulator or RISC systems. Therefore, the setup program should first determine if the system is Windows NT using GetWinFlags (as discussed previously), and then use GetWindowsMode to determine if RISC system and fail installation of x86-based Win32 application.

Please refer to the License Agreement for information concerning Win32s Redistributable Files.


  Win32 and Win32s Differences

The following programming information lists Windows 3.x and Windows NT differences that programmers should be aware of when designing Win32 applications that run on both platforms. Reviewing these differences can save time developing and debugging applications.


  Win32s Version 1.0 Unsupported Features

The following features are being considered for a future release of Win32s:

•	Named pipe support

•	MAPI (Mail APIs)

•	ODBC (Open Database Connectivity)

The following Win32 features are not currently planned for Win32s:

•	Console APIs

•	Unicode APIs

•	Security APIs

•	Communication APIs

•	Asynchronous File I/O

•	Threads

•	Paths (graphics object)

•	Enhanced Metafiles

•	Bezier curves


Window Manager User
  Window Manager (User)

Win32s relies on Windows 3.x to provide standard dialog controls such as list boxes, combo boxes, and edit controls. Win32s translates messages between the controls and the Win32 application.

Controls have size limitations that do not exist on Windows NT. An edit control, for example, is limited to 32K of text; list boxes store data in one 64K heap. Therefore, a Win32 application can create a large file in an edit control in Windows NT and not be able to read the file back into the same edit control when the Win32 application is run with Windows 3.x.

Controls support specifying limits on the amount of information they can hold, such as EM_SETLIMIT for edit controls. One solution is to specify a lowest common denominator for controls to ensure compatibility across platforms. Other solutions are application specific.

Win32s does not support EM_SETHANDLE and EM_GETHANDLE. These messages allow the sharing of local memory handles between an application and the system. In Win32s, an application's local heap is 32 bits and is allocated from the global heap, so Windows 3.x cannot interpret a local handle. Text for multiline edit controls is stored in the 16-bit local heap. This means that the amount of edit control text is limited to somewhat less than 64K. To read and write multiline edit control text, an application should use the WM_GETTEXT and WM_SETTEXT messages.

Any private application message must be defined above WM_USER+0x100. This ensures that there is no collision between private messages and dialog control messages on Windows 3.x.

When calling the PeekMessage function, a Win32 application should not filter any messages for Windows 3.x private window classes (button, edit, scroll bar, and so on.). The messages for these controls are mapped to different values in Win32, and checking for the necessity of mapping is a time-consuming operation.

Win32s child window identifiers must be sign-extended 16-bit values. This precludes using 32-bit pointer values as child window IDs.

Windows NT dynamically grows the message queue size. Windows 3.x has a default message queue size of eight which can be changed by calling SetMessageQueue. This call is supported in Win32s and is a NOP on Windows NT.

SetClipbrdData must be called with global handles; otherwise, the data cannot be accessed by other applications.

Applications specify the return value for the DialogBox function by way of the nResult parameter to the EndDialog function. This parameter is of type int, which is 32 bits for Win32 applications. However, this value is thunked by Win32s to the Windows 3.x EndDialog function, which will truncate it to 16 bits. Win32s sign-extends the return code from DialogBox.

Resource IDs (identifiers in resource files) must be 16-bit values.

The resource table size is limited to 32K (not including the resource data).


  Graphics (GDI)

Windows 3.x has a limit of five cached device contexts (DCs). The GetDC call obtains a cached DC in Windows 3.x; therefore, it is important to call ReleaseDC before checking the message queue. Otherwise, another application may be scheduled and there will be one less cached DC for all applications in the system. Windows NT does not have a cached DC limit, but applications should not waste DCs. It is important to follow the GetDC/ReleaseDC model for compatibility on both platforms and good memory management.

Windows 3.x allows drawing objects (pens and brushes) to be deleted while still selected into a DC. However, the memory allocated for the drawing object remains allocated until the process terminates. Windows NT fails the DeleteObject call. Applications should not delete selected objects or they may slowly use up system resources while the application is running on Windows 3.x.

Windows 3.x has a 16-bit world coordinate system. Windows NT supports a 32-bit world coordinate system. Therefore, it is necessary to use the Windows 3.x limit in developing a Win32 graphics application that can run with both Windows 3.x and Windows NT.


  System Services (Kernel)

Win32s processes that are started by Windows 3.x applications should be launched using WinExec. LoadModule cannot start a Win32s process.

Memory-mapped files support named shared memory only in this release. There is no support for backing memory-mapped files to disk. Therefore, a memory-mapped file's maximum size is limited by Windows memory.

VirtualAlloc provides a feature on Windows NT that allows the process to request the memory allocation at a specified virtual address. This is supported on Win32s, but applications should not depend on address range that is available. Windows NT allocates memory in the low 2 GB address space, and Win32s allocates memory in the high 2 GB address space. Applications can query the address space using GetSystemInfo.

The precision of the time of a file is two seconds (this is an MS-DOS limitation).

Win32 applications and DLLs should be linked with 4K alignment. This is the default for the linker that ships with Visual C++. 64K alignment is supported, but 4K is more efficient for the memory manager in the shared 2 GB address space of Windows 3.x.


Chapter 10: Using Precompiled Headers
  Chapter 10  Using Precompiled Headers

The Microsoft C and C++ compilers provide options for precompiling any C or C++ code — including inline code. Using this performance feature, you can compile a stable body of code, store the compiled state of the code (including information for the debugger) in a file, and during subsequent compilations combine the precompiled code with code that is still under development. Each subsequent compilation is faster by the time not required to recompile the stable code. Use of the fast compile option (/f),  the compiler's default action, further speeds compilation.

With Microsoft Visual C++, you can precompile any C or C++ code; you are not limited to precompiling only header files. To precompile headers, you can choose one of two approaches:

•	Automatic precompiling. Simply use one option (/YX) and let the compiler decide when to create and use precompiled headers.

•	Manual precompiling. Use this when you know that your source files use common sets of header files but do not include them in the same order, or when you want to include source code in your precompilation.

The first choice is quick and easy. The second requires some planning, but it offers significantly faster compilations if you precompile source code other than simple header files.


  When to Precompile Source Code

Precompiled code is useful during the development cycle to reduce compilation time, especially if:

•	You always use a large body of code that changes infrequently.

•	Your program comprises multiple modules, all of which use a standard set of include files and the same compilation options. In this case, all include files can be precompiled into one precompiled header.

The first compilation — the one that creates the precompiled header file — takes a bit longer than subsequent compilations. Subsequent compilations can proceed more quickly by including the precompiled code.

You can precompile both C and C++ programs. In C++ programming, it is common practice to separate class interface information into header files. These header files can later be included in programs that use the class. By precompiling these headers, you can reduce the time a program takes to compile.

Note  Although you can use only one precompiled header (.PCH) file per source file, you can use multiple .PCH files in a project.


  Creating and Using Precompiled Headers

Either way you can precompile code — automatically or manually — stores the resulting precompiled code in a file called a precompiled header.

The easiest way to precompile code is to simply use the automatic precompiled-header option (/YX) on the command line. The /YX option causes the compiler to either create a precompiled header with a default name of MSVC.PCH or use a precompiled header named MSVC.PCH if one exists. You can also control the name of the precompiled header that is created or used with the /Fp ("specify precompiled header filename") option.

The other way to precompile code is to use the manual precompiled-header options /Yc ("create precompiled header") and /Yu ("use precompiled header"). Use the /Yc option to create a precompiled header. When used with the optional hdrstop pragma, you can use /Yc to precompile both header files and source code. You can also use the /Fp option with the /Yc and /Yu options to provide an alternative name for the precompiled header.

The following sections describe the precompiled header options and the »hdrstop« pragma in more detail. The section, »Using Precompiled Headers in a Project« includes an example makefile and the code that it manages. For further examples using precompiled headers, see the makefiles used to build the program examples that ship with the Microsoft Foundation Class Library.


  Precompiled Header Compiler Options

The compiler options described in the following sections control the creation and use of precompiled headers. »The hdrstop pragma« gives you extra control over the behavior of these options.


  The /YX (Automate Precompiled Header) Option

The /YX ("Automate Precompiled Header") option instructs the compiler to use a precompiled header file with a default name of MSVC.PCH if it exists or to create one if it does not. The file is created in the current directory. You can use the /Fpfilename option to change the default name (and placement) of the precompiled header. The following command line uses /YX to create a precompiled header named MSVC.PCH:

CL /YX MYPROG.CPP

The following command line creates a precompiled header named MYPROG.PCH and places it in the \PROJPCH directory:

CL /YX /Fp\PROJPCH\MYPROG.PCH MYPROG.CPP

Using the /YX option limits precompilation to header files only. The precompiled header is created when the compiler encounters the first declaration, definition, hdrstop pragma, or #line directive that occurs in the source file. In a subsequent compilation, the precompiled header is used at the point in a source file where the compiler makes its final consistency check. For more information, see »Consistency Rules for /YX«.

The actual set of header files precompiled with /YX is determined by the compiler, which may use a subset of the header files available to make the resulting precompiled header useful in more cases.

Although it is usually best to let the compiler determine which header files to use, you can selectively precompile header files by placing a hdrstop pragma in the source file between two #include directives. All header files before the hdrstop pragma are precompiled; those after are not. When used with /YX, any filename specified with the hdrstop pragma is ignored. If any subsequent compilation using the precompiled header does not find an identical hdrstop pragma at the same point in the source file, the compiler builds a new precompiled header. For more information, see »The hdrstop Pragma«.

Note  If either /Yc or /Yu is specified with /YX, a warning is issued. In such cases, /YX is ignored, and /Yc or /Yu takes precedence.

Use of the /YX option implies the /Yd ("Duplicate Debugging Information in all Object Files") option.


  Debugging Code Compiled with /YX

You can use either the /Zi or the /Z7 option with the /YX option to generate debugging information for CodeView or the Visual Workbench integrated debugger.

It is recommended that you use the /Zi option unless you need /Z7 to maintain compatibility with Microsoft C/C++ version 7.0. The /Zi option places the generated debugging information into a program database (PDB); a PDB speeds linking during the debugging process. The /Yd option, which places all debugging information into every object file created using a precompiled header, is ignored unless used with /Z7.

Table 10.1 summarizes results obtained from using the /Zi, /Z7, and /Yd options in combination with /YX.

Table 10.1    Results of Combining Debugging Options with /YX

Option combination	Result
/Zi	Debugging information for both the precompiled header and the rest of the source code is placed in a program database (PDB) with the default name of MSVC.PDB.
/Zi /Yd	/Yd is ignored. Debugging information for both the precompiled header and the rest of the source code is placed in a PDB with the default name of MSVC.PDB.
/Z7	Debugging information for both the precompiled header and the rest of the source code is placed in every object file created using the precompiled header.
/Z7 /Yd	Debugging information for both the precompiled header and the rest of the source code is placed in every object file created using the precompiled header.
For more information on PDBs, /Zi, and /Z7, see Chapter 1, "CL Command Reference," in Command-Line Utilities User's Guide; this chapter discusses the Visual C++ compiler, a file called CL.EXE. For information on /Yd, see »The /Yd (Duplicate Debugging Information in All Object Files) Option«.


  Consistency Rules for /YX

If a precompiled header file exists (either MSVC.PCH or one specified by /Fpfilename), it is compared to the current compilation for consistency. Unless the following requirements are met, a new precompiled header file is created and the new file overwrites the old:

•	The current compiler options must match those specified when the precompiled header was created.

•	The current working directory must match that specified when the precompiled header was created.

•	The order and values of all #include and #pragma directives must match those specified when the precompiled header was created. These, along with #define directives, are checked one by one as they appear during subsequent compilations that use the precompiled header. The values of #define directives must match. However, a sequence of #define directives need not occur in exactly the same order because there are no semantic order dependencies for #define directives. The #pragma directives must be nearly identical, with a few exceptions; for example, multiple spaces outside of strings are treated as a single space to allow for different programming styles.

•	The value and order of include paths specified on the command line with /I options must match those specified when the precompiled header was created.

•	The time stamps of all the header files (all files specified with #include directives) used to build the precompiled header must match those that existed when the precompiled header was created.


  The /Yc (Create Precompiled Header) Option

The /Yc ("Create Precompiled Header") option instructs the compiler to create a precompiled header file that represents the state of compilation at a certain point. The syntax of this option is:

/Yc[filename]

Using /Yc with a Filename

If you specify a filename with the /Yc option, the compiler precompiles all code up to and including the specified file. The precompiled code is saved in a file with a name created from the base name of the file specified with the /Yc option and a .PCH extension. You can also use the /Fp option, described in »The /Fp (Specify Precompiled Header Filename) Option«, to specify a name for the resulting precompiled header file.

Consider the following code:

#include <afxwin.h>   // Include header for class library
#include "resource.h" // Include resource definitions
#include "myapp.h"    // Include information specific to this
                      //   application
...

When compiled with the command

CL /YcMYAPP.H PROG.CPP

the compiler saves all the results of processing AFXWIN.H, RESOURCE.H, and MYAPP.H in a precompiled header file called MYAPP.PCH.

Using /Yc Without a Filename

If you specify the /Yc option with no filename, the resulting precompiled header saves the compilation state at the end of the base source file or, if the base file contains a hdrstop pragma, at the place where the hdrstop pragma occurs.

The resulting .PCH file has the same base name as your base source file unless you specify a different filename using the hdrstop pragma or the /Fp option.

Note  If /Ycfilename and /Yufilename options occur on the same command line and both reference the same filename, /Ycfilename takes precedence, precompiling all code up to and including the named file. This feature simplifies the writing of makefiles.


  The /Yu (Use Precompiled Header) Option

The /Yu ("Use Precompiled Header") option instructs the compiler to use an existing precompiled header in the existing compilation. The syntax of this option is:

/Yu[filename]

Using /Yu with a Filename

The filename argument is the name of a header file, which is included in the source file using an #include preprocessor directive. The include file's name must be the same for both the /Yc option that creates the precompiled header and any subsequent /Yu option indicating use of the precompiled header.

For /Yc, filename specifies the point at which precompilation stops; the compiler precompiles all code though filename and names the resulting precompiled header using the base name of the include file and an extension of .PCH. For /Yu, the compiler assumes that all code occurring before filename is precompiled. The compiler skips to the specified #include directive, uses the code contained in the precompiled header file, and then compiles all code after filename.

Consider the following code:

#include <afxwin.h>   // Include header for class library
#include "resource.h" // Include resource definitions
#include "myapp.h"    // Include information specific to this
                      //   application
...

When compiled with the command line

CL /YuMYAPP.H PROG.CPP

the compiler does not process the three #include statements but uses the precompiled code from the precompiled header MYAPP.PCH, thereby saving the time involved in preprocessing all three of the files (and any files they might include).

Using /Yu Without a Filename

When you specify the /Yu option without a filename, your source program must contain a hdrstop pragma. The compiler skips to the location of that pragma and uses the content of the precompiled header file specified by the pragma. If the hdrstop pragma does not specify a filename, the name is derived from the base name of the source file with the .PCH extension. You can also use the /Fp option to specify a different .PCH file.

If you specify the /Yu option without a filename and fail to specify a hdrstop pragma, an error message is generated and the compilation is unsuccessful.

Note  If the Ycfilename and /Yufilename options occur on the same command line and both reference the same filename, /Ycfilename takes precedence, precompiling all code up to and including the named file. This feature simplifies the writing of makefiles.


  Debugging Code Compiled with /Yc or /Yu

You can use either the /Zi or the /Z7 option with the /Yc and /Yu options to generate debugging information compatible with CodeView or the debugger that is integrated with the Visual Workbench.

It is recommended that you use the /Zi option unless you need /Z7 to maintain compatibility with Microsoft C/C++ version 7.0. The /Zi option places the generated debugging information into a program database (PDB); a PDB speeds linking during the debugging process.

The /Yd option, which places all debugging information into every object file created using a precompiled header, is ignored unless used with /Z7.

Table 10.2 summarizes results obtained from using the /Zi, /Z7, and /Yd options in combination with /Yc and /Yu.

Table 10.2    Results of Combining Debugging Options with /Yc or /Yu

Option combination	Result
/Zi	Debugging information for both the precompiled header and the rest of the source code is placed in a program database (PDB) with the default name of MSVC.PDB.
/Zi /Yd	/Yd is ignored. Debugging information for both the precompiled header and the rest of the source code is placed in a PDB with the default name of MSVC.PDB.
/Z7	Debugging information for both the precompiled header and the rest of the source code is placed in the first object file created using the precompiled header.
/Z7 /Yd	Debugging information for both the precompiled header and the rest of the source code is placed in every object file created using the precompiled header.
For more information on PDBs, /Zi, and /Z7, see Chapter 1, "CL Command Reference," in Command-Line Utilities User's Guide. For information on /Yd, see "»The Yd (Duplicate Debugging Information in All Object Files) Option«.


  The hdrstop Pragma

The hdrstop pragma gives you additional control over precompilation filenames and over the place at which the compilation state is saved. The syntax of the hdrstop pragma is

#pragma hdrstop [("filename")]

where filename is the name of the precompiled header file to use or create (depending on whether /Yu or /Yc is specified). If the filename does not contain a path specification, the precompiled header file is assumed to be in the current directory. Any filename is ignored when the automatic precompiled header option (/YX) is specified.

Note  The hdrstop pragma is ignored unless either the /YX option is specified or the /Yu or /Yc compiler option is specified without a filename.

For the /Yc and the /Yu options, if neither of the two compilation options nor the hdrstop pragma specifies a filename, the base name of the source file is used as the base name of the precompiled header file. This differs from the precompiled-header naming conventions of /YX; with /YX, the default name of the precompiled header is MSVC.PCH.

The filename specified in the hdrstop pragma is a string and is therefore subject to the constraints of any C or C++ string. In particular, you must escape backslashes ( \ ) when specifying paths. For example:

#pragma hdrstop( "c:\\c700\\include\\myinc.pch" )

You can also use preprocessing commands to perform macro replacement as follows:

#define INCLUDE_PATH "c:\\c700\\include\\"
#define PCH_FNAME "PROG.PCH"
.
.
.
#pragma hdrstop( INCLUDE_PATH PCH_FNAME )

Placement of the hdrstop Pragma

The following rules govern where the hdrstop pragma can be placed:

•	It must appear outside any data or function declaration or definition.

•	It must be specified in the base file, not within a header file.

Consider the following example:

#include <windows.h>                 // Include several files
#include "myhdr.h"

--inline Disp( char *szToDisplay )   // Define an inline function
{
    ...                              // Some code to display string
}
#pragma hdrstop

In this example, the hdrstop pragma appears after two files have been included and an inline function has been defined. This might, at first, seem to be an odd placement for the pragma. Consider, however, that using the manual precompilation options, /Yc and /Yu, with the hdrstop pragma makes it possible for you to precompile entire source files — even inline code. The Microsoft compiler does not limit you to precompiling only data declarations.


  Consistency Rules for /Yc and /Yu

When you use a precompiled header created using the /Yc option, the compiler compares the current compilation environment to the one that existed when you created the .PCH file. You should take care to specify a environment consistent with the previous one (using consistent compiler options, pragmas, and so on) for the current compilation. If the compiler detects an inconsistency, it issues a warning and identifies the inconsistency where possible. Such warnings don't necessarily indicate a problem with the .PCH file; they simply warn you of possible conflicts. The following sections explain the consistency requirements for precompiled headers.

Compiler Option Consistency

Table 10.3 lists compiler options that might trigger an inconsistency warning when using a precompiled header.

Table 10.3    Compilation Option Consistency

Option	Name	Rule
/AX or /Axxx	Specify memory model	Must be the same between the compilation that created the precompiled header and the current compilation. If these options differ, an error message results.
/D	Define constants and macros	Must be the same between the compilation that created the precompiled header and the current compilation. The state of defined constants is not checked, but unpredictable results can occur if your files depend on the values of the changed constants.
/E or /EP	Copy preprocessor output to standard output	Precompiled headers do not work with the /E or /EP option.
/Fr or /FR	Generate Microsoft Source Browser information	For the /Fr and /FR options to be valid with the /Yu option, they must also have been in effect when the precompiled header was created. Subsequent compilations that use the precompiled header also generate Source Browser information. Browser information is placed in a single .SBR file and is referenced by other files in the same manner as CodeView information. You cannot override the placement of Source Browser information.
/GA, /GD, /GE, /Gw, or /GW	Windows protocol options	Must be the same between the compilation that created the precompiled header and the current compilation. If these options differ, a warning message results.
/Zi	Generate complete debugging information	If this option is in effect when the precompiled header is created, subsequent compilations that use the precompilation can use that debugging information. If /Zi is not in effect when the precompiled header is created, subsequent compilations that use the precompilation and the /Zi option trigger a warning. The debugging information is placed in the current object file, and local symbols defined in the precompiled header are not available to the debugger.
Note  The precompiled header facility is not intended for use with a file that is not a C or C++ program.

Include Path Consistency

A precompiled header created with /Yc does not contain information about the include path that was in effect when you created the .PCH file. When you use a .PCH file, the compiler always uses the include path specified in the current compilation.

Source File Consistency

When you use a precompiled header, the compiler ignores all preprocessor directives (including pragmas) that appear before the hdrstop pragma. The compilation specified by such preprocessor directives must be the same as the compilation used to create the precompiled header file.

Pragma Consistency

Pragmas processed during the compilation of a precompiled header usually affect the file in which the precompiled header is subsequently used. The following pragmas affect only the code within the .PCH file; they do not affect code that subsequently uses the .PCH file:

comment	pagesize
linesize	skip
message	subtitle
page	title
The following pragmas are retained as part of a precompiled header. They do affect the remainder of a compilation that uses the precompiled header:

alloc_text	inline_recursion
auto_inline	intrinsic
check_pointer	loop_opt
check_stack	native_caller
code_seg	optimize
data_seg	pack
function	same_seg
inline_depth	warning


  The /Yd (Duplicate Debugging Information in All Object Files) Option

Use the /Yd ("Duplicate Debugging Information in all Object Files") option with the /Z7 ("Generate Microsoft C/C++ Version 7.0 Compatible CodeView Information") option to place complete debugging information in all object files that are ultimately created from the resulting precompiled header (.PCH) file. The /Yd option takes no argument.

Note  The /Yd option is obsolete with the advent of the new program database (PDB) files created by the "Generate Complete Debugging Information" (/Zi) option. The /Yd option is retained on /Zi, /Zd, and /Z7 for backward compatibility with Microsoft C/C++ version 7.0. For more information, see Chapter 1, "CL Command Reference," in Command-Line Utilities User's Guide.

Storing complete debugging information in every object file, including the information that describes only the .PCH file, is sometimes convenient, but it slows compilation and requires considerable disk space.

In contrast, when /Yc and /Z7 are used without /Yd, the compiler stores debugging information describing the .PCH file in the first object file created from that file. The compiler does not insert this common debugging information into object files subsequently created from the .PCH file; rather, it inserts cross-references to the debugging information. Therefore, no matter how many object files use the .PCH file, only one object file contains the common debugging information.

Although this default behavior results in faster build times and reduces disk-space demands, it is undesirable if a small change requires rebuilding the object file containing the common debugging information. In this case, the compiler must rebuild all object files containing cross-references to the original object file. Also, it is difficult to rely on cross-references to a single object file if a common .PCH file is used by different projects.

Examples

Suppose you have two base files, F.CPP and G.CPP, each containing these #include statements:

#include "windows.h"
#include "etc.h"

The following command creates the precompiled header file ETC.PCH and the object file F.OBJ:

CL /YcETC.H /Z7 F.CPP

The object file F.OBJ includes type and symbol information for WINDOWS.H and ETC.H (and any other header files they include). Now you can use the precompiled header ETC.PCH to compile the source file G.CPP:

CL /YuETC.H /Z7 G.CPP

The object file G.OBJ does not include the debugging information for the precompiled header but simply references that information in the F.OBJ file. Note that you must link with F.OBJ.

If your precompiled header was not compiled with /Z7, you can still use it in later compilations using /Z7. However, the debugging information is placed in the current object file, and local symbols for functions and types defined in the precompiled header are not available to the debugger.


  The /Fp (Specify Precompiled Header Filename) Option

The /Fp option gives you extra control over the name of the precompiled header (.PCH) file. Use it to specify a precompiled header filename that is different from the default. For example, use the following command to rename the default MSVC.PCH file created and used by the "Automate Precompiled Header" option:

CL /YX /FpMYPCH.PCH PROG.CPP

This command causes the compiler either to use a precompiled header named MYPCH.PCH if it exists or to create the file if it does not exist.

If you want to create a precompiled header file for a debugging version of your program and you are compiling both header files and source code, you can specify a command such as:

CL /DDEBUG /Zi /Yc /FpDPROG.PCH PROG.CPP

This command assumes the existence of a hdrstop pragma in PROG.CPP and creates a precompilation of all code up to the hdrstop pragma. The precompiled code is stored in a file called DPROG.PCH. If you need a release version in parallel, you simply change the compilation command to:

CL /Yc /FpRPROG.PCH PROG.CPP

This command creates a separate precompilation of all code up to the hdrstop pragma and stores it in RPROG.PCH.

You can also use the /Fp option with the /Yu and /YX options.


  Using Precompiled Headers in a Project

Previous sections in this chapter present an overview of precompiled headers and reference material describing the manual precompiled-header options, /Yc and /Yu, the /Fp option, and the hdrstop pragma. This section describes a method for using the manual precompiled-header options in a project; it ends with an example makefile and the code that it manages.

For another approach to using the manual precompiled-header options in a project, study the makefile located in the \MSVC\MFC\SRC directory that is created during the default setup of Visual C++. The makefile takes a similar approach to the one presented in this section but makes greater use of Microsoft Program Maintenance Utility (NMAKE) macros to offer greater control of the build process.

Note  The techniques presented in this section do not apply when using the Automate Precompiled Header option (/YX).


  The Build Process

The code base of a software project is usually contained in multiple C or C++ source files, object files, libraries, and header files. Typically, a makefile coordinates the combination of these elements into an executable file. »Figure 10.1« shows the structure of a makefile that uses a precompiled header file. Both the NMAKE macro names and the filenames in this diagram coincide with those in the example code found at the end of this section.

»Figure 10.1« uses three diagrammatic devices to show the flow of the build process. Named rectangles represent each file or each macro; the three macros represent one or more files. Shaded areas represent each compile or link action. Arrows show which files and macros are combined during the compilation or linking process.

Beginning at the top of the diagram, both STABLEHDRS and BOUNDRY are NMAKE macros in which you list files not likely to need recompilation. These files are compiled using the command string

CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp

only if the precompiled header file (STABLE.PCH) does not exist or if you make changes to the files listed in the two macros. In either case, the precompiled header file will contain only code from the files listed in the STABLEHDRS macro. List the last file you want precompiled in the BOUNDRY macro.

The files you list in these macros can be either header files or C or C++ source files. (A single .PCH file cannot be used with both C and C++ modules.) Note that you can use the hdrstop macro to stop precompilation at some point within the BOUNDRY file. The hdrstop pragma is discussed in »The hdrstop Pragma«.

Continuing down the diagram, APPLIB.OBJ represents the support code used in your final application. It is created from APPLIB.CPP, the files listed in the UNSTABLEHDRS macro, and precompiled code from the precompiled header.

MYAPP.OBJ represents your final application. It is created from MYAPP.CPP, the files listed in the UNSTABLEHDRS macro, and precompiled code from the precompiled header.

Finally, the executable file (MYAPP.EXE) is created by linking the files listed in the OBJS macro (APPLIB.OBJ and MYAPP.OBJ).


  Sample Makefile

The following makefile uses macros and an !IF, !ELSE, !ENDIF flow-of-control command structure to simplify its adaptation to your project.

# Makefile : Illustrates the effective use of precompiled
#            headers in a project
# Usage:     NMAKE option
# option:    DEBUG=[0|1]
#            (DEBUG not defined is equivalent to DEBUG=0)
#
OBJS = myapp.obj applib.obj
# List all stable header files in the STABLEHDRS macro.
STABLEHDRS = stable.h another.h
# List the final header file to be precompiled here:
BOUNDRY = stable.h

# List header files under development here:
UNSTABLEHDRS = unstable.h
# List all compiler options common to both debug and final
# versions of your code here:
CLFLAGS = /c /W3
# List all linker options common to both debug and final
# versions of your code here:
LINKFLAGS = /NOD /ONERROR:NOEXE
!IF "$(DEBUG)" == "1"
CLFLAGS   = /D_DEBUG $(CLFLAGS) /Od /Zi /f
LINKFLAGS = $(LINKFLAGS) /COD
LIBS      = slibce
!ELSE
CLFLAGS   = $(CLFLAGS) /Oselg /Gs
LINKFLAGS = $(LINKFLAGS)
LIBS      = slibce
!ENDIF
myapp.exe: $(OBJS)
    link $(LINKFLAGS) @<<
$(OBJS), myapp, NUL, $(LIBS), NUL;
<<
# Compile myapp
myapp.obj  : myapp.cpp $(UNSTABLEHDRS)  stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    myapp.cpp
# Compile applib
applib.obj : applib.cpp $(UNSTABLEHDRS) stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    applib.cpp
# Compile headers
stable.pch : $(STABLEHDRS)
    $(CPP) $(CLFLAGS) /Yc$(BOUNDRY)    applib.cpp myapp.cpp

Besides the STABLEHDRS, BOUNDRY, and UNSTABLEHDRS macros shown in »Figure 10.1«, this makefile also provides a CLFLAGS macro and a LINKFLAGS macro. You must use these macros to list compiler and linker options that apply whether you build a debug or final version of the application's executable file. There is also a LIBS macro where you list the libraries required by your project.

The makefile also uses !IF, !ELSE, !ENDIF to detect whether you define a DEBUG symbol on the NMAKE command line:

NMAKE DEBUG=[1|0]

This feature makes it possible for you to use the same makefile during development and for the final versions of your program — use DEBUG=0 for the final versions. The following command lines are equivalent:

NMAKE
NMAKE DEBUG=0


  The Example Code

The following examples are used in the makefile described previously. Note that the comments contain important information.

// ANOTHER.H : Contains the interface to code that is not
//             likely to change.
//
#ifndef --ANOTHER_H
#define --ANOTHER_H
#include<iostream.h>
void savemoretime( void );
#endif // --ANOTHER_H

// STABLE.H : Contains the interface to code that is not likely
//            to change. List code that is likely to change
//            in the makefile's UNSTABLEHDR macro.
//
#ifndef --STABLE_H
#define --STABLE_H
#include<iostream.h>
void savetime( void );
#endif // --STABLE_H

// UNSTABLE.H : Contains the interface to code that is
//              likely to change. As the code in a header
//              file becomes stable, remove the header file
//              from the makefile's UNSTABLEHDR macro and list
//              it in the STABLEHDR macro.
//
#ifndef --UNSTABLE_H
#define --UNSTABLE_H
#include<iostream.h>
void notstable( void );
#endif // --UNSTABLE_H

// APPLIB.CPP : This file contains the code that implements
//              the interface code declared in the header
//              files STABLE.H, ANOTHER.H, and UNSTABLE.H.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
// The following code represents code that is deemed stable and
// not likely to change. The associated interface code is
// precompiled. In this example, the header files STABLE.H and
// ANOTHER.H are precompiled.
void savetime( void )
    { cout << "Why recompile stable code?\n"; }
void savemoretime( void )
    { cout << "Why, indeed?\n\n"; }
// The following code represents code that is still under
// development. The associated header file is not precompiled.
void notstable( void )
    { cout << "Unstable code requires"
            << " frequent recompilation.\n"; }

// MYAPP.CPP : Sample application
//             All precompiled code other than the file listed
//             in the makefile's BOUNDRY macro (stable.h in
//             this example) must be included before the file
//             listed in the BOUNDRY macro. Unstable code must
//             be included after the precompiled code.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
void main( void )
{
    savetime();
    savemoretime();
    notstable();
}


Chapter 11: Using the Inline Assembler
  Chapter 11  Using the Inline Assembler

This chapter explains how to use the Visual C/C++ inline assembler with Intel x86-series compatible processors (such as the AMD386 and the i486™). Assembly language serves many purposes, such as improving program speed, reducing memory needs, and controlling hardware. You can use the inline assembler to embed assembly-language instructions directly in your C and C++ source programs without extra assembly and link steps. The inline assembler is built into the compiler — you don't need a separate assembler such as the Microsoft Macro Assembler (MASM).


  Advantages of Inline Assembly

Because the inline assembler doesn't require separate assembly and link steps, it is more convenient than a separate assembler. Inline assembly code can use any C variable or function name that is in scope, so it is easy to integrate it with your program's C code. Because the assembly code can be mixed inline with C or C++ statements, it can do tasks that are cumbersome or impossible in C or C++.

The uses of inline assembly include:

•	Writing functions in assembly language.

•	Spot-optimizing speed-critical sections of code.

•	Making direct hardware access for device drivers.

•	Writing prolog and epilog code for "naked" calls.

Inline assembly is a special-purpose tool. If you plan to port an application to different machines, you'll probably want to place machine-specific code in a separate module. Because the inline assembler doesn't support all of MASM's macro and data directives, you may find it more convenient to use MASM for such modules.


  The __asm Keyword

The __asm keyword invokes the inline assembler and can appear wherever a C or C++ statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces. The term "__asm block" here refers to any instruction or group of instructions, whether or not in braces.

The following code fragment is a simple __asm block enclosed in braces:

__asm
{
   mov al, 2
   mov dx, 0xD007
   out al, dx
}

Alternatively, you can put __asm in front of each assembly instruction:

__asm mov al, 2
__asm mov dx, 0xD007
__asm out al, dx

Because the __asm keyword is a statement separator, you can also put assembly instructions on the same line:

__asm mov al, 2   __asm mov dx, 0xD007   __asm out al, dx

All three examples generate the same code, but the first style (enclosing the __asm block in braces) has some advantages. The braces clearly separate assembly code from C or C++ code and avoid needless repetition of the __asm keyword. Braces can also prevent ambiguities. If you want to put a C or C++ statement on the same line as an __asm block, you must enclose the block in braces. Without the braces, the compiler cannot tell where assembly code stops and C or C++ statements begin. Finally, because the text in braces has the same format as ordinary MASM text, you can easily cut and paste text from existing MASM source files.

The braces enclosing an __asm block don't affect variable scope, as do braces in C and C++. You can also nest __asm blocks; nesting does not affect variable scope.


  Using Assembly Language in __asm Blocks

The inline assembler has much in common with other assemblers. For example, it accepts any expression that is legal in MASM. This section describes the use of assembly-language features in __asm blocks.

Instruction Set

The inline assembler supports the full instruction set of the Intel 486 processor. Additional instructions supported by the target processor can be created with the _emit instruction. See »The _emit Pseudoinstruction«.

Expressions

Inline assembly code can use any MASM expression, which is any combination of operands and operators that evaluates to a single value or address.

Data Directives and Operators

Although an __asm block can reference C or C++ data types and objects, it cannot define data objects with MASM directives or operators. Specifically, you cannot use the definition directives DB, DW, DD, DQ, DT, and DF, or the operators DUP or THIS. MASM structures and records are also unavailable. The inline assembler doesn't accept the directives STRUC, RECORD, WIDTH, or MASK.

EVEN and ALIGN Directives

Although the inline assembler doesn't support most MASM directives, it does support EVEN and ALIGN. These directives put NOP (no operation) instructions in the assembly code as needed to align labels to specific boundaries. This makes instruction-fetch operations more efficient for some processors.

Macros

The inline assembler is not a macro assembler. You cannot use MASM macro directives (MACRO, REPT, IRC, IRP, and ENDM) or macro operators (<>, !, &, %, and .TYPE). An __asm block can use C preprocessor directives, however. See »Using C or C++ in __asm Blocks« for more information.

Segment References

You must refer to segments by register rather than by name (the segment name _TEXT is invalid, for instance). Segment overrides must use the register explicitly, as in ES:[BX].

Type and Variable Sizes

The LENGTH, SIZE, and TYPE operators have a limited meaning in inline assembly. They cannot be used at all with the DUP operator (because you cannot define data with MASM directives or operators). But you can use them to find the size of C or C++ variables or types:

•	The LENGTH operator can return the number of elements in an array. It returns the value 1 for non-array variables.

•	The SIZE operator can return the size of a C or C++ variable. A variable's size is the product of its LENGTH and TYPE.

•	The TYPE operator can return the size of a C or C++ type or variable. If the variable is an array, TYPE returns the size of a single element of the array.

For example, if your program has an 8-element int array,

int arr[8];

the following C and assembly expressions yield the size of arr and its elements.

__asm	C	Size
LENGTH arr	sizeof(arr)/sizeof(arr[0])	8
SIZE arr	sizeof(arr)	16
TYPE arr	sizeof(arr[0])	2
Comments

Instructions in an __asm block can use assembly-language comments:

__asm mov ax, offset buff ; Load address of buff

Because C macros expand into a single logical line, avoid using assembly-language comments in macros. (See »Defining __asm Blocks as C Macros«.) An __asm block can also contain C-style comments; for more information, see »Using C or C++ in __asm Blocks«.

The _emit Pseudoinstruction

The _emit pseudoinstruction is similar to the DB directive of MASM. You use _emit to define a single immediate byte at the current location in the current text segment. However, _emit can define only one byte at a time, and it can only define bytes in the text segment. It uses the same syntax as the INT instruction.

The following fragment places the given bytes into the code:

#define randasm __asm _emit 0x4A __asm _emit 0x43 __asm _emit 0x4B
 .
 .
 .
__asm {
     randasm
     }

Debugging and Listings

Programs containing inline assembly code can be debugged with a source-level debugger if you compile with the /Zi option.

Within the debugger, you can set breakpoints on both C or C++ and assembly-language lines. If you enable mixed assembly and source mode, you can display both the source and disassembled form of the assembly code.

Note that putting multiple assembly instructions or source language statements on one line can hamper debugging. In source mode, you can use the debugger to breakpoints on a single line but not on individual statements on the same line. The same principle applies to an __asm block defined as a C macro, which expands to a single logical line.

If you create a mixed source and assembly listing with the /Fc compiler option, the listing contains both the source and assembly forms of each assembly-language line. Macros are not expanded in listings, but they are expanded during compilation.


  Using C or C++ in __asm Blocks

Because inline assembly instructions can be mixed with C or C++ statements, they can refer to C or C++ variables by name and use many other elements of those languages.

An __asm block can use the following language elements:

•	Symbols, including labels and variable and function names

•	Constants, including symbolic constants and enum members

•	Macros and preprocessor directives

•	Comments (both /* */ and // )

•	Type names (wherever a MASM type would be legal)

•	typedef names, generally used with operators such as PTR and TYPE or to specify structure or union members

Within an __asm block, you can specify integer constants with either C notation or assembler radix notation (0x100 and 100h are equivalent, for example). This allows you to define (using #define) a constant in C and then use it in both C or C++ and assembly portions of the program. You can also specify constants in octal by preceding them with a 0. For example, 0777 specifies an octal constant.


  Using Operators

An __asm block cannot use C or C++ specific operators, such as the << operator. However, operators shared by C and MASM, such as the  (*)  operator, are interpreted as assembly-language operators. For instance, outside an __asm block, square brackets ([]) are interpreted as enclosing array subscripts, which C automatically scales to the size of an element in the array. Inside an __asm block, they are seen as the MASM index operator, which yields an unscaled byte offset from any data object or label (not just an array). The following code illustrates the difference:

int array[10];

__asm mov array[6], bx ;  Store BX at array+6 (not scaled)

array[6] = 0;         /* Store 0 at array+12 (scaled) */

The first reference to array is not scaled, but the second is. Note that you can use the TYPE operator to achieve scaling based on a constant. For example, the following statements are equivalent:

__asm mov array[6 * TYPE int], 0 ; Store 0 at array + 12

array[6] = 0;                   /* Store 0 at array + 12 */


  Using C or C++ Symbols

An __asm block can refer to any C or C++ symbol in scope where the block appears. (C and C++ symbols are variable names, function names, and labels; that is, names that aren't symbolic constants or enum members. You cannot call C++ member functions.)

A few restrictions apply to the use of C and C++ symbols:

•	Each assembly-language statement can contain only one C or C++ symbol. Multiple symbols can appear in the same assembly instruction only with LENGTH, TYPE, and SIZE expressions.

•	Functions referenced in an __asm block must be declared (prototyped) earlier in the program. Otherwise, the compiler cannot distinguish between function names and labels in the __asm block.

•	An __asm block cannot use any C or C++ symbols with the same spelling as MASM reserved words (regardless of case). MASM reserved words include instruction names such as PUSH and register names such as SI.

•	Structure and union tags are not recognized in __asm blocks.


  Accessing C or C++ Data

A great convenience of inline assembly is the ability to refer to C or C++ variables by name. An __asm block can refer to any symbols, including variable names, that are in scope where the block appears. For instance, if the C variable var is in scope, the instruction

__asm mov eax, var

stores the value of var in EAX.

If a class, structure, or union member has a unique name, an __asm block can refer to it using only the member name, without specifying the variable or typedef name before the period (.) operator. If the member name is not unique, however, you must place a variable or typedef name immediately before the period operator. For example, the following structure types share same_name as their member name:

struct first_type
{
   char *weasel;
   int same_name;
};

struct second_type
{
   int wonton;
   long same_name;
};

If you declare variables with the types

struct first_type hal;
struct second_type oat;

all references to the member same_name must use the variable name because same_name is not unique. But the member weasel has a unique name, so you can refer to it using only its member name:

__asm
{
   mov ebx, OFFSET hal
   mov ecx, [ebx]hal.same_name ; Must use 'hal'
   mov esi, [ebx].weasel       ; Can omit 'hal'
}

Note that omitting the variable name is merely a coding convenience. The same assembly instructions are generated whether or not the variable name is present.

You can access data members in C++ without regard to access restrictions. However, you cannot call member functions.


  Writing Functions

If you write a function with inline assembly code, it's easy to pass arguments to the function and return a value from it. The following examples compare a function first written for a separate assembler and then rewritten for the inline assembler. The function, called power2, receives two parameters, multiplying the first parameter by 2 to the power of the second parameter. Written for a separate assembler, the function might look like this:

; POWER.ASM
; Compute the power of an integer
;
       PUBLIC _power2
_TEXT SEGMENT WORD PUBLIC 'CODE'
_power2 PROC

        push ebp        ; Save EBP
        mov ebp, esp    ; Move ESP into EBP so we can refer
                        ;   to arguments on the stack
        mov eax, [ebp+4] ; Get first argument
        mov ecx, [ebp+6] ; Get second argument
        shl eax, cl     ; EAX = EAX * ( 2 ^ CL )
        pop ebp         ; Restore EBP
        ret             ; Return with sum in EAX

_power2 ENDP
_TEXT   ENDS
        END

Since it's written for a separate assembler, the function requires a separate source file and assembly and link steps. C and C++ function arguments are usually passed on the stack, so this version of the power2 function accesses its arguments by their positions on the stack. (Note that the MODEL directive, available in MASM and some other assemblers, also allows you to access stack arguments and local stack variables by name.)

The POWER2.C program writes the power2 function with inline assembly code:

/* POWER2.C */
#include <stdio.h>

int power2( int num, int power );

void main( void )
{
   printf( "3 times 2 to the power of 5 is %d\n", \
           power2( 3, 5) );
}
int power2( int num, int power )
{
   __asm
   {
      mov eax, num    ; Get first argument
      mov ecx, power  ; Get second argument
      shl eax, cl     ; EAX = EAX * ( 2 to the power of CL )
   }
   /* Return with result in EAX */
}

The inline version of the power2 function refers to its arguments by name and appears in the same source file as the rest of the program. This version also requires fewer assembly instructions.

Because the inline version of power2 doesn't execute a C return statement, it causes a harmless warning if you compile at warning levels 2 or higher. The function does return a value, but the compiler cannot tell that in the absence of a return statement. You can use #pragma warning to disable the generation of this warning.


  Using and Preserving Registers

In general, you should not assume that a register will have a given value when an __asm block begins. An __asm block inherits whatever register values happen to result from the normal flow of control.

If you use the __fastcall calling convention, the compiler passes function arguments in registers instead of on the stack. This can create problems in functions with __asm blocks because a function has no way to tell which parameter is in which register. If the function happens to receive a parameter in EAX and immediately stores something else in EAX, the original parameter is lost. In addition, you must preserve the ECX register in any function declared with __fastcall.

To avoid such register conflicts, don't use the __fastcall convention for functions that contain an __asm block. If you specify the __fastcall convention globally with the /Gr compiler option, declare every function containing an __asm block with __cdecl or __stdcall. (The __cdecl attribute tells the compiler to use the C calling convention for that function.) If you are not compiling with /Gr, avoid declaring the function with the __fastcall attribute.

As you may have noticed in the POWER2.C example in »Writing Functions«, the power2 function doesn't preserve the value in the EAX register. When you write a function in assembly language, you don't need to preserve the EAX, EBX, ECX, EDX, ES, and flags registers. However, you should preserve any other registers you use (EDI, ESI, DS, SS, SP, and BP).

Note  If your inline assembly code changes the direction flag using the STD or CLD instructions, you must restore the flag to its original value.

Assembly instructions that appear inline with C or C++ statements are free to alter the EAX, EBX, ECX, and EDX registers. C and C++ don't expect these registers to be maintained between statements, so you don't need to preserve them. The same is true of the ESI and EDI registers, with some exceptions (see »Optimizing«). You should preserve the ESP and EBP registers unless you have some reason to change them—to switch stacks, for example.


  Jumping to Labels

Like an ordinary C or C++ label, a label in an __asm block has scope throughout the function in which it is defined (not only in the block). Both assembly instructions and goto statements can jump to labels inside or outside the __asm block.

Labels defined in __asm blocks are not case sensitive; both goto statements and assembly instructions can refer to those labels without regard to case. C and C++ labels are case sensitive only when used by goto statements. Assembly instructions can jump to a C or C++ label without regard to case.

The following do-nothing code shows all the permutations:

void func( void )
{
   goto C_Dest;  /* Legal: correct case   */
   goto c_dest;  /* Error: incorrect case */

   goto A_Dest;  /* Legal: correct case   */
   goto a_dest;  /* Legal: incorrect case */

   __asm
   {
      jmp C_Dest ; Legal: correct case
      jmp c_dest ; Legal: incorrect case

      jmp A_Dest ; Legal: correct case
      jmp a_dest ; Legal: incorrect case

      a_dest:    ; __asm label
   }

   C_Dest:       /* C label */
   return;
}

Don't use C library function names as labels in __asm blocks. For instance, you might be tempted to use exit as a label, as follows:

; BAD TECHNIQUE: using library function name as label
jne exit
   .
   .
   .
exit:
   ; More __asm code follows

Because exit is the name of a C library function, this code might cause a jump to the exit function instead of to the desired location.

As in MASM programs, the dollar symbol ($) serves as the current location counter. It is a label for the instruction currently being assembled. In __asm blocks, its main use is to make long conditional jumps:

jne $+5 ; next instruction is 5 bytes long
jmp farlabel
; $+5
   .
   .
   .
farlabel:


  Calling C Functions

An __asm block can call C functions, including C library routines. The following example calls the printf library routine:

#include <stdio.h>

char format[] = "%s %s\n";
char hello[] = "Hello";
char world[] = "world";
void main( void )
{
   __asm
   {
      mov  eax, offset world
      push eax
      mov  eax, offset hello
      push eax
      mov  eax, offset format
      push eax
      call printf
   }
}

Because function arguments are passed on the stack, you simply push the needed arguments — string pointers, in the previous example — before calling the function. The arguments are pushed in reverse order, so they come off the stack in the desired order. To emulate the C statement

printf( format, hello, world );

the example pushes pointers to world, hello, and format, in that order, and then calls printf.


  Calling C++ Functions

An __asm block can call only global C++ functions that are not overloaded. If you call an overloaded global C++ function or a C++ member function, the compiler issues an error.

You can also call any functions declared with extern "C" linkage. This allows an __asm block within a C++ program to call the C library functions, because all the standard header files declare the library functions to have extern "C" linkage.


  Defining __asm Blocks as C Macros

C macros offer a convenient way to insert assembly code into your source code, but they demand extra care because a macro expands into a single logical line. To create trouble-free macros, follow these rules:

•	Enclose the __asm block in braces.

•	Put the __asm keyword in front of each assembly instruction.

•	Use old-style C comments ( /* comment */) instead of assembly-style comments ( ; comment) or single-line C comments ( // comment).

To illustrate, the following example defines a simple macro:

#define PORTIO __asm	\
/* Port output */	\
{	\
   __asm mov al, 2	\
   __asm mov dx, 0xD007 	\
   __asm out al, dx	\
}

At first glance, the last three __asm keywords seem superfluous. They are needed, however, because the macro expands into a single line:

__asm /* Port output */ { __asm mov al, 2  __asm mov dx, 0xD007 __asm out al, dx }

The third and fourth __asm keywords are needed as statement separators. The only statement separators recognized in __asm blocks are the newline character and __asm keyword. Because a block defined as a macro is one logical line, you must separate each instruction with __asm.

The braces are essential as well. If you omit them, the compiler can be confused by C or C++ statements on the same line to the right of the macro invocation. Without the closing brace, the compiler cannot tell where assembly code stops, and it sees C or C++ statements after the __asm block as assembly instructions.

Assembly-style comments that start with a semicolon (;) continue to the end of the line. This causes problems in macros because the compiler ignores everything after the comment, all the way to the end of the logical line. The same is true of single-line C or C++ comments ( // comment). To prevent errors, use old-style C comments ( /* comment */) in __asm blocks defined as macros.

An __asm block written as a C macro can take arguments. Unlike an ordinary C macro, however, an __asm macro cannot return a value. So you cannot use such macros in C or C++ expressions.

Be careful not to invoke macros of this type indiscriminately. For instance, invoking an assembly-language macro in a function declared with the __fastcall convention may cause unexpected results. (See »Using and Preserving Registers«.)


  Optimizing

The presence of an __asm block in a function affects optimization in several ways. First, the compiler doesn't try to optimize the __asm block itself. What you write in assembly language is exactly what you get. Second, the presence of an __asm block affects register variable storage. The compiler avoids enregistering variables across an __asm block if the register's contents would be changed by the __asm block. Finally, some other function-wide optimizations will be affected by the inclusion of assembly language in a function.


Chapter 12: Programming with Mixed Languages
  Chapter 12  Programming with Mixed Languages

Mixed-language programming is the process of building programs in which the source code is written in two or more languages. Although mixed-language programming presents some additional challenges, it is frequently worthwhile because it enables you to call existing code that may be written in another language.

Microsoft provides 32-bit versions of C, C++, MASM, and FORTRAN, and mixed-language programming is possible between all these languages. The rules for Win32 change from that for mixed-language programming for 16-bit environments, but in many respects it is simpler.

This chapter contains the following sections:

•	Overview of mixed-language issues

•	C calls to FORTRAN

•	FORTRAN calls to C

•	Building the mixed-language program

•	C++ calls

•	Handling data types


  Overview of Mixed-Language Issues

This section reviews basic concepts of mixed-language programming, as well as introducing relevant features new to Win32. For example, the __stdcall keyword replaces the fortran and pascal keywords in C modules. Another important aspect of Win32 is that all addresses are the same size, simplifying pass by reference. Thus, you may want to review this section even if you have written mixed-language programs extensively for MS-DOS.

Mixed-language programming is possible with Microsoft languages because each language implements functions, subroutines, and procedures in approximately the same way. Table 12.1 shows how different kinds of routines from each language equate to each other. For example, a C main program could call an external void function, which is actually implemented as a FORTRAN subroutine.

Table 12.1    Language Equivalents for Calls to Routines

Language	Call with return value	Call with no return value
Assembly language	Procedure	Procedure
C and C++	function	(void) function
FORTRAN	FUNCTION	SUBROUTINE
This chapter uses the term "routine" in a generic way, to refer to functions, subroutines, and procedures from different languages. This definition does not extend to macros or inline functions, which are not implemented using the stack.

There are some important differences in the way languages implement these routines, however. This chapter presents a series of keywords, attributes, and techniques to reconcile these differences, which fall into the following three categories:

•	Adjusting calling conventions

•	Adjusting naming conventions

•	Passing by value or by reference

In addition, you need to reconcile any differences in the way individual data types (strings, arrays, common blocks, and so on) may be treated. This is an important and complex topic that is discussed in the last section.


  Adjusting Calling Conventions

The calling convention determines how a program makes a call and where the parameters are passed. In a single-language program, calling conventions are nearly always correct, because there is one default for all modules and because header files enforce consistency between the caller and the called routine. In a mixed-language program, different languages cannot share the same header files. It's all too easy to link FORTRAN and C modules that use different calling conventions, and the error isn't apparent until the bad call is made at run time, causing immediate program failure. Therefore, you should check calling conventions carefully for each mixed-language call.

Table 12.2 summarizes how C and FORTRAN calling conventions work.

Table 12.2    C and FORTRAN Calling Conventions

Calling convention	Parameter passing	Stack cleared by
C/C++	Pushes parameters on the stack, in reverse order (right to left)	Caller
FORTRAN (__stdcall)	Pushes parameters on the stack, in reverse order (right to left)	Called function
In C and C++ modules, you can specify the FORTRAN calling convention by using the __stdcall keyword in a function prototype or definition. The __stdcall convention is also used by window procedures and API functions. For example, the following C language prototype sets up a function call to a subroutine using the FORTRAN calling convention:

extern void __stdcall fortran_routine (int n);

Instead of changing the calling convention of the C code, you can adjust the FORTRAN source code by using the C attribute, enclosed in brackets ([ ]). For example, the following declaration assumes the subroutine is called with the C calling convention:

      SUBROUTINE CALLED_FROM_C [C] (A)

      INTEGER*4 A

It should be clear that calling conventions need only agree between individual calls and the called routines, and that the conventions must be the same: both caller and called routine must use the C/C++ convention or both must use the __stdcall convention (the FORTRAN default).

Note  In programs written for the graphical user interface of Windows, PASCAL, WINAPI, and CALLBACK are all defined with __stdcall. But the C language default is still cdecl.

Table 12.3 summarizes how to specify calling conventions. You can always specify calling conventions explicitly rather than relying on the default, which is a good technique for mixed-language programming.

Table 12.3    Specifying Calling Conventions

Language	C calling convention	FORTRAN calling convention
C/C++	cdecl (default)	__stdcall
FORTRAN	C attribute	STDCALL attribute (default)


  Adjusting Naming Conventions

The naming convention determines how a language alters a symbol name as it places the name in a .OBJ file. This is an issue for external data symbols shared between modules as well as external routines. Parameter names are never affected. The reasons for altering the name include case sensitivity or lack thereof, type decoration, and other issues. Note that you can always see exactly how a name has been placed in a .OBJ file by using the DUMPBIN utility with the  − SYMBOLS option. If naming conventions are not reconciled, the program cannot successfully link. You will receive an "unresolved external" error.

Naming conventions are closely related to calling conventions because the keywords that specify calling conventions affect naming conventions as well. However, C/C++ preserves case sensitivity in its symbol tables and FORTRAN does not, a fact which can require some additional work on your part. Fortunately, the FORTRAN ALIAS attribute can be use to resolve any discrepency in names.

Table 12.4 summarizes how C, FORTRAN, and C++ handle public names.

Table 12.4   Naming Conventions in C, FORTRAN, and C++

Language	Name translated as	Case of name in OBJ file
C, cdecl (default)	_name	Mixed case preserved
C, __stdcall	_name@nn	Mixed case preserved
FORTRAN [C]	_name	All lowercase
FORTRAN [STDCALL]	_name@nn	All lowercase
FORTRAN default	_name@nn	All uppercase
C++	_name@@decoration	Mixed case preserved
In Table 12.4, nn represents the stack space, in decimal notation, occupied by parameters. For example, assume a function is declared in C as

extern int __stdcall Sum_Up( int a, int b, int c );

Each integer occupies 4 bytes, so the symbol name placed in the .OBJ file is:

_Sum_Up@12

Case sensitivity can present a problem. The 32-bit linker always distinguishes case. The best strategy for handling discrepency due to case depends on the situation:

•	Calls from C to FORTRAN, where FORTRAN cannot be recompiled

•	Symbol names that are all lowercase

•	Mixed-case names

C Calls Using FORTRAN Names

If you call a FORTRAN routine from C and cannot recompile the FORTRAN code, and if the routine uses FORTRAN defaults, then you must use an all-uppercase name to make the call. Use of the __stdcall convention is not enough, because __stdcall (unlike the fortran keyword in 16-bit code) always preserves case. FORTRAN generates all-uppercase names by default and the C code must match it.

For example, this prototype sets up a call to a FORTRAN function ffarctan:

extern float __stdcall FFARCTAN( float angle );

All-Lowercase Names

If the name of the routine appears as all lowercase in C, then naming conventions are automatically correct when the C or STDCALL attribute is applied to the FORTRAN declaration. Any case may be used in the FORTRAN source code, including mixed case; the C and STDCALL attributes change the name to all lowercase. Note that this is a way in which STDCALL differs from the FORTRAN default behavior.

Mixed Case Names

If the name of the routine appears as mixed-case in C, and you cannot change the name, then you can only resolve naming conflicts by using the FORTRAN ALIAS attribute. ALIAS is required in this situation because otherwise FORTRAN never generates mixed-case names.

To use the ALIAS attribute, place the name in quotation marks exactly as it is to appear in the .OBJ file. For example, suppose you are calling a C function that has the following prototype:

extern void My_Proc (int i);

The FORTRAN call to this function should be declared with the following INTERFACE block:

      INTERFACE TO SUBROUTINE My_Proc [C, ALIAS:'_My_Proc'] (I)

      INTEGER*4 I

      END

Note  When using the __stdcall convention, both FORTRAN and C should calculate parameter-space size by rounding each parameter upward to multiples of four (because it is more efficient to keep the stack-pointer aligned on 4-byte boundaries). Thus, the function Print_Nums which is passed a byte, a short, and a long integer should be translated as _Print_Nums@12. However, there is an early version of 32-bit FORTRAN that translates this as _Print_Nums@7, not rounding upward. To correct the discrepancy, use the ALIAS attribute.


  Passing By Value or By Reference

Each individual parameter can be passed by value or by reference (which places the address of the parameter on the stack). In FORTRAN, C, and C++, all addresses are the same size (4 bytes), so there is no passing by near or far reference. You need to make sure that for every call, the calling program and the called routine agree on how each parameter is passed. Otherwise, the called routine receives bad data.

The C/C++ technique for passing parameters is always the same, regardless of calling convention: all parameters are passed by value, except for arrays, which are translated into the address of the first member. To pass data by reference, pass a pointer to it.

The FORTRAN technique for passing parameters changes depending on the calling convention specified. By default, FORTRAN passes all data by reference (except the hidden length argument of strings, which is a special case). If the C or STDCALL attribute is used, the default changes to passing all data by value.

In FORTRAN, use the VALUE and REFERENCE attributes to specify pass by value or pass by reference. In mixed-language programming, it is a good idea to always specify passing technique explicitly rather than relying on defaults. For example, the following C declaration sets up a call to a FORTRAN subroutine:

extern void __stdcall TESTPROC( int ValParm, int *RefParm );

In the following example, the definition of TESTPROC in FORTRAN declares how each parameter is passed. The REFERENCE attribute is not strictly necessary in this example, but using it is a good idea, in case you later change the calling convention.

      SUBROUTINE TESTPROC( VALPARM, REFPARM )

      INTEGER*4 VALPARM [VALUE]

      INTEGER*4 REFPARM [REFERENCE]

      END

Table 12.5 summarizes parameter-passing defaults. Note that an array name in C is equated to its starting address. Therefore arrays are passed by reference. To pass an array by value, declare a structure with the array as its only member.

Table 12.5    C/C++ and FORTRAN Defaults for Passing Parameters

Language	By value	By reference
C/C++	variable	* variable
FORTRAN	variable [VALUE]	variable [REFERENCE], or variable
FORTRAN [C or STDCALL]	variable [VALUE], or variable	variable [REFERENCE]
C/C++ arrays	struct { type } variable	variable


  C Calls to FORTRAN

This section applies the principles in the section "Overview of Mixed-Language Issues" to a typical case involving one function call and one subroutine call from C to FORTRAN. Default conventions are assumed for FORTRAN, so adjustments are made to the C code.

The C main program uses the __stdcall keyword to call the FORTRAN routines with the correct calling convention. The C source must use all-uppercase names for the routines, because this FORTRAN code does not use the C, STDCALL, or ALIAS attributes. Finally, pass by value and pass by reference are specified explicitly, though pass by reference would have been assumed by default for FORTRAN.

/*     File CMAIN.C   */

#include <stdio.h>

extern int __stdcall FACT (int n);

extern void __stdcall PYTHAGORAS (float a, float b, float *c);

main()

{

    float c;

    printf("Factorial of 7 is: %d\n", FACT(7));

    PYTHAGORAS (30, 40, &c);

    printf("Hypotenuse if sides 30, 40 is: %f\n", c);

}

C    File FORSUBS.FOR

C

      INTEGER*4 FUNCTION Fact (n)

      INTEGER*4 n [VALUE]

      INTEGER*4 i, amt

      amt = 1

      DO i = 1, n

        amt = amt * i

      END DO

      Fact = amt

      END

      SUBROUTINE Pythagoras (a, b, c)

      REAL*4 a [VALUE]

      REAL*4 b [VALUE]

      REAL*4 c [REFERENCE]

      c = SQRT (a * a + b * b)

      END


  FORTRAN Calls to C

This section applies the principles in the section "Overview of Mixed-Language Issues" to a typical case involving one function call and one subroutine call from  FORTRAN to C. Default conventions are assumed for C, so adjustments are made to the FORTRAN code. The example in this section is the exact converse of that in the previous section.

The FORTRAN main program uses the C attribute to call the C functions with the correct calling convention. The C attribute causes FORTRAN to generate all-lowercase names, so the ALIAS attribute must be used to preserve mixed case. Finally, pass by value and pass by reference are specified explicitly, though pass by value would have been assumed because of the C attribute.

C   File FORMAIN.FOR

C

      INTERFACE TO INTEGER*4 FUNCTION Fact [C,ALIAS:'_Fact'] (n)

      INTEGER*4 n [VALUE]

      END

      INTERFACE TO SUBROUTINE Pythagoras [C,ALIAS:'_Pythagoras'] (a,b,c)

      REAL*4 a [VALUE]

      REAL*4 b [VALUE]

      REAL*4 c [REFERENCE]

      END

      INTEGER*4 Fact

      REAL*4 c

      WRITE (*,*) 'Factorial of 7 is ', Fact (7)

      CALL Pythagoras (30, 40, c)

      WRITE (*,*) 'Hypotenuse if sides 30, 40 is ', c

      END

/*  File CSUBS.C  */

#include <math.h>

int Fact( int n )

{

    if (n > 1)

        return( n * Fact( n - 1 ));

    return 1;

}

void Pythagoras( float a, float b, float *c)

{

    *c = sqrt( a * a + b * b );

}


  Building the Mixed-Language Program

In Win32, the choice of libraries is much simpler than it is in 16-bit environments. Consequently, it is easier to build a mixed-language program. To link C and FORTRAN modules together, use the FORTRAN linker; the linker should find the correct default libraries.

For example, the simple console applications featured in the previous sections require no special options. The CMAIN application can be created with the following commands:

cl /c cmain.c

fl32 cmain.obj forsubs.for

The FORMAIN application can be created with the following commands:

cl /c csubs.c

fl32 formain.for cmain.obj

Multithread applications should have full multithread support, so if you use LIBFMT.LIB, make sure that LIBCMT.LIB is specified as a default library as well.


  Mixed-Language Programming with C++

C++ uses the same calling convention and parameter-passing techniques as C, but naming conventions are different because of C++ decoration of external symbols. The extern "C" syntax makes it possible for a C++ module to share data and routines with other languages, by causing C++ to drop name decoration.

The following example declares prn as an external function using the C naming convention. This declaration appears in C++ source code.

extern "C"
{
    void prn();
}

To call functions written in FORTRAN (or MASM), declare the function as you would in C and use a "C" linkage specification. For example, to call the FORTRAN function FACT from C++, declare it as follows:

extern "C" {    int __stdcall FACT( int n ); }

The extern "C" syntax can be used to adjust a call from C++ to other languages, or to change the naming convention of C++ routines called from other languages. However, extern "C" can only be used from within C++. If the C++ code does not use extern "C" and cannot be changed, you can call C++ routines only by determining the name decoration and generating it from the other language. You can always determine the decoration by using the DUMPBIN utility. Such an approach should only be used as a last resort, because the decoration scheme is not guaranteed to remain the same between versions.

Use of extern "C" has some restrictions:

•	You cannot declare a member function with extern "C".

•	You can specify extern "C" for only one instance of an overloaded function; all other instances of an overloaded function have C++ linkage.

For more information on the extern "C" linkage specification, see the C++ Language Reference.


  Handling Data Types

Even when you've reconciled calling conventions, naming conventions, and parameter passing technique (pass by value or pass by reference), it is still possible to pass data incorrectly, because each language has different ways of handling data types. The following sections describe how to pass each type of data between languages.


  Numeric Data Types

Normally, passing numeric data does not present a problem. Probably the most important thing to keep in mind when passing numeric types is that in Win32, the C int type is 4 bytes, not 2 bytes, and therefore is equivalent to the FORTRAN INTEGER*4 type. The COMPLEX type is a special case and is discussed in a later section. Table 12.6 summarizes equivalent numeric data types for FORTRAN, MASM, and C/C++.

Table 12.6    Equivalent FORTRAN, MASM, and C/C++ Numeric Data Types

FORTRAN	MASM	C/C++
CHARACTER*1	BYTE	unsigned char
INTEGER*1	SBYTE	char
(none)	WORD	unsigned short
INTEGER*2	SWORD	short
(none)	DWORD	unsigned long, unsigned int
INTEGER, INTEGER*4	SDWORD	long, int
REAL, REAL*4	REAL4	float
DOUBLE PRECISION, REAL*8	REAL8	double
If a C program passes an unsigned data type to a FORTRAN routine, the routine can accept the argument as the equivalent signed data type, but you should be careful that the range of the signed type is not exceeded.


  Pointers (Address Variables)

In FORTRAN, you use the LOC function to extract the address of a variable. (In Win32, all addresses are 4 bytes, so there is no separate LOCFAR function as for 16-bit environments.) Because FORTRAN does not have a pointer type, the result of the LOC function must be stored in an INTEGER*4 variable or passed as a parameter of type INTEGER*4. Generally, a pointer should be passed by value.

Passing a pointer by value is equivalent to passing what it points to by reference. In the following example, the two subroutine calls push identical data on the stack, and in each case the C routine called should expect an address. The two functions require different parameter declarations.

  INTERFACE TO SUBROUTINE pass_addr1 [C] (addr_data)

  REAL*8 addr_data [REFERENCE]

  END

  INTERFACE TO SUBROUTINE pass_addr2 [C] (addr_data)

  INTEGER*4 addr_data [VALUE]

  END

  REAL*8 x

  INTEGER*4 ptr

  CALL pass_addr1 (x)

  ptr = LOC(x)

  CALL pass_addr2 (ptr)


  Arrays

Each language varies in the way that arrays are declared and indexed. Array indexing is a source-level consideration and involves no difference in the underlying data. There are two differences in the way elements are indexed by each language:

•	The value of the lower array bound is different.

By default, FORTRAN indexes the first element of an array as 1. C and C++ index it as 0. FORTRAN subscripts should therefore be 1 higher. (FORTRAN also provides the option of specifying another integer lower bound.)

•	C varies subscripts in row-major order, FORTRAN in column-major order.

The differences in how subscripts are varied only affect arrays with more than one dimension. With row-major order (used by C and C++), the rightmost dimension changes fastest. With column-major order (used by FORTRAN), the leftmost dimension changes fastest. Thus, in C, the first four elements of an array declared as X[3][3] are

X[0][0]    X[0][1]    X[0][2]    X[1][0]

In FORTRAN, the four elements are

X(1,1)     X(2,1)     X(3,1)     X(1,2)

The preceding C and FORTRAN arrays illustrate the difference between row-major and column-major order and also the difference in the assumed lower bound between C and FORTRAN. Table 12.7 shows equivalences for array declarations in each language. In this table, r is the number of elements of the row dimension (which changes the slowest), and c is the number of elements of the column dimension (which changes the fastest).

Table 12.7    Equivalent Array Declarations

Language	Array declaration	Array reference
C/C++	type x[r][c], or struct { type x[r][c]; } x 1	x[r][c]
FORTRAN	type x(c, r)	x(c+1, r+1)
1 Use a structure to pass an array by value in C and C++.
The order of indexing extends to any number of dimensions you declare. For example, the C declaration

int arr1[2][10][15][20];

is equivalent to the FORTRAN declaration

INTEGER*2 ARR1( 20, 15, 10, 2 )

The constants used in a C array declaration represent dimensions, not upper bounds as they do in other languages. Therefore, the last element in the C array declared as int arr[5][5] is arr[4][4], not arr[5][5].

The following code provides a complete example, showing how arrays are passed as arguments to a routine.

C    File FORARRS.FOR

C

      INTERFACE TO SUBROUTINE Pass_Arr [C,ALIAS:'_Pass_Arr'] ( Array )

      INTEGER*4 Array( 10, 10 )

      END

      INTEGER*4 Arr( 10, 10 )

      CALL Pass_Arr( Arr )

      write (*,*) 'Array values: ', Arr(1, 10), Arr(2, 10)

      END

/*     File CF.C  */

#include <stdio.h>

void Pass_Arr ( int arr[10][10] )

{

    arr[9][0] = 10;

    arr[9][1] = 20;

}


  Character Strings

In Win32, FORTRAN by default passes a hidden length argument for strings. This argument is easily accessible to other languages, unlike the string-length information passed in 16-bit versions of FORTRAN. The hidden length argument consists of an unsigned four-byte integer, always passed by value, immediately following the character string argument.

For example, if a FORTRAN program sets up the following call to a routine, Pass_Str, implemented in C:

      INTERFACE TO SUBROUTINE Pass_Str (string)

      CHARACTER*(*) string

      END

Then the C routine must expect two arguments:

void __stdcall PASS_STR (char *string, unsigned int length_arg )

Another important difference in the handling of strings is in the format of the strings themselves. C strings are null-terminated. For example, given the following assignment:

Char *cstring="C text string";

The string data is stored as shown in the following figure.

FORTRAN strings are not null-terminated, and they are padded with blank spaces when assigned string data that is shorter than the declared length. For example, given the following assignment:

      CHARACTER*14 forstring

      DATA FORSTRING /"FORTRAN STRING'/

The string data is stored as follows. Note that if the string were any longer, it would be padded with trailing blanks.

A more efficient approach, wherever possible, is to adopt C string behavior. When the C or STDCALL attribute is applied to a routine, FORTRAN does not pass a hidden length argument. Futhermore, you can use the C-string feature to assign null-terminated string data in FORTRAN, as follows:

      CHARACTER*20 forstring

      DATA forstring /'This is a string'C/

The string variable, forstring, can then be passed to a C routine. If the C or STDCALL attribute is used, FORTRAN passes forstring just as C does: pushing the address of a null-terminated string onto the stack, with no hidden length argument.

Note  FORTRAN functions of type CHARACTER*(*) place a hidden string argument at the beginning of the parameter list; this may include both string address and length, as appropriate. C functions that implement such a call from FORTRAN must declare this hidden string argument explicitly and use it to return a value. However, you are more likely to avoid errors by not using character-string return types. Use subroutines whenever possible.

The following example demonstrates how a FORTRAN main program calls a C function that translates a string to all-uppercase. Because the string is passed by reference, there is no need to use a string return type. Note that the C attribute stops FORTRAN from passing a hidden string-length argument, and the DATA statement uses a "C" to specify null termination.

C    File FORMAIN.FOR

C

      INTERFACE TO SUBROUTINE Ucase [C,ALIAS:'_Ucase'] (text)

      CHARACTER*(*) text [REFERENCE]

      END

      CHARACTER*40 forstring

      DATA forstring /'This is a sample string.'C/

      WRITE (*, *) forstring

      CALL Ucase (forstring)

      WRITE (*, *) forstring

      END

/*     File CSTR.C   */

#include <ctype.h>

void Ucase( char *string )

{

    char *ptr;

    for (ptr = string; *ptr; ptr++)

        *ptr = toupper( *ptr );

}

This use of C strings is usually the best approach, because most C library functions, as well as API functions, assume null-termination. However, if you use C to write string-manipulation functions, it is a good idea to translate null-terminated strings back into blank-padded strings after the C function returns. The following code performs this operation:

      SUBROUTINE Fix_C_Str (text, length)

      CHARACTER*(*) text

      INTEGER*4 length

      INTEGER*4 i

C  Find the first null ('\0')

      i = 1

      DO WHILE ((i .LE. length) .AND. (text(i:i) .NE. '\0'))

        i = i + 1

      END DO

C  Pad with blanks to the end of the string

      DO WHILE (i .LE. length)

        text (i:i) = ' '

      END DO

      END


  Structures, COMPLEX, and LOGICAL Types

The FORTRAN structure variable, defined with the STRUCTURE keyword and declared with the RECORD statement, is equivalent to C struct declarations. You can pass structures by value or by reference. Be careful, however, about the effect of structure alignment if you are going to share structures.

C, C++, and MASM do not directly implement the FORTRAN types COMPLEX*8 and COMPLEX*16. However, you can write structures that are equivalent. The type COMPLEX*8 has two fields, both of which are 4-byte floating-point numbers; the first contains the real-number component, and the second contains the imaginary-number component. The type COMPLEX is equivalent to the type COMPLEX*8. The type COMPLEX*16 is similar to COMPLEX*8. The only difference is that each field of COMPLEX*16 contains an 8-byte floating-point number.

Note  FORTRAN functions of type COMPLEX place a hidden COMPLEX argument at the beginning of the parameter list. C functions that implement such a call from FORTRAN must declare this hidden string argument explicitly, and use it to return a value. The C return type should be void.

Here are the C/C++ structure definitions for the FORTRAN COMPLEX types.

struct complex8 {

float	real, imag;

};

struct complex16 {

double	real, imag;

};

A FORTRAN LOGICAL*2 is stored as a 1-byte indicator value (1=true, 0=false) followed by one unused byte. A FORTRAN LOGICAL*4 is stored as a 1-byte indicator value followed by three unused bytes. The type LOGICAL is equivalent to LOGICAL*4.

To pass or receive a FORTRAN LOGICAL type, use an integer. Note that only the low byte is tested or used by FORTRAN.

The C++ class type has the same layout as the corresponding C struct type, unless the class defines virtual functions or has base classes. Classes that lack those features can be passed in the same way as C structures.


  Common Blocks

You can pass individual members of a FORTRAN common block in an argument list, just as you can any data item. However, you can also give a different language module access to the entire common block at once.

C or C++ modules can reference the items of a common block by first declaring a structure with fields that correspond to the common-block variables. Having defined a structure with the appropriate fields, the C or C++ module must then connect with the common block itself. The next two sections present methods for gaining access to common blocks.

Passing the Address of a Common Block

To pass the address of a common block, simply pass the address of the first variable in the block. (In other words, pass the first variable by reference.) The receiving C or C++ module should expect to receive a structure by reference.

In the following example, the C function initcb receives the address of the variable N, which it considers to be a pointer to a structure with three fields:

C      FORTRAN SOURCE CODE
C
       COMMON /CBLOCK/N, X, Y
       INTEGER (*) 4 N
       REAL (*) 8    X, Y
.
.
.
       CALL INITCB( N )

/* C source code */

struct block_type
{
long   n;
double x;
double y;
};

initcb( struct block_type * block_hed )
{
    block_hed->n = 1;
    block_hed->x = 10.0;
    block_hed->y = 20.0;
}

Accessing Common Blocks Directly

You can access FORTRAN common blocks directly by defining a structure with the appropriate fields and then declaring the structure as an external data symbol. For example, the following code defines a structure named CBLOCK, which the C code can use to directly access items in the FORTRAN common block named CBLOCK:

struct block_type
{
    int    n;
    double x;
    double y;
};

extern struct block_type CBLOCK;


Chapter 13: Writing Portable C Programs
  Chapter 13  Writing Portable C Programs

Chapter 1, »Porting 16-Bit Code to 32-Bit Windows«, describes how to port applications written for Windows 3.x; it discusses specific issues such as changes to the memory layout and the architecture. This chapter deals with much more general portability issues: how to write code that is most likely to compile and run successfully on different hardware or operating systems, or even different compilers.

Because C compilers exist on a variety of computers, some C applications developed for one computer system can be ported to other systems. However, some aspects of language behavior depend on how a particular C compiler is implemented and how a specific computer operates. Therefore, when designing a program to be ported to another system, it is important that you examine programming assumptions. This chapter describes those assumptions that can affect writing portable programs.

The American National Standards Institute Standard for the C Language (the ANSI Standard) details every instance where language behavior is defined by the implementation. Appendix B in the C Language Reference manual summarizes implementation-defined behavior for Microsoft C.


  Assumptions About Hardware

To make C programs portable, you must examine two aspects of your code: hardware assumptions and compiler dependency. This section deals with hardware assumptions. »Assumptions About the Compiler« deals with compiler dependency.


  Size of Basic Types

In C, the size of basic types (char, signed int, unsigned int, float, double, and long double) is implementation-defined, so relying on a particular data type to be a given size reduces the portability of a program.

Because the size of basic types is left to the implementation, do not make assumptions about the size or alignment of data types within aggregate types. You should always use the sizeof operator to determine the size or amount of storage required for a variable or a type.

Following are some rules governing the size of data types.

Type char

Type char is the smallest of the basic types, but it must be large enough to hold any of the characters in the implementation's basic character set. Normally, variables of type char are 1 byte.

Type int and Type short int

Type int often corresponds to the register size of the target machine. Type short int may be less than or equal to the size of type int. Both int and short are greater than or equal to the size of type char but less than or equal to the size of type long.

If you assume that type int is a certain size, your code may not be portable because:

•	An int can be defined as a 16-bit (2-byte) or a 32-bit quantity.

•	An int is not always large enough to hold array indexes. For large arrays, you must use unsigned int; for extremely large arrays, use long or unsigned long. To be certain your code is portable, define your array indexes as type size_t. You may not know, before porting your code, the maximum value to expect an array index of type int to hold. The file LIMITS.H contains manifest constants, listed in the following table, for the maximum and minimum values of each basic integral type.

Constant	Value
CHAR_BIT	Number of bits in a variable of type char
CHAR_MIN	Minimum value a variable of type char can hold
CHAR_MAX	Maximum value a variable of type char can hold
SCHAR_MIN	Minimum value a variable of type signed char can hold
SCHAR_MAX	Maximum value a variable of type signed char can hold
UCHAR_MAX	Maximum value a variable of type unsigned char can hold
SHRT_MIN	Minimum value a variable of type short can hold
SHRT_MAX	Maximum value a variable of type short can hold
USHRT_MAX	Maximum value a variable of type unsigned short can hold
INT_MIN	Minimum value a variable of type int can hold
INT_MAX	Maximum value a variable of type int can hold
UINT_MAX	Maximum value a variable of type unsigned int can hold
LONG_MIN	Minimum value a variable of type long can hold
LONG_MAX	Maximum value a variable of type long can hold
ULONG_MAX	Maximum value a variable of type unsigned long can hold
Type float, Type double, and Type long double

Type float is the smallest of the basic floating-point types. Type double is usually larger than type float, and type long double is usually the largest of the floating-point types. You can make the following portability assumptions about floating-point types:

•	Any value that can be represented as type float can be represented as type double (type float is a subset of type double).

•	Any value that can be represented as type double can be represented as type long double (type double is a subset of type long double).

The file FLOAT.H contains manifest constants, listed in the following table, for the maximum and minimum values of each basic floating-point type.

Constant	Value
DBL_DIG	Number of decimal digits of precision a variable of type double can hold
DBL_MAX	Maximum value a variable of type double can hold
DBL_MAX_10_EXP	Maximum value (base 10) the exponent of a variable of type double can hold
DBL_MAX_EXP	Maximum value (base 2) the exponent of a variable of type double can hold
DBL_MIN	Minimum positive value a variable of type double can hold
DBL_MIN_10_EXP	Minimum value (base 10) the exponent of a variable of type double can hold
DBL_MIN_EXP	Minimum value (base 2) the exponent of a variable of type double can hold
FLT_DIG	Number of decimal digits of precision a variable of type float can hold
FLT_MAX	Maximum value a variable of type float can hold
FLT_MAX_10_EXP	Maximum value (base 10) the exponent of a variable of type float can hold
FLT_MAX_EXP	Maximum value (base 2) the exponent of a variable of type float can hold
FLT_MIN	Minimum positive value a variable of type float can hold
FLT_MIN_10_EXP	Minimum value (base 10) the exponent of a variable of type float can hold
FLT_MIN_EXP	Minimum value (base 2) the exponent of a variable of type float can hold
LDBL_DIG	Number of decimal digits of precision a variable of type long double can hold
LDBL_MAX	Maximum value a variable of type long double can hold
LDBL_MAX_10_EXP	Maximum value (base 10) the exponent of a variable of type long double can hold
LDBL_MAX_EXP	Maximum value (base 2) the exponent of a variable of type long double can hold
LDBL_MIN	Minimum positive value a variable of type long double can hold
LDBL_MIN_10_EXP	Minimum value (base 10) the exponent of a variable of type long double can hold
LDBL_MIN_EXP	Minimum value (base 2) the exponent of a variable of type long double can hold
Microsoft C Type Sizes

Table 13.1 summarizes the size of the basic types in Microsoft C.

Table 13.1    Size of Basic Types in Microsoft C

Type	Number of bytes
char, unsigned char	1
short, unsigned short	2
int, unsigned int	2 or 4*
near pointer	2 or 4*
long, unsigned long	4
far pointer	4 or 8*
float	4
double	8
long double	10
* These data types have different sizes in 16-bit and 32-bit environments.


  Storage Order and Alignment

The C language does not define any specific layout for the storage of data items relative to one another. The layout for storage of structure elements, or unions within a structure or union, is defined by the implementation.

Some processors require that data longer than 1 byte be aligned to 2-byte or 4-byte boundaries. Other processors, such as the 80x86 family, do not have such a restriction. However, the 80x86 processors work more efficiently with aligned data.

The architecture of the R4000 processor requires that each piece of data in memory be aligned on a boundary appropriate to its size. For example, an n-byte integer can be aligned on a boundary whose address is a multiple of n bytes, up to a maximum of 8 bytes. This restriction permits the memory system to run much faster.

Ordinarily, alignment has no effect on correctly written programs, because the compiler inserts unused space ("padding") between variables wherever necessary to conform to the rules.

Structure Order and Alignment

The following example illustrates how alignment can affect your program. In the example, a structure is cast to type long because the programmer knew the order in which a particular implementation stored data.

/* Nonportable code */
struct time
{
    char hour;     /* 0 < hour < 24   — fits in a char */
    char minute;   /* 0 < minute < 60 — fits in a char */
    char second;   /* 0 < second < 60 — fits in a char */
};

    .
    .
    .
    struct time now, alarm_time;
    .
    .
    .
    if ( *(long *)&now >= *(long *)&alarm_time )
    {
        /* sound an alarm */
    }

The preceding code makes these nonportable assumptions:

•	The data for hour will be stored in a higher order position than minute or
second. Because C does not guarantee storage order or alignment of structures or unions, the code may not be portable to other machines.

•	Three variables of type char will be shorter than or the same length as a variable of type long. Thus, the code is not portable according to the rules governing the size of basic types, as described in »Size of Basic Types«.

If either of these assumptions proves false, the comparison (if statement) is invalid.

To make the program in the preceding example portable, you can break the comparison between the two long integers into a component-by-component comparison. This technique is illustrated in the following example:

/* Portable code */
struct time
{
    char hour;     /* 0 < hour < 24   — fits in a char */
    char minute;   /* 0 < minute < 60 — fits in a char */
char second;   /* 0 < second < 60 — fits in a char */
};

    .
    .
    .
    struct time now, alarm_time;
    .
    .
    .
    if ( time_cmp( now, alarm_time ) >= 0 )
    {
        /* sound an alarm */
    }
    .
    .
    .

int time_cmp( struct time t1, struct time t2 )
{
    if( t1.hour != t2.hour )
        return( t2.hour - t1.hour );
    if( t1.minute != t2.minute )
        return( t2.minute - t1.minute );
    return( t2.second - t1.second );
}

Even a program that follows the rules given previously may have trouble when writing data on one machine and reading it on another. In addition to padding, machines differ with regard to endiannes, floating-point formats, and size of data types. If I/O speed is not important, a possible solution is to use ASCII files rather than binary ones.

Union Order and Alignment

Programmers use unions most often for two purposes: to store data whose exact type is not known until run time or to access the same data in different ways.

Unions falling into the second category are usually not portable. For example, the following union is not portable:

union tag_u
{
char bytes_in_long[4];
long a_long;
};

The intent of the preceding union is to access the individual bytes of a variable of type long. However, the union may not work as intended when ported to other computers because:

•	It relies on a constant size for type long.

•	It may assume byte ordering within a variable of type long. (Byte ordering is described in detail in the next section.)

The first problem can be addressed by coding the union as follows:

union tag_u
{
char bytes_in_long[sizeof( long ) / sizeof( char )];
long a_long;
};

Note the use of the sizeof operator to determine the size of a data type.


  Byte Order in a Word

The order of bytes within an integral type longer than a byte (short, int, or long) can vary among machines. Machines that number the bytes from right to left with the least significant byte within a word being byte zero are called "little-endian." Machines that number the bytes from left to right with the least significant byte being byte 3 are called "big-endian." Code that assumes an internal order is not portable, as shown by this example:

/*
 * Nonportable structure to access an
 * int in bytes.
 */
struct tag_int_bytes
{
    char lobyte;
    char hibyte;
};

A more portable way to access the individual bytes in a word is to define two macros that rely on the constant CHAR_BIT, defined in LIMITS.H:

#define LOBYTE(a) (char)((a) & 0xff)
#define HIBYTE(a) (char)((unsigned)(a) >> CHAR_BIT)

The LOBYTE macro is still not completely portable. It assumes that a char is 8 bits long, and it uses the constant 0xff to mask the high-order 8 bits. Because portable programs cannot rely on a given number of bits in a byte, consider the revision below:

#define LOBYTE(a) (char)((a) & ((unsigned)~0>>CHAR_BIT))
#define HIBYTE(a) (char)((unsigned)(a) >> CHAR_BIT)

This revised LOBYTE macro performs a bitwise complement on 0; that is, all zero bits are turned into ones. The macro then takes that unsigned quantity and shifts it right far enough to create a mask of the correct length for the implementation.

The following code assumes that the order of bytes in a word will be least-significant first:

int c;
.
.
.
fread( &c, sizeof( char ), 1, fp );

The code attempts to read 1 byte as an int, without converting it from a char. However, the code fails in any implementation where the low-order byte is not the first byte of an int. The following solution is more portable. In this example, the data is read into an intermediate variable of type char before being assigned to the integer variable:

int c;
char ch;
.
.
.
fread( &ch, sizeof( char ), 1, fp );
c = ch;

The following example shows how to use the C run-time function fgetc to return the value. The fgetc function returns type char, but the value is promoted to type int when it is assigned to a variable of type int:

int c;
.
.
.
c = fgetc( fp );

You might create porting problems by placing small objects side by side to make a bigger object, or splitting a big object into several small objects. For example, the following code that reads and compares a pair of short integers is machine-dependent, because on some machines the 0th element of the array represents the high-order half of the word rather than the low-order half:

char carr[BUFSIZ];
err = read( 0, carr, 4 );
if ( ( carr[0] | ( carr[1] << 8 ) ) > ( carr[2] | ( carr[3] << 8 ) )
...

There is never a problem if you use the correct data type and let the compiler deal with the order of the bytes:

short sarr[BUFSIZ];
err = read( 0, (char *) sarr, 2 * sizeof( short ) );
if ( sarr[0] > sarr[i] )
...

Microsoft C Specific

Microsoft C normally aligns data types longer than 1 byte to an even-byte address for improved performance. See the /Zp compiler option in Chapter 13, "CL Command Reference," of the Environment & Tools manual; see the pack pragma in the C Language Reference or in Help for information about controlling structure packing in Microsoft C.


  Floating-Point Accuracy

Some compilers use extended precision even when your program does not specify it, because it is more natural for the design of the processor to use the extended precision. When an expression is evaluated using extended precision, you may get a slightly different answer than if it were evaluated in double precision. Intel 80x87 math coprocessors use 80-bit precision for calculations, whereas R4000 processors use 64-bit precision.

In addition to differences resulting from hardware, each implementation typically differs in the algorithms and characteristics of its math library. Even IEEE machines that are otherwise identical may produce different results due to differences in math libraries.


  Reading and Writing Structures

Many C programs read data from disk into structures and write data to disk from structures. The functions that perform disk I/O in C require you to specify the number of bytes to be transferred. You should always use the sizeof operator to obtain the size of the data to be read or written, because differing data type sizes or alignment schemes might alter the size of a given structure. The following code shows one such use of the sizeof operator:

fread( &my_struct, sizeof(my_struct), 1, fp );

Microsoft C Specific

When performing disk input and output in Microsoft C, structures might be different sizes depending on the structure-packing option you have selected. (See the /Zp compiler option in Chapter 13, "CL Command Reference," of the Environment and Tools manual; see the pack pragma in the C Language Reference or in Help.)


  Bit Fields in Structures

The Microsoft C compiler implements bit fields. However, many C compilers
do not.

You use bit fields to access the individual bits within a data item. While the practice of accessing the bits in a data item is inherently nonportable, you can improve your chances of porting a program that uses bit fields if you make no assumptions about order of assignment, or size and alignment of bit fields.

Order of Assignment

Because the order of assignment of bit fields in memory is left to the implementation, you cannot rely on a particular entry in a bit field structure to be in a higher order position than another. (This problem is similar to the portability constraint imposed by alignment of basic data types in structures. The C language does not define any specific layout for the storage of data items relative to one another.) See »Storage Order and Alignment« for more information.

Size and Alignment of Bit Fields

The Microsoft C compiler supports bit fields up to the size of the type long. Each individual member of the bit field structure can be up to the size of the declared type. Some compilers do not support bit field-structure elements that are longer than type int.

The following example defines a bit field, short_bitfield, that is shorter than type int:

struct short_bitfield
{
    unsigned usr_bkup : 1; /* 0  <= usr_bkup <  1 */
    unsigned usr_sec  : 4; /* 9 <= usr_sec < 16 */
};

The following example defines a bit field, long_bitfield, that has an element longer than type int in a 16-bit environment:

struct long_bitfield
{
    unsigned long disk_pos : 22;  /* 0 <= disk_pos   < 4,194,304 */
    unsigned long rec_no   : 10;  /* 0 <= rec_no < 1,024 */
};

The bit field short_bitfield is likely to be supported by more implementations than long_bitfield.

Microsoft C Specific

The following example introduces another portability issue: alignment of data defined in bit fields.

struct long_bitfield
{
    unsigned int day    : 5;  /* 0 <= day   < 32 */
    unsigned int month  : 4;  /* 0 <= month < 16 */
    unsigned int year   : 11; /* 0 <= year  < 2048 */
};

In the 32-bit environment, all three elements can fit within a single word, so there is no gap between any of the elements in the representation by Microsoft C of the structure. Microsoft C for the 16-bit environment, by contrast, uses a word size of 16 bits. Because the compiler does not allow structure elements to cross a word boundary, there is 7-bit gap between the second and third elements in the 16-bit environment.


  Processor Arithmetic Mode

Two types of arithmetic are common on digital computers: one's-complement arithmetic and two's-complement arithmetic. Some programs assume that all target computers perform two's-complement arithmetic. If you take advantage of the fact that a given operation causes a particular bit pattern to be set on either a one's-complement or two's-complement computer, your program will not be portable. For example, two's-complement machines represent the 8-bit integer value −1 as a binary 11111111. A one's-complement machine represents the same decimal value (−1) as 11111110. Some programmers assume that −1 will fill a byte or a word with ones, and they use it to construct a mask template that they later shift. This will not work correctly on one's-complement machines, but the error will not surface until the least-significant bit is used.

In two's-complement arithmetic, there is only one value that represents zero. In one's-complement arithmetic, there is a value for zero and a value for negative zero. Use the C relational operators to handle this anomaly correctly; if you write code that deliberately circumvents the C relational operators, tests for zero or NULL may not operate correctly.

Microsoft C Specific

Microsoft C produces code only for the Intel 80x86 processors, which perform two's-complement arithmetic.


  Pointers

One of the most powerful but potentially dangerous features of the C language is its use of indirect addressing through pointers. Bugs introduced by misusing pointers can be difficult to detect and isolate because the error often corrupts memory unpredictably.

Casting Pointers

Be sure you do not make nonportable assumptions when casting pointers to different types. The following code is nonportable because using a cast to change an array of char to a pointer of type long assumes a particular byte-ordering scheme. This is discussed in greater detail in »Byte Order in a Word«.

/* Nonportable coercion */
char c[4];
long *lp;

lp = (long *)c;
*lp = 0x12345678L;

Pointer Size

A pointer can be assigned (or cast) to any integer type large enough to hold it, but the size of the integer type depends on the machine and the implementation. (In fact, it can even depend on the memory model.) Therefore, you cannot assume that a pointer is the same size as an integer; that is:

sizeof( char * ) == sizeof( int )

To determine the size of any unmodified data pointer, use:

sizeof( void * )

This expression returns the size of a generic data pointer.

Pointer Subtraction

Code that assumes that pointer subtraction yields an int value is nonportable. Pointer subtraction yields a result of type ptrdiff_t (defined in STDDEF.H). Portable code must always use variables of type ptrdiff_t for storing the result of pointer subtraction.

The Null Pointer

In most implementations, NULL is defined as 0. In Microsoft C, it is defined as ((void *)0). Because code pointers and data pointers are often different sizes, using 0 for the null pointer for both can lead to nonportability. The difference in size between code pointers and data pointers causes problems for functions that expect pointer arguments longer than an int. To avoid these problems, use the null pointer, as defined in the include file STDDEF.H; use prototypes; or explicitly cast NULL to the correct data type. Here is a portable way to use the null pointer:

/* Portable use of the null pointer */
main()
{
    func1( (char *)NULL );
    func2( (void *(*)())NULL );
}

void func1( char * c )
{
}

void func2( void *(* func)() )
{
}

The invocations of func1 and func2 explicitly cast NULL to the correct size. In the case of func1, NULL is cast to type char *; in the case of func2, it is cast to a pointer to a function that returns type void.

Microsoft C Specific

In the 32-bit environment, support for memory models and pointers of different sizes (__near, __far, and __huge) is removed. All pointers are 32 bits in size, and an attempt to use near pointers causes an error. You can, however, use the /Zf option to cause the compiler to simply ignore __far pointers.


  Address Space

The amount of available memory and the address space on systems varies, depending on many factors outside your control. A program designed with portability in mind should handle insufficient-memory situations. To ensure that your program handles these situations, you should always check the error return from any of the dynamic memory allocation routines, such as malloc, calloc, strdup, and realloc.

These situations occur not only because of a lack of installed memory but also because too many other applications are using memory. For example,

•	Installed resident software can cause your program to fail. In MS-DOS, these programs are usually device drivers or terminate-and-stay-resident (TSR) utilities.

•	An event or combination of events in a multitasking operating system such as OS/2 or XENIX can cause your program to fail. These failures are complex and difficult to predict. Here is an example: the user has installed a daemon to "pop up" every so often and check the system status. The user is running your application along with enough other large applications to cause a critical shortage of memory. When the daemon pops up, your program might fail on a memory allocation request.

•	An application running under Windows can use an extraordinary amount of the global heap and not return it to the free pool. This type of behavior eventually causes Windows to deny a GlobalAlloc request.


  Character Set

The C language does not define the character set used in an implementation. This means that any programs that assume the character set to be ASCII are nonportable.

The only restrictions on the character set are these:

•	No character in the implementation's character set can be larger than the size of type char.

•	Each character in the set must be represented as a positive value by type char, whether it is treated as signed or unsigned. So, in the case of the ASCII character set and an 8-bit char, the maximum value is 127. (128 is a negative number when stored in a char variable.)

Character Classification

The standard C run-time support contains a complete set of character classification macros and functions. These functions are defined in the CTYPE.H file and are guaranteed to be portable:

isalnum

isalpha

iscntrl

isdigit

isgraph

islower

isprint

ispunct

isspace

isupper

isxdigit

The following code fragment is not portable to implementations that do not use the ASCII character set:

/* Nonportable */
if( c >= 'A' && c <= 'Z' )
    /* uppercase alphabetic */

Instead, consider using this:

/* Portable */
if( isalpha(c) && isupper(c) )
    /* uppercase alphabetic */

The first example is nonportable, because it assumes that uppercase A is represented by a smaller value than uppercase Z, and that no lowercase characters fall between the values of A and Z. The second example is portable, because it uses the character classification functions to perform the tests.

In a portable program, you should not perform any comparison on variables of type char except strict equality (==). You cannot assume the character set follows an increasing sequence—that may not be true on a different machine.

Case Translation

Translation of characters from uppercase to lowercase or from lowercase to uppercase is called "case translation." The following example shows a coding technique for case translation not portable to implementations using a non-ASCII character set:

#define make_upper(c) ((c)&0xcf)
#define make_lower(c) ((c)|0x20)

This code takes advantage of the fact that you can map uppercase to lowercase simply by changing the state of bit 6. It is extremely efficient but nonportable. To write portable code, use the case-translation macros toupper and tolower (defined in CTYPE.H).


  Assumptions About the Compiler

Different compilers translate C source code into object code in different ways. The ANSI draft standard for the C programming language defines how many of these translations must be done; others are implementation-defined.

This section describes assumptions about how the compiler translates your C code, which can make your programs nonportable. For a complete description of how Microsoft C handles implementation-defined operations, see Appendix B of the
C Language Reference.


  Sign Extension

"Sign extension" is the propagation of the sign bit to fill unoccupied space when promoting to a more significant type or when performing bitwise right-shift operations.

Promotion from Shorter Types

Integral promotions from shorter types occur when you make an assignment, perform arithmetic, perform a comparison, or perform an explicit cast.

The behavior of integral promotion is well defined, except for type char. The implementation defines whether type char is treated as signed or unsigned. The following code fragment is an example of promotion as a result of assignment:

char c1 = -3;
int  i1;

i1 = c1;

In this example, the expected result of the assignment statement is that i1 will be set to −3. If the implementation defines type char as unsigned, however, sign extension will not occur, and i1 will be 253 (on a two's-complement machine).

Promotion can also occur as a result of a comparison of different types:

char c;

if( c == 0x80 )
    .
    .
    .

This comparison never evaluates as true on an implementation that sign-extends char types but treats hexadecimal constants as unsigned. Use a character constant of the form '\x80', or explicitly cast the constant to type char to perform the comparison correctly.

The following comparison, which is an example of promotion as a result of a cast, is also nonportable:

char c;
unsigned int u;

if( u == (unsigned)c )

There are two problems with this code:

•	The char type may be treated as signed or unsigned, depending on the implementation.

•	If the char type is treated as signed, it can be converted to unsigned in two ways: the char value may first be sign-extended to int, and then converted to unsigned; or the char may be converted to unsigned char, then sign-extended to int length.

It is always safe to compare a signed int with a char constant because C requires all character constants to be positive.

Variables of type char are promoted to type int when passed as arguments to a function. This causes sign extension on some machines. Consider the following code:

char c = 128;

printf( "%d\n", c );

Microsoft C Specific

Microsoft C allows you to treat type char as signed or unsigned. By default, a char is considered signed, but if you change the default char type using the /J compiler option, you can treat it as unsigned.

Bitwise Right-Shift Operations

Positive or unsigned integral types (char, short, int, and long) yield positive or zero values after a right bitwise shift (>>) operation. For example,

(char)120 >> 4

yields 7,

(unsigned char)240 >> 8

yields 0,

(int)500 >> 8

yields 1, and

(unsigned int)65535 >> 4

yields 4,095.

Negative-signed integral types yield implementation-defined values after a bitwise right-shift operation. This means that you must know whether you want to do a signed or unsigned shift, and then code accordingly.

If you don't know how the implementation performs, you might get unexpected results. For example, (signed char)0x80 >> 3 yields 0xf0 if the implementation performs sign extension on right bitwise shifts. If the implementation does not perform the sign extension, the result is 0x10.

You can use right shifts to speed up division when the divisor can be represented by powers of 2 and the dividend is positive. To maintain portability, you should use the division operator.

To perform an unsigned shift, explicitly cast the data to an unsigned type. To perform a shift that extends the sign bit, use the division operator as follows: divide by 2n, where n is the number of bits you want to shift.


  Length and Case of Identifiers

Some implementations do not support long identifiers. Some allow only 6 characters, while others allow as many as 32. They may report each identifier that exceeds the maximum length or truncate identifiers to a given length. Truncation causes serious problems, especially if you have a number of similarly named variables within the scope of a block of code, such as the following:

double acct_receivable_30_days;
double acct_receivable_60_days;
double acct_receivable_90_days;
double current_interest_rate;

acct_receivable_30_days *= current_interest_rate;

If your target system retains only six significant characters, you need to rename all your acct_receivable variables.

Case sensitivity also affects portability. C is usually a case-sensitive language. That is, CalculateInterest is not considered the same identifier as calculateinterest. Some systems are not case sensitive, however, so to write portable code, differentiate your identifiers by something other than case.

These problems with identifiers can occur in two locations: the compiler and the linker or loader. Even if the compiler can handle long and case-differentiated identifiers, if the linker or loader cannot, you can get duplicate definitions or other unexpected errors.

Microsoft C Specific

The Microsoft C compiler issues the /NOIGNORECASE command to the Microsoft Segmented-Executable Linker (LINK), which directs it to consider case significant.


  Register Variables

The number and type of register variables in a function depend on the implementation. You can declare more variables as register than the number of physical registers the implementation uses. In such a case, the compiler treats the excess register variables as automatic.

Because the types that qualify for register class differ among implementations, invalid register declarations are treated as automatic.

If you declare variables as register to optimize performance, declare them in decreasing order of importance to make sure the compiler allocates a register to the most important variables.

Microsoft C Specific

The compiler ignores register declarations if you select the global register allocation optimization. You can select global register allocation as shown in the following table.

Environment	Selection
CL command line	Specify either the /Oe or /Ox option.
PWB	Select the Global Register Allocation option in the Optimizations dialog box.
pragma	Use the optimize pragma with the e parameter.


  Functions with a Variable Number of Arguments

Functions that accept a variable number of arguments are not portable. Although both the ANSI Standard and The C Programming Language specify how to write these functions and how they behave, differences still exist among compiler implementors about how to use variable argument lists.

Many UNIX systems support a standard that differs from the ANSI Standard for variable arguments. Although this may change, it currently presents a portability concern.

Microsoft C run-time libraries and macros allow you to use whichever version of variable argument support you expect to be most portable for your application.


  Evaluation Order

The C language does not guarantee the evaluation order of most expressions. Avoid writing constructs that depend on evaluation within an expression to proceed in a particular manner. For example,

i = 0;
func( i++, i++ );
.
.
.
func( int a, int b )
{

A compiler could evaluate this code fragment and pass 0 as a and 1 as b. It could also pass 1 as a and 0 as b and conform equally with the standards.

The C language does guarantee that an expression will be completely evaluated at any given "sequence point." A sequence point is a point in the syntax of the language at which all side effects of an expression or series of expressions have been completed.

These are the sequence points in the C language:

•	The semicolon (;) statement separator

•	The call to a function after the arguments have been evaluated

•	The end of the first operand of one of the following:

•	Logical AND (&&)

•	Logical OR (||)

•	Conditional (?)

•	Comma separator (,) when used to separate statements or in expressions; the comma separator is not a sequence point when it is used between variables in declaration statements or between parameters in a function invocation:

•	The end of a full expression, such as:

•	An initializer

•	The expression in an expression statement (for example, any expression inside parentheses)

•	The controlling expression of a while or do statement

•	Any of the three expressions of a for statement

•	The expression in a return statement


  Function and Macro Arguments with Side Effects

Run-time support functions can be implemented either as functions or as macros. Avoid including expressions with side effects inside function invocations unless you are sure the function will not be implemented as a macro. Here is an illustration of how an argument with side effects can cause problems:

#define limit_number(x) ((x > 1000) ? 1000 : (x))

a = limit_number( a++ );

If a is greater than 1000, it is incremented once. If a is less than or equal to 1000, it is incremented twice, which is probably not the intended behavior.

A macro can be used safely with an argument that has side effects if it evaluates its parameter only once. You can determine whether a macro is safe only by inspecting the code.

A common example of a run-time support function that is often implemented as a macro is toupper. You will find your program's behavior confusing if you use the following code:

char c;

c = toupper( getc() );

If toupper is implemented as a function, getc will be called only once, and its return value will be translated to uppercase. However, if toupper is implemented as a macro, getc will be called once or twice, depending on whether c is uppercase or lowercase. Consider the following macro example:

#define toupper(c) ( (islower(c)) ? _toupper(c) : (c) )

If you include the toupper macro in your code, the preprocessor expands it as follows:

/* What you wrote */
c = toupper( getc() );

/* Macro expansion */
ch = (islower( (getc()) ) ? _toupper( getc() ) : (getc()) );

The expansion of the macro shows that the argument to toupper will always be called twice: once to determine if the character is lowercase and the next time to perform case translation (if necessary). In the example, this double evaluation calls the getc function twice. Because getc is a function whose side effect is to read a character from the standard input device, the example requests two characters from standard input.


  Environment Differences

Many programs perform some file I/O. When writing these programs for portability, consider the following:

•	Do not hard code filenames or paths. Use constants you define either in a header file or at the beginning of the program.

•	Do not assume the use of any particular file system. For example, the UNIX-model, hierarchical file system is prevalent on small computers. On larger systems, the file system often follows a different model.

•	Do not assume a particular display size (number of rows and columns).

•	Do not assume that display attributes exist. Some environments do not support such attributes as color, underlined text, blinking text, highlighted text, inverse text, protected text, or dim text.


  Portability of Data Files

Data files are rarely portable across different CPUs. Structures, unions, and arrays have varying internal layout and alignment requirements on different machines. In addition, byte ordering within words and actual word length may vary.

The best way to achieve data-file portability is to write and read data files as one-dimensional character arrays. This procedure prevents alignment and padding problems if the data is written and read as characters. The only portability problem you are likely to encounter if you follow this course is a conflict in character sets; many computers have character-set conversion utilities.


  Portability Concerns Specific to Microsoft C

Microsoft C offers extensions that you can use to take advantage of the full capabilities of the computer. These extensions are not portable to other compilers or environments. See Chapter 1, "Elements of C," of the C Language Reference for a list of Microsoft-specific keywords.

The Run-Time Library Reference contains compatibility information for every function in the run-time library. Any function or macro that does not have the ANSI box marked may not be portable to other compilers or computer systems.


  Microsoft C Byte Ordering

Tables 13.2 and  13.3 summarize Microsoft C byte ordering for short and long types, respectively. In these tables, the least-significant byte of the data item is b0; the next byte is denoted by b1, and so on.

Because byte ordering is machine specific, any program that uses this byte ordering will not be portable.

Table 13.2    Byte Ordering for Short Types

CPU	Byte order
8086	b0   b1
80286	b0   b1
80386	b0   b1
PDP-11	b0   b1
VAX-11	b0   b1
M68000	b1   b0
Z8000	b1   b0
Table 13.3    Byte Ordering for Long Types

CPU	Byte order
8086	b0  b1  b2  b3
80286	b0  b1  b2  b3
80386	b0  b1  b2  b3
PDP-11	b2  b3  b0  b1
VAX-11	b0  b1  b2  b3
M68000	b3  b2  b1  b0
Z8000	b3  b2  b1  b0


Figure 4.1 Linking Two DLLs with Mutual Imports


Figure 10.1 Structure of a Makefile That Uses a Precompiled Header File


Figure 2.1 Passing Parameters to Message Handlers with Message Crackers


Figure 1.1 Parameter Sizes


Figure 7.1 Order of Termination-Handler Execution


Figure 9.1 The Win32s Architecture
t

Figure 9.1 The Win32s Architecture


Figure 9.2 Calling a DLL under Windows NT


Figure 9.3 Calling a DLL under Win32s


Figure 9.4 Translation List Architecture


Introduction
Help Compiler User's Guide

Introduction

This manual, the Help Compiler User's Guide, serves as a reference for writers and developers of online Help systems for the Microsoft® Windows™ ( ) operating system.

The Help Compiler User's Guide also defines some specific rules you need to follow when creating a Help system for any single application. For that reason, some sections include step-by-step procedures, while others suggest general methods.

The files included with the Help Compiler are:

•	HC31.EXE, the Windows Help Compiler version 3.1.

•	SHED.EXE, the Segmented Hypergraphics Editor version 3.5.

•	MRBC.EXE, the Multiple Resolution Bitmap Compiler version 1.1.

Note  The help compiler, HC31.EXE, runs in an MS-DOS window under the Windows NT operating system. Both the Help application for Windows 3.x (WINHELP.EXE) and the Help application for Windows NT (WINHLP32.EXE) can read and display any help file that HC31 produces without any further modification.

The multi-resolution bitmap compiler (MRBC.EXE) compiles versions of a bitmap created on monitors with different resolutions into one image file (.MRB). You can then incorporate the resulting .MRB file into a help source file in order to display graphics correctly in any resolution supported by MRBC. Because Windows NT supports only VGA resolutions, this capability is most useful for help files developed for use with Windows 3.x.


Book Location
Help Compiler User's Guide


  Document Conventions

This document uses the following typographic conventions.

Example of convention	Description
WinHelp, ByVal, #include, MULTIKEY	Words in bold with the initial letter capitalized indicate language-specific keywords and options with special meaning in Microsoft Visual C++™.
BackColor, Click, Debug object	Names of properties, events, and special objects appear with the initial letter capitalized.
context-sensitive	In text, italic letters are used for defined terms, usually the first time they occur in the book. Italics are also used occasionally for emphasis.
sectionname, dwData	In syntax, italic letters indicate placeholders for information you supply.
[expressionlist]	In syntax, items inside square brackets are optional.
{do | while }	In syntax, braces and a vertical bar indicate a mandatory choice between two or more items. You must choose one of the items unless all of the items are also enclosed in square brackets.
Syntax error	This font is used for variables and error messages.
[FILES] #include<hlpfiles.txt>	This font is also used for code.
; Covered in Dialog Boxes.	A semicolon introduces comments. These lines are ignored when the Help Compiler is running.
WINHELP.TXT, HELP_QUIT	Words in all capital letters indicate file names and commands specific to the Help Compiler.
ENTER	Small capital letters are used for the names of keys and key sequences, such as ENTER and CTRL+R. (Key names in Help have only the initial letter capitalized.) The key names correspond to the names on the IBM® Personal Computer keyboard. Other machines may use different names.
SHIFT+F1	A plus sign (+) between key names indicates a combination of keys. For example, SHIFT+F1 means to hold down the SHIFT key while pressing the F1 key.
HOME	Other navigational keys are referred to by their specific names.
Graphical User Interface (GUI)	Acronyms are usually defined the first time they are used.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  Chapter 1  Introduction to the Help System

You can add professional polish to your applications and make them easier to use by adding a Help system. A Help system gives users access to online information that teaches them how to use your application. This chapter describes:

•	Features of the Windows Help system.

•	Elements of a Help system.

•	Creating a Help system.

•	How Help appears to the user.

•	How Help appears to the developer.

•	Skills needed to create a Help system.


  Features of the Windows Help System

Using the Help Compiler, you can create a system of online Help for users of your application. Windows Help version 3.1, or the WinHelp application (WINHELP.EXE), displays the compiled Help system. The WinHelp application provides:

•	Text with multiple fonts, font sizes, and colors.

•	Graphics, including bitmaps with multiple resolutions and metafiles created in the Windows operating system.

•	Macros that automate or extend the operation of the Help system.

•	Hot spots, which are mouse-sensitive areas you create to give users jumps that link topics; pop-up windows that display additional text; and macro commands that you add to the Help system.

•	Segmented hypergraphics (graphics with one or more hot spots).

•	Secondary windows for presenting related information.

•	Keyword search capability that guides a user to specific information.

With the Help Compiler and related tools, you can produce Help files that take advantage of all these features.


  Elements of a Help System

A Help system consists of one or more Help files that contain text and graphics needed to communicate online information about your application. Each Help file contains one or more topics a user can select by clicking hot spots, using the keyword search, or browsing through topics in any order you determine.

This chapter introduces you to the tools and various source files you can use to create Help files. Subsequent chapters discuss how to create and compile the source files into a Help file you can display with the WinHelp application.


  Tools

The following table describes the three tools you use to create a Help file.

Tool	Description
Help Compiler (HC31.EXE)	Compiles topic and graphic files into a Help file. The topic and graphic files, and instructions for their compiling, are contained in the Help project file. The successfully compiled Help file is displayed in the WinHelp application.
Hotspot Editor (SHED.EXE)	Opens bitmaps or metafiles to define hot spots within graphics. Hot spots link graphics to topics in the Help file.
Multiple-Resolution Bitmap Compiler (MRBC.EXE)	Compiles bitmaps of different screen resolutions into a single file. The WinHelp application displays the graphic at the user's screen resolution.


  Source Files

The following table describes the different source files you can use to create a Help file.

Type of source file	Extension	Description
Topic	.RTF	Contains text for the Help file and codes needed to link topics. Also contains graphics or codes needed to include graphics. Text in topic files must be in rich text format (RTF). You must have at least one topic file to create a Help file.
Project	.HPJ	Contains a list of text and graphic files needed for the Help file. Also contains macro and secondary window definitions, and instructions the Help Compiler uses to control the compile process. Text in a Help project file must be in ASCII format. You must use only one project file for each Help file.
Bitmap	.BMP	Contains a single graphic in Windows bitmap format, such as a screen image from the application or a bullet in text. You can use one or more bitmap files in a Help file. Bitmap files are optional.
Metafile	.WMF	Contains a single graphic in Windows metafile format, such as a diagram or other graphic created by a drawing program. You can use one or more metafiles in a Help file. Metafiles are optional.
Hypergraphic	.SHG	Contains a bitmap or metafile graphic produced by SHED.EXE, to which you have added one or more hot spots using the Hotspot Editor. You can use one or more hypergraphics in a Help file. Hypergraphics are optional.
Multiple-resolution bitmap	.MRB	Contains more than one version of the same bitmap at different screen resolutions compiled into a single file. Multiple-resolution bitmaps must be produced by MRBC.EXE. You can use one or more multiple-resolution bitmaps in a Help file. Multiple-resolution bitmaps are optional.


  Creating a Help System

To create a Help system for your application, you perform a number of primary tasks. This section identifies these tasks and shows you where to find detailed information on each step of creating a Help system.

To create a Help system:

1.	Gather the information that you want included in the Help topics.

2.	Plan the Help system by creating an outline of its scope and a list of topics.

»Chapter 2, Planning the Help System,« describes considerations to keep in mind when planning your Help system.

3.	Write and edit the text for the topics.

4.	Enter the required control codes into the text files.

Control codes determine how the user moves around the Help system. »Chapter 3, Creating the Topic Files,« describes these codes.

5.	Create graphics, if needed.

»Chapter 4, Creating Graphics for Help,« describes how to create visually appealing graphics and how to create hypergraphics that link information in the Help system.

6.	Create macros, if needed.

Macros can improve your Help system by providing faster access to Help features. »Chapter 5, Creating Help Macros,« describes how to create macros and provides reference information for all Help macro commands.

7.	Create the project files and compile the source files.

»Chapter 6, Building the Help Files,« describes how to create Help project files and compile Help source files.

8.	Test and debug the Help system.

»Chapter 7, Testing and Debugging Help Files,« describes how to test and debug Help source files. This chapter also contains the Help Compiler error messages.

9.	Program your application so it can access the Help system.

»Chapter 8, Programming Your Application for Help,« describes how to prepare your application to use the Help system.


  How Help Appears to the User

To the user, the Help system appears as part of your application, consisting of text and graphics displayed in the Help window. The WinHelp application interprets and displays the elements of your Help file — text, pictures, hypertext links, and keyword search index — and lets the user explore the contents of the file.

Note  Except for adding notes and bookmarks, users can only view a compiled Help file; they can't change its content or structure.


  Topics

The primary unit of information in a Help file is the topic. A topic is a self-contained body of text and graphics, similar to a page in a book. Unlike a page, however, a topic can hold as much information as you require. If there is more information in a topic than the Help window can display, scroll bars appear to let the user scroll through the information.


  Pop-Up Windows

Some topics contain hot spots that a user can click to get definitions of terms or lists of information. By clicking the dotted-underlined word, the user can read the information in a pop-up window, an overlapping box or window that remains on screen until the user clicks the mouse again or presses any key.

Jumps are cross-references to related topics. When a user clicks a jump, indicated by a solid underline, the Help window switches to a different topic. For details about displaying topics in pop-up windows or creating jumps between topics, see »Chapter 3, Creating the Topic Files.«


  Secondary Windows

Another way to display additional information without leaving the topic in the main Help window is to use a secondary window. Secondary windows are opened with a hot spot; they have a title bar and scroll bars, but no menu bar. They remain open until closed by the user, whether or not the main Help window is open.

Secondary windows are useful for glossaries, procedures, examples, sample code, indexes, alphabetic lists, or other information the user may want to have available with or without the main Help window.

You define the characteristics of a secondary window in the Help project file. For details about defining secondary windows, see the section »Defining Window Attributes«. For details about displaying topics in a secondary windows, see »Chapter 3, Creating the Topic Files.«


  How Help Appears to the Developer

To the developer, the Help system is a group of topic files — text files that include special formatting codes.

To create this topic, you must write the text, format it, and insert codes using underlined text, hidden text, and footnotes. Footnotes in the text contain linking information required by the Help Compiler. For information on formatting text, see »Chapter 2, Planning the Help System.« For information on creating topics and entering control codes, see »Chapter 3, Creating the Topic Files.«

From a programming perspective, WinHelp is a stand-alone application in Windows that the user can run like any other application. However, applications can provide context-sensitive Help so that users can get Help on a particular topic directly by pressing F1, instead of scrolling through the main Help menu.

Your application can also call the WinHelp function to ask Windows to run the WinHelp application and to display a specific topic. For information on calling the WinHelp function, see »Chapter 8, Programming Your Application for Help.«


  Skills Needed to Create a Help System

Because the WinHelp application integrates text and graphics, you might use many skills during the creation of a Help file — analysis, writing, editing, graphic design and production, programming in Windows, and compiling. This manual assumes you have this expertise or work with others who do.

The actual skills necessary to create the topic files are much simpler. Still, you should know:

•	How to work with the Microsoft MS-DOS® operating system (using commands, editing files, and navigating across directories).

•	How to work with the Microsoft Windows operating system.

•	How to use Microsoft Word for Windows (or other RTF editor).


  Chapter 2  Planning the Help System

The initial task for the Help writer is to gather information for the Help topics; the second task is to develop a plan for the Help system. This chapter discusses planning the Help system for a particular application and provides information on:

•	Defining your audience.

•	Planning the content of your Help system.

•	Planning the structure of Help topics.

•	Planning context sensitivity.

•	Determining the topic file structure.

•	Designing Help topics.

•	Managing Help topic files.

•	Obtaining more information about planning Help.

You may want to make your plan explicit with a design document that includes an outline of Help information, a diagram of the structure of topics, and samples of the kinds of topics your Help system will include. Keep in mind that context-sensitive Help requires increased development time, especially for the programmer.


  Defining Your Audience

Your audience determines the type of information you make available in your Help system and how you present that information.

Users of Help systems can be classified in the following ways.

User	Background
Computer novice	Completely new to computing.
Application novice	Some knowledge of computing, but new to your kind of application. For example, if you're providing Help for a spreadsheet program, the application novice may be familiar only with word-processing packages.
Application intermediate	Knowledgeable about your kind of application.
Application expert	Extensive experience with your kind of application.


  Planning for Novice Users

Novice users need help learning tasks and getting acquainted with the interface. These users require topics that define new, application-specific terminology, or that offer conceptual and task-oriented information.


  Planning for Intermediate and Expert Users

Sophisticated users occasionally use Help for a procedure or term, but most often need to refresh their memory of statements and functions. The expert user tends to either look up reference information or seek help only with statement or function syntax, keyboard equivalents, and shortcut keys. This is especially true for users of, for example, a language Help system.


  Planning for All Types of Users

There are no rules for determining the overall content of your Help system. If you're providing a Help system for all types of users, you may want to document menu commands, procedures, definitions of new terms, features, functions, and all other relevant aspects of your application. Let the definition of your audience guide you when deciding what information to include in your topics.

Consider carefully the decision to implement context-sensitive Help. Because context-sensitive Help demands a close working relationship between the Help writer and the application programmer, the development time required to create a successful Help system increases significantly.


  Planning the Content of Your Help System

You should create as many topics as necessary to provide all the Help your users may need. Your topics should be concise and should cover the breadth of the application. Because reading from a screen strains a user's eye faster than reading the same information on a printed page, you should keep topics brief.

Help systems should include:

•	A Help menu.

•	Contents screens.

•	Keyword lists and indexes.

•	Individual Help topics.


  Planning the Help Menu

A good Help menu includes the following core selections:

•	Contents

•	Search

•	About <applicationname>

Other Help menu selections provide additional benefits to the user. If you include any of these features, place them between the Search and the About the Application selections:

•	Index (full alphabetic index)

•	Keyboard Guide

•	How to Use Help

Do not use separator bars between the initial navigational entries on your Help menu (Contents, Search, or Index).


  Planning Contents Screens

The purpose of the main Contents screen is to provide an overview of the Help system contents and to give clear, logical paths to information. It should work like the table of contents in a book.

Sublevel Contents Screens

Sublevel contents screens open paths from the main contents to individual topics. Category entries on the main contents screen jump to sublevel contents screens that either list Help topics in that category or display other sublevel contents screens.

Guidelines

Follow these guidelines when planning contents screens:

•	List entries under several different category headings. For example, you can separate reference entries and procedural entries.

•	Present entries by category, as either text jumps or graphic hot spots. List entries in a logical order (for example, by learning-path, frequency of use, or alphabetically).

•	Include no more than 10 entries, if possible. Avoid having more than 15 entries. If your list is longer, break it up with headings or into more than one contents screen.

•	Avoid deeply nested sublevels so the user doesn't have to jump more than two or three times to display a Help topic.

•	Avoid long scrolling lists of entries on contents screens with entries that jump to individual Help topics.


  Planning for Keyword Lists and Index Topics

Keyword lists and index topics are navigational aids used with contents screens. The keyword list and index topics should be similar to each other and work like a book index.


  Planning the Structure of Help Topics

One of the first things you should do when planning a Help system is identify the topics that you want to appear in the system. You should then decide how you want to organize those topics into a usable structure.

Whatever structure you use, try to minimize the number of lists that users must jump through to obtain information. Avoid making users move through multiple levels to reach a topic. Most Help systems function well with only two or three levels.


  Structuring Topics Into a Hierarchy

Many Help systems structure topics hierarchically — that is, topics are arranged into a ranked tree structure. At the top of the hierarchy is an index, or a table of contents, or both. The index and table of contents list individual topics or categories of topics available to the user.

Topics themselves can be related hierarchically. Each successive step takes the user one level down in the hierarchy of the Help system until the user reaches discrete and specific topic information. The hierarchical relationship of Help topics determines in part how the user navigates through the Help system.

Moving from the index to a topic, the user proceeds from the general to the specific. A hierarchical structure provides a point of reference within Help.


  Structuring Topics for Search Access

Users are not constrained to navigate up and down the hierarchy; they can jump laterally from one topic to another, moving across categories of topics. The effect of jumps is to bypass the hierarchical structure.

For example, the WinHelp application (WINHELP.EXE) contains a Search feature that lets the user type a keyword into a dialog box to search for topics associated with that keyword. WinHelp then displays a list of topics that relate to the keyword.

If users know the feature on which they need help, they can usually find the information faster by using Search, rather than moving through the hierarchical structure. For more information about the Search feature, see »Coding Keywords«.


  Structuring Topics in Sequences

In addition to ordering topics hierarchically, you can order them in a logical sequence that suits your audience. The logical sequence, or browse sequence, lets the user choose the Browse buttons to move from topic to topic. Browse sequences are especially important for users who like to read several related topics at once, such as the topics covering the commands on the File menu, or a series of sequential steps leading to the completion of a task, such as copying a file. For more information about browse sequences, see »Browse Sequences«.


  Planning Context Sensitivity

WinHelp supports context-sensitive Help. When written in conjunction with programming the application, context-sensitive Help lets the user press F1 for Help on the item that currently has the focus.

In Visual Workbench, for example, if the user types a C++ keyword in the Edit window and then presses F1, Visual C++ starts the Help system and displays the information specific to that keyword.


  Creating Context References

Developing context-sensitive Help requires the Help writer and the application programmer to agree on a list of context references so that WinHelp and the application pass the correct information back and forth. A context reference is a unique number or string that corresponds to a particular object in the application — for example, to a menu command, form, control, or screen region. You can assign context references arbitrarily, but you should not change them afterward. You use context references to create links between the application and the corresponding Help topics.

You enter context references and their corresponding context strings in the Help project file (.HPJ), which the Help Compiler uses to build a Help file. For details on how to create a Help project file, see »Creating the Help Project File«.


  Assigning Context References

You can provide context-sensitive Help for an object by assigning it a context reference. How you assign context references, the objects to which you can assign them, and whether you use numbers or strings depend on the product you used to develop your application.

The context references assigned in the Help project file should correspond to the context references that the application sends at run time to invoke a particular topic. For more information on assigning context references, see »Chapter 8, Programming Your Application For Help.«


  Default Context Numbers

If you do not explicitly assign context numbers to topics, the Help Compiler generates default values by converting topic context strings into context numbers. For more information on context-sensitive Help and context strings, see »Mapping Context-Sensitive Topics«.


  Tracking Context References

To manage context references and file information, you may want to create a Help tracking file. For information about using a tracking file, see »Creating a Help Tracker« later in this chapter.


  Determining the Topic File Structure

Topic files are source files that contain the text, graphics, and hidden codes that are compiled into the Help system. Although the number and content of topic files differ between Help systems, their structure is consistent. Each file holds one or more topics separated by page breaks.


  Choosing a File Structure

When choosing a file structure, consider the scope and content of the Help system you are planning. For example, you could place all Help topics in a single topic file, or you could place each Help topic in a separate file. For large projects, these extremes may create tracking and debugging problems. Most projects use several topic files, dividing the contents by subject or writer.


  Choosing the Number of Topics

The number of topics relates to the number of features covered by the Help system. You cannot make extensive changes to the application without making changes to your Help system. For instance, if additional product features are added to the application, then additional topics must be created in your Help system to describe them.


  Designing Help Topics

How information in the Help window appears to the user is primarily a function of the layout of the Help topic. WinHelp supports a number of text attributes and graphic images you can use to design your Help window.


  Topic Length

Optimally, a Help topic is one, or at most, two screens long. A screen is defined as approximately one-half the width of a maximized window and 15 − 20 lines long.

You can minimize topic length by breaking information into smaller categories, using multiple-column lists of topics, or creating pop-up and secondary windows for subordinate information.


  Using Jumps and Pop-Up Windows in Topics

Avoid using too many pop-up windows on a single screen because they can make the screen hard to read. For example, if you use pop-up windows for definitions, each definition should pop up only the first time the word appears. An exception to this may occur in long topics, where an author includes a second definition for users who have scrolled past the first.

Avoid using jumps in running text that replace the topic in the main Help window. If you must use a jump in running text, consider using a secondary window so that the original topic remains displayed in the main Help window.


  Designing the Text

Help text files are not limited to plain, unformatted text. You can use different fonts and font sizes, include color and graphics to emphasize points, indent paragraphs to present complex information, and use a variety of other visual devices. Research on screen format and Help systems has produced the following general guidelines for presenting information to users.


  Consistency

Keep the finished Help system in mind when planning. For example, develop a consistent strategy for using secondary windows. Decide whether you will use pop-up windows only for definitions of terms or for notes or tips, too.

Make these decisions based on the needs of your audience, but be rigorously consistent in your design. Users expect Help topics to have the same appearance, regardless of the information presented. Consistent titling, highlighting, fonts, and text positioning are essential to an effective Help system.


  Language

Use language that is appropriate for the audience you have identified. Language that is too sophisticated can frustrate users by requiring them to learn the definitions of unfamiliar terms and concepts.

Consider changes you might have to make if your application has an international audience. Certain visual elements that communicate well in your country might be misunderstood by users in other countries.


  Paragraph and Text Length

Use short paragraphs. Online users become overloaded with text more easily than readers of printed material. Breaking your text into short paragraphs helps avoid this problem.

Use a minimum of text. Reading speed for online text decreases by 30 percent compared to printed text. Concise text helps compensate for this decreased reading speed.


  White Space

Use white space to isolate information visually and to make online text more readable, but also consider the overall space a topic will occupy on the screen. Users tend to think there is more information on a screen than actually exists. For example, if the ratio of white space to text is 50:50, users perceive it to be 40:60. Whenever possible, work with a graphic designer to plan white space, color, leading, and other visual elements.


  Highlighting

Use highlighting techniques judiciously. WinHelp provides a variety of highlighting devices, including fonts, font sizes, and color. Careful highlighting can help users find information quickly. Using too many devices confuses them. Use only one or two fonts at a time.


  Fonts and Font Sizes

WinHelp can display text in any font and size available to the Help system. When you compile the topic files, the Help Compiler (HC31.EXE) tries to use the fonts and sizes found in the topic files. If a font or font size cannot be matched exactly, the Help system uses the closest available font and font size on the user's system.

Microsoft Windows version 3.1 provides three types of fonts:

•	Bitmap fonts in specific sizes designed for the resolution of the user's system.

•	TrueType® fonts that can be scaled to almost any size and that work for both screen display and printer output.

•	Vector fonts designed for use with plotters.

If you write Help files using the fonts and sizes included with Windows 3.1, the fonts displayed in the Help file will closely match those seen in the editor or word processor. Because fonts other than those shipped with Windows 3.1 may not be available on a user's machine, you might want to limit your font selection to those that ship with Windows 3.1.

Bitmap Fonts

The bitmap fonts included with Windows 3.1 are:

•	Courier (10, 12, 15 points)

•	MS Sans Serif (8, 10, 12, 14, 18, 24 points)

•	MS Serif (8, 10, 12, 14, 18, 24 points)

•	Symbol (8, 10, 12, 14, 18, 24 points)

TrueType Fonts

The TrueType fonts included with Windows 3.1 are:

•	Arial (normal, bold, italic, and bold-italic)

•	Courier (normal, bold, italic, and bold-italic)

•	Times New Roman (normal, bold, italic, and bold-italic)

•	Symbol

Vector Fonts

The vector fonts included with Windows 3.1 are:

•	Modern

•	Roman

•	Script

Since WinHelp supports any font in Windows 3.1, you can use the Symbol font to include special symbols, such as arrows, in your topic files.


  Designing Graphics

Use graphics to help explain visual events, but remember that graphics attract a user's eye faster than text. Crop your images to remove distracting information.

WinHelp supports the use of bitmaps and Windows metafile graphic formats. You can place and display graphics anywhere on the screen. Text can appear next to the graphic or below it

Graphics are most effective when they contribute to understanding. Graphics not tied to the information can be distracting rather than helpful. For more information on placing graphics into your Help files, see »Chapter 4, Creating Graphics for Help.«


  Using Color

You can include color graphic images, but you must use only the system colors available with Windows 3.1. If you use graphics tools that support an enhanced color palette to create or capture images, these images may not always be displayed with the intended colors. Remember that much less detail and subtlety of color is available online than in print, and poor use of color can cause user eyestrain.


  Effects of Color

When designing the "look" of your Help system, you should consider the visual impact of color. For example, color attracts the eye and adds emphasis. Items of the same color appear related, while items of different colors appear to belong to separate groups. Different colors have different associations for people and cultures. Don't rely on color to convey a particular meaning. Red, for example, can imply "warning" in one culture and "happiness" in another.

Add color to your Help files with extreme care. Overuse of color actually makes information more difficult to process because the user slows down to think about what the different color means. In particular, adding color to text makes it difficult to read, and its meaning may be easily confused with green hot spots in text. Because green is the color that indicates jumps or pop-up hot spots, avoid using green for anything else.


  Strategies for Using Color

Use color to convey information about structure, such as grouping or hierarchy, rather than as decoration or to imply a particular meaning or use. However, don't depend on color alone to communicate structure. The user's monitor may not have color or may not correctly display colors. Some users may be color disabled.

Design for VGA colors as a best-case scenario. Avoid the brighter colors of the Windows 16-color palette. Bright colors can cause after-images, complementary (opposite) colors appear to vibrate, and both can cause eyestrain. If you must use colored text, use strong contrast. Do not put light text on a light background or bright text, like bright-green, on a bright background, like magenta.

It is helpful to use color for the hidden text coding in the source files. Colored text stands out and makes it easier to debug and localize the topic files.


  Managing Help Topic Files

You can save Help topic files in the default word-processor format or in RTF (rich-text format). If you always save your files in RTF, and later need to make a change, the word processor may take additional time to convert the format as it reloads the file. Since you will make numerous changes during the Help development process, you may want to minimize this delay by saving topic files in default format. Before you compile the Help file, however, it must be saved in RTF.


  Keeping Track of Files and Topics

It is important to keep track of all topic files. A tracking system should:

•	Ensure that no topics are left out of the build process.

•	Ensure that each topic is assigned a unique context string.

•	Double-check browse sequencing within general and specific lists.

•	Show keyword and title matches.

•	Show the location of the text for each topic.

•	Keep track of changes to files and their current status.

•	Track any other aspect of the Help development process that you think is essential.

At minimum, writers need to track their own topic files and relay the file names to the person responsible for creating the Help project file.


  Creating a Help Tracker

While it is very helpful to track topic files throughout the development cycle, you can use any tracking tool that suits your needs. You can maintain a current list of topics in an ASCII text file, in a Microsoft Excel worksheet, or in another format.


  Contents of a Help Tracker

When you or another writer creates a topic, update the Help tracking file to reflect the change. The contents of the tracking file are not rigidly defined but can contain entries for the file name, context string, title, browse sequence, and keywords for each topic. You may want to include optional information, such as date created, status, and author. How you organize this information is entirely up to you.

If your application implements context-sensitive Help, you may want to keep track of the context-sensitive information as well. This information is necessary only if you are assigning context references to topics in the Help project file.


  More Information About Planning Help

For additional information about planning your Help system, see the following sources.

Bradford, Annette Norris. "Conceptual Differences Between the Display Screen and the Printed Page." Technical Communication (Third Quarter 1984): 13 − 16.

Galitz, Wilbert O. Handbook of Screen Format Design. 3d ed. Wellesley, MA: QED Information Sciences, Inc., 1989.

Horton, William K. Designing & Writing Online Documentation: Help Files to Hypertext. New York: John Wiley & Sons, Inc., 1990.

Houghton, Raymond C., Jr. "Online Help Systems: A Conspectus." Communications of the ACM 27 (February 1984): 126 − 133.

Queipo, Larry. "User Expectations of Online Information." IEEE Transactions on Professional Communications PC 29 (December 1986): 11 − 15.


  Chapter 3  Creating the Topic Files

Help topic files are text files that define what the user sees when using the Help system. Topic files can include an index, information on the system, a list of commands, or a description of how to perform a task.

Creating topic files involves writing the text that the user sees and then entering control codes that determine how the user moves from one topic to another. This chapter provides information on:

•	Choosing an authoring tool.

•	Structuring Help topic files.

•	Coding Help topic files.

•	Linking topics with jumps and pop-up windows.

•	Creating a nonscrolling region.


  Choosing an Authoring Tool

To write your text files, you'll need a text editor or word processor that saves files in rich-text format (RTF). Your choices include, but are not limited to:

•	Microsoft Word for Windows version 1.0 or later.

•	Microsoft Word for MS-DOS version 5.0 or 5.5.

•	Microsoft Word Macintosh® Series, version 3.0 or 4.0.

•	Other word processors that support RTF.

With the Microsoft Word RTF capability, you can insert the coded text that defines Help terms, such as jumps, keywords, and pop-up definitions. If you choose an editor other than one of the Microsoft Word products, make sure it creates Help files that work as you intend.


  Structuring Help Topic Files

A Help topic file typically contains multiple Help topics. To identify each topic within a file:

•	Topics are separated by hard page breaks.

•	Each topic has a unique identifier, or context string.

•	Each topic can have a title.

•	A topic can have a list of keywords attached to it. These keywords are used to access information quickly using the Search feature.

•	Each topic can have a build-tag indicator.

•	Any topic can be assigned a browse sequence.

Note  For information about inserting page breaks between topics, see the documentation for the editor you are using. For information about assigning context strings and titles to topics, see the following sections in this chapter.


  Coding Help Topic Files

The Help system uses control codes for particular tasks, as described in the following table.

Control code	Name	Purpose
Number sign (#) footnote	Context string	Defines a context string that uniquely identifies a topic. Because hypertext relies on links provided by context strings, topics without context strings can be displayed only with keywords or browse sequences.
Dollar sign ($) footnote	Title	Defines the topic title. Titles appear in a list box when you use the Search feature. Titles are optional.
Letter K footnote	Keyword	Defines a keyword with which the user searches for a topic. Keywords are optional.
Plus sign (+) footnote	Browse sequence number	Defines a sequence that determines the order in which the user can browse through topics. Browse sequences are optional.
Asterisk (*) footnote	Build tag	Defines a tag that specifies topics the Help Compiler builds into the system conditionally. Build tags are optional, but when they are used, they must appear first in a topic.
Strikethrough or double-underlined text	Jump text	Indicates the text the user can choose to jump to another topic.
Underlined text	Definition	Specifies that a pop-up window appears when the user clicks the mouse button or presses ENTER.
Hidden text	Context string	Specifies the context string for the topic that will be displayed when the user selects the text that immediately precedes it.
The following sections in this chapter describe how to assign these control codes to a topic.

Note  If you use build tags, footnote them at the very beginning of the topic. After the initial build tag footnote, footnotes can be placed in any order.


  Coding Context Strings

Context strings identify each topic in the Help system. Each context string must be unique — you can assign it to only one topic within the Help project (.HPJ) file.

Assigning a context string gives a topic an identifier that you can use to create jumps to that topic or to display it in a pop-up window. Although the Help Compiler can successfully compile topics that don't have a context string, the user of the Help system can't display them unless they contain keywords or are part of a browse sequence.

To assign a context string to a Help topic:

1.	Place the insertion point to the left of the topic heading.

2.	Insert the number sign (#) as the footnote reference mark.

Note that a superscript number sign (#) appears next to the heading.

3.	Type the context string as the footnote.

Be sure to allow only a single space between the number sign (#) and the string. Context strings are not case-sensitive and cannot include spaces.

Valid context strings can contain the alphabetic characters A − Z, the numeric characters 0 − 9, and the period (.) and underscore ( _ ) characters. The following context-string footnote identifies a topic called "Opening an Existing Text File":

# OpeningTextFile

Although a context string has a practical limitation of 255 characters, you should keep the strings short so they are easier to enter into the text files.

You can assign additional context strings to a topic by placing them in various locations throughout the topic. When the user clicks a hotspot that is coded to one of the additional context strings, WinHelp jumps to the specified location in the topic.

For example, in an alphabetic list of commands or any index-style list, you can use a hypergraphic in a nonscrolling region at the beginning of the topic and add a context string in front of each uppercase letter. When users click a letter in the graphic, the jump takes them to that letter in the list.


  Coding Titles

In the WinHelp application, the title of a topic can appear:

•	At the beginning of the topic.

•	In the Bookmark menu, if the topic contains a bookmark.

•	In the Search dialog box, if the topic contains keywords.

To place the title at the beginning of the topic, type it as the first paragraph. You must define code for the title in a footnote for the title to appear correctly in the Bookmark menu and the Search dialog. Although the Help Compiler doesn't require that a topic have a title footnote, only those topics in the main Help window or a secondary window that do have a title footnote appear correctly in the Bookmark menu.

To assign a title to a Help topic:

1.	Place the insertion point to the left of the topic heading.

2.	Insert a footnote with a dollar sign ($) as the footnote reference mark.

Note that a superscript dollar sign ($) appears next to the heading.

3.	Type the title as the footnote.

Be sure to allow only a single space between the dollar sign ($) and the title.

The following example shows a footnote that defines the title for a topic:

$ Help Keys

When adding titles, keep in mind the following restrictions.

Item	Restrictions
Characters	Titles can be up to 128 characters. The Help Compiler truncates title strings longer than 128 characters. The Help system displays titles in a list box when the user searches for a keyword or enters a bookmark.
Formatting	Do not format title footnote entries.


  Coding Keywords

With the WinHelp application, a user can search for topics using keywords assigned to those topics. WinHelp lists matching topics by their titles (as defined in the title footnote) in the Search dialog box. The keyword search facility serves the same purpose as the index in a book. Because a keyword search is often the fastest way for users to access Help topics, you'll probably want to assign keywords to most topics in your Help system.

Note  Because the title of the topic appears in the Search dialog box when the user searches for the keyword, you should specify a keyword footnote only if the topic has a title footnote. Topics that do not have titles but that are accessible through keywords are listed as >>Untitled Topic<< in the list at the bottom of the Search dialog box.

To assign a keyword to a Help topic:

1.	Place the insertion point to the left of the topic heading.

2.	Insert an uppercase K as the footnote reference mark.

Note that a superscript K (K) appears next to the heading.

3.	Type the keyword, or keywords, as the footnote.

Be sure to allow only a single space between the K and the first keyword. If you add more than one keyword, separate them with a semicolon (;).

The following is an example of keywords for a topic:

K open;opening;text file;ASCII;existing;text only;documents;

When the user performs a search on any of these keywords, the corresponding titles appear in a list box. A keyword can appear in more than one topic.

When adding keywords, keep in mind the following restrictions.

Item	Restrictions
Characters	Keywords can use any ANSI character, including accented characters. The maximum length for keywords in a single topic is 255 characters. Both phrases and individual words can be keywords, since a space embedded in a key phrase is considered a character.
Phrases	Help searches for any word in the specified phrase.
Formatting	Keywords are unformatted.
Case sensitivity	Keywords are not case-sensitive; however, in the Search dialog box they appear just as they are typed in the source file.
Punctuation	Except for semicolons, you can use punctuation just as in printed indexes.


  Creating Multiple Keyword Tables

Multiple keyword tables let you define additional lists of keywords in a Help file. Your application can display these keyword tables using the WinHelp function. You can use this feature to provide context-sensitive Help for special words in your application. With multiple keyword tables, users familiar with keywords from a different application can find matching keywords in your application.

Writing additional keyword tables is a two-part process. First, the MULTIKEY option must be placed in the [OPTIONS] section of the Help project file. (See »MULTIKEY Option«.)

Second, you must write and label the topics to be associated with the additional keyword table. Footnotes are assigned in the same manner as the normal keyword footnotes, except that the letter specified with the MULTIKEY option is used. The keyword footnote is not case-sensitive.

Be sure to associate only one topic with each multiple keyword. The WinHelp application doesn't display the normal Search dialog box for a multiple keyword search. Instead, it displays the first topic found with the specified keyword. If you want the topics in your additional keyword table to appear in the Search dialog box, you must define the same keyword using the K footnote in the topic.

Program your application to display the Help topic associated with a given string in a specified keyword table. Keywords are sorted without regard to case for the keyword table. For information on the parameters passed by the application to call a topic found in an alternate keyword table, see »Searching for Help with Keywords«.


  Browse Sequences

With the Browse Forward (>>) and Browse Back (<<) buttons on the toolbar in WinHelp, a user can move through topics in a linear fashion, as in reading a book. The order the user follows when moving from topic to topic is called a browse sequence. A browse sequence is determined by codes established by the Help writer.

To plan browse sequences in Help topics:

1.	Group topics and arrange them in a logical sequence within each group.

2.	Code topics to implement the sequence.

3.	Test the sequence in a build to make sure it is logical.

Note  WinHelp version 3.1 doesn't automatically provide Browse Forward (>>) and Browse Back (<<) buttons. If your Help file includes one or more browse sequences, you must use the BrowseButtons( ) macro so the user can browse forward and backward.


  Organizing Browse Sequences

When organizing browse sequences, arrange the topics in an order that makes sense to the user. You can organize topics into a browse sequence:

•	In alphabetical order, by subject.

•	From the least complex or difficult to the most complex or difficult.

•	For topics describing menu selections, from the top of the menu list to the bottom.

Browse codes have two parts: group and order. Both are sorted by their ASCII values. The order can be numeric or alphabetical. The following example shows browse sequences for the menu commands for a given application. The Help writer has organized the topics that describe the menu selections into two browse sequences, one for each menu. You can, of course, choose a different order.

SampleApp Commands

File Menu - commands:005

New Command - file_menu:005

Open Command - file_menu:010

Save Command - file_menu:015

Save As Command - file_menu:020

Print Command - file_menu:025

 	Printer Setup Command - file_menu:030

Exit Command - file_menu:035

Edit Menu - commands:010

Undo Command - edit_menu:025

Cut Command - edit_menu:015

Copy Command - edit_menu:010

Paste Command - edit_menu:020

Clear Command - edit_menu:005

Select All Command - edit_menu:030

Word Wrap Command - edit_menu:035

Type Face Command - edit_menu:040

Point Size Command - edit_menu:045

Each line consists of a group name followed by a colon and an order string. The group name is optional. If the sequence does not have a group name, as in the following example, the Help Compiler places the topic in a "null" list:

Window Menu - 120

Note  The numbers used in the browse sequence example begin at 005 and advance in increments of 005. Generally, when using numbers in order strings, it is good practice to skip one or more numbers in a sequence so that, if necessary, you can add new topics later. Skipped numbers are of no consequence to the Help Compiler; only their order is significant.

Order strings establish the order of topics within a browse group. Order strings can consist of any alphanumeric characters. During the compiling process, strings are sorted using the ASCII sorting technique, not a numeric sort.

Both the group and order portions of a sequence can be several characters long. If you use only numbers in the order strings, make sure the strings are all the same length; otherwise, a higher sequence number could appear before a lower one. For example, the number 100 is numerically higher than 99, but 100 will appear before 99 in the sort used by Help, because Help is sorting by ASCII value. To keep the topics in their correct numeric order, make 99 a three-digit string: 099. To browse through the topics in alphabetical order by title, use the topic title as the order string.

Note  If you use only letters in the order strings, make sure you use all uppercase or all lowercase letters; otherwise, they won't appear in alphabetical order. For example, "Time Series" appears before "Timer" because "S" is uppercase, even though "r" comes before "S."


  Coding Browse Sequences

After determining how to group and order topics, code the browse sequence by assigning the appropriate group name and order string to each topic.

To assign a browse sequence code to a Help topic:

1.	Place the insertion point to the left of the topic heading.

2.	Insert the plus sign (+) as the footnote reference mark. Note that a superscript plus sign (+) appears next to the heading.

3.	Type the group name, a colon, and the order string as the footnote. (Remember that a group name is optional.)

The following footnote defines the browse sequence number for the Edit menu topic in the preceding browse sequence example:

+ commands:010


  Assigning Build Tags

Build tags are strings you assign to a topic that the Help project file can specify to include or not include in a build. Build tags can be made up of any alphanumeric characters and are not case-sensitive. A tag can't contain spaces within the string. You can specify multiple build tags by separating them with a semicolon (;).

Each topic can have one or more build tags. Build tags are not a necessary component of your Help system; however, they do provide a means of supporting different versions of a Help system without having to create different source files for each version. Topics without build tags are always included in a build, along with all tagged topics not expressly excluded from that particular build in the build expression.

You insert build tags as footnotes, using the asterisk (*). When you assign a build-tag footnote to a topic, the Help Compiler includes or excludes the topic according to information specified in the BUILD option and [BUILDTAGS] section of the Help project file. For information about the BUILD option, the [BUILDTAGS] section, and the Help project file, see »Chapter 6, Building the Help Files.«

To assign a build tag to a Help topic:

1.	Place the insertion point at the beginning of the topic heading line, so that it precedes all other footnotes for that topic.

2.	Insert the asterisk (*) as the footnote reference mark. Note that a superscript asterisk (*) appears next to the heading.

3.	Type the build-tag name as the footnote. Be sure to allow only a single space between the asterisk (*) and the build tag:

* AppVersion1; AppVersion2; Test_Build

Note  You must declare all build tags in the Help project file.

The Help Compiler includes topics that do not have a build-tag footnote in all builds, regardless of the build-tag expressions defined in the Help project file. For this reason, you may want to use build tags primarily to exclude specific topics from certain builds. If the Help Compiler finds any build tags not declared in the Help project file, it displays an error message.

By allowing conditional exclusion of specific topics, you can create multiple builds using the same source files. This saves writing time and allows you to maintain a higher level of consistency across your product lines.


  Linking Topics with Jumps and Pop-Up Windows

The context strings you code in the topics of a topic file give you a way to link those topics together. Without linking, the topics in a Help file would be isolated islands of information; a user could not move from one topic to another. Of course, keywords and browse sequences provide additional routes through the topics in a Help file. But the most convenient way of linking topics is to create hot spots that enable users to jump between topics or display a pop-up window.


  Jumps Between Topics

Jumps between topics in the WinHelp application serve a purpose similar to cross-references in a book. These jumps consist of specially coded text or graphics that cause the WinHelp application to display another topic in the main Help window.

In the Help window, jumps appear underlined and on color monitors appear green. For example, the strikethrough text (double-underlined in Word for Windows) New Command appears as New Command in green text to the user.

To code a word or phrase as a jump in the topic file:

1.	Place the insertion point at the place in the text where you want to enter the jump term.

2.	Select the strikethrough (or double-underline) feature of your editor.

3.	Type the jump word or words in strikethrough mode.

4.	Turn off strikethrough and select the editor's hidden text feature.

5.	Type the context string assigned to the topic that is the target of the jump.

When coding jumps, keep the following in mind:

•	No spaces can occur between the strikethrough (or double-underlined) text and the hidden text.

•	Spaces before or after the jump term are not permitted.

•	Be careful not to format paragraph marks accidentally as hidden text.


  Jumps to Topics in Another Help File

The Help system you design can consist of more than one Help file. In these cases, you may want to jump from a topic in one Help file to a topic in another Help file. By providing extra information in the hidden text of the jump code, you can jump between Help files. Use this syntax to create jumps between Help files:

Jump textcontextstring@d:\path\file.hlp

The double-underlined text (shown as underlined) is the hot spot clicked by the user to jump to the new topic. The remaining text in the syntax is formatted as hidden text. As with a jump to another topic in the same Help file, the context string of the new topic immediately follows the hot spot text. To jump to another file, follow the context string with the @ symbol and then the path and file name of the Help file containing the new topic. You can provide only a file name if you want to use a relative path.

If you create jumps from one Help file to another, keep in mind that when the user jumps to a different file, the only way to return to the first Help file is by using the Back button, the History list, or through an explicit jump that calls the first file. (The Contents and Browse buttons work only within the confines of the current Help file.)


  Jumps to a Secondary Window

When you create a jump to another topic, the WinHelp application assumes you want to display the topic in the main Help window. But you can code the jump to display the new topic in a secondary window. Use this syntax to code a jump that displays a topic in a secondary window. Note that double underline is shown as single underline in the following example.

Jump textcontextstring>windowname

The syntax is similar to the syntax used to jump to a topic in another Help file. Immediately following the context string of the new topic is a greater than (>) sign followed by the name of the secondary window. For more information on defining names for secondary windows, see »Defining Window Attributes«.


  Combining Jumps

You can combine a jump to a topic in another Help file and a jump to a secondary window using this syntax. Note that double underline is shown as single underline in the following example.

Jump textcontextstring@d:\path\file.hlp>windowname


  Jumps to Pop-Up Windows

Some topics contain words or phrases that may be unfamiliar to the user. To get the definition of a word or phrase, the user selects the word and then clicks the mouse button or presses the ENTER key, causing the definition to appear in a pop-up window within the Help window. You decide which words to define, considering the audience that will be using your application and the terminology that may be new or specific to the application.

Note  Pop-up windows need not be limited to definitions, although it's important to keep the text brief, since the main purpose of a pop-up window is to display definitions or notes that don't distract the user from the main topic. For the same reason, pop-up windows should not include information the user needs to do the task at hand.

Defining a term requires that you:

•	Create a topic that defines the term. The definition topic must include a context string. See »Coding Context Strings« earlier in this chapter.

•	Provide a jump for the definition topic where you want the definition to appear. For more information, see the following section.


  Creating Definition Topics

You create definition topics the same way as any other topic, although you probably won't provide search access with keywords.

To create a definition topic:

1.	Place the insertion point where you want to place the term that requires definition.

2.	Select the underline feature of your editor.

3.	Type the term.

4.	Turn off the underline feature, and then select the editor's hidden-text feature.

5.	Type the context string assigned to the topic that contains the definition of the term.


  Creating a Nonscrolling Region

If a topic contains more text or graphics than will fit in the main Help window, the WinHelp application provides scroll bars to let the user scroll through the information.

By default, all text and graphics scroll when the scroll bars appear. However, if you want certain text or graphics to remain in place while the rest of the topic scrolls, you can create a nonscrolling region.

The nonscrolling region always appears at the head of a topic. When the user scrolls the topic, only the information below the nonscrolling region scrolls. You can place both text and graphics in the nonscrolling region. The text and graphics can contain hot spots to jump to other topics, display a pop-up window, or run a Help macro.

The default appearance of the nonscrolling region is a white background separated from the scrollable region by a black line. You can change the background color of the nonscrolling region by creating a definition for the main window in the Help project file. For more information, see »Defining Window Attributes«.

The nonscrolling region is useful for displaying information that you don't want users to lose when they scroll the file, such as the title of the topic.

To create a nonscrolling region in a topic

1.	Select the paragraphs that belong in the nonscrolling region.

The nonscrolling region must be the first paragraphs in the topic.

2.	Format the selected paragraphs with a "Keep With Next" paragraph attribute.

See the documentation for your editor or word processor to determine how to apply this attribute.

3.	If you want to change the background color of the nonscrolling region, define the nonscrolling colors in the [WINDOWS] section of the Help project (.HPJ) file.


  Chapter 4  Creating Graphics for Help

You can increase clarity and add interest to a Help system by using graphics. This chapter describes techniques for adding graphic images to Help files and provides detailed information about:

•	Graphics formats.

•	Adding graphics to topic files.

•	Creating hypergraphics.

•	Creating multiple-resolution bitmaps.


  Graphic Formats

You can include four types of graphics in your Help system. The following table describes each type.

Graphic format	Description
Bitmap	Defines an image as a pattern of dots (pixels). A bitmap has the extensions .BMP or .DIB. Also called paint-type or raster graphics.
Metafile	Defines an image as coded lines and shapes. A metafile has the extension .WMF. Only files that are compatible with Microsoft Windows version 3.0 or later can be included in the Help file. Also called draw-type or vector graphics.
Hypergraphic	A bitmap or metafile to which you add hot spots with the Hotspot Editor (SHED.EXE). A hypergraphic has the extension .SHG.
Multiple-resolution bitmap	A bitmap compiled from several bitmaps with different screen resolutions by the Multiple-Resolution Bitmap Compiler (MRBC.EXE). A multiple-resolution bitmap has the extension .MRB.
Graphics incorporated in the WinHelp application must use one of these four formats.

The WinHelp application limits paragraphs (text plus graphics) to 64K. If possible, avoid creating large graphics or including large graphics in the same paragraph with text.

Note  This chapter assumes you've already identified or prepared the images you want to include in your Help system. If you need information about preparing graphics, see the documentation for the graphics application you are using. Be sure to follow those guidelines when creating graphics for Help files.


  Creating Bitmaps

You must save each bitmap you create as a separate file. This section assumes that your bitmaps have 16 or fewer colors. If you don't use Microsoft Paintbrush™ to create your bitmaps, the color palette in your paint program should have no more than 16 colors.

Create bitmaps in the same screen resolutions (EGA, VGA, VGA+, or 8514) that you want the WinHelp application to use when it displays the topics that contain the bitmaps. If you plan to use the Help file at only one screen resolution, you can create bitmaps for that resolution only.

With the Multiple-Resolution Bitmap Compiler (MRBC.EXE), you can create a single bitmap file that is displayed correctly at more than one screen resolution. For more information, see »Creating Multiple-Resolution Bitmaps« later in this chapter.


  Creating Metafiles

Because metafiles are typically much smaller files than bitmaps, using metafiles can give you a smaller Help file size. Metafiles are device-independent, so you don't need to create metafiles for different display resolutions as you do for bitmaps.

The WinHelp application can use metafiles created by most drawing applications, including CorelDRAW!™ and Micrografx Designer™. Metafiles created by some drawing applications don't strictly adhere to the Windows metafile format. Such metafiles aren't displayed correctly in the compiled Help file. If you're not sure whether a metafile will be displayed correctly, open the metafile in the Hotspot Editor (SHED.EXE). If the metafile is displayed correctly in the Hotspot Editor, it will be displayed correctly in a compiled Help file.


  Adding Graphics to Topic Files

There are two methods for including graphics in a Help file:

•	Place the bitmap or metafile directly in the topic file.

− Or −

•	Place a bitmap or metafile reference in the topic file.

Each method has advantages and disadvantages. Use the following information to help you decide which to use.


  Including Graphics Directly

The easiest way to place a graphic into a Help topic file is to import the graphic or metafile directly from the Windows Clipboard into Word for Windows. You can then paste the graphic where you want it to appear in the Help topic file. You can format your text so it's positioned below or alongside the graphic. When you save the Help topic file in rich-text format (RTF), the pasted bitmaps and metafiles are automatically included in the Help file.

Note  Word for Windows allows you to include bitmaps or metafiles directly in the Help topic file.


  Advantages

These are the advantages of including graphics directly in the Help topic file:

•	You can see the graphic whenever you work in the Help topic file.

•	You don't have to enter the graphic location in the Help project file.


  Disadvantages

These are the disadvantages of importing graphics directly into a Help topic file:

•	You can use only Word for Windows to author topic files.

•	You can use only inline graphics (those treated the same as a character). This limits the ways you can display text and graphics. For example, you can't wrap text around an inline graphic.

•	Graphics inserted in a Word for Windows document increase the time needed to scroll or save the topic file.

•	You can't change the graphic inside Word for Windows. Instead, you must modify it in your graphics application and then reimport it into Word for Windows.

•	You can't paste hypergraphics (graphics created with the Hotspot Editor) in topic files.

•	Including the same graphic directly at multiple locations in the topic file adds multiple copies of the graphic to the compiled Help file, thus increasing its size.


  Including Graphics by Reference

To insert a graphic into a topic by reference, you include special text that tells the WinHelp application the name of the bitmap file or metafile and how to position it with respect to text. To position a graphic by reference, make the following changes to the topic and project files:

•	Enter the reference text in the topic file where you want the graphic to appear.

•	Enter the location of the graphic file in the Help project (.HPJ) file.


  Advantages

These are the advantages of including graphics by reference:

•	You can author your Help file with any text editor that produces RTF files.

•	You have the widest range of options for displaying text and graphics. For example, you can treat the graphic as a character, or you can wrap text around the graphic's left or right edge.

•	You can change the graphic without having to reimport it into the Help topic file. The references are pointers to the graphic files. The Help Compiler inserts the actual graphics only when you compile the Help file.

•	You can use hypergraphics (created with the Hotspot Editor) in your topic files. You can include hypergraphics only by reference.

•	Including the same graphic by reference at multiple locations in a topic file adds only one copy of the graphic in the compiled Help file.


  Disadvantages

These are the disadvantages of including graphics by reference:

•	You can't see the graphic when you work in the topic file.

•	You have to enter the locations of the graphic files in the Help project file. Although this is a simple task, any mistakes will cause errors when you compile the Help file.


  Creating a Graphic Reference

Use the following syntax to create references to graphics not directly included in a topic file:

{command filename}

The following table lists the three commands you can use in a graphic reference.

Command	Description
bmc	Aligns the graphic as a character. The compiled Help file contains a single copy of the graphic data separate from the text.
bml	Aligns the graphic at the left margin; text wraps along the graphic's right edge. The Help file contains a single copy of the graphic data separate from the text.
bmr	Aligns the graphic at the right margin; text wraps along the graphic's left edge. The Help file contains a single copy of the graphic data separate from the text.
The filename given in the graphic reference includes only the file name, not the file's full path. The Help project (.HPJ) file contains all the path information for graphics included by reference.


  Aligning Graphics as Characters

The Help Compiler treats a graphic inserted with a bmc reference as a character. After compiling the Help file, graphics aligned as characters appear on the baseline of the type at the location of the reference command.

Because the graphic is positioned as text, any paragraph formatting applied to the paragraph also applies to the graphic. Text appearing above and below doesn't wrap around the graphic, but the size of the graphic may increase the line space between the line containing the graphic and the preceding line in the text.

Note  Don't specify negative line spacing for a paragraph that has a bmc graphic reference. If you do, the graphic might appear on top of the paragraph when the WinHelp application displays the topic.

A bullet or other special symbol is a good example of a graphic used as a character. Some help files use a small bitmap (BULLET.BMP) for the bullet in bulleted lists:

{bmc bullet.bmp}	Indicates the current icon with a square border.

{bmc bullet.bmp}	Displays the actual size of the icons being edited.


  Aligning Graphics at the Left Margin

The Help Compiler places a bml graphic along the left margin. Text wraps automatically along the right edge of the image. Text is aligned with the graphic's upper-right corner, so any white space saved at the top of the image affects the way text appears in relation to the graphic.

Placing the Reference at the Beginning of a Paragraph

Normally, you should place bml references at the beginning of a paragraph. This ensures proper wrapping of text around the graphic's right edge. The following example shows a typical bml reference:

{bml name.bmp}Paragraph text follows the bitmap reference...

Note  Do not put any space characters between the bml reference and the paragraph text unless you want the first line of text to appear indented from the rest of the text that wraps along the graphic's right edge.

Placing the Reference at the End of a Paragraph

You can also put a bml reference at the end of a paragraph, as shown in this example:

...Paragraph text precedes the bitmap reference.{bml name.bmp}

When you code a bml reference this way, WinHelp wraps the text up to the end of the paragraph, and then displays the graphic. After you compile the Help file, the graphic appears under the text and to the left.


  Aligning Graphics at the Right Margin

The Help Compiler places a bmr graphic along the right margin. Text automatically wraps along the image's left edge. Text is aligned with the upper-left corner of the graphic, so any white space saved at the top of the image affects the way text appears in relation to the graphic.

Placing the Reference at the Beginning of a Paragraph

Normally, you should place bmr references at the beginning of a paragraph. This ensures proper wrapping of text around the graphic's left edge. For example, some help files use a bmr reference to display a hypergraphic with the application interface window:

{bmr iwedit.shg}Click the part of the window you want to know

more about.

Note  Do not put any space characters between the bmr reference and the paragraph text unless you want the first line of text to appear indented from the topic's left margin.

Placing the Reference at the End of a Paragraph

You can also place a bmr reference at the end of a paragraph:

...Paragraph text precedes the bitmap reference.{bmr name.bmp}

When you code a bmr reference this way, WinHelp wraps text up to the end of the paragraph, and then displays the graphic. After you compile the Help file, the graphic appears under the text and to the right.


  Using Graphic References as Hot Spots

You can do more with graphics in your Help file than simply display them. The WinHelp application allows you to use graphics as hot spots. This means you can use graphics, such as icons or buttons, as jumps to particular topics or as hot spots for pop-up windows or Help macros.

To code a graphic reference as a jump or hot spot for a pop-up window:

1.	Enter the graphic reference (bmc, bml, or bmr) in the topic file where you want the jump.

Be sure you've already created the topic (and its context string) that will appear in the pop-up window.

2.	Select the entire graphic reference, including the filename and opening and closing braces.

3.	Format the graphic reference as double-underlined text to create a jump.
− or −
Format the graphic reference as underlined text to create a hot spot for a pop-up window.

4.	Type the context string of the destination topic for the jump immediately following the graphic reference.

5.	Format the context string as hidden text.

To code a graphic reference as a hot spot for a macro:

1.	Enter the graphic reference (bmc, bml, or bmr) in the topic file where you want the macro.

2.	Select the entire graphic reference, including the filename and opening and closing braces.

3.	Format the graphic reference as double-underlined text.

4.	Immediately following the graphic reference, type an exclamation point (!) followed by the macro, with its parameters, that you want WinHelp to run when the user selects this hot spot.

5.	Format the context string as hidden text.


  Creating Hypergraphics

Multiple hot spots can make the graphics in your Help file more useful. The preceding section, »Using Graphic References as Hot Spots,« shows how to create a single hot spot in a graphic. To create more than one hot spot within a single graphic, you must create a hypergraphic.

A hypergraphic is a graphic (bitmap or metafile) with embedded hot spots that users can click to:

•	Jump to another Help topic.

•	Display a pop-up window.

•	Activate a Help macro.

•	Activate routines in external dynamic-link libraries (DLLs).


  Using the Hotspot Editor

You create hypergraphics with the Hotspot Editor. This tool can open a bitmap (.BMP), a device-independent bitmap (.DIB), or a Windows metafile (.WMF), and add hot spots to the existing graphic. It then saves the graphic as a hypergraphic (.SHG) file.

Because the Hotspot Editor is not a drawing or painting program, you must create the actual graphic outside the Hotspot Editor. Once you save a graphic as a hypergraphic using the Hotspot Editor, you can't open the graphic again with a drawing or painting program.

To create a hypergraphic:

1.	Open a bitmap or metafile in the Hotspot Editor.

2.	Draw hot-spot locations in the graphic.

3.	Define attributes for each hot spot in the graphic.

4.	Save the graphic as a hypergraphic.

Once you define the hot spots, the graphic is ready to be included in topic files for compiling into a Help file.

The Hotspot Editor will load any Windows bitmap (.BMP) or device-independent bitmap (.DIB) created by a Windows-based drawing or painting program, such as Paintbrush. If you're using Paintbrush, you can save the image file in one of the following formats:

•	Monochrome bitmap

•	16-color bitmap

•	256-color bitmap

•	24-bit bitmap

The Hotspot Editor also works with metafiles (.WMF) that are compatible with Windows version 3.0 or later.


  The Hotspot Editor Window

Because the Hotspot Editor is a multiple-document interface (MDI) window, you can edit several graphics at the same time. Each graphic appears in a separate document window. The status bar at the bottom of the Hotspot Editor window displays brief descriptions of the selected menu or command as well as attribute information for the selected hot spot.

When you select a hot spot, the status bar displays the following information for that hot spot:

•	Context string

•	Binding type

•	Binding attribute

•	Hot-spot identifier

•	Bounding box coordinates


  Opening Graphics

Before you can add hot spots to a graphic with the Hotspot Editor, you must create an image file and then open it in the Hotspot Editor.

To open a graphic file in the Hotspot Editor:

1.	From the File menu, choose Open.

The Open dialog box appears.

2.	If the file is in the current directory, select the filename in the Files list box.

The current directory is shown below the Filename text box. Double-clicking the two periods [..] at the top of the Directories box shows the files and directories located one level closer to the root directory.
− or −
If the file is not in the current directory, double-click the directory you want in the Directories box. Then select the name of the file in the Files box.

The Files box displays only files whose extensions match the supported file formats.

3.	Choose OK.

Instead of using the Files and Directories boxes to open a file, you can type the complete path in the Filename text box and click OK.

The Hotspot Editor records the last four files you have opened. Their paths and file names appear at the bottom of the File menu. To reopen a file, choose the filename from the File menu.


  Adding Hot Spots to Graphics

After opening a graphic in the Hotspot Editor, you can create hot spots that link to topics, pop-up windows, or macros. When you compile with the Help Compiler, the hot spots you define become part the completed Help file.

A hot spot can be any rectangular area within the graphic. You draw hot spots on the graphic as you would a rectangle in a Windows-based drawing or painting program.

To draw a hot spot:

1.	Click the location on the graphic where you want to anchor one corner of the hot spot.

2.	Drag the mouse until the rectangle encloses the area you want to define as the hot spot.

The box stretches from the anchor point to the position of the mouse and expands and contracts as you move the mouse.

3.	When the hot-spot rectangle is the desired size, release the mouse button.

After you release the mouse button, the hot-spot rectangle displays eight sizing handles, indicating the currently selected hot spot. You can use the sizing handles to resize the rectangle.


  Defining Hot-Spot Attributes

After creating a hot spot, you must define the attributes that determine what happens when a user clicks the hot spot. To define these attributes, use the Attributes dialog box. The Attributes dialog box contains binding information for each hot spot you define.

The following table describes the options in the Attributes dialog box.

Field	Description
Context string	Specifies binding information for the hot spot. Can be either a context string or a macro.
Type	Indicates the type of action taken when the user selects the hot spot. You can jump to another topic, display a topic in a pop-up window, or run a Help macro.
Attribute	Specifies whether the hot spot is visible or invisible in the Help window. Hot spots are always visible in the Hotspot Editor.
Hotspot ID	Specifies a unique identifier for the hot spot. The hot-spot name is used internally by the Hotspot Editor and helps you identify hot spots in the Select dialog box. The Hotspot Editor automatically assigns an incremental number to the hot-spot name; however, you can type in a unique name.
Bounding box coordinates	Display the coordinates for the hot-spot rectangle: left, right, top, and bottom. The coordinates are measured in pixels and are restricted to the size of the graphic image.
To define attributes for a hot spot:

1.	Create the hot spot or select it.

2.	Click the hot spot with the right mouse button to display the Attributes dialog box.

3.	For a jump or pop-up window, enter the context string for the destination jump or pop-up window topic in the Context String box.
− or −
For a Help macro, enter the macro in the Context String box. (For more information, see »Chapter 5, Creating Help Macros.«)

4.	Choose the type of hot spot you want to create from the Type list: Jump, Pop-up, or Macro.

5.	Choose Visible or Invisible for the binding attribute.

If you want to make the hot-spot region visible to users, choose Visible from the Attribute list.

6.	If you want to change the default name assigned to the hot spot, edit the hot-spot identifier.

7.	If you want to change the size or location of the hot spot, edit the bounding box coordinates.

8.	Choose OK.

The attributes defined for the hot spot now appear in the Hotspot Editor status bar.


  Selecting Hot Spots

You must select a hot spot before you can move it, cut or copy it to the Clipboard, delete it, or modify its attributes. When a hot spot is selected, it displays eight handles, which you can use to resize the rectangle.

To select a hot spot with the mouse, you can click the hot spot with the left mouse button or press TAB or SHIFT+TAB until you select the hot spot you want.

To select a hot spot using the Select command:

1.	From the Edit menu, choose Select.

The Select dialog box appears. All the hot spots defined for the hypergraphic appear in the Hotspots box. By default, the Hotspot Editor will not select a hot spot in the list box unless one is selected before you choose the Select command. Then the Hotspot Editor highlights the identifier of the currently selected hot spot.

2.	Select a hot-spot name from the Hotspots box.

The Hotspot Editor displays the binding information for the selected hot-spot name.

3.	Choose the Select button.

The hot spot shows eight sizing handles to indicate the hot spot is selected.

For more information on the Select command, search for Select in the Hotspot Editor Help.


  Moving Hot Spots

After you create a hot spot, you can move it anywhere within the graphic.

To move a hot spot:

1.	Select the hot spot.

2.	Point to the center of the selected hot spot.

The pointer changes to a hand pointer, indicating the hot spot can be moved.

3.	Press and hold down the left mouse button.

The hot-spot sizing handles disappear and the hot spot can be dragged to any location.

4.	Move the hot spot to where you want it, and then release the mouse button.

The sizing handles reappear to indicate the hot spot is selected.

5.	Click the mouse button outside the hot spot to fix the hot spot in its new position.

Note  If the client area is the same size or larger than the image area, the Hotspot Editor will not allow you to move the hot spot outside the hypergraphic image area. If the client area is smaller than the image area (that is, the client area shows scroll bars), then the Hotspot Editor scrolls in the direction of the attempted move if a hot spot crosses the edge of the client area.


  Resizing Hot Spots

A hot spot's eight sizing handles allow you to resize a hot spot the same way you resize a window.

To resize a hot spot:

1.	Select the hot spot.

2.	Point to the sizing handle on the border or corner that you want to change.

The pointer changes to a two-headed arrow.

3.	Drag the sizing handle until the rectangle is the size you want.

If you drag a side handle, the rectangle changes size only on the side of the border you drag. If you drag a corner, the two adjoining sides that form the corner change size at the same time.

4.	Release the mouse button.


  Setting Preferences

Whenever you define a hot spot, the Hotspot Editor uses the binding information and hot-spot identifier stored in the Preferences dialog box (Preferences command, Edit menu).

If you want to change these default values, you can edit them. Setting your own preferences for hot-spot attributes can save time and effort when creating hypergraphics that require settings different from the Hotspot Editor's internal defaults. The following table shows the default settings for each of the Preferences options.

Field	Default entry
Context string	Empty
Type	Jump
Attribute	Invisible
Hotspot ID	Hot spot
To change the Hotspot Editor preferences:

1.	From the Edit menu, choose Preferences.

2.	Type a context string or macro in the Context String box.

The context string you enter will be the binding string for each hot spot created with this preference.

1.	Choose the binding type.

2.	Choose Visible or Invisible for the binding attribute.

3.	Enter a hot-spot name.

This entry affects only the hot-spot name. The Hotspot Editor will continue to assign numbers incrementally to each new hot spot created.

4.	Choose OK.

The Hotspot Editor assigns the attributes you entered to subsequent hot spots created with these preferences.


  Creating Multiple-Resolution Bitmaps

When the WinHelp application displays bitmaps, it must first determine whether the bitmap file contains resolution data about the bitmap image. If the bitmap file does contain this information, WinHelp then displays the bitmap at the current display resolution if the bitmap and display resolution match. If these resolutions do not match, WinHelp resizes the bitmap to match the display resolution. If the bitmap file doesn't contain resolution data, WinHelp uses the default resolution for VGA display.

If the bitmap and display resolutions don't match, or if WinHelp must stretch a bitmap to display it, the bitmap doesn't appear as it did when created. To compensate for differences between bitmap and display resolutions, use the Windows Multiple-Resolution Bitmap Compiler (MRBC).

The MRBC lets you create bitmaps with different resolutions (CGA, EGA, VGA, or 8514) and combine them into a single graphic that can be compiled into a Help file. When the WinHelp application encounters a multiple-resolution bitmap, or an .MRB file created by MRBC, it cycles through the stored resolutions and selects the bitmap that most closely matches your display. MRBC supports CGA, EGA, VGA, and 8514 resolutions.

Note  The .MRB output file cannot be edited or viewed by using any existing graphics program and therefore has no value outside the WinHelp application.


  Including .MRB Files in a Help File

You include .MRB files in a Help file by referencing them in an RTF source file. The syntax for an .MRB bitmap reference is the same as for other bitmaps.

Bitmap type	Source file syntax
Inline .MRB bitmap	(bmc bitmap.mrb)
Left-aligned .MRB bitmap	(bml bitmap.mrb)
Right-aligned .MRB bitmap	(bmr bitmap.mrb)


  Using MRBC

You can run MRBC from the command line in either of two modes: interactive or silent. Use interactive mode when input is wanted or required. Use silent mode for batch processing and automated builds. Use the following syntax for compiling multiple-resolution bitmaps:

mrbc [/s] name1.bmp [name2.bmp...namen.bmp]

The following table defines the parameters of this syntax.

Parameter	Definition
/s	Specifies silent mode. If the /s switch is used, MRBC determines the resolution of each bitmap based on the first character of the bitmap extension. If the /s switch is not used, MRBC prompts the user for the resolution of each bitmap.
name1, name2...namen	Specifies the names of the bitmaps to be included in the .MRB file. These files can be bitmaps, metafiles, or hypergraphics.
Bitmap paths can be either relative or absolute. Relative paths are relative to the user's current directory.

The output file MRBC has the same file name as the first bitmap on the command line (NAME1.BMP) but with an .MRB extension. All output files are written into the current directory.


  Performing Preprocessing Checks

Before starting the conversion process, MRBC performs certain preprocessing checks. First, it checks the existence and format of each bitmap listed on the command line. If any bitmap listed is not found or is in an invalid format, MRBC stops processing and displays an error message.


  Starting the Conversion Process

If the command-line entry passes the two preprocessing checks without errors, the conversion process begins. If the /s switch is not used, you are prompted to give the monitor type for each of the bitmaps. In the prompt message, the bitmap names are displayed on the command line with no path, a relative path, or an absolute path.

For example, if you type:

mrbc c:\bitmaps\vga\menu1.bmp c:\bitmaps\ega\menu2.bmp

and the preprocessing checks are passed successfully, MRBC displays the following messages:

Please enter the monitor type for the bitmap c:\bitmap\vga\menu1.bmp

Please enter the monitor type for the bitmap c:\bitmap\ega\menu2.bmp

You supply the appropriate response—in this case VGA and EGA respectively. MRBC then creates the output file and writes it to the current directory.

MRBC supports only four monitor types: CGA, EGA, VGA, and 8514. If you enter a monitor-type that is not supported, MRBC displays a warning message.

At run time, WinHelp selects the best possible bitmap for your display. In addition to resolution, WinHelp uses color as a selection criterion. Therefore, you should include both color and monochrome bitmaps in the same .MRB file to ensure compatibility with both monitor types.

Note  MRBC does not check for valid matches between bitmap resolution and the entered option. For example, if you enter VGA for an EGA graphic, MRBC accepts it and marks it as a VGA bitmap. When the bitmap is displayed on a VGA monitor, however, it will not appear as originally authored. For that reason, it is important to check .MRB bitmaps on the target monitors to ensure that they are correctly displayed.

If the /s switch is used, the conversion process takes place without your input. Instead, MRBC uses the first character of the input filename extension to determine the bitmap resolution. The following table shows how the extensions are mapped.

First character	Example	MRBC interpretation
C	(bitmap.cbm)	CGA bitmap
E	(bitmap.ebm)	EGA bitmap
V	(bitmap.vbm)	VGA bitmap
8	(bitmap.8bm)	8514 bitmap
other	(bitmap.bmp)	VGA bitmap
For example, if you type:

mrbc /s house.vga house.ega house.cga house.8xx

MRBC will create an .MRB file named HOUSE.MRB that consists of VGA, EGA, CGA, and 8514 bitmaps.

Note  As in interactive mode, MRBC does not check for valid matches between bitmap resolution and the entered option. Be sure that you match the correct extensions with the correct display resolutions.

In both interactive and silent modes, MRBC accepts the asterisk (*) and question mark (?) as wildcards for the file names.

In some cases, the drawing tool that creates bitmaps stores the resolution in the bitmap file. MRBC checks all bitmap files to determine whether the resolution is specified. If MRBC finds the resolution specified in the bitmap files, it uses the resolution you specify instead of the existing graphic resolution, and then displays an informative warning message. This warning message appears only when the conversion is performed in interactive mode.


  Chapter 5  Creating Help Macros

You can customize the way the WinHelp application works with your Help files by using Windows Help (WinHelp) macros. This chapter describes:

•	Running Help macros.

•	Rules for coding Help macros.

•	Using DLL calls as Help macros.

•	Windows Help macro commands.

•	Virtual-key codes.


  Running Help Macros

WinHelp macros allow you to customize your WinHelp application. You can add and remove custom buttons and menus, change the function of buttons and menu items, execute applications from within Help, and execute functions from external dynamic-link libraries (DLLs).

For example, the MSVC.HLP Help file contains macros that add an Up button to the button bar of the main Help window. When the user clicks the Up button, a jump to the next highest Help topic in the hierarchy is executed.

Help macros can be run:

•	When WinHelp first opens a Help file.

•	When the user selects a particular topic in the Help file.

•	When the user chooses a button, menu item, or hot spot containing a macro.


  Running Macros When Opening a Help File

If a macro appears in the [CONFIG] section of the Help project file (.HPJ), WinHelp runs that macro when it first runs the Help file. If more than one macro is listed in the [CONFIG] section, WinHelp runs them in their listed order.

The [CONFIG] section of the Help project file for the MSCXX.HLP Help file contains these two macros:

CreateButton("btn-up", "&Up", "JumpId(`mscxx.hlp', `up_runtime')")

BrowseButtons()

The first macro defines a new button called Up in the button bar; when clicked, this button executes a jump to a higher level Help topic. The second macro places the buttons in the button bar that control browse sequences.

Note  WinHelp version 3.1 doesn't automatically provide Browse Forward (>>) and Browse Back (<<) buttons. If your Help file includes one or more browse sequences, you must use the BrowseButtons( ) macro so the user can move forward or backward.

For more information about coding a Help macro in the Help project file, see »Customizing Help«.


  Running Macros When a User Enters a Topic

If a Help macro is authored in a topic footnote, WinHelp runs that macro automatically whenever the user jumps to the topic. Macros that control Help buttons, menus, or menu items remain in effect until the user quits WinHelp or opens a new Help file. A user can jump to a topic by:

•	Clicking a jump to the topic.

•	Clicking the Back button or a browse button.

•	Selecting the topic from the history list or keyword search list. (For more information on how to use Help file menus, see the Microsoft Windows User's Guide.)


  Running Macros From a Hot Spot

Help macros can also be run from hot spots within a topic. WinHelp runs a hot-spot macro whenever the user chooses the hot spot containing that macro. WinHelp continues displaying the topic while it runs the macro, unless the macro causes a jump to another topic.

A hot spot containing a macro is formatted like any other hot spot. The text or bitmap reference used for the macro is formatted as double-underlined text, and the macro (preceded by an exclamation point) is formatted as hidden text. For more information about coding jumps in a topic, see »Linking Topics with Jumps and Pop-Up Windows«.


  Rules for Coding Help Macros

Authors must follow these rules when coding Help macros:

•	Macros are not case-sensitive; you can use any capitalization convention you choose.

•	Separate each macro in a string by a semicolon (;) if a single macro string can include more than one Help macro.

•	Specify empty spaces in a macro string by placing the surrounding text in quotation marks.

•	Insert special characters in a quotation-marked string prefaced by a backslash. Special characters include double quotation marks ("), opening and closing single quotation marks (` '), and backslashes (\).

Note  The single opening quotation mark is different from the single closing quotation mark. The single opening quotation mark (`) is paired with the tilde (~) above the TAB key on extended keyboards; the single closing quotation mark (') is the same as the apostrophe.

•	Quotation marks can be either matching double quotation marks or a pair of single opening and closing quotation marks. You cannot use double quotation marks inside a string already enclosed in double quotation marks. Use single opening and closing quotation marks instead. For example:

CreateButton("time_btn", "&Time", "ExecProgram("clock", 0)")

is invalid because the string clock uses double quotation marks within the double quotation marks used for the ExecProgram macro. The following example corrects the error by enclosing clock in single quotation marks:

CreateButton("time_btn", "&Time", "ExecProgram(`clock', 0)")

•	Macros can be included within other macros. In other words, a macro can be used as a parameter value for another macro.

•	A single macro must be 512 or fewer characters.


  Using DLL Calls as Help Macros

If you are a C programmer and have created a DLL for use with WinHelp, you can use calls to functions in the DLL as Help macros, provided you register the function in the Help project file. To register the DLL function, enter a WinHelp RegisterRoutine macro in the [CONFIG] section of the project file.

The RegisterRoutine macro has the following format:

RegisterRoutine("DLLname", "functionname", "formatspec")

The DLLname is the file name for the DLL, and the functionname is the function you want to use as a Help macro. The formatspec is a string of format specifiers that give the formats of arguments to the function. WinHelp checks the format string to make sure it matches the function prototype defined in the DLL. (For a complete list of format specifiers and examples, see the RegisterRoutine macro later in this chapter.)

In effect, the RegisterRoutine macro gives you the power to extend WinHelp with your own DLLs. Once you have registered a DLL function with WinHelp, you can create menu items or macro buttons that execute the function. In this way, you can offer specialized capabilities to users of your Help file that are not available in the standard WinHelp application.


  Macro Command Reference

This section lists Help macros alphabetically and provides the following information.

Heading	Information
Macro	Name of the macro and its abbreviation, if available, enclosed in parentheses. Use the abbreviation in place of the macro name in the syntax.
Syntax	Syntax and parameters required for each macro. For information about the typographic conventions used in syntax descriptions, see »Document Conventions« in the Introduction.
Parameters	Descriptions of parameters to the macro.
Example	Example of the macro.
Comments	Information about preferred or restricted uses for the macro.


  About

This macro displays the About dialog box (same as the About command on the Help menu).

Syntax

About()

Comments

Use of this macro in secondary windows is discouraged.


  AddAccelerator (AA)

This macro assigns a Help macro to a shortcut key (or key combination) so that the macro is run when the user presses the shortcut key(s).

Syntax

AddAccelerator(key, shiftstate, "macro")

Parameters

Argument	Definition
key	The Windows virtual-key value. For a list of these keys, see  »Virtual-Key Codes« later in this chapter.
shiftstate	A number specifying the combination of ALT, SHIFT, and CTRL keys used with the shortcut key: 0 (none), 1 (SHIFT), 2 (CTRL), 3 (SHIFT+CTRL), 4 (ALT), 5 (ALT+SHIFT), 6 (ALT+CTRL), or 7 (ALT+SHIFT+CTRL).
macro	The Help macro or macro string that is run when the user presses the shortcut key(s). The macro must appear in quotation marks. Multiple macros in a string must be separated by semicolons (;).
Example

The following macro starts the Windows Clock program (provided in Windows version 3.1) when the user presses CTRL+ALT+SHIFT+F4:

AddAccelerator(0x73, 7, "ExecProgram(`clock.exe', 1)")

Comments

The Help macro that is run by AddAccelerator might not work in secondary windows, or its use may be discouraged if the macro it runs is prohibited or discouraged in secondary windows. Check the usage notes for the macro before using AddAccelerator to run it in a secondary window.


  Annotate

This macro displays the Annotation dialog box (same as the Annotate command on the Edit menu).

Syntax

Annotate()

Comments

Use of this macro in secondary windows is discouraged.

If the Annotate macro is run from a pop-up window, the annotation is attached to the topic that contains the hot spot to the pop-up window.


  AppendItem

This macro appends a menu item to the end of a menu you create with the InsertMenu macro.

Syntax

AppendItem("menuid", "itemid", "itemname", "macro")

Parameters

Argument	Definition
menuid	Name used in the InsertMenu macro to create the menu. This name must appear in quotation marks. The new item is appended to this menu.
itemid	Name that WinHelp uses internally to identify the menu item. This name is case-sensitive and must appear in quotation marks. Use this name in the DisableItem or DeleteItem macro if you want to disable or remove the item, or change the operations that the item performs in certain topics.
itemname	Name that WinHelp displays on the menu for the item. This name is case-sensitive and must appear in quotation marks. Within the quotation marks, place an ampersand (&) before the character used as the macro's keyboard access key.
macro	Help macro or macro string that is run when the user chooses the menu item. The name must appear in quotation marks. Multiple macros in a string must be separated by semicolons (;).
Example

The following macro appends a menu item labeled "Tools" to a menu that has an identifier "mnu_books":

AppendItem("mnu_books", "mnu_tools", "&Tools", "JI(`tools.hlp',

`first_topic')")

Choosing the menu item causes a jump to a topic with the context string "first_topic" in the TOOLS.HLP file.

Comments

WinHelp ignores this macro if it is run in a secondary window.

Make sure that the keyboard access keys you assign to menu items are unique. If you assign a key that conflicts with other menu access keys, WinHelp displays the error message, Unable to add item, and ignores the macro.


  Back

This macro displays the previous topic in the Back list. The Back list includes the last 40 topics the user has displayed since starting WinHelp.

Syntax

Back()

Comments

WinHelp ignores this macro if it is run in a secondary window.

If the Back macro is run when the Back list is empty, WinHelp takes no action.


  BookmarkDefine

This macro displays the Define dialog box (same as the Define command on the Bookmark menu).

Syntax

BookmarkDefine()

Comments

Use of this macro in secondary windows is discouraged.

If the BookmarkDefine macro is run from a pop-up window, the bookmark is attached to the topic that invoked the pop-up window.


  BookmarkMore

This macro displays the More dialog box (same as the More command on the Bookmark menu). The More command appears on the Bookmark menu if the user has defined more than nine bookmarks.

Syntax

BookmarkMore()

Comments

Use of this macro in secondary windows is discouraged.


  BrowseButtons

This macro adds the Browse Back (<<) and Browse Forward (>>) buttons to the toolbar in WinHelp.

Syntax

BrowseButtons()

Example

The following macros in the .HPJ file cause the Clock button to appear immediately before the two browse buttons on the toolbar:

CreateButton("&Clock", "ExecProgram(`clock', 0)")

BrowseButtons()

Comments

WinHelp ignores this macro if it is run in a secondary window.

If the BrowseButtons macro is used with one or more CreateButton macros in the [CONFIG] section of the .HPJ file, the order of the browse buttons on the WinHelp toolbar is determined by the order of the BrowseButtons macro in relation to the other macros listed in the [CONFIG] section.

Note  WinHelp version 3.1 doesn't automatically provide Browse Forward (>>) and Browse Back (<<) buttons. If your Help file includes one or more browse sequences, you must use the BrowseButtons() macro so the user can move forward or backward.


  ChangeButtonBinding (CBB)

This macro assigns a Help macro to a Help button.

Syntax

ChangeButtonBinding("buttonid", "buttonmacro")

Parameters

Argument	Definition
buttonid	Identifier assigned to the button in the CreateButton macro or, for a standard Help button, one of the following predefined button identifiers: btn_contents (Contents), btn_search (Search), btn_back (Back), btn_history (History), btn_previous (<<), or btn_next (>>). The button identifier must appear in quotation marks.
buttonmacro	Help macro run when the user chooses the button. The macro must appear in quotation marks.
Example

The following macro changes the function of the Contents button so that choosing it causes a jump to the Table of Contents topic (identified by the context string "dict_contents") in the DICT.HLP file:

ChangeButtonBinding("btn_contents", "JumpId(`dict.hlp',

`dict_contents')")

Comments

WinHelp ignores this macro if it is run in a secondary window.


  ChangeItemBinding (CIB)

This macro assigns a Help macro to an item that you add to a WinHelp menu using the AppendItem macro.

Syntax

ChangeItemBinding("itemid", "itemmacro")

Parameters

Argument	Definition
itemid	Identifier assigned to the item in the AppendItem macro. The item identifier must appear in quotation marks.
itemmacro	Help macro that is run when the user selects the item. The macro must appear in quotation marks.
Example

The following macro changes the menu item identified by "time_item" so that it starts the Windows Clock program:

ChangeItemBinding("time_item", "ExecProgram(`clock', 0)")

Comments

WinHelp ignores this macro if it is run in a secondary window.


  CloseWindow

This macro closes the specified window, which is either the main WinHelp window or a secondary window.

Syntax

CloseWindow("windowname")

Parameters

Argument	Definition
windowname	The name of the window to close. The name "main" is reserved for the primary Help window. For secondary windows, the window name is defined in the [WINDOWS] section of the .HPJ file. This name must appear in quotation marks.
Example

The following macro closes the secondary window "keys":

CloseWindow("keys")

Comments

If the window does not exist, WinHelp ignores the macro.


  Contents

This macro displays the contents topic in the current Help file. The contents topic is defined by the CONTENTS option in the [OPTIONS] section of the Help project file.

Syntax

Contents()

Comments

If the project file does not have a CONTENTS option, the contents topic is the first topic in the first topic file specified in the Help project file.


  CopyDialog

This macro displays the Copy dialog box (same as the Copy command on the Edit menu).

Syntax

CopyDialog()

Comments

Use of this macro in secondary windows is discouraged.


  CopyTopic

This macro copies all the text in the currently displayed topic onto the Windows Clipboard.

Syntax

CopyTopic()

Comments

Use of this macro in secondary windows is discouraged.

This macro copies text only; it does not copy bitmaps or any other images in the Help topic.


  CreateButton (CB)

This macro adds a new button to the WinHelp toolbar.

Syntax

CreateButton("buttonid", "name", "macro")

Parameters

Argument	Definition
buttonid	Name that WinHelp uses internally to identify the button. This name must appear in quotation marks. Use this name in the DisableButton or DestroyButton macro if you want to remove or disable the button, or in the ChangeButtonBinding macro if you want to change the Help macro that the button runs in certain topics.
name	The text that appears on the button. This name must appear in quotation marks. To designate a letter as a keyboard access key for this button, place an ampersand (&) before a letter in this text. The button name is case-sensitive and can contain up to 29 characters, beyond which the name is clipped.
macro	Help macro or macro string that is run when the user chooses the button. The macro must appear in quotation marks. Multiple macros in a macro string must be separated by semicolons (;).
Example

The following macro creates a new button labeled "Ideas" that jumps to a topic with the context string "directory" in the IDEAS.HLP file when the button is chosen:

CreateButton("btn_ideas", "&Ideas", "JumpId(`ideas.hlp', `directory')")

Comments

WinHelp ignores this macro if it is run in a secondary window.

WinHelp allows a maximum of 16 authored buttons. It allows a total of 22 buttons, including the standard browse buttons, on the toolbar.

If the BrowseButtons macro is used with one or more CreateButton macros in the [CONFIG] section of the .HPJ file, the order of the browse buttons on the WinHelp toolbar is determined by where the BrowseButtons macro is listed in relation to the other macros in the [CONFIG] section.


  DeleteItem

This macro removes a menu item that was added using the AppendItem macro.

Syntax

DeleteItem("itemid")

Parameters

Argument	Definition
itemid	The item identifier string used in the AppendItem macro. The item identifier must appear in quotation marks.
Example

The following macro removes the menu item "Tools" appended in the example for the AppendItem macro:

DeleteItem("mnu_tools")

Comments

WinHelp ignores this macro if it is run in a secondary window.


  DeleteMark

This macro removes a text marker added with the SaveMark macro.

Syntax

DeleteMark("markertext")

Parameters

Argument	Definition
markertext	Marker text specified in the SaveMark macro. The marker text must appear in quotation marks.
Example

The following macro removes the marker "Managing Memory" from the Troubleshooting Help file:

DeleteMark("Managing Memory")

Comments

If the marker does not exist when the DeleteMark macro is run, WinHelp displays a Topic not found error message.


  DestroyButton

This macro removes a button added with the CreateButton macro.

Syntax

DestroyButton("buttonid")

Parameters

Argument	Definition
buttonid	Identifier assigned to the button in the CreateButton macro. The button identifier must appear in quotation marks. The button identifier cannot duplicate an identifier used for one of the standard Help buttons. (See the ChangeButtonBinding macro for a list of these identifiers.)
Comments

WinHelp ignores this macro if it is run in a secondary window.


  DisableButton (DB)

This macro disables and dims a button added with the CreateButton macro.

Syntax

DisableButton("buttonid")

Parameters

Argument	Definition
buttonid	Identifier assigned to the button in the CreateButton macro. The button identifier appears in quotation marks.
Comments

WinHelp ignores this macro if it is run in a secondary window.

A button disabled by the DisableButton macro cannot be used in the topic until an EnableButton macro is run.


  DisableItem (DI)

This macro disables and dims a menu item added with the AppendItem macro.

Syntax

DisableItem("itemid")

Parameters

Argument	Definition
itemid	Identifier assigned to the menu item in the AppendItem macro. The item identifier must appear in quotation marks.
Comments

WinHelp ignores this macro if it is run in a secondary window.

A menu item disabled by the DisableItem macro cannot be used in the topic until an EnableItem macro is run.


  EnableButton (EB)

This macro re-enables a button disabled with the DisableButton macro.

Syntax

EnableButton("buttonid")

Parameters

Argument	Definition
buttonid	Identifier assigned to the button in the CreateButton macro. The button identifier must appear in quotation marks.
Comments

WinHelp ignores this macro if it is run in a secondary window.


  EnableItem (EI)

This macro re-enables a menu item disabled with the DisableItem macro.

Syntax

EnableItem("itemid")

Parameters

Argument	Definition
itemid	Identifier assigned to the menu item in the AppendItem macro. The item identifier must appear in quotation marks.
Comments

WinHelp ignores this macro if it is run in a secondary window.


  ExecProgram (EP)

This macro runs a Windows-based application.

Syntax

ExecProgram("commandline", displaystate)

Parameters

Argument	Definition
commandline	Command line for the application to be executed. The command line must appear in quotation marks. WinHelp searches for this application in the current directory, followed by the Windows directory, the user's path, and the directory of the currently displayed Help file.
displaystate	A value indicating how the application is shown when executed. A value of 0 indicates normal, 1 indicates minimized, and 2 indicates maximized.
Example

The following macro runs the Windows Clock program in its normal window size:

ExecProgram("clock.exe", 0)


  Exit

This macro exits the WinHelp application (same as the Exit command on the File menu).

Syntax

Exit()


  FileOpen

This macro displays the Open dialog box (same as the Open command on the File menu).

Syntax

FileOpen()

Comments

Use of this macro in secondary windows is discouraged.


  FocusWindow

This macro changes the focus to the specified window, which is either the main WinHelp window or a secondary window.

Syntax

FocusWindow("windowname")

Parameters

Argument	Definition
windowname	The name of the window to have the focus. The name "main" is reserved for the primary Help window. For secondary windows, the window name is defined in the [WINDOWS] section of the .HPJ file. This name must appear in quotation marks.
Example

The following macro changes the focus to the secondary window "keys":

FocusWindow("keys")

Comments

If the window does not exist, WinHelp ignores the macro.


  GoToMark

This macro jumps to a marker set with the SaveMark macro.

Syntax

GoToMark("markertext")

Parameters

Argument	Definition
markertext	Marker text specified in the SaveMark macro. The marker text must appear in quotation marks.
Example

The following macro jumps to the marker "Managing Memory" in the Troubleshooting Help file:

GoToMark("Managing Memory")


  HelpOn

This macro displays the Using Help file for the WinHelp application (same as the Using Help command on the Help menu).

Syntax

HelpOn()


  History

This macro displays the Windows Help History window, which shows the last 40 topics the user has viewed since opening a Help file in WinHelp. It has the same effect as choosing the History button on the WinHelp toolbar.

Syntax

History()

Comments

WinHelp ignores this macro if it is run in a secondary window.


  IfThen

This macro runs a Help macro if a given marker exists. It uses the IsMark macro to make the test.

Syntax

IfThen(IsMark("markertext"), "macro")

Parameters

Argument	Definition
markertext	Marker text tested by the IsMark macro. The marker text must appear in quotation marks.
macro	The Help macro or macro string that is run if the marker exists. The macro must appear in quotation marks. Multiple macros in a macro string must be separated by semicolons (;).
Example

The following macro jumps to the topic with the context string "man_mem" if a marker named "Managing Memory" has been set by the SaveMark macro:

IfThen(IsMark("Managing Memory"), "JI(`trb.hlp', `man_mem')")


  IfThenElse

This macro runs one of two Help macros, provided a marker exists. It uses the IsMark macro to make the test.

Syntax

IfThenElse(IsMark("markertext"), "macro1", "macro2")

Parameters

Argument	Definition
markertext	Marker text tested by the IsMark macro. The marker text must appear in quotation marks.
macro1, macro2	WinHelp runs macro1 if the marker exists and macro2 if it does not. Both macros must appear in quotation marks. Multiple macros in either macro string must be separated by semicolons (;).
Example

The following macro jumps to the topic with the context string "man_mem" if a marker named "Managing Memory" has been set by the SaveMark macro. If the marker does not exist, it jumps to the contents screen for the TRB.HLP file:

IfThenElse(IsMark("Managing Memory"), "JI(`trb.hlp', `man_mem')",

"JumpContents(`TRB.HLP')")


  InsertItem

This macro inserts a menu item at a given position on an existing menu. The menu can be either one you create with the InsertMenu macro or one of the standard WinHelp menus.

Syntax

InsertItem("menuid", "itemid", "itemname", "macro", position)

Parameters

Argument	Definition
menuid	Either a standard WinHelp menu name or the name used in the InsertMenu macro to create the menu. Standard menu names are mnu_file (File menu), mnu_edit (Edit menu), mnu_bookmark (Bookmark menu), and mnu_helpon (Help menu). The menu identifier must appear in quotation marks. The new item is inserted into this menu.
itemid	Name that WinHelp uses internally to identify the menu item. The item identifier must appear in quotation marks. Use this name in the DisableItem or DeleteItem macro if you want to disable or remove the item, or change the operations that the item performs in certain topics.
itemname	Name that WinHelp displays on the menu for the item. This name is case-sensitive and must appear in quotation marks. Within the quotation marks, place an ampersand (&) before the character used for the item's keyboard access key.
macro	Help macro or macro string that is run when the user chooses the menu item. The macro must appear in quotation marks. Multiple macros in a string must be separated by semicolons (;).
position	An integer specifying the position in the menu where the new item will appear. Position 0 is the first or topmost position in the menu.
Example

The following macro inserts a menu item labeled "Tools" as the third item on a menu that has an identifier "mnu_books":

InsertItem("mnu_books", "mnu_tools", "&Tools", "JI(`tools.hlp',

`first_topic')", 3)

Selecting the menu item causes a jump to a topic with the context string "first_topic" in the TOOLS.HLP file.

Comments

WinHelp ignores this macro if it is run in a secondary window.

Make sure that the keyboard access keys you assign to menu items are unique. If you assign a key that conflicts with other menu access keys, WinHelp displays the error message Unable to add item and ignores the macro.


  InsertMenu

This macro adds a new menu to the WinHelp menu bar.

Syntax

InsertMenu("menuid", "menuname", menuposition)

Parameters

Argument	Definition
menuid	Name that WinHelp uses internally to identify the menu. The menu identifier must appear in quotation marks. Use this identifier in the AppendItem macro to add commands to the menu.
menuname	Name for the menu that WinHelp displays on the menu bar. This name is case-sensitive and must appear in quotation marks. Within the quotation marks, place an ampersand (&) before the character used for the menu's keyboard access key.
menuposition	Number telling WinHelp which position on the menu bar the new menu name will have. Positions are numbered from left to right, with position 0 being the leftmost menu.
Example

The following macro adds a menu named "Utilities" to WinHelp:

InsertMenu("menu_util", "&Utilities", 3)

The label "Utilities" appears as the fourth menu on the WinHelp menu bar. The user presses ALT+U to display the menu and its commands.

Comments

WinHelp ignores this macro if it is run in a secondary window.

Make sure that the keyboard access keys you assign to menus are unique. If you assign a key that conflicts with other menu access keys, WinHelp displays the error message Unable to add menu and ignores the macro.


  IsMark

This macro determines whether a marker set by the SaveMark macro exists. It is used as a parameter to the conditional macros IfThen and IfThenElse.

Syntax

IsMark("markertext")

Parameters

Argument	Definition
markertext	Marker text tested by the IsMark macro. The IsMark macro returns a True value if the mark exists and a False value if it does not. The marker text must appear in quotation marks.
Example

The following macro jumps to the topic with the context string "man_mem" if a marker named "Managing Memory" has been set by the SaveMark macro:

IfThen(IsMark("Managing Memory"), "JI(`trb.hlp', `man_mem')")

Comments

The Not macro can be used to reverse the results of the IsMark macro.


  JumpContents

This macro jumps to the contents topic of a specified Help file. The contents topic is indicated by the CONTENTS option entry in the [OPTIONS] section of the .HPJ file.

Syntax

JumpContents("filename")

Parameters

Argument	Definition
filename	The name of the destination file for the jump. The file name must appear in quotation marks. If WinHelp cannot find this file, it displays an error message and does not perform the jump.
Example

The following macro jumps to the contents topic of the PROGMAN.HLP file:

JumpContents("PROGMAN.HLP")

Comments

If the CONTENTS option is not specified, WinHelp jumps to the first topic in the Help file.

WinHelp ignores this macro if it is run in a secondary window.


  JumpContext (JC)

This macro jumps to a topic identified by a context number. The context is identified by an entry in the [MAP] section of the .HPJ file.

Syntax

JumpContext("filename", contextnumber)

Parameters

Argument	Definition
filename	The name of the destination file for the jump. The file name must appear in quotation marks. If WinHelp cannot find this file, it displays an error message and does not perform the jump.
contextnumber	Context number of the topic in the destination file. The context number must be mapped in the destination Help file's [MAP] section. If the context number does not exist or cannot be found in the [MAP] section, WinHelp jumps to the contents topic or the first topic in the file instead, and displays an error message. (For more information about context numbers, see »Planning Context Sensitivity«)
Example

The following macro jumps to the topic mapped to the context number 801 in the PROGMAN.HLP file:

JumpContext("PROGMAN.HLP", 801)


  JumpHelpOn

This macro jumps to the contents topic of the Using Help file. The Using Help file is either the default WINHELP.HLP file or the Help file designated by the SetHelpOnFile macro in the [CONFIG] section of the .HPJ file. (For more information, see the SetHelpOnFile macro later in this section.)

Syntax

JumpHelpOn()

Example

The following macro jumps to the contents topic of the designated Using Help file:

JumpHelpOn()

Comments

If WinHelp cannot find the specified Help file, it displays an error message and does not perform the jump.


  JumpId (JI)

This macro jumps to the topic with the specified context string in the Help file.

Syntax

JumpId("filename", "contextstring")

Parameters

Argument	Definition
filename	Name of the Help file (.HLP) containing the context string. The file name must appear in quotation marks. If WinHelp does not find this file, it displays an error message and does not perform the jump.
contextstring	Context string of the topic in the destination file. The context string must appear in quotation marks. If the context string does not exist, WinHelp jumps to the contents topic for that file instead.
Example

The following macro jumps to a topic with "second_topic" as its context string in the Help file SECOND.HLP:

JumpId("second.hlp", "second_topic")


  JumpKeyword (JK)

This macro opens the indicated Help file (.HLP), searches through the K keyword table, and displays the first topic containing the keyword specified in the macro.

Syntax

JumpKeyword("filename", "keyword")

Parameters

Argument	Definition
filename	The name of the .HLP file that contains the desired keyword table. The file name must appear in quotation marks. If this file does not exist, WinHelp displays an error message and does not perform the jump.
keyword	The keyword that the macro searches for. The keyword must appear in quotation marks. If WinHelp finds more than one match, it displays the first matched topic. If it does not find any matches, it displays a "Not a keyword" message and the contents topic of the destination file.
Example

The following macro opens the first topic that has "hands" as an index keyword in the Help file CLOCK.HLP:

JumpKeyword("clock.hlp", "hands")


  Next

This macro displays the next topic in the browse sequence for the Help file. It has the same effect as choosing the Browse Forward (>>) button.

Syntax

Next()

Comments

If the current topic is the last of a browse sequence, this macro does nothing.

WinHelp ignores this macro if it is run in a secondary window.


  Not

This macro reverses the True or False result returned by the IsMark macro. It is used with the IsMark macro as a parameter to the conditional macros IfThen and IfThenElse.

Syntax

Not(IsMark("markertext")

Parameters

Argument	Definition
markertext	Marker text tested by the IsMark macro. The Not macro returns a False value if the mark exists or a True value if it does not. The marker text must appear in quotation marks.
Example

The following macro jumps to the topic with context string "Expanded Memory" if a marker named "Managing Memory" has not been set by the SaveMark macro:

IfThen(Not(IsMark("Managing Memory")), "JI(`trb.hlp', `Expanded

Memory')")


  PopupContext (PC)

This macro displays a topic identified by a context number. The context is identified by an entry in the [MAP] section of the .HPJ file.

Syntax

PopupContext("filename", contextnumber)

Parameters

Argument	Definition
filename	The name of the file that contains the topic to be displayed in the pop-up window. The file name must appear in quotation marks. If WinHelp cannot find this file, it displays an error message.
contextnumber	Context number of the topic to be displayed in the pop-up window. The context number must be mapped in the [MAP] section of the specified Help file. If the context number does not exist or cannot be found in the [MAP] section, WinHelp displays the contents topic or the first topic in the file instead. (For more information about context numbers, see »Mapping Context-Sensitive Topics«.)
Example

The following macro displays in a pop-up window the topic mapped to the context number 801 in the file PROGMAN.HLP:

PopupContext("progman.hlp", 801)


  PopupId (PI)

This macro displays a topic from a specified file in a pop-up window.

Syntax

PopupId("filename", "contextstring")

Parameters

Argument	Definition
filename	The name of the file that contains the pop-up window topic. The file name must appear in quotation marks. If this file does not exist, WinHelp displays an error message.
contextstring	Context string of the topic in the destination file. The context string must appear in quotation marks. If the requested context string does not exist, WinHelp displays the contents topic or the first topic in the file in the pop-up window. (For more information, see »Coding Context Strings«.)
Example

The following macro displays in a pop-up window a topic identified by the context string "second_topic" in the file SECOND.HLP:

PopupId("second.hlp", "second_topic")


  PositionWindow (PW)

This macro sets the size and position of the main Help window or an existing secondary window.

Syntax

PositionWindow(xcoord, ycoord, width, height, windowstate, "windowname")

Parameters

Argument	Definition
xcoord, ycoord	X and Y coordinates of the upper-left window corner. Positions are defined in terms of WinHelp's 1024 x 1024 coordinate system.
width, height	Gives the default width and height of the window. Window sizes, like positions, are defined in terms of WinHelp's coordinate system.
windowstate	Specifies how the window is sized. This parameter is 0 for normal size and 1 for maximized. If the parameter is 1, WinHelp ignores the xcoord, ycoord, width, and height parameters.
windowname	The name of the window to position. The name "main" is reserved for the primary Help window. For secondary windows, the window name is defined in the [WINDOWS] section of the .HPJ file. This name must appear in quotation marks.
Example

The following macro positions the secondary window "Samples" in the upper-left corner (100, 100) with a width and height of 500 (in WinHelp coordinates):

PositionWindow(100, 100, 500, 500, 0, "Samples")

Comments

If the window to be positioned does not exist, WinHelp ignores the macro.


  Prev

This macro displays the previous topic in the browse sequence for the Help file. It has the same effect as choosing the Browse Back (<<) button.

Syntax

Prev()

Comments

If the currently displayed topic is the first topic of a browse sequence, this macro does nothing.

WinHelp ignores this macro if it is run in a secondary window.


  Print

This macro sends the currently displayed topic to the printer.

Syntax

Print()

Comments

This macro should be used only to print topics in windows other than the main Help window. For example, it can be used to print topics displayed in secondary windows, provided the user doesn't have a dialog box open at the time of printing.

Use of this macro in secondary windows is discouraged.


  PrinterSetup

This macro displays the Print Setup dialog box (same as the Print Setup command on the File menu).

Syntax

PrinterSetup()

Comments

Use of this macro in secondary windows is discouraged.


  RegisterRoutine (RR)

This macro registers a function within a DLL as a Help macro. Registered functions can be used in macro hot spots or footnotes within topic files, or in the [CONFIG] section of the .HPJ file, just as standard Help macros are used.

Syntax

RegisterRoutine("DLLname", "functionname", "formatspec")

Parameters

Argument	Definition
DLLname	The file name of the DLL being called. The file name must appear in quotation marks. If WinHelp cannot find the DLL, it displays an error message and does not perform the call.
functionname	The name of the function to be executed in the designated DLL. The function name must appear in quotation marks.
formatspec	A string specifying the formats of parameters passed to the function. The format string must appear in quotation marks. Characters in the string represent C parameter types: "u" for unsigned short, "U" for unsigned long, "i" for short int, "I" for long int, "s" for string (near char *), "S" for string (far char *), or "v" for void. WinHelp automatically makes sure these formats match the parameter types specified in the function prototype.
Example

The following DLL call registers a routine "RetString" in the DLL named HELPLIB.DLL. RetString takes arguments of types far char *, short int, and unsigned long.

RegisterRoutine("HELPLIB", "RetString", "S=iU")


  SaveMark

This macro saves the location of the currently displayed topic and file and associates a text marker with that location. The GoToMark macro can then be used to jump to this location.

Syntax

SaveMark("markertext")

Parameters

Argument	Definition
markertext	Text used to identify the topic location. The marker text must appear in quotation marks, and it must be unique. If the same text is used for more than one marker, WinHelp recognizes only the most recently entered marker.
Example

The following macro saves the marker "Managing Memory" in the current topic in the Troubleshooting Help file:

SaveMark("Managing Memory")

Comments

In addition to GoToMark, WinHelp offers the following other macros for use with text markers:

•	DeleteMark removes any defined marker.

•	IsMark tests whether a given marker has been set in the Help file. Not negates the result of this test.

•	IfThen and IfThenElse run one or more Help macros if a given marker has been set. These use the IsMark (and optional Not) macro to test whether the marker is set.

Text markers are not saved if the user exits and then restarts WinHelp.


  Search

This macro displays the dialog box for the Search button, which allows users to search for topics using keywords defined in K footnotes. It has the same effect as choosing the Search button.

Syntax

Search()

Comments

WinHelp ignores this macro if it is run in a secondary window.


  SetContents

This macro designates a specific topic as the contents topic within the Help file.

Syntax

SetContents("filename", contextnumber)

Parameters

Argument	Definition
filename	The name of the Help file that contains the desired contents topic. The file name must appear in quotation marks. If WinHelp cannot find the file, it displays an error message and does not perform the jump.
contextnumber	Context number of the topic in the specified file. The context number must be mapped in the [MAP] section of the destination Help file. If the context number does not exist or cannot be found in the [MAP] section, WinHelp displays an error message.
Example

The following macro sets the topic mapped to the context number 801 in the PROGMAN.HLP file as the contents topic:

SetContents("PROGMAN.HLP", 801)

After running this macro, pressing the Contents button causes a jump to the specified topic.


  SetHelpOnFile

This macro designates the specific Help file that replaces WINHELP.HLP, the default Using Help file in the Windows environment.

Syntax

SetHelpOnFile("filename")

Parameters

Argument	Definition
filename	The name of the replacement Using Help file. The file name must appear in quotation marks. If WinHelp cannot find this file, it displays an error message.
Example

The following macro sets the Using Help file as MYHELP.HLP:

SetHelpOnFile("myhelp.hlp")

Comments

If this macro appears within a topic in the Help file, the replacement file is set after execution of the macro. If this macro appears in the [CONFIG] section of the .HPJ file, the replacement file is set when the Help file is opened.


  Virtual-Key Codes

The following list shows the symbolic constant names, hexadecimal values, and descriptive information for Microsoft Windows virtual-key codes. Virtual-key codes are used to assign a shortcut key or key combination to a macro. (For more information on assigning shortcut keys or key combinations, see the AddAccelerator macro earlier in this chapter.) The codes are listed in numeric order.

Name	Value	Description
VK_CANCEL	03H	Used for control-break processing
+	05H−07H	Undefined
VK_BACK	08H	BACKSPACE key
VK_TAB	09H	TAB key
+	0AH−0BH	Undefined
VK_CLEAR	0CH	CLEAR key
VK_RETURN	0DH	RETURN key
VK_SHIFT	10H	SHIFT key
VK_CONTROL	11H	CTRL key
VK_MENU	12H	ALT key
VK_PAUSE	13H	PAUSE key
VK_CAPITAL	14H	CAPITAL key
+	15H−19H	Reserved for Kanji systems
+	1AH	Undefined
VK_ESCAPE	1BH	ESC key
+	1CH−1FH	Reserved for Kanji systems
VK_SPACE	20H	SPACEBAR
VK_PRIOR	21H	PGUP key
VK_NEXT	22H	PGDN key
VK_END	23H	END key
VK_HOME	24H	HOME key
VK_LEFT	25H	LEFT ARROW key
VK_UP	26H	UP ARROW key
VK_RIGHT	27H	RIGHT ARROW key
VK_DOWN	28H	DOWN ARROW key
VK_SELECT	29H	SELECT key
+	2AH	OEM specific
VK_EXECUTE	2BH	EXECUTE key
VK_SNAPSHOT	2CH	PRINT SCREEN key for Windows version 3.0 and later
VK_INSERT	2DH	INS key
VK_DELETE	2EH	DEL key
VK_HELP	2FH	HELP key
VK_0	30H	0 key
VK_1	31H	1 key
VK_2	32H	2 key
VK_3	33H	3 key
VK_4	34H	4 key
VK_5	35H	5 key
VK_6	36H	6 key
VK_7	37H	7 key
VK_8	38H	8 key
VK_9	39H	9 key
+	3AH−40H	Undefined
VK_A	41H	A key
VK_B	42H	B key
VK_C	43H	C key
VK_D	44H	D key
VK_E	45H	E key
VK_F	46H	F key
VK_G	47H	G key
VK_H	48H	H key
VK_I	49H	I key
VK_J	4AH	J key
VK_K	4BH	K key
VK_L	4CH	L key
VK_M	4DH	M key
VK_N	4EH	N key
VK_O	4FH	O key
VK_P	50H	P key
VK_Q	51H	Q key
VK_R	52H	R key
VK_S	53H	S key
VK_T	54H	T key
VK_U	55H	U key
VK_V	56H	V key
VK_W	57H	W key
VK_X	58H	X key
VK_Y	59H	Y key
VK_Z	5AH	Z key
+	5BH−5FH	Undefined
VK_NUMPAD0	60H	Numeric key pad 0 key
VK_NUMPAD1	61H	Numeric key pad 1 key
VK_NUMPAD2	62H	Numeric key pad 2 key
VK_NUMPAD3	63H	Numeric key pad 3 key
VK_NUMPAD4	64H	Numeric key pad 4 key
VK_NUMPAD5	65H	Numeric key pad 5 key
VK_NUMPAD6	66H	Numeric key pad 6 key
VK_NUMPAD7	67H	Numeric key pad 7 key
VK_NUMPAD8	68H	Numeric key pad 8 key
VK_NUMPAD9	69H	Numeric key pad 9 key
VK_MULTIPLY	6AH	Multiply key
VK_ADD	6BH	Add key
VK_SEPARATER	6CH	Separater key
VK_SUBTRACT	6DH	Subtract key
VK_DECIMAL	6EH	Decimal key
VK_DIVIDE	6FH	Divide key
VK_F1	70H	F1 key
VK_F2	71H	F2 key
VK_F3	72H	F3 key
VK_F4	73H	F4 key
VK_F5	74H	F5 key
VK_F6	75H	F6 key
VK_F7	76H	F7 key
VK_F8	77H	F8 key
VK_F9	78H	F9 key
VK_F10	79H	F10 key
VK_F11	7AH	F11 key
VK_F12	7BH	F12 key
VK_F13	7CH	F13 key
VK_F14	7DH	F14 key
VK_F15	7EH	F15 key
VK_F16	7FH	F16 key
+	80H−87H	OEM specific
+	88H−8FH	Unassigned
VK_NUMLOCK	90H	NUM LOCK key
+	91H	OEM specific
+	92H-B9H	Unassigned
+	BAH-C0H	OEM specific
+	C1H-DAH	Unassigned
+	DBH-E4H	OEM specific
+	E5H	Unassigned
+	E6H	OEM specific
+	E7H-E8H	Unassigned
+	E9H-F5H	OEM specific
+	F6H-FEH	Unassigned


  Chapter 6  Building the Help Files

After the topic files for your Help system have been written, you're ready to create a Help project file and run a build to test it. The Help project file contains all the information the Help Compiler needs to convert Help topic files into a binary Help resource file.

You use the Help project file to tell the Help Compiler which topic files to include in the build process. Information in the Help project file also lets the Help Compiler map specific topics to context numbers. This chapter describes the following:

•	Creating the Help project file.

•	Specifying topic files.

•	Specifying options.

•	Specifying build tags.

•	Specifying alternate context strings.

•	Mapping context-sensitive topics.

•	Including bitmaps by reference.

•	Customizing Help.

•	Defining window attributes.

•	Using external files.

•	A sample project file.

•	Compiling the Help file.


  Creating the Help Project File

You use the Help project file to control how the Help Compiler creates a Help file from your topic files. You can use any text editor to create your Help project file, but you must save the file as unformatted text (ASCII). The extension of a Help project file is .HPJ. If you do not use the extension .HPJ on the command line, the Help Compiler looks for a Help project file with this extension in the current directory before loading the file. The Help output file (.HLP) will have the same name as the Help project file (.HPJ).

The Help project file contains up to nine sections, each of which specifies information about the source files to compile or directives for the Help Compiler to follow at compile time.

Section names are placed within square brackets using the following syntax:

[sectioname]

You can use a semicolon (;) to indicate a comment in the Help project file. The Help Compiler ignores all text from the semicolon to the end of the line on which it occurs.

Note  The order of the various sections within the Help project file is unimportant, with one exception: if an [Alias] section is used, it must precede the [Map] section.


  Section List

The following table describes each of the sections you can create in a Help project file.

Section	Description
[OPTIONS]	Specifies options that control the build process. This section is optional. If used, it should be the first section listed in the Help project file so that the options will apply during the entire build process.
[FILES]	Specifies topic files to be included in the build. This section is required.
[BUILDTAGS]	Specifies valid build tags. This section is optional.
[CONFIG]	Specifies author-defined menus and buttons used in the Help file and registers dynamic-link libraries (DLLs) and DLL functions used as macros within the Help file. This section is required if the Help file uses any of these features.
[BITMAPS]	Specifies bitmap files to be included in the build. This section is not required if the Help project file lists a path for bitmap files in the [OPTIONS] section using the BMROOT or ROOT option. For more details, see »Specifying Options« later in this chapter.
[MAP]	Associates context strings with context numbers. This section is optional.
[ALIAS]	Assigns one or more context strings to the same topic. This section is optional.
[WINDOWS]	Defines the characteristics of the primary Help window and types of secondary windows used in the Help file. This section is required if the Help file uses secondary windows.
[BAGGAGE]	Lists files to be placed within the Help file's .HLP file (which contains its own file system). This section is optional.


  Specifying Topic Files

Use the [Files] section of the Help project file to list all topic files that the Help Compiler should process to produce a Help resource file. A Help project file must have a [Files] section.

The following CallHelp sample shows the format of the [Files] section:

[FILES]

CALLHELP.DOC	; Main topics for CallHelp application.

Note that because CallHelp is a small project, all topics are listed in the same file.

Using the path defined in the ROOT option, the Help Compiler finds and processes all files listed in this section of the Help project file. If the file is not on the defined path and can't be found, the Help Compiler generates an error. For more information, see the »ROOT Option« section later in this chapter.

You can include other list files in the build process with the #include directive (the #include directive is used as it is in C language). The #include directive uses the following syntax:

#include <filename>

You must include the angle brackets around the file name. The number sign (#) must be the first character in the line. The file name must specify a complete path, either the path defined by the ROOT option or an absolute directory path to the file.

You may find it easier to create a text file that lists all files in the Help project and include that file in the build, as in this example:

[FILES]

#include <hlpfiles.txt>


  Specifying Options

The [OPTIONS] section includes options that control how a Help file is built and what feedback the build process displays. If this section is included in the Help project file, it should be the first section listed so that the options will apply during the entire build process. This section can include the following options.

Option	Description
BMROOT	Designates the directory where the Help Compiler can find the bitmap files used in bmc, bml, and bmr references in the Help topic files.
BUILD	Determines which topics to include or exclude in the build.
COMPRESS	Specifies what type of compression to use during the build.
CONTENTS	Specifies the context string of the contents topic for a Help file.
COPYRIGHT	Adds a unique copyright message for the Help file to the About dialog box.
ERRORLOG	Puts compilation errors in a file during the build.
FORCEFONT	Forces all authored fonts in the RTF topic files to appear in a different font when displayed in the Help file.
ICON	Specifies that the icon file to be displayed when the Help file is minimized.
LANGUAGE	Specifies a different sort ordering for Help files authored in a Scandinavian language.
MAPFONTSIZE	Maps a font size in the RTF file to a different font size in the compiled Help file.
MULTIKEY	Specifies an alternate keyword table for mapping topics.
OLDKEYPHRASE	Designates whether the Help Compiler should use the existing key phrase table or create a new one during the build.
REPORT	Controls the display of messages during the build process.
ROOT	Designates the directories used to locate topic and data files listed in the Help project file.
TITLE	Specifies the text that is displayed in the title bar of the Help window when the file is open.
WARNING	Indicates the level of error-message reporting the Help Compiler displays during the build.
These options can appear in any order within the [OPTIONS] section. The [OPTIONS] section is not required.

Detailed explanations of each of these options follow.


  BMROOT Option

The BMROOT option designates the directory where the WinHelp application looks for bitmap files specified in bmc, bml, and bmr references. This option uses the following syntax:

BMROOT = pathname[, pathname]

Each pathname can specify a drive and full path. If the Help project file has a BMROOT option, you don't need to list bitmap files in the [BITMAPS] section.

If the Help project file doesn't have a BMROOT option, WinHelp looks for bitmaps in the directories specified by the ROOT option. If the Help project file doesn't have a ROOT option, or if the ROOT option doesn't specify the directory containing the bitmap files, you must list the file name for each bitmap in the [BITMAPS] section of the Help project file.

For example, the following entry specifies that bitmaps reside in the \HELP\BMP directory on drive C and in the \GRAPHICS\ART directory on drive D:

[OPTIONS]

BMROOT = C:\HELP\BMP, D:\GRAPHICS\ART


  BUILD Option

The BUILD option specifies whether topics containing build tags are included or excluded in a build. Use this option only if the RTF topic files have build tags.

The BUILD option line uses the following syntax:

BUILD = expression

The expression is a logical statement that specifies which topics to include or exclude in the build. The logical symbols used in an expression appear as follows in order of importance.

Symbol	Description
( )	Parentheses
&	AND operator
|	OR operator
~	NOT operator
tag	Build tag
The Help Compiler evaluates all build expressions from left to right using the following precedence rules:

•	Expressions within parentheses are evaluated first.

•	Expressions with a logical NOT (~) are evaluated next.

•	Expressions with a logical AND (&) are evaluated next.

•	Expressions with a logical OR ( | ) are evaluated next.

For example, if you code DEMO, MASTER, and TEST_BUILD build tags in your topic files, you can include any one of the following build expressions in the [OPTIONS] section.

Example	Topics built
BUILD = DEMO	Only topics that have the DEMO tag or topics with no tags.
BUILD = DEMO & MASTER	Topics that have both the DEMO and the MASTER build tags, or topics with no tags.
BUILD = DEMO | MASTER	Topics that have either the DEMO tag or the MASTER tag, or topics with no tags.
BUILD = (DEMO | MASTER) & TEST_BUILD	Topics that have either the DEMO or the MASTER build tags and that also have the TEST_BUILD tag, or topics with no tags.
BUILD =~ MASTER	Topics that do not have a MASTER tag or topics with no tags.


  COMPRESS Option

The COMPRESS option specifies the level of compression for the build: no compression, a medium level of compression (approximately 40%), or a high level of compression (approximately 50%). Depending on the degree of compression requested, the build uses either block compression or block and key-phrase compression.

•	Block compression compresses the topic data into predefined units known as blocks.

•	Key-phrase compression combines repeated phrases found within the source file(s). The Help Compiler creates a phrase-table file with the .PH extension if it doesn't find one. If the Help Compiler finds a file with the .PH extension, it uses that file for the current compilation. Because the .PH file speeds the compression process when the text hasn't changed significantly since the last compilation, you might want to save the phrase file if you compile the same Help file several times with compression. You will get maximum compression, however, if you delete the .PH file before starting each build.

The following forms of the option specify no compression:

COMPRESS = NO

COMPRESS = FALSE

COMPRESS = 0

The following form of the option specifies medium compression:

COMPRESS = MEDIUM

The following forms of the option specify high compression (block and key-phrase):

COMPRESS = YES

COMPRESS = TRUE

COMPRESS = 1

COMPRESS = HIGH


  CONTENTS Option

The CONTENTS option identifies the context string of the highest-level or "home" topic (usually a Table of Contents or index within the Help file). Users access this topic by choosing the Contents button.

If the [OPTIONS] section does not include a CONTENTS option, the Help Compiler assumes that the contents topic is the first topic it encounters in the first listed topic file in the [FILES] section of the Help project file.

The CONTENTS option uses the following syntax:

CONTENTS = contextstring

The following example tells the Help Compiler that the context string of the contents topic for this Help file is "main_contents":

CONTENTS = main_contents


  COPYRIGHT Option

The COPYRIGHT option places custom text in the About dialog box of WinHelp. This option has the following syntax:

COPYRIGHT = copyrightnotice

The placeholder copyrightnotice usually contains the copyright information you want to display for users of your Help file, although you can use this option to provide a version number or other information. The notice is displayed immediately following the Microsoft Help copyright notice in the About dialog box, and can contain from 35 to 75 characters.


  ERRORLOG Option

The ERRORLOG option displays error messages on the screen during the build. It also writes the messages to a file at the same time. This option has the following syntax:

ERRORLOG = errorfilename

The errorfilename can be an absolute path, or a relative path if you want the file to be written to a different directory than the Help project root directory.

For example, the following code would write all errors during the build to the file HLPBUGS.TXT file in the Help project root directory:

ERRORLOG = HLPBUGS.TXT


  FORCEFONT Option

The FORCEFONT option creates a Help file that displays text in only one font. This option is useful if you must compile a Help file with topic files that include fonts not supported by your user's system.

The FORCEFONT option has the following syntax:

FORCEFONT = fontname

Font names must be spelled as they appear in the Fonts dialog box in the Microsoft Windows Control Panel. These font names do not exceed 20 characters. If you designate a font that the Help Compiler does not recognize, WinHelp uses the Helvetica font as the default for the Help file.


  ICON Option

The ICON option identifies the icon file to display when the user minimizes the WinHelp application. This option has the following syntax:

ICON = iconfile

The iconfile is the file name of the .ICO bitmap file.


  LANGUAGE Option

The LANGUAGE option changes the sort ordering in the Search keyword list box to something other than English alphabetic ordering.

This option uses the following syntax:

LANGUAGE = languagename

Because WinHelp 3.1 supports only one language sort ordering other than English, the languagename parameter must be "Scandinavian" if you use this option.


  MAPFONTSIZE Option

The MAPFONTSIZE option maps font sizes specified in your topic files to different sizes when displayed in the Help window. This means you can use one font size in your topic files and have the Help Compiler change it to an appropriate size for the actual Help file display.

This option is especially useful if there is a significant size difference between your authoring monitor and your intended display monitor, as there is between screen fonts on the Apple® Macintosh™ and Microsoft Windows.

The MAPFONTSIZE option uses the following syntax:

MAPFONTSIZE = m[-n]:p

The m argument is the size of the source font, and the p argument is the size of the desired font for the Help file. All fonts in the topic files that are size m are changed to size p. The optional argument, n, allows you to specify a font range to be mapped. All fonts in the topic files falling between m and n, inclusively, are changed to size p.

The following examples illustrate the use of the MAPFONTSIZE option:

MAPFONTSIZE = 8:12        ; make all 8 pt. fonts come out 12 pt.

MAPFONTSIZE = 12-24:16    ; make fonts from 12 to 24 pt. come out 16 pt.

You can specify up to five font ranges in the [OPTIONS] section of the Help project file; however, you can map only one font size or range with each MAPFONTSIZE statement. If you use more than one MAPFONTSIZE statement, the source font size or range specified in subsequent statements can't overlap previous mappings. For instance, the following mappings would generate an error when the Help Compiler encountered the second statement:

MAPFONTSIZE = 12-24:16

MAPFONTSIZE = 14:20

Because the second mapping statement contains a size already mapped in the preceding statement (14-point font falls within the 12- to 24-point range), the Help Compiler will ignore the second line.


  MULTIKEY Option

The MULTIKEY option specifies the footnote character to use for an additional keyword table.

This option uses the following syntax:

MULTIKEY = footnotecharacter

The footnotecharacter argument is the case-sensitive letter used for the keyword footnote. The following example illustrates how to enable the letter L for a keyword table footnote:

MULTIKEY = L

Note  Be sure to limit your keyword table footnotes to one case, usually uppercase. In the previous example, topics with the footnote L would have their keywords incorporated into the additional keyword table, whereas those assigned the lowercase letter l would not.

You can use any alphanumeric character for a keyword table except K and k, which are reserved for Help's standard keyword table. There is an absolute limit of five keyword tables, including the standard table. Depending upon your system configuration and the structure of your Help system, however, a practical limit of only two or three may be more realistic. If the Help Compiler can't create an additional keyword table, the additional table is ignored in the build.


  REPORT Option

The REPORT option displays messages on the screen during the build. These messages indicate when the Help Compiler is performing the different phases of the build, including compiling the file, resolving jumps, and verifying browse sequences.

The following option turns on the message display:

REPORT = ON


  ROOT Option

The ROOT option designates the directories in which the Help Compiler looks for files listed in the Help project file.

This option has the following syntax:

ROOT = pathname[, pathname]

Each pathname can specify either a drive and full path or a relative path from the project directory. If the Help project file has a ROOT option, all relative paths in the Help project file refer to one of these paths. If the Help project file does not have a ROOT option, all paths are relative to the directory containing the Help project file.

If the Help project file does not have a BMROOT option, the Help Compiler looks in the directories specified by the ROOT option to find all bitmaps included by reference. If none of the directories specified by the ROOT option contains these bitmaps, the bitmap file names must be listed in the [BITMAPS] section of the Help project file.

For example, the following entry specifies that the project root directory is named \WINHELP\HELPDIR and is located on drive C:

[OPTIONS]

ROOT = C:\WINHELP\HELPDIR

Given this root directory, the entry "TOPICS\FILE.RTF" in the [FILES] section actually refers to the path C:\WINHELP\HELPDIR\TOPICS\FILE.RTF.


  TITLE Option

The TITLE option assigns a title of up to 50 characters to your Help file. This option uses the following syntax:

TITLE = titlename

The titlename is displayed in the WinHelp title bar. If you do not specify a title using the TITLE option, the title bar displays "Microsoft Help."

The following example displays the title "Cardfile Help" in the Help title bar:

[OPTIONS]

TITLE = Cardfile Help


  WARNING Option

The WARNING option specifies the amount of debugging information that the Help Compiler reports.

This option has the following syntax:

WARNING = level

You can set the warning level to the following levels.

Level	Help Compiler reports
1	Only the most severe errors.
2	An intermediate number of errors.
3	All errors and warnings.
The following example specifies an intermediate level of error reporting:

[OPTIONS]

WARNING = 2


  Sample [OPTIONS] Section

The following example shows the [OPTIONS] section in a sample Help project file.

[OPTIONS]

COMPRESS = OFF

WARNING = 3

ERRORLOG = CARD.LOG

REPORT = ON

This sample [OPTIONS] section indicates the following to the Help Compiler:

•	Do not use compression during the build.

•	Report all errors and warnings.

•	Write messages displayed during the build to the file CARD.LOG.

•	Display messages throughout the build to indicate when processes are occurring.


  Specifying Build Tags

If you code build tags in your topic files, use the [BUILDTAGS] section of the Help project file to define all the valid build tags for a particular Help project. The [BUILDTAGS] section is optional.

Note  Use build tags when you plan to share files among Help projects. Tags allow you to select specific topics to share or exclude.

The following example shows the format of the [BUILDTAGS] section in a sample Help project file:

[BUILDTAGS]

DEBUGONLY	; Topics for debugging build.

TESTONLY	; Topics for a mini-build for testing.

The [BUILDTAGS] section can include up to 30 build tags. Build tags are not case-sensitive and can't contain space characters. Only one build tag is allowed per line in this section. The Help Compiler generates an error message if anything other than a comment is listed after a build tag in the [BUILDTAGS] section.

For information about coding build tags in topic files, see »Assigning Build Tags«.


  Specifying Alternate Context Strings

Use the [Alias] section to assign one or more context strings to the same topic alias. Because context strings must be unique for each topic and can't be used for any other topic in the Help project file, the [Alias] section provides a way to combine Help topics without recoding your files. The [Alias] section is optional.

For example, if you create a topic that replaces the information in three other topics, and you delete those three topics, you'll have to search through your files for invalid cross-references to the deleted topics. You can avoid this problem by using the [Alias] section to assign the name of the new topic to the deleted topics. The [Alias] section can also be used when your application program has multiple context identifiers for which you have only one topic. This can be the case with context-sensitive Help.

Each expression in the [Alias] section has the following format:

contextstring = alias

In the alias expression, the alias parameter is the alternate string, or alias name, and the contextstring parameter is the context string identifying a particular topic. An alias string has the same format and follows the same conventions as the topic context string — that is, it is not case-sensitive and can contain the alphabetic characters A − Z, numeric characters 0 − 9, and the period (.) and underscore ( _ ) characters.

The following example illustrates an [Alias] section.

[ALIAS]

sm_key = key_shrtcuts

cc_key = key_shrtcuts

st_key = key_shrtcuts	; Combined into Keyboard Shortcuts topic.

clskey = us_dlog_bxs

maakey = us_dlog_bxs	; Covered in Using Dialog Boxes topic.

chk_key = dlogprts

drp_key = dlogprts

lst_key = dlogprts

opt_key = dlogprts

tbx_key = dlogprts	; Combined into Parts of Dialog Box topic.

frmtxt = edittxt

wrptxt = edittxt

seltxt = edittxt	; Covered in Editing Text topic.


  Mapping Context-Sensitive Topics

If your Help system supports context-sensitive Help, use the [Map] section to associate either context strings or aliases to context numbers. The context number corresponds to a value the parent application passes to the WinHelp application to display a particular topic. This section is optional.

When writing the [Map] section, you can:

•	Use either decimal or hexadecimal numbers (formatted in standard C-language notation) to specify context numbers.

•	Assign a unique context number to each context string or alias. Assigning the same context number to more than one context string generates a compiler error.

•	Separate context numbers and context strings by an arbitrary amount of white space, using either space characters or tabs.

You can use the #include directive to include other files in the mapping. (The syntax for #include is the same as in C language.) In addition, the [Map] section supports an extended format that allows you to include C header files (files with an .H extension) directly. Entries using this format must begin with the #define directive and can contain comments in C format, as in this example:

#define	   contextstring	   contextnumber	   /* Comment */

The following examples illustrate several formats you can use in the [Map] section.

[MAP]

Edit_Window	0x0001

Control_Menu	0x0002

Maximize_Icon	0x0003

Minimize_Icon	0x0004

Split_Bar	0x0005

Scroll_Bar	0x0006

Title_Bar	0x0007

Window_Border	0x0008

dcmb_scr	30	; Document Control Menu Icon.

dmxi_scr	31	; Document Maximize Icon.

dmni_scr	32	; Document Minimize Icon.

dri_scr	33	; Document Restore Icon.

dtb_scr	34	; Document Title Bar.

#define vscroll	0x010A	/* Vertical Scroll Bar */

#define hscroll	0x010E	/* Horizontal Scroll Bar */

#define scrollthm	0x0111	/* Scroll Thumb */

#define upscroll	0x0112	/* Up Scroll Arrow */

#define dnscroll	0x0113	/* Down Scroll Arrow */

#include <sample.h>

You can define the context strings listed in the [Map] section either in a Help topic file or in the [Alias] section. The Help Compiler generates a warning message if a context string appearing in the [Map] section is not defined in any of the topic files or in the [Alias] section.

Note  If you use an alias name, the [Alias] section must precede the [Map] section in the Help project file.

For information about context-sensitive Help, see »Planning Context Sensitivity«.


  Including Bitmaps by Reference

To refer to bitmaps not located in the directories specified in the ROOT or BMROOT option, you must list the bitmap file names in the [Bitmaps] section of the Help project file. The following example illustrates the format of the [Bitmaps] section:

[BITMAPS]

DUMP01.BMP

DUMP02.BMP

DUMP03.BMP

C:\PROJECT\HELP\BITMAPS\DUMP04.BMP

Use either relative paths from the directories specified by the ROOT option as defined with the ROOT or BMROOT option in the [Options] section, or use absolute paths.

Note  The [Bitmaps] section uses the same rules as the [Files] section for locating bitmap files.


  Customizing Help

The [CONFIG] section of the Help project file registers DLLs and specifies macros that WinHelp runs when a Help file is opened. Help macros typically add menus or buttons to the standard WinHelp application. For descriptions of these macros, see »Chapter 5, Creating Help Macros.«

The [CONFIG] section also contains macros that register routines in external DLLs as WinHelp macros. These routines can be used the same way WinHelp macros are used. The RegisterRoutine macro registers DLL routines; for more information on this Help macro, see »Chapter 5, Creating Help Macros.«

The [CONFIG] section can include any number of lines. Each line of the [CONFIG] section can contain up to 254 characters.

The following example shows the format of the [CONFIG] section in a sample Help project file:

[CONFIG]

RegisterRoutine("bmp","HDisplayBmp","USSS")

RegisterRoutine("bmp","CopyBmp", "v = USS")

CreateButton("btn_up", "&Up", "JumpContents(`HOME.HLP')")

BrowseButtons()

SetHelpOnFile("APPHELP.HLP")

This sample [CONFIG] section performs the following operations:

•	Registers the DLL required to display extended bitmap windows (HDisplayBmp).

•	Registers a routine to copy a bitmap from an embedded window (CopyBmp).

•	Creates an Up button to aid users in navigating the Help system (CreateButton).

•	Adds browse buttons to the WinHelp toolbar (BrowseButtons).

•	Replaces the standard Using Help file with a customized version (SetHelpOnFile).


  Defining Window Attributes

The [WINDOWS] section of the Help project file defines the size, location, and colors for the primary Help window and any secondary window types used in a Help file.

Window characteristics are defined using the following syntax:

typename = "caption", (horizposition, vertposition, width, height), sizing,
(clientRGB), (nonscrollingRGB), topmost

Parameters	Description
typename	Specifies the type of window that uses the defined attributes. For the primary Help window, this parameter is main. For a secondary window type, this parameter can be any unique name up to eight characters other than main. Any jumps that display a topic in a secondary window give this unique type name as part of the jump.
caption	The caption that appears on the title bar of different types of secondary windows. For the main Help window, this caption is given by the Help TITLE option in the [OPTIONS] section of the Help project file.
horizposition, vertposition	Horizontal and vertical position, respectively, of the window's upper-left corner. WinHelp uses a 1024 x 1024 coordinate system internally and maps this coordinate system onto the resolution of the video card displaying the Help file. If a video card has resolution hres by vres pixels, and the horizontal and vertical positions are horizposition and vertposition, the x-coordinate of the window corner is: horizposition * (hres/1024) and the y-coordinate is: vertposition * (vres/1024)
width, height	Gives the default width and height of a secondary window. The width and height, like the x and y positions, are based on the resolution of the video adapter (as indicated for the horizposition and vertposition parameters in the preceding description).
sizing	Specifies how a secondary window is sized when WinHelp first opens it. This parameter is 0 for normal size and 1 for maximized. If the value is 1, WinHelp ignores the horizposition, vertposition, width, and height parameters given in the type definition.
clientRGB, nonscrollingRGB	Three-digit values giving the background colors for the window and nonscrolling region (if any) in the window. The three digits represent the red, green, and blue (RGB) components of the color. If these colors are not given, the scrolling and nonscrolling areas are displayed with the normal system colors in the background.
topmost	Specifies whether a secondary window always remains on top of all other windows. This parameter is optional. If not specified, the secondary window normally moves behind other windows. If the value is 1, WinHelp keeps the secondary window on top of other windows. This feature works only when WinHelp 3.1 is running under Windows version 3.1.


  Using External Files

The [BAGGAGE] section of the Help project file lists files (typically multimedia elements) that the Help Compiler stores within the Help (.HLP) file's internal file system. WinHelp can access data files stored in the Help file system more efficiently than files in the normal MS-DOS file system because it doesn't have to read the file allocation table from the CD-ROM.

A maximum of 1000 bitmap files can be stored as baggage files.

If a file is listed in the [BAGGAGE] section, refer to that file in the topic file by prefixing an exclamation point (!) to the file name. In the topic file, the file name must appear exactly the same as it appears in the [BAGGAGE] section. To avoid having to specify a full path, use the ROOT option in the [OPTIONS] section to specify the path. That way, all file names that you give in the topic file are relative to the path specified in the ROOT option. (For more information, see the »ROOT Option« section earlier in this chapter.)


  Sample Project File

The following example is a sample project file for the Cardfile application. Comments indicate the purpose of each section in the file:

; Options used to define the Help title bar and icon
[OPTIONS]
ROOT=C:\HELP
BMROOT=C:\HELP\ART
CONTENTS=cont_idx_card
TITLE=Cardfile Help
ICON=CARDHLP.ICO
COMPRESS=OFF
WARNING=3
REPORT=ON
ERRORLOG=CARD.BUG

; Files used to build Cardfile Help
[FILES]
RTFTXT\COMMANDS.RTF
RTFTXT\HOWTO.RTF
RTFTXT\KEYS.RTF
RTFTXT\GLOSSARY.RTF

; Button macros and Using Help file
[CONFIG]
CreateButton("btn_up", "&Up", "JumpContents(`HOME.HLP')")
BrowseButtons()
SetHelpOnFile("APPHELP.HLP")

; Secondary-window characteristics
[WINDOWS]
picture = "Samples", (123,123,256,256), 0, (0,255,255), (255,0,0)


  Compiling the Help File

After you've created a Help project file, you're ready to build a Help file using the Help Compiler. The Help Compiler generates the binary Help resource file from the topic files listed in the Help project file. When the build process is complete, your application can access the resulting Help resource file.

Before initiating a build operation to create the Help file, consider the locations of the following files:

•	The Help Compiler, HC31.EXE. The Help Compiler must be in a directory from which it can be executed. This could be the current working directory, on the path set with the PATH environment variable, or a directory specified by a fully qualified path, as follows:

C:\BIN\HC31 CALLHELP.HPJ

•	The Help project file, filename.HPJ. The project file can be located either in the current directory or specified by a path, as follows:

C:\BIN\HC31 D:\MYPROJ\CALLHELP.HPJ

•	The topic files named in the Help project file, saved as RTF. The topic files can be located in the current working directory, a subdirectory of the current working directory specified in the [Files] section, or the location specified in the ROOT option.

•	Files included with the #include directive in the Help project file. Because the #include directive can take paths, any number of locations will work for these files.

•	All bitmap files (filename.BMP) listed by reference in the topic files.

You must also place any files named in an #include directive in the path of the project root directory or specify their path using the ROOT option. The Help Compiler searches only the directories specified in the Help project file. For information about the ROOT option, see the section »ROOT Option« earlier in this chapter.

Note  If you use a RAM drive for temporary files, the drive must be large enough to hold the compiled Help resource file. If your Help file is larger than the size of the available RAM drive, the Help Compiler will generate an error message and the compilation will stop.


  Building a Help File

After you've created the topic files and project file, the job of building the Help file is simple.

Note  Version 3.10.504 of the Windows Help Compiler (HC31.EXE) requires protected-mode memory. A number of system configurations support protected-mode memory by providing DPMI or VCPI servers. The following configurations provide protected-mode memory access to the Help Compiler, although not all configurations have been fully tested.

•	Microsoft Windows version 3.0 or 3.1

The best way to access protected-mode memory is to run the Help Compiler in an MS-DOS session under Windows 3.1 enhanced or standard mode. You can also compile in an MS-DOS session under Windows 3.0 enhanced mode.

•	EMM386 under MS-DOS

The Help Compiler runs under EMM386 (if the noems option is not used and enough EMS memory is allocated to EMM386).

•	386Max

The Help Compiler runs as a DPMI client with version 6.01 of 386Max (the version shipped with Microsoft C version 7.0 or its equivalent). The Help Compiler can also work with some earlier versions of 386Max as a VCPI client if enough EMS memory is configured.

•	QEMM

Under version 6.02 of QEMM, the Help Compiler runs as a DPMI client. It should also work under some earlier versions of QEMM as a VCPI client, provided it is configured with enough EMS memory.

•	EMS Memory Requirements

You need enough EMS memory to hold the Help Compiler and dynamic data being compiled. The exact amount of memory needed depends heavily on the size of the Help file you want to compile. Between 1MB and 2MB should meet most needs.

To build a Help file:

1.	To monitor the build process on your monitor, edit the Help project file and enter the following options in the [OPTIONS] section:

WARNING = 3

REPORT = ON

When the WARNING option is set, the Help Compiler reports all warnings and errors it encounters during the build. When the REPORT option is set, the Help Compiler displays its messages as it performs the different phases of the build, including compiling the file, resolving jumps, and verifying browse sequences.

2.	Change to the directory that holds the Help project file.

3.	Type the HC31 command using the following syntax:

hc31 projectfile

The projectfile is the name of your Help project file. The Help Compiler assumes that your Help project file has an .HPJ extension. The following code is a sample HC31 command:

HC31 myhelp

The Help Compiler displays periods on the screen to show its progress and warnings and error messages when it encounters problems. For more information, see »Debugging the Help File«.

If everything goes smoothly, the Help Compiler creates a Help file in the project directory and then returns to the command line. The Help file has the same name as the Help project file, but with an extension of .HLP. For example, the command in the preceding example would produce MYHELP.HLP.


  Building Large Help Files

The number of topic files affects the amount of time required to complete the build. Help files consisting of a small number of files compile quickly; Help files with large numbers of files can require several hours to compile.

For large Help files, you might want to start the build process at the end of the day and let it work at night. (You can also start a build at the command line within Windows, then change its settings to run in the background while you use other applications. For more information, see the Microsoft Windows User's Guide.)


  Building Separate Topic Files

To improve efficiency, you can divide your Help file into separate topic files, and then build and test those files independently. The easiest way to compile individual files separately is by editing the .HPJ file and commenting out lines in the [FILES] section for topic files you don't want to include. To comment out a line, insert a semicolon (;) at the beginning of the line; the Help Compiler ignores that line. Remember, though, that if you comment out topic files that contain hot spots referencing excluded topics, you'll receive warnings as the Help file builds.


  Chapter 7  Testing and Debugging Help Files

The Help Compiler displays a message when it encounters an error in building the Help file. Whenever possible, the Help Compiler displays the name of the topic file that contains the error, as well as the number used to identify the specific line of the Help Project (.HPJ) file or the topic that produced the error.

Understanding how the Help Compiler reports and reacts to errors allows you to test and debug your Help files. This chapter describes the error-reporting behavior of the Help Compiler and lists Help Compiler error messages. Each message is shown as it appears when the Help Compiler encounters the specific error. A short explanation accompanies each message to aid you in solving the problem in your Help system.


  Debugging the Help File

This section examines ways you can investigate problems that might arise during the build process.

Because topics are not actually numbered, the topic number given with an error message refers to that topic's sequential position in the topic file (first topic, second topic, and so on). These numbers may be identical to the page numbers shown by your word processor, depending on the number of lines you've assigned to the hypothetical printed page. Remember that topics are separated by hard page breaks, even though there is no such thing as a "page" in the Help system.

A single error in a topic file can cause the Help Compiler to produce many error messages. For example, an incorrectly identified topic causes an error every time a jump term refers to the correct topic identifier. Such a mistake is easily fixed by correcting the footnote that contains the incorrect context string. In general, if you find an error (for example, an unresolved jump), correct it, and then recompile.

Note  An easy way to avoid build errors is to make sure the Help Compiler can access all the topic files and graphic files needed to build the Help file.


  Displaying Error Messages on the Screen

The REPORT option in the Help project file tells the Help Compiler to display messages on the screen while it is building. These messages indicate when the Help Compiler is performing the different phases of the build, including compiling the file, resolving jumps, and verifying browse sequences.

The following option turns on the message display:

REPORT = on


  Warning Message Reporting

You can specify the level of warnings reported by the Help Compiler during the build process. Warning messages alert you to conditions that are not serious enough to stop the build but that might cause problems in your Help file.

The WARNING option in your .HPJ file sets the amount of warning information that the Help Compiler displays. You set the warning level under the [OPTIONS] section, using the following command:

WARNING = level

The following table describes each of the three possible reporting levels.

Warning level	Build program reports
1	Only the most severe warnings.
2	Severe and less serious warnings.
3	All warnings.
The following example specifies the intermediate level of error reporting:

[OPTIONS]

WARNING = 2

For information about the [OPTIONS] section of the Help project file, see »Specifying Options«.


  Redirecting Errors to a File

By default, the Help Compiler displays all errors on your screen; however, you can redirect errors to a file so that you can examine the errors more carefully and fix problems in your Help file. You can examine the redirected file using any ASCII text editor. Use the standard MS-DOS syntax to redirect error and status messages to a file. For example, this command places all the messages sent during the build process into the ERRORS.TXT file:

HC31 MYHELP.HPJ > ERRORS.TXT

You can also enter the following option in the [OPTIONS] section of your Help project file:

ERRORLOG = errorfile

The Help Compiler places compilation errors in the file given by errorfile. The errorfile can be an absolute path, or a relative path if the file doesn't appear in the standard Viewer directory. Using ERRORLOG eliminates two disadvantages of redirecting error messages:

•	In addition to error messages, the Help Compiler puts unnecessary characters (including the periods it displays to indicate the progress of the build) and status messages in the output file. Using ERRORLOG will give you only the error messages.

•	Using redirection, the Help Compiler doesn't display error messages on the screen, so you can't monitor the messages during the build. Using ERRORLOG, the Help Compiler displays the error messages on the screen and writes them to the file.


  Testing the Built Help File

Once you've successfully built your Help file, you'll want to look at the finished product to see if there are problems in displaying the topics.

To test a built Help file:

1.	In Microsoft Windows, start the WinHelp application by clicking the WinHelp icon or choosing the Run command from the Program Manager.

2.	From the File menu, choose Open and open the Help file you have built.

3.	Test all components to make sure that text and graphics have been formatted correctly, that no typographical errors appear, and that all elements such as jumps, keywords, browse sequences, pop-up windows, and macros work correctly.


  Help Compiler Error Messages

This section lists the error messages that may be generated when you build a Help file.


  Interpreting Error Messages

Messages beginning with the word Error may indicate fatal errors. Fatal errors are always reported, because no usable Help file will result from the build. Messages beginning with the word Warning are less serious. A build with warnings produces a valid Help file that WinHelp can open, but the file may contain operational errors. As stated previously, you specify the amount of warning information to be reported by the Help Compiler using the WARNING option.

The following list describes the Help Compiler's response for each error. During processing of the .HPJ file, the Help Compiler ignores lines that contain errors and attempts to continue with the build. This means that errors encountered early in a build may result in many more errors being reported as the build continues.

Similarly, errors encountered during the processing of the RTF topic files are reported, but if the errors are not serious, the Help Compiler continues with the build.


  Error Message Categories

Build errors fall into eight general categories. Error message numbers have four digits. The first one or two digits of the number identify the message category. These one- or two-digit message-number prefixes and the categories they identify are listed in the following table.

Message prefix	Error category
1	Problems with files used to build the Help file.
2	Problems with the .HPJ file.
30−31	Problems with build tags or build-tag expressions.
35−36	Problems with Help macros.
40−41	Problems with context strings.
42−45	Problems with footnotes.
46−47	Problems with the .RTF file.
5	Miscellaneous problems.
Note  You might encounter errors other than the build errors described here. See the Readme file for more information.


  File Errors

The following messages result from problems with the files used to build a Help file.

Number	Error message
1019	Project file extension cannot be .HLP or .PH.
	You cannot specify a project file with an .HLP or .PH extension. Project files must use the .HPJ extension.
	Rename the Help project file and then recompile.
1030	File name exceeds limit of 259 characters.
	The combined length of the path and file name is more than the MS-DOS limit of 259 characters.
	Shorten the path and then recompile.
1079	Out of file handles.
	The Help Compiler does not have enough available file handles to continue the build.
1100	Cannot open file filename: permission denied.
	You do not have the required file privileges to open the requested file.
1150	Cannot overwrite file filename.
	The Help file cannot overwrite the specified file because the file has a Read-Only attribute.
	Rename the Help project file or change the Read-Only attribute.
1170	File filename is a directory.
	A subdirectory in the Help project root directory has the same name as the requested Help file. This is an MS-DOS file error.
	Move or rename the subdirectory and then recompile.
1190	Cannot use reserved MS-DOS file filename.
	A file has been referred to by a reserved MS-DOS name such as COM1, LPT2, or PRN. This is an MS-DOS file error.
	Rename the file and then recompile.
1230	File filename not found.
	The specified file could not be found or is unreadable. This is an MS-DOS file error or an out-of-memory condition.
	Check to see if the file exists and also check the amount of available memory.
1292	File filename is not a valid bitmap.
	The specified bitmap file could not be found or is not in a recognizable bitmap format. This is an MS-DOS file error or an out-of-memory condition.
	Check to see if the file exists, and if it does, check its format. If necessary, save the file again in your paint or draw program and then recompile.
1319	Disk full.
	The Help file could not be written to disk.
	Create more space on the destination disk and then recompile.
1513	Bitmap name filename duplicated.
	The [BITMAPS] section contains duplicate bitmap names. The Help Compiler uses the first occurrence of the name.
	Rename the duplicate bitmap file names and then recompile.
1536	Not enough memory to check and compress bitmap filename.
	The specified bitmaps cannot be compressed because of insufficient memory. If any of the specified bitmaps are segmented hypergraphics, the context strings stored in them are not checked for validity during the build.
1000	UNKNOWN ERROR Contact Microsoft Product Support Services.


  Project File Errors

The following messages result from errors in the .HPJ file used to build a Help file.

Number	Error message
2010	Include statements nested more than 5 deep.
	The #include statement on the specified line has exceeded the maximum of five include levels.  Do not nest #include statements more than five deep.


  Syntax Errors

The following messages result from syntax errors in the Help project file.

Number	Error message
2030	Comment starting at line linenumber of file filename unclosed at end of file.
	The Help Compiler has unexpectedly come to the end of the Help project file. There may be an open comment in the .HPJ file or in an included file.
2050	Invalid #include syntax.
	The correct #include syntax is as follows:
	#include <filename>
	Correct the syntax and then recompile.
2091	Bracket missing from section heading [sectionname].
	The right bracket (]) is missing from the specified section heading.
	Insert the bracket and then recompile.
2111	Section heading missing.
	The section heading on the specified line is not complete. This error is also reported if the first entry in the Help project file is not a section heading.
2131	Invalid OPTIONS syntax: 'option=value' expected.
	Check the syntax of the options in the [OPTIONS] section.
2141	Invalid ALIAS syntax: 'context=context' expected.
	Check the syntax of the entries in the [ALIAS] section.
2151	Incomplete line in [sectionname] section.
	The entry on the specified line is incomplete.
	The Help Compiler skips the line.
2171	Unrecognized text.
	There is unrecognizable text following valid text.
	The Help Compiler ignores the line.
2191	Section heading [sectionname] unrecognized.
	A section heading that is not supported by the Help Compiler has been used.
	The Help Compiler ignores the line.
2214	Line in .HPJ file exceeds length limit of 2047 characters.
	There is a line in the .HPJ file that exceeds the maximum length of 2047 characters.


  General Section Errors

The following messages result from general errors in the different sections of the Help project file.

Number	Error message
2273	[OPTIONS] should precede [FILES] and [BITMAPS] for all options to take effect.
	It is recommended that the [OPTIONS] section be the first section of the .HPJ file so that all the options will take effect. Also, if the ERRORLOG option is used, it should be the first line in the [OPTIONS] section.
2291	Section sectionname previously defined.
	A duplicate section has been found in the Help project file.
	The Help Compiler ignores the lines under the duplicated section and continues from the next valid section heading.
2305	No valid files in [FILES] section.
	The file section is either empty or contains only invalid files.
2322	Context string context_name cannot be used as alias string.
	A context string that has been assigned an alias cannot be used later as an alias for another context string. That is, you cannot map a = b and then c = a in the [ALIAS] section.
	The Help Compiler ignores the attempted reassignment on this line.
2331	Context number already used in [MAP] section.
	The context number on the specified line in the Help project file was previously mapped to a different context string.
	The Help Compiler ignores the line.


  Alias and Map Section Errors

The following messages result from errors in the [ALIAS] or [MAP] sections of the Help project file.

Number	Error message
2341	Invalid or missing context string.
	The specified line is missing a context string before an equal sign.
2351	Invalid context identification number.
	The context number on the specified line is empty or contains invalid characters.
2362	Context string context_name already assigned an alias.
	A context string can only have one alias. That is, you cannot map a = b and then a = c in the [ALIAS] section. The specified context string has already been assigned an alias in the [ALIAS] section.
	The Help Compiler ignores the attempted reassignment on this line.
2372	Alias string aliasname already assigned.
	You can't alias an alias. An alias string cannot, in turn, be assigned another alias. That is, you cannot map a = b and then b = c in the [ALIAS] section.
	The Help Compiler ignores the attempted reassignment on this line.


  Windows Section Errors

The following messages result from errors in the definitions of the types of secondary windows given in the [WINDOWS] section of the Help project file.

Number	Error message
2391	Limit of 6 window definitions exceeded.
	The maximum number of window definitions is one main window definition and five secondary window definitions.
2401	Window maximization state must be 0 or 1.
	The value of the fMax variable in the window attribute specification in the .HPJ file is something other than 0 or 1.
	Correct the entry and then recompile.
2411	Invalid syntax in window color.
	The correct syntax for the text and background color is: .mono (rrr, ggg, bbb).endmono.
	Correct the syntax and then recompile. For information on setting the window color, see »Defining Window Attributes«.
2421	Invalid window position.
	The correct syntax to indicate the predefined window position is: .mono (x, y, DX, dy).endmono.
	The Help Compiler ignores this line, and the window does not have a predefined position. For more information, see »Defining Window Attributes«.
2431	Missing quote in window caption.
	The value of the caption attribute for the window definition in the .HPJ file is not enclosed in quotation marks.
	Correct the syntax and then recompile.
2441	Window name windowname is too long.
	The window name exceeds the maximum length of 8 characters.
2451	Window position value out of range 01023.
	One or more of the window position coordinates (X, Y, X + dX, or [Y+dY]) exceed the maximum position value of 1023.
2461	Window name missing.
	The window specification in the .HPJ file is missing the window name.
2471	Invalid syntax in [WINDOWS] section.
	The entry for a main or secondary window is incorrect.
	The Help Compiler ignores the window entry.
	Check the window entry syntax and then recompile.
2481	Secondary window position required.
	The X, Y, dX, and dY entries for the secondary window definitions must be specified in the .HPJ file.
2491	Duplicate window name windowname.
	There are duplicate window names in the .HPJ file.
	Check the uniqueness of each member name and then recompile.
2501	Window caption windowcaption exceeds limit of 50 characters.
	The caption for the window exceeds the limit of 50 characters.


  Options Section Errors

The following error messages are caused by problems in the [OPTIONS] section of the Help project file.

Number	Error message
2511	Unrecognized option optionname in [OPTIONS] section.
	An option has been used that is not supported by the compiler.
	The Help Compiler skips this line.
2532	Option optionname previously defined.
	The specified option has been defined on a previous line.
	The Help Compiler ignores the attempted redefinition.
ROOT Option Errors

The following error messages are caused by problems with the ROOT option in the [OPTIONS] section of the Help project file.

Number	Error message
2550	Invalid path pathname in optionname option.
	The Help Compiler cannot find the path specified by the ROOT option.
	The Help Compiler uses the current working directory.
2570	Path in optionname option exceeds number of characters.
	The path specified by the ROOT option exceeds the MS-DOS maximum limit.
	The Help Compiler ignores the path and uses the current working directory.
Font Range Option Errors

The following error messages are caused by problems with the MAPFONTSIZE option in the [OPTIONS] section of the Help project file.

Number	Error message
2591	Invalid MAPFONTSIZE option.
	The font range syntax is invalid.
	The correct syntax is m[-n]:p.
2612	Maximum of 5 font ranges exceeded.
	The maximum number of font ranges that can be specified is five.
	The Help Compiler ignores any additional ranges.
2632	Current font range overlaps previously defined range.
	A font size range overlaps a previously defined mapping.
	The Help Compiler ignores the second mapping.
	Adjust one or both of the font ranges to remove any overlaps.
FORCEFONT Option Errors

The following error messages are caused by problems with the FORCEFONT option in the [OPTIONS] section of the Help project file.

Number	Error message
2651	Font name exceeds limit of 20 characters.
	Font names cannot exceed 20 characters.
	The Help Compiler ignores this line.
2672	Unrecognized font name fontname in FORCEFONT option.
	The Help Compiler has encountered a font name that it does not support.
	The Help Compiler ignores the font name and uses the default Helvetica font.
MULTIKEY Option Errors

The following error messages are caused by problems with the MULTIKEY option in the [OPTIONS] section of the Help project file.

Number	Error message
2691	Invalid MULTIKEY syntax.
	The Help Compiler does not recognize the syntax used in a MULTIKEY option. The valid syntax is MULTIKEY = char, where char is any capital letter other than K.
2711	Maximum of 5 keyword tables exceeded.
	The limit of five keyword tables has been exceeded.
	The Help Compiler ignores the additional tables.
	Reduce the number of tables and then recompile.
2732	Character already used.
	A character used for indicating the keyword table (MULTIKEY = char) was previously used.
	The Help Compiler ignores the entry.
2752	Characters 'K' and 'k' cannot be used.
	These characters are reserved for Help's normal keyword table.
	Choose another character and then recompile.
Other Options Errors

The following error messages are caused by problems with other options in the [OPTIONS] section of the Help project file.

Number	Error message
2771	REPORT option must be 'ON' or 'OFF.'
	The REPORT option must be either True, 1, ON, YES, False, 0, OFF, or NO.
	Correct the entry and then recompile.
2811	OLDKEYPHRASE option must be 'ON' or 'OFF.'
	The OLDKEYPHRASE option must be either True, 1, ON, YES, False, 0, OFF, or NO.
	Correct the entry and then recompile.
2832	COMPRESS option must be 'OFF', 'MEDIUM' or 'HIGH.'
	The COMPRESS option must be either 1, YES, ON, True, HIGH, MEDIUM, 0, NO, OFF, or False.
	Correct the entry and then recompile.
2852	Invalid TITLE option.
	The TITLE option defines a string that is empty or contains more than 32 characters.
	The Help Compiler truncates the title.
2872	Invalid LANGUAGE option.
	You have specified an ordering that is not supported by the compiler.
	The Help Compiler defaults to U.S. sort ordering.
2893	Warning option must be 1, 2, or 3.
	The warning reporting level can be set only to 1, 2, or 3.
	The Help Compiler defaults to full reporting (level 3).
2911	Invalid icon file filename.
	The Help Compiler cannot find the icon file specified in the ICON option, or the file is not a valid icon file.
2932	Copyright string exceeds limit of 50 characters.
	The maximum length of the copyright string in the About box is 50 characters.
	The Help Compiler truncates the string.
2000	UNKNOWN ERROR Contact Microsoft Product Support Services.


  BUILDTAG Footnote and Expression Errors

The following messages are caused by errors in build-tag footnotes or build expressions in the [BUILDTAGS] section of the Help project file.

Number	Error message
3011	Maximum of 32 build tags exceeded.
	The maximum number of build tags that can be defined is 32.
	The Help Compiler ignores the additional tags.
3031	Build tag length exceeds 32 characters.
	The build tag on the specified line exceeds the maximum of 32 characters.
	The Help Compiler skips this entry.
3051	Build tag tagname contains invalid characters.
	Build tags can contain only alphanumeric characters or the underscore ( _ ) character.
	The Help Compiler skips this line.
3076	[BUILDTAGS] section missing.
	The BUILD option declared a conditional build, but there is no [BUILDTAGS] section in the Help project file.
	The Help Compiler includes all topics in the build.
3096	Build expression too complex.
	The build expression has too many expressions (~, |, or &) or is too deeply nested.
3116	Invalid build expression.
	The syntax used on the specified line of the build expression contains one or more logical or syntax errors.
3133	Duplicate build tag in [BUILDTAGS] section.
	A build tag in the [BUILDTAGS] section has been repeated unnecessarily.
3152	Build tag tagname not defined in [BUILDTAGS] section.
	The specified build tag has been assigned to a topic, but not declared in the Help project file.
	The Help Compiler ignores the tag for the topic.
3178	Build expression missing from project file.
	The topics have build tags, but there is no BUILD = expression in the .HPJ file.
	The Help Compiler includes all topics in the build.


  Macro Errors

The following messages result from errors in the use of Help macros in footnotes, hot spots, and the [CONFIG] section of the Help project file.

Number	Error message
3511	Macro macrostring exceeds limit of 254 characters.
	The macro string exceeds the maximum limit of 254 characters.
3532	Undefined function in macro macroname.
	The specified macro is not on the list of macros supported by the compiler, nor is it specified in the RegisterRoutine().
	The Help Compiler nonetheless passes the macro to the .HLP file.
3552	Undefined variable in macro macroname.
	The macro contains a variable that is not recognized by the compiler.
3571	Wrong number of parameters to function in macro macroname.
	There are too many or too few parameters in the macro.
3591	Syntax error in macro macroname.
	The syntax of the macro is invalid.
3611	Function parameter type mismatch in macro macroname.
	There is a type mismatch (string or numeric) in the function call.
3631	Bad macro prototype.
	The prototype string passed to RegisterRoutine is invalid.
3652	Empty macro string.
	The ! footnote or a hidden text starting with ! does not contain a macro.
3000	UNKNOWN ERROR Contact Microsoft Product Support Services.


  Context String Errors

The following messages are caused by problems with context string footnotes or context strings specified in jumps or project file options.

Number	Error message
4011	Context string contextname already used.
	The specified context string was previously assigned to another topic.
	The Help Compiler ignores the latter string, and the topic has no identifier.
4031	Invalid context string contextname.
	The context string footnote contains non-alphanumeric characters or is empty.
	The Help Compiler does not assign the topic an identifier.
4056	Unresolved context string specified in CONTENTS option.
	The Contents topic defined in the Help project file could not be found.
	The Help Compiler uses the first topic in the build as the Contents.
4072	Context string exceeds limit of 255 characters.
	The context string hidden text cannot exceed 255 characters.
	The Help Compiler ignores the string.
4098	Context string(s) in [MAP] section not defined in any topic.
	The Help Compiler cannot find a context string listed in the [MAP] section in any of the topics in the build.
	The Help Compiler ignores the entry.
4113	Unresolved jump or pop-up contextname.
	The specified topic contains a context string that identifies a nonexistent topic.
	Check the topic for spelling errors in the context string, and also check to see if the requested topic is included in the build.
4131	Hash conflict between contextname and contextname.
	The hash algorithm has generated the same hash value for both of the listed context strings.
	Change either of the context strings and then recompile.
4151	Invalid secondary window name windowname.
	The window name for the secondary window is "main" or another disallowed member name.
4171	Cannot use secondary window with pop-up.
	The hidden text defining the pop-up identifier contains a secondary window name.
4196	Jumps and lookups not verified.
	Due to the low memory conditions, the build is continued without the jump and keyword validity verification.


  Footnote Errors

The following messages are caused by problems with footnotes in topic files.

Number	Error message
4211	Footnote text exceeds limit of 1023 characters.
	The footnote text cannot exceed the limit of 1023 characters.
	The Help Compiler ignores the footnote.
4231	Footnote text missing.
	The specified topic contains a footnote that has no characters.
4251	Browse sequence not in first paragraph.
	The browse-sequence footnote is not in the topic's first paragraph.
	The Help Compiler ignores the browse sequence.
4272	Empty browse sequence string.
	The browse-sequence footnote for the specified topic contains no sequence characters.
4292	Missing sequence number.
	A browse-sequence number ends in a colon (:) for the specified topic.
	Remove the colon, or enter a "minor" sequence number and then recompile.
4312	Browse sequence already defined.
	There is already a browse-sequence footnote for the specified topic.
	The Help Compiler ignores the latter sequence.


  Topic Title Errors

Number	Error message
4331	Title not in first paragraph.
	The title footnote ($) is not in the first paragraph of the topic.
	The topic will not have a topic title string.
4352	Empty title string.
	The title footnote for the specified topic contains no characters.
	The Help Compiler does not assign the topic a title.
4372	Title defined more than once.
	There is more than one title footnote in the specified topic.
	The Help Compiler uses the first title string.
4393	Title exceeds limit of 128 characters.
	The title for the specified topic exceeds the limit of 128 characters.
	The Help Compiler ignores the additional characters.


  Keyword Errors

Number	Error message
4412	Keyword string exceeds limit of 255 characters.
	The keyword string exceeds the maximum limit of 255 characters.
4433	Empty keyword string.
	There are no characters in the keyword footnote.
4452	Keyword(s) defined without title.
	The topic has a keyword assigned to it, but no title.
	The topic will appear as ">>Untitled Topic<<" in the history list and in the keyword search dialog.


  Build Tag Errors

Number	Error message
4471	Build tag footnote not at beginning of topic.
	The build tag footnote marker, if used, has to be the first character in the topic.
4492	Build tag exceeds limit of 32 characters.
	A build tag for the specified topic exceeds the maximum of 32 characters.
	The Help Compiler ignores the tag for the topic.


  Entry Macro Errors

Number	Error message
4551	Entry macro not in first paragraph.
	The ! footnote (for running a macro) is not in the first paragraph of the topic.
	The Help Compiler ignores the macro.


  Topic File Errors

The following messages result from problems in the use of Word for Windows formatting in one or more topic files.

Number	Error message
4616	File filename is not a valid RTF topic file.
	The specified file is not an RTF file.
	Check to make sure that you have saved the topic file as RTF from your word processor.
4639	Error in file filename at byte offset 0x%lX.
	The specified file contains unrecognized RTF at that byte offset.
	This message should not appear if you are using Microsoft Word for Windows, Microsoft Word for MS-DOS, or Microsoft Word for the Macintosh.
	Check the RTF syntax and then recompile. If you are using Microsoft Word for the Macintosh, transfer the file to the PC again, and then recompile.
4649	File filename contains more than 32767 topics.
	The maximum number of topics allowed in one RTF file is 32767.
4652	Table formatting too complex.
	The Help Compiler encountered a table with borders, shading, or right justification.
	Remove the unsupported formatting and then recompile.
4662	Side-by-side paragraph formatting not supported.
	The side-by-side paragraph formatting is not supported in WinHelp in Windows 3.1.
	The Help Compiler ignores the side-by-side text.
	If you are using WinHelp in Windows 3.1, use the table feature.
4671	Table contains more than 32 columns.
	The maximum number of columns in one table is 32. Some word processors may have different limits for the number of columns supported.
4680	Font fontname in file filename not in RTF font table.
	A font not defined in the RTF header has been entered into the topic.
	The Help Compiler uses the default system font.
4692	Unrecognized graphic format.
	The Help Compiler supports only Windows bitmaps and metafiles.
	The Help Compiler ignores the graphic.
	Make sure that you have not used Macintosh picture formats.
4733	Hidden page break.
	The page break was found as a part of the hidden text. A page break formatted as hidden text will not separate two topics.
4753	Hidden paragraph.
	A paragraph marker was found in the hidden text.
	The Help Compiler ignores the paragraph marker.
4763	Hidden carriage return.
	A carriage return was found in the hidden text.
	The Help Compiler ignores the carriage return.
4774	Paragraph exceeds limit of 64K.
	A single paragraph has more than 64K of text or 64K of graphics.
4792	Nonscrolling region defined after scrolling region.
	A paragraph that was authored as "keep with next" is not the first paragraph in the topic.
	The Help Compiler ignores the "keep with next" attribute, and the paragraph is treated as regular text and will be part of the regular topic text.
4813	Nonscrolling region crosses page boundary.
	The "keep with next" paragraph formatting crosses a page break boundary.
4000	UNKNOWN ERROR Contact Microsoft Product Support Services.


  Miscellaneous Errors

The following messages are caused by conditions such as MS-DOS file errors or out-of-memory conditions.

Number	Error message
5035	File filename not created.
	There are no topics to compile, or the build expression is False for all topics.
	The Help Compiler does not create a Help file.
5059	Not enough memory to build Help file.
	To free up memory, unload any unneeded applications, device drivers, and memory-resident programs.
5075	Help Compiler corrupted. Please reinstall HC31.EXE.
	The virus checking code has detected a corruption in the Help Compiler.
	Reinstall the Help Compiler from the original source disk.
5098	Using old key-phrase table.
	Maximum compression can only result by deleting the .PH file before each recompilation of the Help topics or by setting the OLDKEYPHRASE option to 0.
5115	Write failed.
	Write to disk failed.
	Contact Microsoft Product Support Services.
5000	UNKNOWN ERROR Contact Microsoft Product Support Services.


  Chapter 8  Programming Your Application for Help

Windows applications can offer help to their users by using the WinHelp function to start Windows Help and display topics in the application's help file. The WinHelp function gives a Windows application complete access to the help file, as well as to the menus and commands of Windows Help. Many applications use WinHelp to implement context-sensitive Help. Context-sensitive Help enables users to view topics about specific windows, menus, menu items, and control windows by selecting the item with the keyboard or the mouse. For example, a user can learn about the Open command on the File menu by selecting the command (using the direction keys) and pressing the F1 key.


  Choosing Help from the Help Menu

Every application should provide a Help menu to allow the user to open the help file with either the keyboard or the mouse. The Help menu should contain at least one Contents menu item that, when chosen, displays the contents or the main topic in the help file. To support the Help menu, the application's main window procedure should check for the Contents menu item and call the WinHelp function, as in the following example:

case WM_COMMAND:
    switch (wParam) {
    case IDM_HELP_CONTENTS:
        WinHelp(hwnd, "myhelp.hlp", HELP_CONTENTS, 0L);
        return 0L;
        .
        .
        .

    }
    break;

You can add other menu items to the Help menu for topics containing general information about the application. For example, if your help file contains a topic that describes how to use the keyboard, you can place a Keyboard menu item on the Help menu. To support additional menu items, your application must specify either the context string or the context identifier for the corresponding topic when it calls the WinHelp function. The following example uses a Help macro to specify the context string IDM_HELP_KEYBOARD for the Keyboard topic:

case IDM_HELP_KEYBOARD:
    WinHelp(hwnd, "myhelp.hlp", HELP_COMMAND,
            (LPSTR)"JumpID(\"myhelp.hlp\",\"IDM_HELP_KEYBOARD\")");
    return 0L;

A better way to display a topic is to use a context identifier. To do this, the help file must assign a unique number to the corresponding context string, in the [MAP] section of the project file. For example, the following section assigns the number 101 to the context string IDM_HELP_KEYBOARD:

[MAP]
IDM_HELP_KEYBOARD   101

An application can display the Keyboard topic by specifying the context identifier in the call to the WinHelp function, as in the following example:

#define IDM_HELP_KEYBOARD 101

WinHelp(hwnd, "myhelp.hlp", HELP_CONTEXT, (DWORD)IDM_HELP_KEYBOARD);

To make maintenance of an application easier, most programmers place their defined constants (such as IDM_HELP_KEYBOARD in the previous example) in a single header file. As long as the names of the defined constants in the header file are identical to the context strings in the help file, you can include the header file in the [MAP] section to assign context identifiers, as shown in the following example:

[MAP]
#include <myhelp.h>

If a help file contains two or more Contents topics, the application can assign one as the default by using the context identifier and the HELP_SETCONTENTS value in a call to the WinHelp function.


  Choosing Help with the Keyboard

An application can enable the user to choose a help topic with the keyboard by intercepting the F1 key. Intercepting this key lets the user select a menu, menu item, dialog box, message box, or control window and view Help for it with a single keystroke.

To intercept the F1 key, the application must install a message-filter procedure by using the SetWindowsHook function. This allows the application to examine all keystrokes for the application, regardless of which window has the input focus. If the filter procedure detects the F1 key, it posts a WM_F1DOWN message (application-defined) to the application's main window procedure. The procedure then determines which help topic to display.

The filter procedure should have the following form:

int FAR PASCAL FilterFunc(nCode, wParam, lParam)
int nCode;
WORD wParam;
DWORD lParam;
{
    LPMSG lpmsg = (LPMSG)lParam;

    if ((nCode == MSGF_DIALOGBOX || nCode == MSGF_MENU) &&
            lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_F1) {
        PostMessage(hWnd, WM_F1DOWN, nCode, 0L);
    }

    DefHookProc(nCode, wParam, lParam, &lpFilterFunc);

    return 0;
}

The application should install the filter procedure after creating the main window, as shown in the following example:

lpProcInstance = MakeProcInstance(FilterFunc, hInstance);
if (lpProcInstance == NULL)
    return FALSE;

lpFilterFunc = SetWindowsHook(WH_MSGFILTER, lpProcInstance);

Like all callback functions, the filter procedure must be exported by the application.

The filter procedure sends a WM_F1DOWN message only when the F1 key is pressed in a dialog box, message box, or menu. Many applications also display the Contents topic if no menu, dialog box, or message box is selected when the user presses the F1 key. In this case, the application should define the F1 key as an accelerator key that starts Help.

To create an accelerator key, the application's resource-definition file must define an accelerator table, as follows:

1 ACCELERATORS
BEGIN
    VK_F1, IDM_HELP_CONTENTS, VIRTKEY
END

To support the accelerator key, the application must load the accelerator table by using the LoadAccelerators function and translate the accelerator keys in the main message loop by using the TranslateAccelerator function.

In addition to installing the filter procedure, the application must keep track of which menu, menu item, dialog box, or message box is currently selected. In other words, when the user selects an item, the application must set a global variable indicating the current context. For dialog and message boxes, the application should set the global variable immediately before calling the DialogBox or MessageBox function. For menus and menu items, the application should set the variable whenever it receives a WM_MENUSELECT message. As long as identifiers for all menu items and controls in an application are unique, an application can use code similar to the following example to monitor menu selections:

case WM_MENUSELECT:
    /*
     * Set dwCurrentHelpId to the Help ID of the menu item that is
     * currently selected.
     */

    if (HIWORD(lParam) == 0)             /* no menu selected    */
        dwCurrentHelpId = ID_NONE;

    else if (lParam & MF_POPUP) {        /* pop-up selected     */
        if ((HMENU)wParam == hMenuFile)
            dwCurrentHelpId = ID_FILE;
        else if ((HMENU)wParam == hMenuEdit)
            dwCurrentHelpId = ID_EDIT;
        else if ((HMENU)wParam == hMenuHelp)
            dwCurrentHelpId = ID_HELP;
        else
            dwCurrentHelpId = ID_SYSTEM;
    }

    else                                 /* menu item selected */
        dwCurrentHelpId = wParam;

    break;

In this example, the hMenuFile, hMenuEdit, and hMenuHelp parameters must previously have been set to specify the corresponding menu handles. An application can use the GetMenu and GetSubMenu functions to retrieve these handles.

When the main window procedure finally receives a WM_F1DOWN message, it should use the current value of the global variable to display a help topic. The application can also provide Help for individual controls in a dialog box by determining which control has the focus at this point, as shown in the following example:

case WM_F1DOWN:
    /*
     * If there is a current Help context, display it.
     */

    if (dwCurrentHelpId != ID_NONE) {
        DWORD dwHelp = dwCurrentHelpId;

        /*
         * Check for context-sensitive Help for individual dialog
         * box controls.
         */

        if (wParam == MSGF_DIALOGBOX) {
            WORD wID = GetWindowWord(GetFocus(), GWW_ID);
            if (wID != IDOK && wID != IDCANCEL)
                dwHelp = (DWORD) wID;
        }

        WinHelp(hWnd, szHelpFileName, HELP_CONTEXT, dwHelp);

        /*
         * This call is used to remove the highlighting from the
         * System menu, if necessary.
         */

        DrawMenuBar(hWnd);
    }

    break;

When the application ends, it must remove the filter procedure by using the UnhookWindowsHook function and free the procedure instance for the function by using the FreeProcInstance function.


  Choosing Help with the Mouse

An application can enable the user to choose a help topic with the mouse by intercepting mouse input messages and calling the WinHelp function. To distinguish requests to view Help from regular mouse input, the user must press the SHIFT+F1 key combination. In such cases, the application sets a global variable when the user presses the key combination and changes the cursor shape to a question-mark pointer to indicate that the mouse can be used to choose a help topic.

To detect the SHIFT+F1 key combination, an application checks for the VK_F1 virtual-key value in each WM_KEYDOWN message sent to its main window procedure. It also checks for the VK_ESCAPE virtual-key code. The user presses the ESC key to quit Help and restore the mouse to its regular function. The following example checks for these keys:

case WM_KEYDOWN:
    if (wParam == VK_F1) {

        /* If Shift-F1, turn Help mode on and set Help cursor. */

        if (GetKeyState(VK_SHIFT)) {
            bHelp = TRUE;
            SetCursor(hHelpCursor);
            return DefWindowProc(hwnd, message, wParam, lParam);
        }

        /* If F1 without shift, call Help main index topic. */

        else {
            WinHelp(hwnd,"myhelp.hlp",HELP_CONTENTS,0L);
        }
    }

    else if (wParam == VK_ESCAPE && bHelp) {

        /* Escape during Help mode: turn Help mode off. */

        bHelp = FALSE;
        SetCursor((HCURSOR) GetClassWord(hWnd, GCW_HCURSOR));
    }

    break;

Until the user clicks the mouse or presses the ESC key, the application responds to WM_SETCURSOR messages by resetting the cursor to the arrow and question-mark combination.

case WM_SETCURSOR:
    /*
     * In Help mode, it is necessary to reset the cursor in response
     * to every WM_SETCURSOR message. Otherwise, by default, Windows
     * will reset the cursor to that of the window class.
     */

    if (bHelp) {
        SetCursor(hHelpCursor);
        break;
    }

    return (DefWindowProc(hwnd, message, wParam, lParam));

case WM_INITMENU:
    if (bHelp) {
        SetCursor(hHelpCursor);
    }

    return (TRUE);

If the user clicks the mouse button in a nonclient area of the application window while in Help mode, the application receives a WM_NCLBUTTONDOWN message. By examining the wParam value of this message, the application can determine which context identifier to pass to WinHelp.

case WM_NCLBUTTONDOWN:
    /*
     * If in Help mode (SHIFT+F1), display context-sensitive
     * Help for nonclient area.
     */

    if (bHelp) {
        dwHelpContextId =
            (wParam == HTCAPTION) ?(DWORD) HELPID_TITLE_BAR:
            (wParam == HTSIZE) ? (DWORD) HELPID_SIZE_BOX:
            (wParam == HTREDUCE) ? (DWORD) HELPID_MINIMIZE_ICON:
            (wParam == HTZOOM) ? (DWORD) HELPID_MAXIMIZE_ICON:
            (wParam == HTSYSMENU) ?(DWORD) HELPID_SYSTEM_MENU:
            (wParam == HTBOTTOM) ? (DWORD) HELPID_SIZING_BORDER:
            (wParam == HTBOTTOMLEFT) ? (DWORD) HELPID_SIZING_BORDER:
            (wParam == HTBOTTOMRIGHT) ?(DWORD) HELPID_SIZING_BORDER:
            (wParam == HTTOP) ?(DWORD) HELPID_SIZING_BORDER:
            (wParam == HTLEFT) ?(DWORD) HELPID_SIZING_BORDER:
            (wParam == HTRIGHT) ?(DWORD) HELPID_SIZING_BORDER:
            (wParam == HTTOPLEFT) ?(DWORD) HELPID_SIZING_BORDER:
            (wParam == HTTOPRIGHT) ? (DWORD) HELPID_SIZING_BORDER:
            (DWORD) 0L;

        if (!((BOOL) dwHelpContextId))
            return DefWindowProc(hwnd, message, wParam, lParam);
        bHelp = FALSE;
        WinHelp(hWnd, szHelpFileName, HELP_CONTEXT, dwHelpContextId);
        break;
    }

    return (DefWindowProc(hWnd, message, wParam, lParam));

If the user clicks a menu item while in Help mode, the application intercepts the WM_COMMAND message and sends the Help request:

case WM_COMMAND:

    /* In Help mode (Shift-F1)? */

    if (bHelp) {
        bHelp = FALSE;
        WinHelp(hWnd,szHelpFileName,HELP_CONTEXT, (DWORD)wParam);
        return NULL;
    }


  Searching for Help with Keywords

An application can enable the user to search for help topics based on full or partial keywords. This method is similar to employing the Search dialog box in Windows Help to find useful topics. The following example searches for the keyword "Keyboard" and displays the corresponding topic, if found:

WinHelp(hwnd, "myhelp.hlp", HELP_KEY, "Keyboard");

If the topic is not found, Windows Help displays an error message. If more than one topic has the same keyword, Windows Help displays only the first topic.

An application can give the user more options in a search by specifying partial keywords. When a partial keyword is given, Windows Help usually displays the Search dialog box to allow the user to continue the search or return to the application. However, if there is an exact match and no other topic exists with the given keyword, Windows Help displays the topic. The following example opens the Search dialog box and selects the first keyword in the list starting with the letters Ke:

WinHelp(hwnd, "myhelp.hlp", HELP_PARTIALKEY, "Ke");

When the HELP_KEY and HELP_PARTIALKEY values are specified in the WinHelp function, Windows Help searches the K keyword table. This table contains keywords generated by using the letter K with \footnote statements in the topic file. An application can search alternative keyword tables by specifying the HELP_MULTIKEY value in the WinHelp function. In this case, the application must specify the footnote character and the full keyword in a MULTIKEYHELP structure, as follows:

HGLOBAL hglblmkh;
MULTIKEYHELP FAR* mkh;
PSTR pszKeyword = "Frame";
UINT cb;

cb = sizeof(MULTIKEYHELP) + lstrlen(pszKeyword);

hglblmkh = GlobalAlloc(GHND, (DWORD) cb);
if (hglblmkh == NULL)
    break;
mkh = (MULTIKEYHELP FAR*) GlobalLock(hglblmkh);

mkh->mkSize    = cb;
mkh->mkKeylist = 'L';
lstrcpy(mkh->szKeyphrase, pszKeyword);

WinHelp(hwnd, "myhelp.hlp", HELP_MULTIKEY, (DWORD) mkh);

GlobalUnlock(hglblmkh);
GlobalFree(hglblmkh);

If the keyword is not found, Windows Help displays an error message. If more than one topic has the keyword, Windows Help displays only the first topic. (For a full description of the MULTIKEYHELP structure, see the Microsoft Programmer's Reference)

Applications cannot use alternative keyword tables unless the MULTIKEY option is specified in the [OPTIONS] section of the project file.


  Displaying Help in a Secondary Window

An application can display help topics in secondary windows instead of in the Windows Help main window. Secondary windows are useful whenever the user does not need the full capabilities of Windows Help. The Windows Help menus and buttons are not available in secondary windows.

To display Help in a secondary window, the application specifies the name of the secondary window along with the name of the help file. The following example displays the help topic having the context identifier IDM_FILE_SAVE in the secondary window named wnd_menu:

WinHelp(hwnd, "myhelp.hlp>wnd_menu", HELP_CONTEXT, IDM_FILE_SAVE);

The name and characteristics of the secondary window must be defined in the [WINDOWS] section of the project file, as in the following example:

[WINDOWS]
wnd_menu = "Menus", (128, 128, 256, 256), 0

Windows Help displays the secondary window with the initial size and position specified in the [WINDOWS] section. However, an application can set a new size and position by specifying the HELP_SETWINPOS value in the WinHelp function. In this case, the application sets the members in a HELPWININFO structure to specify the window size and position. The following examples sets the secondary window wnd_menu to a new size and position:

HANDLE hhwi;
LPHELPWININFO lphwi;
WORD wSize;
char *szWndName = "wnd_menu";

wSize = sizeof(HELPWININFO) + lstrlen(szWndName);
hhwi = GlobalAlloc(GHND, wSize);
lphwi = (LPHELPWININFO)GlobalLock(hhwi);

lphwi->wStructSize = wSize;
lphwi->x           = 256;
lphwi->y           = 256;
lphwi->dx          = 767;
lphwi->dy          = 512;
lphwi->wMax        = 0;
lstrcpy(lphwi->rgchMember, szWndName);

WinHelp(hwnd, "myhelp.hlp", HELP_SETWINPOS, lphwi);

GlobalUnlock(hhwi);
GlobalFree(hhwi);


  Canceling Help

Windows Help requires an application to explicitly cancel Help so that Windows Help can free any resources it used to keep track of the application and its help files. The application can do this at any time.

An application cancels Windows Help by calling the WinHelp function and specifying the HELP_QUIT value, as shown in the following example:

WinHelp(hwnd, "myhelp.hlp", HELP_QUIT, NULL);

If the application has made any calls to the WinHelp function, it must cancel Help before it closes its main window (for example, in response to the WM_DESTROY message in the main window procedure). An application needs to call WinHelp only once to cancel Help, no matter how many help files it has opened. Windows Help remains running until all applications or dynamic-link libraries that have called the WinHelp function have canceled Help.


iostream Introduction
iostream Class Library Reference

Introduction

Microsoft Visual C++ contains the C++ iostream class library, which supports object-oriented input and output. This library follows the syntax that the authors of the C++ language originally established and thus represents a de facto standard for C++ input and output.


Book Location
iostream Class Library Reference


  About This Book

»Chapter 1, iostream Programming,« provides information you need to get started using iostream classes. After reading this material, you will begin to understand how to write programs that process formatted text character streams and binary disk files and how to customize the library in limited ways. The chapter includes advanced information on how to derive iostream classes and create custom multiparameter "manipulators." These topics will get you started on extending the library and doing specialized formatting. You will also learn about the relationship between the iostream classes and their subsidiary buffer classes. You can then apply some of the iostream library design principles to your own class libraries.

»Chapter 2, Alphabetic Microsoft iostream Class Library Reference,« begins with a detailed class hierarchy diagram. The iostream class library reference follows, arranged by classes in alphabetic order. Each class description includes a summary of each member, arranged by category, followed by alphabetical listings of member functions (public and protected), overloaded operators, data members, and manipulators.

Public and protected class members are documented only when they are normally used in application programs or derived classes. See the class header files for a complete listing of class members.


  Document Conventions

This book uses the following document conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, register names, and terms used at the MS-DOS command level.
CObject, GetTime, TRACE, MF_STRING, CREATESTRUCT, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. Library routines include the classes and member functions of the Microsoft class libraries, macros, flags, data structures and their members and enumerators. Within syntax descriptions, bold type indicates that the text must be entered exactly as shown. Many functions and constants begin with either a single or a double underscore. These are part of the name and are mandatory.
expression	Words in italic indicate placeholders for information you must supply, such as a filename. Italic type is also occasionally used for emphasis in the text.
[ option ]	Items inside square brackets are optional.
#pragma pack { 1 | 2 }	Braces and a vertical bar indicate a choice among two or more items. You must choose one of the items unless square brackets ([ ]) surround the braces.
#include <io.h>,  myObject	Monospace font is used for example programs, user input, program output, and error messages in text. It is also used for names of user-derived classes and members.
CL [option...]    file...	Three dots (an ellipsis) following an item indicate that more items having the same form may appear.
while( ) {    .    .    . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
"C string"	Some C constructs, such as strings, require quotation marks. Quotation marks required by the language have the form " " and ' ' rather than " " and ' '.
"inheritance"	Quotation marks enclose a new term the first time it is defined in text.
American National Standards Institute (ANSI)	The first time an acronym is used, it is often spelled out.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  Chapter 1  iostream Programming

This chapter begins with a general description of the iostream classes and then describes output streams, input streams, and input/output streams. The end of the chapter provides information about advanced iostream programming.


  1.1  What Is a Stream?

Like C, C++ does not have built-in input/output capability. All C++ compilers, however, come bundled with a systematic, object-oriented I/O package, known as the iostream classes. The "stream" is the central concept of the iostream classes. You can think of a stream object as a "smart file" that acts as a source and destination for bytes. A stream's characteristics are determined by its class and by customized insertion and extraction operators.

Through device drivers, the disk operating system deals with the keyboard, screen, printer, and communication ports as extended files. The iostream classes interact with these extended files. Built-in classes support reading from and writing to memory with syntax identical to that for disk I/O, which makes it easy to derive stream classes.


  Input/Output Alternatives

This product provides several options for I/O programming:

•	C run-time library direct, unbuffered I/O

•	ANSI C run-time library stream I/O

•	Console and port direct I/O

•	The Microsoft Foundation Class Library

•	The Microsoft iostream Class Library

The iostream classes are useful for buffered, formatted text I/O. They are also useful for unbuffered or binary I/O if you need a C++ programming interface and decide not to use the Microsoft Foundation classes. The iostream classes are an object-oriented I/O alternative to the C run-time functions.

You can use iostream classes with the Microsoft® Windows (™)  operating system. String and file streams work without restrictions, but the character-mode stream objects cin, cout, cerr, and clog are inconsistent with the Windows graphical user interface. You can also derive custom stream classes that interact directly with the Windows environment. If you link with the QuickWin library, however, the cin, cout, cerr, and clog objects are assigned to special windows because they are connected to the predefined files stdin, stdout, and stderr.

You cannot use iostream classes in tiny-model programs because tiny-model programs cannot contain static objects such as cin and cout.


  The iostream Class Hierarchy

The class hierarchy diagram at the beginning of »Chapter 2« shows some relationships between iostream classes. Further "member" relationships exist between the ios and streambuf families. Use the diagram to locate base classes that provide inherited member functions for derived classes.


  1.2  Output Streams

An output stream object is a destination for bytes. The three most important output stream classes are ostream, ofstream, and ostrstream.

The ostream class, through the derived class ostream_withassign, supports the predefined stream objects:

•	cout    standard output

•	cerr    standard error with limited buffering

•	clog    similar to cerr but with full buffering

Objects are rarely constructed from ostream or (ostream_withassign); predefined objects are generally used. In some cases, you can reassign predefined objects after program startup. The ostream class, which can be configured for buffered or unbuffered operation, is best suited to sequential text-mode output. All functionality of the base class, ios, is included in ostream. If you construct an object of class ostream, you must specify a streambuf object to the constructor.

The ofstream class supports disk file output. If you need an output-only disk, construct an object of class ofstream. You can specify whether ofstream objects accept binary or text-mode data before or after opening the file. Many formatting options and member functions apply to ofstream objects, and all functionality of the base classes ios and ostream is included.

If you specify a filename in the constructor, that file is automatically opened when the object is constructed. Otherwise, you can use the open member function after invoking the default constructor, or you can construct an ofstream object based on an open file that is identified by a file descriptor.

Like the run-time function sprintf, the ostrstream class supports output to in-memory strings. To create a string in memory using I/O stream formatting, construct an object of class ostrstream. Because ostrstream objects are write-only, your program must access the resulting string through a pointer to char.


  Constructing Output Stream Objects

If you use only the predefined cout, cerr, or clog objects, you don't need to construct an output stream. If you use file or string streams, you must use constructors.


  Output File Stream Constructors

To construct an output file stream, you have three choices:

•	Use the default constructor, then call the open member function.

ofstream myFile; // Static or on the stack
myFile.open( "filename", iosmode );

ofstream* pmyFile = new ofstream; // On the heap
pmyFile->open( "filename", iosmode );

•	Specify a filename and mode flags in the constructor call.

ofstream myFile( "filename", iosmode );

•	Specify an integer file descriptor for a file already open for output. You can specify unbuffered output or a pointer to your own buffer.

int fd = _open( "filename", dosmode );
ofstream myFile1( fd );  // Buffered mode (default)
ofstream myFile2( fd, NULL, 0 );  // Unbuffered mode ofstream
myFile3( fd, pch, buflen);  // User-supplied buffer


  Output String Stream Constructors

To construct an output string stream, you can use one of two ostrstream constructors. One dynamically allocates its own storage, and the other requires the address and size of a preallocated buffer.

•	The dynamic constructor is used like this:

char* sp;
ostrstream myString << "this is a test" << ends;
sp = myString.str();  // Get a pointer to the string

The ends "manipulator" adds the necessary terminating null character to the string.

•	The constructor that requires the preallocated buffer is used like this:

char s[32];
ostrstream myString( s, sizeof( s ) );
myString << "this is a test" << ends; // Text stored in s


  Using Insertion Operators and Controlling Format

This section shows how to control format and how to create insertion operators for your own classes. The insertion (<<) operator, which is preprogrammed for all standard C++ data types, sends bytes to an output stream object. Insertion operators work with predefined "manipulators," which are elements that change the default format of integer arguments.


  Output Width

To align output, you specify the output width for each item by placing the setw manipulator in the stream or by calling the width member function. This example right aligns the values in a column at least 10 characters wide:

#include <iostream.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   for( int i = 0; i < 4; i++ )
   {
      cout.width(10);
      cout << values[i] << '\n';
   }
}

The output looks like this:

      1.23
     35.36
     653.7
   4358.24

Leading blanks are added to any value less than 10 characters wide.

To pad a field, use the fill member function, which sets the value of the padding character for fields that have a specified width. The default is a blank. To pad the column of numbers with asterisks, modify the previous for loop as follows:

for( int i = 0; i < 4; i++ )
{
   cout.width( 10 );
   cout.fill( '*' );
   cout << values[i] << endl
}

The endl manipulator replaces the newline character ('\n'). The output looks like this:

******1.23
*****35.36
*****653.7
***4358.24

To specify widths for data elements in the same line, use the setw manipulator:

#include <iostream.h>
#include <iomanip.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
   for( int i = 0; i < 4; i++ )
      cout << setw( 6 )  << names[i]
           << setw( 10 ) << values[i] << endl;
}

The width member function is declared in IOSTREAM.H. If you use setw or any other manipulator with arguments, you must include IOMANIP.H. In the output, strings are printed in a field of width 6 and integers in a field of width 10:

 Zoot       1.23
Jimmy      35.36
   Al      653.7
 Stan    4358.24

Neither setw nor width truncates values. If formatted output exceeds the width, the entire value prints, subject to the stream's precision setting. Both setw and width affect the following field only. Field width reverts to its default behavior (the necessary width) after one field has been printed. However, the other stream format options remain in effect until changed.


  Alignment

Output streams default to right-aligned text. To left align the names in the previous example and right align the numbers, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) << values[i] << endl;

The output looks like this:

Zoot        1.23
Jimmy      35.36
Al         653.7
Stan     4358.24

The left-align flag is set by using the setiosflags manipulator with the ios::left enumerator. This enumerator is defined in the ios class, so its reference must include the ios:: prefix. The resetiosflags manipulator turns off the left-align flag. Unlike width and setw, the effect of setiosflags and resetiosflags is permanent.


  Precision

The default value for floating-point precision is six. For example, the number 3466.9768 prints as 3466.98. To change the way this value prints, use the setprecision manipulator. The manipulator has two flags, ios::fixed and ios::scientific. If ios::fixed is set, the number prints as 3466.976800. If ios::scientific is set, it prints as 3.4669773+003.

To display the floating-point numbers in the previous »Alignment« section with one significant digit, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )
        << names[i]
        << resetiosflags( ios::left )
        << setw( 10 )
        << setprecision( 1 )
        << values[i]
        << endl;

The program prints this list:

Zoot          1
Jimmy     4e+001
Al        7e+002
Stan      4e+003

To eliminate scientific notation, insert this statement before the for loop:

cout << setiosflags( ios::fixed );

With fixed notation, the program prints with one digit after the decimal point.

Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2

If you change the ios::fixed flag to ios::scientific, the program prints this:

Zoot    1.2e+000
Jimmy   3.5e+001
Al      6.5e+002
Stan    4.4e+003

Again, the program prints one digit after the decimal point. If either ios::fixed or ios::scientific is set, the precision value determines the number of digits after the decimal point. If neither flag is set, the precision value determines the total number of significant digits. The resetiosflags manipulator clears these flags.


  Radix

The dec, oct, and hex manipulators set the default radix for input and output. If you insert the hex manipulator into the output stream, for example, the object correctly translates the internal data representation of integers into a hexadecimal output format. The numbers are displayed with digits a through f in lowercase if the ios::uppercase flag is clear (the default); otherwise, they are displayed in uppercase. The default radix is dec (decimal).


  Output File Stream Member Functions

Output stream member functions have three types: those that are equivalent to manipulators, those that perform unformatted write operations, and those that otherwise modify the stream state and have no equivalent manipulator or insertion operator. For sequential, formatted output, you might use only insertion operators and manipulators. For random-access binary disk output, you would use other member functions, with or without insertion operators.


  The open Function

To use an output file stream (ofstream), you must associate that stream with a specific disk file in the constructor or the open function. If you use the open function, you can reuse the same stream object with a series of files. In either case, the arguments describing the file are the same.

When you open the file associated with an output stream, you generally specify an open_mode flag. These flags, which are defined as enumerators in the ios class, can be combined with the bitwise OR ( | ) operator.

Flag	Function
ios::app	Opens an output file for appending.
ios::ate	Opens an existing file (either input or output) and seeks the end.
ios::in	Opens an input file. Use ios::in as an open_mode for an ofstream file to prevent truncating an existing file.
ios::out	Opens an output file. When you use ios::out for an ofstream object without ios::app, ios::ate, or ios::in, ios::trunc is implied.
ios::nocreate	Opens a file only if it already exists; otherwise the operation fails.
ios::noreplace	Opens a file only if it does not exist; otherwise the operation fails.
ios::trunc	Opens a file and deletes the old file (if it already exists).
ios::binary	Opens a file in binary mode (default is text mode).
Three common output stream situations involve mode options:

•	Creating a file. If the file already exists, the old version is deleted.

ostream ofile( "FILENAME" );  // Default is ios::out
ofstream ofile( "FILENAME", ios::out ); // Equivalent to above

•	Appending records to an existing file or creating one if it does not exist.

ofstream ofile( "FILENAME", ios::app );

•	Opening two files, one at a time, on the same stream.

ofstream ofile();
ofile.open( "FILE1", ios::in );
// Do some output
ofile.close(); // FILE1 closed
ofile.open( "FILE2", ios::in );
// Do some more output
ofile.close(); // FILE2 closed
// When ofile goes out of scope it is destroyed.


  The put Function

The put function writes one character to the output stream. The following two statements are the same by default, but the second is affected by the stream's format arguments:

cout.put( 'A' ); // Exactly one character written
cout << 'A'; // Format arguments 'width' and 'fill' apply


  The write Function

The write function writes a block of memory to an output file stream. The length argument specifies the number of bytes written. This example creates an output file stream and writes the binary value of the Date structure to it:

#include <fstream.h>

struct Date
{
   int mo, da, yr;
};

void main()
{
   Date dt = { 6, 10, 92 };
   ofstream tfile( "date.dat" , ios::binary );
   tfile.write( (char *) &dt, sizeof dt );
}

The write function does not stop writing when it reaches a null character, so the complete class structure is written. The function takes two arguments: a char pointer and a count of characters to write. Note the required cast to char* before the address of the structure object.


  The seekp and tellp Functions

An output file stream keeps an internal pointer that points to the position where data is to be written next. The seekp member function sets this pointer and thus provides random-access disk file output. The tellp member function returns the file position. For examples that use the input stream equivalants to seekp and tellp, see »The seekg and tellg Functions«.


  The close Function

The close member function closes the disk file associated with an output file stream. The file must be closed to complete all disk output. If necessary, the ofstream destructor closes the file for you, but you can use the close function if you need to open another file for the same stream object.

The output stream destructor automatically closes a stream's file only if the constructor or the open member function opened the file. If you pass the constructor a file descriptor for an already-open file or use the attach member function, you must close the file explicitly.


  Error Processing Functions

Use these member functions to test for errors while writing to a stream:

Function	Return value
bad	Returns TRUE if there is an unrecoverable error.
fail	Returns TRUE if there is an unrecoverable error or an "expected" condition, such as a conversion error or the file is not found. Processing can often resume after a call to clear with a zero argument.
good	Returns TRUE if there is no error condition (unrecoverable or otherwise) and the end-of-file flag is not set.
eof	Returns TRUE on the end-of-file condition.
clear	Sets the internal error state. If called with the default arguments, it clears all error bits.
rdstate	Returns the current error state. For a complete description of error bits, see the Class Library Reference.
The ! operator is overloaded to perform the same function as the fail function. Thus the expression

if( !cout)...

is equivalent to

if( cout.fail() )...

The void*() operator is overloaded to be the opposite of the ! operator; thus the expression

if( cout)...

is equal to

if( !cout.fail() )...

The void*() operator is not equivalent to good because it doesn't test for the end of file.


  The Effects of Buffering

The following example shows the effects of buffering. You might expect the program to print please wait, wait 5 seconds, and then proceed. It won't necessarily work this way, however, because the output is buffered.

#include <iostream.h>
#include <time.h>

void main()
{
   time_t tm = time( NULL ) + 5;
   cout << "Please wait...";
   while ( time( NULL ) < tm )
      ;
   cout << "\nAll done" << endl;
}

To make the program work logically, the cout object must empty itself when the message is to appear. To flush an ostream object, send it the flush manipulator:

cout << "Please wait..." << flush;

This step flushes the buffer, ensuring the message prints before the wait. You can also use the endl manipulator, which flushes the buffer and outputs a carriage return−linefeed, or you can use the cin object. This object (with the cerr or clog objects) is usually tied to the cout object. Thus, any use of cin (or of the cerr or clog objects) flushes the cout object.


  Binary Output Files

Streams were originally designed for text, so the default output mode is text. In text mode, the newline character (hexadecimal 10) expands to a carriage return−linefeed (16-bit only). The expansion can cause problems, as shown here:

#include <fstream.h>
int iarray[2] = { 99, 10 };
void main()
{
    ofstream os( "test.dat" );
    os.write( (char *) iarray, sizeof( iarray ) );
}

You might expect this program to output the byte sequence { 99, 0, 10, 0 }; instead, it outputs { 99, 0, 13, 10, 0 }, which causes problems for a program expecting binary input. If you need true binary output, in which characters are written untranslated, then you have several choices:

•	Construct a stream as usual, then use the setmode member function, which changes the mode after the file is opened:

ofstream ofs ( "test.dat" );
ofs.setmode( filebuf::binary );
ofs.write( char*iarray, 4 ); // Exactly 4 bytes written

•	Specify binary output by using the ofstream constuctor mode argument:

#include <fstream.h>
#include <fcntl.h>
#include <io.h>
int iarray[2] = { 99, 10 };
void main()
{
    ofstream os( "test.dat", ios::binary );
    ofs.write( iarray, 4 ); // Exactly 4 bytes written
}

•	Use the binary manipulator instead of the setmode member function:

ofs << binary;

Use the text manipulator to switch the stream to text translation mode.

•	Open the file using the run-time _open function with a binary mode flag:

filedesc fd = _open( "test.dat",
              _O_BINARY | _O_CREAT | _O_WRONLY );
ofstream ofs( fd );
ofs.write( ( char* ) iarray, 4 ); // Exactly 4 bytes written


  Overloading the << Operator for Your Own Classes

Output streams use the insertion (<<) operator for standard types. You can also overload the << operator for your own classes.

The write function example showed the use of  a Date structure. A date is an ideal candidate for a C++ class in which the data members (month, day, and year) are hidden from view. An output stream is the logical destination for displaying such a structure. This code displays a date using the cout object:

Date dt( 1, 2, 92 );
cout << dt;

To get cout to accept a Date object after the insertion operator, overload the insertion operator to recognize an ostream object on the left and a Date on the right. The overloaded << operator function must then be declared as a friend of class Date so it can access the private data within a Date object.

#include <iostream.h>

class Date
{
   int mo, da, yr;
public:
   Date( int m, int d, int y )
   {
      mo = m; da = d; yr = y;
   }
   friend ostream& operator<< ( ostream& os, Date& dt );
};

ostream& operator<< ( ostream& os, Date& dt )
{
   os << dt.mo << '/' << dt.da << '/' << dt.yr;
   return os;
}

void main()
{
   Date dt( 5, 6, 92 );
   cout << dt;
}

When you run this program, it prints the date:

5/6/92

The overloaded operator returns a reference to the original ostream object, which means you can combine insertions:

cout << "The date is" << dt << flush;


  Writing Your Own Manipulators Without Arguments

Writing manipulators that don't use arguments requires neither class derivation nor use of complex macros. Suppose your printer requires the pair <ESC>[ to enter bold mode. You can insert this pair directly into the stream:

cout << "regular " << '\033' << '[' << "boldface" << endl;

Or you can define the bold manipulator, which inserts the characters:

ostream& bold( ostream& os ) {
    return os << '\033' << '[';
}
cout << "regular " << bold << "boldface" << endl;

The globally defined bold function takes an ostream reference argument and returns the ostream reference. It is not a member function or a friend because it doesn't need access to any private class elements. The bold function connects to the stream because the stream's << operator is overloaded to accept that type of function, using a declaration that looks something like this:

ostream& ostream::operator<< ( ostream& (*_f)( ostream& ) ); {
    (*_f)( *this );
    return *this;
}

You can use this feature to extend other overloaded operators. In this case, it is incidental that bold inserts characters into the stream. The function is called when it is inserted into the stream, not necessarily when the adjacent characters are printed. Thus, printing could be delayed because of the stream's buffering.


  1.3  Input Streams

An input stream object is a source of bytes. The three most important input stream classes are istream, ifstream, and istrstream.

The istream class is best used for sequential text-mode input. You can configure objects of class istream for buffered or unbuffered operation. All functionality of the base class, ios, is included in istream. You will rarely construct objects from class istream. Instead, the predefined cin object (actually an object of class istream_withassign) is generally used. In some cases, you can assign cin to other stream objects after program startup.

The ifstream class supports disk file input. If you need an input-only disk file, construct an object of class ifstream. You can specify binary or text-mode data. If you specify a filename in the constructor, the file is automatically opened when the object is constructed. Otherwise, you can use the open function after invoking the default constructor. Many formatting options and member functions apply to ifstream objects. All functionality of the base classes ios and istream is included in ifstream.

Like the library function sscanf, the istrstream class supports input from in-memory strings. To extract data from a character array that has a null terminator, allocate and initialize the string, then construct an object of class istrstream.


  Constructing Input Stream Objects

If you use only the cin object, you don't need to construct an input stream; however, if you use file streams or string streams, you must do so.


  Input File Stream Constructors

To create an input file stream, you have three choices:

•	Use the void-argument constructor, then call the open member function:

ifstream myFile; // On the stack
myFile.open( "filename", iosmode );

ifstream* pmyFile = new ifstream; // On the heap
pmyFile->open( "filename", iosmode );

•	Specify a filename and mode flags in the constructor invocation, thereby opening the file during the construction process:

ifstream myFile( "filename", iosmode );

•	Specify an integer file descriptor for a file already open for input. In this case you can specify unbuffered input or a pointer to your own buffer:

int fd = _open( "filename", dosmode );
ifstream myFile1( fd );  // Buffered mode (default)
ifstream myFile2( fd, NULL, 0 );  // Unbuffered mode
ifstream myFile3( fd, pch, buflen );  // User-supplied buffer


  Input String Stream Constructors

Input string stream constructors require the address of preallocated, preinitialized storage:

char s[] = "123.45";
double amt;
istrstream myString( s );
myString >> amt; // Amt should contain 123.45


  Using Extraction Operators

The extraction operator (>>), which is preprogrammed for all standard C++ data types, is the easiest way to get bytes from an input stream object.

Formatted text input extraction operators depend on white space to separate incoming data values. This is inconvenient when a text field contains multiple words or when commas separate numbers. One method in such a case is to use the unformatted input member function getline to read a block of text with white space included, then parse the block with special functions. Another method is to derive an input stream class with a member function such as GetNextToken, which can call istream members to extract and format character data.


  Testing for Extraction Errors

Output error processing functions, discussed in »Error Processing Functions« apply to input streams. Testing for errors during extraction is important. Consider this statement:

cin >> n;

If n is a signed integer, a value greater than 32,767 (the maximum allowed value, or MAX_INT) sets the stream's fail bit, and the cin object becomes unusable. All subsequent extractions result in an immediate return with no value stored.


  Input Stream Manipulators

Many manipulators, such as setprecision, are defined for the ios class and thus apply to input streams. Few manipulators, however, actually affect input stream objects. The most important are the radix manipulators, dec, oct, and hex, which determine the conversion base used with numbers from the input stream.

On extraction, the hex manipulator enables processing of various input formats. For example, c, C, 0xc, 0xC, 0Xc, and 0XC are all interpreted as the decimal integer 12. Any character other than 0 through 9, A through F, a through f, x, and X terminates the numeric conversion. Thus the sequence "124n5" is converted to the number 124 with the ios::fail bit set.


  Input Stream Member Functions

Input stream member functions are used for disk input.


  The open Function

If you are using an input file stream (ifstream), you must associate that stream with a specific disk file. You can do this in the constructor, or you can use the open function. In either case, the arguments are the same.

You generally specify an open_mode flag when you open the file associated with an input stream (the default mode is ios::in). For a list of the open_mode flags, see »The open Function«. The flags can be combined with the bitwise OR ( | ) operator.

To read a file, first use the fail member function to determine whether it exists:

istream ifile( "FILENAME", ios::nocreate );
if ( ifile.fail() )
// The file does not exist ...


  The get Function

The unformatted get member function works like the >> operator with two exceptions. First, the get function includes white-space characters, whereas the extractor excludes white space when the ios::skipws flag is set (the default). Second, the get function is less likely to cause a tied output stream (cout, for example) to be flushed.

A variation of the get function specifies a buffer address and the maximum number of characters to read. This is useful for limiting the number of characters sent to a specific variable, as this example shows:

#include <iostream.h>

void main()
{
   char line[25];
   cout << " Type a line terminated by carriage return\n>";
   cin.get( line, 25 );
   cout << ' ' << line;
}

In this example, you can type up to 24 characters and a terminating character. Any remaining characters can be extracted later.


  The getline Function

The getline member function works similarly to the get function. Both functions allow a third argument that specifies the terminating character for input. The default value is the newline character. Both functions reserve one character for the required terminating character. However, get leaves the terminating character in the stream and getline removes the terminating character.

The following example specifies a terminating character for the input stream:

#include <iostream.h>

void main()
{
   char line[100];
   cout << " Type a line terminated by 't'" << endl;
   cin.getline( line, 100, 't' );
   cout << line;
}


  The read Function

The read member function reads bytes from a file to a specified area of memory. The length argument determines the number of bytes read. If you do not include that argument, reading stops when the physical end of file is reached or, in the case of a text-mode file, when an embedded EOF character is read.

This example reads a binary record from a payroll file into a structure:

#include <fstream.h>
#include <fcntl.h>
#include <io.h>

void main()
{
   struct
   {
      double salary;
      char name[23];
   } employee;

   ifstream is( "payroll", ios::binary | ios::nocreate );
   if( is ) {  // ios::operator void*()
      is.read( (char *) &employee, sizeof( employee ) );
      cout << employee.name << ' ' << employee.salary << endl;
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

The program assumes that the data records are formatted exactly as specified by the structure with no terminating carriage-return or linefeed characters.


  The seekg and tellg Functions

Input file streams keep an internal pointer to the position in the file where data is to be read next. You set this pointer with the seekg function, as shown here:

#include <fstream.h>

void main()
{
   char ch;

   ifstream tfile( "payroll", ios::binary | ios::nocreate );
   if( tfile ) {
      tfile.seekg( 8 );      // Seek 8 bytes in (past salary)
      while ( tfile.good() ) { // EOF or failure stops the reading
         tfile.get( ch );
         if( !ch ) break; // quit on null
         cout << ch;
      }
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

To use seekg to implement record-oriented data management systems, multiply the fixed-length record size by the record number to obtain the byte position relative to the end of the file, then use the get object to read the record.

The tellg member function returns the current file position for reading. This value is of type streampos, a typedef defined in IOSTREAM.H. The following example reads a file and displays messages showing the positions of spaces.

#include <fstream.h>

void main()
{
   char ch;
ifstream tfile( "payroll", ios::binary | ios::nocreate );
   if( tfile ) {
       while ( tfile.good() ) {
          streampos here = tfile.tellg();
          tfile.get( ch );
          if ( ch == ' ' )
             cout << "\nPosition " << here << " is a space";
       }
   }

   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}


  The close Function

The close member function closes the disk file associated with an input file stream and frees the operating system file handle. The ifstream destructor closes the file for you (unless you called the attach function or passed your own file descriptor to the constructor), but you can use the close function if you need to open another file for the same stream object.


  Overloading the >> Operator for Your Own Classes

Input streams use the extraction (>>) operator for the standard types. You can write similar extraction operators for your own types; your success depends on using white space precisely.

Here is an example of an extraction operator for the Date class presented earlier:

istream& operator>> ( istream& is, Date& dt )
{
   is >> dt.mo >> dt.da >> dt.yr;
   return is;
}


  1.4  Input/Output Streams

An iostream object is a source and/or a destination for bytes. The two most important I/O stream classes, both derived from iostream, are fstream and strstream. These classes inherit the functionality of the istream and ostream classes described earlier.

The fstream class supports disk file input and output. If you need to read from and write to a particular disk file in the same program, construct an fstream object. An fstream object is a single stream with two logical substreams, one for input and one for output. Although the underlying buffer contains separately designated positions for reading and writing, those positions are tied together.

The strstream class supports input and output of in-memory strings.


  1.5  Custom Manipulators with Arguments

This section describes how to create output stream manipulators with one or more arguments, and how to use manipulators for non-output streams.


  Output Stream Manipulators with One Argument (int or long)

The iostream class library provides a set of macros for creating parameterized manipulators. Manipulators with a single int or long argument are a special case.  To create an output stream manipulator that accepts a single int or long argument (like setw), you must use the OMANIP macro, which is defined in IOMANIP.H. This example defines a fillblank manipulator that inserts a specified number of blanks into the stream:

#include <iostream.h>
#include <iomanip.h>

ostream& fb( ostream& os, int l )
{
   for( int i=0; i < l; i++ )
        os << ' ';
   return os;
}

OMANIP(int) fillblank( int l )
{
   return OMANIP(int) ( fb, l );
}

void main()
{
    cout << "10 blanks follow" << fillblank( 10 ) << ".\n";
}

The IOMANIP.H header file contains a macro that expands OMANIP(int) into a class, __OMANIP_int, which includes a constructor and an overloaded ostream insertion operator for an object of the class. In the previous example, the fillblank function calls the __OMANIP_int constructor to return an object of class __OMANIP_int. Thus, fillblank can be used with an ostream insertion operator. The constructor calls the fb function.

The OMANIP macro represents an advanced use of C++. It will be superseded once C++ accommodates parameterized types. In the meantime, it is easier to adapt the previous code than to analyze the syntax. The expression OMANIP(long) expands to another built-in class, __OMANIP_long, which accommodates functions with a long integer argument.


  Other One-Argument Output Stream Manipulators

To create manipulators that take arguments other than int and long, you must use the IOMANIPdeclare macro, which declares the classes for your new type, as well as the OMANIP macro.

The following example uses a class money, which is a long type. The setpic manipulator attaches a formatting "picture" string to the class that can be used by the overloaded stream insertion operator of the class money. The picture string is stored as a static variable in the money class rather than as data member of a stream class, so you do not have to derive a new output stream class.

#include <iostream.h>
#include <iomanip.h>
#include <string.h>

typedef char* charp;
IOMANIPdeclare( charp );

class money {
private:
    long value;
    static char *szCurrentPic;
public:
    money( long val ) { value = val; }
    friend ostream& operator << ( ostream& os, money m ) {
        // A more complete function would merge the picture
        // with the value rather than simply appending it
        os << m.value << '[' << money::szCurrentPic << ']';
        return os;
    }
    friend ostream& setpic( ostream& os, char* szPic ) {
        money::szCurrentPic = new char[strlen( szPic ) + 1];
        strcpy( money::szCurrentPic, szPic );
        return os;
    }
};
char *money::szCurrentPic;  // Static pointer to picture

OMANIP(charp) setpic(charp c)
{
    return OMANIP(charp) (setpic, c);
}

void main()
{
    money amt = 35235.22;
    cout << setiosflags( ios::fixed );
    cout << setpic( "###,###,###.##" ) << "amount = " << amt << endl;
}


  Output Stream Manipulators with More Than One Argument

The following example shows how to write a manipulator, fill, to insert a specific number of a particular character. The manipulator, which takes two arguments, is similar to setpic in the previous example. The difference is that the character pointer type declaration is replaced by a structure declaration.

#include <iostream.h>
#include <iomanip.h>

struct fillpair {
 char ch;
        int  cch;
};

IOMANIPdeclare( fillpair );

ostream& fp( ostream& os, fillpair pair )
{
    for ( int c = 0; c < pair.cch; c++ ) {
        os << pair.ch;
    }
    return os;
}

OMANIP(fillpair) fill( char ch, int cch )
{
    fillpair pair;

    pair.cch = cch;
    pair.ch  = ch;
    return OMANIP (fillpair)( fp, pair );
}

void main()
{
    cout << "10 dots coming" << fill( '.', 10 ) << "done" << endl;
}

This example can be rewritten so that the manipulator definition is in a separate program file. In this case, the header file must contain these declarations:

struct fillpair {
       char ch;
       int  cch;
};
IOMANIPdeclare( fillpair );
ostream& fp( ostream& o, fillpair pair );
OMANIP(fillpair) fill( char ch, int cch );


  Custom Manipulators for Input and Input/Output Streams

The OMANIP macro works with ostream and its derived classes. The SMANIP, IMANIP, and IOMANIP macros work with the classes ios, istream, and iostream, respectively.


  Using Manipulators with Derived Stream Classes

Suppose you define a manipulator, xstream, that works with the ostream class. The manipulator will work with all classes derived from ostream. Further suppose you need manipulators that work only with xstream. In this case, you must add an overloaded insertion operator that is not a member of ostream:

xstream& operator<< ( xstream& xs, xstream& (*_f)( xstream& ) ) {
    (*_f)( xs );
    return xs;
}

The manipulator code looks like this:

xstream& bold( xstream& xs ) {
    return xs << '\033' << '[';
}

If the manipulator needs to access xstream protected data member functions, you can declare the bold function as a friend of the xstream class.


  1.6  Deriving Your Own Stream Classes

Like any C++ class, a stream class can be derived to add new member functions, data members, or manipulators. If you need an input file stream that tokenizes its input data, for example, you can derive from the ifstream class. This derived class can include a member function that returns the next token by calling its base class's public member functions or extractors. You may need new data members to hold the stream object's state between operations, but you probably won't need to use the base class's protected member functions or data members.

For the straightforward stream class deriviation, you need only write the necessary constructors and the new member functions.


  The streambuf Class

Unless you plan to make major changes to the iostream library, you do not need to work much with the streambuf class, which does most of the work for the other stream classes. In most cases, you will create a modified output stream by deriving only a new streambuf class and connecting it to the ostream class.


  Why Derive a Custom streambuf Class?

Existing output streams communicate to the file system and to in-memory strings. You can create streams that address a memory-mapped video screen, a window as defined by Microsoft Windows, a new physical device, and so on. A simpler method is to alter the byte stream as it goes to a file system device.


  A streambuf Derivation Example

The following example modifies the cout object to print in two-column landscape (horizontal) mode on a printer that uses the PCL control language (for example, Hewlett-Packard LaserJet printer). As the test driver program shows, all member functions and manipulators that work with the original cout object work with the special version. The application programming interface is the same.

The example is divided into three source files:

•	HSTREAM.H—the LaserJet class declaration that must be included in the implementation file and application file

•	HSTREAM.CPP—the LaserJet class implementation that must be linked with the application

•	EXIOS204.CPP—the test driver program that sends output to a LaserJet printer

HSTREAM.H contains only the class declaration for hstreambuf, which is derived from the filebuf class and overrides the appropriate filebuf virtual functions.

// hstream.h - HP LaserJet output stream header
#include <fstream.h> // Accesses filebuf class
#include <string.h>
#include <stdio.h> // for sprintf

class hstreambuf : public filebuf
{
public:
    hstreambuf( int filed );
    virtual int sync();
    virtual int overflow( int ch );
    ~hstreambuf();
private:
    int column, line, page;
    char* buffer;
    void convert( long cnt );
    void newline( char*& pd, int& jj );
    void heading( char*& pd, int& jj );
    void pstring( char* ph, char*& pd, int& jj );
};
ostream& und( ostream& os );
ostream& reg( ostream& os );

HSTREAM.CPP contains the hstreambuf class implementation.

// hstream.cpp  - HP LaserJet output stream
#include "hstream.h"

const int REG  = 0x01;   // Regular font code
const int UND  = 0x02;   // Underline font code
const int CR   = 0x0d;   // Carriage return character
const int NL   = 0x0a;   // Newline character
const int FF   = 0x0c;   // Formfeed character
const int TAB  = 0x09;   // Tab character
const int LPP  = 57;     // Lines per page
const int TABW = 5;      // Tab width

// Prolog defines printer initialization (font, orientation, etc.
char prolog[] =
{ 0x1B, 0x45,                         // Reset printer
  0x1B, 0x28, 0x31, 0x30, 0x55,	// IBM PC char set
  0x1B, 0x26, 0x6C, 0x31, 0x4F,	// Landscape
  0x1B, 0x26, 0x6C, 0x38, 0x44,       // 8 lines per inch
  0x1B, 0x26, 0x6B, 0x32, 0x53};	     // Lineprinter font

// Epilog prints the final page and terminates the output
char epilog[] = { 0x0C, 0x1B, 0x45 };   // Formfeed, reset

char uon[] = { 0x1B, 0x26, 0x64, 0x44, 0 }; // Underline on
char uoff[] = { 0x1B, 0x26, 0x64, 0x40, 0 };// Underline off

hstreambuf::hstreambuf( int filed ) : filebuf( filed )
{
    column = line = page = 0;
    int size = sizeof( prolog );
    setp( prolog, prolog + size );
    pbump( size );   // Puts the prolog in the put area
    filebuf::sync(); // Sends the prolog to the output file
    buffer = new char[1024]; // Allocates destination buffer
}

hstreambuf::~hstreambuf()
{
    sync(); // Makes sure the current buffer is empty
    delete buffer; // Frees the memory
    int size = sizeof( epilog );
    setp( epilog, epilog + size );
    pbump( size );   // Puts the epilog in the put area
    filebuf::sync(); // Sends the epilog to the output file
}
virtual int hstreambuf::sync()
{
    long count = out_waiting();
if ( count ) {
convert( count );
}
return filebuf::sync();
}

virtual int hstreambuf::overflow( int ch )
{
    long count = out_waiting();
if ( count ) {
convert( count );
}
return filebuf::overflow( ch );
}
// The following code is specific to the HP LaserJet printer

// Converts a buffer to HP, then writes it
void hstreambuf::convert( long cnt )
{
    char *bufs, *bufd; // Source, destination pointers
    int j = 0;

    bufs = pbase();
    bufd = buffer;
    if( page == 0 ) {
        newline( bufd, j );
    }
    for( int i = 0; i < cnt; i++ ) {
        char c = *( bufs++ );  // Gets character from source buffer
        if( c >= ' ' ) {       // Character is printable
            * ( bufd++ ) = c;
            j++;
            column++;
        }

else if( c == NL ) {            // Moves down one line
            *( bufd++ ) = c;    // Passes character through
            j++;
            line++;
            newline( bufd, j ); // Checks for page break, etc.
        }
        else if( c == FF ) {    // Ejects paper on formfeed
            line = line - line % LPP + LPP;
            newline( bufd, j ); // Checks for page break, etc.
        }
        else if( c == TAB ) {   // Expands tabs
            do {
                *( bufd++ ) = ' ';
                j++;
                column++;
            } while ( column % TABW );
        }
        else if( c == UND ) { // Responds to und manipulator
            pstring( uon, bufd, j );
        }
        else if( c == REG ) { // Responds to reg manipulator
            pstring( uoff, bufd, j );
        }
    }
    setp( buffer, buffer + 1024 ); // Sets new put area
    pbump( j ); // Tells number of characters in the dest buffer
}

// simple manipulators - apply to all ostream classes
ostream& und( ostream& os ) // Turns on underscore mode
{
    os << (char) UND; return os;
}

ostream& reg( ostream& os ) // Turns off underscore mode
{
    os << (char) REG; return os;
}

void hstreambuf::newline( char*& pd, int& jj ) {
// Called for each newline character
column = 0;
if ( ( line % ( LPP*2 ) ) == 0 ) { // Even page
page++;
pstring( "\033&a+0L", pd, jj );  // Set left margin to zero
heading( pd, jj );	             // Print heading
pstring( "\033*p0x77Y", pd, jj );// Cursor to (0,77) dots
}
if ( ( ( line % LPP ) == 0 ) && ( line % ( LPP*2 ) ) != 0 ) {
//  Odd page; prepare to move to right column
page++;
pstring( "\033*p0x77Y", pd, jj ); // Cursor to (0,77) dots
pstring( "\033&a+88L", pd, jj );  // Left margin to col 88
}
}

void hstreambuf::heading( char*& pd, int& jj ) // Prints heading
{
char hdg[20];
int i;

if( page > 1 ) {
*( pd++ ) = FF;
jj++;
}
pstring( "\033*p0x0Y", pd, jj ); // Top of page
pstring( uon, pd, jj );          // Underline on
sprintf( hdg, "Page %-3d", page );
pstring( hdg, pd, jj );
for( i=0; i < 80; i++ ) {        // Pads with blanks
*( pd++ ) = ' ';
jj++;
}
sprintf( hdg, "Page %-3d", page+1 ) ;
pstring( hdg, pd, jj );
for( i=0; i < 80; i++ ) {        // Pads with blanks
*( pd++ ) = ' ';
jj++;
}
pstring( uoff, pd, jj ); // Underline off
}
// Outputs a string to the buffer
void hstreambuf::pstring( char* ph, char*& pd, int& jj )
{
    int len = strlen( ph );
    strncpy( pd, ph, len );
    pd += len;
    jj += len;
}

EXIOS204.CPP reads text lines from the cin object and writes them to the modified cout object.

// exios204.cpp
// hstream Driver program copies cin to cout until end of file
#include "hstream.h"

hstreambuf hsb( 1 ); // 1=stdout

void main()
{
    char line[200];
    cout = &hsb; // Associates the HP LaserJet streambuf to cout
    while( 1 ) {
       cin.getline( line, 200 );
       if( !cin.good() ) break;
       cout << line << endl;
    }
}

Here are the main points in the code above:

•	The new class hstreambuf is derived from filebuf, which is the buffer class for disk file I/O. The filebuf class does the actual writing to disk in response to commands from its associated ostream class. The hstreambuf constructor takes an argument that corresponds to the operating system file number, in this case 1, for stdout. This constructor is invoked by this line:

hstreambuf hsb( 1 );

•	The ostream_withassign assignment operator associates the hstreambuf object with the cout object:

ostream& operator =( streambuf* sbp );

This statement in EXIOS204.CPP executes the assignment:

cout = &hsb;

•	The hstreambuf constructor prints the prolog that sets up the laser printer, then allocates a temporary print buffer.

•	The destructor outputs the epilog text and frees the print buffer when the object goes out of scope, which happens after the exit from main.

•	The streambuf virtual overflow and sync functions do the low-level output. The hstreambuf class overrides these functions to gain control of the byte stream. The functions call the private convert member function.

•	The convert function processes the characters in the hstreambuf buffer and stores them in the object's temporary buffer. The filebuf functions process the temporary buffer.

•	The details of convert relate more to the PCL language than to the iostream library. Private data members keep track of column, line, and page numbers.

•	The und and reg manipulators control the underscore print attribute by inserting codes 0x02 and 0x03 into the stream. The convert function later translates these codes into printer-specific sequences.

•	The program can be extended easily to embellish the heading, add more formatting features, and so forth.

•	In a more general program, the hstreambuf class could be derived from the streambuf class rather than the filebuf class. The filebuf derivation shown gets the most leverage from existing iostream library code, but it makes assumptions about the implementation of filebuf, particularly the overflow and sync functions. Thus you cannot necessarily expect this example to work with other derived streambuf classes or with filebuf classes provided by other software publishers.


  Chapter 2  Alphabetic Microsoft iostream Class Library Reference

iostream Class Hierarchy Diagram

»iostream class hierarchy diagram«


  iostream Class List

Abstract Stream Base Class

ios	Stream base class.
Input Stream Classes

istream	General-purpose input stream class and base class for other input streams.
ifstream	Input file stream class.
istream_withassign	Input stream class for cin.
istrstream	Input string stream class.
Output Stream Classes

ostream	General-purpose output stream class and base class for other output streams.
ofstream	Output file stream class.
ostream_withassign	Output stream class for cout, cerr, and clog.
ostrstream	Output string stream class.
Input/Output Stream Classes

iostream	General-purpose input/output stream class and base class for other input/output streams.
fstream	Input/output file stream class.
strstream	Input/output string stream class.
stdiostream	Input/output class for standard I/O files.
Stream Buffer Classes

streambuf	Abstract stream buffer base class.
filebuf	Stream buffer class for disk files.
strstreambuf	Stream buffer class for strings.
stdiobuf	Stream buffer class for standard I/O files.
Predefined Stream Initializer Class

Iostream_init	Predefined stream initializer class.


  class filebuf : public streambuf

The filebuf class is a derived class of streambuf that is specialized for buffered disk file I/O. The buffering is managed entirely within the Microsoft iostream Class Library. filebuf member functions call the run-time low-level I/O routines (the functions declared in IO.H) such as _sopen, _read, and _write.

The file stream classes, ofstream, ifstream, and fstream, use filebuf member functions to fetch and store characters. Some of these member functions are virtual functions of the streambuf class.

The reserve area, put area, and get area are introduced in the streambuf class description. The put area and the get area are always the same for filebuf objects. Also, the get pointer and put pointers are tied; when one moves, so does the other.

#include <fstream.h>

See Also

»ifstream«, »ofstream«, »streambuf«, »strstreambuf«, »stdiobuf«

Construction/Destruction — Public Members

filebuf	Constructs a filebuf object.
~filebuf	Destroys a filebuf object.
Operations — Public Members

open	Opens a file and attaches it to the filebuf object.
close	Flushes any waiting output and closes the attached file.
setmode	Sets the file's mode to binary or text.
attach	Attaches the filebuf object to an open file.
Status/Information — Public Members

fd	Returns the stream's file descriptor.
is_open	Tests whether the file is open.


  filebuf::attach

filebuf* attach( filedesc fd );

fd    A file descriptor as returned by a call to the run-time function _open or _sopen. filedesc is a typedef equivalent to int.

Remarks

Attaches this filebuf object to the open file specified by fd.

Return Value

The function returns NULL when the stream is already attached to a file; otherwise it returns the address of the filebuf object.


  filebuf::close

filebuf* close();

Remarks

This function flushes any waiting output, closes the file, and disconnects the file from the filebuf object. If an error occurs, the function returns NULL and leaves the filebuf object in a closed state. If there is no error, the function returns the address of the filebuf object and clears its error state.

See Also

»filebuf::open«


  filebuf::fd

filedesc fd() const;

Remarks

Returns the file descriptor associated with the filebuf object; filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system. The function returns EOF if the object is not attached to a file.

See Also

»filebuf::attach«


  filebuf::filebuf

filebuf();

filebuf( filedesc fd );

filebuf( filedesc fd, char* pr, int nLength );

fd    A file descriptor as returned by a call to the run-time function _sopen. filedesc is a typedef equivalent to int.

pr    Pointer to a previously allocated reserve area of length nLength.

nLength    The length (in bytes) of the reserve area.

Remarks

The three filebuf constructors are described as follows:

Constructor	Description
filebuf()	Constructs a filebuf object without attaching it to a file.
filebuf( filedesc )	Constructs a filebuf object and attaches it to an open file.
filebuf( filedesc, char*, int )	Constructs a filebuf object, attaches it to an open file, and initializes it to use a specified reserve area.


  filebuf::~filebuf

~filebuf();

Remarks

Closes the attached file only if that file was opened by the open member function.


  filebuf::is_open

int is_open() const;

Remarks

Returns a nonzero value if this filebuf object is attached to an open disk file identified by a file descriptor; otherwise 0.

See Also

»filebuf::open«


  filebuf::open

filebuf* open( const char* szName, int nMode, int nProt = filebuf::openprot );

szName    The name of the file to be opened during construction.

nMode    An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ofstream constructor for a list of the enumerators.

nProt    The file protection specification; defaults to the static integer filebuf::openprot, which is equivalent to the operating system default (filebuf::sh_compat for MS-DOS). Here are the possible values of nProt, with meanings as given:

•	filebuf::sh_compat    Compatibility share mode (MS-DOS only).

•	filebuf::sh_none    Exclusive mode — no sharing.

•	filebuf::sh_read    Read sharing allowed.

•	filebuf::sh_write    Write sharing allowed.

You can combine the filebuf::sh_read and filebuf::sh_write modes with the logical OR ( || ) operator.

Remarks

Opens a disk file and attaches it with this filebuf object. If the file is already open, or if there is an error while opening the file, the function returns NULL; otherwise it returns the filebuf address.

See Also

»filebuf::is_open«, »filebuf::close«, »filebuf::~filebuf«


  filebuf::setmode

int setmode( int nMode = filebuf::text );

nMode    An integer that must be one of the static filebuf constants. The nMode parameter must have one of the following values, with meanings as given:

•	filebuf::text    Text mode (newline characters translated to and from carriage return-linefeed pairs under MS-DOS).

•	filebuf::binary    Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream's filebuf object.

Return Value

The previous mode if there is no error; otherwise 0.

See Also

»ios binary manipulator«, »ios text manipulator«


  class fstream : public iostream

The fstream class is an iostream derivative specialized for combined disk file input and output. Its constructors automatically create and attach a filebuf buffer object.

The filebuf class documentation describes the get and put areas and their associated pointers. Although the filebuf object's get and put pointers are theoretically independent, the get area and the put area are not active at the same time. When the stream's mode changes from input to output, the get area is emptied and the put area is reinitialized. When the mode changes from output to input, the put area is flushed and the get area is reinitialized. Thus, either the get pointer or the put pointer is null at all times.

#include <fstream.h>

See Also

»ifstream«, »ofstream«, »strstream«, »stdiostream«, »filebuf«

Construction/Destruction — Public Members

fstream	Constructs an fstream object.
~fstream	Destroys an fstream object.
Operations — Public Members

open	Opens a file and attaches it to the filebuf object and thus to the stream.
close	Flushes any waiting output and closes the stream's file.
setbuf	Attaches the specified reserve area to the stream's filebuf object.
setmode	Sets the stream's mode to binary or text.
attach	Attaches the stream (through the filebuf object) to an open file.
Status/Information — Public Members

rdbuf	Gets the stream's filebuf object.
fd	Returns the file descriptor associated with the stream.
is_open	Tests whether the stream's file is open.


  fstream::attach

void attach( filedesc fd );

fd    A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

Attaches this stream to the open file specified by fd. The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream's error state.

See Also

»filebuf::attach«, »fstream::fd«


  fstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, flushes any waiting output, closes the file, and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream's error state is cleared unless the call to filebuf::close fails.

See Also

»filebuf::close«, »fstream::open«, »fstream::is_open«


  fstream::fd

filedesc fd() const;

Remarks

Returns the file descriptor associated with the stream. filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

See Also

»filebuf::fd«, »fstream::attach«


  fstream::fstream

fstream();

fstream( const char* szName, int nMode, int nProt = filebuf::openprot );

fstream( filedesc fd );

fstream( filedesc fd, char* pch, int nLength );

szName    The name of the file to be opened during construction.

nMode    An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values, with the meaning as given:

•	ios::app    The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream::seekp function.

•	ios::ate    The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position.

•	ios::in    The file is opened for input. The original file (if it exists) will not be truncated.

•	ios::out    The file is opened for output.

•	ios::trunc    If the file already exists, its contents are discarded. This mode is implied if ios::out is specified and ios::ate, ios::app, and ios:in are not specified.

•	ios::nocreate    If the file does not already exist, the function fails.

•	ios::noreplace    If the file already exists, the function fails.

•	ios::binary    Opens the file in binary mode (the default is text mode).

Note that there is no ios::in or ios::out default mode for fstream objects. You must specify both modes if your fstream object must both read and write files.

nProt    The file protection specification; defaults to the static integer filebuf::openprot, which is equivalent to the operating system default, filebuf::sh_compat, under MS-DOS. The possible nProt values are as follows, with meanings as given:

•	filebuf::sh_compat    Compatibility share mode (MS-DOS only).

•	filebuf::sh_none    Exclusive mode — no sharing.

•	filebuf::sh_read    Read sharing allowed.

•	filebuf::sh_write    Write sharing allowed.

The filebuf::sh_read and filebuf::sh_write modes can be combined with the logical OR ( || ) operator.

fd    A file descriptor as returned by a call to the run-time function _open or _sopen. filedesc is a typedef equivalent to int.

pch    Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength    The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four fstream constructors are described as follows, with meanings as given:

•	fstream()    Constructs an fstream object without opening a file.

•	fstream( const char*, int, int )    Contructs an fstream object, opening the specified file.

•	fstream( filedesc )    Constructs an fstream object that is attached to an open file.

•	fstream( filedesc, char*, int )    Constructs an fstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.

All fstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area. The user-allocated area is not automatically released during destruction.


  fstream::~fstream

~fstream();

Remarks

Flushes the buffer, then destroys an fstream object, along with its associated filebuf object. The file is closed only if it was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


  fstream::is_open

int is_open() const;

Remarks

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

See Also

»filebuf::is_open«, »fstream::open«, »fstream::close«


  fstream::open

void open( const char* szName, int nMode, int nProt = filebuf::openprot );

szName    The name of the file to be opened during construction.

nMode    An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the fstream constructor for a list of the enumerators. There is no default; a valid mode must be specified.

nProt    The file protection specification; defaults to the static integer filebuf::openprot. See the fstream constructor for a list of the other allowed values.

Remarks

Opens a disk file and attaches it to the stream's filebuf object. If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, then the ios::failbit is set only if the ios::nocreate mode was used.

See Also

»filebuf::open«, »fstream::fstream«, »fstream::close«, »fstream::is_open«


  fstream::rdbuf

filebuf* rdbuf() const;

Remarks

Returns a pointer to the filebuf buffer object that is associated with this stream. (Note that this is not the character buffer; the filebuf object contains a pointer to the character area.)


  fstream::setbuf

streambuf* setbuf( char* pch, int nLength );

pch    A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength    The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

Attaches the specified reserve area to the stream's filebuf object. If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf cast as a streambuf. The reserve area will not be released by the destructor.


  fstream::setmode

int setmode( int nMode = filebuf::text );

nMode    An integer that must be one of the static filebuf constants, with values and meanings as follows:

•	filebuf::text    Text mode (newline characters translated to and from carriage-return − linefeed pairs).

•	filebuf::binary    Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream's filebuf object. It can be called only after the file is opened.

Return Value

The previous mode; −1 if the parameter is invalid, the file is not open, or the mode cannot be changed.

See Also

»ios binary manipulator« , »ios text manipulator«


  class ifstream : public istream

The ifstream class is an istream derivative specialized for disk file input. Its constructors automatically create and attach a filebuf buffer object.

The filebuf class documentation describes the get and put areas and their associated pointers. Only the get area and the get pointer are active for the ifstream class.

#include <fstream.h>

See Also

»filebuf«, »streambuf«, »ofstream«, »fstream«

Construction/Destruction — Public Members

ifstream	Constructs an ifstream object.
~ifstream	Destroys an ifstream object.
Operations — Public Members

open	Opens a file and attaches it to the filebuf object and thus to the stream.
close	Closes the stream's file.
setbuf	Associates the specified reserve area to the stream's filebuf object.
setmode	Sets the stream's mode to binary or text.
attach	Attaches the stream (through the filebuf object) to an open file.
Status/Information — Public Members

rdbuf	Gets the stream's filebuf object.
fd	Returns the file descriptor associated with the stream.
is_open	Tests whether the stream's file is open.


  ifstream::attach

void attach( filedesc fd );

fd    A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

Attaches this stream to the open file specified by fd. The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream's error state.

See Also

»filebuf::attach«, »ifstream::fd«


  ifstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, closes the file and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream's error state is cleared unless the call to filebuf::close fails.

See Also

»filebuf::close«, »ifstream::open«, »ifstream::is_open«


  ifstream::fd

filedesc fd() const;

Remarks

Returns the file descriptor associated with the stream; filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

See Also

»filebuf::fd«, »ifstream::attach«


  ifstream::ifstream

ifstream();

ifstream( const char* szName, int nMode = ios::in, int nProt = filebuf::openprot );

ifstream( filedesc fd );

ifstream( filedesc fd, char* pch, int nLength );

szName    The name of the file to be opened during construction.

nMode    An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values, with the meanings as given:

•	ios::in    The file is opened for input (default).

•	ios::nocreate    If the file does not already exist, the function fails.

•	ios::binary    Opens the file in binary mode (the default is text mode).

Note that the ios::nocreate flag is necessary if you intend to test for the file's existence (the usual case).

nProt    The file protection specification; defaults to the static integer filebuf::openprot that is equivalent to filebuf::sh_compat. The possible nProt values are as follows, with meanings as given:

•	filebuf::sh_compat    Compatibility share mode.

•	filebuf::sh_none    Exclusive mode — no sharing.

•	filebuf::sh_read    Read sharing allowed.

•	filebuf::sh_write    Write sharing allowed.

The filebuf::sh_read and filebuf::sh_write modes can be combined with the logical OR ( || ) operator.

fd    A file descriptor as returned by a call to the run-time function  _open or _sopen; filedesc is a typedef equivalent to int.

pch    Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength    The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four ifstream constructors are described as follows:

•	ifstream()    Constructs an ifstream object without opening a file.

•	ifstream( const char*, int, int )    Contructs an ifstream object, opening the specified file.

•	ifstream( filedesc )    Constructs an ifstream object that is attached to an open file.

•	ifstream( filedesc, char*, int )    Constructs an ifstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.

All ifstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area.


  ifstream::~ifstream

~ifstream();

Remarks

Destroys an ifstream object along with its associated filebuf object. The file is closed only if it was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


  ifstream::is_open

int is_open() const;

Remarks

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

See Also

»filebuf::is_open«, »ifstream::open«, »ifstream::close«


  ifstream::open

void open( const char* szName, int nMode = ios::in, int nProt = filebuf::openprot );

szName    The name of the file to be opened during construction.

nMode    An integer containing bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ifstream constructor for a list of the enumerators. The ios::in mode is implied.

nProt    The file protection specification; defaults to the static integer filebuf::openprot. See the ifstream constructor for a list of the other allowed values.

Remarks

Opens a disk file and attaches it to the stream's filebuf object. If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, then the ios::failbit is set only if the ios::nocreate mode was used.

See Also

»filebuf::open«, »ifstream::ifstream«, »ifstream::close«, »ifstream::is_open«


  ifstream::rdbuf

filebuf* rdbuf() const;

Remarks

Returns a pointer to the filebuf buffer object that is associated with this stream. (Note that this is not the character buffer; the filebuf object contains a pointer to the character area.)


  ifstream::setbuf

streambuf* setbuf( char* pch, int nLength );

pch    A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength    The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

Attaches the specified reserve area to the stream's filebuf object. If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf, which is cast as a streambuf. The reserve area will not be released by the destructor.


  ifstream::setmode

int setmode( int nMode = filebuf::text );

nMode    An integer that must be one of the static filebuf constants, with values and meanings as follows:

•	filebuf::text    Text mode (newline characters translated to and from carriage return−linefeed pairs).

•	filebuf::binary    Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream's filebuf object. It may be called only after the file is opened.

Return Value

The previous mode; −1 if the parameter is invalid, the file is not open, or the mode cannnot be changed.

See Also

»ios binary manipulator«, »ios text manipulator«


  class ios

As the iostream class hierarchy diagram shows, the ios class is the base class for all the input/output stream classes. While ios is not technically an abstract base class, you will not usually construct ios objects, nor will you derive classes directly from ios. Instead, you will use the derived classes istream and ostream or other derived classes.

Even though you will not use ios directly, you will be using many of the inherited member functions and data members described here. Remember that these inherited member function descriptions are not duplicated for derived classes.

#include <iostream.h>

See Also

»istream«, »ostream«

Data Members (static) — Public Members

basefield	Mask for obtaining the conversion base flags (dec, oct, or hex).
adjustfield	Mask for obtaining the field padding flags (left, right, or internal).
floatfield	Mask for obtaining the numeric format (scientific or fixed).
Construction/Destruction — Public Members

ios	Constructor for use in derived classes.
~ios	Virtual destructor.
Flag and Format Access Functions — Public Members

flags	Sets or reads the stream's format flags.
setf	Manipulates the stream's format flags.
unsetf	Clears the stream's format flags.
fill	Sets or reads the stream's fill character.
precision	Sets or reads the stream's floating-point format display precision.
width	Sets or reads the stream's output field width.
Status-Testing Functions — Public Members

good	Indicates good stream status.
bad	Indicates a serious I/O error.
eof	Indicates end of file.
fail	Indicates a serious I/O error or a possibly recoverable I/O formatting error.
rdstate	Returns the stream's error flags.
clear	Sets or clears the stream's error flags.
User-Defined Format Flags — Public Members

bitalloc	Provides a mask for an unused format bit in the stream's private flags variable (static function).
xalloc	Provides an index to an unused word in an array reserved for special-purpose stream state variables (static function).
iword	Converts the index provided by xalloc to a reference (valid only until the next xalloc).
pword	Converts the index provided by xalloc to a pointer (valid only until the next xalloc).
Other Functions — Public Members

delbuf	Controls the connection of streambuf deletion with ios destruction.
rdbuf	Gets the stream's streambuf object.
sync_with_stdio	Synchronizes the predefined objects cin, cout, cerr, and clog with the standard I/O system.
tie	Ties a specified ostream to this stream.
Operators — Public Members

operator void*()	Converts a stream to a pointer that can be used only for error checking.
operator !()	Returns a nonzero value if a stream I/O error has occurred.
ios Manipulators

dec	Causes the interpretation of subsequent fields in decimal format (the default mode).
hex	Causes the interpretation of subsequent fields in hexadecimal format.
oct	Causes the interpretation of subsequent fields in octal format.
binary	Sets the stream's mode to binary (stream must have an associated filebuf buffer).
text	Sets the stream's mode to text — the default mode (stream must have an associated filebuf buffer).
Parameterized Manipulators

(#include <iomanip.h> required)

setiosflags	Sets the stream's format flags.
resetiosflags	Resets the stream's format flags.
setfill	Sets the stream's fill character.
setprecision	Sets the stream's floating-point display precision.
setw	Sets the stream's field width (for the next field only).


  ios::bad

int bad() const;

Remarks

Returns a nonzero value to indicate a serious I/O error. This condition corresponds to the badbit error state being set. Do not continue I/O operations on the stream in this situation.

See Also

»ios::good«, »ios::fail«, »ios::rdstate«


   ios::bitalloc

static long bitalloc();

Remarks

The ios class currently defines 15 format flag bits accessible through flags and other member functions. These bits reside in a 32-bit private ios data member and are accessed through enumerators such as ios::left and ios::hex.

The bitalloc member function provides a mask for a previously unused bit in the data member. Once you obtain the mask, you can use it to set or test the corresponding custom flag bit in conjunction with the ios member functions and manipulators listed under "See Also."

See Also

»ios::flags«, »ios::setf«, »ios::unsetf«, »ios setiosflags manipulator«, »ios resetiosflags manipulator«


  ios::clear

void clear( int nState = 0 );

nState    If 0, all error bits are cleared; otherwise bits are set according to the following masks (ios enumerators) that can be combined using the bitwise OR ( | ) operator. The nState parameter must have one of the following values, with the meanings as given:

•	ios::goodbit    No error condition (no bits set).

•	ios::eofbit    End of file reached.

•	ios::failbit    A possibly recoverable formatting or conversion error.

•	ios::badbit    A severe I/O error.

Remarks

Sets or clears the error-state flags. The rdstate function can be used to read the current error state.

See Also

»ios::rdstate«, »ios::good«, »ios::bad«, »ios::eof«


  ios::delbuf

void delbuf( int nDelFlag );

int delbuf() const;

nDelFlag    A nonzero value indicates that ~ios should delete the stream's attached streambuf object. A 0 value prevents deletion.

Remarks

The first overloaded delbuf function assigns a value to the stream's buffer-deletion flag.

The second function returns the current value of the flag.

This function is public only because it is accessed by the Iostream_init class. Treat it as protected.

See Also

»ios::rdbuf«, »ios::~ios«


  ios::eof

int eof() const;

Remarks

Returns a nonzero value if end of file has been reached. This condition corresponds to the eofbit error flag being set.


  ios::fail

int fail() const;

Remarks

Returns a nonzero value if any I/O error (not end of file) has occurred. This condition corresponds to either the badbit or failbit error flag being set. If a call to bad returns 0, you can assume that the error condition is nonfatal and that you can probably continue processing after you clear the flags.

See Also

»ios::bad«, »ios::clear«


  ios::fill

char fill( char cFill );

char fill() const;

cFill    The new fill character to be used as padding between fields.

Remarks

The first overloaded function sets the stream's internal fill character variable to cFill and returns the previous value. The default fill character is a space.

The second fill function returns the stream's fill character.

See Also

»ios setfill manipulator«


  ios::flags

long flags( long lFlags );

long flags() const;

lFlags    The new format flag values for the stream. The values are specified by the following bit masks (ios enumerators) that can be combined using the bitwise OR ( | ) operator. The lFlags parameter must have one of the following values, with the meanings as given:

•	ios::skipws    Skip white space on input.

•	ios::left    Left-align values; pad on the right with the fill character.

•	ios::right    Right-align values; pad on the left with the fill character (default alignment).

•	ios::internal    Add fill characters after any leading sign or base indication, but before the value.

•	ios::dec    Format numeric values as base 10 (decimal) (default radix).

•	ios::oct    Format numeric values as base 8 (octal).

•	ios::hex    Format numeric values as base 16 (hexadecimal).

•	ios::showbase    Display numeric constants in a format that can be read by the C++ compiler.

•	ios::showpoint    Show decimal point and trailing zeros for floating-point values.

•	ios::uppercase    Display uppercase A through F for hexadecimal values and E for scientific values.

•	ios::showpos    Show plus signs (+) for positive values.

•	ios::scientific    Display floating-point numbers in scientific format.

•	ios::fixed    Display floating-point numbers in fixed format.

•	ios::unitbuf    Cause ostream::osfx to flush the stream after each insertion. By default, cerr is unit buffered.

•	ios::stdio    Cause ostream::osfx to flush stdout and stderr after each insertion.

Remarks

The first overloaded flags function sets the stream's internal flags variable to lFlags and returns the previous value.

The second function returns the stream's current flags.

See Also

»ios::setf«, »ios::unsetf«, »ios setiosflags manipulator«, »ios resetiosflags manipulator«, »ios::adjustfield«, »ios::basefield«, »ios::floatfield«


  ios::good

int good() const;

Remarks

Returns a nonzero value if all error bits are clear. Note that the good member function is not simply the inverse of the bad function.

See Also

»ios::bad«, »ios::fail«, »ios::rdstate«


  ios::init

Protected

void init( streambuf* psb );

psb    A pointer to an existing streambuf object.

Remarks

Associates an object of a streambuf-derived class with this stream and, if necessary, deletes a dynamically created stream buffer object that was previously associated. The init function is useful in derived classes in conjunction with the protected default istream, ostream, and iostream constructors. An ios-derived class constructor can thus construct and attach its own predetermined stream buffer object.

See Also

»istream::istream«, »ostream::ostream«, »iostream::iostream«


  ios::ios

ios( streambuf* psb );

psb    A pointer to an existing streambuf object.

Remarks

Constructor for ios. You will seldom need to invoke this constructor except in derived classes. Generally, you will be deriving classes not from ios but from istream, ostream, and iostream.


  ios::~ios

virtual ~ios();

Remarks

Virtual destructor for ios.


  ios::iword

long& iword( int nIndex ) const;

nIndex    An index into a table of words that are associated with the ios object.

Remarks

The xalloc member function provides the index into the table of special-purpose words. The pword function converts that index to a reference to a 32-bit word.

See Also

»ios::xalloc«, »ios::pword«


  ios::precision

int precision( int np );

int precision() const;

np    An integer that indicates the number of significant digits or significant decimal digits to be used for floating-point display.

Remarks

The first overloxaded precision function sets the stream's internal floating-point precision variable to np and returns the previous value. The default precision is six digits. If the display format is scientific or fixed, then the precision indicates the number of digits after the decimal point. If the format is automatic (neither floating point nor fixed), then the precision indicates the total number of significant digits.

The second function returns the stream's current precision value.

See Also

»ios setprecision manipulator«


  ios::pword

void*& pword( int nIndex ) const;

nIndex    An index into a table of words that are associated with the ios object.

Remarks

The xalloc member function provides the index into the table of special-purpose words. The pword function converts that index to a reference to a pointer to a 32-bit word.

See Also

»ios::xalloc«, »ios::iword«


  ios::rdbuf

streambuf* rdbuf() const;

Remarks

Returns a pointer to the streambuf object that is associated with this stream. The rdbuf function is useful when you need to call streambuf member functions.


ios::rdstate

int rdstate() const;

Remarks

Returns the current error state as specified by the following masks (ios enumerators):

•	ios::goodbit    No error condition.

•	ios::eofbit    End of file reached.

•	ios::failbit    A possibly recoverable formatting or conversion error.

•	ios::badbit    A severe I/O error or unknown state.

The returned value can be tested against a mask with the AND (&) operator.

See Also

»ios::clear«


  ios::setf

long setf( long lFlags );

long setf( long lFlags, long lMask );

lFlags    Format flag bit values. See the »flags« member function for a list of format flags. These flags can be combined by using the bitwise OR ( | ) operator.

lMask    Format flag bit mask.

Remarks

The first overloaded setf function turns on only those format bits that are specified by 1s in lFlags.  It returns a long that contains the previous value of all the flags.

The second function alters those format bits specified by 1s in lMask. The new values of those format bits are determined by the corresponding bits in lFlags. It returns a long that contains the previous value of all the flags.

See Also

»ios::flags«, »ios::unsetf«, »ios setiosflags manipulator«


  ios::sync_with_stdio

static void sync_with_stdio();

Remarks

Synchronizes the C++ streams with the standard I/O system. The first time this function is called, it resets the predefined streams (cin, cout, cerr, clog) to use a stdiobuf object rather than a filebuf object. After that, I/O using these streams can be freely mixed with I/O using stdin, stdout, and stderr. Some performance decrease will result because there is buffering both in the stream class and in the standard I/O file system.

After the call to sync_with_stdio, the ios::stdio bit is set for all affected predefined stream objects, and cout is set to unit buffered mode.


  ios::tie

ostream* tie( ostream* pos );

ostream* tie() const;

pos    A pointer to an ostream object.

Remarks

The first overloaded tie function ties this stream to the specified ostream and returns the value of the previous tie pointer (NULL if this stream was not previously tied). A stream tie enables automatic flushing of the ostream in response to (1) a need for more characters or (2) the presence of characters to be consumed.

By default, cin is initially tied to cout so that attempts to get more characters from standard input may result in flushing standard output. In addition, cerr and clog are tied to cout by default.

The second function returns the value of the previous tie pointer (NULL if this stream was not previously tied).


  ios::unsetf

long unsetf( long lFlags );

lFlags    Format flag bit values. See the »flags« member function for a list of format flags.

Remarks

Clears the format flags specified by 1s in lFlags. It returns a long that contains the previous value of all the flags.

See Also

»ios::flags«, »ios::setf«, »ios resetiosflags manipulator«


  ios::width

int width( int nw );

int width() const;

nw    The minimum field width in characters.

Remarks

The first overloaded width function sets the stream's internal field width variable to nw. When the width is 0 (the default), inserters insert only as many characters as necessary to represent the inserted value. When the width is not 0, the inserters pad the field with the stream's fill character, up to nw. If the unpadded representation of the field is larger than nw, the field is not truncated. Thus nw is a minimum field width.

The internal width value is reset to 0 after each insertion or extraction.

The second overloaded width function returns the current value of the stream's width variable.

See Also

»ios setw manipulator«


  ios::xalloc

static int xalloc();

Remarks

Provides extra ios object state variables without the need for class derivation. It does so by returning an index to an unused 32-bit word in an internal array. This index can be subsequently converted into a reference or pointer by using the iword or pword member functions.

Any call to xalloc invalidates values returned by previous calls to iword and pword.

See Also

»ios::iword«, »ios::pword«


  ios::operator void* ()

operator void* () const;

Remarks

An operator that converts a stream to a pointer that can be compared to 0. The conversion returns 0 if either failbit or badbit is set in the stream's error state. See »rdstate« for a description of the error state masks. A nonzero pointer is not meant to be dereferenced.

See Also

»ios::good«, »ios::fail«


  ios::operator ! ()

int operator !() const;

Remarks

Returns a nonzero value if either failbit or badbit are set in the stream's error state. See »rdstate« for a description of the error state masks.

See Also

»ios::good«, »ios::fail«


  ios::adjustfield

static const long adjustfield;

Remarks

A mask that can be used to obtain the padding flag bits (left, right, or internal).

See Also

»ios::flags«

Example

extern ostream os;
if( ( os.flags() & ios::adjustfield ) == ios::left ) .....


  ios::basefield

static const long basefield;

Remarks

A mask that can be used to obtain the current radix flag bits (dec, oct, or hex).

See Also

»ios::flags«

Example

extern ostream os;
if( ( os.flags() & ios::basefield ) == ios::hex ) .....


  ios::floatfield

static const long floatfield;

Remarks

A mask that can be used to obtain floating-point format flag bits (scientific or fixed).

See Also

»ios::flags«

Example

extern ostream os;
if( ( os.flags() & ios::floatfield ) == ios::scientific ) .....


  ios& binary

binary

Remarks

Sets the stream's mode to binary. The default mode is text.

The stream must have an associated filebuf buffer.

See Also

»ios text manipulator«, »ofstream::setmode«, »ifstream::setmode«, »filebuf::setmode«


  ios& dec

dec

Remarks

Sets the format conversion base to 10 (decimal).

See Also

»ios hex manipulator«, »ios oct manipulator«


  ios& hex

hex

Remarks

Sets the format conversion base to 16 (hexadecimal).

See Also

»ios dec manipulator«, »ios oct manipulator«


  ios& oct

oct

Remarks

Sets the format conversion base to 8 (octal).

See Also

»ios dec manipulator«, »ios hex manipulator«


  resetiosflags

SMANIP( long ) resetiosflags( long lFlags );

#include <iomanip.h>

lFlags    Format flag bit values. See the »flags« member function for a list of format flags. These flags can be combined by using the OR ( | ) operator.

Remarks

This parameterized manipulator clears only the specified format flags. This setting remains in effect until the next change.


  setfill

SMANIP( int ) setfill( int nFill );

#include <iomanip.h>

nFill    The new fill character to be used as padding between fields.

Remarks

This parameterized manipulator sets the stream's fill character. The default is a space. This setting remains in effect until the next change.


  setiosflags

SMANIP( long ) setiosflags( long lFlags );

#include <iomanip.h>

lFlags    Format flag bit values. See the »flags« member function for a list of format flags. These flags can be combined by using the OR ( | ) operator.

Remarks

This parameterized manipulator sets only the specified format flags. This setting remains in effect until the next change.


  setprecision

SMANIP( int ) setprecision( int np );

#include <iomanip.h>

np    An integer that indicates the number of significant digits or significant decimal digits to be used for floating-point display.

Remarks

This parameterized manipulator sets the stream's internal floating-point precision variable to np. The default precision is six digits. If the display format is scientific or fixed, then the precision indicates the number of digits after the decimal point. If the format is automatic (neither floating point nor fixed), then the precision indicates the total number of significant digits.

This setting remains in effect until the next change.


  setw

SMANIP( int ) setw( int nw );

#include <iomanip.h>

nw    The field width in characters.

Remarks

This parameterized manipulator sets the stream's internal field width parameter. See the »width« member function for more information. This setting remains in effect only for the next insertion.


  ios& text

text

Remarks

Sets the stream's mode to text (the default mode).

The stream must have an associated filebuf buffer.

See Also

»ios binary manipulator«, »ofstream::setmode«, »ifstream::setmode«, »filebuf::setmode«


class iostream : public istream, public ostream
+ [image]  class iostream : public istream, public ostream

The iostream class provides the basic capability for sequential and random-access I/O. It inherits functionality from both the istream and ostream classes.

The iostream class works in conjunction with classes derived from streambuf (for example, filebuf). In fact, most of the iostream "personality" comes from its attached streambuf class. You can use iostream objects for sequential disk I/O if you first construct an appropriate filebuf object. More often, you will use objects of classes fstream and strstream.

Derivation

For derivation suggestions, see the istream and ostream classes.

#include <iostream.h>

See Also

»istream«, »ostream«, »fstream«, »strstream«, »stdiostream«

Public Members

iostream	Constructs an iostream object that is attached to an existing streambuf object.
~iostream	Destroys an iostream object.
Protected Members

iostream	Acts as a void-argument iostream constructor.


  iostream::iostream

Public

iostream( streambuf* psb ); ♦

Protected

iostream( ); ♦

psb    A pointer to an existing streambuf object (or an object of a derived class).

Remarks

Constructs an object of type iostream.

See Also

»ios::init«


  iostream::~iostream

virtual ~iostream();

Remarks

Virtual destructor for the iostream class.


  class Iostream_init

The Iostream_init class is a static class that initializes the predefined stream objects cin, cout, cerr, and clog. A single object of this class is constructed "invisibly" in response to the reference of any of the predefined objects. The class is documented for completeness only. You will not normally construct objects of this class.

#include <iostream.h>

Public Members

Iostream_init	A constructor that initializes cin, cout, cerr, and clog.
~Iostream_init	The destructor for the Iostream_init class.


  Iostream_init::Iostream_init

Iostream_init();

Remarks

Iostream_init constructor that initializes cin, cout, cerr, and clog. For internal use only.


  Iostream_init::~Iostream_init

~Iostream_init();

Remarks

Iostream_init destructor. For internal use only.


  class istream : virtual public ios

The istream class provides the basic capability for sequential and random-access input. An istream object has a streambuf-derived object attached, and the two classes work together; the istream class does the formatting, and the streambuf class does the low-level buffered input.

You can use istream objects for sequential disk input if you first construct an appropriate filebuf object. More often, you will use the predefined stream object cin (which is actually an object of class istream_withassign), or you will use objects of classes ifstream (disk file streams) and istrstream (string streams).

Derivation

It is not always necessary to derive from istream in order to add functionality to a stream; consider deriving from streambuf instead, as illustrated in »Deriving Your Own Stream Classes«. The ifstream and istrstream classes are examples of istream-derived classes that construct member objects of predetermined derived streambuf classes.

You can add manipulators without deriving a new class.

If you add new extraction operators for a derived istream class, then the rules of C++ dictate that you must reimplement all the base class extraction operators. See the "Derivation" section of class »ostream« for an efficient reimplementation technique.

#include <iostream.h>

See Also

»streambuf«, »ifstream«, »istrstream«, »istream_withassign«

Construction/Destruction — Public Members

istream	Constructs an istream object attached to an existing object of a streambuf-derived class.
~istream	Destroys an istream object.
Prefix/Suffix Functions — Public Members

ipfx	Check for error conditions prior to extraction operations (input prefix function).
isfx	Called after extraction operations (input suffix function).
Input Functions — Public Members

get	Extracts characters from the stream up to, but not including, delimiters.
getline	Extracts characters from the stream (extracts and discards delimiters).
read	Extracts data from the stream.
ignore	Extracts and discards characters.
peek	Returns a character without extracting it from the stream.
gcount	Counts the characters extracted in the last unformatted operation.
eatwhite	Extracts leading white space.
Other Functions — Public Members

putback	Puts characters back to the stream.
sync	Synchronizes the stream buffer with the external source of characters.
seekg	Changes the stream's get pointer.
tellg	Gets the value of the stream's get pointer.
Operators — Public Members

operator >>	Extraction operator for various types.
Protected Members

istream	Constructs an istream object.
Manipulators

ws	Extracts leading white space.


  istream::eatwhite

void eatwhite();

Remarks

Extracts white space from the stream by advancing the get pointer past spaces and tabs.

See Also

»istream ws  manipulator«


  istream::gcount

int gcount() const;

Remarks

Returns the number of characters extracted by the last unformatted input function. Formatted extraction operators may call unformatted input functions and thus reset this number.

See Also

»istream::get«, »istream::getline«, »istream::ignore«, »istream::read«


  istream::get

int get();&

istream& get( char* pch, int nCount, char delim = '\n' );

istream& get( unsigned char* puch, int nCount, char delim = '\n' );

istream& get( signed char* psch, int nCount, char delim = '\n' );& istream& get( char& rch );

istream& get( unsigned char& ruch );

istream& get( signed char& rsch );& istream& get( streambuf& rsb, char delim = '\n' );

pch, puch, psch    A pointer to a character array.

nCount    The maximum number of characters to store, including the terminating NULL.

delim    The delimiter character (defaults to newline).

rch, ruch, rsch    A reference to a character.

rsb    A reference to an object of a streambuf-derived class.

Remarks

These functions extract data from an input stream as follows:

Variation	Description
get();	Extracts a single character from the stream and returns it.
get( char*, int, char );	Extracts characters from the stream until either delim is found, the limit nCount is reached, or the end of file is reached. The characters are stored in the array followed by a null terminator.
get( char& );	Extracts a single character from the stream and stores it as specified by the reference argument.
get( streambuf&, char );	Gets characters from the stream and stores them in a streambuf object until the delimiter is found or the end of the file is reached. The ios::failbit flag is set if the streambuf output operation fails.
In all cases, the delimiter is neither extracted from the stream nor returned by the function. The getline function, in contrast, extracts the delimiter but does not store it.

See Also

»istream::getline«, »istream::read«, »istream::ignore«, »istream::gcount«


  istream::getline

istream& getline( char* pch, int nCount, char delim = '\n' );

istream& getline( unsigned char* puch, int nCount, char delim = '\n' );

istream& getline( signed char* psch, int nCount, char delim = '\n' );

pch, puch, psch    A pointer to a character array.

nCount    The maximum number of characters to store, including the terminating NULL.

delim    The delimiter character (defaults to newline).

Remarks

Extracts characters from the stream until either the delimiter delim is found, the limit nCount−1 is reached, or end of file is reached. The characters are stored in the specified array followed by a null terminator. If the delimiter is found, it is extracted but not stored.

The get function, in contrast, neither extracts nor stores the delimiter.

See Also

»istream::get«, »istream::read«


  istream::ignore

istream& ignore( int nCount = 1, int delim = EOF );

nCount    The maximum number of characters to extract.

delim    The delimiter character (defaults to EOF).

Remarks

Extracts and discards up to nCount characters. Extraction stops if the delimiter delim is extracted or the end of file is reached. If delim = EOF (the default), then only the end of file condition causes termination. The delimiter character is extracted.


  istream::ipfx

int ipfx( int need = 0 );

need    Zero if called from formatted input functions; otherwise the minimum number of characters needed.

Remarks

This input prefix function is called by input functions prior to extracting data from the stream. Formatted input functions call ipfx( 0 ), while unformatted input functions usually call ipfx( 1 ).

Any ios object tied to this stream is flushed if need = 0 or if there are fewer than need characters in the input buffer. Also, ipfx extracts leading white space if ios::skipws is set.

Return Value

A nonzero return value if the operation was successful; 0 if the stream's error state is nonzero, in which case the function does nothing.

See Also

»istream::isfx«


  istream::isfx

void isfx();

Remarks

This input suffix function is called at the end of every extraction operation.


  istream::istream

Public

istream( streambuf* psb );

Protected

istream( );

psb    A pointer to an existing object of a streambuf-derived class.

Remarks

Constructs an object of type istream.

See Also

»ios::init«


  istream::~istream

virtual ~istream();

Remarks

Virtual destructor for the istream class.


  istream::peek

int peek();

Remarks

Returns the next character without extracting it from the stream. Returns EOF if the stream is at end of file or if the ipfx function indicates an error.


  istream::putback

istream& putback( char ch );

ch    The character to put back; must be the character previously extracted.

Remarks

Puts a character back into the input stream. The putback function may fail and set the error state. If ch does not match the character that was previously extracted, then the result is undefined.


  istream::read

istream& read( char* pch, int nCount );

istream& read( unsigned char* puch, int nCount );

istream& read( signed char* psch, int nCount );

pch, puch, psch    A pointer to a character array.

nCount    The maximum number of characters to read.

Remarks

Extracts bytes from the stream until the limit nCount is reached or until the end of file is reached. The read function is useful for binary stream input.

See Also

»istream::get«, »istream::getline«, »istream::gcount«, »istream::ignore«


  istream::seekg

istream& seekg( streampos pos );

istream& seekg( streamoff off, ios::seek_dir dir );

pos    The new position value; streampos is a typedef equivalent to long.

off    The new offset value; streamoff is a typedef equivalent to long.

dir    The seek direction. Must be one of the following enumerators, with values and meanings as follows:

•	ios::beg    Seek from the beginning of the stream.

•	ios::cur    Seek from the current position in the stream.

•	ios::end    Seek from the end of the stream.

Remarks

Changes the get pointer for the stream. Not all derived classes of istream need support positioning; it is most often used with file-based streams.

See Also

»istream::tellg«, »ostream::seekp«, »ostream::tellp«


  istream::sync

int sync();

Remarks

Synchronizes the stream's internal buffer with the external source of characters. This function calls the virtual streambuf::sync function so you can customize its implementation by deriving a new class from streambuf.

Return Value

EOF to indicate errors.

See Also

»streambuf::sync«


  istream::tellg

streampos tellg();

Remarks

Gets the value for the stream's get pointer.

Return Value

A streampos type, corresponding to a long.

See Also

»istream::seekg«, »ostream::tellp«, »ostream::seekp«


  istream::operator >>

istream& operator >>( char* psz );

istream& operator >>( unsigned char* pusz );

istream& operator >>( signed char* pssz );

istream& operator >>( char& rch );

istream& operator >>( unsigned char& ruch );

istream& operator >>( signed char& rsch );

istream& operator >>( short& s );

istream& operator >>( unsigned short& us );

istream& operator >>( int& n );

istream& operator >>( unsigned int& un );

istream& operator >>( long& l );

istream& operator >>( unsigned long& ul );

istream& operator >>( float& f );

istream& operator >>( double& d );

istream& operator >>( long double& ld ); (16-bit only)

istream& operator >>( streambuf* psb );

istream& operator >>( istream& (*fcn)(istream&) );

istream& operator >>( ios& (*fcn)(ios&) );

Remarks

These overloaded operators extract their argument from the stream. The last two variations allow the use of manipulators that are defined for both istream and ios.


  istream& ws

ws

Remarks

Extracts leading white space from the stream by calling the eatwhite function.

See Also

»istream::eatwhite«


  class istream_withassign : public istream

The istream_withassign class is a variant of istream that allows object assignment. The predefined object cin is an object of this class and thus may be reassigned at run time to a different istream object.

A program that normally expects input from stdin, for example, could be temporarily directed to accept its input from a disk file.

Predefined Objects

The cin object is a predefined object of class ostream_withassign. It is connected to stdin (standard input, file descriptor 0).

The objects cin, cerr, and clog are tied to cout so that use of any of these may  cause cout to be flushed.

#include <iostream.h>

See Also

»ostream_withassign«

Construction/Destruction — Public Members

istream_withassign	Constructs an istream_withassign object.
~istream_withassign	Destroys an istream_withassign object.
Operators — Public Members

operator =	Indicates an assignment operator.


istream_withassign::istream_withassign

istream_withassign( streambuf* psb );

istream_withassign();

psb    A pointer to an existing object of a streambuf-derived class.

Remarks

The first constructor creates a ready-to-use object of type istream_withassign, complete with attached streambuf object.

The second constructor creates an object but does not initialize it. You must subsequently use the second variation of the istream_withassign assignment operator to attach the streambuf object, or you must use the first variation to initialize this object to match the specified istream object.

See Also

»istream_withassign::operator =«


  istream_withassign::~istream_withassign

~istream_withassign();

Remarks

Destructor for the istream_withassign class.


  istream_withassign::operator =

istream& operator =( const istream& ris );

istream& operator =( streambuf* psb );

Remarks

The first overloaded assignment operator assigns the specified istream object to this istream_withassign object.

The second operator attaches a streambuf object to an existing istream_withassign object, and it initializes the state of the istream_withassign object. This operator is often used in conjunction with the void-argument constructor.

See Also

»istream_withassign::istream_withassign«, cin

Example 1

char buffer[100];
class xistream; // A special-purpose class derived from istream
extern xistream xin; // An xistream object constructed elsewhere

cin = xin; // cin is reassigned to xin
cin >> buffer; // xin used instead of cin

Example 2

char buffer[100];
extern filedesc fd; // A file descriptor for an open file
filebuf fb( fd ); // Construct a filebuf attached to fd

cin = &fb;     // fb associated with cin
cin >> buffer; // cin now gets its intput from the fb file


  class istrstream : public istream

The istrstream class supports input streams that have character arrays as a source. You must allocate a character array prior to the construction of an istrstream object. All the istream operators and functions (including seeking) can then be used on this character data.

You must be aware that there is a get pointer working behind the scenes in the attached strstreambuf class. This pointer advances as you extract fields from the stream's array. The only way you can make it go backwards is to use the istream::seekg function. If the get pointer reaches the end of the string (and sets the ios::eof flag), then you must call clear before seekg.

#include <strstrea.h>

See Also

»strstreambuf«, »streambuf«, »strstream«, »ostrstream«

Construction/Destruction — Public Members

istrstream	Constructs an istrstream object.
~istrstream	Destroys an istrstream object.
Other Functions — Public Members

rdbuf	Returns a pointer to the stream's associated strstreambuf object.
str	RReturns a character array pointer to the string stream's contents.


  istrstream::istrstream

istrstream( char* psz );

istrstream( char* pch, int nLength );

psz    A null-terminated character array (string).

pch    A character array that is not necessarily null terminated.

nLength    Size (in characters) of pch. If 0, then pch is assumed to point to a null-terminated array; if less than 0, then the array length is assumed to be unlimited.

Remarks

The first constructor uses the specified psz buffer to make an istrstream object with length corresponding to the string length.

The second constructor makes an istrstream object out of the first nLength characters of the pch buffer.

Both constructors automatically construct a strstreambuf object that manages the specified character buffer.


  istrstream::~istrstream

~istrstream();

Remarks

Destroys an istrstream object and its associated strstreambuf object. The character buffer is not released because it was allocated by the user prior to istrstream construction.


  istrstream::rdbuf

strstreambuf* rdbuf() const;

Remarks

Returns a pointer to the strstreambuf buffer object that is associated with this stream. Note that this is not the character buffer itself; the strstreambuf object contains a pointer to the character area.

See Also

»istrstream::str«


  istrstream::str

char* str();

Remarks

Returns a pointer to the string stream's character array. This pointer corresponds to the array used to construct the istrstream object.

See Also

»istrstream::istrstream«


  class ofstream : public ostream

The ofstream class is an ostream derivative specialized for disk file output. All of its constructors automatically create and associate a filebuf buffer object.

The filebuf class documentation describes the get and put areas and their associated pointers. Only the put area and the put pointer are active for the ofstream class.

#include <fstream.h>

See Also

»filebuf«, »streambuf«, »ifstream«, »fstream«

Construction/Destruction — Public Members

ofstream	Constructs an ofstream object.
~ofstream	Destroys an ofstream object.
Operations — Public Members

open	Opens a file and attaches it to the filebuf object and thus to the stream.
close	Flushes any waiting output and closes the stream's file.
setbuf	Associates the specified reserve area to the stream's filebuf object.
setmode	Sets the stream's mode to binary or text.
attach	Attaches the stream (through the filebuf object) to an open file.
Status/Information — Public Members

rdbuf	Gets the stream's filebuf object.
fd	Returns the file descriptor associated with the stream.
is_open	Tests whether the stream's file is open.


  ofstream::attach

void attach( filedesc fd );

fd    A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

Attaches this stream to the open file specified by fd. The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream's error state.

See Also

»filebuf::attach«, »ofstream::fd«


  ofstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, flushes any waiting output, closes the file, and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream's error state is cleared unless the call to filebuf::close fails.

See Also

»filebuf::close«, »ofstream::open«, »ofstream::is_open«


  ofstream::fd

filedesc fd() const;

Remarks

Returns the file descriptor associated with the stream. filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

See Also

»filebuf::fd«, »ofstream::attach«


  ofstream::is_open

int is_open() const;

Remarks

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

See Also

»filebuf::is_open«, »ofstream::open«, »ofstream::close«


  ofstream::ofstream

ofstream();

ofstream( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot );

ofstream( filedesc fd );

ofstream( filedesc fd, char* pch, int nLength );

szName    The name of the file to be opened during construction.

nMode    An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values, with the meanings as given:

•	ios::app    The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream::seekp function.

•	ios::ate    The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position.

•	ios::in    If this mode is specified, then the original file (if it exists) will not be truncated.

•	ios::out    The file is opened for output (implied for all ofstream objects).

•	ios::trunc    If the file already exists, its contents are discarded. This mode is implied if ios::out is specified and ios::ate, ios::app, and ios:in are not specified.

•	ios::nocreate    If the file does not already exist, the function fails.

•	ios::noreplace    If the file already exists, the function fails.

•	ios::binary    Opens the file in binary mode (the default is text mode).

nProt    The file protection specification; defaults to the static integer filebuf::openprot that is equivalent to filebuf::sh_compat. The possible nProt values are as follows, with meanings as given:

•	filebuf::sh_compat    Compatibility share mode.

•	filebuf::sh_none    Exclusive mode; no sharing.

•	filebuf::sh_read    Read sharing allowed.

•	filebuf::sh_write    Write sharing allowed.

The filebuf::sh_read and filebuf::sh_write modes can be combined with the logical OR ( || ) operator.

fd    A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

pch    Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength    The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four ofstream constructors are described as follows:

Constructor	Description
ofstream()	Constructs an ofstream object without opening a file.
ofstream( const char*, int, int )	Contructs an ofstream object, opening the specified file.
ofstream( filedesc )	Constructs an ofstream object that is attached to an open file.
ofstream( filedesc, char*, int )	Constructs an ofstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.
All ofstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area. The user-allocated area is not automatically released during destruction.


  ofstream::~ofstream

~ofstream();

Remarks

Flushes the buffer, then destroys an ofstream object along with its associated filebuf object. The file is closed only if was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


  ofstream::open

void open( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot );

szName    The name of the file to be opened during construction.

nMode    An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ofstream constructor for a list of the enumerators. The ios::out mode is implied.

nProt    The file protection specification; defaults to the static integer filebuf::openprot. See the ofstream constructor for a list of the other allowed values.

Remarks

Opens a disk file and attaches it to the stream's filebuf object. If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, the ios::failbit is set only if the ios::nocreate mode was used.

See Also

»filebuf::open«, »ofstream::ofstream«, »ofstream::close«, »ofstream::is_open«


  ofstream::rdbuf

filebuf* rdbuf() const;

Remarks

Returns a pointer to the filebuf buffer object that is associated with this stream. (Note that this is not the character buffer; the filebuf object contains a pointer to the character area.)

Example

extern ofstream ofs;
int fd = ofs.rdbuf()->fd(); // Get the file descriptor for ofs


  ofstream::setbuf

streambuf* setbuf( char* pch, int nLength );

pch    A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength    The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

Attaches the specified reserve area to the stream's filebuf object. If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf cast as a streambuf. The reserve area will not be released by the destructor.


  ofstream::setmode

int setmode( int nMode = filebuf::text );

nMode    An integer that must be one of the static filebuf constants, with values and meanings as follows:

•	filebuf::text    Text mode (newline characters translated to and from carriage return − linefeed pairs).

•	filebuf::binary    Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream's filebuf object. It may be called only after the file is opened.

Return Value

The previous mode; −1 if the parameter is invalid, the file is not open, or the mode cannnot be changed.

See Also

»ios binary manipulator«, »ios text manipulator«


  class ostream : virtual public ios

The ostream class provides the basic capability for sequential and random-access output. An ostream object has a streambuf-derived object attached, and the two classes work together; the ostream class does the formatting, and the streambuf class does the low-level buffered output.

You can use ostream objects for sequential disk output if you first construct an appropriate filebuf object. (The filebuf class is derived from streambuf.) More often, you will use the predefined stream objects cout, cerr, and clog (actually objects of class ostream_withassign), or you will use objects of classes ofstream (disk file streams) and ostrstream (string streams).

All of the ostream member functions write unformatted data; formatted output is handled by the insertion operators.

Derivation

It is not always necessary to derive from ostream to add functionality to a stream; consider deriving from streambuf instead, as illustrated in »Deriving Your Own Stream Classes«. The ofstream and ostrstream classes are examples of ostream-derived classes that construct member objects of predetermined derived streambuf classes.

You can add manipulators without deriving a new class.

If you add new insertion operators for a derived ostream class, then the rules of C++ dictate that you must reimplement all the base class insertion operators. If, however, you reimplement the operators through inline equivalence, no extra code will be generated. For example:

class xstream : public ostream
{
public:
    // Constructors, etc.
    // ........
    inline xstream& operator << ( char ch ) // insertion for char
    {
          return (xstream&)ostream::operator << ( ch );
    }
    // ........
    // Insertions for other types
};

#include <iostream.h>

See Also

»streambuf«, »ofstream«, »ostrstream«, cout, cerr, clog

Construction/Destruction — Public Members

ostream	Constructs an ostream object that is attached to an existing streambuf object.
~ostream	Destroys an ostream object.
Prefix/Suffix Functions — Public Members

opfx	Output prefix function, called prior to insertion operations to check for error conditions, and so forth.
osfx	Output suffix function, called after insertion operations; flushes the stream's buffer if it is unit buffered.
Unformatted Output — Public Members

put	Inserts a single byte into the stream.
write	Inserts a series of bytes into the stream.
Other Functions — Public Members

flush	Flushes the buffer associated with this stream.
seekp	Changes the stream's put pointer.
tellp	Gets the value of the stream's put pointer.
Operators — Public Members

operator <<	An insertion operator for various types.
Manipulators

endl	Inserts a newline sequence and flushes the buffer.
ends	Inserts a null character to terminate a string.
flush	Flushes the stream's buffer.


  ostream::flush

ostream& flush();

Remarks

Flushes the buffer associated with this stream. The flush function calls the sync function of the associated streambuf.

See Also

»ostream flush  manipulator«, »streambuf::sync«


  ostream::opfx

int opfx();

Remarks

This output prefix function is called before every insertion operation. If another ostream object is tied to this stream, then the opfx function flushes that stream.

Return Value

If the ostream object's error state is not 0, opfx returns 0 immediately; otherwise it returns a nonzero value.


  ostream::osfx

void osfx();

Remarks

This output suffix function is called after every insertion operation. It flushes the ostream object if ios::unitbuf is set. It flushes stdout and stderr if ios::stdio is set.


  ostream::ostream

Public

ostream( streambuf* psb );

Protected

ostream( );

psb    A pointer to an existing object of a streambuf-derived class.

Remarks

Constructs an object of type ostream.

See Also

»ios::init«


  ostream::~ostream

virtual ~ostream();

Remarks

Destroys an ostream object. The output buffer is flushed as appropriate. The attached streambuf object is destroyed only if it was allocated internally within the ostream constructor.


  ostream::put

ostream& put( char ch );

ch    The character to insert.

Remarks

This function inserts a single character into the output stream.


  ostream::seekp

ostream& seekp( streampos pos );

ostream& seekp( streamoff off, ios::seek_dir dir );

pos    The new position value; streampos is a typedef equivalent to long.

off    The new offset value; streamoff is a typedef equivalent to long.

dir    The seek direction specified by the enumerated type ios::seek_dir, with 	values and meanings as follows:

•	ios::beg    Seek from the beginning of the stream.

•	ios::cur    Seek from the current position in the stream.

•	ios::end    Seek from the end of the stream.

Remarks

Changes the position value for the stream. Not all derived classes of ostream need support positioning. For file streams, the position is the byte offset from the beginning of the file; for string streams, it is the byte offset from the beginning of the string.

See Also

»ostream::tellp«, »istream::seekg«, »istream::tellg«


  ostream::tellp

streampos tellp();

Remarks

Gets the position value for the stream. Not all derived classes of ostream need support positioning. For file streams, the position is the byte offset from the beginning of the file; for string streams, it is the byte offset from the beginning of the string. Gets the value for the stream's put pointer.

Return Value

A streampos type that corresponds to a long.

See Also

»ostream::seekp«, »istream::tellg«, »istream::seekg«


ostream::write

ostream& write( const char* pch, int nCount );

ostream& write( const unsigned char* puch, int nCount );

ostream& write( const signed char* psch, int nCount );

pch, puch, psch    A pointer to a character array.

nCount    The number of characters to be written.

Remarks

Inserts a specified number of bytes from a buffer into the stream. If the underlying file was opened in text mode, additional carriage return characters may be inserted. The write function is useful for binary stream output.


  ostream::operator <<

ostream& operator <<( char ch );

ostream& operator <<( unsigned char uch );

ostream& operator <<( signed char sch );

ostream& operator <<( const char*  psz );

ostream& operator <<( const unsigned char* pusz );

ostream& operator <<( const signed char* pssz );

ostream& operator <<( short s );

ostream& operator <<( unsigned short us );

ostream& operator <<( int n );

ostream& operator <<( unsigned int un );

ostream& operator <<( long l );

ostream& operator <<( unsigned long ul );

ostream& operator <<( float f );

ostream& operator <<( double d );

ostream& operator <<( long double ld ); (16-bit only)

ostream& operator <<( const void* pv );

ostream& operator <<( streambuf* psb );

ostream& operator <<( ostream& (*fcn)(ostream&) );

ostream& operator <<( ios& (*fcn)(ios&) );

Remarks

These overloaded operators insert their argument into the stream. The last two variations allow the use of manipulators that are defined for both ostream and ios.


  ostream& endl

endl

Remarks

This manipulator, when inserted into an output stream, inserts a newline character and then flushes the buffer.


  ostream& ends

ends

Remarks

This manipulator, when inserted into an output stream, inserts a null-terminator character. It is particularly useful for ostrstream objects.


  ostream& flush

flush

Remarks

This manipulator, when inserted into an output stream, flushes the output buffer by calling the streambuf::sync member function.

See Also

»ostream::flush«, »streambuf::sync«


  class ostream_withassign : public ostream

The ostream_withassign class is a variant of ostream that allows object assignment. The predefined objects cout, cerr, and clog are objects of this class and thus may be reassigned at run time to a different ostream object.

A program that normally sends output to stdout, for example, could be temporarily directed to send its output to a disk file.

Predefined Objects

There are three predefined objects of class ostream_withassign. They are connected as follows:

cout    Standard output (file descriptor 1).

cerr    Unit buffered standard error (file descriptor 2).

clog    Fully buffered standard error (file descriptor 2).

Unit buffering, as used by cerr, means that characters are flushed after each insertion operation. The objects cin, cerr, and clog are tied to cout so that use of any of these will cause cout to be flushed.

#include <iostream.h>

See Also

»istream_withassign«

Construction/Destruction — Public Members

ostream_withassign	Constructs an ostream_withassign object.
~ostream_withassign	Destroys an ostream_withassign object.
Operators — Public Members

operator =	Assignment operator.


  ostream_withassign::ostream_withassign

ostream_withassign( streambuf* psb );

ostream_withassign();

psb    A pointer to an existing object of a streambuf-derived class.

Remarks

The first constructor makes a ready-to-use object of type ostream_withassign, complete with an attached streambuf object.

The second constructor makes an object but does not initialize it. You must subsequently use the streambuf assignment operator to attach the streambuf object, or you must use the ostream assignment operator to initialize this object to match the specified object.

See Also

»ostream_withassign::operator =«


  ostream_withassign::~ostream_withassign

~ostream_withassign();

Remarks

Destructor for the ostream_withassign class.


  ostream_withassign::operator =

ostream& operator =( const ostream&_os );

ostream& operator =( streambuf*_sp );

Remarks

The first overloaded assignment operator assigns the specified ostream object to this ostream_withassign object.

The second operator attaches a streambuf object to an existing ostream_withassign object, and it initializes the state of the ostream_withassign object. This operator is often used in conjunction with the void-argument constructor.

See Also

»ostream_withassign::ostream_withassign«,
cout

Example

filebuf fb( "test.dat" ); // Filebuf object attached to "test.dat"
cout = &fb;         // fb associated with cout
cout << "testing"; // Message goes to "test.dat" instead of stdout


  class ostrstream : public ostream

The ostrstream class supports output streams that have character arrays as a destination. You can allocate a character array prior to construction, or the constructor can internally allocate an expandable array. All the ostream operators and functions can then be used to fill the array.

You must be aware that there is a put pointer working behind the scenes in the attached strstreambuf class. This pointer advances as you insert fields into the stream's array. The only way you can make it go backwards is to use the ostream::seekp function. If the put pointer reaches the end of user-allocated memory (and sets the ios::eof flag), then you must call clear before seekp.

#include <strstrea.h>

See Also

»strstreambuf«, »streambuf«, »strstream«, »istrstream«

Construction/Destruction — Public Members

ostrstream	Constructs an ostrstream object.
~ostrstream	Destroys an ostrstream object.
Other Functions — Public Members

pcount	Returns the number of bytes that have been stored in the stream's buffer.
rdbuf	Returns a pointer to the stream's associated strstreambuf object.
str	Returns a character array pointer to the string stream's contents and freezes the array.


  ostrstream::ostrstream

ostrstream();

ostrstream( char* pch, int nLength, int nMode = ios::out );

pch    A character array that is large enough to accommodate future output stream activity.

nLength    The size (in characters) of pch. If 0, then pch is assumed to point to a null-terminated array and strlen( pch ) is used as the length; if less than 0, then the array is assumed to have infinite length.

nMode    The stream-creation mode. Must be one of the following enumerators as defined in class ios, with the following values and meanings:

•	ios::out    Default; storing begins at pch.

•	ios::ate    The pch parameter is assumed to be a null-terminated array; storing begins at the NULL character.

•	ios::app    Same as ios::ate.

Remarks

The first constructor makes an ostrstream object that uses an internal, dynamic buffer.

The second constructor makes an ostrstream object out of the first nLength characters of the pch buffer. The stream will not accept characters once the length reaches nLength.


  ostrstream::~ostrstream

~ostrstream();

Remarks

Destroys an ostrstream object and its associated strstreambuf object, thus releasing all internally allocated memory. If you used the void-argument constructor, then the internally allocated character buffer is released; otherwise, you must release it yourself.

An internally allocated character buffer will not be released if it was previously frozen by an str or strstreambuf::freeze function call.

See Also

»ostrstream::str«, »strstreambuf::freeze«


  ostrstream::pcount

int pcount() const;

Remarks

Returns the number of bytes that have been stored in the buffer. This information is especially useful when you have stored binary data in the object.


  ostrstream::rdbuf

strstreambuf* rdbuf() const;

Remarks

Returns a pointer to the strstreambuf buffer object that is associated with this stream. Note that this is not the character buffer; the strstreambuf object contains a pointer to the character area.

See Also

»ostrstream::str«


  ostrstream::str

char* str();

Remarks

Returns a pointer to the internal character array. If the stream was built with the void-argument constructor, then str freezes the array. You must not send characters to a frozen stream, and you are responsible for deleting the array. You can, however, subsequently unfreeze the array by calling rdbuf->freeze( 0 ).

If the stream was built with the constructor that specified the buffer, then the pointer contains the same address as the array used to construct the ostrstream object.

See Also

»ostrstream::ostrstream«, »ostrstream::rdbuf«, »strstreambuf::freeze«


  class stdiobuf : public streambuf

The run-time library supports three conceptual sets of I/O functions: iostreams (C++ only), standard I/O (the functions declared in STDIO.H), and low-level I/O (the functions declared in IO.H). The stdiobuf class is a derived class of streambuf that is specialized for buffering to and from the standard I/O system.

Because the standard I/O system does its own internal buffering, the extra buffering level provided by stdiobuf may reduce overall input/output efficiency. The stdiobuf class is useful when you need to mix iostream I/O with standard I/O (printf and so forth).

You can avoid use of the stdiobuf class if you use the filebuf class. You must also use the stream class's ios::flags member function to set the ios::stdio format flag value.

#include <stdiostr.h>

See Also

»stdiostream«, »filebuf«, »strstreambuf«, »ios::flags«

Construction/Destruction — Public Members

stdiobuf	Constructs a stdiobuf object from a FILE pointer.
~stdiobuf	Destroys a stdiobuf object.
Other Functions — Public Members

stdiofile	Gets the file that is attached to the stdiofile object.


  stdiobuf::stdiobuf

stdiobuf( FILE* fp );

fp    A standard I/O file pointer (can be obtained through an fopen or _fsopen call).

Remarks

Objects of class stdiobuf are constructed from open standard I/O files, including stdin, stdout, and stderr. The object is unbuffered by default.


  stdiobuf::~stdiobuf

~stdiobuf();

Remarks

Destroys a stdiobuf object and, in the process, flushes the put area. The destructor does not close the attached file.


  stdiobuf::stdiofile

FILE* stdiofile();

Remarks

Returns the standard I/O file pointer associated with a stdiobuf object.


  class stdiostream : public iostream

The stdiostream class makes I/O calls (through the stdiobuf class) to the standard I/O system, which does its own internal buffering. Calls to the functions declared in STDIO.H, such as printf, can be mixed with stdiostream I/O calls.

This class is included for compatibility with earlier stream libraries. You can avoid use of the stdiostream class if you use the ostream or istream class with an associated filebuf class. You must also use the stream class's ios::flags member function to set the ios::stdio format flag value.

The use of the stdiobuf class may reduce efficiency because it imposes an extra level of buffering. Do not use this feature unless you need to mix iostream library calls with standard I/O calls for the same file.

#include <stdiostr.h>

See Also

»stdiobuf«, »ios::flags«

Construction/Destruction — Public Members

stdiostream	Constructs a stdiostream object that is associated with a standard I/O FILE pointer.
~stdiostream	Destroys a stdiostream object (virtual).
Other Functions — Public Members

rdbuf	Gets the stream's stdiobuf object.


  stdiostream::rdbuf

stdiobuf* rdbuf() const;

Remarks

Returns a pointer to the stdiobuf buffer object that is associated with this stream. The rdbuf function is useful when you need to call stdiobuf member functions.


  stdiostream::stdiostream

stdiostream( FILE* fp );

fp    A standard I/O file pointer (can be obtained through an fopen or _fsopen call). Could be stdin, stdout, or stderr.

Remarks

Objects of class stdiostream are constructed from open standard I/O files. An unbuffered stdiobuf object is automatically associated, but the standard I/O system provides its own buffering.

Example

stdiostream myStream( stdout );


  stdiostream::~stdiostream

~stdiostream();

Remarks

This destructor destroys the stdiobuf object associated with this stream; however, the attached file is not closed.


  class streambuf

All the iostream classes in the ios hierarchy depend on an attached streambuf class for the actual I/O processing. This class is an abstract class, but the iostream class library contains the following derived buffer classes for use with streams:

•	filebuf    Buffered disk file I/O.

•	strstreambuf    Stream data held entirely within an in-memory byte array.

•	stdiobuf    Disk I/O with buffering done by the underlying standard I/O system.

All streambuf objects, when configured for buffered processing, maintain a fixed memory buffer, called a reserve area, that can be dynamically partitioned into a get area for input and a put area for output. These areas may or may not overlap. Protected member functions allow access and manipulation of a get pointer for character retrieval and a put pointer for character storage. The exact behavior of the buffers and pointers depends on the implementation of the derived class.

The capabilities of the iostream classes can be extended significantly through the derivation of new streambuf classes. The ios class tree supplies the programming interface and all formatting features, but the streambuf class does the real work. The ios classes call the streambuf public members, including a set of virtual functions.

The streambuf class provides a default implementation of certain virtual member functions. The "Default Implementation" section for each such function suggests function behavior for the derived class.

#include <iostream.h>

Character Input Functions — Public Members

in_avail	Returns the number of characters in the get area.
sgetc	Returns the character at the get pointer, but does not move the pointer.
snextc	Advances the get pointer, then returns the next character.
sbumpc	Returns the current character, and then advances the get pointer.
stossc	Moves the get pointer forward one position, but does not return a character.
sputbackc	Attempts to move the get pointer back one position.
sgetn	Gets a sequence of characters from the streambuf object's buffer.
Character Output Functions — Public Members

out_waiting	Returns the number of characters in the put area.
sputc	Stores a character in the put area and advances the put pointer.
sputn	Stores a sequence of characters in the streambuf object's buffer and advances the put pointer.
Construction/Destruction — Public Members

~streambuf	Virtual destructor.
Diagnostic Functions — Public Members

dbp	Prints buffer statistics and pointer values.
Virtual Functions — Public Members

sync	Empties the get area and the put area.
setbuf	Attempts to attach a reserve area to the streambuf object.
seekoff	Seeks to a specified offset.
seekpos	Seeks to a specified position.
overflow	Empties the put area.
underflow	Fills the get area if necessary.
pbackfail	Augments the sputbackc function.
Construction/Destruction — Protected Members

streambuf	Constructors for use in derived classes.
Other Protected Member Functions — Protected Members

base	Returns a pointer to the start of the reserve area.
ebuf	Returns a pointer to the end of the reserve area.
blen	Returns the size of the reserve area.
pbase	Returns a pointer to the start of the put area.
pptr	Returns the put pointer.
epptr	Returns a pointer to the end of the put area.
eback	Returns the lower bound of the get area.
gptr	Returns the get pointer.
egptr	Returns a pointer to the end of the get area.
setp	Sets all the put area pointers.
setg	Sets all the get area pointers.
pbump	Increments the put pointer.
gbump	Increments the get pointer.
setb	Sets up the reserve area.
unbuffered	Tests or sets the streambuf buffer state variable.
allocate	Allocates a buffer, if needed, by calling doalloc.
doallocate	Allocates a reserve area (virtual function).


  streambuf::allocate

Protected

int allocate(); ♦

Remarks

Calls the virtual function doallocate to set up a reserve area. If a reserve area already exists or if the streambuf object is unbuffered, allocate returns 0. If the space allocation fails, allocate returns EOF.

See Also

»streambuf::doallocate«, »streambuf::unbuffered«


  streambuf::base

Protected

char* base() const; ♦

Remarks

Returns a pointer to the first byte of the reserve area. The reserve area consists of space between the pointers returned by base and ebuf.

See Also

»streambuf::ebuf«, »streambuf::setb«, »streambuf::blen«


  streambuf::blen

Protected

int blen() const; ♦

Remarks

Returns the size, in bytes, of the reserve area.

See Also

»streambuf::base«, »streambuf::ebuf«, »streambuf::setb«


  streambuf::dbp

void dbp();

Remarks

Writes ASCII debugging information directly on stdout. Treat this function as part of the protected interface.

Some sample output follows:

STREAMBUF DEBUG INFO: this = 00E7:09DC
 base()=00E7:0A0C, ebuf()=00E7:0C0C,  blen()=512
eback()=0000:0000, gptr()=0000:0000, egptr()=0000:0000
pbase()=00E7:0A0C, pptr()=00E7:0A22, epptr()=00E7:0C0C


  streambuf::doallocate

Protected

virtual int doallocate(); ♦

Remarks

Called by allocate when space is needed. The doallocate function must allocate a reserve area, then call setb to attach the reserve area to the streambuf object. If the reserve area allocation fails, doallocate returns EOF.

Default Implementation

Attempts to allocate a reserve area using operator new.

See Also

»streambuf::allocate«, »streambuf::setb«


  streambuf::eback

Protected

char* eback() const; ♦

Remarks

Returns the lower bound of the get area. Space between the eback and gptr pointers is available for putting a character back into the stream.

See Also

»streambuf::sputbackc«, »streambuf::gptr«


  streambuf::ebuf

Protected

char* ebuf() const; ♦

Remarks

Returns a pointer to the byte after the last byte of the reserve area. The reserve area consists of space between the pointers returned by base and ebuf.

See Also

»streambuf::base«, »streambuf::setb«, »streambuf::blen«


  streambuf::egptr

Protected

char* egptr() const; ♦

Remarks

Returns a pointer to the byte after the last byte of the get area.

See Also

»streambuf::setg«, »streambuf::eback«, »streambuf::gptr«


  streambuf::epptr

Protected

char* epptr() const; ♦

Remarks

Returns a pointer to the byte after the last byte of the put area.

See Also

»streambuf::setp«, »streambuf::pbase«, »streambuf::pptr«


  streambuf::gbump

Protected

void gbump( int nCount ); ♦

nCount    The number of bytes to increment the get pointer. May be positive or negative.

Remarks

Increments the get pointer. No bounds checks are made on the result.

See Also

»streambuf::pbump«


  streambuf::gptr

Protected

char* gptr() const; ♦

Remarks

Returns a pointer to the next character to be fetched from the streambuf buffer. This pointer is known as the get pointer.

See Also

»streambuf::setg«, »streambuf::eback«, »streambuf::egptr«


  streambuf::in_avail

int in_avail() const;

Remarks

Returns the number of characters in the get area that are available for fetching. These characters are between the gptr and egptr pointers and may be fetched with a guarantee of no errors.


  streambuf::out_waiting

int out_waiting() const;

Remarks

Returns the number of characters in the put area that have not been sent to the final output destination. These characters are between the pbase and pptr pointers.


  streambuf::overflow

virtual int overflow( int nCh = EOF ) = 0;

nCh    EOF or the character to output.

Remarks

The virtual overflow function, together with the sync and underflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement overflow differently, but the interface with the calling stream class is the same.

The overflow function is most frequently called by public streambuf functions like sputc and sputn when they sense that the put area is full, but other classes, including the stream classes, can call overflow anytime.

The function "consumes" the characters in the put area between the pbase and pptr pointers and then reinitializes the put area. The overflow function must also consume nCh (if nCh is not EOF), or it might choose to put that character in the new put area so that it will be consumed on the next call.

The definition of "consume" varies among derived classes. The filebuf class, for example, writes its characters to a file. The strsteambuf class, on the other hand, keeps them in its buffer and (if the buffer is designated as dynamic) expands the buffer in response to a call to overflow. This expansion is achieved by freeing the old buffer and replacing it with a new, larger one. The pointers are adjusted as necessary.

Default Implementation

No default implementation. Derived classes must define this function.

Return Value

EOF to indicate an error.

See Also

»streambuf::pbase«, »streambuf::pptr«, »streambuf::setp«, »streambuf::sync«, »streambuf::underflow«


  streambuf::pbackfail

virtual int pbackfail( int nCh );

nCh    The character used in a previous sputbackc call.

Remarks

This function is called by sputbackc if it fails, usually because the eback pointer equals the gptr pointer. The pbackfail function should deal with the situation, if possible, by such means as repositioning the external file pointer.

Default Implementation

Returns EOF.

Return Value

The nCh parameter if successful; otherwise EOF.

See Also

»streambuf::sputbackc«


  streambuf::pbase

Protected

char* pbase() const; ♦

Remarks

Returns a pointer to the start of the put area. Characters between the pbase pointer and the pptr pointer have been stored in the buffer but not flushed to the final output destination.

See Also

»streambuf::pptr«, »streambuf::setp«, »streambuf::out_waiting«


  streambuf::pbump

Protected

void pbump( int nCount ); ♦

nCount    The number of bytes to increment the put pointer. May be positive or negative.

Remarks

Increments the put pointer. No bounds checks are made on the result.

See Also

»streambuf::gbump«, »streambuf::setp«


  streambuf::pptr

Protected

char* pptr() const; ♦

Remarks

Returns a pointer to the first byte of the put area. This pointer is known as the put pointer and is the destination for the next character(s) sent to the streambuf object.

See Also

»streambuf::epptr«, »streambuf::pbase«, »streambuf::setp«


  streambuf::sbumpc

int sbumpc();

Remarks

Returns the current character, then advances the get pointer. Returns EOF if the get pointer is currently at the end of the sequence (equal to the egptr pointer).

See Also

»streambuf::epptr«, »streambuf::gbump«


  streambuf::seekoff

virtual streampos seekoff( streamoff off, ios::seek_dir dir, int nMode = ios::in | ios::out );

off    The new offset value; streamoff is a typedef equivalent to long.

dir    The seek direction specified by the enumerated type seek_dir, with values and meanings as follows:

•	ios::beg    Seek from the beginning of the stream.

•	ios::cur    Seek from the current position in the stream.

•	ios::end    Seek from the end of the stream.

nMode    An integer that contains a bitwise OR ( | ) combination of the enumerators ios::in and ios::out.

Remarks

Changes the position for the streambuf object. Not all derived classes of streambuf need to support positioning; however, the filebuf, strstreambuf, and stdiobuf classes do support positioning.

Classes derived from streambuf often support independent input and output position values. The nMode parameter determines which value(s) is set.

Default Implementation

Returns EOF.

Return Value

The new position value. This is the byte offset from the start of the file (or string). If both ios::in and ios::out are specified, then the function returns the output position. If the derived class does not support positioning, then the function returns EOF.

See Also

»streambuf::seekpos«


  streambuf::seekpos

virtual streampos seekpos( streampos pos, int nMode = ios::in | ios::out );

pos    The new position value; streampos is a typedef equivalent to long.

nMode    An integer that contains mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See ofstream::ofstream for a listing of the enumerators.

Remarks

Changes the position, relative to the beginning of the stream, for the streambuf object. Not all derived classes of streambuf need to support positioning; however, the filebuf, strstreambuf, and stdiobuf classes do support positioning.

Classes derived from streambuf often support independent input and output position values. The nMode parameter determines which value(s) is set.

Default Implementation

Calls seekoff( (streamoff) pos, ios::beg, nMode ). Thus, to define seeking in a derived class, it is usually necessary to redefine only seekoff.

Return Value

The new position value. If both ios::in and ios::out are specified, then the function returns the output position. If the derived class does not support positioning, then the function returns EOF.

See Also

»streambuf::seekoff«


  streambuf::setb

Protected

void setb( char* pb, char* peb, int  nDelete = 0 ); ♦

pb    The new value for the base pointer.

peb    The new value for the ebuf pointer.

nDelete    Flag that controls automatic deletion. If nDelete is not 0, then the reserve area will be deleted (1) when the base pointer is changed by another setb call or (2) when the streambuf destructor is called.

Remarks

Sets the values of the reserve area pointers. If both pb and peb are NULL, then there is no reserve area. If pb is not NULL and peb is NULL, then the reserve area has a length of 0.

See Also

»streambuf::base«, »streambuf::ebuf«


  streambuf::setbuf

virtual streambuf* setbuf( char* pr, int nLength );

pr    A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength    The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

Attaches the specified reserve area to the streambuf object. Derived classes may or may not use this area.

Default Implementation

Accepts the request if there is not a reserved area already.

Return Value

A streambuf pointer if the buffer is accepted; otherwise NULL.


  streambuf::setg

Protected

void setg( char* peb, char* pg, char* peg ); ♦

peb    The new value for the eback pointer.

pg    The new value for the gptr pointer.

peg    The new value for the egptr pointer.

Remarks

Sets the values for the get area pointers.

See Also

»streambuf::eback«, »streambuf::gptr«, »streambuf::egptr«


  streambuf::setp

Protected

void setp( char* pp, char* pep ); ♦

pp    The new value for the pbase and pptr pointers.

pep    The new value for the epptr pointer.

Remarks

Sets the values for the put area pointers.

See Also

»streambuf::pptr«, »streambuf::pbase«, »streambuf::epptr«


  streambuf::sgetc

int sgetc();

Remarks

Returns the character at the get pointer. The sgetc function does not move the get pointer. Returns EOF if there is no character available.

See Also

»streambuf::sbumpc«, »streambuf::sgetn«, »streambuf::snextc«, »streambuf::stossc«


  streambuf::sgetn

int sgetn( char* pch, int nCount );

pch    A pointer to a buffer that will receive characters from the streambuf object.

nCount    The number of characters to get.

Remarks

Gets the nCount characters that follow the get pointer and stores them in the area starting at pch. When fewer than nCount characters remain in the streambuf object, sgetn fetches whatever characters remain. The function repositions the get pointer to follow the fetched characters.

Return Value

The number of characters fetched.

See Also

»streambuf::sbumpc«, »streambuf::sgetc«, »streambuf::snextc«, »streambuf::stossc«


  streambuf::snextc

int snextc();

Remarks

First tests the get pointer, then returns EOF if it is already at the end of the get area. Otherwise, it moves the get pointer forward one character and returns the character that follows the new position. It returns EOF if the pointer has been moved to the end of the get area.

See Also

»streambuf::sbumpc«, »streambuf::sgetc«, »streambuf::sgetn«, »streambuf::stossc«


  streambuf::sputbackc

int sputbackc( char ch );

ch    The character to be put back to the streambuf object.

Remarks

Moves the get pointer back one character. The ch character must match the character just before the get pointer.

Return Value

EOF on failure.

See Also

»streambuf::sbumpc«, »streambuf::pbackfail«


  streambuf::sputc

int sputc( int nCh );

nCh    The character to store in the streambuf object.

Remarks

Stores a character in the put area and advances the put pointer.

This public function is available to code outside the class, including the classes derived from ios. A derived streambuf class can gain access to its buffer directly by using protected member functions.

Return Value

The number of characters successfully stored; EOF on error.

See Also

»streambuf::sputn«


  streambuf::sputn

int sputn( const char* pch, int nCount );

pch    A pointer to a buffer that contains data to be copied to the streambuf object.

nCount    The number of characters in the buffer.

Remarks

Copies nCount characters from pch to the streambuf buffer following the put pointer. The function repositions the put pointer to follow the stored characters.

Return Value

The number of characters stored. This number is usually nCount but could be less if an error occurs.

See Also

»streambuf::sputc«


  streambuf::stossc

void stossc();

Remarks

Moves the get pointer forward one character. If the pointer is at the end of the get area already, the function has no effect.

See Also

»streambuf::sbumpc«, »streambuf::sgetn«, »streambuf::snextc«, »streambuf::sgetc«


  streambuf::streambuf

Protected

streambuf();

streambuf( char* pr, int nLength ); ♦

pr    A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength    The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

The first constructor makes an uninitialized streambuf object. This object is not suitable for use until a setbuf call is made. A derived class constructor usually calls setbuf or uses the second constructor.

The second constructor initializes the streambuf object with the specified reserve area or marks it as unbuffered.

See Also

»streambuf::setbuf«


  streambuf::~streambuf

Public

virtual ~streambuf(); ♦

Remarks

The streambuf destructor flushes the buffer if the stream is being used for output.


  streambuf::sync

virtual int sync();

Remarks

The virtual sync function, together with the overflow and underflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement sync differently, but the interface with the calling stream class is the same.

The sync function flushes the put area. It also empties the get area and, in the process, sends any unprocessed characters back to the source, if necessary.

Default Implementation

Returns 0 if the get area is empty and there are no more characters to output; otherwise, it returns EOF.

Return Value

EOF if an error occurs.

See Also

»streambuf::overflow«


  streambuf::unbuffered

Protected

void unbuffered( int nState );

int unbuffered() const; ♦

nState    The value of the buffering state variable; 0 = buffered, nonzero = unbuffered.

Remarks

The first overloaded unbuffered function sets the value of the streambuf object's buffering state. This variable's primary purpose is to control whether the allocate function automatically allocates a reserve area.

The second function returns the current buffering state variable.

See Also

»streambuf::allocate«, »streambuf::doallocate«


  streambuf::underflow

mfvirtual int underflow() = 0;

Remarks

The virtual underflow function, together with the sync and overflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement underflow differently, but the interface with the calling stream class is the same.

The underflow function is most frequently called by public streambuf functions like sgetc and sgetn when they sense that the get area is empty, but other classes, including the stream classes, can call underflow anytime.

The underflow function supplies the get area with characters from the input source. If the get area contains characters, then underflow returns the first character. If the get area is empty, then it fills the get area and returns the next character (which it leaves in the get area). If there are no more characters available, then underflow returns EOF and leaves the get area empty.

In the strstreambuf class, underflow adjusts the egptr pointer to access storage that was dynamically allocated by a call to overflow.

Default Implementation

No default implementation. Derived classes must define this function.


  class strstream : public iostream

The strstream class supports I/O streams that have character arrays as a source and destination. You can allocate a character array prior to construction, or the constructor can internally allocate a dynamic array. All the input and output stream operators and functions can then be used to fill the array.

You must be aware that there is a put pointer and a get pointer working independently behind the scenes in the attached strstreambuf class. The put pointer advances as you insert fields into the stream's array, and the get pointer advances as you extract fields. The ostream::seekp function moves the put pointer, and the istream::seekg function moves the get pointer. If either pointer reaches the end of the string (and sets the ios::eof flag), then you must call clear before seeking.

#include <strstrea.h>

See Also

»strstreambuf«, »streambuf«, »istrstream«, »ostrstream«

Construction/Destruction — Public Members

strstream	Constructs a strstream object.
~strstream	Destroys a strstream object.
Other Functions — Public Members

pcount	Returns the number of bytes that have been stored in the stream's buffer.
rdbuf	Returns a pointer to the stream's associated strstreambuf object.
str	Returns a pointer to the string stream's character buffer and freezes it.


  strstream::pcount

int pcount() const;

Remarks

Returns the number of bytes that have been stored in the buffer. This information is especially useful when you have stored binary data in the object.


  strstream::rdbuf

strstreambuf* rdbuf() const;

Remarks

Returns a pointer to the strstreambuf buffer object that is associated with this stream. Note that this is not the character buffer; the strstreambuf object contains a pointer to the character area.

See Also

»strstream::str«


  strstream::str

char* str();

Remarks

Returns a pointer to the internal character array. If the stream was built with the void-argument constructor, then str freezes the array. You must not send characters to a frozen stream, and you are responsible for deleting the array. You can unfreeze the the stream by calling rdbuf->freeze( 0 ).

If the stream was built with the constructor that specified the buffer, then the pointer contains the same address as the array used to construct the ostrstream object.

See Also

»strstreambuf::freeze«, »strstream::rdbuf«


  strstream::strstream

strstream();

strstream( char* pch, int nLength, int nMode );

pch    A character array that is large enough to accommodate future output stream activity.

nLength    The size (in characters) of pch. If 0, then pch is assumed to point to a null-terminated array; if less than 0, then the array is assumed to have infinite length.

nMode    The stream creation mode. Must be one of the following enumerators as defined in class ios, with values and meanings as follows:

•	ios::in    Retrieval begins at the beginning of the array.

•	ios::out    By default, storing begins at pch.

•	ios::ate    The pch parameter is assumed to be a null-terminated array; storing begins at the NULL character.

•	ios::app    Same as ios::ate.

The use of the ios::in and ios::out flags is optional for this class; both input and output are implied.

Remarks

The first constructor makes an strstream object that uses an internal, dynamic buffer that is initially empty.

The second constructor makes an strstream object out of the first nLength characters of the psc buffer. The stream will not accept characters once the length reaches nLength.


  strstream::~strstream

~strstream();

Remarks

Destroys a strstream object and its associated strstreambuf object, thus releasing all internally allocated memory. If you used the void-argument constructor, then the internally allocated character buffer is released; otherwise, you must release it yourself.

An internally allocated character buffer will not be released if it was previously frozen by calling rdbuf->freeze( 0 ).

See Also

»strstream::rdbuf«


  class strstreambuf : public streambuf

The strstreambuf class is a derived class of streambuf that manages an in-memory character array.

The file stream classes, ostrstream, istrstream, and strstream, use strstreambuf member functions to fetch and store characters. Some of these member functions are virtual functions defined for the streambuf class.

The reserve area, put area, and get area were introduced in the streambuf class description. For strsteambuf objects, the put area is the same as the get area, but the get pointer and the put pointer move independently.

#include <strstrea.h>

See Also

»istrstream«, »ostrstream«, »filebuf«, »stdiobuf«

Construction/Destruction — Public Members

strstreambuf	Constructs a strstreambuf object.
~strstreambuf	Destroys a strstreambuf object.
Other Functions — Public Members

freeze	Freezes a stream.
str	Returns a pointer to the string.


strstreambuf::freeze

void freeze( int n = 1 );

n    A 0 value permits automatic deletion of the current array and also its automatic growth (if it is dynamic); a nonzero value prevents deletion.

Remarks

If a strstreambuf object has a dynamic array, then memory is usually deleted on destruction and size adjustment. The freeze function provides a means of

preventing that automatic deletion. Once an array is frozen, no further input or output is permitted. The results of such operations are undefined.

The freeze function can also unfreeze a frozen buffer.

See Also

»strstreambuf::str«


  strstreambuf::str

char* str();

Remarks

Returns a pointer to the object's internal character array. If the strstreambuf object was constructed with a user-supplied buffer, then that buffer address is returned. If the object has a dynamic array, then str freezes the array. You must not send characters to a frozen strstreambuf object, and you are responsible for deleting the array. If a dynamic array is empty, then str returns NULL.

You can use the freeze function with a 0 parameter to unfreeze a frozen strstreambuf object.

See Also

»strstreambuf::freeze«


  strstreambuf::strstreambuf

strstreambuf();

strstreambuf( int nBytes );

strstreambuf( char* pch, int n, char* pstart = 0 );

strstreambuf( unsigned char* puch, int n, unsigned char* pustart = 0 );

strstreambuf( signed char* psch, int n, signed char* psstart = 0 );

strstreambuf( void* (*falloc)(long), void (*ffree)(void*) );

nBytes    The initial length of a dynamic stream buffer.

pch, puch, psch    A pointer to a character buffer that will be attached to the object. The get pointer is initialized to this value.

n    An integer parameter with the following values and meanings:

•	positive    n bytes, starting at pch, is used as a fixed-length stream buffer.

•	0    The pch parameter points to the start of a null-terminated string that constitutes the stream buffer (terminator excluded).

•	negative    The pch parameter points to a stream buffer that continues indefinitely.

pstart, pustart, psstart    The initial value of the put pointer.

falloc    A memory-allocation function with the prototype void* falloc( long ). The default is new.

ffree    A function that frees allocated memory with the prototype void ffree( void* ). The default is delete.

Remarks

The four streambuf constructors are described as follows:

Constructor	Description
strstreambuf()	Constructs an empty strstreambuf object with dynamic buffering. The buffer is allocated internally by the class and grows as needed, unless it is frozen.
strstreambuf( int )	Constructs an empty strstreambuf object with a dynamic buffer n bytes long to start with. The buffer is allocated internally by the class and grows as needed, unless it is frozen.
strstreambuf( char*, int, char* )	Constructs a strstreambuf object from already-allocated memory as specified by the arguments. There are constructor variations for both unsigned and signed character arrays.
strstreambuf( void*(*), void(*) )	Constructs an empty strstreambuf object with dynamic buffering. The falloc function is called for allocation. The long parameter specifies the buffer length and the function returns the buffer address. If the falloc pointer is NULL, then operator new is used. The ffree function frees memory allocated by falloc. If the ffree pointer is NULL, the operator delete is used.


  strstreambuf::~strstreambuf

~strstreambuf();

Remarks

Destroys a strstreambuf object and, in the process, releases all internally allocated dynamic memory unless the object is frozen. The destructor does not release user-allocated memory.


iostream Hierarchy Chart


Preprocessor Introduction
Preprocessor Reference

Introduction

This manual explains the preprocessor as it is implemented in Microsoft® Visual C++™ for Windows NT™. The preprocessor is a tool you use to process C and C++ files before they are passed to the compiler. It allows you to

•	Define and undefine macros.

•	Expand macros.

•	Conditionally compile code.

•	Insert specified files.

•	Specify compile-time error messages.

•	Apply machine-specific rules to specified sections of code.


Book Location
Preprocessor Reference


  Scope and Organization of This Manual

This manual is intended for programmers who have already learned the fundamentals of programming; it is not intended as a learning guide. It is organized as follows:

»Chapter 1, The Preprocessor,« introduces all elements of the preprocessor, the directives and operators, except for the pragma directives.

»Chapter 2, Pragma Directives,« describes the pragmas that you can use to apply machine- and operating-system-specific rules to specific sections of source code.

»Appendix A, Phases of Translation,« explains in what order C and C++ programs are translated from source code to an executable file or a dynamic-link library.

»Appendix B, Grammar Summary,« describes the formal grammar of the preprocessor.

Note  For information on Microsoft product support, see the chapter "Microsoft Support Services" in Getting Started.


  Document Conventions

This book uses the following typographic conventions:

Example	Description
STDIO.H	Uppercase letters indicate filenames, segment names, registers, and terms used at the operating-system command level.
char, _setcolor, __far	Bold type indicates C and C++ keywords, operators, language-specific characters, and library routines. Within discussions of syntax, bold type indicates that the text must be entered exactly as shown.
	Many functions and constants begin with either a single or double underscore. These are part of the name and are mandatory. For example, to have the __cplusplus manifest constant be recognized by the compiler, you must enter the leading double underscore.
expression	Words in italic indicate placeholders for information you must supply, such as a filename.
grammar-elementopt	The subscript indicates that this element of the grammar is optional and can be omitted.
[option]	Items inside square brackets are optional.
#pragma pack {1 | 2}	Braces and a vertical bar indicate a choice among two or more items. You must choose one of these items unless square brackets ([ ])surround the braces.
#include <io.h>	This font is used for examples, user input, program output, and error messages in text.
CL [option...]  file...	Three dots (an ellipsis) following an item indicate that more items having the same form may appear.
while() {  .  .  . }	A column or row of three dots tells you that part of an example program has been intentionally omitted.
CTRL+ENTER	Small capital letters are used to indicate the names of keys on the keyboard. When you see a plus sign (+) between two key names, you should hold down the first key while pressing the second.
	The carriage-return key, sometimes marked as a bent arrow on the keyboard, is called ENTER.
"argument"	Quotation marks enclose a new term the first time it is defined in text.
"C string"	Some language constructs, such as strings, require quotation marks. Quotation marks required by the language have the form " " and ' ' rather than " " and ' '.
Dynamic-Link Library (DLL)	The first time an acronym is used, it is usually spelled out.
Microsoft Specific	This manual documents the C++ language, as it is implemented in Microsoft C++. As a result, some of the features of C++ that are implementation dependent or undefined in the ANSI base document are defined by the Microsoft implementation. You can find these features by looking for the "Microsoft Specific" heading in the left margin.
32-Bit Specific 16-Bit Specific	When a particular feature is specific only to 32-bit compilations or to 16-bit compilations, it is marked by the appropriate heading in the left margin. In text, such compilations are referred to as "32-bit (or 16-bit) target compilations." For more information on the differences between the Microsoft 16-bit and 32-bit compilers, see Chapter 1, "Porting 16-bit code to 32-bit Windows" in Programming Techniques.
♦	This symbol denotes the end of "Microsoft Specific," "16-Bit Specific," or "32-Bit Specific" information.
see »Using Projects«	Hypertext cross-references are enclosed in green double chevrons. Click the term enclosed in the chevrons to jump to display the referenced information.


  Special Terminology

In this manual, the term "argument" refers to the entity that is passed to a function. In some cases, it is modified by "actual" or "formal," which mean the argument expression specified in the function call and the argument declaration specified in the function definition, respectively.

The term "variable" refers to a simple C-type data object. The term "object" refers to both C++ objects and variables; it is an inclusive term.


  Chapter 1  The Preprocessor

The preprocessor is a text processor that manipulates the text of a source file as part of the first phase of translation. (For more information on translation phases, see Appendix A, »Phases of Translation«.) The preprocessor does not parse the source text, but it does break it up into tokens for the purpose of locating macro calls. Although the compiler ordinarily invokes the preprocessor in its first pass, the preprocessor can also be invoked separately to process text without compiling.

Microsoft Specific

You can obtain a listing of your source code after preprocessing by using the /E or /EP compilation options. Both options cause the preprocessor to be invoked and the resulting text to be output to the standard output device, which, in most cases, is the console. The difference between the two options is that /E includes #line directives and /EP strips these directives out. ♦


  1.1 Overview of Preprocessor Directives

Preprocessor directives, such as #define and #ifdef, are typically used to make source programs easy to change and easy to compile in different execution environments. Directives in the source file tell the preprocessor to perform specific actions. For example, the preprocessor can replace tokens in the text, insert the contents of other files into the source file, or suppress compilation of part of the file by removing sections of text. Preprocessor lines are recognized and carried out before macro expansion. Therefore, if a macro expands into something that looks like a preprocessor command, that command is not recognized by the preprocessor.

Preprocessor statements use the same character set as source file statements, with the exception that escape sequences are not supported. The character set used in preprocessor statements is the same as the execution character set. (For infor-mation on the execution character set, see "Character Constants" in Chapter 1 of the C++ Language Reference.) The preprocessor also recognizes negative character values.

The preprocessor recognizes the following directives:

#define	#else	#error	#ifdef
#elif	#endif	#if	#ifndef
#include	#line	#pragma	#undef
The number sign (#) must be the first nonwhite-space character on the line containing the directive; white-space characters can appear between the number sign and the first letter of the directive. Some directives include arguments or values. Any text that follows a directive (except an argument or value that is part of the directive) must be preceded by the single-line comment delimiter (//) or enclosed in comment delimiters (/*  */). Lines containing preprocessor directives can be continued by immediately preceding the end-of-line marker with a backslash (\).

Preprocessor directives can appear anywhere in a source file, but they apply only to the remainder of the source file.


  1.2  Macros

Preprocessing expands macros in all lines that are not preprocessor directives (lines that do not have a # as the first nonwhite-space character) and in parts of some directives that are not skipped as part of a conditional compilation. (For more information, see »Conditional Compilation«.) The #define directive is typically used to associate meaningful identifiers with constants, keywords, and commonly used statements or expressions. Identifiers that represent constants are sometimes called "symbolic constants" or "manifest constants." Identifiers that represent statements or expressions are called "macros." In this book, only the term "macro" is used. Macros have their own name space. For information, see "Name Spaces" in Chapter 2 of the C++ Language Reference.

When the name of the macro is recognized in the program source text or in the arguments of certain other preprocessor commands, it is treated as a call to that macro. The macro name is replaced by a copy of the macro body. If the macro accepts arguments, the actual arguments following the macro name are substituted for formal parameters in the macro body. The process of replacing a macro call with the processed copy of the body is called "expansion" of the macro call.

In practical terms, there are two types of macros. "Object-like" macros take no arguments, whereas "function-like" macros can be defined to accept arguments so that they look and act like function calls. Because macros do not generate actual function calls, you can sometimes make programs run faster by replacing function calls with macros. (In C++, inline functions are often a preferred method.) However, macros can create problems if you do not define and use them with care. You may have to use parentheses in macro definitions with arguments to preserve the proper precedence in an expression. Also, macros may not correctly handle expressions with side effects. For more information, see the getrandom example in »The #define Directive«.

Once you have defined a macro, you cannot redefine it to a different value without first removing the original definition. However, you can redefine the macro with exactly the same definition. Thus, the same definition can appear more than once in a program.

The #undef directive removes the definition of a macro. Once you have removed the definition, you can redefine the macro to a different value. »The #define Directive« and »The #undef Directive« discuss the #define and #undef directives, respectively.


  Macros and C++

C++ offers new capabilities, some of which supplant those offered by the ANSI C preprocessor. These new capabilities enhance the type safety and predictability of the language:

•	In C++, objects declared as const can be used in constant expressions. This allows programs to declare constants that have type and value information, and enumerations that can be viewed symbolically with the debugger. Using the preprocessor #define directive to define constants is not as precise. No storage is allocated for a const object unless an expression that takes its address is found in the program.

•	The C++ inline function capability supplants function-type macros. The advantages of using inline functions over macros are:

•	Type safety. Inline functions are subject to the same type checking as normal functions. Macros are not type safe.

•	Correct handling of arguments that have side effects. Inline functions evaluate the expressions supplied as arguments prior to entering the function body. Therefore, there is no chance that an expression with side effects will be unsafe.

For backward compatibility, all preprocessor facilities that existed in ANSI C and in earlier C++ specifications are preserved for Microsoft C++.


  The #define Directive

You can use the #define directive to give a meaningful name to a constant in your program. The two forms of the syntax are:

Syntax

#define  identifier token-string (opt)

#define  identifier [(  identifier (opt) ,  ...  ,  identifier (opt) )]   token-string (opt)

The #define directive substitutes token-string for all subsequent occurrences of an identifier in the source file. The identifier is replaced only when it forms a token. (For information on tokens, see "Tokens" in Chapter 1 of the C++ Language Reference.) For instance, identifier is not replaced if it appears in a comment, within a string, or as part of a longer identifier.

A #define without a token-string removes occurrences of identifier from the source file. The identifier remains defined and can be tested using the #if defined and #ifdef directives.

The token-string argument consists of a series of tokens, such as keywords, constants, or complete statements. One or more white-space characters must separate token-string from identifier. This white space is not considered part of the substituted text, nor is any white space following the last token of the text.

Formal parameter names appear in token-string to mark the places where actual values are substituted. Each parameter name can appear more than once in token-string, and the names can appear in any order. The number of arguments in the call must match the number of parameters in the macro definition. Liberal use of parentheses ensures that complicated actual arguments are interpreted correctly.

The second syntax form allows the creation of function-like macros. This form accepts an optional list of parameters that must appear in parentheses. References to the identifier after the original definition replace each occurrence of identifier( identifier (opt) , ..., identifier (opt ) ) with a version of the token-string argument that has actual arguments substituted for formal parameters.

The formal parameters in the list are separated by commas. Each name in the list must be unique, and the list must be enclosed in parentheses. No spaces can separate identifier and the opening parenthesis. Use line concatenation — place a backslash (\) before the newline character — for long directives on multiple source lines. The scope of a formal parameter name extends to the new line that ends token-string.

When a macro has been defined in the second syntax form, subsequent textual instances followed by an argument list constitute a macro call. The actual arguments following an instance of identifier in the source file are matched to the corresponding formal parameters in the macro definition. Each formal parameter in token-string that is not preceded by a stringizing (#), charizing (#@), or token-pasting (##) operator, or followed by a ## operator, is replaced by the corresponding actual argument. Any macros in the actual argument are expanded before it replaces the formal parameter. (The operators are described in »Preprocessor Operators«.)

The following examples of macros with arguments illustrate the second form of the #define syntax:

// Macro to define cursor lines

#define CURSOR(top, bottom) ((top) << 8) | bottom))

// Macro to get a random integer with a specified range

#define getrandom(min, max) \

    ((rand()%(int)(((max) + 1)-(min)))+ (min))

Arguments with side effects sometimes cause macros to produce unexpected results. A given formal parameter may appear more than once in token-string. If that formal parameter is replaced by an expression with side effects, the expression, with its side effects, may be evaluated more than once. (See examples in »Token-Pasting Operator (##)«.)

The #undef directive causes an identifier's preprocessor definition to be forgotten. For more information, see »The #undef Directive«.

If the name of the macro being defined occurs in token-string (even as a result of another macro expansion), it is not expanded.

A second #define for a macro with the same name generates an error unless the second token sequence is identical to the first.

Microsoft Specific

Microsoft C/C++ allows the redefinition of a macro, but generates a warning, provided the new definition is lexically identical to a previous definition. ANSI C considers macro redefinition an error. For example, these macros are equivalent for C/C++ but generate warnings:

#define test( f1, f2 ) ( f1 * f2 )
#define test( a1, a2 ) ( a1 * a2 ) ♦

This example illustrates the #define directive:

#define WIDTH       80#define LENGTH      ( WIDTH + 10 )

The first statement defines the identifier WIDTH as the integer constant 80 and defines LENGTH in terms of WIDTH and the integer constant 10. Each occurrence of LENGTH is replaced by (WIDTH + 10). In turn, each occurrence of WIDTH + 10 is replaced by the expression (80 + 10). The parentheses around WIDTH + 10 are important because they control the interpretation in statements such as the following:

var = LENGTH * 20;

After the preprocessing stage the statement becomes:

var = ( 80 + 10 ) * 20;

which evaluates to 1800. Without parentheses, the result is:

var = 80 + 10 * 20;

which evaluates to 280.

Microsoft Specific

Defining macros and constants with the /D command-line option has the same effect as using a #define preprocessing directive at the beginning of your file. Up to 30 macros can be defined with the /D option. ♦


  Preprocessor Operators

Four preprocessor-specific operators are used in the context of the #define directive. (For information on the defined operator, see »The #if, #elif, #else, and #endif Directives«.) This list gives a short summary of each of the preprocessor directives described in the following sections.

Operator	Action
Stringizing operator (#)	Causes the corresponding actual argument to be enclosed in double quotation marks
Charizing operator (#@)	Causes the corresponding argument to be enclosed in single quotation marks and to be treated as a character (Microsoft Specific)
Token-pasting operator (##)	Allows tokens used as actual arguments to be concatenated to form other tokens
defined operator	Simplifies the writing of compound expressions in certain macro directives


  Stringizing Operator (#)

The number-sign or "stringizing" operator (#) converts macro parameters (after expansion) to string constants. It is used only with macros that take arguments. If it precedes a formal parameter in the macro definition, the actual argument passed by the macro invocation is enclosed in quotation marks and treated as a string literal. The string literal then replaces each occurrence of a combination of the stringizing operator and formal parameter within the macro definition.

White space preceding the first token of the actual argument and following the last token of the actual argument is ignored. Any white space between the tokens in the actual argument is reduced to a single white space in the resulting string literal. Thus, if a comment occurs between two tokens in the actual argument, it is reduced to a single white space. The resulting string literal is automatically concatenated with any adjacent string literals from which it is separated only by white space.

Further, if a character contained in the argument usually requires an escape sequence when used in a string literal (for example, the quotation mark (") or backslash (\) character), the necessary escape backslash is automatically inserted before the character. The following example shows a macro definition that includes the stringizing operator and a main function that invokes the macro:

#define stringer( x ) printf( #x "\n" )

void main()
{
    stringer( In quotes in the printf function call\n );
    stringer( "In quotes when printed to the screen"\n );
    stringer( "This: \"  prints an escaped double quote" );
}

Such invocations would be expanded during preprocessing, producing the following code:

void main()
{
printf( "In quotes in the printf function call\n" "\n" );
printf( "\"In quotes when printed to the screen\"\n" "\n" );
printf( "\"This: \\\" prints an escaped double quote\"" "\n" );
}

When the program is run, screen output for each line is as follows:

In quotes in the printf function call

"In quotes when printed to the screen"

"This: \" prints an escaped double quotation mark"

Microsoft Specific

The Microsoft C (versions 6.0 and earlier) extension to the ANSI C standard that previously expanded macro formal arguments appearing inside string literals and character constants is no longer supported. Code that relied on this extension should be rewritten using the stringizing (#) operator. ♦


  Charizing Operator (#@)

Microsoft Specific

The charizing operator can be used only with arguments of macros. If #@ precedes a formal parameter in the definition of the macro, the actual argument is enclosed in single quotation marks and treated as a character when the macro is expanded. For example:

#define makechar(x)  #@x

causes the statement

a = makechar(b);

to be expanded to

a = 'b';

The single-quotation character cannot be used with the charizing operator. ♦


  Token-Pasting Operator (##)

The double-number-sign or "token-pasting" operator (##), which is sometimes called the "merging" operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token and therefore cannot be the first or last token in the macro definition.

If a formal parameter in a macro definition is preceded or followed by the token-pasting operator, the formal parameter is immediately replaced by the unexpanded actual argument. Macro expansion is not performed on the argument prior to replacement.

Then, each occurrence of the token-pasting operator in token-string is removed, and the tokens preceding and following it are concatenated. The resulting token must be a valid token. If it is, the token is scanned for possible replacement if it represents a macro name. The identifier represents the name by which the concatenated tokens will be known in the program before replacement. Each token represents a token defined elsewhere, either within the program or on the compiler command line. White space preceding or following the operator is optional.

This example illustrates use of both the "stringizing" and "token-pasting" operators in specifying program output:

#define paster( n ) printf( "token" #n " = %d", token##n )

int token9 = 9;

If macro is called with a numeric argument like

paster( 9 );

the macro yields

printf( "token" "9" " = %d", token9 );

which becomes

printf( "token9 = %d", token9 );


  The #undef Directive

As its name implies, the #undef directive removes (undefines) a name previously created with #define.

Syntax

#undef  identifier

The #undef directive removes the current definition of identifier. Consequently, subsequent occurrences of identifier are ignored by the preprocessor. To remove a macro definition using #undef, give only the macro identifier; do not give a parameter list.

You can also apply the #undef directive to an identifier that has no previous definition. This ensures that the identifier is undefined. Macro replacement is not performed within #undef statements.

The #undef directive is typically paired with a #define directive to create a region in a source program in which an identifier has a special meaning. For example, a specific function of the source program can use manifest constants to define environment-specific values that do not affect the rest of the program. The #undef directive also works with the #if directive to control conditional compilation of the source program. For more information, see »The #if, #elif, #else, and #endif Directives«.

In the following example, the #undef directive removes definitions of a symbolic constant and a macro. Note that only the identifier of the macro is given.

#define WIDTH           80
#define ADD( X, Y )     (X) + (Y)
.
.
.
#undef WIDTH
#undef ADD

Microsoft Specific

Macros can be undefined from the command line using the /U option, followed by the macro names to be undefined. The effect of issuing this command is equivalent to a sequence of #undef macro-name statements at the beginning of the file. ♦


  Predefined Macros

The compiler recognizes five predefined ANSI C macros, and the Microsoft C++ implementation provides several more. These macros take no arguments and cannot be redefined. Their value (except for __LINE__ and __FILE__) must be constant throughout compilation.

The ANSI-recognized predefined macros are:

Macro	Description
__DATE__	The compilation date of the current source file. The date is a string literal of the form Mmm dd yyyy. The month name Mmm is the same as for dates generated by the library function asctime declared in TIME.H.
__FILE__	The name of the current source file. __FILE__ expands to a string surrounded by double quotation marks.
__LINE__	The line number in the current source file. The line number is a decimal integer constant. It can be altered with a #line directive.
__STDC__	Indicates full conformance with the ANSI C standard. Defined as the integer constant 1 only if the /Za command-line option is given; otherwise, is undefined.
__TIME__	The most recent compilation time of the current source file. The time is a string literal of the form hh:mm:ss.
Microsoft Specific

The Microsoft-specific predefined macros are described in the following tables. Table 1.1 describes the macros predefined for 16-bit programs, and Table 1.2 describes the macros predefined for 32-bit programs.

If a predefined macro has two forms, with and without a leading underscore, the 16-bit command-line driver defines both if you specify the /Ze option (compile for Microsoft extensions). It defines only the leading-underscore form if you specify the /Za option (compile for ANSI compatibility). The 32-bit command-line driver defines only the leading-underscore form.

Table 1.1    Predefined Macros for 16-Bit Programs

Symbol	Function
_CHAR_UNSIGNED	Default char type is unsigned. Defined when /J is specified. Microsoft specific.
__cplusplus	Defined for C++ programs only.
_DLL	Code for run-time library as a dynamic-link library. Microsoft specific; defined when /MD is specified.
_FAST	Fast compile. Microsoft specific; defined when /f is specified (the default). Supersedes _QC, which is still supported but not recommended. Using /Od causes CL to compile your program with /f. The /f option compiles source files without any default optimizations.
M_I86, _M_I86	Identifies target machine as a member of the 8086 family. Always defined. Microsoft specific.
M_I8086, _M_I8086	Defined for 8086 and 8088 processors (default or /G0 option). Microsoft specific.
M_I286, _M_I286	Defined for 80286 processor (/G1 or /G2 option). Microsoft specific.
M_I86mM, _M_I86mM	Identifies memory model, where m is either T (tiny model), S (small model), C (compact model), M (medium model), L (large model), or H (huge model). Defined by /AT, /AS, /AC, /AM, /AL, and /AH, respectively. If huge model is used, both M_I86LM and M_I86HM are defined. Small model is the default. A memory-model identifier is always defined. Microsoft specific.
_MSC_VER	Defines the compiler version in the form "ddd". Defined as 800 for Microsoft Visual C++. Microsoft specific.
MSDOS, _MSDOS	Identifies target operating system as MS-DOS. Always defined. Microsoft specific.
_PCODE	Defined for sections of code that are compiled as p-code. Microsoft specific; defined when /Oq is enabled.
_WINDLL	Identifies Windows protected-mode dynamic-link library selected with /GD. Microsoft specific.
_WINDOWS	Identifies Windows protected mode selected with /GA, /Gw, /GW, /Mq, or /GD. Microsoft specific.
Table 1.2    Predefined Macros for 32-Bit Programs

Symbol	Function
_CHAR_UNSIGNED	Default char type is unsigned. Defined when /J is specified. Microsoft specific.
__cplusplus	Defined for C++ programs only.
_DLL	Defined when /MD is specified. Microsoft specific.
_M_IX86	Defined as 300 for the 80386 processor (/G3 option), as 400 for the 80486 processor (/G4 option), and as 500 for the Pentium processor (/G5 option). Microsoft specific.
_MSC_VER	Defines the compiler version in the form "ddd". Defined as 800 for Microsoft Visual C++ for Windows NT. Always defined. Microsoft specific.
_WIN32	Defined for WIN32 applications. Always defined. Microsoft specific.
_MT	Defined when /MD or /MT is specified. Microsoft specific.


  1.3  Include Files

The #include directive tells the preprocessor to treat the contents of the named file as if it appeared in the source program at the point where the directive appears. You can organize constant and macro definitions into include files and then use #include directives to add these definitions to any source file. Include files are also useful for incorporating declarations of external variables and complex data types. You only need to define and name the types once in an include file created for that purpose.

Syntax

#include  "  q-char-sequence  "

#include  <  h-char-sequence  >

q-char-sequence

Any sequence of characters except " and the end-of-line character specifying a filename.

h-char-sequence

Any sequence of characters except <  > and the end-of-line character specifying a filename.

Both forms cause replacement of that directive by the entire contents of the source file given. The difference between the two forms is how they search for header files when the path is incompletely specified.

Syntax Form	Action
Quoted form	This form, specified as #include "filename.h", instructs the preprocessor to look in the current directory and paths specified using the INCLUDE environment variable or the /I compile option for include files.
Angle-bracket form	This form, specified as #include <filename.h>, causes the preprocessor to search along the path specified with the INCLUDE environment variable and the /I compile option for header files.
The q-char-sequence and h-char-sequence are filenames optionally preceded by a directory specification. The filename must name an existing file. The syntax of the file specification depends on the operating system on which the program is compiled.

The preprocessor stops searching as soon as it finds a file with the given name. If you specify a complete, unambiguous path specification for the include file between two sets of double quotation marks (" "), the preprocessor searches only that path specification and ignores the standard directories.

If the filename enclosed in double quotation marks is an incomplete path specification, the preprocessor first searches the "parent" file's directory. A parent file is the file containing the #include directive. For example, if you include a file named file2 within a file named file1, file1 is the parent file.

Include files can be "nested"; that is, an #include directive can appear in a file named by another #include directive. For example, file2, above, could include file3. In this case, file1 would still be the parent of file2 but would be the "grandparent" of file3.

When include files are nested, directory searching begins with the directories of the parent file and then proceeds through the directories of any grandparent files. Thus, searching begins relative to the directory containing the source currently being processed. If the file is not found, the search moves to directories specified on the compiler command line. Finally, the standard directories are searched. For example,

#include <stdio.h>

adds the contents of the file named STDIO.H to the source program. The angle brackets cause the preprocessor to search the standard directories for STDIO.H, after searching directories specified on the command line.

For file specifications enclosed in angle brackets, the preprocessor does not search the current working directory. It begins by searching for the file in the directories specified on the compiler command line and then in the standard directories specified in the INCLUDE environment variable. The following example shows file inclusion using the quoted form:

#include "defs.h"

This example adds the contents of the file specified by DEFS.H to the source program. The double quotation marks mean that the preprocessor searches the directory containing the "parent" source file first.

Nesting of include files can continue up to 10 levels. Once the nested #include is processed, the preprocessor continues to insert the enclosing include file into the original source file.

Microsoft Specific

To locate includable source files, the preprocessor first searches the directories specified by the CL option /I. If the /I option is not present or fails, the preprocessor uses the INCLUDE environment variable to find any include files within angle brackets. If more than one directory appears as part of the /I option or within the INCLUDE environment variable, the preprocessor searches them in the order in which they appear.

For example, the command

CL /ID:\MSC  \INCLUDE MYPROG.C

causes the preprocessor to search the directory D:\MSC\INCLUDE for include files such as STDIO.H. The commands

SET INCLUDE = D:\C700\INCLUDE
CL MYPROG.C

have the same effect. If both sets of searches fail, a fatal error is generated. ♦

Microsoft Specific

If the filename is fully specified for an include file with a path that includes a colon (for example, F:\MSC\SPECIAL\INCL\TEST.H), the preprocessor follows the path.

For include files specified as #include "path-spec", directory searching begins with the directory of the parent file and then proceeds through the directories of any grandparent files. Thus, searching begins relative to the directory containing the source file containing the #include directive being processed. If there is no grandparent file and the file has not been found, the search continues as if the filename were enclosed in angle brackets.

For file specifications enclosed in angle brackets, the preprocessor does not search directories of the parent files. Instead, it begins by searching for the file in the directories specified on the compiler command line following /I. If the /I option is not present or fails, the preprocessor uses the INCLUDE environment variable to find any include files. The INCLUDE environment variable can contain multiple paths separated by semicolons (;). If more than one directory appears as part of the /I option or within the INCLUDE environment variable, the preprocessor searches them in the order in which they appear. ♦


  1.4  Conditional Compilation

This section describes the syntax and use of directives that control "conditional compilation." These directives allow you to suppress compilation of parts of a source file by testing a constant expression or identifier to determine which text blocks are passed on to the compiler and which text blocks are removed from the source file during preprocessing.


  The #if, #elif, #else, and #endif Directives

The #if directive, with the #elif, #else, and #endif directives, controls compilation of portions of a source file. If the expression you write (after the #if) has a nonzero value, the line group immediately following the #if directive is retained in the translation unit.

Syntax

conditional:
if-part  elif-parts (opt)   else-part (opt)   endif-line

if-part:
if-line  text

if-line:
#if  constant-expression
#ifdef  identifier
#ifndef  identifier

elif-parts:
elif-line  text
elif-parts  elif-line  text

elif-line:
#elif  constant-expression

else-part:
else-line  text

else-line:
#else

endif-line:
#endif

Each #if directive in a source file must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. The #else directive, if present, must be the last directive before #endif.

The #if, #elif, #else, and #endif directives can nest in the text portions of other #if directives. Each nested #else, #elif, or #endif directive belongs to the closest preceding #if directive.

All conditional-compilation directives, such as #if and #ifdef, must be matched with closing #endif directives prior to the end of file; otherwise, an error message is generated. When conditional-compilation directives are contained in include files, they must satisfy the same conditions: there must be no unmatched conditional-compilation directives at the end of the include file.

Macro replacement is performed within the part of the command line that follows an #elif command, so a macro call can be used in the constant-expression.

The preprocessor selects one of the given occurrences of text for further processing. A block specified in text can be any sequence of text. It can occupy more than one line. Usually text is program text that has meaning to the compiler or the preprocessor.

The preprocessor processes the selected text and passes it to the compiler. If text contains preprocessor directives, the preprocessor carries out those directives. Any text blocks not selected by the preprocessor are not compiled.

The preprocessor selects a single text item by evaluating the constant expression following each #if or #elif directive until it finds a true (nonzero) constant expression. It selects all text (including other preprocessor directives beginning with #) up to its associated #elif, #else, or #endif.

If all occurrences of constant-expression are false, or if no #elif directives appear, the preprocessor selects the text block after the #else clause. If the #else clause is omitted and all instances of constant-expression in the #if block are false, no text block is selected.

The constant-expression is an integer constant expression with these additional restrictions:

•	Expressions must have integral type and can only include integer constants, character constants, and the defined operator.

•	The expression cannot use sizeof or a type-cast operator.

•	The target environment may not be able to represent all ranges of integers.

•	The translation represents type int the same as type long, and unsigned int the same as unsigned long.

•	The translator can translate character constants to a set of code values different from the set for the target environment. To determine the properties of the target environment, check values of macros from LIMITS.H in an application built for the target environment.

•	The expression must not perform any environmental inquiries and must remain insulated from implementation details on the target computer.

The preprocessor operator defined can be used in special constant expressions, as shown by the following syntax:

Syntax

defined  (  identifier  )

defined  identifier

This constant expression is considered true (nonzero) if the identifier is currently defined; otherwise, the condition is false (0). An identifier defined as empty text is considered defined. The defined directive can be used in an #if and an #elif directive, but nowhere else.

In the following example, the #if and #endif directives control compilation of one of three function calls:

#if defined(CREDIT)
    credit();
#elif defined(DEBIT)
    debit();
#else
    printerror();
#endif

The function call to credit is compiled if the identifier CREDIT is defined. If the identifier DEBIT is defined, the function call to debit is compiled. If neither identifier is defined, the call to printerror is compiled. Note that CREDIT and credit are distinct identifiers in C and C++ because their case is different.

These next conditional compilation statements assume a previously defined symbolic constant named DLEVEL.

#if DLEVEL > 5
    #define SIGNAL  1
    #if STACKUSE == 1
        #define STACK   200
    #else
        #define STACK   100
    #endif
#else
    #define SIGNAL  0
    #if STACKUSE == 1
        #define STACK   100
    #else
        #define STACK   50
    #endif
#endif
#if DLEVEL == 0
    #define STACK 0
#elif DLEVEL == 1
    #define STACK 100
#elif DLEVEL > 5
    display( debugptr );
#else
    #define STACK 200
#endif

The first #if block shows two sets of nested #if, #else, and #endif directives. The first set of directives is processed only if DLEVEL > 5 is true. Otherwise, the statements after #else are processed.

The #elif and #else directives in the second example are used to make one of four choices, based on the value of DLEVEL. The constant STACK is set to 0, 100, or 200, depending on the definition of DLEVEL. If DLEVEL is greater than 5, then the statement

#elif DLEVEL > 5
display(debugptr);

is compiled and STACK is not defined.

A common use for conditional compilation is to prevent multiple inclusions of the same header file. In C++, where classes are often defined in header files, constructs like the following can be used to prevent multiple definitions:

// EXAMPLE.H - Example header file

#if !defined( EXAMPLE_H )
#define EXAMPLE_H

class Example
{
...
};

#endif // !defined( EXAMPLE_H )

The preceding code checks to see if the symbolic constant EXAMPLE_H is defined. If so, the file has already been included and need not be reprocessed. If not, the constant EXAMPLE_H is defined to mark EXAMPLE.H as already processed.

Microsoft Specific

Conditional compilation expressions are treated as signed long values, and these expressions are evaluated using the same rules as expressions in C++. For example, this expression:

#if 0xFFFFFFFFL > 1UL

is true. ♦


  The #ifdef and #ifndef Directives

The #ifdef and #ifndef directives perform the same task as the #if directive when it is used with defined(identifier).

Syntax

#ifdef  identifier

#ifndef  identifier

is equivalent to

#if defined  identifier

#if !defined  identifier

You can use the #ifdef and #ifndef directives anywhere #if can be used. The #ifdef  identifier statement is equivalent to #if 1 when identifier has been defined, and it is equivalent to #if 0 when identifier has not been defined or has been undefined with the #undef directive. These directives check only for the presence or absence of identifiers defined with #define, not for identifiers declared in the C or C++ source code.

These directives are provided only for compatibility with previous versions of the language. The defined(identifier) constant expression used with the #if directive is preferred.

The #ifndef directive checks for the opposite of the condition checked by #ifdef. If the identifier has not been defined (or its definition has been removed with #undef), the condition is true (nonzero). Otherwise, the condition is false (0).

Microsoft Specific

The identifier can be passed from the command line using the /D option. Up to 30 macros can be specified with /D.

This is useful for checking whether a definition exists, since a definition can be passed from the command line. For example:

// PROG.CPP
#ifndef test    // These three statements go in your source code.
#define final
#endif

CL /Dtest prog.cpp // This is the command for compilation. ♦


  The Null Directive (#)

The null preprocessor directive is a single number sign (#) alone on a line. It has no effect.

Syntax

#


  1.5  Line Control

The #line directive tells the preprocessor to change the compiler's internally stored line number and filename to a given line number and filename. The compiler uses the line number and filename to refer to errors that it finds during compilation. The line number usually refers to the current input line, and the filename refers to the current input file. The line number is incremented after each line is processed.

Syntax

#line  constant  "filename" (opt)

The constant is interpreted as a decimal integer. Macro replacement can be performed on the preprocessing tokens, but the result must evaluate to the correct syntax.

You can alter the source line number and filename by writing a #line directive. The translator uses the line number and filename to determine the values of the predefined macros __FILE__ and __LINE__. For information on these predefined macros, see »Predefined Macros«.

If you change the line number and filename, the compiler ignores the previous values and continues processing with the new values. The #line directive is typically used by program generators to cause error messages to refer to the original source file instead of to the generated program.

The constant value in the #line directive can be any integer constant. The filename can be any combination of characters and must be enclosed in double quotation marks (" "). If filename is omitted, the previous filename remains unchanged.

The current line number and filename are always available through the predefined macros __LINE__ and __FILE__. You can use the __LINE__ and __FILE__ identifiers to insert self-descriptive error messages into the program text. For more information, see »Predefined Macros«.

The __FILE__ macro expands to a string whose contents are the filename, surrounded by double quotation marks (" ").

The following examples illustrate #line and the __LINE__ and __FILE__ macros.

In this statement, the internally stored line number is set to 151 and the filename is changed to copy.c.

#line 151 "copy.c"

In this example, the macro ASSERT uses the predefined identifiers __LINE__ and __FILE__ to print an error message about the source file if a given "assertion" is not true.

#define ASSERT(cond)

if( !(cond) )\
{printf( "assertion error line %d, file(%s)\n", \
__LINE__, __FILE__ );}


  1.6  Error Directives

Error directives produce compiler-time error messages.

Syntax

#error  token-string

The error messages include the argument token-string and are subject to macro expansion. These directives are most useful for detecting programmer inconsistencies and violation of constraints during preprocessing. The following example demonstrates error processing during preprocessing:

#if !defined(__cplusplus)
#error C++ compiler required.
#endif

When #error directives are encountered, compilation terminates.


  Chapter 2  Pragma Directives

Each implementation of C and C++ supports some features unique to its host machine or operating system. Some programs, for instance, need to exercise precise control over the memory areas where data is placed or to control the way certain functions receive parameters. The #pragma directives offer a way for each C and C++ compiler to offer machine- and operating-system-specific features while retaining overall compatibility with the C and C++ languages. Since pragmas are machine- or operating-system-specific by definition, they usually are different for every compiler.

Syntax

#pragma token-string

The token-string is a series of characters that gives a specific compiler instruction and arguments, if any. The number sign (#) must be the first nonwhite-space character on the line containing the pragma; white-space characters can separate the number sign and the word pragma. Following #pragma, write any text that the translator can parse as preprocessing tokens. The argument to #pragma is subject to macro expansion.

If the compiler finds a pragma that it does not recognize, it issues a warning, but compilation continues.

Pragmas can be used in conditional statements, to provide new preprocessor functionality, or to provide implementation-defined information to the compiler.

The #pragma directives instruct the compiler to implement the features specified by the argument. The compiler recognizes the following pragmas:

alloc_text	inline_depth	page
auto_inline	inline_recursion	pagesize
check_pointer	init_seg	pointers_to_members
check_stack	intrinsic	setlocale
code_seg	linesize	skip
comment	message	subtitle
data_seg	native_caller	title
function	optimize	vtordisp
hdrstop	pack	warning
These three pragma directives, init_seg, pointers_to_members, and vtordisp, are defined for the C++ compiler only:


  #pragma init_seg

#pragma init_seg( { compiler | lib | user | "seg-name" } )

Specifies a keyword or segment that affects the order in which startup code is executed. Because initialization of global static objects can involve executing code, you must specify a keyword that defines when the objects are to be constructed. It is particularly important to use the init_seg pragma in dynamic-link libraries (DLLs) or libraries requiring initialization.

The compiler option is reserved for Microsoft C run-time library initialization. Objects in this group are constructed first. The lib option is available for third-party class-library vendors initializations. Objects in this group are constructed after those marked as compiler but before any others. The user is available to any user. Objects in this group are constructed last. The seg-name allows explicit specification of the initialization segment. Objects in a user-specified seg-name are not implicitly constructed; however, the addresses of their initialization routines are placed in the segment named by seg-name.


  #pragma pointers_to_members

#pragma pointers_to_members( pointer-declaration, [[most-general-representation]] )

Specifies whether a pointer to a class member can be declared before its associated class definition and is used to control the pointer size and the code required to interpret the pointer. You can place a pointers_to_members pragma in your source file as an alternative to using /vmx options on the command line.

The pointer-declaration argument specifies whether you have declared a pointer to a member before or after the associated function definition. The pointer-declaration argument is one of the following two symbols.

Argument	Comments
full_generality	Generates safe, sometimes nonoptimal code. You use full_generality if any pointer to a member is declared after the associated class definition. This argument always uses the pointer representation specified by the most-general-representation argument. Equivalent to /vmg.
best_case	Generates safe, optimal code using best-case representation for all pointers to members. Requires defining the class before declaring a pointer to a member of the class. The default is best_case.
The most-general-representation argument specifies the smallest pointer representation that the compiler can safely use to reference any pointer to a member of a class in a translation unit. The argument can be one of the following.

Argument	Comments
single_inheritance	The most general representation is single-inheritance, pointer to a member function. Causes an error if the inheritance model of a class definition for which a pointer to a member is declared is ever either multiple or virtual.
multiple_inheritance	The most general representation is multiple-inheritance, pointer to a member function. Causes an error if the inheritance model of a class definition for which a pointer to a member is declared is virtual.
virtual_inheritance	The most general representation is virtual-inheritance, pointer to a member function. Never causes an error. This is the default argument when #pragma pointers_to_members(full_generality) is used.


  #pragma vtordisp

#pragma vtordisp( [[{on | off}]] )

Applicable only to code that uses virtual bases. If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or destructor for the derived class calls that function using a pointer to the virtual base class, the compiler may introduce additional hidden vtordisp fields into classes with virtual bases. The vtordisp pragma enables the addition of the hidden vtordisp construction/destruction displacement member. This pragma affects the layout of classes that follow the pragma. The /vd0 and /vd1 options specify the same behavior for complete modules. Specifying off suppresses the hidden vtordisp members. Specifying on, the default, enables them where they are necessary. Turn off vtordisps only if there is no possibility that the classs constructors and destructors do not call virtual functions virtually.

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )

The following pragmas are defined for both the C and C++ compilers:


  #pragma alloc_text

#pragma alloc_text( textsegment, function1, ... )

Names the segment where the specified function definitions are to reside. The pragma must occur between a function declarator and the function definition for the named functions.

16-Bit Specific

The recommended technique for functions in 16-bit targets is to use __based to specify the function location instead of alloc_text.

32-Bit Specific

Since function addressing using __based is not supported in 32-bit targets, specifying segment locations requires the use of the alloc_text pragma. Any name specified by textsegment that is longer than 8 characters will be truncated to 8 characters.


  #pragma auto_inline

#pragma auto_inline( [[{on | off}]] )

Any functions defined within the range where #pragma auto_line is off will not be considered as candidates for auto-inline expansion. To use this pragma, place it before and immediately after (not in) a function definition. This pragma takes effect at the first function definition after the pragma is seen. Pragma auto_inline does not apply to explicit inline functions.


  #pragma check_pointer

#pragma check_pointer( [[{on | off}]] )

Instructs the compiler to turn off pointer checking if off is specified, or to turn on pointer checking if on is specified. If turned on, this pragma causes the compiler to check every pointer dereference to make sure the pointer is not a null or out-of-range pointer. The check_pointer pragma is only available when the /f option is specified. If you do not specify either on or off, the effect of check_pointer is to reverse the current state of pointer checking. Far pointers are checked in programs targeted for MS-DOS but not in Windows-targeted programs. You can also specify pointer checking by using the /Zr option.

This pragma works function by function, not statement by statement. To use this pragma, place a pair of check_pointer pragmas around any function definition that contains pointer usage you want to check.


  #pragma check_stack

#pragma check_stack( [[{on | off}]] )

Instructs the compiler to turn off stack probes if off is specified or to turn on stack probes if on is specified. If no argument is given, stack probes are treated according to the default. This pragma takes effect at the first function defined after the pragma is seen. Stack probes are not a part of macros nor of functions that are generated inline.

16-Bit Specific

The default value of the check_stack pragma is on, unless /Gs was used to remove stack probes from function calls.

If you dont give an argument for the check_stack pragma, stack checking reverts to the behavior specified on the command line: enabled if the /Ge option is given, or disabled if it is not. The interaction of the check_stack pragma with the /Gs option is summarized in Table 2.1.

Table 2.1    Using the check_stack Pragma

Syntax	Compiled with /Gs option	Action
#pragma check_stack( )	Yes	Turns off stack checking for functions that follow
#pragma check_stack( )	No	Turns on stack checking for functions that follow
#pragma check_stack(on)	Yes or no	Turns on stack checking for functions that follow
#pragma check_stack(off)	Yes or no	Turns off stack checking for functions that follow


  #pragma code_seg

#pragma code_seg( [["segment-name"[[,"segment-class"]]]] )

Specifies a segment where functions are to be allocated, allowing the use of based allocation without rewriting code. The code_seg pragma specifies the default segment for functions. This is equivalent to using the /NT (name the code segment) compilation option. It is also equivalent to specifying functions as based. You can, optionally, specify the class as well as the segment name. For example,

#pragma code_seg( "MY_CODE", "CODE" )

causes functions following to be allocated in a segment called MY_CODE. The segment is given a CODE class.

Specifying the code_seg pragma with no arguments causes the compiler to allocate all following functions in the default code segment.

Note  There is no way to specify the segment class using based function allocation or the /NT compilation option.

Functions allocated using the /NT option or code_seg pragma do not retain any information about their location. However, functions allocated using the based function-allocation syntax retain that information in their external name.


  #pragma comment

#pragma comment( comment-type [[, commentstring]] )

Allows you to place a comment record in an object file or executable file. The comment-type is one of four predefined identifiers, described below, that specify the type of comment record. The optional commentstring is a string literal that provides additional information for some comment types. Because commentstring is a string literal, it obeys all the rules for string literals with respect to escape characters, embedded quotation marks ("), and concatenation.

compiler

Places the name and version number of the compiler in the object file. This comment record is ignored by the linker. If you supply a commentstring parameter for this record type, the compiler generates a warning error message.

exestr

Places commentstring in the object file. At link time, this string is placed in the executable file. The string is not loaded into memory when the executable file is loaded; however, it can be found with a program that finds printable strings in files. One use for this comment-record type is to embed a version number or similar information in an executable file.

lib

Places a library-search record in the object file. This comment type must be accompanied by a commentstring parameter containing the name (and possibly the path) of the library for which you want the linker to search. Since the library name precedes the default library-search records in the object file, the linker searches for this library just as if you had named it on the command line. You can place multiple library-search records in the same source file; each record appears in the object file in the same order in which it is encountered in the source file.

user

Places a general comment in the object file. The commentstring parameter contains the text of the comment. This comment record is ignored by the linker.


  #pragma data_seg

#pragma data_seg( [["segment-name"[[, "segment-class"]]]] )

Specifies the default segment for data.

32-Bit Specific

Any name specified by segment-name that is longer than 8 characters will be truncated to 8 characters.

Using the data_seg pragma is equivalent to specifying objects or pointers as based. You can, optionally, specify the class as well as the segment name. For example,

#pragma data_seg( "MY_DATA", "DATA" )

causes functions following to be allocated in a segment called MY_DATA. The segment is given a DATA class.

Specifying the data_seg pragma with no arguments causes the compiler to allocate all following data in the default data segment.

16-Bit Specific

Using this pragma is equivalent to using the /ND (name the data segment) compilation option. The /ND option is not supported by the 32-bit compiler.

Note  There is no way to specify the segment class using based function allocation or the /ND compilation option.

Data allocated using the /ND option or data_seg pragma does not retain any information about its location. However, data allocated using the based syntax retains that information in its external name.

If you compile with /Za, the data_seg pragma does not affect the allocation of uninitialized objects. This is true under /Za. However, under /Ze, the uninitialized objects also get allocated in the segment specified by the data_seg pragma.


  #pragma function

#pragma function( function1 [[ , function2, ...]] )

Specifies that calls to functions specified in the pragmas argument list be generated. If you use the intrinsic pragma (or /Oi) to tell the compiler to generate intrinsic functions (intrinsic functions are generated as inline code, not as function calls), you can use the function pragma to explicitly force a function call. Once a function pragma is seen, it takes effect at the first function definition containing a specified intrinsic function. The effect continues to the end of the source file or to the appearance of an intrinsic pragma specifying the same intrinsic function. The function pragma can be used only outside of a function  at the global level.

For lists of the functions that have intrinsic forms, see the description of the intrinsic pragma later in this section.


  #pragma hdrstop

#pragma hdrstop [[( "filename" )]]

Controls the way precompiled headers work. The filename is the name of the precompiled header file to use or create (depending on whether /Yu or /Yc is specified). If filename does not contain a path specification, the precompiled header file is assumed to be in the same directory as the source file. Any filename is ignored when /YX, the automatic precompiled header option, is specified. See Chapter 1 of Programming Techniques for more information about precompiled header files.

If a C or C++ file contains a hdrstop pragma when compiled with either /YX or /Yc, the compiler saves the state of the compilation up to the location of the pragma. The compiled state of any code that follows the pragma is not saved.

The hdrstop pragma cannot occur inside a header file. It must occur in the source file at the file level; that is, it cannot occur within any data or function declaration or definition.

Note  The hdrstop pragma is ignored unless either the /YX option is specified or the /Yu or /Yc option is specified without a filename.

Use filename to name the precompiled header file in which the compiled state is saved. A space between hdrstop and filename is optional. The filename specified in the hdrstop pragma is a string and is therefore subject to the constraints of any C or C++ string. In particular, you must enclose it in quotation marks as shown in the following example:

#pragma hdrstop( "c:\c700\include\myinc.pch" )

If no filename is given with the hdrstop pragma, the name of the precompiled header file is derived from the base name of the source file with a .PCH extension.


  #pragma inline_depth

#pragma inline_depth( [[0... 255]] )

Controls the number of times inline expansion can occur by controlling the number of times that a series of function calls can be expanded (from 0 to 255 times). Use this pragma to control functions marked as inline and __inline or functions that the compiler automatically expands under the /Ob2 option. Use of this pragma requires an /Ob command-line option setting of either 1 or 2. This pragma takes effect at the first function call after the pragma is seen. Its default setting is 8. Once the depth set by this pragma is exceeded, calls are made.


  #pragma inline_recursion

#pragma inline_recursion( [[{on | off}]] )

Controls the inline expansion of direct or mutually recursive function calls. Use this pragma to control functions marked as inline and __inline or functions that the compiler automatically expands under the /Ob2 option. Use of this pragma requires an /Ob command-line option setting of either 1 or 2. The default state for inline_recursion is off. This pragma takes effect at the first function call after the pragma is seen and does not affect the definition of the function.


  #pragma intrinsic

#pragma intrinsic( function1 [[, function2, ...]] )

Specifies that calls to functions specified in the pragmas argument list are intrinsic. The compiler generates intrinsic functions as inline code, not as function calls. The library functions with intrinsic forms are listed below. Once an intrinsic pragma is seen, it takes effect at the first function definition containing a specified intrinsic function. The effect continues to the end of the source file or to the appearance of a function pragma specifying the same intrinsic function. The intrinsic pragma can be used only outside of a function definition  at the global level.

16-Bit Specific

This pragma cannot be used with /f.

The following functions have intrinsic forms:

_alloca	_lrotr	_strset	memset
_disable	_outp	abs	strcat
_enable	_outpw	fabs	strcmp
_inp	_rotl	labs	strcpy
_inpw	_rotr	memcmp	strlen
_lrotl	_setjmp	memcpy
16-Bit Specific

The following functions have intrinsic forms but are only supported for 16-bit targets:

_fmemcmp	_fmemset	_fstrcmp	_fstrlen
_fmemcpy	_fstrcat	_fstrcpy	_fstrset
The following floating-point functions do not have true intrinsic forms; they do have versions that pass arguments directly to the floating-point chip instead of pushing them onto the argument stack:

acos	cos	log	sinh
asin	cosh	log10	sqrt
atan	exp	pow	tan
atan2	fmod	sin	tanh
16-Bit Specific

The following floating-point functions do not have true intrinsic forms; they do have versions that pass arguments directly to the floating-point chip instead of pushing them onto the argument stack. These are supported only for 16-bit targets:

acosl	ceill	floorl	sinl
asinl	cosl	fmodl	sinhl
atanl	coshl	logl	sqrtl
atan2l	expl	log10l	tanl
ceil	floor	powl	tanhl


  #pragma linesize

#pragma linesize( [[numchars]] )

Specifies the number of characters per line in the source listing. The optional parameter numchars is an integer constant in the range 79  132. If numchars is absent, the compiler uses the value specified in the /Sl option or, if that option is absent, the default value of 79 characters per line. The linesize pragma takes effect the line after it appears.


  #pragma message

#pragma message( messagestring )

Sends a string literal to the standard output without terminating the compilation. The messagestring parameter can be a macro that expands to a string literal. You can concatenate such macros with string literals in any combination.


  #pragma native_caller

#pragma native_caller( [[{on | off}]] )

Controls the removal of native-code entry points from functions compiled into p-code on a function-by-function basis. This pragma takes on or off as an argument. For example, to turn off native-code entry point generation for a p-code function, enter the following line prior to the beginning of the function:

#pragma native_caller (off)

Then turn the native_caller pragma back on after the end of the function by entering

#pragma native_caller (on)


  #pragma optimize

#pragma optimize( "[[optimization-list]]", {on | off} )

Specifies optimizations to be performed on a function-by-function basis. The optimize pragma must appear outside a function and takes effect at the first function defined after the pragma is seen. The on and off arguments turn options specified in the optimization-list on or off.

16-Bit Specific

The optimization-list can be zero or more of the parameters shown in Table 2.2.

Table 2.2    Parameters of the optimize Pragma

Parameter(s)	Type of optimization
a	Assume no aliasing
c	Optimize local common sub expressions
e	Allow compiler-determined enregistration
f	Turn on and off p-code quoting
g	Optimize global common sub expressions
l	Optimize loops
n	Turn off potentially unsafe loop optimizations
o	Control post-code-generation optimizing
p	Improve floating-point consistency
q	Turn on p-code optimization
r	Specify common function-exit sequence
s or t	Specify short or fast sequences of machine code
v	Specify type of  frame sorting
w	Assume no aliasing across function calls
x	Use maximization optimizations
z	Turn on maximum loop optimizations
Using the optimize pragma with the empty string (" ") is a special form of the directive. It either turns off all optimizations, except p-code, or restores them to their original (or default) settings.

Note  Turning on p-code, either with the /Oq command line option or by passing q to the optimize pragma, disables all other optimizations.

32-Bit Specific

The optimization-list can be zero or more of the parameters shown in Table 2.3.

Table 2.3    Parameters of the optimize Pragma

Parameter(s)	Type of optimization
a	Assume no aliasing
g	Enable global optimizations
n	Disabling of unsafe optimizations
p	Improve floating-point consistency
s or t	Specify short or fast sequences of machine code
w	Assume no aliasing across function calls
x	Use maximum optimization
Using the optimize pragma with the empty string (" ") is a special form of the directive. It either turns off all optimizations or restores them to their original (or default) settings.


  #pragma pack

#pragma pack( [[ n]] )

Specifies packing alignment for structure and union members. Whereas the packing alignment of structures and unions is set for an entire translation unit by the /Zp option, the packing alignment is set at the data-declaration level by the pack pragma. The pragma takes effect at the first structure or union declaration after the pragma is seen; the pragma has no effect on definitions.

When you give the #pragma pack(n), where n is 1, 2, 4, 8, or 16, each structure or union member after the first member is stored on n-byte boundaries. If you use the pack pragma without an argument, structure members are packed to the value specified by /Zp.

16-Bit Specific

For 16-bit targets, the default packing alignment is 2.

32-Bit Specific

For 32-bit targets, the compiler also supports an enhanced syntax for #pragma pack. This syntax allows you to combine program components into a single translation unit if the different components use pack pragmas to specify different packing alignments. The syntax is as follows:


#pragma pack with Push Argument
  #pragma pack

#pragma pack( [[ [[ { push | pop}, ]] [[  identifier,  ]]]] [[ n]] )

Each occurrence of a pack pragma with a push argument stores the current packing alignment on an internal compiler stack. The pragmas argument list is read from left to right. If you use push, the current packing value is stored. If you provide a value for n, that value becomes the new packing value. If you specify an identifier, a name of your choosing, the identifier is associated with the new packing value.

Each occurrence of a pack pragma with a pop argument retrieves the value at the top of an internal compiler stack and makes that value the new packing alignment. If you use pop and the internal compiler stack is empty, the alignment value is that set from the command-line and a warning is issued. If you use pop and specify a value for n, that value becomes the new packing value. If you use pop and specify an identifier, all values stored on the stack are removed from the stack until a matching identifier is found. The packing value associated with the identifier is also removed from the stack and the packing value that existed just before the identifier was pushed becomes the new packing value. If no matching identifier is found, the packing value set from the command line is used and a level-one warning is issued. For 32-bit targets, the default packing alignment is 8.

The new, enhanced functionality of the pack pragma allows you to write header files that ensure that packing values are the same before and after the header file is encountered:

/* File name: include1.h

*/

#pragma pack( push, enter_include1 )

/* Your include-file code ... */

#pragma pack( pop, enter_include1 )

/* End of include1.h */

In the previous example, the current pack value is associated with the identifier enter_include1 and pushed, remembered, on entry to the header file. The pack pragma at the end of the header file removes all intervening pack values that may have occurred in the header file and removes the pack value associated with enter_include1. The header file thus ensures that the pack value is the same before and after the header file.

The new functionality also allows you to use code, such as header files, that uses pack pragmas to set packing alignments that differ from the packing value set in your code:

#pragma pack( push, before_include1 )

#include include1.h

#pragma pack( pop, before_include1 )

In the previous example, your code is protected from any changes to the packing value that might occur in include.h.


  #pragma page

#pragma page( [[pages]] )

Tells the compiler to generate formfeeds in the source listing at the line where it appears. The page pragma generates one or more formfeeds (page eject) in the source listing (created with /Fs) at the place where the pragma appears. The number of formfeeds is specified by pages. Legal values are 1  127, with the default being 1.


  #pragma pagesize

#pragma pagesize( [[numlines]]  )

Sets the number of lines per page in the source listing. The optional numlines parameter is an integer constant in the range 15  255 that specifies the number of lines that you want each page of the source listing to have. If numlines is absent, the pragma sets the page size to the number of lines specified in the /Sp option or, if that option is absent, to a default value of 63 lines.


  #pragma setlocale

#pragma setlocale( locale-string )

Defines the locale (country and language) to be used when translating wide-character constants and string literals. Since the algorithm for converting multibyte characters to wide characters may vary by locale or the compilation may take place in a different locale from where an executable will be run, this pragma provides a way to specify the target locale, at compiler time. This guarantees that the wide-character strings will be stored in the correct format. The locale-string currently supported for 16-bit targets is "C". The "C" locale maps each character in the string to its value as a wchar_t (unsigned short).


  #pragma skip

#pragma skip([[numlines]])

Skips the specified number of lines in the source listing. The skip pragma generates a newline character (carriage return  linefeed) in the source listing at the point where the pragma appears. The optional numlines parameter is an integer constant in the range 1  127 that specifies the number of lines to skip. If this parameter is absent, the skip pragma defaults to one line.


  #pragma subtitle

#pragma subtitle( "subtitlename" )

Specifies a subtitle for the source listing. The subtitlename parameter can be a macro that expands to a string literal. You can concatenate such macros with string literals in any combination. A null subtitlename ("") erases any previous subtitle.


  #pragma title

#pragma title( "titlename" )

Specifies a title for the source listing. The title appears in the upper-left corner of each page of the listing. The titlename parameter can be a macro that expands to a string literal. You can concatenate such macros with string literals in any combination. A null titlename ("") erases any previous title.


  #pragma warning

#pragma warning( warning-specifier : warning-number-list )

The warning pragma allows selective modification of the behavior of compiler warning messages.

The warning-specifier can be one of the following:

warning-specifier	Meaning
once	Cause the message(s) to be displayed only once
default	Cause the compilers default behavior to apply to the message(s)
1, 2, 3, 4	Force the warning message(s) to have the specified warning level
disable	Cause the compiler not to issue the warning message(s)
error	Cause the compiler to report the warnings as error
The warning-number-list can contain any warning numbers. Multiple options can be specified in the same pragma directive as follows:

#pragma warning( disable : 4507 34; once : 4385; error : 164 )

This is functionally equivalent to:

#pragma warning( disable : 4507 34 )  // Disable warning messages
                                      //  4507 and 34.
#pragma warning( once : 4385 )        // Issue warning 4385
                                      //  only once.
#pragma warning( error : 164 )        // Report warning 164
                                      //  as an error.

For warning numbers greater than 4699, those associated with code generation, the warning pragma has affect only when placed outside of function definitions. The pragma is ignored if it specifies a number greater than 4699 and is used inside of a function. The following example illustrates the correct placement of warning pragmas to disable, and then restore, the generation of a code-generation warning message:

int a;

#pragma warning( disable : 4705 )

void func()

{

    a;

}

#pragma warning( default : 4705 )


  Appendix A  Phases of Translation

C and C++ programs consist of one or more "source files," each of which contain some of the text of the program. A source file, together with its "include files" (files that are included using the #include preprocessor directive) but not including sections of code removed by conditional-compilation directives such as #if, is called a "translation unit."

Source files can be translated at different times — in fact, it is common to translate only out-of-date files. The translated translation units can be kept either in separate object files or in object-code libraries. These separate translation units are then linked to form an executable program or a dynamic-link library (DLL).

Translation units can communicate using:

•	Calls to functions that have external linkage.

•	Calls to class member functions that have external linkage.

•	Direct modification of objects that have external linkage.

•	Direct modification of files.

•	Interprocess communication (for Microsoft Windows applications only).

The following list describes the phases in which the compiler translates files:

Character mapping

Characters in the source file are mapped to the internal source representation. Trigraph sequences are converted to single-character internal representation in this phase.

Line splicing

All lines ending in a backslash (\) and immediately followed by a newline character are joined with the next line in the source file, forming logical lines from the physical lines. Unless it is empty, a source file must end in a newline character that is not preceded by a backslash.

Tokenization

The source file is broken into preprocessing tokens and white-space characters. Comments in the source file are replaced with one space character each. Newline characters are retained.

Preprocessing

Preprocessing directives are executed and macros are expanded into the source file. The #include statement invokes translation starting with the preceding three translation steps on any included text.

Character-set mapping

All source-character-set members and escape sequences are converted to their equivalents in the execution-character set. For Microsoft C and C++, both the source and the execution character sets are ASCII.

String concatenation

All adjacent string and wide-string literals are concatenated. For example, "String " "concatenation" becomes "String concatenation".

Translation

All tokens are analyzed syntactically and semantically; these tokens are converted into object code.

Linkage

All external references are resolved to create an executable program or a dynamic-link library.

The compiler issues warnings or errors during phases of translation in which it encounters syntax errors.

The linker resolves all external references and creates an executable program or DLL by combining one or more separately processed translation units along with standard libraries.


Appendix A  Grammar Summary
  Appendix B  Grammar Summary

This appendix describes the formal grammar of the preprocessor. It covers the syntax of preprocessing directives and operators discussed in Chapters 1 and 2.


  Definitions

Terminals are endpoints in a syntax definition. No other resolution is possible. Terminals include the set of reserved words and user-defined identifiers.

Nonterminals are placeholders in the syntax and most are defined elsewhere in this syntax summary. Definitions can be recursive. The following nonterminals are defined in the C++ Language Reference:

constant, constant expression, digit, identifier, keyword, operator, punctuator

An optional component is indicated by the subscripted  (opt) . For example,

{ expression (opt) }

indicates an optional expression enclosed in curly braces.


  Conventions

The conventions use different font attributes for different components of the syntax. The symbols and fonts are as follows:

Attribute	Description
nonterminal	Italic type indicates nonterminals.
#include	Terminals in bold type are literal reserved words and symbols that must be entered as shown. Characters in this context are always case sensitive.
opt	Nonterminals followed by opt are always optional.
default typeface	Characters in the set described or listed in this typeface can be used as terminals in statements.
A colon (:) following a nonterminal introduces its definition. Alternative definitions are listed on separate lines.


  Preprocessor Grammar

#define identifier  token-string

#define identifier  (  identifier  ,  ...  ,  identifier  )  token-string

#include "filename"

#include <filename>

#line  digit-sequence  "filename" (opt)

#undef  identifier

conditional:
if-part  elif-parts (opt)   else-part (opt)   endif-line

if-part:
if-line text

if-line:
#if  constant-expression
#ifdef  identifier
#ifndef  identifier

elif-parts:
elif-line  text
elif-parts  elif-line  text

elif-line:
#elif constant-expression

else-part:
else-line text

else-line:
#else

endif-line:
#endif

digit-sequence:
digit
digit-sequence digit

token-string:
String of tokens

token:
keyword
identifier
constant
operator
punctuator

filename:
Legal MS-DOS filename

text:
Any sequence of text

Note  The expansions of the following nonterminals are in the C++ Language Reference: constant, constant expression, digit, identifier, keyword, operator, and punctuator.