C Training Material
C Training Material
(Note: This document does not cover C/C++ or SDK & VC++ in detail. This is only a document made to give one enough no!ledge to "roceed !ith #indo!s $rogramming !ith C/C++ and then C%&.The contents o' this document are retrived 'rom various (oo s and !e( "ages and modi'ied to suit the re)uirement.*
Contents
+ntroduction to the $rogramming ,anguage C -istory %' C Nature C as a second generation and third generation ,anguage
.sage ,oo ing at C 'or the /irst Time Com"iling 01uilding and #arning &essages Ste"s to Create a C a""lication Some Theory a(out Com"iling and ,in ing $rinting moe than one line Data declaration Some comments a(out Comments The 2rammer o' C 34ercise 5 'e! de'initions and Terms /unctions %%$S (%(6ect %riented $rograming Systems* $rocedural0 Structured and %(6ect %riented $romming %(6ect Class 3nca"sulation 5(straction #hy C++ 5 com"arison o' C and C++ +ntoduction #hy is C++ (etter than C Streams 3sca"e Se)uences #hat is a $ointer The +ndirection and 5ddress%' %"erators /unctions Structures 3numerations Class 3nca"sulation +nline /unctions $olymor"hism +nheritance Dynamic ,in ing 5$+s and &emory &odels Threading #indo!s $rograming in C (SDK* 5n +ntroducton to .nicode #ide Characters and #indo!s #indo!s and &essages 5 #indo! o' %ne7s %!n The #indo!s $rogramming -urdles 5n 34ercise in Te4t %ut"ut $ainting and 8e"ainting The #&9$5+NT &essage 5n +ntroduction to 2D+ 1asic Dra!ing The Structure o' 2D+ The Device Conte4t
=hrs
=hrs =hrs
>hrs
#indo!s $rograming in C (SDK* 5n +ntroducton to .nicode #ide Characters and #indo!s #indo!s and &essages 5 #indo! o' %ne7s %!n The #indo!s $rogramming -urdles 5n 34ercise in Te4t %ut"ut $ainting and 8e"ainting The #&9$5+NT &essage 5n +ntroduction to 2D+ 1asic Dra!ing The Structure o' 2D+ The Device Conte4t Dra!ing Dots and ,ines Child #indo! Controls
MFC COM
"rograms. #ithin these "atterns are0 (elieve it or not0 vast "ossi(ilities. The "attern 'or the sim"le 15S+C "rogram is: $8+NT Iyour9te4t9hereI -ere +Hm introducing a convention +Hll use throughout the (oo : !ords in italics re"resent something that you "rovide. Nou could ty"e any com(ination o' characters you !anted !here your9te4t9here is indicated. The C version is: main (* K "rint'(Iyour9te4t9hereI*L M So0 'or C0 another e4am"le that 'ollo!s this "attern is: main(* K "rint'(I$rogramming0 it sounds li e 'un.I*L M #hen you ty"e in this short "rogram0 you should (e care'ul a(out the 'ollo!ing matters: O Ca"italiPation counts. %r rather0 in this case0 lac o' ca"italiPation counts. 15S+C "rogrammers0 'or some reason no one understands0 o'ten leave the C5$S ,%CK ey on0 (ut it !ould ma e no di''erence i' they al!ays le't ca"italiPation o''. #ith C0 youHll )uic ly 'ind that ty"ing Q$8+NT/R or Q$rint'R instead o' Q"rint'R results in an un'riendly error message. O $unctuation also counts. The 'irst mista e that a!aits you i' youHre coming 'rom 15S+C or /%8T85N is to 'orget the semicolon (L* at the end o' a statement. 5t least C is sim"ler in this res"ect than $ascal: you al!ays terminate a statement !ith a semicolonL you donHt have to guess !hether or not to use one. -o!ever0 this rule doesnHt mean that you "ut one a'ter the terminating (race (L*. (#eHll s"end more time !ith semicolons and statements later0 in case youHre thirsting 'or more no!ledge on these esoteric su(6ects.* O 8emem(er also that dou(le:)uotation mar s (I*0 not single0 are re)uired. O S"acing does not count. Nou can "ut any num(er o' e4tra s"aces around the "arentheses and (races0 i' you !ant0 or even ty"e everything on the same line. %' course0 you canHt "ut s"aces in the middle o' individual !ords0 turning Q"rint'R into Q"r int '0R 'or e4am"le. 5nd s"acing matters to some e4tent in the te4t inside the )uotation mar s0 (ecause the te4t you enter there !ill (e "rinted as you entered it0 letter 'or letter. -ereHs the "rogram one more time0 !ith slightly di''erent s"acing: main( * K "rint'( I$rogramming0 it sounds li e 'un.I *L M +' all goes !ell !hen you enter and run the "rogram0 it !ill "rint the te4t string sans )uotation mar s: $rogramming0 it sounds li e 'un.
5ssuming that this !or s0 you might try redoing the "rogram !ith di''erent strings. +' you have "ro(lems0 revie! the "receding "aragra"hs 'or "ossi(le mista es in entering the "rogram. Nou also might need to ma e sure that youHre using your com"iler to correctly (uild an a""lication.
+' youHre using &icroso't Visual C++0 !hich + re'er to (ecause it is one o' the standard com"ilers in use today0 the ste"s you ta e are sho!n in the list that 'ollo!s. Nou !ould 'ollo! roughly the same ste"s !ith other com"ilers0 although the menus and e4act command names may (e di''erent. Note that although QC++R is in the "roduct name0 the com"iler is "er'ectly ca"a(le o' acting as a straight C com"ilerS6ust ma e sure you give your source 'iles a .C e4tension0 and the com"iler !ill use the rules o' the C language rather than C++. + !ould e4"ect other C/C++ "ac ages to (ehave in a similar !ay. 5nother thing + recommend0 i' you are using Visual C++ in the #indo!s environment0 is to select Console a""lication (i' running #indo!s NT* or @uic #in (i' running in the =C:(it environment* as the "ro6ect ty"e. 1oth o' these ty"es o' a""lications "rint directly to the screen !ithout 'orcing you to !orry a(out all the e4tra details o' managing a #indo!s a""lication. (ThatHs a su(6ect 'or another (oo .* The ste"s 'or com"iling and lin ing are: =. 5'ter entering a "rogram0 save it as a source 'ile !ith a .C e4tension ('or e4am"le0 -+.C*. ;. Create a ne! "ro6ect and select Console or @uic #in as the a""lication ty"e. 5dd the source 'ile (-+.C* to the "ro6ect. G. /rom the $ro6ect menu0 choose 1uild. >. /rom the $ro6ect menu0 choose 8un. +' you got stuc on ste" G0 you encountered either a com"iler error or a lin er error or (oth. 5 com"iler error indicates that something !as !rong in the !ay you ty"ed in the "rogramL "erha"s you 'orgot to ty"e in the semicolon (L* or one o' the )uotation mar s (I*. 5 lin er error0 at this "oint0 "ro(a(ly indicates that something in the develo"ment environment !as not set u" correctly. Chec your manual to ma e sure that you installed the "roduct correctly. +'0 ho!ever0 you ty"ed in the "rogram and 'ollo!ed all the ste"s correctly0 instead o' error messages you "ro(a(ly received a cou"le o' !arning messages. 5t this "oint0 donHt "anic i' you got !arning messagesL thereHs a (ig di''erence (et!een !arnings and errors. #arning messages donHt sto" you. 5s long as you got only !arning messages0 you can run the "rogram.
1ut you may !ant to get rid o' the !arning messages any!ay0 and 'or a good reason: !arning messages are there to alert you that something une4"ected may (e ha""ening. Not much can go !rong !ith this "articular "rogram0 (ut in a larger "rogram0 a !arning can easily catch the source o' a "otential error. Nou may as !ell get in the ha(it o' trying to eliminate causes o' !arnings. +n the !orld o' "ro'essional develo"ment0 testers donHt certi'y that a (uild is correct unless it com"letes !ith Pero !arnings and Pero errors. +' youHre running Visual C++0 version =.F0 !ith the standard environment settings0 you got these !arnings: !arning C>F=G: 7"rint'7 unde'inedL assuming e4tern returning int !arning C>FG?: 7main7 : no return value The 'irst !arning message tells you that the "rint' 'unction has no return value0 so the com"iler assumes an integer (int* return value (y de'ault. T!o things a(out this 'act may (e sur"rising. /irst0 C has no conce"t o' a statement or su(routine the !ay that 15S+C and /%8T85N do. 5ll routines are 'unctions0 and every 'unction returns a value. +n this "rogram0 "rint' is a 'unction !hose return value is ignored. (+n C0 you can al!ays ignore return values i' you choose.* The 'ollo!ing directive0 added to the (eginning o' the "rogram0 clears u" the "ro(lem: Tinclude Ustdio.hV The Tinclude directive causes the com"iler to read in a 'ile that "ro"erly declares "rint'. 5t this "oint0 you may (e "rotesting that it shouldnHt (e necessary to declare such a 'unction (e'ore using it. 5'ter all0 it isnHt necessary !ith the $8+NT statement in 15S+C. 1ut C is di''erent. The num(er o' ey!ords in C is e"t )uite small0 and "rint' is not a ey!ordL itHs 6ust another 'unction !ith no s"ecial status. 5s it ha""ens0 "rint' is e4tremely use'ul and is there'ore "rovided in every standard C li(rary. 1ut you could 'reely re!rite or rede'ine "rint' i' you choose to0 and the com"iler itsel' doesnHt no! anything a(out it. This as"ect o' C may (e a slight inconvenience 'or no!0 (ut it ultimately ma es C much more com"act and 'le4i(le. /or all these reasons0 the com"iler e4"ects you to declare "rint' (e'ore you use it. 5s mentioned0 the stdio.h header 'ile ta es care o' this declaration. N%T3: 5 directive is not )uite the same thing as a statement0 although they may loo similar. %ne critical di''erence is that a directive does not end !ith a semicolon (L*. There is e4actly one 'unction !ith s"ecial status to C itsel': the main 'unction. Nou must have a main 'unction some!here 'or your "rogram to actually do anything0 (ut e4ce"t 'or that0 main o(eys all the (asic C "rinci"les a""lying to 'unctions. So main should return a value too0 shouldnHt itW This is true0 and it e4"lains the second !arning: main has no return value. The !ay to clear u" this "ro(lem is to "recede main !ith the ey!ord void0 !hich tells the com"iler not to e4"ect the 'unction to return a value: void main(* K 3arlier + stated that every 'unction must return a value0 (ut void 'unctions are the e4ce"tion. The com"lete !arning:'ree "rogram is no!: Tinclude Ustdio.hV
code. The resulting "rogram runs 'aster and ta es u" less s"ace. NouHll have to !ait !hile the com"iler translates your "rogram0 (ut the !ait is 'or a good reason. The second chic en:and:egg "ro(lem is this: ho! can anyone create a translator in the 'irst "lace0 i' no one ever !rites directly in machine languageW This "ro(lem is similar to the 'ollo!ing "ro(lem in economics: i' nothing can (e (uilt 'rom scratch and i' every tool re)uires the e4istence o' another tool in order to (e (uilt0 then ho! did our industrial society ever come to e4istW This is the 'amiliar 1ootstra" "ro(lem: ho! do you get startedW 1ut the +ndustrial 8evolution did ha""en0 and a similar revolution has (een going on !ith com"uters. 3ssentially0 !henever a ne! chi" is introduced0 the manu'acturer ma es sure that a rudimentary assem(ler and systems so't!are are availa(le. This initial software may be generated on another previously existing computer. (This is called cross platform development.! .ltimately0 you can trace the lineage o' all so't!are (ac to a time !hen "eo"le really did !rite in machine code and 'ed it into a dinosaur in the 'orm o' "unch cards. The 'inal stage in (uilding a "rogram is usually lin ing. ,in ing is the "rocess o' (ringing together your "rogram module !ith code 'rom li(rariesL this is !hat ma es it "ossi(le 'or you to call the "rint' 'unction. +n addition0 i' you (rea your "rogram into multi"le modulesSes"ecially use'ul 'or multi"rogrammer "ro6ectsSthe "rocess o' lin ing connects these modules and com"letes 'unction calls (et!een the modules. ,in er errors tend to occur !hen a 'unction re'erred to in one module is not de'ined any!here else or is de'ined in a !ay that is inconsistent !ith ho! it !as used. %'ten0 you clear u" a lin er error (y ma ing sure that a li(rary is in the right directory or that the environment varia(les are correctly set. The (ottom line is that a'ter you !rite a "rogram0 there is a !ait !hile the com"iler e4amines your "rogram 'or correctness and translates it. 1ut there are good reasons 'or having to !ait. No! itHs time to get (ac to creating "rograms.
printf("Last line"); %ne thing that may sur"rise you is that (ecause Yn is a character li e any other0 you can 'reely em(ed it inside a te4t string. The 'ollo!ing "rogram "rints the same results: #include <stdio.h> void main() { printf("Line1\nLine2\nLast line"); Nou can even dou(le:s"ace0 i' you !ant to: #include <stdio.h> void main() { printf("Line1\n\nLine2\n\nLast line"); +t should (e clear !hat is going on at this "oint. 5s the "rint' 'unction reads each character that is not a (ac slash0 it out"uts the character to the terminal as is. +'0 ho!ever0 it reads a (ac slash0 it inter"ets the ne4t character as a s"ecial character. #hen an QnR 'ollo!s the (ac slash0 it causes out"ut to start on a ne! line. (5nother !ay o' saying this is to say that "rint' generates a carriage return.* +' there is te4t remaining in the string0 "rint' continues reading characters normally. 1y the !ay0 itHs common "ractice to terminate every lineSeven the lastS!ith a ne!line (Yn*0 unless you no! that the ne4t in"ut or out"ut is to continue on the same line. #ith this a""roach0 the 'irst e4am"le in this section !ould (e re!ritten as: #include <stdio.h> void main (){ printf("Line 1\n"); printf("Line 2\n"); printf("Last line\n");
These statements0 li e any other C statements0 are each terminated (y a semicolon (L*. The ey!ords do$/le and int s"eci'y data ty"esSdou(le:"recision 'loating "oint and integer0 res"ectively. (The di''erence (et!een these ty"es is that the com"uter can mani"ulate integers much more e''iciently0 (ut only 'loating:"oint varia(les can store 'ractional )uantities.* The names 40 count0 i0 60 and em"loyee9num in the "receding e4am"le all (ecome the names o' varia(les created (y the de'inition. 34ce"t 'or 40 all the varia(les are integers. 5n e4am"le "rogram should hel" clari'y this. #include <stdio.h> void main(){ int i# $; i ' 1; $ ' 2; printf("(he sum of i and $ is )d"# i * $); This e4am"le introduces a very use'ul 'eature o' "rint': 'ormatted num(er out"ut. The 'irst argument to "rint' is the 'ormat string: IThe sum o' i and 6 is ZdI This is a )uoted string o' te4t in !hich most characters are "rinted literally (ut some se)uences o' characters have s"ecial meaning. T!o:character se)uences starting !ith a (ac slash (Y* are one ind o' s"ecial se)uence0 as !eHve seen. 5nother ind o' s"ecial se)uence consists o' those starting !ith the "ercent sign (Z*. Such se)uences "rint num(ers. S"eci'ically0 the meaning o' Zd is0 Q$rint the integer value o' the ne4t argument.R +n this case0 that argument is the result calculated (y adding the value o' i to the value o' 6: i+6 The "ractice o' com"uter languages varies 'rom standard 3nglish here. Note the "lacement o' the comma (0* in the com"lete statement: "rint'(IThe sum o' i and 6 is ZdI0 i + 6*L The comma must a""ear a'ter0 not (e'ore0 the second )uotation mar (I*. The role o' the comma is to se"arate the t!o arguments0 and it must a""ear between those arguments. +n this case0 at least0 the rule im"osed (y the "rogramming language is a good deal more logical than 3nglish is. Nou donHt "lace the comma inside the )uotation mar s unless you intend 'or it to (e "rinted. Commas can (e used in (oth !ays0 o' course. Nou could "lace a comma inside the )uotation mar s (ecause you actually did !ant to "rint it. NouHd still need to "lace another comma outside the )uotation mar s so that the arguments !ould (e se"arated. Nou can e4"eriment !ith much more interesting calculations here0 such as the 'ollo!ing 'loating:"oint calculation. Note that almost all 'loating:"oint calculations assume that data ty"es and return values are do$/le (dou(le "recision*0 !hich "rovides greater accuracy than single "recision (float*. 5nother thing to ee" in mind is that to "rint a 'loating:"oint value0 you must use Z'0 not Zd. /or e4am"le: Tinclude Ustdio.hV Tinclude Umath.hV void main(*K dou(le a [ G.FL dou(le ( [ >.FL
dou(le cL c [ s)rt(a \ a + ( \ (*L "rint'(IThe hy"otenuse [ Z'I0 c*L M This e4am"le introduces a cou"le o' ne! 'eatures !orth commenting on. /irst0 the "rogram calls another 'unction0 s)rt. ,i e "rint'0 s)rt is "rovided (y the standard li(rary. The math.h header 'ile "ro"erly declares the s)rt 'unction0 so math.h is included at the (eginning o' the "rogram. +' s)rt is not declared0 C assumes that the 'unction returns an integer value0 !hich in 'act it does not (li e most math 'unctions0 s)rt returns a dou(le:"recision 'loating:"oint result*. This !ould (e a serious "ro(lem (ecause it !ould cause the com"uter to ma e a mista e a(out !hat ind o' data to "ass.
)O%01 The s)rt 'unction ta es the s)uare root o' its argument0 (ut C "rogrammers a''ectionately re'er to this 'unction as the Qs)uirtR 'unction.
+tHs al!ays good to declare all 'unctions (e'ore using them. +' the 'unction is 'rom the standard C li(rary0 thereHs a header 'ile availa(le !ith the a""ro"riate declaration. Documentation on li(rary 'unctions indicates !hich header 'ile to include. 5nother 'eature introduced here is the use o' de'inition and assignment o' values in the same statement. This assignment is actually initialization0 and it has some im"ortant restrictions: dou(le a [ G.FL dou(le ( [ >.FL dou(le cL The varia(les a and ( are "ro"erly intialiPed !ith constant values. #hen you com(ine varia(le de'inition !ith the e)ual sign ([* this !ay0 the value assigned must (e a constantL the com"iler must (e a(le to determine !hat this value is at the time the com"iler reads the "rogram. The ne4t statement0 !hich assigns a value to the varia(le c0 cannot (e com(ined !ith a declaration0 (ecause the value on the right is not a constant: c [ s)rt(a \ a + ( \ (*L This may seem li e a lot o' rules0 (ut it stems 'rom the 'act that the C language reuses o"erators very e''iciently. #hen you de'ine a varia(le (such as a0 (0 or c*0 you can give it an initial value0 (ut ma e sure it is a constant. The use o' the e)ual sign ([* in other inds o' statements is much more 'le4i(le. Nou can "lace any varia(le on the le't side and any valid e4"ression on the right. The "revious line o' code0 !hich calcalates the value o' c0 is an e4am"le.
gro!s in com"le4ity0 you may not understand the "ur"ose o' a declaration or statement !ritten earlier0 even i' you !rote it yoursel'. The solution to this "ro(lem is to use a healthy dose o' comments and to say things that !ill (e hel"'ul 'or someone loo ing at the code. C comments consist o' te4t (et!een the sym(ols /\ and \/. This te4t may occur on a single line or can s"an multi"le lines. /or e4am"le0 the last e4am"le in the "receding section could "ro'ita(ly (e commented as 'ollo!s: Tinclude Ustdio.hV Tinclude Umath.hV void main(*K /\ Declare a0 (0 and c as three sides o' a triangle0 in !hich a and ( are G and > units long. \/ dou(le a [ G.FL dou(le ( [ >.FL dou(le cL /\/ind hy"otenuse and "rint result. \/ c [ s)rt(a \ a + ( \ (*L "rint'(IThe hy"otenuse [ Z'I0 c*L M 5gain0 the com"iler ignores all the te4t (et!een /\ and \/. The e4act !ording and s"elling are there'ore unim"ortant.
%he 6rammar of C
$rogramming0 i' you thin a(out it0 is all a(out "atterns. 5 "rogramming:language grammar is a set o' "atterns 'or "utting !ords and sym(ols together to 'orm meaning'ul actions. #hen you understand the "atterns !ell enough0 you can use them to get the com"uter to do anything you !ant0 !ithin limitations. 1ut !ithout some ind o' easy introduction to C0 loo ing at a "ure0 com"rehensive summary o' CHs grammar !ould (e over!helming. /or this reason0 !eHll start !ith "atterns around !hich you can (uild sim"le "rograms and then gradually add to their com"le4ity. The sim"lest "rograms 'ollo! this "attern: include&directives void main () { data_declaration_statements executable_statements include_directives use the 7incl$de ey!ord to read header 'iles (the effect is the same as if you typed the entire file right into your program code*. 5s mentioned earlier0 such header 'iles are necessary (ecause C doesnHt no! anything a(out li(rary 'unctions. +t doesnHt no!0 'or e4am"le0 !hether the s)uare root 'unction (s)rt* returns an integer or a 'loating:"oint result. Nor does it no! ho! many arguments to e4"ect. The header 'iles0 such as stdio.h and math.h0 "rovide this in'ormation. 34am"les o' 7incl$de directives are: #include <stdio.h> #include <math.h>
#include <strin+.h> #hen you use a li(rary 'unction0 such as "rint'0 consult C standard:li(rary documentation to determine the corres"onding header 'ile to include. 5 header 'ile needs to (e included no more than one time0 regardless o' ho! many di''erent 'unctions re)uire it. 8o$ ma( /e wondering wh( these lines of code are called 9directives: and wh( the( don;t end with a semicolon. This is the ind o' distinction that can drive a novice craPy0 although e4"erienced C "rogrammers gro! used to it. The easiest0 most "ractical rule to remem(er is that any line (eginning !ith a "ound sign (T* is a directive0 and0 unli e statements0 directives are not terminated !ith semicolons. )O%01 +n case youHre curious0 a directive is an instruction to the com"iler that controls a general condition during com"ilation. /or e4am"le0 there are directives that a''ect re"orting o' error and !arning messages. 5 C statement0 in contrast0 either declares data or is translated directly into an action that is "er'ormed !hen the "rogram is actually running. The distinction (et!een statements and directives may seem ar(itrary0 es"ecially (ecause there are some directives that can have im"ortant e''ects on "rogram (ehavior. +t may (e easiest 'or no! 6ust to remem(er that i' something (egins !ith a "ound sign (T*0 itHs a directive. 1y data_definition_statements0 + re'er to varia(le de'initions you "lace in your "rogram. 5lthough technically you donHt have to have varia(les0 virtually any "rogram that does anything use'ul has at least a 'e!. +n C0 varia(le de'initions are statements0 and each must (e terminated (y a semicolon (L*. The sim"lest data de'initions declare one varia(le each. The ty"e nameSint0 long0 or do$/le in the 'ollo!ing e4am"lesS"recedes the varia(le name: dou!le "; dou!le %; dou!le h%potenuse; int total; int c; Varia(le declarations in C ena(le you to de'ine as many varia(les on the same line as you choose Sas long as you se"arate the names (y using commas. /or e4am"le0 the 'ollo!ing e4am"le de'ines the same dou(le:"recision 'loating "oint varia(les and integers that the "receding e4am"le does. +n the 'irst line0 40 y0 and hy"otenuse are all de'ined as having ty"e do$/le0 meaning that each varia(le stores dou(le:"recision 'loating:"oint data. The varia(les total and c are integers. dou!le "# %# h%potenuse; int total# c; Nou can also com(ine muli"le data de'initions !ith initialiPation: dou!le ,ei+ht ' -..# hei+ht ' 1./; int i# $# 0 ' 1; int a ' /# !# c ' 21; /inally0 (y executable_statements + re'er to the rest o' the "rogram. These statements ta e some sort o' action during run time. Data de'initions0 in contrast0 donHt cause any actions !hile the "rogram is actually runningL they 6ust reserve s"ace. The distinction (et!een data de'initions and e4ecuta(le statements is im"ortant0 (ecause you must "lace all data de'initions ahead o' all e4ecuta(le statementsSthe t!o inds cannot (e
intermingled. 34ecuta(le statements can do a lot o' things0 (ut nearly all o' these things 'all into one o' three ma6or categories o' actions: < Call a 'unction. < 5ssign a value to a varia(le (or other memory location*. < Trans'er "rogram control to a ne! location or "er'orm an action conditionally. The last category involves control structures0 !hich !eHll start to e4amine later in the cha"ter. 5side 'rom control structures0 nearly all actions in C (oil do!n to either calling a 'unction or assigning a value. &any statements do (oth0 as in the 'ollo!ing statement0 !hich uses the result o' the s)rt 'unction to hel" calcuate the ne! value o' c: 23 4alculate c as the s5uare root of a s5uared plus ! s5uared. 32 c ' s5rt(a 3 a * ! 3 !); This list o' action categories shouldnHt (e too sur"rising i' youHve loo ed at other "rogramming languages. 5ll the "rocessor can do0 really0 is move data0 "er'orm calculations0 or 6um" to a ne! instruction. 5s !ith all other high:level languages0 C lets you com(ine assignment to a varia(le !ith calculation. C is no di''erent 'rom any other language in this res"ect e4ce"t that it com(ines t!o inds o' routines ('unctions and "rocedures in 15S+C* into one: the C 'unction. 5(out the only innovation here is that C uses 6ust one ty"e o' su(routine: the 'unction. Nou can use a 'unctionHs return value 'or calculation0 as !as done in the "receding e4am"le. 1ut you can also thro! a!ay the return value0 6ust as you !ould !ith a 15S+C "rocedure or a /%8T85N su(routine. /or e4am"le: printf("(he value of c is )f\n"# c);
0=ercise Solve the "ro(lem and get introduced to Data Ty"es0 "rogramming Constructs and &odular "rogramming.
#rite a "rogram to acce"t t!o num(ers and Dis"lay highest o' the t!o. Dis"lay all the odd num(ers (et!een the t!o (inclusive o' (oth*. Dis"lay all the even num(ers (et!een the t!o (inclusive o' (oth*.
angleC [ Calculate95ngle(angle50 angle1* 5s youHll see in Cha"ter G0 you can use the same or di''erent varia(les !ithin the 'unction de'initionSthe code that de'ines !hat Calculate95ngle does. Some "urists insist on calling the values actually "assed arguments and the varia(les used in de'initions "arametersSor alternatively0 actual arguments vs. 'ormal argumentsS(ut !eHll stic !ith using arguments e4ce"t !here the distinction is critical. #nteger Nou may recall 'rom high:school math that an integer is a !hole num(er (no 'ractional "ortion* that can range into negative values as !ell as Pero or "ositive. This corres"onds e4actly !ith the conce"t o' integer (int* in C and other languages. 2enerally s"ea ing0 'loating:"oint varia(les can hold any value that an integer can0 so !hy use integers at allW The reason is that 'loating:"oint math is much more com"le4. 5 C$. can o"erate 'ar more e''iciently on an integer. &oreover0 there are many cases in !hich a varia(le needs to hold a num(er that !ill never (e a 'raction. 3ver. 5n e4am"le is a varia(le used to count tri"s through a loo". +ntegers are a much (etter choice 'or data re"resentation in such cases. Floating-Point ?al$es /loating:"oint values can hold 'ractions. %ther languages o'ten re'er to 'loating:"oint values as reals ('or real num(ers*0 and0 realistically s"ea ing0 the terms can (e used interchangea(ly. To "rovide ma4imum 'le4i(ility0 'loating:"oint values are re"resented !ith a ind o' scienti'ic notation involving sign0 e4"onent0 and mantissa. +' you donHt remem(er these terms 'rom school0 thatHs %K0 (ecause itHs all su""osed to (e hidden 'rom you any!ay. The only thing to remem(er is that it re)uires more com"uting "o!er 'or the "oor little C$. to handle 'loating "oint0 although modern:day math co"rocessors do hel". /or o"timal results0 stic to integers as much as "ossi(le. ,ingle-Precision ?al$es 5 single:"recision value in C is a 'loating:"oint value stored in 'our (ytes. Strangely0 varia(les o' this ty"e are declared !ith the 'loat ey!ord. Do$/le Precision ?al$es 5 dou(le:"recision value (dou(le* in C is a 'loating:"oint value stored in eight (ytes. These values re)uire more s"ace (ut "rovide su(stantially more range and accuracy. 1ecause o' the necessary conversion (et!een decimal ('or dis"lay* and (inary ('or internal storage*0 thereHs usually a loss o' "recision !henever 'ractions are involved. /or this reason0 i' you are going to do 'loating:"oint calculations0 dou(le "recision is much (etter. 0=-ressions 5n e4"ression is a single num(er or varia(le0 or a com(ination o' varia(les0 num(ers0 and o"erators (such as +* that evaluates to a single value. The numeral ? is an e4"ressionL so is 4 + y. +n C0 e4"ressions have an interesting relationshi" to statements (the (asic unit o' e4ecution* as descri(ed in the ne4t section. 0=-ressions and ,tatements %ne o' the areas in !hich C most strongly de"arts 'rom other languages is in its conce"t o' e4"ressions. There are some "oints here that arenHt o(vious0 and you need to understand them to 'ully ta e advantage o' C or to read C code.
+n 15S+C or /%8T85N0 !hich are ty"ical o' most com"uter languages0 you can only assign a value to only one varia(le at a time. /or e4am"le0 the 'ollo!ing is a com"lete statement in either 15S+C or /%8T85N: i[6+= 15S+C and /%8T85N use a single e)ual sign ([* to sho! assignment. C does the same. +n $ascal0 youHd use the :[ sym(ol instead: i :[ 6 + = $ascal also uses semicolons in its o!n "erverse 'ashion0 (ut letHs not get into that. #ith all three languagesS15S+C0 /%8T85N0 and $ascalSyou can loo at this e4"ression and no! that it 'orms a com"lete statement. 1ut !ith C0 the e)ual sign ([* is an o"erator li e any other0 and it returns a value 6ust as o"erators such as +0 ]0 \0 and / do. This means that assignment may (e "er'ormed in the middle o' a larger e4"ression. 5n e4am"le should hel" clari'y. Nou can !rite the same e4"ression in C as you can in 15S+C or /%8T85N0 (ut the C version returns a valueSnamely0 the value that !as assigned: i[6+= /\ Value o' this e4"ression is 6 + = \/ 5nd hereHs !here !e can see the (ig di''erence. 1ecause this assignment returns a value (namely0 6 + =*0 you can "lace the !hole thing inside a more com"le4 e4"ression: [ i [ 6 + =L #hat is this 'unny:loo ing constructW To understand it0 you 'irst have to understand that the associativity o' assignment is right:to:le't0 !hich means that !hen more than one assignment o"erator ([* is involved0 the rightmost assignment is evaluated 'irst. Conse)uently0 the "receding e4am"le is e)uivalent to: [ (i [ 6 + =*L The su(e4"ression i [ 6 + = does t!o things: it assigns the value o' 6 + = to i and then it returns the value that !as assignedSnamely0 6 + =. 8e"lacing the right side !ith 6 + = creates the 'ollo!ing e4"ression: [ 6 + =L +n other !ords0 a'ter i is assigned the value 6 + =0 that value is then assigned to . So (oth and i are assigned the value o' 6 + =. ,etHs loo at another e4am"le0 !hich uses a common coding techni)ue. This e4am"le assigns the value F to all 'our varia(les: a0 (0 c0 and d. a [ ( [ c [ d [ FL 5gain0 associativity is right:to:le't. There'ore0 this e4"ression is e)uivalent to: a [ (( [ (c [ (d [ F***L /\ 5ssign F to d \/ The su(e4"ression d [ F o(viously assigns F to d. The return value o' d [ F is F0 !hich means that the "rogram acts as though d [ F !ere re"laced !ith F. The "rogram then evaluates the statement as i' it !ere: a [ (( [ (c [ F**L /\ 5ssign F to c \/ This causes F to (e assigned to the varia(le c. The "rocess continues0 (y successive ste"s: a [ (( [ F*L /\ 5ssign F to ( \/ a [ FL So a0 (0 c0 and d all get the value F. The statement isnHt really (eing re!ritten. The "rogram statements al!ays remain intact and can (e e4ecuted re"eatedly (!hich can ha""en !hen you !rite a loo"*. #hatHs going on is that the C com"iler inter"rets the statement as though it !ere a series o' smaller statements.
,etHs loo at one more e4am"le. 1ecause the e)ual sign ([* is an o"erator li e any other0 it can (e com(ined !ith other o"erators0 such as addition (+*. /or e4am"le0 assume that a0 (0 and c are all integer varia(les: a [ = + (( [ = + (c [ GF**L /\ 5ssign GF to c \/ The "rogram 'irst evaluates c [ GF0 !hich "laces GF into c and returns the value GF. The "rogram then "roceeds as i' the su(e4"ression c [ GF !ere re"laced (y its return value0 GF: a [ = + (( [ = + GF*L /\ 5ssign G= to ( \/ No! the "rogram evaluates ( [ = + GF0 !hich "laces G= into ( and returns the value G=. The "rogram "roceeds as i' the su(e4"ression ( [ = + GF !ere re"laced (y the value G=: a [ = + G=L /\ 5ssign G; to a \/ /inally0 a is assigned the value G;. N%T3: +n the "receding e4am"le0 "arentheses are necessary. 5lthough you can 'reely mi4 the assignment o"erator ([* !ith other o"erators0 the assignments must ma e sense. C language e4"ressions are governed (y CHs rules o' "recedence0 !hich dictate that addition (+* is evaluated (e'ore assignment ([*. Consider !hat !ould ha""en i' the "receding e4am"le had no "arentheses: a [ = + ( [ = + c [ GFL 1ecause addition (+* has higher "recedence than assignment ([*0 this statement is e)uivalent to: a [ (= + (* [ (= + c* [ GFL This in turn "laces the su(e4"ression (= + c* on the le't side o' an assignment: (= + c* [ GF This last e4"ression clearly ma+es no sense and is e4"licitly disallowed /( r$les of C synta4. There'ore0 !hen you mi4 assignment !ith other o"erations0 (e sure to use "arentheses to clari'y order o' evaluation. This 'le4i(ility in the use o' assignment has im"ortant im"lications 'or C synta4. 5ssignments are 6ust one o' the (uilding (loc s o' e4"ressionsSassignments donHt automatically 'orm com"lete statements as they do in other languages. #hen does an e4"ression (ecome a statementW ThatHs sim"le: !hen itHs terminated (y a semicolon. 5n e4"ression terminated (y a semicolon is the most common ty"e o' statement in C: e4"ressionL This synta4 has some interesting conse)uences. +t im"lies that any e4"ression can (e terminated !ith a semicolon to 'orm a com"lete statement. Such e4"ressions donHt even have to involve assignment. -ereHs an e4am"le: 4L i + 6L total \ sum + ;L ?L ;D.FL Nou !ill li ely never see these statements in a real C "rogram0 'or the good reason that they donHt actually do anything. 1ut they are legal 6ust the same. 5s !ith all e4"ressions0 each o' these returns a value. 1ut !hen a statement is terminated (y a semicolon0 the overall value o' the e4"ression is thro!n a!ay. #hat you !ill see0 and o'ten0 are e4"ressions in !hich a 'unctionHs return value is ignored. /or e4am"le0 (oth o' the 'ollo!ing are legal constructs: result [ Calc(a0 (0 c*L
Calc(a0 (0 c*L Nou could !rite either statement de"ending on !hether you !anted to save the result o' the 'unction. This is a nice convenience0 (ecause some times you may care a(out the result o' the 'unction and other times you may not. N%T3: The 'irst statement in the "receding e4am"le is not legal i' the 'unction is declared void0 although the second statement is al!ays legal. &any 'unctions (o' !hich "rint' is a "rominent e4am"le* have side e''ects: they do more than 6ust return a value. #hen a 'unction has side e''ects o' some ind0 a 'unction call can (e use'ul even though it has no return value or that value is ignored. Ret$rning a ?al$e to the ,(stem The main 'unction can return a value 6ust as other 'unctions can0 de"ending on ho! you declare it. The value returned (y main is "assed (ac to the system or calling "rocess. 5n e4am"le o' !here such a return value might (e used is in an &S:D%S (atch 'ile. The value returned (y the "rogram (its return code* can cause a 6um" to a ne! location !ithin the (atch 'ile0 assuming that the 'ile is !ritten to test the "rogramHs return code. 5s a rule0 a return code o' F indicates that the "rogram detected no "ro(lems. 1y convention0 a nonPero return code indicates an error. The revised synta4 'or a "rogram is: include9directives int main (* K data9declaration9statements e4ecuta(le9statements return e4"ressionL M Strictly s"ea ing0 this synta4 isnHt a(solutely "recise0 (ut it gives you an idea o' !hatHs "ossi(le. 5ctually0 the return statement can occur any num(er o' times !ithin e4ecuta(le9statements0 and it doesnHt necessarily have to occur on the last line. 5s a 'irst e4am"le0 the 'ollo!ing "rogram "rints out a message and returns F unconditionally0 to indicate sucess: Tinclude Ustdio.hV int main(* K "rint'(I-ello0 there.YnI*L return FL M &ore ty"ical is the ne4t e4am"le0 !hich tests 'or an error condition (a Pero divisor* (e'ore deciding !hether to return an error code: Tinclude Ustdio.hV Tinclude Umath.hV int main(* K dou(le divisor0 )uotientL scan'(IZ'I0 divisor*L
i' (divisor [[ F* return :=L )uotient [ =FF.F / divisorL "rint'(IThe )uotient is ZdYnI0 )uotient*L return FL M This e4am"le introduces the use o' the C i' statement0 !hich in this case tests the value o' divisor (e'ore deciding !hether to return an error code. Note care'ully the use o' dou(le e)ual signs ([[* to test 'or e)uality. i' (divisor [[ F* return :=L #eHll see a lot more o' the i' statement in later cha"ters. The sim"lest 'orm o' the i' statement has the 'ollo!ing 'ormat: i' (condition* statement + should clari'y that condition is 6ust an integer e4"ression. 5n e4"ression evaluating to Pero means 'alseSstatement is not e4ecutedS!hereas everything else means true. This im"lies that any integer e4"ression is valid in this conte4t. So you can !rite this: i' (=* return :=L 1ut this code !ould mean return ]= unconditionally0 !hich is silly0 i' you thin a(out it0 (ecause it !ould (e easier 6ust to ty"e: return :=L The i' statement loo s harmless0 (ut it has a 'e! "it'alls that a!ait you. 1y 'ar the !orst is the "ossi(ility o' mista ing the assignment o"erator ([* 'or the test:'or:e)uality o"erator ([[*. 1e care'ulJ These t!o o"erators are very di''erent0 in !ays to (e e4"lained later. /or no!0 6ust ma e sure that you dou(le chec all tests 'or e)uality !ithin an i' condition to ma e sure that dou(le e)ual signs ([[* are in use. There are times !hen you !ill !ant to use the assignment o"erator ([* !ithin a condition0 (ut they are much less common. /or no!0 consider a single e)ual sign ([* !ithin a condition as a sure:'ire indicator o' a (ug. The i' statement is the 'irst e4am"le o' a control structure in this (oo . 5 control structure is a "lace at !hich the "rogram may s i" ahead or (ac instead o' going to the ne4t statement. +n the case o' i'0 a condition that evaluates to 'alse causes the "rogram to s i" over the statement immediately 'ollo!ing the i'. 5 condition evaluating to true lets the "rogram e4ecute that statement. #eHll return to the su(6ect o' control structures in detail0 (ut 'irst letHs move to the all:im"ortant to"ic o' 'unctions in C.
F$nctions
%ne o' the greatest aids in "rogramming is the use o' 'unctions. They can save you 'rom having to ty"e common se)uences o' code over and over. They also let you organiPe your "rogram into logical and coherent units. 5 'unction de'ines ho! to carry out a s"eci'ic tas . %nce the tas is de'ined0 you can have it carried out !herever you !ant0 sim"ly (y calling the 'unction. +' youHve (een 'ollo!ing all thrugh0 youHve seen e4am"les o' 'unction calls:
"rint'(I-i thereJYnI*L scan'(IZdI0 &num(er*L 4 [ s)rt(;.F*L The !ords "rint'0 scan'0 and s)rt re'er to 'unctions0 although only in the last case is the value returned (y the 'unction actually used. +n C0 a 'unction is a 'unction !hether or not it returns a value and !hether or not the value is used. There is no se"arate terminology such as "rocedure0 su(routine0 or su("rogram. %' course0 Qsu("rogramR is a good !ay to suggest !hat 'unctions do. #hen a 'unction is called0 control "asses to the 'unction as i' it !ere a se"arate "rogram. The com"uter then e4ecutes each statement in that 'unction until it either comes to the end o' the 'unction or encounters a return statement. +n either case0 the 'unction is said to return. 5t that "oint0 control returns to the "lace in the "rogram !here the 'unction !as called. 8eturn is an a""ro"riate term. +t means that the "rogram goes (ac to !here it !as (e'ore the 'unction !as called.
Calls to 'unctions such as "rint'0 scan'0 and s)rt !or (ecause these 'unctions are de'ined in the standard li(rary. Nou donHt need to su""ly de'initions 'or the 'unctions.
&ost C "rogrammers usually "lace the main 'unction 'irst0 'ollo!ed (y the 'unctions that main calls directly0 'ollo!ed (y other 'unctions. This style o' "rogram organiPation is the to":do!n a""roach. %he new s(nta= element here is f$nction@-rotot(-esA 5 'unction "rototy"e "rovides ty"e in'ormation to the com"iler. Nou can call a 'unction !ithout 'irst "roviding a "rototy"e0 (ut the com"iler !ould have to assume a de'ault return ty"e (int*0 and it !ould not (e a(le to chec argument ty"es. 5s a rule0 you should al!ays include 'unction "rototy"es 'or each 'unction you call. -ereHs the general 'orm 'or a 'unction "rototy"e: return9ty"e 'unction9name(arguments*L The arguments consist o' a list o' argument declarationsL they are se"arated (y commas i' there are more than one. The declarations0 in turn0 consist o' a data ty"e 'ollo!ed (y an argument name: ty"e name0 ty"e name0 ... -ere are some e4am"les o' "rototy"es: =. Dou(le:"recision result0 integer argument. dou(le /ind8eci"rocal(int n*L ;. Dou(le:"recision result0 three dou(le:"recision arguments. dou(le @uadratic(dou(le a0 dou(le (0 dou(le c*L G. +nteger result0 t!o integer and one dou(le:"recision argument. int 8esetVars(int Ne!Start0 int Delta0 dou(le 8atio*L The argument names have little "ur"ose in a "rototy"e e4ce"t 'or documentation. +' you !ant to0 you can omit argument names 'rom "rototy"es. The 'ollo!ing declarations are e)uivalent to the ones youHve 6ust seen: dou(le /ind8eci"rocal(int*L dou(le @uadratic(dou(le0 dou(le0 dou(le*L int 8esetVars(int0 int0 dou(le*L De'ining the /unction %nce again0 hereHs the 'unction:de'inition "art o' the synta4: return9ty"e 'unction9name ( arguments * K
data9declaration9statements e4ecuta(le9statements M The e4ecuta(le9statements can include one or more return statements (assuming return9ty"e is not void*: return e4"ressionL T!o things may stri e you a(out this synta4. /irst0 it loo s very similar to the synta4 'or the main 'unction. +t should0 (ecause the main 'unction is li e any other 'unction e4ce"t 'or a 'e! ey di''erences (mainly0 that it gets e4ecuted 'irst*. Second0 the 'irst line is almost the same as a 'unction "rototy"e. /or e4am"le0 here is a "ossi(le 'irst line o' a 'unction de'inition: dou(le /ind8eci"rocal(int n* K +n 'act0 the (eginning o' a 'unction de'inition is so close to the synta4 'or a "rototy"e that you can save !or (y co"ying the "rototy"e and "asting it into the de'inition. 1ut there are a cou"le o' im"ortant di''erences (et!een "rototy"es and de'initions: O 5 "rototy"e ends !ith a semicolon (L*0 (ut in a 'unction de'inition0 an o"ening (race (K* 'ollo!s the argument list. /unction de'initions are not terminated (y semicolons at all0 not even a'ter the 'inal (race (M*. +ndividual statements inside the (races !ill have semicolons0 ho!ever. O The argument name is not o"tional in a 'unction de'inition even though it is o"tional in "rototy"es. > Com-lete 0=am-le /unctions donHt do anything until called (y an e4ecuting "rogram. 3ven main has to (e called (e'ore it can e4ecuteSalthough in the case o' main0 the caller is the o"erating system. %nce !ritten0 a 'unction can (e called any num(er o' times. Nou can use this techni)ue to create a more com"act version o' the "rogram:
"ont worry #ead$n to understand the program
Tinclude Ustdio.hV int /actorial(int n*L void main(* K "rint'(IThe 'actorial o' G is ZdYnI0 /actorial(G**L "rint'(IThe 'actorial o' > is ZdYnI0 /actorial(>**L "rint'(IThe 'actorial o' ? is ZdYnI0 /actorial(?**L M int /actorial(int n* K int result [ =L !hile (n V =* result \[ n::L return resultL
M
>rg$ments and More >rg$ments (he 6actorial function ta0es a certain amount of li!ert% ,ith its ar+ument# n7 ,hile (n > 1) 23 8hile n > 1# result 3' n99; 23 multipl% !% n decrement n 32 (hese statements cause n to chan+e durin+ e"ecution of the function7 n is continuall% decremented until it is no lon+er +reater than 1. :o n is finall% reduced to 1. ;o,# ,hat do %ou thin0 the follo,in+ statements do< int (emp1# (emp2 ' -; (emp1 ' 6actorial((emp2); printf("(he value of (emp2 is still )d.\n"# (emp2); =f %ou put this code into a pro+ram and run it# %ou>ll find that it produces the follo,in+7 (he value of (emp2 is still -. ?o, can this !e< (he value of (emp2 ,as passed to the ar+ument n# and the function chan+ed the value of n to 1. 8h% didn>t (emp2 chan+e< (he ans,er is that the function +ets a cop% of (emp2>s value !ut not the ri+ht to alter it. (he ar+ument# n# is initiali@ed to the same value as (emp2. (he function then +oes on its merr% ,a% ,ithout havin+ an% further interaction ,ith (emp2. 8hat happens to n later doesn>t matter; the value of n is thro,n a,a% as the function returns. (his is called pass by value. ((he other principal method for passin+ ar+umentsApass by referenceA re5uires pointers in 4 and is the su!$ect of 4hapter 1# BCointers and Dther :harp =nstrumentsE.) Fs a conse5uence# an% valid e"pression can !e passed as an ar+ument as lon+ as it is the ri+ht t%pe. Gou aren>t limited to passin+ varia!les. (he follo,in+ function calls are all le+al7 temp ' 6actorial(1 * 2 * (- 9 1) ); temp ' 6actorial(- * diff); result ' s5rt(1./ * 6actorial(thin+)); 6unctions can have multiple ar+uments. 6or e"ample# here is a protot%pe for the C%tha+oras function7 dou!le C%tha+oras(dou!le a# dou!le !); Fnd here>s the function definition7 dou!le C%tha+oras(dou!le a# dou!le !) { return s5rt(a 3 a * ! 3 !); Dnce C%tha+oras is properl% declared and defined# %ou can pass an% t,o valid ar+uments. (he first ar+ument in the function call is assi+ned to a; the second# to !7 23 Cass -'>a# H'>! 32
h%p1 ' C%tha+oras (-#H); 23 Cass H./'>a# ../'>! 32 h%p2 ' C%tha+oras (H./# ../); 23 Cass temp1'>a# "*-'>!32 h%p- ' C%tha+oras (temp1# "*-); ?ere# of course# the order doesn>t matter. Iut it usuall% does matter ,ith most functions. 6or e"ample# the Juadratic function treats its ar+uments differentl%7 dou!le Juadratic(dou!le a# dou!le !# dou!le c) { dou!le temp; temp ' s5rt(! 3 ! 9 H 3 a 3 c); return ((9! * temp) 2 (2 3 a));
)O%01 &athematically0 this 'unction is incom"lete (ecause it returns only one o' the t!o roots o' a )uadratic e)uation. -o!ever0 the 'unction can return only one value. +n Cha"ter D0 youHll see ho! to return more than one value.
F function can even have no ar+uments. F trivial e"ample is a function that prints a standard messa+e. (he protot%pe uses the void 0e%,ord in the ar+ument list# as does the function definition. =n this conte"t# void simpl% means Bno ar+uments.E int Crint&messa+e(void); ... int Crint&messa+e(void) { printf("6atal error7 stop the pro+ram."); return /; (he function is then called ,ith an empt% ar+ument list# !ut the parentheses must still !e used7 temp ' Crint&messa+e(); +' the 'unction has no need to return a value0 the return value may also (e void. This means that no value is returned at allL in that case0 no ret$rnexpression statement may a""ear !ithin the 'unction de'inition0 and the 'unction0 !hen called0 cannot (e used as "art o' a larger e4"ression. +nstead0 a void 'unction can (e called only directly: Crint&messa+e(); +tHs not very common to see a 'unction !ith (oth a void return ty"e and a void argument list0 (ut such a 'unction !ould (e "er'ectly valid. Note the a(sence o' a ret$rn statement in the 'unction de'inition: void Crint&messa+e(void); 23 function protot%pe 32 ... void Crint&messa+e(void) { printf("6atal error7 stop the pro+ram.");
+' you have a "hiloso"hical turn o' mind0 you might thin o' void as CHs contri(ution to the conce"t o' (eing and nothingness. (To !hat entity does the !ord nothing re'erW* The void ey!ord can mean an em"ty argument list0 orSmore "arado4icallySa return value that is not a return value0 (ut is instead an indicator o' the absence o' return value. %he Bo( of Rec$rsion Sim"ly stated0 recursion occurs !hen a 'unction calls itsel'. This is legal in C0 as it is in many other "rogramming languages. )O%01 8ecursion is an interesting logical and mathematical techni)ue0 (ut itHs not vital to the !riting o' most C "rograms. +' you are eager to understand 6ust the (asics o' C synta40 you can sa'ely s i" this section. Nou might thin that recursion leads automatically to an in'inite regress0 as is the case !hen you "oint a mirror at another mirror. #hen recursion is "ro"erly done0 this doesnHt ha""en at all0 (ecause there is an initial condition. ,etHs return to the 'actorial e4am"le. The 'actorial o' a num(er is the "roduct o' all the integers 'rom = to the num(er. /or any num(er n: factorial of n ' 1 3 2 3 - 3 ... n To go 'rom the 'actorial o' n ] = to n0 multi"ly (y n. /or e4am"le0 here are the 'actorials o' G and >: factorial of - ' 1 3 2 3 factorial of H ' 1 3 2 3 - 3 H &ulti"lying 'actorial o' G (y > "roduces the 'actorial o' >. 2eneraliPing on this0 !e can say: factorial of n ' (factorial of n 9 1) 3 n There is one case in !hich this does not hold: the case o' the num(er =. The 'actorial o' = is sim"ly =. So0 logically0 !e can say: +' n V = then 'actorial o' n [ ('actorial o' n : =* \ n else 'actorial o' n [ = #e can code this logic in a C 'unction very nicely (y !riting a /actorial 'unction that calls itsel': int /actorial(int n* K i' (n V =* return (/actorial(n : =* \ n*L return =L M +' n is greater than =0 the 'irst ret$rn statement causes the 'unction to return immediately a'ter calculating the value. %nly i' n is not greater than = does the second ret$rn get e4ecuted. The statements there'ore create an Qi':then:elseR logic. This a""roach results in a !hole series o' 'unction calls0 (ecause0 in most cases0 (e'ore the 'unction can com"lete e4ecution0 it must call itsel'. 1ut during each call to /actorial0 there is a di''erent value o' n. This is "er'ectly 'ine. C su""orts multi"le instances o' the same 'unction0 each !ith its o!n value o' n. +' the main "rogram e4ecutes /actorial(>*0 'or e4am"le0 the series o' actions is:
!A &ain "rogram calls /actorial(>*. CA /actorial(>* calls /actorial(G*. DA /actorial(G* calls /actorial(;*. EA /actorial(;* calls /actorial(=*. FA /actorial(=* returns the value =. A /actorial(;* multi"lies this result (y ; and returns ;. GA /actorial(G* multi"lies this result (y G and returns C. HA /actorial(>* multi"lies this result (y > and returns ;>.
8ecursion can (e a use'ul techni)ue 'or e4"ressing a calculation succinctly. +tHs most o'ten a""lica(le in "rograms that involve com"le4 math or logical relationshi"s. 'owever. (o$ sho$ld /e aware that rec$rsion is almost never the most efficient wa( to im-lement somethingA 2enerally s"ea ing0 any algorithm that can (e e4"ressed through recursion also has an iterative solutionSthat is0 an a""roach that uses a loo" (such as a while loo"*. The recursive a""roach is almost al!ays less e''icient0 (ecause 'or each 'unction call0 there is a certain amount o' overhead. $art o' the 'unction overhead stores the values o' arguments and local varia(les0 such as n0 'or the "articular instance o' the 'unction call. The 'unction overhead also ee"s trac o' !here the 'unction returns !hen 'inished. #;m not sa(ing that (o$ sho$ld never $se rec$rsionI /$t if there is an o/vio$s alternative that $ses a loo- 3as is the case with factorials5. $se the loo- instead. +n some cases0 though0 the recursive version may (e much easier to !rite and nearly as e''icient.
#hy do + mention recursion0 i' it is rarely the (est a""roachW 8ecursion is use'ul as a !ay o' illustrating a (asic 'act o' most real:!orld C "rograms: at any time0 there may (e many 'unction calls "ending. %nly one 'unction call can (e currently e4ecuting0 (ut there may (e a num(er o' them !aiting 'or another 'unction to return.
None o' that !ould (e the case i' you did a!ay !ith all 'unctions e4ce"t main. +n 'act0 you could do 6ust that0 using com"le4 loo"s and control structures to handle re"eated o"erations. -o!ever0 such code !ould (e e4ce"tionally di''icult to !rite0 understand0 and maintain0 even though in theory it might (e slightly more e''icient. +t !ouldnHt (e reusa(leL only !hen you !rite 'unctions can you create "art o' a "rogram so that it can easily (e reused in another "rogram. /unctions0 a'ter all0 "rovide many (ene'its. 5lthough machine:level e''iciency is an im"ortant goal in C0 the a(ility o' a human (eing to !rite good "rograms is even more im"ortant. /or all these reasons0 'unctions are an invalua(le tool. +' you !ant to avoid having to !rite "rototy"es0 one !ay to do so is to de'ine a 'unction com"letely (e'ore using it. This (ottom:u" a""roach means "utting main last. #ith this a""roach0 the /actorial 'unction !ould (e re!ritten as 'ollo!s: Tinclude Ustdio.hV int /actorial(int n* K int result [ =L !hile (n V =* /\ #hile n is greater than =0 \/ result \[ n::L /\ multi"ly result (y n and decrement n \/ return resultL M void main(* K "rint'(IThe 'actorial o' G is ZdYnI0 /actorial(G**L
"rint'(IThe 'actorial o' > is ZdYnI0 /actorial(>**L "rint'(IThe 'actorial o' ? is ZdYnI0 /actorial(?**L M &ost C "rogrammers donHt use this a""roach0 (ecause they li e to start !ith the (ig "icture (the main "rogram* and !or do!n!ard. &oreover0 i' you s"end enough time "rogramming0 youHll 'ind that ultimately there is no esca"e 'rom !riting "rototy"es. +n a serious "rogram0 the relationshi"s (et!een di''erent 'unctions (ecome very com"le4. +t is not uncommon 'or 'unctions to end u" calling each other (a variation on recursion*0 in !hich case it is im"ossi(le to de'ine every 'unction (e'ore it is called. The (ottom line is that you might as !ell get into the ha(it o' "utting a "rototy"e 'or every 'unction at the (eginning o' your "rogram. > Final Word on Protot(-es +n many serious C "rograms0 you !onHt see "rototy"es at the (eginning o' a source:code 'ile0 and 'or a good reason: all the "rototy"es are "laced in a header 'ile0 !hich is then read in !ith a 7incl$de directive. This is a sensi(le a""roach0 es"ecially !hen you have multi"le source 'iles and !ant all o' them to get the "rototy"es 'or all the 'unctions in the "rogram. /or e4am"le0 you might "lace "rototy"es 'or all your 'unctions in a 'ile called my9"rog.h. Then include my9"rog.h along !ith the other header 'iles: #include <stdio.h> #include <math.h> #include "m%&pro+.h" The synta4 'or the last 7incl$de is a little di''erent 'rom that o' the 'irst t!oL the )uotation mar s cause the current directory to (e searched 'or the header 'ile. +n the 'inal analysis0 entering "rototy"es may seem li e unnecessary !or at 'irst0 (ut they are 6ust too use'ul to ignoreSas are 'unctions in general.
OOP,
O/Ject Oriented Programming
Proced$ral. ,tr$ct$red. and O/Ject-Oriented Programming
.ntil recently0 "rograms !ere thought o' as a series o' "rocedures that acted u"on data. 5 "rocedure0 or 'unction0 is a set o' s"eci'ic instructions e4ecuted one a'ter the other. The data !as )uite se"arate 'rom the "rocedures0 and the tric in "rogramming !as to ee" trac o' !hich 'unctions called !hich other 'unctions0 and !hat data !as changed. To ma e sense o' this "otentially con'using situation0 structured "rogramming !as created The "rinci"le idea (ehind structured "rogramming is as sim"le as the idea o' divide and con)uer. 5 com"uter "rogram can (e thought o' as consisting o' a set o' tas s. 5ny tas that is too com"le4 to (e descri(ed sim"ly !ould (e (ro en do!n into a set o' smaller com"onent tas s0 until the tas s !ere su''iciently small and sel':contained enough that they !ere easily understood. 5s an e4am"le0 com"uting the average salary o' every em"loyee o' a com"any is a rather com"le4 tas . Nou can0 ho!ever0 (rea it do!n into the 'ollo!ing su(tas s:
!A /ind out !hat each "erson earns. CA Count ho! many "eo"le you have.
DA Total all the salaries. EA Divide the total (y the num(er o' "eo"le you have.
Totaling the salaries can (e (ro en do!n into the 'ollo!ing ste"s:
!A 2et each em"loyeeHs record. CA 5ccess the salary. DA 5dd the salary to the running total. EA 2et the ne4t em"loyeeHs record.
+n turn0 o(taining each em"loyeeHs record can (e (ro en do!n into the 'ollo!ing:
!A %"en the 'ile o' em"loyees. CA 2o to the correct record. DA 8ead the data 'rom dis .
Structured "rogramming remains an enormously success'ul a""roach 'or dealing !ith com"le4 "ro(lems. 1y the late =B^Fs0 ho!ever0 some o' the de'iciencies o' structured "rogramming had (ecome all too clear. 5s "rograms gro! ever larger and more com"le40 even the structured "rogramming a""roach (egins to sho! signs o' strain. Nou may have heard a(out0 or (een involved in0 horror stories o' "rogram develo"ment. The "ro6ect is too com"le40 the schedule sli"s0 more "rogrammers are added0 com"le4ity increases0 costs s yroc et0 the schedule sli"s 'urther0 and disaster ensues. 5nalyPing the reasons 'or these 'ailures reveals that there are !ea nesses in the "rocedural "aradigm itsel'. No matter ho! !ell the structured "rogramming a""roach is im"lemented0 large "rograms (ecome e4cessively com"le4. #hat are the reasons 'or these "ro(lems !ith "rocedural languagesW There are t!o related "ro(lems. /irst0 f$nctions have $nrestricted access to glo/al dataA Second0 $nrelated f$nctions and data. the /asis of the -roced$ral -aradigm. -rovide a -oor model of the real worldA #hen data items are modi'ied in a large "rogram it may not (e easy to tell !hich 'unctions access the data0 and even !hen you 'igure this out0 modi'ications to the 'unctions may cause them to !or incorrectly !ith other glo(al data items. 3verything is related to everything else0 so a modi'ication any!here has 'ar: reaching0 and o'ten unintended0 conse)uences. The !ay !e are no! using com"utersS!ith menus and (uttons and !indo!sS'osters a more interactive0 event:driven a""roach to com"uter "rogramming. 3vent:driven means that an event ha""ensSthe user "resses a (utton or chooses 'rom a menuSand the "rogram must res"ond. $rograms are (ecoming increasingly interactive0 and it has (ecame im"ortant to design 'or that ind o' 'unctionality. %ld:'ashioned "rograms 'orced the user to "roceed ste":(y:ste" through a series o' screens. &odern event: driven "rograms "resent all the choices at once and res"ond to the userHs actions. %(6ect:oriented "rogramming attem"ts to res"ond to these needs0 "roviding techni)ues 'or managing enormous com"le4ity0 achieving reuse o' so't!are com"onents0 and cou"ling data !ith the tas s that mani"ulate that data. The essence o' o(6ect:oriented "rogramming is to treat data and the "rocedures that act u"on the data as a single Qo(6ectSRa sel':contained entity !ith an identity and certain characteristics o' its o!n. /irst0 a natural desire is to thin o' data (em"loyee records0 'or e4am"le* and !hat you can do !ith data (sort0 edit0 and so on* as a single idea. $rocedural "rogramming !or ed against this0 se"arating data structures 'rom 'unctions that mani"ulated that data.
Second0 programmers found themselves constantly reinventing new solutions to old problems. This is o'ten called Qreinventing the !heel0R !hich is the o""osite o' reusa(ility. The idea (ehind reusa(ility is to (uild com"onents that have no!n "ro"erties0 and then to (e a(le to "lug them into your "rogram as you need them. This is modeled a'ter the hard!are !orldS!hen an engineer needs a ne! transistor0 she doesnHt usually invent one0 she goes to the (ig (in o' transistors and 'inds one that !or s the !ay she needs it to0 or "erha"s modi'ies it. No similar o"tion e4isted 'or a so't!are engineer. O/Ject The 'undamental idea (ehind o(6ect:oriented languages is to com(ine into a single unit (oth data and the 'unctions that o"erate on that data. Such a unit is called an o(6ect. 5n o(6ectHs 'unctions0 called mem(er 'unctions in C++0 ty"ically "rovide the only !ay to access its data. +' you !ant to read a data item in an o(6ect0 you call a mem(er 'unction in the o(6ect. +t !ill access the data and return the value to you. Nou canHt access the data directly. The data is hidden0 so it is sa'e 'rom accidental alteration. Class
Class is the logical category /ty"e o' the %(6ects. 5 class serves as a "lan0 or tem"late. +t s"eci'ies !hat data and !hat 'unctions !ill (e included in o(6ects o' that class. De'ining the class doesnHt create any o(6ects0 6ust as the mere e4istence o' data ty"e int doesnHt create any varia(les.
0nca-s$lation The "ro"erty o' (eing a sel':contained unit is called enca"sulation. #ith enca"sulation0 !e can accom"lish data hiding. Data hiding is the highly valued characteristic that an o(6ect can (e used !ithout the user no!ing or caring ho! it !or s internally. <ust as you can use a re'rigerator !ithout no!ing ho! the com"ressor !or s0 you can use a !ell:designed o(6ect !ithout no!ing a(out its internal data mem(ers. 0nca-s$lation is the a/straction of information and is also called data hiding . +t "revents users 'rom seeing the internal !or ings o' an o(6ect so as to "rotect data that should not (e mani"ulated (y the user. 3nca"sulation im"roves the modularity o' the code and leads to more easy maintenance o' "rograms (y hiding the actual im"lementation details !ithin an o(6ect and sim"ly allo!ing access to an o(6ect7s inter'ace. Pol(mor-hism $olymor"hism allo!s di''erent o(6ects to res"ond di''erently to the same message. There are t!o ty"es o' "olymor"hism (a* %arly &inding !hich allo!s overloading o' 'unctions. %verloading means that di''erent 'unctions can have the same name (ut can (e distinguished (ased on their signature (num(er0 ty"e and order o' "arameters*. ((* 'ate &inding !hich allo!s derived classes to to override the (ase class 'unctionality. #hich 'unction is invo ed de"ends on the conte4t in !hich the 'unction is invo ed. $olymor"hism im"roves the 'le4i(ility o' "rogramming (y allo!ing develo"ers (etter design o"tions #nheritance #hen the engineers at 5cme &otors !ant to (uild a ne! car0 they have t!o choices: They can start 'rom scratch0 or they can modi'y an e4isting model. $erha"s their Star model is nearly "er'ect0 (ut theyHd li e to add a tur(ocharger and a si4:s"eed transmission. The chie' engineer !ould "re'er not to start 'rom the ground u"0 (ut rather
to say0 Q,etHs (uild another Star0 (ut letHs add these additional ca"a(ilities. #eHll call the ne! model a @uasar.R 5 @uasar is a ind o' Star0 (ut a s"ecialiPed one !ith ne! 'eatures. C++ su""orts inheritance. 5 ne! ty"e0 !hich is an e4tension o' an e4isting ty"e0 can (e declared. This ne! su(class is said to derive 'rom the e4isting ty"e and is sometimes called a derived ty"e. The @uasar is derived 'rom the Star and thus inherits all its )ualities0 (ut can add to them as needed. +nheritance allo!s you to create ne! o(6ects o' a derived class 'rom "reviously de'ined o(6ects o' a (ase class. The derived class contains all the attri(utes and methods o' the (ase class "lus any additional s"eci'ications o' the derived class. 5ny changes made to (ase classes are "ro"agated to all derived classes unless e4"licitly overridden. #nheritance
facilitates code re$se there/( c$tting develo-ment costs
>/straction
#hen the engineers at 5cme &otors !ant to (uild a ne! car0 they have t!o choices: They can start 'rom scratch0 or they can modi'y an e4isting model/a set of modals. $erha"s a com(ination o' their Star model and the Su"er Star model loo s li e a great idea0 (ut theyHd li e to add a tur(ocharger and a si4:s"eed transmission. The chie' engineer !ould "re'er not to start 'rom the ground u"0 (ut rather to say0 Q,etHs (uild another model0 (ut letHs add these additional ca"a(ilities. #eHll call the ne! model a Su"er@uasar.R 5 Su"er@uasar is a ind o' Star com Su"er Star0 (ut a s"ecialiPed one !ith ne! 'eatures. +n the a(ove case the user/customer o' the ne! car Su"er@uassar never (others to no! the technology (ie. The "arent technology 'rom !hich it is inherited in this case itHs a com(ination o' the star and su"er star model. *(ehind it.This "rocess o' hiding the technology is called a(straction.
Wh( C++
C++ 'ully su""orts o(6ect:oriented "rogramming0 including the three "illars o' o(6ect:oriented develo"ment: enca"sulation0 inheritance0 5(straction and "olymor"hism
,imilarities
The C language is a su(set o' C++ 'or all "ractical "ur"oses even though it is "ossi(le to !rite C "rograms that are not valid in C++. The main similarity in C and C++ lies in the synta4 o' the t!o languages. C and C++ (oth share many o' the same 'undamental "rogramming constructs. This is the reason !hy it is easy 'or a "ro'icient C "rogrammer to learn C++ "rovided he/she understands the o(6ect:oriented "aradigm. C++ maintains it7s C roots at various levels: a* Source code level: most 5NS+ C "rograms are valid C++ "rogramsL (* %(6ect code level: C++ structures are I(inary:com"ati(leI !ith e)uivalent C structuresL c* 3nvironment/Tool level: C++ !or s !ith standard tools li e ma eL C++ can (e descri(ed as a "rogramming language derived 'rom C !ith im"roved "rocedural synta4 as com"ared to C and o(6ect:oriented 'eatures not "resent in C. Note that though C++ su""orts o(6ect:oriented "rogramming0 it does not en'orce it. C++ is there'ore a multi:"aradigm language.
C is a "rocedural language. +t is not designed to su""ort o(6ect:oriented "rogramming. +n a "rocedural "rogram0 the "ro(lem is (ro en do!n into modules and su(:modules !hich im"lement the solution. C++ on the other hand can "rovide all the advantages inherent in the %% "aradigm. +n an %% "rogram the "ro(lem s"ace is re"resented (y o(6ects that interact !ith each other and these o(6ects are im"lemented along !ith messaging mechanisms to "rovide a solution. %% "rogramming languages have a num(er o' inherent advantages. They lend themselves to (etter design (ecause they allo! "ro(lem s"aces to (e modelled li e real !orld o(6ects. +n an o(6ect oriented language0 an o(6ect is called a class !hich is the so't!are re"resentation o' an o(6ect. 5 class "ac ages all the attri(utes and methods o' an o(6ect. 5ttri(utes are the data associated !ith the o(6ect and methods are the 'unctions that o"erate on the data and e4"ress the (ehavior o' the o(6ect. 5s an o(6ect:oriented language C+ + su""orts inheritance0 enca"sulation and "olymor"hism !hich i' "ro"erly used lead to (etter "rograms. -ere is a lin to the a (rie' tutorial e4"laining the (asics o' +nheritance. +nheritance in C++ The 'ollo!ing is a lin to a tutorial on 3nca"sulation. Data -iding and 3nca"sulation in C++ Chec out the 'ollo!ing lin 'or an introduction to "olymor"hism0 illustrated (y e4am"le. 5n +ntroduction to $olymor"hism >n 0=am-le Chec out this lin 'or a tutorial that e4"lores through e4am"les the di''erences (et!een C and C++. Di''erences (et!een C and C++ >ftertho$ght I+ncreasingly0 "eo"le seem to misinter"ret com"le4ity as so"histication0 !hich is (a''ling : the incom"rehensi(le should cause sus"icion0 rather than admirationI0 Ni laus #irth.
,treams (+/%*
5s you have seen0 the statement cout UU Q3very age has a language o' its o!nYnRL causes the "hrase in )uotation mar s to (e dis"layed on the screen. -o! does this !or W 5 com"lete descri"tion o' this statement re)uires an understanding o' o(6ects0 o"erator overloading0 and other to"ics !e !onHt discuss until later in the (oo 0 (ut hereHs a (rie' "revie!. The identi'ier cout ("ronounced QC outR* is actually an object. +t is "rede'ined in C++ to corres"ond to the standard output stream. 5 stream is an a(straction that re'ers to a 'lo! o' data. The standard out"ut stream normally 'lo!s to the screen dis"laySalthough it can (e redirected to other out"ut devices. The o"erator UU is called the insertion or put to o"erator. +t directs the contents o' the varia(le on its right to the o(6ect on its le't(ie the co$t !hich is nothing (ut the Standard %ut"ut Device*. +n /+8ST it directs the string constant Q3very age has a language o' its o!n YnR to cout0 !hich sends it to the dis"lay.
Similarly the o"erator used !ith cin VV is a extraction or get opeator.+t !aits 'or the in"ut o' the user 'rom the Standard +n"ut Device (ie cin* and "uts it to the right hand side varia(le.
(+' you no! C0 youHll recogniPe UU as the left-shift (it:!ise o"erator and !onder ho! it can also (e used to direct out"ut. +n C++0 o"erators can (e overloaded (> wa( to im-lement -ol(mor-hism*. That is0 they can "er'orm di''erent activities0 de"ending on the conte4t. +n the /+8ST e4am"le0 the "re"rocessor directive Tinclude tells the com"iler to add the source 'ile +%ST835& to the /+8ST.C$$ source 'ile (e'ore com"iling. #hy do thisW +%ST835& is an e4am"le o' a header file (sometimes called an include file). +tHs concerned !ith (asic in"ut/out"ut o"erations0 and contains declarations that are needed (y the cout identi'ier and the UU o"erator. #ithout these declarations0 the com"iler !onHt recogniPe cout and !ill thin UU is (eing used incorrectly. There are many such include 'iles. The ne!er Standard C++ header 'iles donHt have a 'ile e4tension0 (ut some older header 'iles0 le't over 'rom the days o' the C language0 have the e4tension .-. +' you !ant to see !hatHs in +%ST835&0 you can use your com"iler to 'ind the include directory 'or your com"iler and dis"lay it as a source 'ile in the edit !indo!. %r you can loo at it !ith the #ord"ad or Note"ad utilities. The contents !onHt ma e much sense at this "oint0 (ut you !ill at least "rove to yoursel' that +%ST835& is a source 'ile0 !ritten in normal 5SC++ characters.
0sca-e ,eK$ences
This second character constant0 _YtH0 is an odd one. ,i e _YnH !hich !e encountered earlier0 itHs an e4am"le o' an escape sequence. The name re'lects the 'act that the (ac slash causes an Qesca"eR 'rom the normal !ay characters are inter"reted. +n this case the t is inter"reted not as the character _tH (ut as the ta( character. 5 ta( causes "rinting to continue at the ne4t ta( sto". +n console:mode "rograms0 ta( sto"s are "ositioned every eight s"aces. 5nother character constant0 _YnH0 is sent directly to cout in the last line o' the "rogram. 3sca"e se)uences can (e used (oth as se"arate characters and also em(edded in string constants. Ta(le (elo! sho!s a list o' common esca"e se)uences. %a/le Common 3sca"e Se)uences 0sca-e ,eK$ence Character Ya 1ell ((ee"* Y( 1ac s"ace Y' /orm'eed Yn Ne!line Yr 8eturn Yt Ta( YY 1ac slash Y_ Single )uotation mar YQ Dou(le )uotation mar s Y4dd -e4adecimal notation
Since the (ac slash0 the single )uotation mar s0 and the dou(le )uotation mar s all have s"ecialiPed meanings !hen used in constants0 they must (e re"resented (y esca"e se)uences !hen !e !ant to dis"lay them as characters. -ereHs an e4am"le o' a )uoted "hrase in a string constant: cout UU QYR8un0 S"ot0 run0YR she said.RL This translates to Q8un0 S"ot0 run0R she said. Sometimes you need to re"resent a character constant that doesnHt a""ear on the ey(oard0 such as the gra"hics characters a(ove 5SC++ code =;D. To do this0 you can use the _Y4ddH re"resentation0 !here each d stands 'or a he4adecimal digit. +' you !ant to "rint a solid rectangle0 'or e4am"le0 youHll 'ind such a character listed as decimal num(er =D^0 !hich is he4adecimal num(er 1; in the 5SC++ ta(le. This character !ould (e re"resented (y the character constant _Y41;H. #eHll see some e4am"les o' this later.
(yte.* These ty"e names are "receded (y t!o underscores. They are 99int^0 99int=C0 99intG;0 and 99intC>. The 99int^ ty"e corres"onds to char0 and (at least in G;:(it systems li e the current version o' #indo!s* The ty"e name 99int=C corres"onds to short and 99intG; corres"onds to (oth int and long. The 99intC> ty"e holds huge integers !ith u" to =B decimal digits. .sing these ty"e names has the advantage that the num(er o' (ytes used 'or a varia(le is not im"lementation de"endent. -o!ever0 this is not usually an issue0 and these ty"es are seldom used.
What is a -ointer W
#hat is a "ointer W 5 "ointer is a varia(le that contains the memory address o' another varia(le (!hich may(e o' any ty"e including an o(6ect*. $ointers are central to C/C++ "rogramming as they allo! the "rogrammer to access and mani"ulate o(6ects in memory.
%(-es of -ointers
5 "ointer varia(le 6ust li e any other varia(le in C and C++ must have a data ty"e. The data ty"e o' a "ointer is the same as that o' the varia(le !hose address is contained in the "ointer. /or e4am"le0 the 'ollo!ing are all valid declarations o' "ointers:
int \"tr&y+ntL //"tr&y+nt is a "ointer to an integer varia(le char \"tr&yCharL //"tr&yChar is a "ointer to a char varia(le 'loat \"tr&y/loatL //"tr&y/loat is a "ointer to a 'loat varia(le The \ in the varia(le name indicates that these varia(les are "ointers.
#nitialiLing Pointers
5 "ointer varia(le can (e initialiPed in a num(er o' di''erent !ays. 5 "ointer can (e assigned the address o' a varia(le or it can (e assigned another "ointer as illustrated in the e4am"les (elo!: //declare varia(les int iL int \"tr&y+ntL //assign values to varia(les i [ =FL//"tr&y+nt contains the address o' i "tr&y+nt [ &iL //declare and assign value to a second "ointer int \"tr&y+nt;L "tr&y+nt; [ "tr&y+ntL //"tr&y+nt; "oints to the address o' integer i
%he #ndirection and the >ddress-of O-erators #e have 6ust seen the address:o' o"erator. This o"erator is used to access the memory address at !hich a varia(le is stored. /or e4am"le i' !e have an integer i0 then &i contains the memory location at !hich the integer i is stored. +ndirection re'ers to the accessing o' the value stored in the memory address contained in the "ointer. /or e4am"le0 i' !e de'ine a second integer 6 and !e !ant to assign to 60 the value contained in the varia(le iL there are t!o !ays to do this: one !ithout "ointers and the second !ith "ointers. 1oth yield the same result. int iL i [ =FL int \"tr+L "tr+ [ &=FL int 6L 6 [ iL //'irst !ay to assign a value to 6 6 [ \"tr+L //second !ay to assign a value to 6 -ere7s another e4am"le continued 'rom the one !e 6ust loo ed at. Say !e de'ine a varia(le that uses the address:o' o"erator to "oint to the address o' i. int \ L [ &iL Then i' !e assign a value to 0 !hat do you thin ha""ens to the value o' i W \ [ GL Nou are right i' you guessed that the value o' i is no! e)ual to G. Since "oints to
the address0 assigning a value to \ actually changes the value stored in the address re'erenced (y . What )e=t 2 Chec out the 'ollo!ing lin s 'or more on "ointers Notes on $ointers ,ecture Notes on $ointers 5 +ntroduction to $ointers in C++ $ointers and 8e'erences
F$nctions
5ny se)uence o' instructions that a""ears in a "rogram more than once is a candidate 'or (eing made into a 'unction. The 'unctionHs code is stored in only one "lace in memory0 even though the 'unction is e4ecuted many times in the course o' the "rogram. /igure (elo! sho!s ho! a 'unction is invo ed 'rom di''erent sections o' a "rogram. ,im-le F$nctions O$r first e=am-le demonstrates a sim-le f$nction whose -$r-ose is to -rint a line of EF asteris+sA %he e=am-le -rogram generates a ta/le. and lines of asteris+s are $sed to ma+e the ta/le more reada/leA 'ere;s the listing for %>B&01 // table.cpp // demonstrates simple function
#include <iostream> using namespace std; void starline(); declaration //function // (prototype)
int main() { starline(); //call to function cout << Data type ange! << endl; starline(); //call to function cout << c"ar #$%& to $%'! << endl << s"ort #(%)'*& to (%)'*'! << endl << int +ystem dependent! << endl << long #%)$,'),&()*,& to %)$,'),&()*,'! << endl; starline(); //call to function return -; . //######################################################### ##### // starline() // function definition void starline() //function declarator { for(int /0-; /<,1; /22) //function body cout << 345; cout << endl; . %he o$t-$t from the -rogram loo+s li+e this1 444444444444444444444444444444444444444444444 Data type ange 444444444444444444444444444444444444444444444 c"ar #$%& to $%' s"ort #(%)'*& to (%)'*' int +ystem dependent double #%)$,'),&()*,& to %)$,'),&()*,' %he -rogram consists of two f$nctions1 main35 and starline35A 8o$;ve alread( seen man( -rograms that $se main35 aloneA What other com-onents are necessar( to add a f$nction to the -rogram2 %here are three1 the f$nction declaration, the calls to the f$nction. and the f$nction definition. %he F$nction Declaration B$st as (o$ can;t $se a varia/le witho$t first telling the com-iler what it is. (o$ also can;t $se a f$nction witho$t telling the com-iler a/o$t itA %here are two wa(s to do thisA %he a--roach we show here is to declare the f$nction /efore it is calledA 3%he
other a--roach is to define it /efore it;s calledI we;ll e=amine that ne=tA5A #n the %>B&0 -rogram. the f$nction starline35 is declared in the line void starline(); %he declaration tells the com-iler that at some later -oint we -lan to -resent a f$nction called starline. %he +e(word void s-ecifies that the f$nction has no ret$rn val$e. and the em-t( -arentheses indicate that it ta+es no arg$mentsA 38o$ can also $se the +e(word void in -arentheses to indicate that the f$nction ta+es no arg$ments. as is often done in C. /$t leaving them em-t( is the more common -ractice in C++A5 We;ll have more to sa( a/o$t arg$ments and ret$rn val$es soonA )otice that the f$nction declaration is terminated with a semicolonA #t is a com-lete statement in itselfA F$nction declarations are also called prototypes, since the( -rovide a model or /l$e-rint for the f$nctionA %he( tell the com-iler. 9a f$nction that loo+s li+e this is coming $- later in the -rogram. so it;s all right if (o$ see references to it /efore (o$ see the f$nction itselfA: Calling the F$nction %he f$nction is called 3or invoked, or executed5 three times from main35A 0ach of the three calls loo+s li+e this1 starline(); %his is all we need to call the f$nction1 the f$nction name. followed /( -arentheses %he call is terminated /( a semicolonA 0=ec$ting the call statement ca$ses the f$nction to e=ec$teI that is. control is transferred to the f$nction. the statements in the f$nction definition 3which we;ll e=amine in a moment5 are e=ec$ted. and then control ret$rns to the statement following the f$nction callA %he F$nction Definition Finall(. we come to the f$nction itself. which is referred to as the f$nction definition. %he definition contains the act$al code for the f$nctionA 'ere;s the definition for starline351 void starline() //declarator { for(int /0-; /<,1; /22) //function body cout << 345; cout << endl; . %he definition consists of a line called the declarator, followed /( the f$nction body. %he f$nction /od( is com-osed of the statements that ma+e $- the f$nction. delimited /( /racesA %he declarator m$st agree with the declaration1 #t m$st $se the same f$nction name. have the same arg$ment t(-es in the same order 3if there are arg$ments5. and have the same ret$rn t(-eA )otice that the declarator is not terminated /( a semicolonA
When the f$nction is called. control is transferred to the first statement in the f$nction /od(A %he other statements in the f$nction /od( are then e=ec$ted. and when the closing /race is enco$ntered. control ret$rns to the calling -rogramA Com-arison with &i/rar( F$nctions We;ve alread( seen some li/rar( f$nctions in $seA We have em/edded calls to li/rar( f$nctions. s$ch as c" 0 getc"e(); in o$r -rogram codeA Where are the declaration and definition for this li/rar( f$nction2 %he declaration is in the header file s-ecified at the /eginning of the -rogram 3CO)#OA'. for getche355A %he definition 3com-iled into e=ec$ta/le code5 is in a li/rar( file that;s lin+ed a$tomaticall( to (o$r -rogram when (o$ /$ild itA When we $se a li/rar( f$nction we don;t need to write the declaration or definitionA B$t when we write o$r own f$nctions. the declaration and definition are -art of o$r so$rce file. 0liminating the Declaration %he second a--roach to inserting a f$nction into a -rogram is to eliminate the f$nction declaration and -lace the f$nction definition 3the f$nction itself5 in the listing /efore the first call to the f$nctionA For e=am-le. we co$ld rewrite %>B&0 to -rod$ce %>B&0C. in which the definition for starline35 a--ears firstA // ta/leCAc-// demonstrates f$nction definition -receding f$nction calls 7incl$de MiostreamN $sing names-ace stdI //no f$nction declaration //-------------------------------------------------------------// starline35 //f$nction definition void starline35 O for3int JP"I JMEFI J++5 co$t MM QR;I co$t MM endlI S //-------------------------------------------------------------int main35 //main35 follows f$nction O starline35I //call to f$nction co$t MM 9Data t(-e Range: MM endlI starline35I //call to f$nction co$t MM 9char -!CH to !CG: MM endl MM 9short -DC.G H to DC.G G: MM endl MM 9int ,(stem de-endent: MM endl MM 9long -C.!EG.EHD. EH to C.!EG.EHD. EG: MM endlI starline35I //call to f$nction ret$rn "I
S %his a--roach is sim-ler for short -rograms. in that it removes the declaration. /$t it is less fle=i/leA %o $se this techniK$e when there are more than a few f$nctions. the -rogrammer m$st give considera/le tho$ght to arranging the f$nctions so that each one a--ears /efore it is called /( an( otherA ,ometimes this is im-ossi/leA >lso. man( -rogrammers -refer to -lace main35 first in the listing. since it is where e=ec$tion /eginsA Passing >rg$ments to F$nctions >n argument is a -iece of data 3an int val$e. for e=am-le5 -assed from a -rogram to the f$nctionA >rg$ments allow a f$nction to o-erate with different val$es. or even to do different things. de-ending on the reK$irements of the -rogram calling itA >s an e=am-le. let;s s$--ose we decide that the starline35 f$nction in the last e=am-le is too rigidA #nstead of a f$nction that alwa(s -rints EF asteris+s. we want a f$nction that will -rint an( character an( n$m/er of timesA 'ere;s a -rogram. %>B&0>R6. that incor-orates J$st s$ch a f$nctionA We $se arg$ments to -ass the character to /e -rinted and the n$m/er of times to -rint itA // tablearg.cpp // demonstrates function arguments #include <iostream> using namespace std; void repc"ar(c"ar) int); declaration
//function
int main() { repc"ar(3#5) ,(); //call to function cout << Data type ange! << endl; repc"ar(305) %(); //call to function cout << c"ar #$%& to $%'! << endl << s"ort #(%)'*& to (%)'*'! << endl << int +ystem dependent! << endl << double #%)$,'),&()*,& to %)$,'),&()*,'! << endl; repc"ar(3#5) ,(); //call to function return -; . //######################################################### ##### // repc"ar() // function definition void repc"ar(c"ar c") int n) //function declarator { for(int /0-; /<n; /22) //function body cout << c"; cout << endl; .
%he new f$nction is called re-char35A #ts declaration loo+s li+e this1 void repc"ar(c"ar) int); // declaration specifies data types %he items in the -arentheses are the data t(-es of the arg$ments that will /e sent to re-char351 char and intA #n a f$nction call. s-ecific val$esTconstants in this caseTare inserted in the a--ro-riate -lace in the -arentheses1 repc"ar(3#5) ,(); // function call specifies actual values %his statement instr$cts re-char35 to -rint a line of ED dashesA %he val$es s$--lied in the call m$st /e of the t(-es s-ecified in the declaration1 the first arg$ment. the Q-; character. m$st /e of t(-e charI and the second arg$ment. the n$m/er ED. m$st /e of t(-e intA %he t(-es in the declaration and the definition m$st also agreeA %he ne=t call to re-char35. repc"ar(305) %(); tells it to -rint a line of CD eK$al signsA %he third call again -rints ED dashesA 'ere;s the o$t-$t from %>B&0>R61 ########################################### Data type ange 00000000000000000000000 c"ar #$%& to $%' s"ort #(%)'*& to (%)'*' int +ystem dependent long #%)$,'),&()*,& to %)$,'),&()*,' Passing ?aria/les #n the %>B&0>R6 e=am-le the arg$ments were constants1 Q-;. ED. and so onA &et;s loo+ at an e=am-le where varia/les. instead of constants. are -assed as arg$mentsA %his -rogram. ?>R>R6. incor-orates the same re-char35 f$nction as did %>B&0>R6. /$t lets the $ser s-ecif( the character and the n$m/er of times it sho$ld /e re-eatedA // vararg.cpp // demonstrates variable arguments #include <iostream> using namespace std; void repc"ar(c"ar) int); //function declaration int main() { c"ar c"in; int nin; cout << 6nter a c"aracter7 !; cin >> c"in; cout << 6nter number of times to repeat it7 !; cin >> nin; repc"ar(c"in) nin); return -;
. //######################################################### ##### // repc"ar() // function definition void repc"ar(c"ar c") int n) //function declarator { for(int /0-; /<n; /22) //function body cout << c"; cout << endl; . 'ere;s some sam-le interaction with ?>R>R61 6nter a c"aracter7 2 6nter number of times to repeat it7 %22222222222222222222 'ere chin and nin in main35 are $sed as arg$ments to re-char351 repc"ar(c"in) nin); // function call %he data t(-es of varia/les $sed as arg$ments m$st match those s-ecified in the f$nction declaration and definition. J$st as the( m$st for constantsA %hat is. chin m$st /e a char. and nin m$st /e an intA Passing /( ?al$e #n ?>R>R6 the -artic$lar val$es -ossessed /( chin and nin when the f$nction call is e=ec$ted will /e -assed to the f$nctionA >s it did when constants were -assed to it. the f$nction creates new varia/les to hold the val$es of these varia/le arg$mentsA %he f$nction gives these new varia/les the names and data t(-es of the -arameters s-ecified in the declarator1 ch of t(-e char and n of t(-e intA #t initialiLes these -arameters to the val$es -assedA %he( are then accessed li+e other varia/les /( statements in the f$nction /od(A Passing arg$ments in this wa(. where the f$nction creates co-ies of the arg$ments -assed to it. is called passing by value. We;ll e=-lore another a--roach. passing by reference, later in this cha-terA Fig$re /elow shows how new varia/les are created in the f$nction when arg$ments are -assed /( val$eA
Ret$rning ?al$es from F$nctions When a f$nction com-letes its e=ec$tion. it can ret$rn a single val$e to the calling -rogramA *s$all( this ret$rn val$e consists of an answer to the -ro/lem the f$nction has solvedA %he ne=t e=am-le demonstrates a f$nction that ret$rns a weight in +ilograms after /eing given a weight in -o$ndsA 'ere;s the listing for CO)?0R%1 // convertAc-// demonstrates ret$rn val$es. converts -o$nds to +g 7incl$de MiostreamN $sing names-ace stdI float l/sto+g3float5I //declaration
int main35 O float l/s. +gsI co$t MM 94n0nter (o$r weight in -o$nds1 :I cin NN l/sI +gs P l/sto+g3l/s5I co$t MM 98o$r weight in +ilograms is : MM +gs MM endlI ret$rn "I S //-------------------------------------------------------------// l/sto+g35 // converts -o$nds to +ilograms float l/sto+g3float -o$nds5 O float +ilograms P "AEFDFUC R -o$ndsI ret$rn +ilogramsI S 'ere;s some sam-le interaction with this -rogram1 0nter (o$r weight in -o$nds1 !HC 8o$r weight in +ilograms is HCAFFDGE! When a f$nction ret$rns a val$e. the data t(-e of this val$e m$st /e s-ecifiedA %he f$nction declaration does this /( -lacing the data t(-e. float in this case. /efore the f$nction name in the declaration and the definitionA F$nctions in earlier -rogram e=am-les ret$rned no val$e. so the ret$rn t(-e was voidA #n the CO)?0R% -rogram. the f$nction l/sto+g35 3pounds to kilograms, where l/s means -o$nds5 ret$rns t(-e float. so the declaration is float l/sto+g3float5I %he first float s-ecifies the ret$rn t(-eA %he float in -arentheses s-ecifies that an arg$ment to /e -assed to l/sto+g35 is also of t(-e floatA When a f$nction ret$rns a val$e. the call to the f$nction l/sto+g3l/s5 is considered to /e an e=-ression that ta+es on the val$e ret$rned /( the f$nctionA We can treat this e=-ression li+e an( other varia/leI in this case we $se it in an assignment statement1 +gs P l/sto+g3l/s5I %his ca$ses the varia/le +gs to /e assigned the val$e ret$rned /( l/sto+g35A %he ret$rn ,tatement %he f$nction l/sto+g35 is -assed an arg$ment re-resenting a weight in -o$nds. which it stores in the -arameter -o$ndsA #t calc$lates the corres-onding weight in +ilograms /( m$lti-l(ing this -o$nds val$e /( a constantI the res$lt is stored in the varia/le +ilogramsA %he val$e of this varia/le is then ret$rned to the calling -rogram $sing a ret$rn statement1 return 8ilograms; )otice that /oth main35 and l/sto+g35 have a -lace to store the +ilogram varia/le1 +gs in main35. and +ilograms in l/sto+g35A When the f$nction ret$rns. the val$e in +ilograms is copied into +gsA %he calling -rogram does not access the +ilograms
varia/le in the f$nctionI onl( the val$e is ret$rnedA %his -rocess is shown in Fig$re /elowA While man( arg$ments ma( /e sent to a f$nction. onl( one arg$ment ma( /e ret$rned from itA %his is a limitation when (o$ need to ret$rn more informationA 'owever. there are other a--roaches to ret$rning m$lti-le varia/les from f$nctionsA One is to -ass arg$ments /( reference. which we;ll loo+ at later in this cha-terA 8o$ sho$ld alwa(s incl$de a f$nction;s ret$rn t(-e in the f$nction declarationA #f the f$nction doesn;t ret$rn an(thing. $se the +e(word void to indicate this factA #f (o$ don;t $se a ret$rn t(-e in the declaration. the com-iler will ass$me that the f$nction ret$rns an int val$eA For e=am-le. the declaration somefunc(); // declaration ## assumes return type is int tells the com-iler that somef$nc35 has a ret$rn t(-e of intA %he reason for this is historical. /ased on $sage in earl( versions of CA #n -ractice (o$ sho$ldn;t ta+e advantage of this defa$lt t(-eA >lwa(s s-ecif( the ret$rn t(-e e=-licitl(. even if it act$all( is intA %his +ee-s the listing consistent and reada/leA Defa$lt >rg$ments ,$r-risingl(. a f$nction can /e called witho$t s-ecif(ing all its arg$mentsA %his won;t wor+ on J$st an( f$nction1 %he f$nction declaration m$st -rovide defa$lt val$es for those arg$ments that are not s-ecifiedA 'ere;s an e=am-le. a variation on the O?0R&O>D -rogram that demonstrates this effectA #n O?0R&O>D we $sed three different f$nctions with the same name to handle different n$m/ers of arg$mentsA %he -resent e=am-le. M#,,>R6. achieves the same effect in a different wa(A
// missargAc-// demonstrates missing and defa$lt arg$ments 7incl$de MiostreamN $sing names-ace stdI void re-char3charP;R;. intPEF5I //declaration with //defa$lt arg$ments int main35 O re-char35I //-rints EF asteris+s re-char3QP;5I //-rints EF eK$al signs re-char3Q+;. D"5I //-rints D" -l$s signs ret$rn "I S //-------------------------------------------------------------// re-char35 // dis-la(s line of characters void re-char3char ch. int n5 //defa$lts s$--lied O // if necessar( for3int JP"I JMnI J++5 //loo-s n times co$t MM chI //-rints ch co$t MM endlI S #n this -rogram the f$nction re-char35 ta+es two arg$mentsA #t;s called three times from main35A %he first time it;s called with no arg$ments. the second time with one. and the third time with twoA Wh( do the first two calls wor+2 Beca$se the called f$nction -rovides defa$lt arg$ments. which will /e $sed if the calling -rogram doesn;t s$--l( themA %he defa$lt arg$ments are s-ecified in the declaration for re-char351 void re-char3charP;R;. intPEF5I //declaration %he defa$lt arg$ment follows an eK$al sign. which is -laced directl( after the t(-e nameA 8o$ can also $se varia/le names. as in void re-char3char re-tCharP;R;. int n$m/erRe-sPEF5I #f one arg$ment is missing when the f$nction is called. it is ass$med to /e the last arg$mentA %he re-char35 f$nction assigns the val$e of the single arg$ment to the ch -arameter and $ses the defa$lt val$e EF for the n -arameterA #f /oth arg$ments are missing. the f$nction assigns the defa$lt val$e QR; to ch and the defa$lt val$e EF to nA %h$s the three calls to the f$nction all wor+. even tho$gh each has a different n$m/er of arg$mentsA Remem/er that missing arg$ments m$st /e the trailing arg$mentsTthose at the end of the arg$ment listA 8o$ can leave o$t the last three arg$ments. /$t (o$ can;t leave o$t the ne=tto-last and then -$t in the lastA %his is reasona/leI how wo$ld the com-iler +now which arg$me nts (o$ meant. if (o$ left o$t some in the middle2 3Missing arg$ments co$ld have /een indicated with commas. /$t commas are notorio$sl( s$/Ject to mis-rints. so the designers of C++ ignored this -ossi/ilit(A5 )ot s$r-risingl(. the com-iler will flag an error if (o$ leave o$t arg$ments for which the f$nction does not -rovide defa$lt val$esA
Defa$lt arg$ments are $sef$l if (o$ don;t want to go to the tro$/le of writing arg$ments that. for e=am-le. almost alwa(s have the same val$eA %he( are also $sef$l in cases where. after a -rogram is written. the -rogrammer decides to increase the ca-a/ilit( of a f$nction /( adding another arg$mentA *sing defa$lt arg$ments means that the e=isting f$nction calls can contin$e to $se the old n$m/er of arg$ments. while new f$nction calls can $se moreA Reference >rg$ments > reference -rovides an aliasTa different nameTfor a varia/leA One of the most im-ortant $ses for references is in -assing arg$ments to f$nctionsA We;ve seen e=am-les of f$nction arg$ments -assed /( val$eA When arg$ments are -assed /( val$e. the called f$nction creates a new varia/le of the same t(-e as the arg$ment and co-ies the arg$ment;s val$e into itA >s we noted. the f$nction cannot access the original varia/le in the calling -rogram. onl( the co-( it createdA Passing arg$ments /( val$e is $sef$l when the f$nction does not need to modif( the original varia/le in the calling -rogramA #n fact. it offers ins$rance that the f$nction cannot harm the original varia/leA Passing arg$ments /( reference $ses a different mechanismA #nstead of a val$e /eing -assed to the f$nction. a reference to the original varia/le. in the calling -rogram. is -assedA 3#t;s act$all( the memory address of the varia/le that is -assed. altho$gh (o$ don;t need to +now thisA5 >n im-ortant advantage of -assing /( reference is that the f$nction can access the act$al varia/les in the calling -rogramA >mong other /enefits. this -rovides a mechanism for -assing more than one val$e from the f$nction /ac+ to the calling -rogramA Passing ,im-le Data %(-es /( Reference ,$--ose (o$ have -airs of n$m/ers in (o$r -rogram and (o$ want to /e s$re that the smaller one alwa(s -recedes the larger oneA %o do this (o$ call a f$nction. order35. which chec+s two n$m/ers -assed to it /( reference and swa-s the originals if the first is larger than the secondA 'ere;s the listing for R0FORD0R1 // reforderAc-// orders two arg$ments -assed /( reference 7incl$de MiostreamN $sing names-ace stdI int main35 O void order3int&. int&5I int n!PUU. nCP!!I int nDPCC. nEPHHI order3n!. nC5I order3nD. nE5I
//-rotot(-e //this -air not ordered //this -air ordered //order each -air of n$m/ers //-rint o$t all n$m/ers
co$t MM 9nDP: MM nD MM endlI co$t MM 9nEP: MM nE MM endlI ret$rn "I S //-------------------------------------------------------------void order3int& n$m/!. int& n$m/C5 //orders two n$m/ers O if3n$m/! N n$m/C5 //if !st larger than Cnd. O int tem- P n$m/!I //swa- them n$m/! P n$m/CI n$m/C P tem-I S #n main35 there are two -airs of n$m/ersTthe first -air is not ordered and the second -air is orderedA %he order35 f$nction is called once for each -air. and then all the n$m/ers are -rinted o$tA %he o$t-$t reveals that the first -air has /een swa--ed while the second -air hasn;tA 'ere it is1 n!P!! nCPUU nDPCC nEPHH #n the order35 f$nction. the first varia/le is called n$m/! and the second is n$m/CA #f n$m/! is greater than n$m/C the f$nction stores n$m/! in tem-. -$ts n$m/C in n$m/!. and finall( -$ts tem- /ac+ in n$m/CA Remem/er that n$m/! and n$m/C are sim-l( different names for whatever arg$ments were -assedI in this case. n! and nC on the first call to the f$nction. and nC and nD on the second callA %he effect is to chec+ the ordering of the original arg$ments in the calling -rogram and swa- them if necessar(A *sing reference arg$ments in this wa( is a sort of remote-control o-erationA %he calling -rogram tells the f$nction what varia/les in the calling -rogram to o-erate on. and the f$nction modifies these varia/les witho$t ever +nowing their real namesA #t;s as if (o$ called the ho$se -ainters and. altho$gh the( never left their office. (o$ sat /ac+ and watched as (o$r dining room walls m(sterio$sl( changed colorA
5 structure is a collection o' sim"le varia(les. The varia(les in a structure can (e o' di''erent ty"es: Some can (e int0 some can (e 'loat0 and so on. (This is unli e the array0 !hich !eHll meet later0 in !hich all the varia(les must (e the same ty"e.* The data items in a structure are called the members o' the structure. +n (oo s on C "rogramming0 structures are o'ten considered an advanced 'eature and are introduced to!ard the end o' the (oo . -o!ever0 'or C++ "rogrammers0 structures are one o' the t!o im"ortant (uilding (loc s in the understanding o' o(6ects and classesA #n fact. the s(nta= of a str$ct$re is almost identical to that of a class. 5 structure (as ty"ically used* is a collection o' data0 !hile a class is a collection o' (oth data and 'unctions. So (y learning a(out structures !eHll (e "aving the !ay 'or an understanding o' classes and o(6ects.
float cost; ;
0n$merations
5s !eHve seen0 structures can (e loo ed at as a !ay to "rovide user:de'ined data ty"es. 5 di''erent a""roach to de'ining your o!n data ty"e is the enumeration. This 'eature o' C++ is less crucial than structures. Nou can !rite "er'ectly good o(6ect:oriented "rograms in C++ !ithout no!ing anything a(out enumerations. -o!ever0 they are very much in the s"irit o' C++0 in that0 (y allo!ing you to de'ine your o!n data ty"es0 they can sim"li'y and clari'y your "rogramming.
int diff ' da%2 9 da%1; 22can do inte+er arithmetic cout << BLa%s !et,een ' B << diff << endl; if(da%1 < da%2) 22can do comparisons cout << Bda%1 comes !efore da%2\nE; return /; 5n enum declaration de'ines the set o' all names that !ill (e "ermissi(le values o' the ty"e. These "ermissi(le values are called enumerators. The enum ty"e days9o'9!ee has seven enumerators: Sun0 &on0 Tue0 and so on0 u" to Sat.
5n enumeration is a list o' all "ossi(le values. This is unli e the s"eci'ication o' an int0 'or e4am"le0 !hich is given in terms o' a range o' values. +n an enum you must give a s"eci'ic name to every "ossi(le value. /igure (elo! sho!s the di''erence (et!een an int and an enum. %nce youHve declared the enum ty"e days9o'9!ee as sho!n0 you can de'ine varia(les o' this ty"e. D5N3N.& has t!o such varia(les0 day= and day;0 de'ined in the statement da%s&of&,ee0 da%1# da%2; (+n C you must use the ey!ord enum (e'ore the ty"e name. enum da%s&of&,ee0 da%1# da%2; +n C++ this isnHt necessary.* Varia(les o' an enumerated ty"e0 li e day= and day;0 can (e given any o' the values listed in the enum declaration. +n the e4am"le !e give them the values &on and Thu. Nou canHt use values that !erenHt listed in the declaration. Such statements as da%1 ' hallo,een; are illegal. Nou can use the standard arithmetic o"erators on enum ty"es. +n the "rogram !e su(tract t!o values. Nou can also use the com"arison o"erators0 as !e sho!. -ereHs the "rogramHs out"ut: La%s !et,een ' da%1 comes !efore da%2 3numerations are treated internally as integers. This e4"lains !hy you can "er'orm arithmetic and relational o"erations on them. %rdinarily the 'irst name in the list is given the value F0 the ne4t name is given the value =0 and so on. +n the D5N3N.& e4am"le0 the values Sun through Sat are stored as the integer values F through C. 5rithmetic o"erations on enum ty"es ta e "lace on the integer values. -o!ever0 although the com"iler no!s that your enum varia(les are really integers0 you must (e care'ul o' trying to ta e advantage o' this 'act. +' you say da%1 ' .; the com-iler will iss$e a warning 3altho$gh it will com-ile5. +tHs (etter to 'orgetS!henever "ossi(leSthat enums are really integers.
Placing data and f$nctions together into a single entit( is the central idea of o/JectV oriented -rogramming
8emem(er0 data constructs li e structures and classes end !ith a semicolon0 !hile control constructs li e 'unctions and loo"s do not.*
0nca-s$lation
The (ody o' the class contains t!o un'amiliar ey!ords: "rivate and "u(lic. #hat is their "ur"oseW 5 ey 'eature o' o(6ect]oriented "rogramming is data hiding. This term does not re'er to the activities o' "articularly "aranoid "rogrammersL rather it means that data is concealed !ithin a class0 so that it cannot (e accessed mista enly (y 'unctions outside the class. The "rimary mechanism 'or hiding data is to "ut it in a class and ma e it "rivate. $rivate data or 'unctions can only (e accessed 'rom !ithin the class. $u(lic data or 'unctions0 on the other hand0 are accessi(le 'rom outside the class. This is sho!n in /igure (elo!:
DonHt con'use data hiding !ith the security techni)ues used to "rotect com"uter data(ases. To "rovide a security measure you might0 'or e4am"le0 re)uire a user to su""ly a "ass!ord (e'ore granting access to a data(ase. The "ass!ord is meant to ee" unauthoriPed or malevolent users 'rom altering (or o'ten even reading* the data. Data hiding0 on the other hand0 means hiding data 'rom "arts o' the "rogram that donHt need to access it. &ore s"eci'ically0 one classHs data is hidden 'rom other classes. Data hiding is designed to "rotect !ell] intentioned "rogrammers 'rom honest mista es. $rogrammers !ho really !ant to can 'igure out a !ay to access "rivate data0 (ut they !ill 'ind it hard to do so (y accident.
Class Data
The smallo(6 class contains one data item: somedata0 !hich is o' ty"e int. The data items !ithin a class are called data members (or sometimes member data*. There can (e any num(er o' data mem(ers in a class0 6ust as there can (e any num(er o' data items in a structure. The data mem(er somedata 'ollo!s the ey!ord "rivate0 so it can (e accessed 'rom !ithin the class0 (ut not 'rom outside.
&em(er /unctions
Member functions are 'unctions that are included !ithin a class. (+n some o(6ect]oriented languages0 such as Smalltal 0 mem(er 'unctions are called methodsL some !riters use this term in C++ as !ell.* There are t!o mem(er 'unctions in smallo(6: setdata(* and sho!data(*. The 'unction (odies o' these 'unctions have (een !ritten on the same line as the (races that delimit them. Nou could also use the more traditional 'ormat 'or these 'unction de'initions: void setdata(int d) { somedata ' d; and void sho,data() { cout << B\nLata is E << somedata; -o!ever0 !hen mem(er 'unctions are small0 it is common to com"ress their de'initions this !ay to save s"ace. 1ecause setdata(* and sho!data(* 'ollo! the ey!ord "u(lic0 they can (e accessed 'rom outside the class. #eHll see ho! this is done in a moment. .
#nline F$nctions
#e mentioned that 'unctions save memory s"ace (ecause all the calls to the 'unction cause the same code to (e e4ecutedL the 'unction (ody need not (e du"licated in memory. #hen the com"iler sees a 'unction call0 it normally generates a 6um" to the 'unction. 5t the end o' the 'unction it 6um"s (ac to the instruction 'ollo!ing the call. #hile this se)uence o' events may save memory s"ace0 it ta es some e4tra time. There must (e an instruction 'or the 6um" to the 'unction (actually the assem(ly:language instruction C5,, or something similar*0 instructions 'or saving registers0 instructions 'or "ushing arguments onto the stac in the calling "rogram and removing them 'rom the stac in the 'unction (i' there are arguments*0 instructions
'or restoring registers0 and an instruction to return to the calling "rogram. The return value (i' any* must also (e dealt !ith. 5ll these instructions slo! do!n the "rogram. To save e4ecution time in short 'unctions0 you may elect to "ut the code in the 'unction (ody directly in line !ith the code in the calling "rogram. That is0 each time thereHs a 'unction call in the source 'ile0 the actual code 'rom the 'unction is inserted0 instead o' a 6um" to the 'unction. The di''erence (et!een a 'unction and inline code is sho!n in /igure (elo!.
,ong sections o' re"eated code are generally (etter o'' as normal 'unctions: The savings in memory s"ace is !orth the com"aratively small sacri'ice in e4ecution s"eed. 1ut ma ing a short section o' code into an ordinary 'unction may result in little savings in memory s"ace0 !hile im"osing 6ust as much time "enalty as a larger 'unction. +n 'act0 i' a 'unction is very short0 the instructions necessary to call it may ta e u" as much s"ace as the instructions !ithin the 'unction (ody0 so that there is not only a time "enalty (ut a s"ace "enalty as !ell.
De'ining %(6ects
The 'irst statement in main(*0 smallo!$ s1# s2; de'ines t!o o(6ects0 s= and s;0 o' class smallo(6. 8emem(er that the declaration 'or the class smallo(6 does not create any o(6ects. +t only descri(es ho! they !ill loo !hen they are created0 6ust as a structure declaration descri(es ho! a structure !ill loo (ut doesnHt create any structure varia(les. +t is the definition that actually creates o(6ects that can (e used (y the "rogram. De'ining an o(6ect is similar to de'ining a varia(le o' any data ty"e: S"ace is set aside 'or it in memory. De'ining o(6ects in this !ay means creating them. This is also called instantiating them. The term instantiating arises (ecause an instance o' the class is created. 5n o(6ect is an instance (that is0 a s"eci'ic e4am"le* o' a class. %(6ects are sometimes called instance variables.
Similarly0 the 'ollo!ing t!o calls to the sho!data(* 'unction !ill cause the t!o o(6ects to dis"lay their values: s1.sho,data();
s2.sho,data();
&essages
Some o(6ect]oriented languages re'er to calls to mem(er 'unctions as messages. Thus the call s1.sho,data(); can (e thought o' as sending a message to s= telling it to sho! its data. The term message is not a 'ormal term in C++0 (ut it is a use'ul idea to ee" in mind as !e discuss mem(er 'unctions. Tal ing a(out messages em"hasiPes that o(6ects are discrete entities and that !e communicate !ith them (y calling their mem(er 'unctions.
Constructor
5 constructor is a mem(er 'unction that is e4ecuted automatically !henever an o(6ect is created. (The term constructor is sometimes a((reviated ctor0 es"ecially in "rogram listings.*
5 Counter 34am"le
5s an e4am"le0 !eHll create a class o' o(6ects that might (e use'ul as a general]"ur"ose "rogramming element. 5 counter is a varia(le that counts things. &ay(e it counts 'ile accesses0 or the num(er o' times the user "resses the a3nterb ey0 or the num(er o' customers entering a (an . 3ach time such an event ta es "lace0 the counter is incremented (= is added to it*. The counter can also (e accessed to 'ind the current count. ,etHs assume that this counter is im"ortant in the "rogram and must (e accessed (y many di''erent 'unctions. +n "rocedural languages such as C0 a counter !ould "ro(a(ly (e im"lemented as an e4ternal
varia(le. This e4am"le0 C%.NT380 "rovides a counter varia(le that can (e modi'ied only through its mem(er 'unctions. 22 counter.cpp 22 o!$ect represents a counter varia!le #include <iostream> usin+ namespace std; 2222222222222222222222222222222222222222222222222222222222222222 class 4ounter { private7 unsi+ned int count; 22count pu!lic7 4ounter() 7 count(/) 22constructor K /\em"ty (ody\/ M void inc9count(* //increment count K count++L M int get9count(* //return count K return countL M ML //////////////////////////////////////////////////////////////// int main(* K Counter c=0 c;L //de'ine and initialiPe cout UU QYnc=[R UU c=.get9count(*L //dis"lay cout UU QYnc;[R UU c;.get9count(*L c=.inc9count(*L c;.inc9count(*L c;.inc9count(*L //increment c= //increment c; //increment c;
cout UU QYnc=[R UU c=.get9count(*L //dis"lay again cout UU QYnc;[R UU c;.get9count(*L cout UU endlL return FL M The Counter class has one data mem(er: count0 o' ty"e unsigned int (since the count is al!ays "ositive*. +t has three mem(er 'unctions: the constructor Counter(*0 !hich !eHll loo at in a momentL inc9count(*0 !hich adds = to countL and get9count(*0 !hich returns the current value o' count.
5utomatic +nitialiPation
#hen an o(6ect o' ty"e Counter is 'irst created0 !e !ant its count to (e initialiPed to F. 5'ter all0 most counts start at F. #e could "rovide a set9count(* 'unction to do this and call it !ith an argument o' F0 or !e could "rovide a Pero9count(* 'unction0 !hich !ould al!ays set count to F. -o!ever0 such 'unctions !ould need to (e e4ecuted every time !e created a Counter o(6ect. 4ounter c1; 22ever% time ,e do this# c1.@ero&count(); 22,e must do this too This is mista e "rone0 (ecause the "rogrammer may 'orget to initialiPe the o(6ect a'ter creating it. +tHs more relia(le and convenient0 es"ecially !hen there are a great many o(6ects o' a given class0 to cause each o(6ect to initialiPe itsel' !hen itHs created. +n the Counter class0 the constructor Counter(* does this. This 'unction is called automatically !henever a ne! o(6ect o' ty"e Counter is created. Thus in main(*0 the statement 4ounter c1# c2;
creates t!o o(6ects o' ty"e Counter. 5s each is created0 its constructor0 Counter(*0 is e4ecuted. This 'unction sets the count varia(le to F. So the e''ect o' this single statement is to not only create t!o o(6ects0 (ut also to initialiPe their count varia(les to F.
+nitialiPer ,ist
%ne o' the most common tas s a constructor carries out is initialiPing data mem(ers. +n the Counter class the constructor must initialiPe the count mem(er to F. Nou might thin that this !ould (e done in the constructorHs 'unction (ody0 li e this: count() K count [ FL M -o!ever0 this is not the "re'erred a""roach (although it does !or *. -ereHs ho! you should initialiPe a data mem(er: count(* : count(F* K M The initialiPation ta es "lace 'ollo!ing the mem(er 'unction declarator (ut (e'ore the 'unction (ody. +tHs "receded (y a colon. The value is "laced in "arentheses 'ollo!ing the mem(er data. +' multi"le mem(ers must (e initialiPed0 theyHre se"arated (y commas. The result is the initializer list (sometimes called (y other names0 such as the memberinitialization list*. someClass(* : m=(D*0 m;(GG*0 m;(>* c initialiPer list K M #hy not initialiPe mem(ers in the (ody o' the constructorW The reasons are com"le40 (ut have to do !ith the 'act that mem(ers initialiPed in the initialiPer list are given a value (e'ore the constructor even starts to e4ecute. This is im"ortant in some situations. /or e4am"le0 the initialiPer list is the only !ay to initialiPe const mem(er data and re'erences. 5ctions more com"licated than sim"le initialiPation must (e carried out in the constructor (ody0 as !ith ordinary 'unctions.
+' this isnHt enough "roo' that the constructor is o"erating as advertised0 !e can re!rite the constructor to "rint a message !hen it e4ecutes. 4ounter() 7 count(/) { cout << B=>m the constructor\nE; No! the "rogramHs out"ut loo s li e this: =>m the constructor =>m the constructor c1'/ c2'/ c1'1 c2'2 5s you can see0 the constructor is e4ecuted t!iceSonce 'or c= and once 'or c;S!hen the statement 4ounter c1# c2; is e4ecuted in main(*.
5utomatic Varia(les
So 'ar almost all the varia(les !eHve used in e4am"le "rograms have (een de'ined inside the 'unction in !hich they are used. That is0 the de'inition occurs inside the (races that delimit the 'unction (ody: void somefunc() { int somevar; 22varia!les defined ,ithin float othervar; 22the function !od% 22 other statements Varia(les may (e de'ined inside main(* or inside other 'unctionsL the e''ect is similar0 since main(* is a 'unction. Varia(les de'ined !ithin a 'unction (ody are called automatic variables. 5ctually0 a ey!ord0 auto0 can (e used to s"eci'y an automatic varia(le. Nou !ould say void somefunc() { auto int somevar; 22same as int somevar auto float othervar; 22same as float othervar 22 other statements -o!ever0 since this is the de'ault0 there is seldom any need to use the auto ey!ord. Varia(les de'ined !ithin a 'unction are automatic any!ay. ,etHs loo at the t!o im"ortant characteristics o' automatic varia(lesSli'etime and visi(ility.
&ifetime
5n automatic varia(le is not created until the 'unction in !hich it is de'ined is called. (&ore accurately0 !e can say that varia(les de'ined !ithin any (loc o' code are not created until the (loc is e4ecuted.* +n the "rogram 'ragment 6ust given0 the varia(les somevar and othervar donHt e4ist until the some'unc(* 'unction is called. That is0 there is no "lace in memory !here their values are storedL they are unde'ined. #hen control is trans'erred to some'unc(*0 the varia(les are created and memory s"ace is set aside 'or them. ,ater0 !hen some'unc(* returns and control is "assed (ac to the calling "rogram0 the varia(les are destroyed and their values are lost. The name automatic is used (ecause the varia(les are automatically created !hen a 'unction is called and automatically destroyed !hen it returns.
The time "eriod (et!een the creation and destruction o' a varia(le is called its li'etime (or sometimes its duration*. The li'etime o' an automatic varia(le coincides !ith the time !hen the 'unction in !hich it is de'ined is e4ecuting. The idea (ehind limiting the li'etime o' varia(les is to save memory s"ace. +' a 'unction is not e4ecuting0 the varia(les it uses during e4ecution are "resuma(ly not needed. 8emoving them 'rees u" memory that can then (e used (y other 'unctionsA
?isi/ilit(
5 varia(leHs visi(ility descri(es the locations !ithin a "rogram 'rom !hich it can (e accessed. +t can (e re'erred to in statements in some "arts o' the "rogramL (ut in others0 attem"ts to access it lead to an un no!n varia(le error message. The !ord sco"e is also used to descri(e visi(ility. The sco"e o' a varia(le is that "art o' the "rogram !here the varia(le is visi(le. 5utomatic varia(les are only visi(le0 meaning they can only (e accessed0 !ithin the 'unction in !hich they are de'ined. Su""ose you have t!o 'unctions in a "rogram: void some'unc(* K int somevarL //automatic varia(les 'loat othervarL somevar [ =FL //%K othervar [ ==L //%K ne4tvar [ =;L //illegal: not visi(le in some'unc(* M void other'unc(* K int ne4tvarL //automatic varia(le somevar [ ;FL //illegal: not visi(le in other'unc(* othervar [ ;=L //illegal: not visi(le in other'unc(* ne4tvar [ ;;L //%K M The varia(le ne4tvar is invisi(le in 'unction some'unc(*0 and the varia(les somevar and othervar are invisi(le in other'unc(*. ,imiting the visi(ility o' varia(les hel"s organiPe and modulariPe the "rogram. Nou can (e con'ident that the varia(les in one 'unction are sa'e 'rom accidental alteration (y other 'unctions (ecause the other 'unctions canHt see them. This is an im"ortant "art o' structured "rogramming0 the methodology 'or organiPing old:'ashioned "rocedural "rograms. ,imiting visi(ility is also an im"ortant "art o' %(6ect: %riented $rogramming. +n the case o' automatic varia(les0 li'etime and visi(ility coincide: These varia(les e4ist only !hile the 'unction in !hich they are de'ined is e4ecuting0 and are only visi(le !ithin that 'unction. /or some storage classes0 ho!ever0 li'etime and visi(ility are not the same. +nitialiPation #hen an automatic varia(le is created0 the com"iler does not try to initialiPe it. Thus it !ill start o'' !ith an ar(itrary value0 !hich may (e F (ut "ro(a(ly !ill (e something else. +' you !ant it initialiPed0 you must do it e4"licitly0 as in int n [ GGL then it !ill start o'' !ith this value. 5utomatic varia(les are sometimes called local varia(les0 since they are visi(le only locally0 in the 'unction !here they are de'ined.
0=ternal ?aria/les
The ne4t ma6or storage class is external. #hile automatic varia(les are de'ined !ithin 'unctions0 e4ternal varia(les are de'ined outside o' (e4ternal to* any 'unction. 5n e4ternal varia(le is visi(le to all the
'unctions in a "rogram. &ore "recisely0 it is visi(le to all those 'unctions that 'ollo! the varia(leHs de'inition in the listing. .sually you !ant e4ternal varia(les to (e visi(le to all 'unctions0 so you "ut their declarations at the (eginning o' the listing. 34ternal varia(les are also called global variables since they are no!n (y all the 'unctions in a "rogram. -ereHs a "rogram0 3AT38N0 in !hich three 'unctions all access an e4ternal varia(le. 22 e"tern.cpp 22 demonstrates e"ternal varia!les #include <iostream> usin+ namespace std; #include <conio.h> 22for +etch() char ch ' Na>; void +etachar(); void putachar(); int main() { ,hile( ch O' N\r> ) { +etachar(); putachar(); cout << endl; return /; 2299999999999999999999999999999999999999999999999999999999999999 void +etachar() 22+etachar() accesses ch { ch ' +etch(); 2299999999999999999999999999999999999999999999999999999999999999 void putachar() 22putachar() accesses ch { cout << ch; 22e"teral varia!le ch 22function declarations
22main() accesses ch
%ne 'unction in 3AT38N0 getachar(*0 reads characters 'rom the ey(oard. +t uses the li(rary 'unction getch(*0 !hich is li e getche(* e4ce"t that it doesnHt echo the character ty"ed to the screen (hence the a(sence o' the 'inal e in the name*. 5 second 3AT38N 'unction0 "utachar(*0 dis"lays each character on the screen. The e''ect is that !hat you ty"e is dis"layed in the normal !ay: +Hm ty"ing in this line o' te4t The signi'icant thing a(out this "rogram is that the varia(le ch is not de'ined in any o' the 'unctions. +nstead it is de'ined at the (eginning o' the 'ile0 (e'ore the 'irst 'unction. +t is an e4ternal varia(le. 5ny 'unction that 'ollo!s the de'inition o' ch in the listing can access itSin this case all the 'unctions in 3AT38N: main(*0 getachar(*0 and "utachar(*. Thus the visi(ility o' ch is the entire source 'ile.
#nitialiLation
+' an e4ternal varia(le is initialiPed0 as in int e4var [ =BBL this initialiPation ta es "lace !hen the 'ile is 'irst loaded. +' an e4ternal varia(le is not initialiPed e4"licitly (y the "rogramL 'or e4am"le0 i' it is de'ined as int e4varL then it is initialiPed automatically to F !hen it is created. (This is unli e automatic varia(les0 !hich are not initialiPed and "ro(a(ly contain random or gar(age values !hen they are created.*
Static Varia(les
#eHll touch on another storage class: static. -ere !e are concerned !ith static automatic varia(les. There are static e4ternal varia(les0 (ut their meaning !ill (e discussed !hen need arises. 5 static automatic varia(le has the visi(ility o' a local varia(le (that is0 inside the 'unction containing it*. +ts li'etime is similar to that o' an e4ternal varia(le0 e4ce"t that it doesnHt come into e4istence until the 'irst call to the 'unction containing it. Therea'ter it remains in e4istence 'or the li'e o' the "rogram. Static automatic varia(les are used !hen itHs necessary 'or a 'unction to remem(er a value !hen it is not (eing e4ecutedL that is0 (et!een calls to the 'unction. +n the ne4t e4am"le0 a 'unction0 getavg(*0 calculates a running average. +t remem(ers the total o' the num(ers it has averaged (e'ore0 and ho! many there !ere. 3ach time it receives a ne! num(er0 sent as an argument 'rom the calling "rogram0 it adds this num(er to the total0 adds = to a count0 and returns the ne! average (y dividing the total (y the count. -ereHs the listing 'or ST5T+C: // static.c"" // demonstrates static varia(les Tinclude UiostreamV using names"ace stdL 'loat getavg('loat*L //declaration int main(* K 'loat data[=0 avgL !hile( data J[ F * K cout UU Q3nter a num(er: RL cin VV dataL avg [ getavg(data*L cout UU QNe! average is R UU avg UU endlL M return FL M //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // getavg(* // 'inds average o' old "lus ne! data 'loat getavg('loat ne!data* K static 'loat total [ FL //static varia(les are initialiPed static int count [ FL // only once "er "rogram count++L //increment count
total +[ ne!dataL //add ne! data to total return total / countL //return the ne! average M -ereHs some sam"le interaction: 3nter a num(er: =F Ne! average is =F ctotal is =F0 count is = 3nter a num(er: ;F Ne! average is =? ctotal is GF0 count is ; 3nter a num(er: GF Ne! average is ;F ctotal is CF0 count is G The static varia(les total and count in getavg(* retain their values a'ter getavg(* returns0 so theyHre availa(le the ne4t time itHs called.
+nitialiPation
#hen static varia(les are initialiPed0 as total and count are in getavg(*0 the initialiPation ta es "lace only onceSthe 'irst time their 'unction is called. They are not reinitialiPed on su(se)uent calls to the 'unction0 as ordinary automatic varia(les are.
,torage
+' youHre 'amiliar !ith o"erating system architecture0 you might (e interested to no! that automatic varia(les are stored on the stac 0 !hile e4ternal and static varia(les are stored on the hea" %a/le Storage Ty"es >$tomatic Visi(ility 'unction ,i'etime 'unction +nitialiPed value not initialiPed Storage stac $ur"ose Varia(les used (y a single 'unction. ,tatic >$to 'unction "rogram F hea" Same as auto0 (ut must retain value !hen 'unction terminates. 0=ternal 'ile "rogram F hea" Varia(les used (y several 'unctions
DoV#tV8o$rself Data
Constructors are "retty amaPing !hen you thin a(out it. #hoever !rites language com"ilers ('or C or 15S+C or even 'or C++* must e4ecute the e)uivalent o' a constructor !hen the user de'ines a varia(le. +' you de'ine an int0 'or e4am"le0 some!here thereHs a constructor allocating 'our (ytes o' memory 'or it. +' !e can !rite our o!n constructors !e can start to ta e over some o' the tas s o' a com"iler !riter. This is one ste" on the "ath to creating our o!n data ty"es0 as !eHll see later.
"rotected: int 4Co0 yCoL int radiusL color 'illcolorL 'style 'illstyleL "u(lic:
//constructor circle(int 40 int y0 int r0 color 'c0 'style 's* : 4Co(4*0 yCo(y*0 radius(r*0 'illcolor('c*0 'illstyle('s* K M void dra!(* //dra!s the circle K set9color('illcolor*L //set color set9'ill9style('illstyle*L //set 'ill dra!9circle(4Co0 yCo0 radius*L //dra! solid circle M ML //////////////////////////////////////////////////////////////// int main(* K init9gra"hics(*L //initialiPe gra"hics system //create circles circle c=(=?0 D0 ?0 c1,.30 A9/+,,*L circle c;(>=0 =;0 D0 c83D0 %9/+,,*L circle cG(C?0 =^0 >0 c2833N0 &3D+.&9/+,,*L c=.dra!(*L //dra! circles c;.dra!(*L cG.dra!(*L set9cursor9"os(=0 ;?*L //lo!er le't corner return FL M This "rogram is similar to C+8C,3S0 e4ce"t that set(* has (een re"laced (y the constructor. Note ho! this sim"li'ies main(*. +nstead o' t!o se"arate statements 'or each o(6ect0 one to create it and one to set its attri(utes0 no! one statement (oth creates the o(6ect and sets its attri(utes at the same time.
Destructors
We;ve seen that a s-ecial mem/er f$nctionTthe constr$ctorTis called automatically !hen an
o(6ect is 'irst created. Nou might guess that another 'unction is called automatically !hen an o(6ect is destroyed. This is indeed the case. Such a 'unction is called a destructor. 5 destructor has the same name as the constructor (!hich is the same as the class name* (ut is "receded (y a tilde: class /oo K "rivate: int dataL "u(lic: /oo(* : data(F* //constructor (same name as class* K M d/oo(* //destructor (same name !ith tilde* K M ML ,i e constructors0 destructors do not have a return value. They also ta e no arguments (the assum"tion (eing that thereHs only one !ay to destroy an o(6ect*. The most common use o' destructors is to deallocate memory that !as allocated 'or the o(6ect (y the constructor.
Pol(mor-hism
The static "olymor"hism is im"lemented (y %verloading and dynamic "olymor"hism is done (y a conce"t ,ate 1inding
%verloaded /unctions
5n overloaded 'unction a""ears to "er'orm di''erent activities de"ending on the ind o' data sent to it. %verloading is li e the 6o e a(out the 'amous scientist !ho insisted that the thermos (ottle !as the greatest invention o' all time. #hyW Q+tHs a miracle device0R he said. Q+t ee"s hot things hot0 (ut cold things it ee"s cold. -o! does it no!WR +t may seem e)ually mysterious ho! an overloaded 'unction no!s !hat to do. +t "er'orms one o"eration on one ind o' data (ut another o"eration on a di''erent ind. ,etHs clari'y matters !ith some e4am"les.
'or(int 6[FL 6U>?L 6++* // al!ays loo"s >? times cout UU chL // "rints s"eci'ied character cout UU endlL M //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // re"char(* // dis"lays s"eci'ied num(er o' co"ies o' s"eci'ied character void re"char(char ch0 int n* K 'or(int 6[FL 6UnL 6++* // loo"s n times cout UU chL // "rints s"eci'ied character cout UU endlL M This "rogram "rints out three lines o' characters. -ereHs the out"ut: \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ ++++++++++++++++++++++++++++++ The 'irst t!o lines are >? characters long0 and the third is GF. The "rogram contains three 'unctions !ith the same name. There are three declarations0 three 'unction calls0 and three 'unction de'initions. #hat ee"s the com"iler 'rom (ecoming ho"elessly con'usedW +t uses the num(er o' arguments0 and their data ty"es0 to distinguish one 'unction 'rom another. +n other !ords0 the declaration void re"char(*L !hich ta es no arguments0 descri(es an entirely di''erent 'unction than the declaration void re"char(char*L !hich ta es one argument o' ty"e char0 or the declaration void re"char(char0 int*L !hich ta es one argument o' ty"e char and another o' ty"e int. The com"iler0 seeing several 'unctions !ith the same name (ut di''erent num(ers o' arguments0 could decide the "rogrammer had made a mista e (!hich is !hat it !ould do in C*. +nstead0 it very tolerantly sets u" a se"arate 'unction 'or every such de'inition. #hich one o' these 'unctions !ill (e called de"ends on the num(er o' arguments su""lied in the call. /igure (elo! sho!s this "rocess.
#nheritance
Inheritance is "ro(a(ly the most "o!er'ul 'eature o' %(6ect:%riented $rogramming0 a'ter classes
themselves. +nheritance is the "rocess o' creating ne! classes0 called derived classes0 'rom e4isting or base classes. The derived class inherits all the ca"a(ilities o' the (ase class (ut can add em(ellishments and re'inements o' its o!n. The (ase class is unchanged (y this "rocess. The inheritance relationshi" is sho!n in /igure (elo!. The arro! goes in the o""osite direction o' !hat you might e4"ect. +' it "ointed do!n !e !ould la(el it inheritance. -o!ever0 the more common a""roach is to "oint the arro! u"0 'rom the derived class to the (ase class0 and to thin o' it as a Qderived 'romR arro!. +nheritance is an essential "art o' %%$. +ts (ig "ayo'' is that it "ermits code reusabilit#. %nce a (ase class is !ritten and de(ugged0 it need not (e touched again0 (ut0 using inheritance0 can nevertheless (e ada"ted to !or in di''erent situations. 8eusing e4isting code saves time and money and increases a "rogramHs relia(ility. +nheritance can also hel" in the original conce"tualiPation o' a "rogramming "ro(lem0 and in the overall design o' the "rogram. 5n im"ortant result o' reusa(ility is the ease o' distri(uting class li(raries. 5 "rogrammer can use a class created (y another "erson or com"any0 and0 !ithout modi'ying it0 derive other classes 'rom it that are suited to "articular situations.
,etHs su""ose that !e have !or ed long and hard to ma e the Counter class o"erate 6ust the !ay !e !ant0 and !eHre "leased !ith the results0 e4ce"t 'or one thing. #e really need a !ay to decrement the count. $erha"s !eHre counting "eo"le entering a (an 0 and !e !ant to increment the count !hen they come in and decrement it !hen they go out0 so that the count re"resents the num(er o' "eo"le in the (an at any moment. #e could insert a decrement routine directly into the source code o' the Counter class. -o!ever0 there are several reasons !hy !e might not !ant to do this. /irst0 the Counter class !or s very !ell and has undergone many hours o' testing and de(ugging. (%' course thatHs an e4aggeration in this case0 (ut it !ould (e true in a larger and more com"le4 class.* +' !e start 'ooling around !ith the source code 'or Counter0 the testing "rocess !ill need to (e carried out again0 and o' course !e may 'oul something u" and s"end hours de(ugging code that !or ed 'ine (e'ore !e modi'ied it. +n some situations there might (e another reason 'or not modi'ying the Counter class: #e might not have access to its source code0 es"ecially i' it had (een distri(uted as "art o' a class li(rary. To avoid these "ro(lems !e can use inheritance to create a ne! class (ased on Counter0 !ithout modi'ying Counter itsel'. -ereHs the listing 'or C%.NT3N0 !hich includes a ne! class0 CountDn0 that adds a decrement o"erator to the Counter class: 22 counten.cpp 22 inheritance ,ith 4ounter class #include <iostream> usin+ namespace std; 2222222222222222222222222222222222222222222222222222222222222222 class 4ounter 22!ase class { protected7 22;D(P7 not private unsi+ned int count; 22count pu!lic7
4ounter() 7 count(/) { 4ounter(int c) 7 count(c) { unsi+ned int +et&count() const K return countL M Counter increment(* //incr count ("re'i4* K return Counter(++count*L M ML //////////////////////////////////////////////////////////////// class CountDn : "u(lic Counter //derived class K "u(lic: Counter decrement(*//decr count ("re'i4* K return Counter(::count*L M ML //////////////////////////////////////////////////////////////// int main(* K CountDn c=L //c= o' class CountDn cout UU QYnc=[R UU c=.get9count(*L //dis"lay c=
c=.increment(*L c=. increment(*L c=. increment(*L //increment c=0 G times cout UU QYnc=[R UU c=.get9count(*L //dis"lay it c=.decrement(*L c=.decrement(*L cout UU QYnc=[R UU c=.get9count(*L cout UU endlL return FL M //decrement c=0 t!ice //dis"lay it
The listing starts o'' !ith the Counter class0 !hich (!ith one small e4ce"tion0 !hich !eHll loo at later* has not changed since its a""earance in C%.NT$$G.
O$t-$t of CO*)%0)
+n main(* !e increment c= three times0 "rint out the resulting value0 decrement c= t!ice0 and 'inally "rint out its value again. -ereHs the out"ut: c1'/ <<<< after initiali@ation c1'<<<< after **c1# **c1# **c1 c1'1 <<<< after 99c1# 99c1 The increment o"erator0 the constructors0 the get9count(* 'unction in the Counter class0 and the decrement in the CountDn class all !or !ith o(6ects o' ty"e CountDn.
This is all !e need to no! i' !e donHt use inheritance. #ith inheritance0 ho!ever0 there is a !hole ra't o' additional "ossi(ilities. The )uestion that concerns us at the moment is0 can mem(er 'unctions o' the derived class access mem(ers o' the (ase classW +n other !ords0 can o"erator::(* in CountDn access count in CounterW The ans!er is that mem(er 'unctions can access mem(ers o' the (ase class i' the mem(ers are "u(lic0 or i' they are "rotected. They canHt access "rivate mem(ers. #e donHt !ant to ma e count "u(lic0 since that !ould allo! it to (e accessed (y any 'unction any!here in the "rogram and eliminate the advantages o' data hiding. 5 "rotected mem(er0 on the other hand0 can (e accessed (y mem(er 'unctions in its o!n class orSand hereHs the eySin any class derived 'rom its o!n class. +t canHt (e accessed 'rom 'unctions outside these classes0 such as main(*. This is 6ust !hat !e !ant. The situation is sho!n (elo! : +nheritance and 5ccessi(ility >ccess >ccessi/le from >ccessi/le from >ccessi/le from ,-ecifier Own Class Derived Class O/Jects O$tside Class $u(lic yes yes yes $rotected yes yes no $rivate yes no no 5ccess s"eci'iers !ith inheritance.
The moral is that i' you are !riting a class that you sus"ect might (e used0 at any "oint in the 'uture0 as a (ase class 'or other classes0 then any mem(er data that the derived classes might need to access should (e made "rotected rather than "rivate. This ensures that the class is Qinheritance ready.R
Dangers of -rotected
Nou should no! that thereHs a disadvantage to ma ing class mem(ers "rotected. Say youHve !ritten a class li(rary0 !hich youHre distri(uting to the "u(lic. 5ny "rogrammer !ho (uys this li(rary can access "rotected mem(ers o' your classes sim"ly (y deriving other classes 'rom them. This ma es "rotected mem(ers considera(ly less secure than "rivate mem(ers. To avoid corru"ted data0 itHs o'ten sa'er to 'orce derived classes to access data in the (ase class using only "u(lic 'unctions in the (ase class0 6ust as ordinary main(* "rograms must do. .sing the "rotected s"eci'ier leads to sim"ler "rogramming0 so !e rely on itS "erha"s a (it too muchSin the e4am"les in this (oo . NouHll need to !eigh the advantages o' "rotected against its disadvantages in your o!n "rograms.
Other %erms
+n some languages the (ase class is called the superclass and the derived class is called the subclass. Some !riters also re'er to the (ase class as the parent and the derived class as the child.
22 constructors in derived class #include <iostream> usin+ namespace std; 2222222222222222222222222222222222222222222222222222222222222222 class 4ounter { protected7 22;D(P7 not private unsi+ned int count; 22count pu!lic7 4ounter() 7 count() 22constructor# no ar+s { 4ounter(int c) 7 count(c) 22constructor# one ar+ { unsi+ned int +et&count() const 22return count { return count; 4ounter increment() 22incr count { return 4ounter(**count); ; 2222222222222222222222222222222222222222222222222222222222222222 class 4ountLn 7 pu!lic 4ounter { pu!lic7 4ountLn() 7 4ounter() 22constructor# no ar+s { 4ountLn(int c) 7 4ounter(c) 22constructor# 1 ar+ { 4ountLn decrement() 22decr count (prefi") K return CountDn(::count*L M ML //////////////////////////////////////////////////////////////// int main(* K CountDn c=L //class CountDn CountDn c;(=FF*L cout UU QYnc=[R UU c=.get9count(*L cout UU QYnc;[R UU c;.get9count(*L //dis"lay //dis"lay //increment c=
c=.increment(*L c=.increment(*L c=.increment(*L cout UU QYnc=[R UU c=.get9count(*L //dis"lay it c;.decrement(*Lc;.decrement(*L cout UU QYnc;[R UU c;.get9count(*L
//decrement c; //dis"lay it
CountDn cG [ c;.decrement(*L //create cG 'rom c; cout UU QYncG[R UU cG.get9count(*L //dis"lay cG cout UU endlL return FL M This "rogram uses t!o ne! constructors in the CountDn class. -ere is the one:argument constructor: CountDn(* : Counter(* KM This constructor has an un'amiliar 'eature: the 'unction name 'ollo!ing the colon. This construction causes the CountDn(* constructor to call the Counter(* constructor in the (ase class. +n main(*0 !hen !e say CountDn c=L the com"iler !ill create an o(6ect o' ty"e CountDn and then call the CountDn constructor to initialiPe it. This constructor !ill in turn call the Counter constructor0 !hich carries out the !or . The CountDn(* constructor could
add additional statements o' its o!n0 (ut in this case it doesnHt need to0 so the 'unction (ody (et!een the (races is em"ty. Calling a constructor 'rom the initialiPation list may seem odd0 (ut it ma es sense. Nou !ant to initialiPe any varia(les0 !hether theyHre in the derived class or the (ase class0 (e'ore any statements in either the derived or (ase: class constructors are e4ecuted. 1y calling the (ase:class constructor (e'ore the derived:class constructor starts to e4ecute0 !e accom"lish this. The statement CountDn c;(=FF*L in main(* uses the one:argument constructor in CountDn. This constructor also calls the corres"onding one: argument constructor in the (ase class: CountDn(int c* : Counter(c* WWWW argument c is "assed to Counter KM This construction causes the argument c to (e "assed 'rom CountDn(* to Counter(*0 !here it is used to initialiPe the o(6ect. +n main(*0 a'ter initialiPing the c= and c; o(6ects0 !e increment one and decrement the other and then "rint the results. The one:argument constructor is also used in an assignment statement. CountDn cG [ c;.decrement(*L
void "ush(int var* //"ut num(er on stac K i'(to" V[ &5A:=* //error i' stac 'ull K cout UU QYn3rror: stac is 'ullRL e4it(=*L M Stac ::"ush(var*L //call "ush(* in Stac class M int "o"(* //ta e num(er o'' stac K i'(to" U F* //error i' stac em"ty K cout UU QYn3rror: stac is em"tyYnRL e4it(=*L M return Stac ::"o"(*L //call "o"(* in Stac class M ML //////////////////////////////////////////////////////////////// int main(* K Stac ; s=L s=."ush(==*L s=."ush(;;*L s=."ush(GG*L //"ush some values onto stac
cout UU endl UU s=."o"(*L cout UU endl UU s=."o"(*L cout UU endl UU s=."o"(*L cout UU endl UU s=."o"(*L cout UU endlL return FL M
//"o" some values 'rom stac //oo"s0 "o""ed one too many...
+ntroduction to #indo!s $rogramming (5s"ects o' #indo!s* 1oth #indo!s B^ and #indo!s NT are G;:(it "reem"tive multitas ing and multithreading gra"hical o"erating systems. #indo!s "ossesses a gra"hical user inter'ace (2.+*0 sometimes also called a Ivisual inter'aceI or Igra"hical !indo!ing environment.I The conce"ts (ehind the 2.+ date 'rom the mid:=BDFs !ith the !or done at the Aero4 $58C 'or machines such as the 5lto and the Star and 'or environments such as SmallTal . This !or !as later (rought into the mainstream and "o"ulariPed (y 5""le Com"uter and &icroso't. 5lthough some!hat controversial 'or a !hile0 it is no! )uite o(vious that the 2.+ is (in the !ords o' &icroso't7s Charles Simonyi* the single most im"ortant Igrand consensusI o' the "ersonal:com"uter industry. 3vent Driven $rogramming Vs Traditional $rogramming 5ll 2.+s ma e use o' gra"hics on a (itma""ed video dis"lay. 2ra"hics "rovides (etter utiliPation o' screen real estate0 a visually rich environment 'or conveying in'ormation0 and the "ossi(ility o' a #NS+#N2 (!hat you see is !hat you get* video dis"lay o' gra"hics and 'ormatted te4t "re"ared 'or a "rinted document. +n earlier days0 the video dis"lay !as used solely to echo te4t that the user ty"ed using the ey(oard. +n a gra"hical user inter'ace0 the video dis"lay itsel' (ecomes a source o' user in"ut. The video dis"lay sho!s various gra"hical o(6ects in the 'orm o' icons and in"ut devices such as (uttons and scroll (ars. .sing the ey(oard (or0 more directly0 a "ointing device such as a mouse*0 the user can directly mani"ulate these o(6ects on the screen. 2ra"hics o(6ects can (e dragged0 (uttons can (e "ushed0 and scroll (ars can (e scrolled. The interaction (et!een the user and a "rogram thus (ecomes more intimate. 8ather than the one:!ay cycle o' in'ormation 'rom the ey(oard to the "rogram to the video dis"lay0 the user directly interacts !ith the o(6ects on the dis"lay. %very user interaction (#e-uest! with the )pplication triggers an %vent and the )pplication handles it.
5n o"erating system cannot im"lement multitas ing !ithout doing something a(out memory management. 5s ne! "rograms are started u" and old ones terminate0 memory can (ecome 'ragmented. The system must (e a(le to consolidate 'ree memory s"ace. This re)uires the system to move (loc s o' code and data in memory. 3ven #indo!s =.F0 running on an ^F^^ micro"rocessor0 !as a(le to "er'orm this ty"e o' memory management. .nder real:mode restrictions0 this a(ility can only (e regarded as an astonishing 'eat o' so't!are engineering. +n #indo!s =.F0 the C>F: ilo(yte (K1* memory limit o' the $C7s architecture !as e''ectively stretched !ithout re)uiring any additional memory. 1ut &icroso't didn7t sto" there: #indo!s ;.F gave the #indo!s a""lications access to e4"anded memory (3&S*0 and #indo!s G.F ran in "rotected mode to give #indo!s a""lications access to u" to =C &1 o' e4tended memory. #indo!s NT and #indo!s B^ (lo! a!ay these old limits (y (eing 'ull:'ledged G;:(it o"erating systems !ith 'lat memory s"ace. $rograms running in #indo!s can share routines that are located in other 'iles called Idynamic:lin li(raries.I #indo!s includes a mechanism to lin the "rogram !ith the routines in the dynamic:lin li(raries at run time. #indo!s itsel' is (asically a set o' dynamic:lin li(raries. (rograms written for .indows do not directly access the hardware of graphics display devices such as the screen and printer. +nstead0 #indo!s includes a gra"hics "rogramming language (called the 2ra"hics Device +nter'ace0 or 2D+* that allo!s the easy dis"lay o' gra"hics and 'ormatted te4t. #indo!s virtualiPes dis"lay hard!are. > -rogram written for Windows will r$n with an( video /oard or an( -rinter for which a Windows device driver is availa/le. The "rogram does not need to determine !hat ty"e o' device is attached to the system.
D(namic &in+ing
Central to the !or ings o' #indo!s is a conce"t no!n as Idynamic lin ing.I #indo!s "rovides a !ealth o' 'unction calls that an a""lication can ta e advantage o'0 mostly to im"lement its user inter'ace and dis"lay te4t and gra"hics on the video dis"lay. These 'unctions are im"lemented in dynamic:lin li(raries0 or D,,s. These are 'iles !ith the e4tension .D,, or sometimes .3A30 and they are mostly located in the Y#+ND%#SYSNST3& su(directory under #indo!s B^ and the Y#+NNTYSNST3& and Y#+NNTYSNST3&G; su(directories under #indo!s NT. +n the early days0 the great (ul o' #indo!s !as im"lemented in 6ust three dynamic:lin li(raries. These re"resented the three main su(systems o' #indo!s0 !hich !ere re'erred to as /ernel, 0ser, and 1"I. #hile the num(er o' su(systems has "roli'erated in recent versions o' #indo!s0 most 'unction calls that a ty"ical #indo!s "rogram ma es !ill still 'all in one o' these three modules. Kernel (!hich is currently im"lemented (y the =C:(it K8N,G^C.3A3 and the G;:(it K38N3,G;.D,,* handles all the stu'' that an o"erating system ernel traditionally handlesSmemory management0 'ile +/%0 and tas ing. .ser (im"lemented in the =C:(it .S38.3A3 and the G;:(it .S38G;.D,,* re'ers to the user inter'ace0 and im"lements all the !indo!ing logic. 2D+ (im"lemented in the =C:(it 2D+.3A3 and the G;:(it 2D+G;.D,,* is the 2ra"hics Device +nter'ace0 !hich allo!s a "rogram to dis"lay te4t and gra"hics on the screen and "rinter. +n your #indo!s "rogram0 you use the #indo!s 'unction calls in generally the same !ay you use C li(rary 'unctions such as strlen. The "rimary di''erence is that the machine code for $ librar# functions is lin%ed into #our program code whereas the code for &indows functions is located outside of #our program in the '((s . #hen you run a #indo!s "rogram0 it inter'aces to #indo!s through a "rocess called Idynamic lin ing.I 5 #indo!s .3A3 'ile contains re'erences to the various dynamic:lin li(raries it uses and the 'unctions therein. #hen a #indo!s "rogram is loaded into memory0 the calls in the "rogram are resolved to "oint to the entries o' the D,, 'unctions0 !hich are also loaded into memory i' not already there. #hen you lin a #indo!s "rogram to "roduce an e4ecuta(le 'ile0 you must lin !ith s"ecial Iim"ort li(rariesI "rovided !ith your "rogramming environment. These im"ort li(raries contain the dynamic:lin li(rary names and re'erence in'ormation 'or all the #indo!s 'unction calls. The lin er uses this in'ormation to construct the ta(le in the .3A3 'ile that #indo!s uses to resolve calls to #indo!s 'unctions !hen loading the "rogram
To a "rogrammer0 an o"erating system is de'ined (y its 5$+. )n )(I encompasses all the function calls that an application program can make of an operating system, as well as definitions of associated data types and structures. The (iggest change in the #indo!s 5$+ and its synta4 came a(out during the s!itch 'rom a =C:(it architecture to a G;:(it architecture. Versions =.F through G.= o' #indo!s used the so:called segmented memory mode o' the =C:(it +ntel ^F^C0 ^F^^0 and ;^C micro"rocessors0 a mode that !as also su""orted 'or com"ati(ility "ur"oses in the G;:(it +ntel micro"rocessors (eginning !ith the G^C. The micro"rocessor register siPe in this mode !as =C (its0 and hence the C int data ty"e !as also =C (its !ide. +n the segmented memory model0 memory addresses !ere 'ormed 'rom t!o com"onentsSa =C:(it segment "ointer and a =C:(it offset "ointer. /rom the "rogrammer7s "ers"ective0 this !as )uite messy and involved di''erentiating (et!een long or far "ointers (!hich involved (oth a segment address and an o''set address* and short or near "ointers (!hich involved an o''set address !ith an assumed segment address*. 1eginning in #indo!s NT and #indo!s B?0 #indo!s su""orted a G;:(it 'lat memory model using the G;:(it modes o' the +ntel G^C0 >^C0 and $entium "rocessors. The C int data ty"e !as "romoted to a G;:(it value. $rograms !ritten 'or G;:(it versions o' #indo!s use sim"le G;:(it "ointer values that address a 'lat linear address s"ace. The 5$+ 'or the =C:(it versions o' #indo!s (#indo!s =.F through #indo!s G.=* is no! no!n as #in=C. The 5$+ 'or the G;:(it versions o' #indo!s (#indo!s B?0 #indo!s B^0 and all versions o' #indo!s NT* is no! no!n as #inG;. &any 'unction calls remained the same in the transition 'rom #in=C to #inG;0 (ut some needed to (e enhanced. /or e4am"le0 gra"hics coordinate "oints changed 'rom =C:(it values in #in=C to G;:(it values in #inG;. 5lso0 some #in=C 'unction calls returned a t!o:dimensional coordinate "oint "ac ed in a G;:(it integer. This !as not "ossi(le in #inG;0 so ne! 'unction calls !ere added that !or ed in a di''erent !ay. 5ll G;:(it versions o' #indo!s su""ort (oth the #in=C 5$+ to ensure com"ati(ility !ith old a""lications and the #inG; 5$+ to run ne! a""lications.
M$lti %hreading
+' the 5""lication is &ulti Threaded 0 then there could me &ulti"le %"erations ha""ening at the same "oint o' time.5n a""lication gets a minimum o' one thread i.e. Thread &5+N. %ther threads are started 'rom the &ain .
,(nchroniLation
5s soon as there is more than one thread running in the system0 a !hole ne! category o' "ro(lems may "o" u" that !ere not "resent in a single:threaded environment. The )uestion that it all comes do!n to is0 I+s there data that is visi(le to more than one threadWI +' the ans!er to this )uestion is INo0I things do not (ecome too much more com"licated than in the single:threaded version. 5ll one needs to do in this case is to dis"atch the threads0 !ait until they return0 and (i' a""lica(le* gather the results. +' the ans!er to the a(ove )uestion is INes0I ho!ever0 more !or needs to (e done. #e 'irst need to determine !hat the critical data is and ho! to "ut the access to it into an order that does not a''ect the correct e4ecution o' the "rogram. 5'ter that0 !e need to ensure that the "rotection mechanisms do not a''ect the liveness o' the a""lication. ,et us (e a little more clear a(out !hat Icon'use one threadI means. 5 ty"ical e4am"le 'or this scenario is the 'ollo!ing: T!o threads have access to the same varia(le 4 and (oth e4ecute this code se)uence at some "oint: " ' "*1/ %n most "rocessors0 this addition is not an atomic instruction0 that is0 the com"iler !ould generate more than one instruction o' machine code 'or that source statement. /or e4am"le0 it might do something li e this:
mov a"#Q"R add a"#1/ mov Q"R#a" #e !ould e4"ect that !hen (oth threads e4ecute this se)uence0 the value o' 4 a'ter (oth threads are done is ;F higher than it !as (e'ore the 'irst thread e4ecuted it. -o!ever0 i' one thread gets "reem"ted (y the o"erating system a'ter having e4ecuted the 'irst mov instruction0 the other thread !ill "ic u" the same value o' 4 as the 'irst thread0 (oth !ill add =F onto that value0 and !hen the threads store the result o' the addition (ac into 40 one !ill over!rite the u"dated 4 varia(le !ith the same value. Thus0 a'ter (oth threads have e4ecuted the se)uence0 4 !ill (e only =F higher than it !as (e'oreJ #e need to esta(lish some mechanism to shield 4 'rom (eing accessed concurrently 'rom the t!o threads. Shared data con'licts may mani'est themselves in a lot o' !ays0 not only the one mentioned in the "revious "aragra"h. /or e4am"le0 one thread might "ic u" the value o' a shared varia(le and !or on it0 assuming that it does not change0 (ut another thread might change the varia(le !hile the 'irst thread !or s on it.
5 dialog (o4 la(eled #inG; 5""lication : Ste" = %' = !ill a""ear. +ndicate that you !ant to create an 3m"ty $ro6ect0 and "ress the /inish (utton. Select Ne! 'rom the /ile menu again. +n the Ne! dialog (o40 "ic the /iles ta(. Select C++ Source /ile. The 5dd To $ro6ect (o4 should (e chec ed0 and -ello&sg should (e indicated. Ty"e -ello&sg.c in the /ile Name 'ield. Choose %K. No! you can ty"e in the -3,,%&S2.C 'ile sho!n a(ove. %r you can select the +nsert menu and the /ile 5s Te4t o"tion to co"y the contents o' -3,,%&S2.C 'rom the 'ile on this (oo 7s com"anion CD:8%&. Structurally0 -3,,%&S2.C is identical to the K&8 Ihello0 !orldI "rogram. The header 'ile STD+%.- has (een re"laced !ith #+ND%#S.-0 the entry "oint main has (een re"laced !ith &inMain0 and the C run:time li(rary 'unction printf has (een re"laced !ith the #indo!s 5$+ 'unction Message)ox. -o!ever0 there is much in the "rogram that is ne!0 including several strange:loo ing u""ercase identi'iers. ,et7s start at the to".
The &inMain 'unction is declared as returning an int. The #+N5$+ identi'ier is de'ined in #+ND3/.- !ith the statement: #define 8=;FC= &&stdcall This statement s"eci'ies a calling convention that involves ho! machine code is generated to "lace 'unction call arguments on the stac . &ost #indo!s 'unction calls are declared as #+N5$+. The 'irst "arameter to &inMain is something called an Iinstance handle.I +n #indo!s "rogramming0 a handle is sim"ly a num(er that an a""lication uses to identi'y something. +n this case0 the handle uni)uely identi'ies the "rogram. +t is re)uired as an argument to some other #indo!s 'unction calls. +n early versions o' #indo!s0 !hen you ran the same "rogram concurrently more than once0 you created multiple instances o' that "rogram. 5ll instances o' the same a""lication shared code and read:only memory (usually resources such as menu and dialog (o4 tem"lates*. 5 "rogram could determine i' other instances o' itsel' !ere running (y chec ing the h4rev*nstance "arameter. +t could then s i" certain chores and move some data 'rom the "revious instance into its o!n data area. +n the G;:(it versions o' #indo!s0 this conce"t has (een a(andoned. The second "arameter to &inMain is al!ays N.,, (de'ined as F*. The third "arameter to &inMain is the command line used to run the "rogram. Some #indo!s a""lications use this to load a 'ile into memory !hen the "rogram is started. The 'ourth "arameter to &inMain indicates ho! the "rogram should (e initially dis"layedSeither normally or ma4imiPed to 'ill the !indo!0 or minimiPed to (e dis"layed in the tas list (ar. #e7ll see ho! this "arameter used some other time.
#define KI&=4D;PUUDU KI&=4D;?F;L #define KI&=4D;=;6DUKF(=D; KI&=4D;F:(PU=:X #define KI&=4D;:(DC KI&=4D;?F;L There are a 'e! other &19 constants0 (ut you can consult the header 'ile yoursel' or the documentation in 34latform 0'531ser *nterface 0ervices3&indowing3'ialog )oxes3'ialog )ox "eference3'ialog )ox !unctions . +n this "rogram0 the Message)ox 'unction returns the value =0 (ut it7s more "ro"er to say that it returns +D%K0 !hich is de'ined in #+N.S38.- as e)ualing =. De"ending on the other (uttons "resent in the message (o40 the Message)ox 'unction can also return +DN3S0 +DN%0 +DC5NC3,0 +D51%8T0 +D83T8N0 or +D+2N%83. +s this little #indo!s "rogram really the e)uivalent o' the K&8 Ihello0 !orldI "rogramW #ell0 you might thin not (ecause the Message)ox 'unction doesn7t really have all the "otential 'ormatting "o!er o' the printf 'unction in Ihello0 !orld.I 1ut !e7ll see in the ne4t cha"ter ho! to !rite a version o' Message)ox that does printf:li e 'ormatting.
initially to su""lement 5SC++ and0 !ith any luc 0 eventually re"lace it. Considering that 5SC++ is one o' the most dominant standards in com"uting0 this is certainly a tall order. .nicode im"acts every "art o' the com"uter industry0 (ut "erha"s most "ro'oundly o"erating systems and "rogramming languages. +n this res"ect0 !e are almost hal'!ay there. #indo!s NT su""orts .nicode 'rom the ground u". (.n'ortunately0 #indo!s B^ includes only a small amount o' .nicode su""ort.* %he C -rogramming lang$age as formaliLed /( >),# inherentl( s$--orts *nicode thro$gh its s$--ort of wide characters. which #Xll disc$ss in detail /elowA
Wider Characters
)othing a/o$t *nicode or wide characters alters the meaning of the char data t(-e in C. The char continues to indicate = (yte o' storage0 and sizeof 6char) continues to return =. +n theory0 a (yte in C can (e greater than ^ (its0 (ut 'or most o' us0 a (yte (and hence a char* is ^ (its !ide. #ide characters in C are (ased on the wchar_t data ty"e0 !hich is de'ined in several header 'iles0 including #C-58.-0 li e so: t%pedef unsi+ned short ,char&t ; Thus0 the wchar_t data ty"e is the same as an unsigned short integer: =C (its !ide. To de'ine a varia(le containing a single !ide character0 use the 'ollo!ing statement: ,char&t c ' ZF[ ; The varia(le c is the t!o:(yte value F4FF>=0 !hich is the .nicode re"resentation o' the letter 5. (-o!ever0 /eca$se #ntel micro-rocessors store m$lti/(te val$es with the least-significant /(tes first 0 the (ytes are actually stored in memory in the se)uence F4>=0 F4FF. Kee" this in mind i' you e4amine memory storage o' .nicode te4t.* Nou can also de'ine an initialiPed "ointer to a !ide:character string: ,char&t 3 p ' L"?elloO" ; )otice the ca-ital & 3for long5 immediatel( -receding the first K$otation mar+A %his indicates to the com-iler that the string is to /e stored with wide charactersTthat is. with ever( character occ$-(ing C /(tesA The "ointer varia(le p re)uires > (ytes o' storage0 as usual0 (ut the character string re)uires => (ytesS; (ytes 'or each character !ith ; (ytes o' Peros at the end. Similarly0 you can de'ine an array o' !ide characters this !ay: static ,char&t aQR ' L"?elloO" ; The string again re)uires => (ytes o' storage0 and sizeof 6a) !ill return =>. Nou can inde4 the a array to get at the individual characters. The value a789 is the !ide character Ee70 or F4FFC?. 5lthough it loo s more li e a ty"o than anything else0 that , "receding the 'irst )uotation mar is very im"ortant0 and there must not (e s"ace (et!een the t!o sym(ols. %nly !ith that , !ill the com"iler no! you !ant the string to (e stored !ith ; (ytes "er character. ,ater on0 !hen !e loo at !ide:character strings in "laces other than varia(le de'initions0 you7ll encounter the , "receding the 'irst )uotation mar again. /ortunately0 the C com"iler !ill o'ten give you a !arning or error message i' you 'orget to include the ,. Nou can also use the , "re'i4 in 'ront o' single character literals0 as sho!n here0 to indicate that they should (e inter"reted as !ide characters. ,char&t c ' L[F[ ; 1ut it7s usually not necessary. The C com"iler !ill Pero:e4tend the character any!ay.
char 3 pc ' "?elloO"; !e can call iLen+th ' strlen (pc); The varia(le i(ength !ill (e set e)ual to C0 the num(er o' characters in the string. 34cellentJ No! let7s try de'ining a "ointer to a string o' !ide characters: ,char&t 3 p, ' L"?elloO"; 5nd no! !e call strlen again: iLen+th ' strlen (p,); No! the trou(les (egin. /irst0 the C com"iler gives you a !arning message0 "ro(a(ly something along the lines o' Zfunction[ 7 incompati!le t%pes 9 from Zunsi+ned short 3[ to Zconst char 3[ +t7s telling you that the strlen 'unction is declared as acce"ting a "ointer to a char0 and it7s getting a "ointer to an unsigned short. Nou can still com"ile and run the "rogram0 (ut you7ll 'ind that i(ength is set to =. #hat ha""enedW The C characters o' the character string I-elloJI have the =C:(it values: /"//HT /"//M. /"//M4 /"//M4 /"//M6 /"//21 !hich are stored in memory (y +ntel "rocessors li e so: HT // M. // M4 // M4 // M6 // 21 // The strlen 'unction0 assuming that it7s attem"ting to 'ind the length o' a string o' characters0 counts the 'irst (yte as a character (ut then assumes that the second (yte is a Pero (yte denoting the end o' the string. This little e4ercise clearly illustrates the di''erences (et!een the C language itsel' and the run:time li(rary 'unctions. The com"iler inter"rets the string ,I-elloJI as a collection o' =C:(it short integers and stores them in the wchar_t array. The com"iler also handles any array inde4ing and the sizeof o"erator0 so these !or "ro"erly. 1ut run:time li(rary 'unctions such as strlen are added during lin time. These 'unctions e4"ect strings that com"rise single:(yte characters. #hen they are con'ronted !ith !ide:character strings0 they don7t "er'orm as !e7d li e. %h0 great0 you say. No! every C li(rary 'unction has to (e re!ritten to acce"t !ide characters. #ell0 not ever# C li(rary 'unction. %nly the ones that have string arguments. 5nd #ou don7t have to re!rite them. +t7s already (een done. The !ide:character version o' the strlen 'unction is called wcslen (I!ide:character string lengthI*0 and it7s declared (oth in ST8+N2.- (!here the declaration 'or strlen resides* and #C-58.-. The strlen 'unction is declared li e this: si@e&t &&cdecl strlen (const char 3) ; and the wcslen 'unction loo s li e this: si@e&t &&cdecl ,cslen (const ,char&t 3) ; So no! !e no! that !hen !e need to 'ind out the length o' a !ide:character string !e can call iLen+th ' ,cslen (p,) ; The 'unction returns C0 the num(er o' characters in the string. Kee" in mind that the character length o' a string does not change !hen you move to !ide charactersSonly the (yte length changes. 5ll your 'avorite C run:time li(rary 'unctions that ta e string arguments have !ide:character versions. /or e4am"le0 wprintf is the !ide:character version o' printf. These 'unctions are declared (oth in #C-58.- and in the header 'ile !here the normal 'unction is declared.
#define &tcslen ,cslen +' .N+C%D3 isn7t de'ined0 _tcslen is de'ined to (e strlen: #define &tcslen strlen 5nd so on. TC-58.- also solves the "ro(lem o' the t!o character data ty"es !ith a ne! data ty"e named TC-58. +' the 9.N+C%D3 identi'ier is de'ined0 TC-58 is wchar_t: t%pedef ,char&t (4?FU ; %ther!ise0 TC-58 is sim"ly a char: t%pedef char (4?FU ; No! it7s time to address that stic y , "ro(lem !ith the string literals. +' the 9.N+C%D3 identi'ier is de'ined0 a macro called 99T is de'ined li e this: #define &&((") L##" This is 'airly o(scure synta40 (ut it7s in the 5NS+ C standard 'or the C "re"rocessor. That "air o' num(er signs is called a Ito en "aste0I and it causes the letter , to (e a""ended to the macro "arameter. Thus0 i' the macro "arameter is I-elloJI0 then (::x is ,I-elloJI. +' the 9.N+C%D3 identi'ier is not de'ined0 the 99T macro is sim"ly de'ined in the 'ollo!ing !ay: #define &&((") " 8egardless0 t!o other macros are de'ined to (e the same as 99T: #define &((") &&((") #define &(PW((") &&((") #hich one you use 'or your #inG; console "rograms de"ends on ho! concise or ver(ose you7d li e to (e. 1asically0 you must de'ine your string literals inside the 9T or 9T3AT macro in the 'ollo!ing !ay: &(PW( ("?elloO") Doing so causes the string to (e inter"reted as com"osed o' !ide characters i' the 9.N+C%D3 identi'ier is de'ined and as ^:(it characters i' not.
The #+NNT.- header 'ile goes on to de'ine si4 data ty"es you can use as "ointers to ^:(it character strings and 'our data ty"es you can use as "ointers to const ^:(it character strings. +7ve condensed the actual header 'ile statements a (it to sho! the data ty"es here: t%pedef 4?FU 3 C4?FU# 3 LC4?# 3 C4?# 3 ;C:(U# 3 LC:(U# 3 C:(U ; t%pedef 4D;:( 4?FU 3 LC44?# 3 C44?# 3 LC4:(U# 3 C4:(U ; The N and , "re'i4es stand 'or InearI and IlongI and re'er to the t!o di''erent siPes o' "ointers in =C:(it #indo!s. There is no di''erentiation (et!een near and long "ointers in #inG;. Similarly0 #+NNT.- de'ines si4 data ty"es you can use as "ointers to =C:(it character strings and 'our data ty"es you can use as "ointers to const =C:(it character strings: t%pedef 84?FU 3 C84?FU# 3 LC84?# 3 C84?# 3 ;8C:(U# 3 LC8:(U# 3 C8:(U ; t%pedef 4D;:( 84?FU 3 LC484?# 3 C484?# 3 LC48:(U# 3 C48:(U ; So 'ar0 !e have the data ty"es C-58 (!hich is an ^:(it char* and #C-58 (!hich is a =C:(it wchar_t* and "ointers to C-58 and #C-58. 5s in TC-58.-0 #+NNT.- de'ines TC-58 to (e the generic character ty"e. +' the identi'ier .N+C%D3 (without the underscore* is de'ined0 TC-58 and "ointers to TC-58 are de'ined (ased on #C-58 and "ointers to #C-58L i' the identi'ier .N+C%D3 is not de'ined0 TC-58 and "ointers to TC-58 are de'ined (ased on char and "ointers to char: #ifdef V;=4DLP t%pedef 84?FU (4?FU# 3 C(4?FU ; t%pedef LC8:(U LC(4?# C(4?# C(:(U# LC(:(U ; t%pedef LC48:(U LC4(:(U ; #else t%pedef char (4?FU# 3 C(4?FU ; t%pedef LC:(U LC(4?# C(4?# C(:(U# LC(:(U ; t%pedef LC4:(U LC4(:(U ; #endif 1oth the #+NNT.- and #C-58.- header 'iles are "rotected against rede'inition o' the TC-58 data ty"e i' it7s already (een de'ined (y one or the other o' these header 'iles. -o!ever0 !henever you7re using other header 'iles in your "rogram0 you should include #+ND%#S.- (e'ore all others. The #+NNT.- header 'ile also de'ines a macro that a""ends the , to the 'irst )uotation mar o' a character string. +' the .N+C%D3 identi'ier is de'ined0 a macro called 99T3AT is de'ined as 'ollo!s: #define &&(PW((5uote) L##5uote +' the identi'ier .N+C%D3 is not de'ined0 the 99T3AT macro is de'ined li e so: #define &&(PW((5uote) 5uote 8egardless0 the T3AT macro is de'ined li e this: #define (PW((5uote) &&(PW((5uote) This is very similar to the !ay the 9T3AT macro is de'ined in TC-58.-0 e4ce"t that you need not (other !ith the underscore. +7ll (e using the T3AT version o' this macro throughout this (oo . These de'initions let you mi4 5SC++ and .nicode characters strings in the same "rogram or !rite a single "rogram that can (e com"iled 'or either 5SC++ or .nicode. +' you !ant to e4"licitly de'ine ^:(it character varia(les and strings0 use C-580 $C-58 (or one o' the others*0 and strings !ith )uotation mar s. /or e4"licit =C:(it character varia(les and strings0 use #C-580 $#C-580 and a""end an , (e'ore )uotation mar s. /or varia(les and characters strings that !ill (e ^ (it or =C (it de"ending on the de'inition o' the .N+C%D3 identi'ier0 use TC-580 $TC-580 and the T3AT macro.
The G;:(it versions o' #indo!s (that is0 all versions o' #indo!s NT0 as !ell as #indo!s B? and #indo!s B^* include .S38.3A3 'or =C:(it com"ati(ility (ut also have a dynamic:lin li(rary named .S38G;.D,, that contains entry "oints 'or the G;:(it versions o' the user inter'ace 'unctions0 including the G;:(it version o' Message)ox. 1ut here7s the ey to #indo!s su""ort o' .nicode: +n .S38G;.D,,0 there is no entry "oint 'or a G;:(it 'unction named Message)ox. +nstead0 there are t!o entry "oints0 one named Message)ox/ (the 5SC++ version* and the other named Message)ox& (the !ide:character version*. 3very #inG; 'unction that re)uires a character string argument has t!o entry "oints in the o"erating systemJ /ortunately0 you usually don7t have to !orry a(out this. Nou can sim"ly use Message)ox in your "rograms. 5s in the TC-58 header 'ile0 the various #indo!s header 'iles "er'orm the necessary tric s. -ere7s ho! Message)ox/ is de'ined in #+N.S38.-. This is )uite similar to the earlier de'inition o' Message)ox: 8=;V:PUFC= int 8=;FC= Kessa+eIo"F (?8;L h8nd# LC4:(U lp(e"t# LC4:(U lp4aption# V=;( u(%pe) ; 5nd here7s Message)ox&: 8=;V:PUFC= int 8=;FC= Kessa+eIo"8 (?8;L h8nd# LC48:(U lp(e"t# LC48:(U lp4aption# V=;( u(%pe) ; Notice that the second and third "arameters to the Message)ox& 'unction are "ointers to !ide:character strings. Nou can use the Message)ox/ and Message)ox& 'unctions e4"licitly in your #indo!s "rograms i' you need to mi4 and match 5SC++ and !ide:character 'unction calls. 1ut most "rogrammers !ill continue to use Message)ox0 !hich !ill (e the same as Message)ox/ or Message)ox& de"ending on !hether .N+C%D3 is de'ined. -ere7s the rather trivial code in #+N.S38.- that does the tric : #ifdef V;=4DLP #define Kessa+eIo" Kessa+eIo"8 #else #define Kessa+eIo" Kessa+eIo"F #endif Thus0 all the Message)ox 'unction calls that a""ear in your "rogram !ill actually (e Message)ox& 'unctions i' the .N+C%D3 identi'ier is de'ined and Message)ox/ 'unctions i' it7s not de'ined. #hen you run the "rogram0 #indo!s lin s the various 'unction calls in your "rogram to the entry "oints in the various #indo!s dynamic:lin li(raries. #ith 6ust a 'e! e4ce"tions0 ho!ever0 the .nicode versions o' the #indo!s 'unctions are not im"lemented in #indo!s B^. The 'unctions have entry "oints0 (ut they usually return an error code. +t is u" to an a""lication to ta e note o' this error return and do something reasona(le.
The (ad ne!s is that you can7t use printf in a #indo!s "rogram. 5lthough you can use most o' the C run:time li(rary in #indo!s "rogramsSindeed0 many "rogrammers "re'er to use the C memory management and 'ile +/% 'unctions over the #indo!s e)uivalentsS#indo!s has no conce"t o' standard in"ut and standard out"ut. Nou can use fprintf in a #indo!s "rogram0 (ut not printf. The good ne!s is that you can still dis"lay te4t (y using sprintf and other 'unctions in the sprintf 'amily. These 'unctions !or 6ust li e printf0 e4ce"t that they !rite the 'ormatted out"ut to a character string (u''er that you "rovide as the 'unction7s 'irst argument. Nou can then do !hat you !ant !ith this character string (such as "ass it to Message)ox*. +' you7ve never had occasion to use sprintf (as + didn7t !hen + 'irst (egan "rogramming 'or #indo!s*0 here7s a (rie' rundo!n. 8ecall that the printf 'unction is declared li e so: int printf (const char 3 s@6ormat# ...) ; The 'irst argument is a 'ormatting string that is 'ollo!ed (y a varia(le num(er o' arguments o' various ty"es corres"onding to the codes in the 'ormatting string. The sprintf 'unction is de'ined li e this: int sprintf (char 3 s@Iuffer# const char 3 s@6ormat# ...) ; The 'irst argument is a character (u''erL this is 'ollo!ed (y the 'ormatting string. 8ather than !riting the 'ormatted result in standard out"ut0 sprintf stores it in sz)uffer. The 'unction returns the length o' the string. +n character:mode "rogramming0 printf ("(he sum of )i and )i is )i"# .# -# .*-) ; is 'unctionally e)uivalent to char s@Iuffer Q1//R ; sprintf (s@Iuffer# "(he sum of )i and )i is )i"# .# -# .*-) ; puts (s@Iuffer) ; +n #indo!s0 you can use Message)ox rather than puts to dis"lay the results. 5lmost everyone has e4"erience !ith printf going a!ry and "ossi(ly crashing a "rogram !hen the 'ormatting string is not "ro"erly in sync !ith the varia(les to (e 'ormatted. #ith sprintf0 you still have to !orry a(out that and you also have a ne! !orry: the character (u''er you de'ine must (e large enough 'or the result. 5 &icroso't:s"eci'ic 'unction named _snprintf solves this "ro(lem (y introducing another argument that indicates the siPe o' the (u''er in characters. 5 variation o' sprintf is vsprintf0 !hich has only three arguments. The vsprintf 'unction is used to im"lement a 'unction o' your o!n that must "er'orm printf:li e 'ormatting o' a varia(le num(er o' arguments. The 'irst t!o arguments to vsprintf are the same as sprintf: the character (u''er 'or storing the result and the 'ormatting string. The third argument is a "ointer to an array o' arguments to (e 'ormatted. +n "ractice0 this "ointer actually re'erences varia(les that have (een stored on the stac in "re"aration 'or a 'unction call. The va_list0 va_start0 and va_end macros (de'ined in STD582.-* hel" in !or ing !ith this stac "ointer. The SC8NS+X3 "rogram at the end o' this cha"ter demonstrates ho! to use these macros. The sprintf 'unction can (e !ritten in terms o' vsprintf li e so: int sprintf (char 3 s@Iuffer# const char 3 s@6ormat# ...) { int iUeturn ; va&list pFr+s ; va&start (pFr+s# s@6ormat) ; iUeturn ' vsprintf (s@Iuffer# s@6ormat# pFr+s) ; va&end (pFr+s) ; return iUeturn ; The va_start macro sets p/rg to "oint to the varia(le on the stac right a(ove the sz!ormat argument on the stac . So many early #indo!s "rograms used sprintf and vsprintf that &icroso't eventually added t!o similar 'unctions to the #indo!s 5$+. The #indo!s wsprintf and wvsprintf 'unctions are 'unctionally e)uivalent to sprintf and vsprintf0 e4ce"t that they don7t handle 'loating:"oint 'ormatting. %' course0 !ith the introduction o' !ide characters0 the sprintf 'unctions (lossomed in num(er0 creating a thoroughly con'using 6um(le o' 'unction names. -ere7s a chart that sho!s all the sprintf 'unctions su""orted (y &icroso't7s C run:time li(rary and (y #indo!s. )*+II .ide +haracter 1eneric Standard Version sprintf swprintf _stprintf &a4:,ength Version _snprintf _snwprintf _sntprintf
#indo!s Version wsprintf/ wsprintf& wsprintf Standard Version vsprintf vswprintf _vstprintf &a4:,ength Version _vsnprintf _vsnwprintf _vsntprintf #indo!s Version wvsprintf/ wvsprintf& wvsprintf +n the !ide:character versions o' the sprintf 'unctions0 the string (u''er is de'ined as a !ide:character string. +n the !ide:character versions o' all these 'unctions0 the 'ormatting string must (e a !ide:character string. -o!ever0 it7s u" to you to ma e sure that any other strings you "ass to these 'unctions are also com"osed o' !ide characters.
,CR),#Y0AC
2399999999999999999999999999999999999999999999999999999 :4U;:=\P.4 99 Lispla%s screen si@e in a messa+e !o" (c) 4harles Cet@old# 1SST 9999999999999999999999999999999999999999999999999999932 #include <,indo,s.h> #include <tchar.h> #include <stdio.h> int 4LP4L Kessa+eIo"Crintf ((4?FU 3 s@4aption# (4?FU 3 s@6ormat# ...) { (4?FU s@Iuffer Q1/2HR ; va&list pFr+List ; 22 (he va&start macro (defined in :(LFUY.?) is usuall% e5uivalent to7 22 pFr+List ' (char 3) ]s@6ormat * si@eof (s@6ormat) ; va&start (pFr+List# s@6ormat) ; 22 (he last ar+ument to ,vsprintf points to the ar+uments &vsntprintf (s@Iuffer# si@eof (s@Iuffer) 2 si@eof ((4?FU)# s@6ormat# pFr+List) ; reason 22 (he va&end macro $ust @eroes out pFr+List for no +ood
va&end (pFr+List) ; return Kessa+eIo" (;VLL# s@Iuffer# s@4aption# /) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { int c":creen# c%:creen ; c":creen ' Yet:%stemKetrics (:K&4W:4UPP;) ;
c%:creen ' Yet:%stemKetrics (:K&4G:4UPP;) ; Kessa+eIo"Crintf ((PW( (":crn:i@e")# (PW( ("(he screen is )i pi"els ,ide !% )i pi"els hi+h.")# c":creen# c%:creen) ; return / ; The "rogram dis"lays the !idth and height o' the video dis"lay in "i4els (y using in'ormation o(tained 'rom the 2et0#stemMetrics 'unction. 2et0#stemMetrics is a use'ul 'unction 'or o(taining in'ormation a(out the siPes o' various o(6ects in #indo!s.
#nternationaliLation
$re"aring your #indo!s "rograms 'or an international mar et involves more than using .nicode. +nternationaliPation is (eyond our sco"e o' discussion (ut is covered e4tensively in 'eveloping *nternational 0oftware for &indows <= and &indows +. (y Nadine Kano (&icroso't $ress0 =BB?*. #e !ill restrict ourselves to sho!ing "rograms that can (e com"iled either !ith or !ithout he .N+C%D3 identi'ier de'ined. This involves using TC-58 'or all character and string de'initions0 using the T3AT macro 'or string literals0 and ta ing care not to con'use (ytes and characters. /or e4am"le0 notice the _vsntprintf call in SC8NS+X3. The second argument is the siPe o' the (u''er in characters. Ty"ically0 you7d use sizeof 6sz)uffer). 1ut i' the (u''er has !ide characters0 that7s not the siPe o' the (u''er in characters (ut the siPe o' the (u''er in (ytes. Nou must divide it (y sizeof 6.$-/").
,ess o(vious are the various "ush (uttons0 radio (uttons0 chec (o4es0 list (o4es0 scroll (ars0 and te4t:entry 'ields that adorn the sur'aces o' dialog (o4es. 3ach o' these little visual o(6ects is a !indo!. More s-ecificall(. these are called Zchild windowsZ or Zcontrol windowsZ or Zchild window controlsAZ %he $ser sees these windows as o/Jects on the screen and interacts directl( with them $sing the +e(/oard or the mo$se. +nterestingly enough0 the "rogrammer7s "ers"ective is analogous to the user7s "ers"ective. The !indo! receives the user in"ut in the 'orm o' ImessagesI to the !indo!. 5 !indo! also uses messages to communicate !ith other !indo!s. 2etting a good 'eel 'or messages is an im"ortant "art o' learning ho! to !rite "rograms 'or #indo!s. -ere7s an e4am"le o' #indo!s messages: 5s you no!0 most #indo!s "rograms have siPea(le a""lication !indo!s. That is0 you can gra( the !indo!7s (order !ith the mouse and change the !indo!7s siPe. %'ten the "rogram !ill res"ond to this change in siPe (y altering the contents o' its !indo!. Nou might guess (and you !ould (e correct* that #indo!s itsel' rather than the a""lication is handling all the messy code involved !ith letting the user resiPe the !indo!. Net the a""lication I no!sI that the !indo! has (een resiPed (ecause it can change the 'ormat o' !hat it dis"lays. -o! does the a""lication no! that the user has changed the !indo!7s siPeW /or "rogrammers accustomed to only conventional character:mode "rogramming0 there is no mechanism 'or the o"erating system to convey in'ormation o' this sort to the user. +t turns out that the ans!er to this )uestion is central to understanding the architecture o' #indo!s. #hen a user resiPes a !indo!0 #indo!s sends a message to the "rogram indicating the ne! !indo! siPe. The "rogram can then ad6ust the contents o' its !indo! to re'lect the ne! siPe. I#indo!s sends a message to the "rogram.I + ho"e you didn7t read that statement !ithout (lin ing. #hat on earth could it meanW #e7re tal ing a(out "rogram code here0 not a telegra"h system. -o! can an o"erating system send a message to a "rogramW #hen + say that I#indo!s sends a message to the "rogramI + mean that #indo!s calls a 'unction !ithin the "rogramSa 'unction that you !rite and !hich is an essential "art o' your "rogram7s code. The "arameters to this 'unction descri(e the "articular message that is (eing sent (y #indo!s and received (y your "rogram. This 'unction in your "rogram is no!n as the I!indo! "rocedure.I Nou are undou(tedly accustomed to the idea o' a "rogram ma ing calls to the o"erating system. This is ho! a "rogram o"ens a dis 'ile0 'or e4am"le. #hat you may not (e accustomed to is the idea o' an o"erating system ma ing calls to a "rogram. Net this is 'undamental to #indo!s7 architecture. 3very !indo! that a "rogram creates has an associated !indo! "rocedure. This !indo! "rocedure is a 'unction that could (e either in the "rogram itsel' or in a dynamic:lin li(rary. #indo!s sends a message to a !indo! (y calling the !indo! "rocedure. The !indo! "rocedure does some "rocessing (ased on the message and then returns control to #indo!s. &ore "recisely0 a !indo! is al!ays created (ased on a I!indo! class.I The !indo! class identi'ies the !indo! "rocedure that "rocesses messages to the !indo!. The use o' a !indo! class allo!s multi"le !indo!s to (e (ased on the same !indo! class and hence use the same !indo! "rocedure. /or e4am"le0 all (uttons in all #indo!s "rograms are (ased on the same !indo! class. This !indo! class is associated !ith a !indo! "rocedure located in a #indo!s dynamic:lin li(rary that "rocesses messages to all the (utton !indo!s. +n o(6ect:oriented "rogramming0 an o(6ect is a com(ination o' code and data. 5 !indo! is an o(6ect. The code is the !indo! "rocedure. The data is in'ormation retained (y the !indo! "rocedure and in'ormation retained (y #indo!s 'or each !indo! and !indo! class that e4ists in the system. 5 !indo! "rocedure "rocesses messages to the !indo!. Very o'ten these messages in'orm a !indo! o' user in"ut 'rom the ey(oard or the mouse. /or e4am"le0 this is ho! a "ush:(utton !indo! no!s that it7s (eing Iclic ed.I %ther messages tell a !indo! !hen it is (eing resiPed or !hen the sur'ace o' the !indo! needs to (e redra!n. #hen a #indo!s "rogram (egins e4ecution0 #indo!s creates a Imessage )ueueI 'or the "rogram. This message )ueue stores messages to all the !indo!s a "rogram might create. 5 #indo!s a""lication includes a short chun o' code called the Imessage loo"I to retrieve these messages 'rom the )ueue and dis"atch them to the a""ro"riate !indo! "rocedure. %ther messages are sent directly to the !indo! "rocedure !ithout (eing "laced in the message )ueue. +' your eyes are (eginning to glaPe over !ith this e4cessively a(stract descri"tion o' the #indo!s architecture0 may(e it !ill hel" to see ho! the !indo!0 the !indo! class0 the !indo! "rocedure0 the message )ueue0 the message loo"0 and the !indo! messages all 'it together in the conte4t o' a real "rogram.
Creating a !indo! 'irst re)uires registering a !indo! class0 and that re)uires a !indo! "rocedure to "rocess messages to the !indo!. This involves a (it o' overhead that a""ears in almost every #indo!s "rogram. The -3,,%#+N "rogram0 sho!n in /igure G:=0 is a sim"le "rogram sho!ing mostly that overhead. Fig$re D-!A .he -,((>&*+ program.
'0&&OW#)AC
23999999999999999999999999999999999999999999999999999999999999 ?PLLD8=;.4 99 Lispla%s "?ello# 8indo,s STO" in client area (c) 4harles Cet@old# 1SST 99999999999999999999999999999999999999999999999999999999999932 #include <,indo,s.h> LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { static (4?FU s@Fpp;ameQR ' (PW( ("?ello8in") ; ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; ,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; name h,nd ' 4reate8indo, (s@Fpp;ame# 22 ,indo, class
position position
(PW( ("(he ?ello Cro+ram")# 22 ,indo, caption 8:&D_PULFCCPL8=;LD8# 22 ,indo, st%le 48&V:PLP6FVL(# 22 initial " 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# 22 initial % 22 initial " si@e 22 initial % si@e 22 parent ,indo, 22 ,indo, menu 22 pro+ram
handle handle
;VLL) ;
22 creation
:ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X lCaram) { ?L4 CF=;(:(UV4( UP4( 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK hdc ; ps ; rect ;
s,itch (messa+e) { case 8K&4UPF(P7 Cla%:ound ((PW( ("hello,in.,av")# ;VLL# :;L&6=LP;FKP ^ :;L&F:G;4) ; return / ; case 8K&CF=;(7 hdc ' Ie+inCaint (h,nd# ]ps) ; Yet4lientUect (h,nd# ]rect) ; Lra,(e"t (hdc# (PW( ("?ello# 8indo,s STO")# 91# ]rect# L(&:=;YLPL=;P ^ L(&4P;(PU ^ L(&_4P;(PU) ; PndCaint (h,nd# ]ps) ; return / ; case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ; This "rogram creates a normal a""lication !indo!0 as sho!n in /igure G:;0 and dis"lays0 I-ello0 #indo!s B^JI in the center o' that !indo!. +' you have a sound (oard installed0 you !ill also hear me saying the same thing.
6avascri"t:'ullSiPe(7/FGPgF;4.htm7*6avascri"t:'ullSiPe(7/FGPgF;4.htm7* Fig$re D-CA .he -,((>&*+ window. 5 cou"le o' !arnings: +' you use &icroso't Visual C++ to create a ne! "ro6ect 'or this "rogram0 you need to ma e an addition to the o(6ect li(raries the lin er uses. Select the Settings o"tion 'rom the $ro6ect menu0 and "ic the ,in ta(. Select 2eneral 'rom the Category list (o40 and add #+N&&.,+1 (I#indo!s multimediaI* to the %(6ect/,i(rary &odules te4t (o4. Nou need to do this (ecause -3,,%#+N ma es use o' a multimedia 'unction call0 and the multimedia o(6ect li(rary isn7t included in a de'ault "ro6ect. %ther!ise you7ll get an error message 'rom the lin er indicating that the 4la#0ound 'unction is unresolved. -3,,%#+N accesses a 'ile named -3,,%#+N.#5V0 !hich is on the com"anion CD:8%& in the -3,,%#+N directory. #hen you e4ecute -3,,%#+N.3A30 the de'ault directory must (e -3,,%#+N. This is the case !hen you e4ecute the "rogram !ithin Visual C++0 even though the e4ecuta(le !ill (e in the 83,35S3 or D31.2 su(directory o' -3,,%#+N.
%hin+ing 6lo/all(
&ost o' -3,,%#+N.C is overhead 'ound in virtually every #indo!s "rogram. + mentioned a(ove that -3,,%#+N dis"lays the te4t string in the center o' its !indo!. That7s not "recisely true. The te4t is actually dis"layed in the center o' the "rogram7s Iclient area0I !hich in /igure G:; is the large !hite area !ithin the title (ar and the siPing (order. This distinction !ill (e im"ortant to usL the client area is that area of the window in which a -rogram is free to draw and deliver vis$al o$t-$t to the $ser . #hen you thin a(out it0 this "rogram has an amaPing amount o' 'unctionality in its ^F:odd lines o' code. Nou can gra( the title (ar !ith the mouse and move the !indo! around the screen. Nou can gra( the siPing (orders and resiPe the !indo!. #hen the !indo! changes siPe0 the "rogram automatically re"ositions the te4t string in the center o' its client area. Nou can clic the &a4imiPe (utton and Poom -3,,%#+N to 'ill the screen. Nou can clic the minimiPe (utton and clear it 'rom the screen. Nou can invo e all these o"tions 'rom the system menu (the small icon at the 'ar le't o' the title (ar*. Nou can also close the !indo! to terminate the "rogram (y selecting the Close o"tion 'rom the system menu0 (y clic ing the close (utton at the 'ar right o' the title (ar0 or (y dou(le:clic ing the system menu icon. #e7ll (e e4amining this "rogram in detail 'or much o' the remainder o' the cha"ter. /irst0 ho!ever0 let7s ta e a more glo(al loo . -3,,%#+N.C has a &inMain 'unction li e the sam"le "rograms !e sa! earlier0 (ut it also has a second 'unction named .nd(rocA This is the !indo! "rocedure. (+n conversation among #indo!s "rogrammers0 it7s called the I!in "roc .I* Notice that there7s no code in -3,,%#+N.C that calls &nd4roc. -o!ever0 there is a re'erence to &nd4roc in &inMain0 !hich is !hy the 'unction is declared near the to" o' the "rogram.
*--ercase #dentifiers
Nou7ll notice the use o' )uite a 'e! u""ercase identi'iers in -3,,%#+N.C. These identi'iers are de'ined in the #indo!s header 'iles. Several o' these identi'iers contain a t!o:letter or three:letter "re'i4 'ollo!ed (y an underscore: $0_-",'"/& '._@$,+.," 0+'_!*(,+/M, $0_@",'"/& *'$_/"">& &M_$",/., $&_10,',!/1(. *'*_/44(*$/.*>+ &M_',0.">A '._$,+.," M)_*$>+,"">" &M_4/*+. '._0*+2(,(*+, 0+'_/0A+$ &0_>@,"(/44,'&*+'>& %hese are sim-l( n$meric constants. The "re'i4 indicates a general category to !hich the constant (elongs0 as indicated in this ta(le: (refix +onstant CS Class style o"tion C# Create !indo! o"tion DT Dra! te4t o"tion +D+ +D num(er 'or an icon +DC +D num(er 'or a cursor &1 &essage (o4 o"tions SND Sound o"tion #& #indo! message #S #indo! style Nou almost never need to remem(er numeric constants !hen "rogramming 'or #indo!s. Virtually every numeric constant has an identi'ier de'ined in the header 'iles.
Some other identi'iers used in -3,,%#+N.C are ne! data ty"es0 also de'ined in the #indo!s header 'iles using either t#pedef or :define statements. This !as originally done to ease the transition o' #indo!s "rograms 'rom the original =C:(it system to 'uture o"erating systems that !ould (e (ased on G;:(it technology. This didn7t )uite !or as smoothly and trans"arently as everyone thought at the time0 (ut the conce"t !as 'undamentally sound. Sometimes these ne! data ty"es are 6ust convenient a((reviations. /or e4am"le0 the .+NT data ty"e used 'or the second "arameter to &nd4roc is sim"ly an unsigned int0 !hich in #indo!s B^ is a G;:(it value. The $ST8 data ty"e used 'or the third "arameter to &inMain is a "ointer to a non!ide character string0 that is0 a char B. %thers are less o(vious. /or e4am"le0 the third and 'ourth "arameters to &nd4roc are de'ined as #$585& and ,$585&0 res"ectively. The origin o' these names re)uires a (it o' history. #hen #indo!s !as a =C:(it system0 the third "arameter to &nd4roc !as de'ined as a #%8D0 !hich !as a =C:(it unsigned short integer0 and the 'ourth "arameter !as de'ined as a ,%N20 !hich !as a G;:(it signed long integer. That7s the reason 'or the I#I and I,I "re'i4es on the !ord I$585&.I +n the G;:(it versions o' #indo!s0 ho!ever0 #$585& is de'ined as a .+NT and ,$585& is de'ined as a ,%N2 (!hich is still the C long data ty"e*0 so (oth "arameters to the !indo! "rocedure are G;:(it values. This may (e a little con'using (ecause the #%8D data ty"e is still de'ined as a =C:(it unsigned short integer in #indo!s B^0 so the I#I "re'i4 to I$585&I creates some!hat o' a misnomer. The &nd4roc 'unction returns a value o' ty"e ,83S.,T. That7s sim"ly de'ined as a ,%N2. The &inMain 'unction is given a ty"e o' #+N5$+ (as is every #indo!s 'unction call de'ined in the header 'iles*0 and the &nd4roc 'unction is given a ty"e o' C5,,15CK. 1oth these identi'iers are de'ined as __stdcall0 !hich re'ers to a s"ecial calling se)uence 'or 'unction calls that occur (et!een #indo!s itsel' and your a""lication. -3,,%#+N also uses 'our data structures (!hich +7ll discuss later in this cha"ter* de'ined in the #indo!s header 'iles. These data structures are sho!n in the ta(le (elo!. *tructure 2eaning &S2 &essage structure #NDC,5SS #indo! class structure $5+NTST8.CT $aint structure 83CT 8ectangle structure The 'irst t!o data structures are used in &inMain to de'ine t!o structures named msg and wndclass. The second t!o are used in &nd4roc to de'ine t!o structures named ps and rect.
'$ngarian )otation
Nou might also notice that some o' the varia(les in -3,,%#+N.C have "eculiar:loo ing names. %ne e4am"le is sz$md(ine0 "assed as a "arameter to &inMain. &any #indo!s "rogrammers use a varia(le:naming convention no!n as I-ungarian Notation0I in honor o' the legendary &icroso't "rogrammer Charles Simonyi. Very sim"ly0 the varia(le name (egins !ith a lo!ercase letter or letters that denote the data ty"e o' the varia(le. /or e4am"le0 the sz "re'i4 in sz$md(ine stands 'or Istring terminated (y Pero.I The h "re'i4 in h*nstance and h4rev*nstance stands 'or IhandleLI the i "re'i4 in i$md0how stands 'or
Iinteger.I The last t!o "arameters to &nd4roc also use -ungarian notation0 although0 as + e4"lained (e'ore0 w4aram should more "ro"erly (e named ui4aram (ui 'or Iunsigned integerI*. 1ut (ecause these t!o "arameters are de'ined using the data ty"es #$585& and ,$585&0 +7ve chosen to retain their traditional names. #hen naming structure varia(les0 you can use the structure name (or an a((reviation o' the structure name* in lo!ercase either as a "re'i4 to the varia(le name or as the entire varia(le name. /or e4am"le0 in the &inMain 'unction in -3,,%#+N.C0 the msg varia(le is a structure o' the &S2 ty"eL wndclass is a structure o' the #NDC,5SS ty"e. +n the &nd4roc 'unction0 ps is a $5+NTST8.CT structure and rect is a 83CT structure. -ungarian notation hel"s you avoid errors in your code (e'ore they turn into (ugs. 1ecause the name o' a varia(le descri(es (oth the use o' a varia(le and its data ty"e0 you are much less li ely to ma e coding errors involving mismatched data ty"es. The varia(le name "re'i4es +7ll generally (e using in this (oo are sho!n in the 'ollo!ing ta(le. (refix "ata Type c Char or #C-58 or TC-58 b# 1NT3 (unsigned char* n Short i int x0 # int used as 4:coordinate or y:coordinate cx0 c# int used as 4 or y lengthL c stands 'or IcountI b or f 1%%, (int*L ' stands 'or I'lagI w #%8D (unsigned short* l ,%N2 (long* dw D#%8D (unsigned long* fn 'unction s string sz string terminated (y F character h handle p "ointer
Notice some uses o' -ungarian notation here: The lpfn "re'i4 means Ilong "ointer to a 'unction.I (8ecall that in the #inG; 5$+ there is no distinction (et!een long "ointers and near "ointers. This is a remnant o' =C:(it #indo!s.* The cb "re'i4 stands 'or Icount o' (ytesI and is o'ten used 'or a varia(le that denotes a (yte siPe. The h "re'i4 is a handle0 and the hbr "re'i4 means Ihandle to a (rush.I The lpsz "re'i4 is a Ilong "ointer to a string terminated !ith a Pero.I The .nicode version o' the structure is de'ined li e so: t%pedef struct ta+8;L4LF::8 { V=;( st%le ; 8;LCUD4 lpfn8ndCroc ; int c!4lsP"tra ; int c!8ndP"tra ; ?=;:(F;4P h=nstance ; ?=4D; h=con ; ?4VU:DU h4ursor ; ?IUV:? h!rIac0+round ; LC48:(U lps@Kenu;ame ; LC48:(U lps@4lass;ame ; 8;L4LF::8# 3 C8;L4LF::8# ;PFU 3 ;C8;L4LF::8# 6FU 3 LC8;L4LF::8 ; The only di''erence is that the last t!o 'ields are de'ined as "ointers to constant !ide:character strings rather than "ointers to constant 5SC++ character strings. 5'ter #+N.S38.- de'ines the #NDC,5SS5 and #NDC,5SS# structures (and "ointers to the structures*0 the header 'ile de'ines #NDC,5SS and "ointers to #NDC,5SS (some included 'or (ac !ard com"ati(ility* (ased on the de'inition o' the .N+C%D3 identi'ier: #ifdef V;=4DLP t%pedef 8;L4LF::8 8;L4LF:: ; t%pedef C8;L4LF::8 C8;L4LF:: ; t%pedef ;C8;L4LF::8 ;C8;L4LF:: ; t%pedef LC8;L4LF::8 LC8;L4LF:: ; #else t%pedef 8;L4LF::F 8;L4LF:: ; t%pedef C8;L4LF::F C8;L4LF:: ; t%pedef ;C8;L4LF::F ;C8;L4LF:: ; t%pedef LC8;L4LF::F LC8;L4LF:: ; #endif #hen + sho! su(se)uent structures in this (oo 0 +7ll 6ust sho! the 'unctionally e)uivalent de'inition o' the structure0 !hich 'or #NDC,5SS is this: t%pedef struct { V=;( st%le ; 8;LCUD4 lpfn8ndCroc ; int c!4lsP"tra ; int c!8ndP"tra ; ?=;:(F;4P h=nstance ; ?=4D; h=con ; ?4VU:DU h4ursor ; ?IUV:? h!rIac0+round ; LC4(:(U lps@Kenu;ame ; LC4(:(U lps@4lass;ame ; 8;L4LF::# 3 C8;L4LF:: ; +7ll also go easy on the various "ointer de'initions. There7s no reason 'or you to clutter u" your code !ith varia(le ty"es (eginning !ith ,$ and N$. +n &inMain0 you de'ine a structure o' ty"e #NDC,5SS0 generally li e this: 8;L4LF:: ,ndclass ; Nou then initialiPe the =F 'ields o' the structure and call "egister$lass.
The t!o most im"ortant 'ields in the #NDC,5SS structure are the second and the last. The second 'ield (lpfn&nd4roc* is the address o' a !indo! "rocedure used 'or all !indo!s (ased on this class. +n -3,,%#+N.C0 this !indo! "rocedure is &nd4roc. The last 'ield is the te4t name o' the !indo! class. This can (e !hatever you !ant. +n "rograms that create only one !indo!0 the !indo! class name is commonly set to the name o' the "rogram. The other 'ields descri(e some characteristics o' the !indo! class0 as descri(ed (elo!. ,et7s ta e a loo at each 'ield o' the #NDC,5SS structure in order. The statement ,ndclass.st%le ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; com(ines t!o G;:(it Iclass styleI identi'iers !ith a C (it!ise %8 o"erator. The #+N.S38.- header 'iles de'ines a !hole collection o' identi'iers !ith the CS "re'i4: #define 4:&_UPLUF8 /"///1 #define 4:&?UPLUF8 /"///2 #define 4:&XPG4_(8=;LD8 /"///H #define 4:&LIL4LX: /"///T #define 4:&D8;L4 /"//2/ #define 4:&4LF::L4 /"//H/ #define 4:&CFUP;(L4 /"//T/ #define 4:&;DXPG4_( /"/1// #define 4:&;D4LD:P /"/2// #define 4:&:F_PI=(: /"/T// #define 4:&IG(PFL=Y;4L=P;( /"1/// #define 4:&IG(PFL=Y;8=;LD8 /"2/// #define 4:&YLDIFL4LF:: /"H/// #define 4:&=KP /"///1//// +denti'iers de'ined in this !ay are o'ten called I(it 'lagsI (ecause each identi'ier sets a single (it in a com"osite value. %nly a 'e! o' these class styles are commonly used. The t!o identi'iers used in -3,,%#+N indicate that all !indo!s created (ased on this class are to (e com"letely re"ainted !henever the horiPontal !indo! siPe (CS9-83D85#* or the vertical !indo! siPe (CS9V83D85#* changes. +' you resiPe -3,,%#+N7s !indo!0 you7ll see that the te4t string is redra!n to (e in the ne! center o' the !indo!. These t!o identi'iers ensure that this ha""ens. #e7ll see shortly ho! the !indo! "rocedure is noti'ied o' this change in !indo! siPe. The second 'ield o' the #NDC,5SS structure is initialiPed (y the statement: ,ndclass.lpfn8ndCroc ' 8ndCroc ; This sets the !indo! "rocedure 'or this !indo! class to &nd4roc0 !hich is the second 'unction in -3,,%#+N.C. This !indo! "rocedure !ill "rocess all messages to all !indo!s created (ased on this !indo! class. +n C0 !hen you use a 'unction name in a statement li e this0 you7re really re'erring to a "ointer to a 'unction. The ne4t t!o 'ields are used to reserve some e4tra s"ace in the class structure and the !indo! structure that #indo!s maintains internally: ,ndclass.c!4lsP"tra ' / ; ,ndclass.c!8ndP"tra ' / ; 5 "rogram can use this e4tra s"ace 'or its o!n "ur"oses. -3,,%#+N does not use this 'eature0 so F is s"eci'ied. %ther!ise0 as the -ungarian notation indicates0 the 'ield !ould (e set to a Icount o' (ytes.I (+7ll use the cb&nd,xtra 'ield in the C-3CK38G "rogram sho!n in Cha"ter D.* The ne4t 'ield is sim"ly the instance handle o' the "rogram (!hich is one o' the "arameters to &inMain*: ,ndclass.h=nstance ' h=nstance ; The statement ,ndclass.h=con ' Load=con (;VLL# =L=&FCCL=4F(=D;) ; sets an icon 'or all !indo!s created (ased on this !indo! class. The icon is a small (itma" "icture that re"resents the "rogram to the user. #hen the "rogram is running0 the icon a""ears in the #indo!s tas (ar and at the le't side o' the "rogram !indo!7s title (ar. ,ater in this (oo 0 you7ll learn ho! to create customiPed icons 'or your #indo!s "rograms. 8ight no!0 !e7ll ta e an easy a""roach and use a "rede'ined icon. To o(tain a handle to a "rede'ined icon0 you call (oad*con !ith the 'irst argument set to N.,,. #hen you7re loading your o!n customiPed icons that are stored in your "rogram7s .3A3 'ile on dis 0 this argument !ould (e set to h*nstance0 the instance handle o' the "rogram. The second argument identi'ies the icon. /or the "rede'ined icons0 this argument is an identi'ier (eginning !ith the "re'i4 +D+ (I+D 'or an iconI* de'ined in #+N.S38.-. The +D+95$$,+C5T+%N icon is sim"ly a little "icture o' a !indo!. The (oad*con 'unction returns a handle to this icon.
#e don7t really care a(out the actual value o' the handle. +t7s sim"ly used to set the value o' the h*con 'ield. This 'ield is de'ined in the #NDC,5SS structure to (e o' ty"e -+C%N0 !hich stands 'or Ihandle to an icon.I The statement ,ndclass.h4ursor ' Load4ursor (;VLL# =L4&FUUD8) ; is similar to the "revious statement. The (oad$ursor 'unction loads a "rede'ined mouse cursor no!n as +DC9588%# and returns a handle to the cursor. This handle is assigned to the b$ursor 'ield o' the #NDC,5SS structure. #hen the mouse cursor a""ears over the client area o' a !indo! that is created (ased on this class0 the cursor (ecomes a small arro!. The ne4t 'ield s"eci'ies the (ac ground color o' the client area o' !indo!s created (ased on this class. The hbr "re'i4 o' the hbr)ac%ground 'ield name stands 'or Ihandle to a (rush.I 5 (rush is a gra"hics term that re'ers to a colored "attern o' "i4els used to 'ill an area. #indo!s has several standard0 or Istoc 0I (rushes. The 2et0toc%>bject call sho!n here returns a handle to a !hite (rush: ,ndclass.h!rIac0+round ' Yet:toc0D!$ect (8?=(P&IUV:?) ; This means that the (ac ground o' the client area o' the !indo! !ill (e solid !hite0 !hich is a common choice. The ne4t 'ield s"eci'ies the !indo! class menu. -3,,%#+N has no a""lication menu0 so the 'ield is set to N.,,: ,ndclass.lps@Kenu;ame ' ;VLL ; /inally the class must (e given a name. /or a small "rogram0 this can (e sim"ly the name o' the "rogram0 !hich is the I-ello#inI string stored in the sz/pp+ame varia(le. ,ndclass.lps@4lass;ame ' s@Fpp;ame ; This string is com"osed o' either 5SC++ characters or .nicode characters de"ending on !hether the .N+C%D3 identi'ier has (een de'ined. #hen all =F 'ields o' the structure have (een initialiPed0 -3,,%#+N registers the !indo! class (y calling "egister$lass. The only argument to the 'unction is a "ointer to the #NDC,5SS structure. 5ctually0 there7s a "egister$lass/ 'unction that ta es a "ointer to the #NDC,5SS5 structure0 and a "egister$lass& 'unction that ta es a "ointer to the #NDC,5SS# structure. #hich 'unction the "rogram uses to register the !indo! class determines !hether messages sent to the !indo! !ill contain 5SC++ te4t or .nicode te4t. No! here7s a "ro(lem: +' you have com"iled the "rogram !ith the .N+C%D3 identi'ier de'ined0 your "rogram !ill call "egister$lass&. That7s 'ine i' you7re running the "rogram on &icroso't #indo!s NT. 1ut i' you7re running the "rogram on #indo!s B^0 the "egister$lass& 'unction is not really im"lemented. There7s an entry "oint 'or the 'unction0 (ut it 6ust returns a Pero 'rom the 'unction call0 indicating an error. This is a good o""ortunity 'or a .nicode "rogram running under #indo!s B^ to in'orm the user o' the "ro(lem and terminate. -ere7s the !ay most o' the "rograms in this (oo !ill handle the "egister$lass 'unction call: if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; The Message)ox& 'unction !or s "ro"erly (ecause it is one o' the 'e! .nicode 'unctions im"lemented in #indo!s B^. This code 'ragment assumes0 o' course0 that "egister$lass is not 'ailing 'or some other reason0 such as a N.,, lpfn&nd4roc 'ield o' the #NDC,5SS structure. The 2et(ast,rror 'unction hel"s you determine the cause o' the error in cases li e this. 2et(ast,rror is a general:"ur"ose 'unction in #indo!s to get e4tended error in'ormation !hen a 'unction call 'ails. The documentation o' the various 'unctions !ill indicate !hether you can use 2et(ast,rror to o(tain this in'ormation. +n the case o' calling "egister$lass& in #indo!s B^0 2et(ast,rror returns =;F. Nou can loo in #+N388%8.- to see that the value =;F corres"onds to the identi'ier 388%89C5,,9N%T9+&$,3&3NT3D. Nou can also loo u" the error in 34latform 0'53&indows )ase 0ervices3'ebugging and ,rror -andling3,rror $odes30#stem ,rrors - +umerical >rder. Some #indo!s "rogrammers li e to chec the return value o' every 'unction call 'or errors. This certainly ma es some sense0 and here7s !hy: +7m sure you7re 'amiliar !ith the rule that you al!ays0 al!ays chec 'or an error !hen you7re allocating memory. #ell0 many #indo!s 'unctions need to allocate some memory. /or e4am"le0 "egister$lass needs to allocate memory to store in'ormation a(out the !indo! class. So you should (e chec ing the 'unction regardless. %n the other hand0 i' "egister$lass 'ails (ecause it can7t allocate the memory it needs0 #indo!s has "ro(a(ly already ground to a halt. + do a minimum o' error chec ing in the sam"le "rograms in this (oo . This is not (ecause + don7t thin error chec ing is a good idea0 (ut (ecause it !ould distract 'rom !hat the "rograms are su""osed to illustrate. /inally0 a historical note: +n some sam"le #indo!s "rograms0 you might see the 'ollo!ing code in &inMain:
if (OhCrev=nstance) { ,ndclass.c!:t%le ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; [other wndclass initialization] Ue+ister4lass (],ndclass) ; This comes under the category o' Iold ha(its die hard.I +n =C:(it versions o' #indo!s0 i' you started u" a ne! instance o' a "rogram that !as already running0 the h4rev*nstance "arameter to &inMain !ould (e the instance handle o' the "revious instance. To save memory0 t!o or more instances !ere allo!ed to share the same !indo! class. Thus0 the !indo! class !as registered only i' h4rev*nstance !as N.,,0 indicating that no other instances o' the "rogram !ere running. +n G;:(it versions o' #indo!s0 h4rev*nstance is al!ays N.,,. This code !ill still !or "ro"erly0 (ut it7s not necessary to chec h4rev*nstance.
8:&K=;=K=\PIDW ^ \ 8:&KFW=K=\PIDW) The I!indo! ca"tionI is the te4t that !ill a""ear in the title (ar o' the !indo!. The arguments mar ed Iinitial 4 "ositionI and Iinitial y "ositionI s"eci'y the initial "osition o' the u""er le't corner o' the !indo! relative to the u""er le't corner o' the screen. 1y using the identi'ier C#9.S3D3/5.,T 'or these "arameters0 !e are indicating that !e !ant #indo!s to use the de'ault "osition 'or an overla""ed !indo!. (C#9.S3D3/5.,T is de'ined as F4^FFFFFFF.* 1y de'ault0 #indo!s "ositions successive ne!ly created !indo!s at ste""ed horiPontal and vertical o''sets 'rom the u""er le't corner o' the dis"lay. Similarly0 the Iinitial 4 siPeI and Iinitial y siPeI arguments s"eci'y the initial !idth and height o' the !indo!. The C#9.S3D3/5.,T identi'ier again indicates that !e !ant #indo!s to use a de'ault siPe 'or the !indo!. The argument mar ed I"arent !indo! handleI is set to N.,, !hen creating a Ito":levelI !indo!0 such as an a""lication !indo!. Normally0 !hen a "arent:child relationshi" e4ists (et!een t!o !indo!s0 the child !indo! al!ays a""ears on the sur'ace o' its "arent. 5n a""lication !indo! a""ears on the sur'ace o' the des to" !indo!0 (ut you don7t need to 'ind out the des to" !indo!7s handle to call $reate&indow. The I!indo! menu handleI is also set to N.,, (ecause the !indo! has no menu. The I"rogram instance handleI is set to the instance handle "assed to the "rogram as a "arameter o' &inMain. /inally0 a Icreation "arametersI "ointer is set to N.,,. Nou could use this "arameter to "oint to some data that you might later !ant to re'erence in your "rogram. The $reate&indow call returns a handle to the created !indo!. This handle is saved in the varia(le hwnd0 !hich is de'ined to (e o' ty"e -#ND (Ihandle to a !indo!I*. 3very !indo! in #indo!s has a handle. Nour "rogram uses the handle to re'er to the !indo!. &any #indo!s 'unctions re)uire hwnd as an argument so that #indo!s no!s !hich !indo! the 'unction a""lies to. +' a "rogram creates many !indo!s0 each has a di''erent handle. The handle to a !indo! is one o' the most im"ortant handles that a #indo!s "rogram ("ardon the e4"ression* handles.
%he Message &oo5'ter the 1pdate&indow call0 the !indo! is 'ully visi(le on the video dis"lay. The "rogram must no! ma e itsel' ready to read ey(oard and mouse in"ut 'rom the user. #indo!s maintains a Imessage )ueueI 'or each #indo!s "rogram currently running under #indo!s. #hen an in"ut event occurs0 #indo!s translates the event into a ImessageI that it "laces in the "rogram7s message )ueue. 5 "rogram retrieves these messages 'rom the message )ueue (y e4ecuting a (loc o' code no!n as the Imessage loo"I: ,hile (YetKessa+e (]ms+# ;VLL# /# /))
The msg varia(le is a structure o' ty"e &S20 !hich is de'ined in the #+N.S38.- header 'ile li e this: t%pedef struct ta+K:Y { ?8;L h,nd ; V=;( messa+e ; 8CFUFK ,Caram ; LCFUFK lCaram ; L8DUL time ; CD=;( pt ; K:Y# 3 CK:Y ; The $%+NT data ty"e is yet another structure0 de'ined in the #+ND3/.- header 'ile li e this: t%pedef struct ta+CD=;( { LD;Y " ; LD;Y % ; CD=;(# 3 CCD=;(; The 2etMessage call that (egins the message loo" retrieves a message 'rom the message )ueue: YetKessa+e (]ms+# ;VLL# /# /) This call "asses to #indo!s a "ointer to a &S2 structure named msg. The second0 third0 and 'ourth arguments are set to N.,, or F to indicate that the "rogram !ants all messages 'or all !indo!s created (y the "rogram. #indo!s 'ills in the 'ields o' the message structure !ith the ne4t message 'rom the message )ueue. The 'ields o' this structure are: hwnd The handle to the !indo! !hich the message is directed to. +n the -3,,%#+N "rogram0 this is the same as the hwnd value returned 'rom $reate&indow0 (ecause that7s the only !indo! the "rogram has. message The message identi'ier. This is a num(er that identi'ies the message. /or each message0 there is a corres"onding identi'ier de'ined in the #indo!s header 'iles (most o' them in #+N.S38.-* that (egins !ith the identi'ier #& (I!indo! messageI*. /or e4am"le0 i' you "osition the mouse "ointer over -3,,%#+N7s client area and "ress the le't mouse (utton0 #indo!s !ill "ut a message in the message )ueue !ith a message 'ield e)ual to #&9,1.TT%ND%#N0 !hich is the value F4F;F=. w4aram 5 G;:(it Imessage "arameter0I the meaning and value o' !hich de"end on the "articular message. l4aram 5nother G;:(it message "arameter de"endent on the message. time The time the message !as "laced in the message )ueue. pt The mouse coordinates at the time the message !as "laced in the message )ueue. +' the message 'ield o' the message retrieved 'rom the message )ueue is anything e4ce"t #&9@.+T (!hich e)uals F4FF=;*0 2etMessage returns a nonPero value. 5 #&9@.+T message causes 2etMessage to return F. The statement: (ranslateKessa+e (]ms+) ; "asses the msg structure (ac to #indo!s 'or some ey(oard translation. (+7ll discuss this more in Cha"ter C.* The statement LispatchKessa+e (]ms+) ; again "asses the msg structure (ac to #indo!s. #indo!s then sends the message to the a""ro"riate !indo! "rocedure 'or "rocessing. #hat this means is that #indo!s calls the !indo! "rocedure. +n -3,,%#+N0 the !indo! "rocedure is &nd4roc. 5'ter &nd4roc "rocesses the message0 it returns control to #indo!s0 !hich is still servicing the 'ispatchMessage call. #hen #indo!s returns to -3,,%#+N 'ollo!ing the 'ispatchMessage call0 the message loo" continues !ith the ne4t 2etMessage call.
5ll that +7ve descri(ed so 'ar is really 6ust overhead. The !indo! class has (een registered0 the !indo! has (een created0 the !indo! has (een dis"layed on the screen0 and the "rogram has entered a message loo" to retrieve messages 'rom the message )ueue. The real action occurs in the !indo! "rocedure. The !indo! "rocedure determines !hat the !indo! dis"lays in its client area and ho! the !indo! res"onds to user in"ut. +n -3,,%#+N0 the !indo! "rocedure is the 'unction named &nd4roc. 5 !indo! "rocedure can have any name (as long as it doesn7t con'lict !ith some other name0 o' course*. 5 #indo!s "rogram can contain more than one !indo! "rocedure. 5 !indo! "rocedure is al!ays associated !ith a "articular !indo! class that you register (y calling "egister$lass. The $reate&indow 'unction creates a !indo! (ased on a "articular !indo! class. &ore than one !indo! can (e created (ased on the same !indo! class. 5 !indo! "rocedure is al!ays de'ined li e this: LUP:VL( 4FLLIF4X 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK lCaram) The 'our "arameters to the !indo! "rocedure are identical to the 'irst 'our 'ields o' the &S2 structure. The 'irst "arameter is hwnd0 the handle to the !indo! receiving the message. This is the same handle returned 'rom the $reate&indow 'unction. /or a "rogram li e -3,,%#+N0 !hich creates only one !indo!0 this is the only !indo! handle the "rogram no!s a(out. +' a "rogram creates multi"le !indo!s (ased on the same !indo! class (and hence the same !indo! "rocedure*0 hwnd identi'ies the "articular !indo! receiving the message. The second "arameter is the same as the message 'ield in the &S2 structure. +t7s a num(er that identi'ies the message. The last t!o "arameters are G;:(it message "arameters that "rovide more in'ormation a(out the message. #hat these "arameters contain is s"eci'ic to each ty"e o' message. Sometimes a message "arameter is t!o =C:(it values stuc together0 and sometimes a message "arameter is a "ointer to a te4t string or to a data structure. $rograms generally don7t call !indo! "rocedures directly. The !indo! "rocedure is almost al!ays called 'rom #indo!s itsel'. 5 "rogram can indirectly call its o!n !indo! "rocedure (y calling a 'unction named 0endMessage0 !hich !e7ll e4amine in later cha"ters.
device driver. Nou need the device conte4t handle to dis"lay te4t and gra"hics in the client area o' a !indo!. .sing the device conte4t handle returned 'rom )egin4aint0 you cannot dra! outside the client area0 even i' you try. ,nd4aint releases the device conte4t handle so that it is no longer valid. +' a !indo! "rocedure does not "rocess #&9$5+NT messages (!hich is very rare*0 they must (e "assed on to 'ef&indow4roc. 'ef&indow4roc sim"ly calls )egin4aint and ,nd4aint in succession so that the client area is validated. 5'ter &nd4roc calls )egin4aint0 it calls 2et$lient"ect: Yet4lientUect (h,nd# ]rect) ; The 'irst argument is the handle to the "rogram7s !indo!. The second argument is a "ointer to a rectangle structure o' ty"e 83CT. This structure has 'our ,%N2 'ields named left0 top0 right0 and bottom. The 2et$lient"ect 'unction sets these 'our 'ields to the dimensions o' the client area o' the !indo!. The left and top 'ields are al!ays set to F. Thus0 the right and bottom 'ields re"resent the !idth and height o' the client area in "i4els. &nd4roc doesn7t do anything !ith this 83CT structure e4ce"t "ass a "ointer to it as the 'ourth argument to 'raw.ext: Lra,(e"t (hdc# (PW( ("?ello# 8indo,s STO")# 91# ]rect# L(&:=;YLPL=;P ^ L(&4P;(PU ^ L(&_4P;(PU) ; 'raw.ext0 as the name im"lies0 dra!s te4t. 1ecause this 'unction dra!s something0 the 'irst argument is a handle to the device conte4t returned 'rom )egin4aint. The second argument is the te4t to dra!0 and the third argument is set to := to indicate that the te4t string is terminated !ith a Pero character. The last argument to 'raw.ext is a series o' (it 'lags de'ined in #+N.S38.-. (5lthough 'raw.ext seems to (e a 2D+ 'unction call (ecause it dis"lays out"ut0 it7s actually considered "art o' the .ser module (ecause it7s a 'airly high:level dra!ing 'unction. The 'unction is documented in 34latform 0'532raphics and Multimedia 0ervices32'*3!onts and .ext.* The 'lags indicate that the te4t should (e dis"layed as a single line centered horiPontally and vertically !ithin the rectangle s"eci'ied (y the 'ourth argument. This 'unction call thus causes the string I-ello0 #indo!s B^JI to (e dis"layed centered in the client area. #henever the client area (ecomes invalid (as it does !hen you change the siPe o' the !indo!*0 &nd4roc receives a ne! #&9$5+NT message. &nd4roc o(tains the u"dated !indo! siPe (y calling 2et$lient"ect and again dis"lays the te4t in the ne4t center o' the !indo!.
%he Windows Programming '$rdles 3ven !ith my e4"lanation o' -3,,%#+N0 the structure and !or ings o' the "rogram are "ro(a(ly still )uite mysterious. +n a short C "rogram !ritten 'or a character:mode environment0 the entire "rogram might (e contained in the main 'unction. +n -3,,%#+N0 &inMain contains only "rogram overhead necessary to
register the !indo! class0 create the !indo!0 and retrieve and dis"atch messages 'rom the message )ueue. 5ll the real action o' the "rogram occurs in the !indo! "rocedure. +n -3,,%#+N0 this action is not muchS&nd4roc sim"ly "lays a sound 'ile and dis"lays a te4t string in its !indo!. 1ut in later cha"ters0 you7ll 'ind that almost everything a #indo!s "rogram does is in res"onse to a message to a !indo! "rocedure. This is one o' the ma6or conce"tual hurdles you must lea" to (egin !riting #indo!s "rograms. DonXt Call Me. #Xll Call 8o$ Programmers are well acK$ainted with the idea of calling on the o-erating s(stem to do something. /or e4am"le0 C "rogrammers use the "rint' 'unction to dis"lay on the console. The "rint' 'unction is im"lemented !ith a call to the o"erating system to dis"lay out"ut on de'ault out"ut device. No "ro(lem. 1ut #indo!s is di''erent. 5lthough #indo!s has a cou"le thousand 'unction calls0 #indo!s also ma es calls to #our "rogram0 s"eci'ically to the !indo! "rocedure !e have called &nd4roc. The !indo! "rocedure is associated !ith a !indo! class that the "rogram registers (y calling "egister$lass. 5 !indo! that is created (ased on this !indo! class uses this !indo! "rocedure 'or "rocessing all messages to the !indo!. #indo!s sends a message to the !indo! (y calling the !indo! "rocedure. #indo!s calls &nd4roc !hen a !indo! is 'irst created. #indo!s calls &nd4roc !hen the !indo! is eventually destroyed. #indo!s calls &nd4roc !hen the !indo! has (een resiPed or moved or minimiPed. #indo!s calls &nd4roc !hen a user clic s on the !indo! !ith the mouse. #indo!s calls &nd4roc !hen characters are ty"ed 'rom the ey(oard. #indo!s calls &nd4roc !hen an item has (een selected 'rom a menu. #indo!s calls &nd4roc !hen a scroll (ar is mani"ulated or clic ed !ith the mouse. #indo!s calls &nd4roc to tell it !hen it must re"aint its client area. 5ll these calls to &nd4roc are in the 'orm o' messages. +n most #indo!s "rograms0 the (ul o' the "rogram is dedicated to handling these messages. The messages that #indo!s can send to a "rogram are generally identi'ied !ith names that (egin !ith the letters #& and are de'ined in the #+N.S38.- header 'ile. 5ctually0 the idea o' a routine !ithin a "rogram that is called 'rom outside the "rogram is not unheard o' in character:mode "rogramming. The signal 'unction in
C can tra" a Ctrl:C (rea or other interru"ts 'rom the o"erating system. %ld "rograms !ritten 'or &S:D%S o'ten tra""ed hard!are interru"ts. 1ut in #indo!s this conce"t is e4tended to cover everything. 3verything that ha""ens to a !indo! is relayed to the !indo! "rocedure in the 'orm o' a message. The !indo! "rocedure then res"onds to this message in some !ay or "asses the message to 'ef&indow4roc 'or de'ault "rocessing. The w4aram and l4aram "arameters to the !indo! "rocedure are not used in -3,,%#+N e4ce"t as "arameters to 'ef&indow4roc. These "arameters give the !indo! "rocedure additional in'ormation a(out the message. The meaning o' the "arameters is message:de"endent. ,et7s loo at an e4am"le. #henever the client area o' a !indo! changes in siPe0 #indo!s calls that !indo!7s !indo! "rocedure. The hwnd "arameter to the !indo! "rocedure is the handle o' the !indo! changing in siPe. (Remem/er that one window -roced$re co$ld /e handling messages for m$lti-le windows that were created /ased on the same window classA %he hwnd -arameter lets the window -roced$re +now which window is receiving the message .* The message "arameter is #&9S+X3. The w4aram "arameter 'or a #&9S+X3 message is the value S+X3983ST%83D0 S+X39&+N+&+X3D0 S+X39&5A+&+X3D0 S+X39&5AS-%#0 or S+X39&5A-+D3 (de'ined in the #+N.S38.- header 'ile as the num(ers F through >*. That is0 the w4aram "arameter indicates !hether the !indo! is (eing changed to a nonminimiPed or nonma4imiPed siPe0 (eing minimiPed0 (eing ma4imiPed0 or (eing hidden. The l4aram "arameter contains the ne! siPe o' the !indo!. The ne! !idth (a =C: (it value* and the ne! height (a =C:(it value* are stuc together in the G;:(it l4aram. The #+ND3/.- header 'ile de'ines some handy macros that hel" you e4tract these t!o values 'rom l4aram. #e !ill see that later. Sometimes messages generate other messages as a result o' 'ef&indow4roc "rocessing. /or e4am"le0 su""ose you run -3,,%#+N and you eventually clic the Close (utton0 or su""ose you select Close 'rom the system menu using either the ey(oard or the mouse. 'ef&indow4roc "rocesses this ey(oard or mouse in"ut. #hen it detects that you have selected the Close o"tion0 it sends a #&9SNSC%&&5ND message to the !indo! "rocedure. &nd4roc "asses this message to 'ef&indow4roc. 'ef&indow4roc res"onds (y sending a #&9C,%S3 message to the !indo! "rocedure. &nd4roc again "asses this message to 'ef&indow4roc. 'ef&indow4roc res"onds to the #&9C,%S3 message (y
calling 'estro#&indow. 'estro#&indow causes #indo!s to send a #&9D3ST8%N message to the !indo! "rocedure. &nd4roc 'inally res"onds to this message (y calling 4ost?uitMessage to "ut a #&9@.+T message in the message )ueue. This message causes the message loo" in &inMain to terminate and the "rogram to end. [$e$ed and )onK$e$ed Messages +7ve tal ed a(out #indo!s sending messages to a !indo!0 !hich means that #indo!s calls the !indo! "rocedure. 1ut a #indo!s "rogram also has a message loo" that retrieves messages 'rom a message )ueue (y calling 2etMessage and dis"atches these messages to the !indo! "rocedure (y calling 'ispatchMessage. So0 does a #indo!s "rogram "oll 'or messages (much li e a character:mode "rogram "olling 'or ey(oard in"ut* and then route these messages to some locationW %r does it receive messages directly 'rom outside the "rogramW #ell0 (oth. &essages can (e either I)ueuedI or Inon)ueued.I The )ueued messages are those that are "laced in a "rogram7s message )ueue (y #indo!s. +n the "rogram7s message loo"0 the messages are retrieved and dis"atched to the !indo! "rocedure. The non:)ueued messages are the results o' calls (y #indo!s (%S* directly to the !indo! "rocedure. +t is said that )ueued messages are I"ostedI to a message )ueue and that non:)ueued messages are IsentI to the !indo! "rocedure. +n any case0 the !indo! "rocedure gets all the messagesS(oth )ueued and non:)ueuedS'or the !indo!. The !indo! "rocedure is Imessage centralI 'or the !indo!. The )ueued messages are "rimarily those that result 'rom user in"ut in the 'orm o' eystro es (such as the #&9K3ND%#N and #&9K3N.$ messages*0 characters that result 'rom eystro es (#&9C-58*0 mouse movement (#&9&%.S3&%V3*0 and mouse:(utton clic s (#&9,1.TT%ND%#N*. @ueued messages also include the timer message (#&9T+&38*0 the re"aint message (#&9$5+NT*0 and the )uit message (#&9@.+T*. The non)ueued messages are everything else. Non)ueued messages o'ten result 'rom calling certain #indo!s 'unctions. /or e4am"le0 !hen &inMain calls $reate&indow0 #indo!s creates the !indo! and in the "rocess sends the !indo! "rocedure a #&9C835T3 message. #hen &inMain calls 0how&indow0 #indo!s sends the !indo! "rocedure #&9S+X3 and #&9S-%##+ND%# messages. #hen &inMain calls 1pdate&indow0 #indo!s sends the !indo!
"rocedure a #&9$5+NT message. @ueued messages signaling ey(oard or mouse in"ut can also result in non:)ueued messages. /or e4am"le0 !hen you select a menu item !ith the ey(oard or mouse0 the ey(oard or mouse message is )ueued (ut the eventual #&9C%&&5ND message indicating that a menu item has (een selected is non:)ueued. This "rocess is o(viously com"le40 (ut 'ortunately most o' the com"le4ity is #indo!s7 "ro(lem rather than our "rogram7s. /rom the "ers"ective o' the !indo! "rocedure0 these messages come through in an orderly and synchroniPed manner. The !indo! "rocedure can do something !ith these messages or ignore them. #hen + say that messages come through in an orderly and synchroniPed manner0 + mean 'irst that messages are not li+e hardware interr$-ts. #hile "rocessing one message in a !indo! "rocedure0 the "rogram !ill not (e suddenly interru"ted (y another message. 5lthough #indo!s "rograms can have multi"le threads o' e4ecution0 each thread7s message )ueue handles messages 'or only the !indo!s !hose !indo! "rocedures are e4ecuted in that thread. +n other !ords0 the message loo" and the !indo! "rocedure do not run concurrently. #hen a message loo" retrieves a message 'rom its message )ueue and calls 'ispatchMessage to send the message o'' to the !indo! "rocedure0 'ispatchMessage does not return until the !indo! "rocedure has returned control (ac to #indo!s. -o!ever0 the !indo! "rocedure could call a 'unction that sends the !indo! "rocedure another message0 in !hich case the !indo! "rocedure must 'inish "rocessing the second message (e'ore the 'unction call returns0 at !hich time the !indo! "rocedure "roceeds !ith the original message. /or e4am"le0 !hen a !indo! "rocedure calls 1pdate&indow0 #indo!s calls the !indo! "rocedure !ith a #&9$5+NT message. #hen the !indo! "rocedure 'inishes "rocessing the #&9$5+NT message0 the 1pdate&indow call !ill return controls (ac to the !indo! "rocedure. This means that !indo! "rocedures must (e reentrant. +n most cases0 this doesn7t cause "ro(lems0 (ut you should (e a!are o' it. /or e4am"le0 su""ose you set a static varia(le in the !indo! "rocedure !hile "rocessing a message and then you call a #indo!s 'unction. ."on return 'rom that 'unction0 can you (e assured that the varia(le is still the sameW Not necessarilySnot i' the "articular #indo!s 'unction you call generated another message and the !indo! "rocedure changes the varia(le !hile "rocessing that second message. This is one o' the reasons !hy
certain 'orms o' com"iler o"timiPation must (e turned o'' !hen com"iling #indo!s "rograms. +n many cases0 the !indo! "rocedure must retain in'ormation it o(tains in one message and use it !hile "rocessing another message. This in'ormation must (e saved in varia(les de'ined as static in the !indo! "rocedure0 or saved in glo(al varia(les. %' course0 you7ll get a much (etter 'eel 'or all o' this in later cha"ters as the !indo! "rocedures are e4"anded to "rocess more messages. 6et #n and O$t Fast #indo!s B^ and #indo!s NT are "reem"tive multitas ing environments. This means that as one "rogram is doing a lengthy 6o(0 #indo!s can allo! the user to s!itch control to another "rogram. This is a good thing0 and it is one advantage o' the current versions o' #indo!s over the older =C:(it versions. -o!ever0 (ecause o' the !ay that #indo!s is structured0 this "reem"tive multitas ing does not al!ays !or the !ay you might li e. /or e4am"le0 su""ose your "rogram s"ends a minute or t!o "rocessing a "articular message. Nes0 the user can s!itch to another "rogram. 1ut the user cannot do anything !ith #our "rogram. The user cannot move your "rogram7s !indo!0 resiPe/ minimiPe/close it. That7s (ecause your !indo! "rocedure is (usy doing a lengthy 6o(. %h0 it may not seem li e the !indo! "rocedure "er'orms its o!n moving and siPing o"erations0 (ut it does. That7s "art o' the 6o( o' 'ef&indow4roc0 !hich must (e considered as "art o' your !indo! "rocedure.
This !or s (oth !ays. <ust as your "rogram may 'ind itsel' !ith a client area (arely large enough in !hich to say I-ello0I it may also someday (e run on a (ig:screen0 high:resolution video system and discover a client area large enough 'or t!o entire "ages o' te4t and "lenty o' closet s"ace (esides. Dealing intelligently !ith (oth eventualities is an im"ortant "art o' #indo!s "rogramming. #e !ill learn ho! a "rogram dis"lays something on the sur'ace o' its client area !ith more so"histication than that illustrated in the last cha"ter. #hen a "rogram dis"lays te4t or gra"hics in its client area0 it is o'ten said to (e I"aintingI its client area. 5lthough #indo!s has e4tensive 2ra"hics Device +nter'ace (2D+* 'unctions 'or dis"laying gra"hics0 here0 +7ll stic to dis"laying sim"le lines o' te4t. +7ll also ignore the various 'ont 'aces and 'ont siPes that #indo!s ma es availa(le and use only #indo!s7 de'ault Isystem 'ont.I
Dealing !ith #&9$5+NT message re)uires that you alter the !ay you thin a(out ho! you !rite to the video dis"lay. Nour "rogram should (e structured so that it accumulates all the in'ormation necessary to "aint the client area (ut "aints only Ion demandIS!hen #indo!s sends the !indo! "rocedure a #&9$5+NT message. +' your "rogram needs to u"date its client area at some other time0 it can 'orce #indo!s to generate this #&9$5+NT message. This may seem a rounda(out method o' dis"laying something on the screen0 (ut the structure o' your "rogram !ill (ene'it 'rom it.
The device conte4t (also called sim"ly the IDCI* is really 6ust a data structure maintained internally (y 2D+. 5 device conte4t is associated !ith a "articular dis"lay device0 such as a video dis"lay or a "rinter. /or a video dis"lay0 a device conte4t is usually associated !ith a "articular !indo! on the dis"lay. Some o' the values in the device conte4t are gra"hics Iattri(utes.I These attri(utes de'ine some "articulars o' ho! 2D+ dra!ing 'unctions !or . #ith .ext>ut0 'or instance0 the attri(utes o' the device conte4t determine the color o' the te4t0 the color o' the te4t (ac ground0 ho! the 4:coordinate and y:coordinate in the .ext>ut 'unction are ma""ed to the client area o' the !indo!0 and !hat 'ont #indo!s uses !hen dis"laying the te4t. #hen a "rogram needs to "aint0 it must 'irst o(tain a handle to a device conte4t. #hen you o(tain this handle0 #indo!s 'ills the internal device conte4t structure !ith de'ault attri(ute values. 5s you7ll see in later cha"ters0 you can change these de'aults (y calling various 2D+ 'unctions. %ther 2D+ 'unctions let you o(tain the current values o' these attri(utes. Then0 o' course0 there are still other 2D+ 'unctions that let you actually "aint the client area o' the !indo!. 5'ter a "rogram has 'inished "ainting its client area0 it should release the device conte4t handle. #hen a "rogram releases the handle0 the handle is no longer valid and must not (e used. The "rogram should o(tain the handle and release the handle during the "rocessing o' a single message. 34ce"t 'or a device conte4t created !ith a call to $reate'$ (a 'unction + !on7t discuss in this cha"ter*0 you should not ee" a device conte4t handle around 'rom one message to another. #indo!s a""lications generally use t!o methods 'or getting a device conte4t handle in "re"aration 'or "ainting the screen.
The rc4aint rectangle in $5+NTST8.CT is not only the invalid rectangleL it is also a Icli""ingI rectangle. This means that #indo!s restricts "ainting to !ithin the cli""ing rectangle. &ore "recisely0 i' the invalid region is not rectangular0 #indo!s restricts "ainting to !ithin that region. To "aint outside the u"date rectangle !hile "rocessing #&9$5+NT messages0 you can ma e this call: =nvalidateUect (h,nd# ;VLL# (UVP) ; (e'ore calling )egin4aint. This invalidates the entire client area and causes )egin4aint to erase the (ac ground. 5 /5,S3 value in the last argument !ill not erase the (ac ground. #hatever !as there !ill stay. +t is usually most convenient 'or a #indo!s "rogram to sim"ly re"aint the entire client area !henever it receives a #&9$5+NT message0 regardless o' the rc4aint structure. /or e4am"le0 i' "art o' the dis"lay out"ut in the client area includes a circle (ut only "art o' the circle 'alls !ithin the invalid rectangle0 it ma es little sense to dra! only the invalid "art o' the circle. Dra! the !hole circle. #hen you use the device conte4t handle returned 'rom )egin4aint0 #indo!s !ill not "aint outside the rc4aint rectangle any!ay. +n the -3,,%#+N "rogram in Cha"ter ;0 !e didn7t care a(out invalid rectangles !hen "rocessing the #&9$5+NT message. +' the area !here the te4t !as dis"layed ha""ened to (e !ithin the invalid rectangle0 'raw.ext restored it. +' not0 then at some "oint during "rocessing o' the 'raw.ext call #indo!s determined it didn7t need to !rite anything on the dis"lay. 1ut this determination ta es time. 5 "rogrammer concerned a(out "er'ormance and s"eed (and that includes all o' us0 + ho"e* !ill !ant to use the invalid rectangle during "rocessing o' the #&9$5+NT message to avoid unnecessary 2D+ calls. This is "articularly im"ortant i' "ainting re)uires accessing dis 'iles such as (itma"s.
,et7s e4amine this 'unction in more detail. The 'irst argument is the handle to the device conte4tSeither the hdc value returned 'rom 2et'$ or the hdc value returned 'rom )egin4aint during "rocessing o' a #&9$5+NT message. The attri(utes o' the device conte4t control the characteristics o' this dis"layed te4t. /or instance0 one attri(ute o' the device conte4t s"eci'ies the te4t color. The de'ault color (!e discover !ith some degree o' com'ort* is (lac . The de'ault device conte4t also de'ines a te4t (ac ground color0 and this is !hite. #hen a "rogram !rites te4t to the dis"lay0 #indo!s uses this (ac ground color to 'ill in the rectangular s"ace surrounding each character0 called the Icharacter (o4.I The te4t (ac ground color is not the same (ac ground you set !hen de'ining the !indo! class. The (ac ground in the !indo! class is a (rushS!hich is a "attern that may or may not (e a "ure colorSthat #indo!s uses to erase the client area. +t is not "art o' the device conte4t structure. #hen de'ining the !indo! class structure0 most #indo!s a""lications use #-+T3918.S- so that the de'ault te4t (ac ground color in the de'ault device conte4t is the same color as the (rush #indo!s uses to erase the (ac ground o' the client area. The ps.ext argument is a "ointer to a character string0 and i(ength is the num(er o' characters in the string. +' ps.ext "oints to a .nicode character string0 then the num(er o' (ytes in the string is dou(le the i(ength value. The string should not contain any 5SC++ control characters such as carriage returns0 line'eeds0 ta(s0 or (ac s"aces. #indo!s dis"lays these control characters as (o4es or solid (loc s. .ext>ut does not recogniPe a Pero (yte (or 'or .nicode0 a Pero short integer* as denoting the end o' a string. The 'unction uses the i(ength argument to determine the string7s length. The x and # arguments to .ext>ut de'ine the starting "oint o' the character string !ithin the client area. The x value is the horiPontal "ositionL the # value is the vertical "osition. The u""er le't corner o' the 'irst character is "ositioned at the coordinate "oint (x0 #*. +n the de'ault device conte4t0 the origin (that is0 the "oint !here x and # (oth e)ual F* is the u""er le't corner o' the client area. +' you use Pero values 'or x and # in .ext>ut0 the character string starts 'lush against the u""er le't corner o' the client area. #hen you read the documentation o' a 2D+ dra!ing 'unction such as .ext>ut0 you7ll 'ind that the coordinates "assed to the 'unction are usually documented as Ilogical coordinates.I /or no!0 (e a!are that #indo!s has a variety o' Ima""ing modesI that govern ho! the logical coordinates s"eci'ied in 2D+ dra!ing 'unctions are translated to the "hysical "i4el coordinates o' the dis"lay. The ma""ing mode is de'ined in the device conte4t. The de'ault ma""ing mode is called &&9T3AT (using the identi'ier de'ined in the #+N2D+.- header 'ile*. .nder the &&9T3AT ma""ing mode0 logical units are the same as "hysical units0 !hich are "i4els0 relative to the u""er le't corner o' the client area. Values o' x increase as you move to the right in the client area0 and values o' # increase as you move do!n in the client area. (See /igure (elo!.* The &&9T3AT coordinate system is identical to the coordinate system that #indo!s uses to de'ine the invalid rectangle in the $5+NTST8.CT structure. (Things are not )uite as convenient !ith the other ma""ing modes0 ho!ever.*
The device conte4t also de'ines a cli""ing region. 5s you7ve seen0 the de'ault cli""ing region is the entire client area 'or a device conte4t handle o(tained 'rom 2et'$ and the invalid region 'or the device conte4t handle o(tained 'rom )egin4aint. #hen you call .ext>ut0 #indo!s !ill not dis"lay any "art o' the character string that lies outside the cli""ing region. +' a character is "artly !ithin the cli""ing region0 #indo!s dis"lays only the "ortion o' the character inside the region. #riting outside the client area o' your !indo! isn7t easy to do0 so don7t !orry a(out doing it inadvertently.
#hen you need to determine the te4t metrics0 you get a handle to a device conte4t and call 2et.extMetrics: hdc ' YetL4 (h,nd) ; Yet(e"tKetrics (hdc# ]tm) ; UeleaseL4 (h,nd# hdc) ; Nou can then e4amine the values in the te4t metric structure and "ro(a(ly save a 'e! o' them 'or 'uture use.
!our values defining vertical character sizes in a font. The most im"ortant value is tm-eight0 !hich is the sum o' tm/scent and tm'escent. These t!o values re"resent the ma4imum vertical e4tents o' characters in the 'ont a(ove and (elo! the (aseline. The term IleadingI re'ers to s"ace that a "rinter inserts (et!een lines o' te4t. +n the T3AT&3T8+C structure0 internal leading is included in tm/scent (and thus in tm-eight* and is o'ten the s"ace in !hich accent mar s a""ear. The tm*nternal(eading 'ield could (e set to F0 in !hich case accented letters are made a little shorter so that the accent mar s 'it !ithin the ascent o' the character. The T3AT&3T8+C structure also includes a 'ield named tm,xternal(eading0 !hich is not included in the tm-eight value. This is an amount o' s"ace that the designer o' the 'ont suggests (e added (et!een successive ro!s o' dis"layed te4t. Nou can acce"t or re6ect the 'ont designer7s suggestion 'or including e4ternal leading !hen s"acing lines o' te4t. +n the system 'onts that +7ve encountered recently0 tm,xternal(eading has (een Pero0 !hich is !hy + didn7t include it in /igure >:G. (Des"ite my vo! not to tell you the dimensions o' a system 'ont0 /igure >:G is accurate 'or the system 'ont that #indo!s uses (y de'ault 'or a C>F (y >^F dis"lay.* The T3AT&3T8+C structure contains t!o 'ields that descri(e character !idths: the tm/ve$har&idth 'ield is a !eighted average o' lo!ercase characters0 and tmMax$har&idth is the !idth o' the !idest character in the 'ont. /or a 'i4ed:"itch 'ont0 these values are the same. The sam"le "rograms in this cha"ter !ill re)uire another character !idthSthe average !idth o' u""ercase letters. Nou can calculate this 'airly accurately as =?FZ o' tm/ve$har&idth. +t7s im"ortant to realiPe that the dimensions o' a system 'ont are de"endent on the "i4el siPe o' the video dis"lay on !hich #indo!s runs and0 in some cases0 on the system 'ont siPe the user has selected. #indo!s "rovides a device: inde"endent gra"hics inter'ace0 (ut you have to hel". Don7t !rite your #indo!s "rograms so that they guess at character dimensions. Don7t hard:code any values. .se the 2et.extMetrics 'unction to o(tain this in'ormation.
Formatting %e=t
1ecause the dimensions o' the system 'ont do not change during a #indo!s session0 you need to call 2et.extMetrics only once !hen your "rogram e4ecutes. 5 good "lace to ma e this call is !hile "rocessing the #&9C835T3 message in the !indo! "rocedure. The #&9C835T3 message is the 'irst message the !indo! "rocedure receives. #indo!s calls your !indo! "rocedure !ith a #&9C835T3 message !hen you call $reate&indow in &inMain. Su""ose you7re !riting a #indo!s "rogram that dis"lays several lines o' te4t running do!n the client area. Nou7ll !ant to o(tain values 'or the character !idth and height. #ithin the !indo! "rocedure you can de'ine t!o varia(les to save the average character !idth (cx$har* and the total character height (c#$har*: static int c"4har# c%4har ; The "re'i4 c added to the varia(les names stands 'or Icount0I and in this case means a count o' (or num(er o'* "i4els. +n com(ination !ith x or #0 the "re'i4 re'ers to a !idth or height. These varia(les are de'ined as static (ecause they must (e valid !hen the !indo! "rocedure "rocesses other messages0 such as #&9$5+NT. %r you can de'ine the varia(les glo(ally outside o' any 'unction. -ere7s the #&9C835T3 code to o(tain the !idth and height o' characters in the system 'ont: case 8K&4UPF(P7 hdc ' YetL4 (h,nd) ; Yet(e"tKetrics (hdc# ]tm) ; c"4har ' tm.tmFve4har8idth ; c%4har ' tm.tm?ei+ht * tm.tmP"ternalLeadin+ ; UeleaseL4 (h,nd# hdc) ; return / ; Notice that +7ve included the tm,xternal(eading 'ield in the calculation o' c#$har. 3ven though this 'ield is F in the system 'onts +7ve seen lately0 it should (e included i' it7s ever nonPero (ecause it ma es 'or more reada(le line s"acing. 3ach successive line o' te4t is dis"layed c#$har "i4els 'urther do!n the !indo!. Nou7ll o'ten 'ind it necessary to dis"lay 'ormatted num(ers as !ell as sim"le character strings. 5s + discussed earlier you can7t use the traditional tool 'or this 6o( (the (eloved printf 'unction*0 (ut you can use sprintf and the #indo!s version o' sprintf0 wsprintf. These 'unctions !or 6ust li e printf e4ce"t that they "ut the 'ormatted string into a character string. Nou can then use .ext>ut to !rite the string to the dis"lay. Very conveniently0 the value returned 'rom sprintf and wsprintf is the length o' the string. Nou can "ass that value to .ext>ut as the i(ength argument. This code sho!s a ty"ical wsprintf and .ext>ut com(ination: int iLen+th ; (4?FU s@Iuffer QH/R ; [ other pro"ram lines ] iLen+th ' ,sprintf (s@Iuffer# (PW( ("(he sum of )i and )i is )i")# iF# iI# iF * iI) ; (e"tDut (hdc# "# %# s@Iuffer# iLen+th) ; /or something as sim"le as this0 you could dis"ense !ith the i(ength de'inition and com(ine the t!o statements into one: (e"tDut (hdc# "# %# s@Iuffer# ,sprintf (s@Iuffer# (PW( ("(he sum of )i and )i is )i")# iF# iI# iF * iI)) ; +t ain7t "retty0 (ut it !or s.
The 'unction re)uires a single argument called an Iinde4.I The inde4 is one o' D? integer identi'iers de'ined in the #indo!s header 'iles. (The num(er o' identi'iers has increased !ith each release o' #indo!sL the "rogrammer7s documentation in #indo!s =.F listed only ;C o' them.* 2et0#stemMetrics returns an integer0 usually the siPe o' the item s"eci'ied in the argument. ,et7s !rite a "rogram that dis"lays some o' the in'ormation availa(le 'rom the 2et0#stemMetrics calls in a sim"le one:line:"er:item 'ormat. #or ing !ith this in'ormation is easier i' !e create a header 'ile that de'ines an array o' structures containing (oth the #indo!s header:'ile identi'iers 'or the 2et0#stemMetrics inde4 and the te4t !e !ant to dis"lay 'or each value returned 'rom the call. This header 'ile is called SNS&3TS.- and is sho!n here.. .he 0A0M,.0.- file.
,8,M0%,A'
2399999999999999999999999999999999999999999999999 :G:KP(:.? 99 :%stem metrics displa% structure 9999999999999999999999999999999999999999999999932 #define ;VKL=;P: ((int) (si@eof s%smetrics 2 si@eof s%smetrics Q/R)) struct { int i=nde" ; (4?FU 3 s@La!el ; (4?FU 3 s@Lesc ; s%smetrics QR ' { :K&4W:4UPP;# :K&4G:4UPP;# :K&4W_:4UDLL# :K&4G?:4UDLL# :K&4G4FC(=D;# :K&4WIDULPU# :K&4GIDULPU# :K&4W6=WPL6UFKP# :K&4G6=WPL6UFKP# :K&4G_(?VKI# :K&4W?(?VKI# :K&4W=4D;# :K&4G=4D;# :K&4W4VU:DU# :K&4G4VU:DU#
(PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW(
(":K&4W:4UPP;")# (":creen ,idth in pi"els")# (":K&4G:4UPP;")# (":creen hei+ht in pi"els")# (":K&4W_:4UDLL")# ("_ertical scroll ,idth")# (":K&4G?:4UDLL")# ("?ori@ontal scroll hei+ht")# (":K&4G4FC(=D;")# ("4aption !ar hei+ht")# (":K&4WIDULPU")# ("8indo, !order ,idth")# (":K&4GIDULPU")# ("8indo, !order hei+ht")# (":K&4W6=WPL6UFKP")# ("Lialo+ ,indo, frame ,idth")# (":K&4G6=WPL6UFKP")# ("Lialo+ ,indo, frame hei+ht")# (":K&4G_(?VKI")# ("_ertical scroll thum! hei+ht")# (":K&4W?(?VKI")# ("?ori@ontal scroll thum! ,idth")# (":K&4W=4D;")# ("=con ,idth")# (":K&4G=4D;")# ("=con hei+ht")# (":K&4W4VU:DU")# ("4ursor ,idth")# (":K&4G4VU:DU")# ("4ursor hei+ht")#
:K&4GKP;V# :K&4W6VLL:4UPP;# :K&4G6VLL:4UPP;# :K&4GXF;`=8=;LD8# :K&KDV:PCUP:P;(# :K&4G_:4UDLL# :K&4W?:4UDLL# :K&LPIVY# :K&:8FCIV((D;# :K&4WK=;# :K&4GK=;# :K&4W:=\P# :K&4G:=\P# :K&4W:=\P6UFKP# :K&4G:=\P6UFKP# :K&4WK=;(UF4X# :K&4GK=;(UF4X# :K&4WLDVILP4LX# :K&4GLDVILP4LX# :K&4W=4D;:CF4=;Y# :K&4G=4D;:CF4=;Y# :K&KP;VLUDCFL=Y;KP;(# :K&CP;8=;LD8:# :K&LI4:P;FILPL# :K&4KDV:PIV((D;:# :K&:P4VUP# :K&4WPLYP# :K&4GPLYP# :K&4WK=;:CF4=;Y#
(PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW(
(":K&4GKP;V")# ("Kenu !ar hei+ht")# (":K&4W6VLL:4UPP;")# ("6ull screen client area ,idth")# (":K&4G6VLL:4UPP;")# ("6ull screen client area hei+ht")# (":K&4GXF;`=8=;LD8")# ("Xan$i ,indo, hei+ht")# (":K&KDV:PCUP:P;(")# ("Kouse present fla+")# (":K&4G_:4UDLL")# ("_ertical scroll arro, hei+ht")# (":K&4W?:4UDLL")# ("?ori@ontal scroll arro, ,idth")# (":K&LPIVY")# ("Le!u+ version fla+")# (":K&:8FCIV((D;")# ("Kouse !uttons s,apped fla+")# (":K&4WK=;")# ("Kinimum ,indo, ,idth")# (":K&4GK=;")# ("Kinimum ,indo, hei+ht")# (":K&4W:=\P")# ("Kin2Ka"24lose !utton ,idth")# (":K&4G:=\P")# ("Kin2Ka"24lose !utton hei+ht")# (":K&4W:=\P6UFKP")# ("8indo, si@in+ frame ,idth")# (":K&4G:=\P6UFKP")# ("8indo, si@in+ frame hei+ht")# (":K&4WK=;(UF4X")# ("Kinimum ,indo, trac0in+ ,idth")# (":K&4GK=;(UF4X")# ("Kinimum ,indo, trac0in+ hei+ht")# (":K&4WLDVILP4LX")# ("Lou!le clic0 " tolerance")# (":K&4GLDVILP4LX")# ("Lou!le clic0 % tolerance")# (":K&4W=4D;:CF4=;Y")# ("?ori@ontal icon spacin+")# (":K&4G=4D;:CF4=;Y")# ("_ertical icon spacin+")# (":K&KP;VLUDCFL=Y;KP;(")# ("Left or ri+ht menu drop")# (":K&CP;8=;LD8:")# ("Cen e"tensions installed")# (":K&LI4:P;FILPL")# ("Lou!le9I%te 4har :et ena!led")# (":K&4KDV:PIV((D;:")# (";um!er of mouse !uttons")# (":K&:P4VUP")# (":ecurit% present fla+")# (":K&4WPLYP")# ("-9L !order ,idth")# (":K&4GPLYP")# ("-9L !order hei+ht")# (":K&4WK=;:CF4=;Y")#
:K&4GK=;:CF4=;Y# :K&4W:K=4D;# :K&4G:K=4D;# :K&4G:K4FC(=D;# :K&4W:K:=\P# :K&4G:K:=\P# :K&4WKP;V:=\P# :K&4GKP;V:=\P# :K&FUUF;YP# :K&4WK=;=K=\PL# :K&4GK=;=K=\PL# :K&4WKFW(UF4X# :K&4GKFW(UF4X# :K&4WKFW=K=\PL# :K&4GKFW=K=\PL# :K&;P(8DUX# :K&4LPF;IDD(# :K&4WLUFY# :K&4GLUFY# :K&:?D8:DV;L:# :K&4WKP;V4?P4X# :K&4GKP;V4?P4X# :K&:LD8KF4?=;P# :K&K=LPF:(P;FILPL# :K&KDV:P8?PPLCUP:P;(# :K&W_=U(VFL:4UPP;# :K&G_=U(VFL:4UPP;# :K&4W_=U(VFL:4UPP;#
(PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW( (PW(
("Kinimi@ed ,indo, spacin+ ,idth")# (":K&4GK=;:CF4=;Y")# ("Kinimi@ed ,indo, spacin+ hei+ht")# (":K&4W:K=4D;")# (":mall icon ,idth")# (":K&4G:K=4D;")# (":mall icon hei+ht")# (":K&4G:K4FC(=D;")# (":mall caption hei+ht")# (":K&4W:K:=\P")# (":mall caption !utton ,idth")# (":K&4G:K:=\P")# (":mall caption !utton hei+ht")# (":K&4WKP;V:=\P")# ("Kenu !ar !utton ,idth")# (":K&4GKP;V:=\P")# ("Kenu !ar !utton hei+ht")# (":K&FUUF;YP")# ("?o, minimi@ed ,indo,s arran+ed")# (":K&4WK=;=K=\PL")# ("Kinimi@ed ,indo, ,idth")# (":K&4GK=;=K=\PL")# ("Kinimi@ed ,indo, hei+ht")# (":K&4WKFW(UF4X")# ("Ka"imum dra++a!le ,idth")# (":K&4GKFW(UF4X")# ("Ka"imum dra++a!le hei+ht")# (":K&4WKFW=K=\PL")# ("8idth of ma"imi@ed ,indo,")# (":K&4GKFW=K=\PL")# ("?ei+ht of ma"imi@ed ,indo,")# (":K&;P(8DUX")# (";et,or0 present fla+")# (":K&4LPF;IDD(")# ("?o, s%stem ,as !ooted")# (":K&4WLUFY")# ("Fvoid dra+ " tolerance")# (":K&4GLUFY")# ("Fvoid dra+ % tolerance")# (":K&:?D8:DV;L:")# ("Cresent sounds visuall%")# (":K&4WKP;V4?P4X")# ("Kenu chec09mar0 ,idth")# (":K&4GKP;V4?P4X")# ("Kenu chec09mar0 hei+ht")# (":K&:LD8KF4?=;P")# (":lo, processor fla+")# (":K&K=LPF:(P;FILPL")# ("?e!re, and Fra!ic ena!led fla+")# (":K&KDV:P8?PPLCUP:P;(")# ("Kouse ,heel present fla+")# (":K&W_=U(VFL:4UPP;")# ("_irtual screen " ori+in")# (":K&G_=U(VFL:4UPP;")# ("_irtual screen % ori+in")# (":K&4W_=U(VFL:4UPP;")# ("_irtual screen ,idth")#
(":K&4G_=U(VFL:4UPP;")# ("_irtual screen hei+ht")# (":K&4KD;=(DU:")# (";um!er of monitors")# (":K&:FKPL=:CLFG6DUKF(")# (":ame color format fla+")
; The "rogram that dis"lays this in'ormation is called SNS&3TS=. The SNS&3TS=.C source code 'ile is sho!n . &ost o' the code should loo 'amiliar (y no!. The code in &inMain is virtually identical to that in -3,,%#+N0 and much o' the code in &nd4roc has already (een discussed. 0A0M,.08.$.
,8,M0%,!AC
239999999999999999999999999999999999999999999999999999 :G:KP(:1.4 99 :%stem Ketrics Lispla% Cro+ram ;o. 1 (c) 4harles Cet@old# 1SST 999999999999999999999999999999999999999999999999999932 #include <,indo,s.h> #include "s%smets.h" LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { static (4?FU s@Fpp;ameQR ' (PW( (":%sKets1") ; ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; 8ndclass.st%le 8ndclass.lpfn8ndCroc 8ndclass.c!4lsP"tra 8ndclass.c!8ndP"tra 8ndclass.h=nstance 8ndclass.h=con 8ndclass.h4ursor 8ndclass.h!rIac0+round 8ndclass.lps@Kenu;ame 8ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; h,nd ' 4reate8indo, (s@Fpp;ame# (PW( ("Yet :%stem Ketrics ;o. 1")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ;
:ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X lCaram) { static int ?L4 int CF=;(:(UV4( (4?FU (PW(KP(U=4 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK c"4har# c"4aps# c%4har ; hdc ; i ; ps ; s@Iuffer Q1/R ; tm ;
s,itch (messa+e) { case 8K&4UPF(P7 hdc ' YetL4 (h,nd) ; Yet(e"tKetrics (hdc# ]tm) ; 4"4har ' tm.tmFve4har8idth ; 4"4aps ' (tm.tmCitchFnd6amil% ] 1 < - 7 2) 3 c"4har 2 2 ; 4%4har ' tm.tm?ei+ht * tm.tmP"ternalLeadin+ ; UeleaseL4 (h,nd# hdc) ; Ueturn / ; case 8K&CF=;( 7 hdc ' Ie+inCaint (h,nd# ]ps) ; for (i ' / ; i < ;VKL=;P: ; i**) { (e"tDut (hdc# /# c%4har 3 i# s%smetricsQiR.s@La!el# lstrlen (s%smetricsQiR.s@La!el)) ; (e"tDut (hdc# 22 3 c"4aps# c%4har 3 i# s%smetricsQiR.s@Lesc# lstrlen (s%smetricsQiR.s@Lesc)) ; :et(e"tFli+n (hdc# (F&U=Y?( ^ (F&(DC) ; s@Iuffer# (e"tDut (hdc# 22 3 c"4aps * H/ 3 c"4har# c%4har 3 i#
,sprintf (s@Iuffer# (PW( (").d")# Yet:%stemKetrics (s%smetricsQiR.i=nde"))) ; :et(e"tFli+n (hdc# (F&LP6( ^ (F&(DC) ; PndCaint (h,nd# ]ps) ;
Ueturn / ; case 8K&LP:(UDG 7 CostJuitKessa+e (/) ; Ueturn / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ; /igure >:C sho!s SNS&3TS= running on a standard V25. 5s you can see 'rom the 'irst t!o lines in the "rogram7s client area0 the screen !idth is C>F "i4els and the screen height is >^F "i4els. These t!o values0 as !ell as many o' the other values sho!n (y the "rogram0 may (e di''erent 'or di''erent ty"es o' video dis"lays.
The 'irst .ext>ut statement dis"lays the u""ercase identi'iers in the 'irst o' the three columns. The second argument to .ext>ut is F to (egin the te4t at the le't edge o' the client area. The te4t is o(tained 'rom the sz(abel 'ield o' the s#smetrics structure. + use the #indo!s 'unction lstrlen to calculate the length o' the string0 !hich is re)uired as the last argument to .ext>ut. The second .ext>ut statement dis"lays the descri"tion o' the system metrics value. These descri"tions are stored in the sz'esc 'ield o' the s#smetrics structure. +n this case0 the second argument to .ext>ut is set to 22 3 c"4aps The longest u""ercase identi'ier dis"layed in the 'irst column is ;F characters0 so the second column must (egin at least ;F g cx$aps to the right o' the (eginning o' the 'irst column o' te4t. + use ;; to add a little e4tra s"ace (et!een the columns. The third .ext>ut statement dis"lays the numeric values o(tained 'rom the 2et0#stemMetrics 'unction. The varia(le:!idth 'ont ma es 'ormatting a column o' right:6usti'ied num(ers a little tric y. /ortunately0 in all varia(le: !idth 'onts used today0 the digits 'rom F through B all have the same !idth. %ther!ise0 dis"laying columns o' num(ers !ould (e monstrous. -o!ever0 the !idth o' the digits is greater than the !idth o' a s"ace. Num(ers can (e one or more digits !ide0 so di''erent num(ers can (egin at di''erent horiPontal "ositions. #ouldn7t it (e easier i' !e could dis"lay a column o' right:6usti'ied num(ers (y s"eci'ying the horiPontal "i4el "osition !here the num(er ends rather than (eginsW This is !hat the 0et.ext/lign 'unction lets us do (among other things*. 5'ter SNS&3TS= calls :et(e"tFli+n (hdc# (F&U=Y?( ^ (F&(DC) ; #indo!s !ill inter"ret the coordinates "assed to su(se)uent .ext>ut 'unctions as s"eci'ying the to":right corner o' the te4t string rather than the to":le't corner. The .ext>ut 'unction to dis"lay the column o' num(ers has its second argument set to 22 3 c"4aps * H/ 3 c"4har The >F g cx$har value accommodates the !idth o' the second column and the !idth o' the third column. /ollo!ing the .ext>ut 'unction0 another call to 0et.ext/lign sets things (ac to normal 'or the ne4t time through the loo".
case 8K&:=\P7 c"4lient ' LD8DUL (lCaram) ; c%4lient ' ?=8DUL (lCaram) ; return / ; Nou7ll see code li e this in virtually every #indo!s "rogram. ,%#%8D and -+#%8D are macros that are de'ined in the #indo!s header 'ile #+ND3/.-. +' you7re curious0 the de'initions o' these macros loo li e this: #define LD8DUL(l) ((8DUL)(l)) #define ?=8DUL(l) ((8DUL)(((L8DUL)(l) >> 1M) ] /"6666)) The t!o macros return #%8D valuesSthat is0 =C:(it unsigned short integers that range 'rom F through F4////. Ty"ically you7ll store these values in G;:(it signed integers. That doesn7t involve any conversion "ro(lems and ma es the values easier to use in any calculations you may later need. +n many #indo!s "rograms0 a #&9S+X3 message !ill eventually (e 'ollo!ed (y a #&9$5+NT message. -o! do !e no! thisW 1ecause !hen !e de'ine the !indo! class !e s"eci'y the class style as 4:&?UPLUF8 ^ 4:&_UPLUF8 This class style tells #indo!s to 'orce a re"aint i' either the horiPontal or vertical siPe changes. Nou can calculate the num(er o' 'ull lines o' te4t dis"laya(le !ithin the client area !ith the 'ormula: c%4lient 2 c%4har This can (e F i' the height o' the client area is too small to dis"lay a 'ull character. Similarly0 the a""ro4imate num(er o' lo!ercase characters you can dis"lay horiPontally !ithin the client area is e)ual to c"4lient 2 c"4har +' you determine cx$har and c#$har during the #&9C835T3 message0 don7t !orry a(out dividing (y F in these calculations. Nour !indo! "rocedure receives a #&9C835T3 message !hen &inMain calls $reate&indow. The 'irst #&9S+X3 message comes a little later0 !hen &inMain calls 0how&indow0 at !hich "oint cx$har and c#$har have already (een assigned "ositive nonPero values. Kno!ing the siPe o' the !indo!7s client area is the 'irst ste" in "roviding a !ay 'or the user to move the te4t !ithin the client area i' the client area is not large enough to hold everything. +' you7re 'amiliar !ith other #indo!s:(ased a""lications that have similar re)uirements0 you "ro(a(ly no! !hat !e need: this is a 6o( 'or those !onder'ul inventions no!n as scroll (ars.
Basic Drawing
The su(system o' &icroso't #indo!s res"onsi(le 'or dis"laying gra"hics on video dis"lays and "rinters is no!n as the 2ra"hics Device +nter'ace (2D+*. 5s you might imagine0 2D+ is an e4tremely im"ortant "art o' #indo!s. Not only do the a""lications you !rite 'or #indo!s use 2D+ 'or the dis"lay o' visual in'ormation0 (ut #indo!s itsel' uses 2D+ 'or the visual dis"lay o' user inter'ace items such as menus0 scroll (ars0 icons0 and mouse cursors. .n'ortunately0 a com"rehensive discussion o' 2D+ !ould re)uire an entire (oo 0 and this is not that (oo . +nstead0 in this cha"ter + !ant to "rovide you !ith the (asics o' dra!ing lines and 'illed areas. This is enough 2D+ to get you through the ne4t 'e! cha"ters. +n later cha"ters0 !e7ll loo at 2D+ su""ort o' (itma"s0 meta'iles0 and 'ormatted te4t.
These dynamic:lin li(raries call routines in device drivers 'or the video dis"lay and any "rinters you may have set u". The video driver accesses the hard!are o' the video dis"lay0 and the "rinter driver converts 2D+ commands into codes or commands that the various "rinters understand. %(viously0 di''erent video dis"lay ada"ters and "rinters re)uire di''erent device drivers. 5 !ide variety o' dis"lay devices can (e attached to $C com"ati(les. %ne o' the "rimary goals o' 2D+ is to su""ort device:inde"endent gra"hics. #indo!s "rograms should (e a(le to run !ithout "ro(lems on any gra"hics out"ut device that #indo!s su""orts. 2D+ accom"lishes this goal (y "roviding 'acilities to insulate your "rograms 'rom the "articular characteristics o' di''erent out"ut devices. The !orld o' gra"hics out"ut devices is divided into t!o (road grou"s: raster devices and vector devices. &ost $C out"ut devices are raster devices0 !hich means that they re"resent images as a rectangular "attern o' dots. This category includes video dis"lay ada"ters0 dot:matri4 "rinters0 and laser "rinters. Vector devices0 !hich dra! images using lines0 are generally limited these days to "lotters. &uch o' traditional com"uter gra"hics "rogramming (the ty"e you7ll 'ind in older (oo s* is (ased solely on vectors. This means that a "rogram using a vector gra"hics system is a level o' a(straction a!ay 'rom the hard!are. The out"ut device uses "i4els 'or a gra"hics re"resentation0 (ut the "rogram doesn7t tal to the inter'ace in terms o' "i4els. #hile you can certainly use the #indo!s 2D+ as a high:level vector dra!ing system0 you can also use it 'or relatively lo!:level "i4el mani"ulation. +n this res"ect0 #indo!s 2D+ is to traditional gra"hics inter'ace languages !hat C is to other "rogramming languages. C is !ell no!n 'or its high degree o' "orta(ility among di''erent o"erating systems and environments. Net C is also !ell no!n 'or allo!ing a "rogrammer to "er'orm lo!:level system 'unctions that are o'ten im"ossi(le in other high:level languages. <ust as C is sometimes thought o' as a Ihigh:level assem(ly language0I you can thin o' 2D+ as a high:level inter'ace to the hard!are o' the gra"hics device. 5s you7ve seen0 (y de'ault #indo!s uses a coordinate system (ased on "i4els. &ost traditional gra"hics languages use a IvirtualI coordinate system !ith horiPontal and vertical a4es that range ('or instance* 'rom F to G;0DCD. 5lthough some gra"hics languages don7t let you use "i4el coordinates0 #indo!s 2D+ lets you use either system (as !ell as additional coordinate systems (ased on "hysical measurements*. Nou can use a virtual coordinate system and ee" your "rogram distanced 'rom the hard!are0 or you can use the device coordinate system and snuggle right u" to the hard!are. Some "rogrammers thin that !hen you7re !or ing in terms o' "i4els0 you7ve a(andoned device inde"endence. #e7ve already seen in the last cha"ter that this is not necessarily the case. The tric is to use the "i4els in a device: inde"endent manner. This re)uires that the gra"hics inter'ace language "rovide 'acilities 'or a "rogram to determine the hard!are characteristics o' the device and ma e a""ro"riate ad6ustments. /or e4am"le0 in the SNS&3TS "rograms !e used the "i4el siPe o' a standard system 'ont character to s"ace te4t on the screen. This a""roach allo!ed the "rograms to ad6ust to di''erent dis"lay ada"ters !ith di''erent resolutions0 te4t siPes0 and as"ect ratios. Nou7ll see other methods in this cha"ter 'or determining dis"lay siPes. +n the early days0 many users ran #indo!s !ith a monochrome dis"lay. 3ven in more recent years0 la"to" users !ere restricted to gray shades. /or this reason0 2D+ !as constructed so that you can !rite a "rogram !ithout !orrying much a(out colorSthat is0 #indo!s can convert colors to gray shades. 3ven today0 video dis"lays used !ith #indo!s B^ have di''erent color ca"a(ilities (=C color0 ;?C color0 Ihigh color0I and Itrue colorI*. 5lthough in :6et "rinters have (rought lo!:cost hard:co"y color to the masses0 many users still "re'er their (lac :only laser "rinters 'or high:)uality out"ut. +t is "ossi(le to use these devices (lindly0 (ut your "rogram can also determine ho! many colors are availa(le on the "articular dis"lay device and ta e (est advantage o' the hard!are. %' course0 6ust as you can !rite C "rograms that have su(tle "orta(ility "ro(lems !hen they run on other com"uters0 you can also inadvertently let device de"endencies cree" into your #indo!s "rograms. That7s "art o' the "rice o' not (eing 'ully insulated 'rom the hard!are. Nou should also (e a!are o' the limitations o' #indo!s 2D+. 5lthough you can certainly move gra"hics o(6ects around the dis"lay0 2D+ is generally a static dis"lay system !ith only limited animation su""ort. +' you need to !rite so"histicated animations 'or games0 you should e4"lore &icroso't DirectA0 !hich "rovides the su""ort you7ll need.
message0 and 2et'$ and "elease'$ 'unctions let you do this during other messages. #e7ll e4amine some other 'unctions regarding device conte4ts shortly. !unctions that obtain information about the device context +n the SNS&3TS "rograms earlier0 !e used the 2et.extMetrics 'unction to o(tain in'ormation a(out the dimensions o' the 'ont currently selected in the device conte4t. ,ater in this document0 !e7ll loo at the D3VC5$S= "rogram0 !hich o(tains other0 more general0 device conte4t in'ormation. !unctions that draw something %(viously0 once all the "reliminaries are out o' the !ay0 this is the really im"ortant stu''. +n the last cha"ter0 !e used the .ext>ut 'unction to dis"lay some te4t in the client area o' the !indo!. 5s !e7ll see0 other 2D+ 'unctions let us dra! lines and 'illed areas. !unctions that set and get attributes of the device context 5n Iattri(uteI o' the device conte4t determines various details regarding ho! the dra!ing 'unctions !or . /or e4am"le0 you can use 0et.ext$olor to s"eci'y the color o' any te4t you dra! using .ext>ut or other te4t out"ut 'unctions. +n the SNS&3TS "rograms in earlier0 !e used 0et.ext/lign to tell 2D+ that the starting "osition o' the te4t string in the .ext>ut 'unction should (e the right side o' the string rather than the le't0 !hich is the de'ault. 5ll attri(utes o' the device conte4t have de'ault values that are set !hen the device conte4t is o(tained. /or all 0et 'unctions0 there are 2et 'unctions that let you o(tain the current device conte4t attri(utes. !unctions that wor% with 2'* EobjectsE -ere7s !here 2D+ gets a (it messy. /irst an e4am"le: 1y de'ault0 any lines you dra! using 2D+ are solid and o' a standard !idth. Nou may !ish to dra! thic er lines or use lines com"osed o' a series o' dots or dashes. The line !idth and this line style are not attri(utes o' the device conte4t. +nstead0 they are characteristics o' a Ilogical "en.I Nou can thin o' a "en as a collection o' (undled attri(utes. Nou create a logical "en (y s"eci'ying these characteristics in the $reate4en0 $reate4en*ndirect0 or ,xt$reate4en 'unction. 5lthough these 'unctions are considered to (e "art o' 2D+0 unli e most 2D+ 'unctions they do not re)uire a handle to a device conte4t. The 'unctions return a handle to a logical "en. To use this "en0 you IselectI the "en handle into the device conte4t. The current "en selected in the device conte4t is considered an attri(ute o' the device conte4t. /rom then on0 !hatever lines you dra! use this "en. ,ater on0 you deselect the "en o(6ect 'rom the device conte4t and destroy the o(6ect. Destroying the "en is necessary (ecause the "en de'inition occu"ies allocated memory s"ace. 1esides "ens0 you also use 2D+ o(6ects 'or creating (rushes that 'ill enclosed areas0 'or 'onts0 'or (itma"s0 and 'or other as"ects o' 2D+.
o(6ects and 'or o(taining 'ont in'ormation are among the largest in #indo!s. 1eginning !ith #indo!s G.=0 2D+ (egan su""orting TrueTy"e 'onts0 !hich are (ased on 'illed outlines that can (e mani"ulated !ith other 2D+ 'unctions. #indo!s B^ continues to su""ort the older (itma":(ased 'onts 'or com"ati(ility and small memory re)uirements.
Other ,t$ff
%ther as"ects o' 2D+ are not so easily classi'ia(le. These are: Mapping modes and transforms 5lthough (y de'ault you dra! in units o' "i4els0 you are not limited to doing that. The 2D+ ma""ing modes allo! you to dra! in units o' inches (or rather0 'ractions o' inches*0 millimeters0 or anything you !ant. +n addition0 #indo!s NT su""orts a traditional I!orld trans'ormI e4"ressed as a G:(y:G matri4. This allo!s 'or s e!ing and rotation o' gra"hics o(6ects. The !orld trans'orm is not su""orted under #indo!s B^. Metafiles 5 meta'ile is a collection o' 2D+ commands stored in a (inary 'orm. &eta'iles are used "rimarily to trans'er re"resentations o' vector gra"hic dra!ings through the cli"(oard. "egions 5 region is a com"le4 area o' any sha"e and is generally de'ined as a 1oolean com(ination o' sim"ler regions. &ore com"le4 regions can (e stored internally in 2D+ as a series o' scan lines derived 'rom the original de'inition o' the region. Nou can use regions 'or outlining0 'illing0 and cli""ing. 4aths 5 "ath is a collection o' straight lines and curves stored internally in 2D+. $aths can (e used 'or dra!ing0 'illing0 and cli""ing. $aths can also (e converted to regions. $lipping Dra!ing can (e restricted to a "articular section o' the client area. This is no!n as cli""ing. The cli""ing area can (e rectangular or nonrectangular0 generally s"eci'ied as a region or a "ath. 4alettes The use o' a customiPed "alette is generally restricted to dis"lays that sho! ;?C colors. #indo!s reserves only ;F o' these colors 'or use (y the system. Nou can alter the other ;GC colors to accurately dis"lay the colors o' real:!orld images stored in (itma"s. 4rinting 5lthough this cha"ter is restricted to the video dis"lay0 almost everything you learn here can (e a""lied to "rinting.
#indo!s "rovides several methods 'or o(taining a device conte4t handle. +' you o(tain a video dis"lay device conte4t handle !hile "rocessing a message0 you should release it (e'ore e4iting the !indo! "rocedure. 5'ter you release the handle0 it is no longer valid. /or a "rinter device conte4t handle0 the rules are not as strict. The most common method 'or o(taining a device conte4t handle and then releasing it involves using the )egin4aint and ,nd4aint calls !hen "rocessing the #&9$5+NT message: hdc ' Ie+inCaint (h,nd# ]ps) ; [other pro"ram lines] PndCaint (h,nd# ]ps) ; The varia(le ps is a structure o' ty"e $5+NTST8.CT. The hdc 'ield o' this structure is the same handle to the device conte4t that )egin4aint returns. The $5+NST8.CT structure also contains a 83CT (rectangle* structure named rc4aint that de'ines a rectangle encom"assing the invalid region o' the !indo!7s client area. #ith the device conte4t handle o(tained 'rom )egin4aint you can dra! only !ithin this region. The )egin4aint call also validates this region. #indo!s "rograms can also o(tain a handle to a device conte4t !hile "rocessing messages other than #&9$5+NT: hdc ' YetL4 (h,nd) ; [other pro"ram lines] UeleaseL4 (h,nd# hdc) ; This device conte4t a""lies to the client area o' the !indo! !hose handle is hwnd. The "rimary di''erence (et!een the use o' these calls and the use o' the )egin4aint and ,nd4aint com(ination is that you can dra! on your entire client area !ith the handle returned 'rom 2et'$. -o!ever0 2et'$ and "elease'$ don7t validate any "ossi(ly invalid regions o' the client area. 5 #indo!s "rogram can also o(tain a handle to a device conte4t that a""lies to the entire !indo! and not only to the !indo!7s client area: hdc ' Yet8indo,L4 (h,nd) ; [other pro"ram lines] UeleaseL4 (h,nd# hdc) ; This device conte4t includes the !indo! title (ar0 menu0 scroll (ars0 and 'rame in addition to the client area. 5""lications "rograms rarely use the 2et&indow'$ 'unction. +' you !ant to e4"eriment !ith it0 you should also tra" the #&9NC$5+NT (Inonclient "aintI* message0 !hich is the message #indo!s uses to dra! on the nonclient areas o' the !indo!. The )egin4aint0 2et'$0 and 2et&indow'$ calls o(tain a device conte4t associated !ith a "articular !indo! on the video dis"lay. 5 much more general 'unction 'or o(taining a handle to a device conte4t is $reate'$: hdc ' 4reateL4 (ps@Lriver# ps@Levice# ps@Dutput# pLata) ; [other pro"ram lines] LeleteL4 (hdc) ; /or e4am"le0 you can o(tain a device conte4t handle 'or the entire dis"lay (y calling hdc ' 4reateL4 ((PW( ("L=:CLFG")# ;VLL# ;VLL# ;VLL) ; #riting outside your !indo! is generally im"olite0 (ut it7s convenient 'or some unusual a""lications. (5lthough this 'act is not documented0 you can also retrieve a device conte4t 'or the entire screen (y calling 2et'$ !ith a N.,, argument.* Sometimes you need only to o(tain some in'ormation a(out a device conte4t and not do any dra!ing. +n these cases0 you can o(tain a handle to an Iin'ormation conte4tI (y using $reate*$. The arguments are the same as 'or the $reate'$ 'unction. /or e4am"le0 hdc ' 4reate=4 ((PW( ("L=:CLFG")# ;VLL# ;VLL# ;VLL); Nou can7t !rite to the device (y using this in'ormation conte4t handle.
The i*ndex argument is one o' ;B identi'iers de'ined in the #+N2D+.- header 'ile. /or e4am"le0 the i*ndex value o' -%8X83S causes 2et'evice$aps to return the !idth o' the device in "i4elsL a V38T83S argument returns the height o' the device in "i4els. +' hdc is a handle to a screen device conte4t0 that7s the same in'ormation you can get 'rom 2et0#stemMetrics. +' hdc is a handle to a "rinter device conte4t0 2et'evice$aps returns the height and !idth o' the "rinter dis"lay area in "i4els. Nou can also use 2et'evice$aps to determine the device7s ca"a(ilities o' "rocessing various ty"es o' gra"hics. This is usually not im"ortant 'or dealing !ith the video dis"lay0 (ut it (ecomes more im"ortant !ith !or ing !ith "rinters. /or e4am"le0 most "en "lotters can7t dra! (itma""ed images and 2et'evice$aps can tell you that.
D0?C>P,!AC
23999999999999999999999999999999999999999999999999999999999 LP_4FC:1.4 99 Levice 4apa!ilities Lispla% Cro+ram ;o. 1 (c) 4harles Cet@old# 1SST 99999999999999999999999999999999999999999999999999999999932 #include <,indo,s.h> #define ;VKL=;P: ((int) (si@eof devcaps 2 si@eof devcaps Q/R)) struct { int i=nde" ; (4?FU 3 s@La!el ; (4?FU 3 s@Lesc ; devcaps QR ' { ?DU\:=\P# millimeters7")# _PU(:=\P# millimeters7")# ?DU\UP:# _PU(UP:# lines7")# I=(:C=WPL# pi"el7")# CLF;P:# planes7")# ;VKIUV:?P:# !rushes7")# ;VKCP;:# pens7")# ;VKKFUXPU:# mar0ers7")# ;VK6D;(:# fonts7")#
(PW( ("?DU\:=\P")# (PW( ("_PU(:=\P")# (PW( ("?DU\UP:")# (PW( ("_PU(UP:")# (PW( ("I=(:C=WPL")# (PW( ("CLF;P:")# (PW( (";VKIUV:?P:")# (PW( (";VKCP;:")# (PW( (";VKKFUXPU:")# (PW( (";VK6D;(:")#
(PW( ("8idth in (PW( ("?ei+ht in (PW( ("8idth in pi"els7")# (PW( ("?ei+ht in raster (PW( ("4olor !its per (PW( (";um!er of color (PW( (";um!er of device (PW( (";um!er of device (PW( (";um!er of device (PW( (";um!er of device
;VK4DLDU:# colors7")# CLP_=4P:=\P# structure7")# F:CP4(W# pi"el7")# F:CP4(G# pi"el7")# F:CP4(WG# pi"el7")# LDYC=WPL:W# inch7")# LDYC=WPL:G# inch7")# :=\PCFLP((P# entries7")# ;VKUP:PU_PL# entries7")# 4DLDUUP:# resolution7") ;
(PW( (";VK4DLDU:")# (PW( ("CLP_=4P:=\P")# (PW( ("F:CP4(W")# (PW( ("F:CP4(G")# (PW( ("F:CP4(WG")# (PW( ("LDYC=WPL:W")# (PW( ("LDYC=WPL:G")# (PW( (":=\PCFLP((P")# (PW( (";VKUP:PU_PL")# (PW( ("4DLDUUP:")#
(PW( (";um!er of device (PW( (":i@e of device (PW( ("Uelative ,idth of (PW( ("Uelative hei+ht of (PW( ("Uelative dia+onal of (PW( ("?ori@ontal dots per (PW( ("_ertical dots per (PW( (";um!er of palette (PW( ("Ueserved palette (PW( ("Fctual color
LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { static (4?FU s@Fpp;ameQR ' (PW( ("Lev4aps1") ; ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; ,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; h,nd ' 4reate8indo, (s@Fpp;ame# (PW( ("Levice 4apa!ilities")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; :ho,8indo, (h,nd# i4md:ho,) ;
Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X lCaram) { static int (4?FU ?L4 int CF=;(:(UV4( (PW(KP(U=4 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK c"4har# c"4aps# c%4har ; s@IufferQ1/R ; hdc ; i ; ps ; tm ;
s,itch (messa+e) { case 8K&4UPF(P7 hdc ' YetL4 (h,nd) ; Yet(e"tKetrics (hdc# ]tm) ; c"4har ' tm.tmFve4har8idth ; c"4aps ' (tm.tmCitchFnd6amil% ] 1 < - 7 2) 3 c"4har 2 2 ; c%4har ' tm.tm?ei+ht * tm.tmP"ternalLeadin+ ; UeleaseL4 (h,nd# hdc) ; return / ; case 8K&CF=;(7 hdc ' Ie+inCaint (h,nd# ]ps) ; for (i ' / ; i < ;VKL=;P: ; i**) { (e"tDut (hdc# /# c%4har 3 i# devcapsQiR.s@La!el# lstrlen (devcapsQiR.s@La!el)) ; (e"tDut (hdc# 1H 3 c"4aps# c%4har 3 i# devcapsQiR.s@Lesc# lstrlen (devcapsQiR.s@Lesc)) ; :et(e"tFli+n (hdc# (F&U=Y?( ^ (F&(DC) ; (e"tDut (hdc# 1H 3 c"4aps * -. 3 c"4har# c%4har 3 i# s@Iuffer# ,sprintf (s@Iuffer# (PW( (").d")# YetLevice4aps (hdc# devcapsQiR.i=nde"))) ; :et(e"tFli+n (hdc# (F&LP6( ^ (F&(DC) ; PndCaint (h,nd# ]ps) ; return / ;
case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ; 5s you can see0 this "rogram is )uite similar to the SNS&3TS= "rogram sho!n earlier. To ee" the code short0 + didn7t include scroll (ars (ecause + ne! the in'ormation !ould 'it on one screen. The results 'or a ;?C:color0 C>F: (y:>^F V25 are sho!n here.
-o!ever0 your #indo!s a""lications should not assume that the video dis"lay has a >:G as"ect ratio. $eo"le !ho do mostly !ord "rocessing sometimes "re'er a video dis"lay that resem(les the height and !idth o' a sheet o' "a"er. The most common alternative to a >:G dis"lay is a G:> dis"laySessentially a standard dis"lay turned on its side. +' the horiPontal resolution o' a device e)uals the vertical resolution0 the device is said to have Is)uare "i4els.I No!adays all video dis"lays in common use !ith #indo!s have s)uare "i4els0 (ut this !as not al!ays the case. (Nor should your a""lications assume that the video dis"lay al!ays has s)uare "i4els.* #hen #indo!s !as 'irst introduced0 the standard video ada"ter (oards !ere the +1& Color 2ra"hics 5da"ter (C25*0 !hich had a "i4el dimension area o' C>F (y ;FF "i4elsL the 3nhanced 2ra"hics 5da"ter (325*0 !hich had a "i4el dimension o' C>F (y G?F "i4elsL and the -ercules 2ra"hics Card0 !hich had a "i4el dimension o' D;F (y G>^ "i4els. 5ll these video (oards used a dis"lay that had a >:G as"ect ratio0 (ut the num(er o' "i4els horiPontally and vertically !as not in the ratio >:G. +t7s )uite easy 'or a user running #indo!s to determine the "i4el dimensions o' a video dis"lay. 8un the Dis"lay a""let in Control $anel0 and select the Settings ta(. +n the area la(eled Screen 5rea0 you7ll "ro(a(ly see one o' these "i4el dimensions: C>F (y >^F "i4els ^FF (y CFF "i4els =F;> (y DC^ "i4els =;^F (y =F;> "i4els =CFF (y =;FF "i4els 5ll o' these are in the ratio >:G. (#ell0 all e4ce"t the =;^F (y =F;> "i4el siPe. This should "ro(a(ly (e considered an annoying anomaly rather than anything more signi'icant. 5s !e7ll see0 all these "i4el dimensions !hen com(ined !ith a >:G monitor are considered to yield s)uare "i4els.* 5 #indo!s a""lication can o(tain the "i4el dimensions o' the dis"lay 'rom 2et0#stemMetrics !ith the S&9CASC833N and S&9CNSC833N arguments. 5s you7ll note 'rom the D3VC5$S= "rogram0 a "rogram can o(tain the same values 'rom 2et'evice$aps !ith the -%8X83S (IhoriPontal resolutionI* and V38T83S arguments. This is a use o' the !ord IresolutionI that means the "i4el siPe rather than the "i4els "er metrical unit. That7s the sim"le "art o' the device siPe. No! the con'usion (egins. The 'irst t!o device ca"a(ilities0 -%8XS+X3 and V38TS+X30 are documented as I#idth0 in millimeters0 o' the "hysical screenI and I-eight0 in millimeters0 o' the "hysical screenI (in 34latform 0'532raphics and Multimedia 0ervices32'*3'evice $ontexts3'evice $ontext "eference3'evice $ontext !unctions32et'evice$aps *. These seem li e straight'or!ard de'initions until one (egins to thin through their im"lications. /or e4am"le0 given the nature o' the inter'ace (et!een video dis"lay ada"ters and monitors0 ho! can #indo!s really no! the monitor siPeW 5nd !hat i' you have a la"to" (in !hich the video driver conceiva(ly could no! the e4act "hysical dimensions o' the screen* and you attach an e4ternal monitor to itW 5nd !hat i' you attach a video "ro6ector to your $CW +n the =C:(it versions o' #indo!s (and in #indo!s NT*0 #indo!s uses a IstandardI dis"lay siPe 'or the -%8XS+X3 and V38TS+X3 values. 1eginning !ith #indo!s B?0 ho!ever0 the -%8XS+X3 and V38TS+X3 values are derived 'rom the -%8X83S0 V38T83S0 ,%2$+A3,SA0 and ,%2$+A3,SN values. -ere7s ho! it !or s. #hen you use the Dis"lay a""let o' the Control $anel to select a "i4el siPe o' the dis"lay0 you can also select a siPe o' your system 'ont. The reason 'or this o"tion is that the 'ont used 'or the C>F (y >^F dis"lay may (e too small to read !hen you go u" to =F;> (y DC^ or (eyond. +nstead0 you7ll !ant a larger system 'ont. These system 'ont siPes are re'erred to on the Settings ta( o' the Dis"lay a""let as Small /onts and ,arge /onts. +n traditional ty"ogra"hy0 the siPe o' the characters in a 'ont is indicated (y a I"oint siPe.I 5 "oint is a""ro4imately =/D; inch and in com"uter ty"ogra"hy is o'ten assumed to (e e4actly =/D; inch. +n theory0 the "oint siPe o' a 'ont is the distance 'rom the to" o' the tallest character in the 'ont to the (ottom o' descenders in characters such as 60 "0 )0 and y0 e4cluding accent mar s. /or e4am"le0 in a =F:"oint 'ont this distance !ould (e =F/D; inch. +n terms o' the T3AT&3T8+C structure0 the "oint siPe o' the 'ont is e)uivalent to the tm-eight 'ield minus the tm*nternal(eading 'ield0 as sho!n in /igure (elo!.
.he small font and the .,C.M,."*$ fields. +n real:li'e ty"ogra"hy0 the "oint siPe o' a 'ont is not so "recisely related to the actual siPe o' the 'ont characters. The designer o' the 'ont might ma e the actual characters a (it larger or smaller than the "oint siPe !ould indicate. 5'ter all0 'ont design is an art rather than a science. The tm-eight 'ield o' the T3AT&3T8+C structure indicates ho! successive lines o' te4t should (e s"aced on the screen or "rinter. This can also (e measured in "oints. /or e4am"le0 a =;:"oint line s"acing indicates the (aselines o' successive lines o' te4t should (e =;/D; (or =/C* inch a"art. Nou don7t !ant to use =F:"oint line s"acing 'or a =F: "oint 'ont (ecause the successive lines o' te4t could actually touch each other. This (oo is "rinted !ith a =F:"oint 'ont and =G:"oint line s"acing. 5 =F:"oint 'ont is considered com'orta(le 'or reading. 5nything much smaller than =F "oints !ould (e di''icult to read 'or long "eriods o' time. The #indo!s system 'ontSregardless o' !hether it is the Ismall 'ontI or the Ilarge 'ontI and regardless o' !hat video "i4el dimension you7ve selectedSis assumed to (e a =F:"oint 'ont !ith a =;:"oint line s"acing. + no! this sounds odd. #hy call the system 'onts Ismall 'ontI and Ilarge 'ontI i' they7re (oth =F:"oint 'ontsW -ere7s the ey: &hen #ou select the small font or the large font in the 'ispla# applet of the $ontrol 4anel #ou are actuall# selecting an assumed video displa# resolution in dots per inch. #hen you select the small 'ont0 you are saying that you !ant #indo!s to assume that the video dis"lay resolution is BC dots "er inch. #hen you select the large 'ont0 you !ant #indo!s to assume that the video dis"lay resolution is =;F dots "er inch. ,oo at /igure ?:G again. That7s the small 'ont0 !hich is (ased on a dis"lay resolution o' BC dots "er inch. + said it7s a =F:"oint 'ont. Ten "oints is =F/D; inch0 !hich i' you multi"ly (y BC dots "er inch yields a result o' (a""ro4imately* =G "i4els. That7s tm-eight minus tm*nternal(eading. The line s"acing is =; "oints0 or =;/D; inch0 !hich multi"lied (y BC dots "er inch yields =C "i4els. That7s tm-eight. /igure sho!s the large 'ont. This is (ased on a resolution o' =;F dots "er inch. 5gain0 it7s a =F:"oint 'ont0 and =F/D; times =;F dots "er inch e)uals =C "i4els (i' you round do!n*0 !hich is tm-eight minus tm*nternal(eading. The =;: "oint line s"acing is e)uivalent to ;F "i4els0 !hich is tm-eight.
.he large font and the !>+.M,."*$ fields. #ithin a #indo!s "rogram you can use the 2et'evice$aps 'unction to o(tain the assumed resolution in dots "er inch that the user selected in the Dis"lay a""let o' the Control $anel. To get these valuesS!hich in theory could (e di''erent i' the video dis"lay doesn7t have s)uare "i4elsSyou use the indices ,%2$+A3,SA and ,%2$+A3,SN. The name ,%2$+A3,S stands 'or Ilogical "i4els0I !hich (asically means Inot the actual resolution in "i4els "er inch.I The device ca"a(ilities that you o(tain 'rom 2et'evice$aps !ith the -%8XS+X3 and V38TS+X3 indices are documented (as + indicated earlier* as I#idth0 in millimeters0 o' the "hysical screenI and I-eight0 in millimeters0 o' the "hysical screen.I These should (e documented as a Ilogical !idthI and a Ilogical height0I (ecause the values are derived 'rom the -%8X83S0 V38T83S0 ,%2$+A3,SA0 and ,%2$+A3,SN values. The 'ormulas are -orizontal 0ize 6mm) K F=.H L -orizontal "esolution 6pixels)3 (ogical 4ixels C 6dots per inch) @ertical 0ize 6mm) K F=.H L @ertical "esolution 6pixels)3 (ogical 4ixels A 6dots per inch) The ;?.> constant is necessary to convert 'rom inches to millimeters. This may seem (ac !ard and illogical. 5'ter all0 your video dis"lay has a siPe in millimeters that you can actually measure !ith a ruler (at least a""ro4imately*. 1ut #indo!s B^ doesn7t care a(out that siPe. +nstead it calculates a dis"lay siPe in millimeters (ased on the "i4el siPe o' the dis"lay the user selects and also the resolution the user selects 'or siPing the system 'ont. Change the "i4el siPe o' your dis"lay and according to 2et'evice$aps the metrical siPe changes. -o! much sense does that ma eW +t ma es more sense than you might sus"ect. ,et7s su""ose you have a =D:inch monitor. The actual dis"lay siPe !ill "ro(a(ly (e a(out =; inches (y B inches. Su""ose you !ere running #indo!s !ith the minimum re)uired "i4el dimensions o' C>F (y >^F. This means that the actual resolution is ?G dots "er inch. 5 =F:"oint 'ontS"er'ectly reada(le on "a"erSon the screen !ould (e only D "i4els in height 'rom the to" o' the 5 to the (ottom o' the ). Such a 'ont !ould (e ugly and 6ust a(out unreada(le. (5s "eo"le !ho ran #indo!s on the old Color 2ra"hics 5da"ter.* No! hoo u" a video "ro6ector to your $C. ,et7s say the "ro6ected video dis"lay is a > 'eet !ide and G 'eet high. That same C>F (y >^F "i4el dimension no! im"lies a resolution o' a(out =G dots "er inch. +t !ould (e ridiculous to try dis"laying a =F:"oint 'ont under such conditions. 5 =F:"oint 'ont should (e reada(le on the video dis"lay (ecause it is surely reada(le !hen "rinted. The =F:"oint 'ont thus (ecomes an im"ortant 'rame o' re'erence. #hen a #indo!s a""lication is guaranteed that a =F:"oint screen 'ont is o' average siPe0 it can then dis"lay smaller ((ut still reada(le* te4t using an ^:"oint 'ont and larger te4t using 'onts o' "oint siPes greater than =F. Thus0 it ma es sense that the video resolution (in dots "er inch* (e im"lied (y the "i4el siPe o' that =F:"oint 'ont. +n #indo!s NT0 ho!ever0 an older a""roach is used in de'ining the -%8XS+X3 and V38TS+X3 values. This a""roach is consistent !ith =C:(it versions o' #indo!s. The -%8X83S and V38T83S values still indicate the num(er o' "i4els horiPontally and vertically (o' course*0 and ,%2$+A3,SA and ,%2$+A3,SN are still related to the 'ont that you choose !hen setting the video resolution in the Dis"lay a""let o' the Control $anel. 5s !ith #indo!s B^0 ty"ical values o' ,%2$+A3,SA and ,%2$+A3,SN are BC and =;F dots "er inch0 de"ending on !hether you select a small 'ont or large 'ont.
The di''erence in #indo!s NT is that the -%8XS+X3 and V38TS+X3 values are 'i4ed to indicate a standard monitor siPe. /or common ada"ters0 the values o' -%8XS+X3 and V38TS+X3 you7ll o(tain are G;F and ;>F millimeters0 res"ectively. These values are the same regardless o' !hat "i4el dimension you choose. There'ore0 these values are inconsistent !ith the values you o(tain 'rom 2et'evice$aps !ith the -%8X83S0 V38T83S0 ,%2$+A3,SA0 and ,%2$+A3,SN indices. -o!ever0 you can al!ays calculate -%8XS+X3 and V38TS+X3 values li e those you7d o(tain under #indo!s B^ (y using the 'ormulas sho!n earlier. #hat i' your "rogram needs the actual "hysical dimensions o' the video dis"layW $ro(a(ly the (est solution is to actually re)uest them o' the user !ith a dialog (o4. /inally0 three other values 'rom 2et'evice$aps are related to the video dimensions. The 5S$3CTA0 5S$3CTN0 and 5S$3CTAN values are the relative !idth0 height0 and diagonal siPe o' each "i4el0 rounded to the nearest integer. /or s)uare "i4els0 the 5S$3CTA and 5S$3CTN values !ill (e the same. 8egardless0 the 5S$3CTAN value e)uals the s)uare root o' the sum o' the s)uares o' the 5S$3CTA and 5S$3CTN values0 as you7ll recall 'rom $ythagoras.
Notice that the most:signi'icant ^ (its are Pero0 and that each "rimary is s"eci'ied as an ^:(it value. +n theory0 a C%,%883/ value can re'er to ;;> or a(out =C million colors. The #indo!s header 'ile #+N2D+.- "rovides several macros 'or !or ing !ith 821 color values. The "2) macro ta es three arguments re"resenting red0 green0 and (lue values and com(ines them into an unsigned long: #define UYI(r#+#!) ((4DLDUUP6)(((IG(P)(r) ^ \ ((8DUL)((IG(P)(+)) << T)) ^ \ (((L8DUL)(IG(P)(!)) << 1M))) Notice that the order o' the three arguments is red0 green0 and (lue. Thus0 the value 821 (;??0 ;??0 F* is F4FFFF//// or yello!Sthe com(ination o' red and green. #hen all three arguments are set to F0 the color is (lac L !hen all the arguments are set to ;??0 the color is !hite. The 2et"@alue0 2et2@alue0 and 2et)@alue macros e4tract the "rimary color values 'rom a C%,%883/ value. These macros are sometimes handy !hen you7re using a #indo!s 'unction that returns 821 color values to your "rogram. %n =C:color or ;?C:color video ada"ters0 #indo!s can use IditheringI to simulate more colors than the device can dis"lay. Dithering involves a small "attern that com(ines "i4els o' di''erent colors. Nou can determine the closest "ure nondithered color o' a "articular color value (y calling 2et+earest$olor: crCure4olor ' Yet;earest4olor (hdc# cr4olor) ;
Stretching &ode $olygon /ill &ode +ntercharacter S"acing 1rush %rigin Cli""ing 8egion
0et0tretch)ltMode 0et4ol#!illMode 0et.ext$haracter,xtra 0et)rush>rg,x 0elect>bject 0elect$lip"gn *ntersect$lip"gn >ffset$lip"gn ,xclude$lip"ect 0elect$lip4ath
:aveL4 (hdc) ; Nou can then change some attri(utes and call 0ave'$ again. To restore the device conte4t to a saved state0 call UestoreL4 (hdc# 91) ; This restores the device conte4t to the state saved (y the most recent 0ave'$ 'unction.
,etting Pi=els
3ven though the #indo!s 2$+ includes 0et4ixel and 2et4ixel 'unctions0 they are not commonly used. The 0et4ixel 'unction sets the "i4el at a s"eci'ied 4: and y:coordinate to a "articular color: :etCi"el (hdc# "# %# cr4olor) ; 5s in any dra!ing 'unction0 the 'irst argument is a handle to a device conte4t. The second and third arguments indicate the coordinate "osition. &ostly you7ll o(tain a device conte4t 'or the client area o' your !indo!0 and x and # !ill (e relative to the u""er le't corner o' that client area. The 'inal argument is o' ty"e C%,%883/ to s"eci'y the color. +' the color you s"eci'y in the 'unction cannot (e realiPed on the video dis"lay0 the 'unction sets the "i4el to the nearest "ure nondithered color and returns that value 'rom the 'unction. The 2et4ixel 'unction returns the color o' the "i4el at the s"eci'ied coordinate "osition: cr4olor ' YetCi"el (hdc# "# %) ;
,traight &ines
#indo!s can dra! straight lines0 elli"tical lines (curved lines on the circum'erence o' an elli"se*0 and 1ePier s"lines. #indo!s B^ su""orts seven 'unctions that dra! lines: (ine.o Dra!s a straight line. 4ol#line and 4ol#line.o Dra! a series o' connected straight lines. 4ol#4ol#line Dra!s multi"le "olylines. /rc Dra!s elli"tical lines. 4ol#)ezier and 4ol#)ezier.o Dra! 1ePier s"lines. +n addition0 #indo!s NT su""orts three more line:dra!ing 'unctions: /rc.o and /ngle/rc Dra! elli"tical lines. 4ol#'raw Dra!s a series o' connected straight lines and 1ePier s"lines. These three 'unctions are not su""orted under #indo!s B^. ,ater in this cha"ter +7ll also (e discussing some 'unctions that dra! lines (ut that also 'ill the enclosed area !ithin the 'igure they dra!. These 'unctions are "ectangle Dra!s a rectangle. ,llipse Dra!s an elli"se. "ound"ect Dra!s a rectangle !ith rounded corners. 4ie Dra!s a "art o' an elli"se that loo s li e a "ie slice.
$hord Dra!s "art o' an elli"se 'ormed (y a chord. /ive attri(utes o' the device conte4t a''ect the a""earance o' lines that you dra! using these 'unctions: current "en "osition ('or (ine.o0 4ol#line.o0 4ol#)ezier.o0 and /rc.o only*0 "en0 (ac ground mode0 (ac ground color0 and dra!ing mode. To dra! a straight line0 you must call t!o 'unctions. The 'irst 'unction s"eci'ies the "oint at !hich the line (egins0 and the second 'unction s"eci'ies the end "oint o' the line: Kove(oP" (hdc# "Ie+# %Ie+# ;VLL) ; Line(o (hdc# "Pnd# %Pnd) ; Move.o,x doesn7t actually dra! anythingL instead0 it sets the attri(ute o' the device conte4t no!n as the Icurrent "osition.I The (ine.o 'unction then dra!s a straight line 'rom the current "osition to the "oint s"eci'ied in the (ine.o 'unction. The current "osition is sim"ly a starting "oint 'or several other 2D+ 'unctions. +n the de'ault device conte4t0 the current "osition is initially set to the "oint (F0 F*. +' you call (ine.o !ithout 'irst setting the current "osition0 it dra!s a line starting at the u""er le't corner o' the client area. 5 (rie' historical note: +n the =C:(it versions o' #indo!s0 the 'unction to set the current "osition !as Move.o. This 'unction had 6ust three argumentsSthe device conte4t handle and 4: and y:coordinates. The 'unction returned the "revious current "osition "ac ed as t!o =C:(it values in a G;:(it unsigned long. -o!ever0 in the G;:(it versions o' #indo!s0 coordinates are G;:(it values. 1ecause the G;:(it versions o' C do not de'ine a C>:(it integral data ty"e0 this change meant that Move.o could no longer indicate the "revious current "osition in its return value. 5lthough the return value 'rom Move.o !as almost never used in real:li'e "rogramming0 a ne! 'unction !as re)uired0 and this !as Move.o,x. The last argument to Move.o,x is a "ointer to a $%+NT structure. %n return 'rom the 'unction0 the x and # 'ields o' the $%+NT structure !ill indicate the "revious current "osition. +' you don7t need this in'ormation (!hich is almost al!ays the case*0 you can sim"ly set the last argument to N.,, as in the e4am"le sho!n a(ove. 5nd no! the caveat: 5lthough coordinate values in #indo!s B^ a""ear to (e G;:(it values0 only the lo!er =C (its are used. Coordinate values are e''ectively restricted to :G;0DC^ to G;0DCD. +n #indo!s NT0 the 'ull G;:(it values are used. +' you ever need the current "osition0 you can o(tain it (y calling Yet4urrentCositionP" (hdc# ]pt) ; !here pt is a $%+NT structure. The 'ollo!ing code dra!s a grid in the client area o' a !indo!0 s"acing the lines =FF "i4els a"art starting 'rom the u""er le't corner. The varia(le hwnd is assumed to (e a handle to the !indo!0 hdc is a handle to the device conte4t0 and x and # are integers: Yet4lientUect (h,nd# ]rect) ; for (" ' / ; " < rect.ri+ht ; "*' 1//) { Kove(oP" (hdc# "# /# ;VLL) ; Line(o (hdc# "# rect.!ottom) ; for (% ' / ; % < rect.!ottom ; % *' 1//) { Kove(oP" (hdc# /# %# ;VLL) ; Line(o (hdc# rect.ri+ht# %) ; 5lthough it seems li e a nuisance to (e 'orced to use t!o 'unctions to dra! a single line0 the current "osition comes in handy !hen you !ant to dra! a series o' connected lines. /or instance0 you might !ant to de'ine an array o' ? "oints (=F values* that de'ine the outline o' a rectangle: CD=;( aptQ.R ' { 1//# 1//# 2//# 1//# 2//# 2//# 1//# 2//# 1//# 1// ; Notice that the last "oint is the same as the 'irst. No! you need only use Move.o,x 'or the 'irst "oint and (ine.o 'or the successive "oints: Kove(oP" (hdc# aptQ/R."# aptQ/R.%# ;VLL) ; for (i ' 1 ; i < . ; i**) Line(o (hdc# aptQiR."# aptQiR.%) ; 1ecause (ine.o dra!s 'rom the current "osition u" to ((ut not including* the "oint in the (ine.o 'unction0 no coordinate gets !ritten t!ice (y this code. #hile over!riting "oints is not a "ro(lem !ith a video dis"lay0 it might not loo good on a "lotter or !ith some dra!ing modes that +7ll discuss later in this cha"ter.
#hen you have an array o' "oints that you !ant connected !ith lines0 you can dra! the lines more easily using the 4ol#line 'unction. This statement dra!s the same rectangle as in the code sho!n a(ove: Col%line (hdc# apt# .) ; The last argument is the num(er o' "oints. #e could also have re"resented this value (y sizeof 6apt) 3 sizeof 64>*+.). 4ol#line has the same e''ect on dra!ing as an initial Move.o,x 'ollo!ed (y multi"le (ine.o 'unctions. -o!ever0 4ol#line doesn7t use or change the current "osition. 4ol#line.o is a little di''erent. This 'unction uses the current "osition 'or the starting "oint and sets the current "osition to the end o' the last line dra!n. The code (elo! dra!s the same rectangle as that last sho!n a(ove: Kove(oP" (hdc# aptQ/R."# aptQ/R.%# ;VLL) ; Col%line(o (hdc# apt * 1# H) ; 5lthough you can use 4ol#line and 4ol#line.o to dra! 6ust a 'e! lines0 the 'unctions are most use'ul !hen you need to dra! a com"le4 curve. Nou do this (y using hundreds or even thousands o' very short lines. +' they7re short enough and there are enough o' them0 together they7ll loo li e a curve. /or e4am"le0 su""ose you need to dra! a sine !ave. The S+N3#5V3 "rogram sho!s ho! to do it. .he 0*+,&/@, program.
,#)0W>?0AC
2399999999999999999999999999999999999999999 :=;P8F_P.4 99 :ine 8ave Vsin+ Col%line (c) 4harles Cet@old# 1SST 9999999999999999999999999999999999999999932 #include <,indo,s.h> #include <math.h> #define ;VK #define (8DC= 1/// (2 3 -.1H1.S)
LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { static (4?FU s@Fpp;ameQR ' (PW( (":ine8ave") ; ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; ,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("Cro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ;
h,nd ' 4reate8indo, (s@Fpp;ame# (PW( (":ine 8ave Vsin+ Col%line")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; :ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X lCaram) { static int ?L4 int CF=;(:(UV4( CD=;( 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK c"4lient# c%4lient ; hdc ; i ; ps ; apt Q;VKR ;
s,itch (messa+e) { case 8K&:=\P7 c"4lient ' LD8DUL (lCaram) ; c%4lient ' ?=8DUL (lCaram) ; return / ; case 8K&CF=;(7 hdc ' Ie+inCaint (h,nd# ]ps) ; Kove(oP" (hdc# /# c%4lient 2 2# ;VLL) ; Line(o (hdc# c"4lient# c%4lient 2 2) ; for (i ' / ; i < ;VK ; i**) { aptQiR." ' i 3 c"4lient 2 ;VK ; aptQiR.% ' (int) (c%4lient 2 2 3 (1 9 sin ((8DC= 3 i 2 ;VK))) ; Col%line (hdc# apt# ;VK) ; return / ; case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ;
The "rogram has an array o' =FFF $%+NT structures. 5s the for loo" is incremented 'rom F through BBB0 the x 'ields o' the $%+NT structure are set to incrementally increasing values 'rom F to cx$lient. The "rogram sets the # 'ields o' the $%+NT structure to sine curve values 'or one cycle and enlarged to 'ill the client area. The !hole curve is dra!n using a single 4ol#line call. 1ecause the 4ol#line 'unction is im"lemented at the device driver level0 it is 'aster than calling (ine.o =FFF times. The results are sho!n here
i' (J8egisterClass (&!ndclass** K &essage1o4 (N.,,0 T3AT (IThis "rogram re)uires #indo!s NTJI*0 sP5""Name0 &19+C%N388%8* L return F L M h!nd [ Create#indo! (sP5""Name0 T3AT (I1utton ,oo I*0 #S9%V38,5$$3D#+ND%#0 C#9.S3D3/5.,T0 C#9.S3D3/5.,T0 C#9.S3D3/5.,T0 C#9.S3D3/5.,T0 N.,,0 N.,,0 h+nstance0 N.,,* L Sho!#indo! (h!nd0 iCmdSho!* L ."date#indo! (h!nd* L !hile (2et&essage (&msg0 N.,,0 F0 F** K Translate&essage (&msg* L Dis"atch&essage (&msg* L M return msg.!$aram L M ,83S.,T C5,,15CK #nd$roc (-#ND h!nd0 .+NT message0 #$585& !$aram0 ,$585& l$aram* K static -#ND h!nd1uttonaN.&b L static 83CT rect L static TC-58 sPTo"ab [ T3AT (Imessage !$aram l$aramI*0 sP.ndab [ T3AT (I9999999 999999 999999I*0 sP/ormatab [ T3AT (IZ:=CsZF>A:ZF>A ZF>A:ZF>AI*0 sP1u''era?Fb L static int c4Char0 cyChar L -DC hdc L $5+NTST8.CT "s L int iL s!itch (message* K case #&9C835T3 : c4Char [ ,%#%8D (2etDialog1ase.nits (** L cyChar [ -+#%8D (2etDialog1ase.nits (** L 'or (i [ F L i U N.& L i++* h!nd1uttonaib [ Create#indo! ( T3AT(I(uttonI*0 (uttonaib.sPTe4t0 #S9C-+,D e #S9V+S+1,3 e (uttonaib.iStyle0 c4Char0 cyChar \ (= + ; \ i*0 ;F \ c4Char0 D \ cyChar / >0 h!nd0 (-&3N.* i0 ((,$C835T3ST8.CT* l$aram*:Vh+nstance0 N.,,* L return F L case #&9S+X3 : rect.le't [ ;> \ c4Char L rect.to" [ ; \ cyChar L
rect.right [ ,%#%8D (l$aram* L rect.(ottom [ -+#%8D (l$aram* L return F L case #&9$5+NT : +nvalidate8ect (h!nd0 &rect0 T8.3* L hdc [ 1egin$aint (h!nd0 &"s* L Select%(6ect (hdc0 2etStoc %(6ect (SNST3&9/+A3D9/%NT** L Set1 &ode (hdc0 T85NS$583NT* L Te4t%ut (hdc0 ;> \ c4Char0 cyChar0 sPTo"0 lstrlen (sPTo"** L Te4t%ut (hdc0 ;> \ c4Char0 cyChar0 sP.nd0 lstrlen (sP.nd** L 3nd$aint (h!nd0 &"s* L return F L case #&9D85#+T3& : case #&9C%&&5ND : Scroll#indo! (h!nd0 F0 :cyChar0 &rect0 &rect* L hdc [ 2etDC (h!nd* L Select%(6ect (hdc0 2etStoc %(6ect (SNST3&9/+A3D9/%NT** L Te4t%ut (hdc0 ;> \ c4Char0 cyChar \ (rect.(ottom / cyChar : =*0 sP1u''er0 !s"rint' (sP1u''er0 sP/ormat0 message [[ #&9D85#+T3& W T3AT (I#&9D85#+T3&I* : T3AT (I#&9C%&&5NDI*0 -+#%8D (!$aram*0 ,%#%8D (!$aram*0 -+#%8D (l$aram*0 ,%#%8D (l$aram*** L 8eleaseDC (h!nd0 hdc* L Validate8ect (h!nd0 &rect* L (rea L case #&9D3ST8%N : $ost@uit&essage (F* L return F L M return De'#indo!$roc (h!nd0 message0 !$aram0 l$aram* L M
5s you clic on each (utton0 the (utton sends a #&9C%&&5ND message to the "arent !indo! "rocedure0 !hich is the 'amiliar &nd4roc. 1TN,%%K7s &nd4roc dis"lays the w4aram and l4aram "arameters o' this message in the right hal' o' the client area0 as sho!n. The (utton !ith the style 1S9%#N38D85# is dis"layed on this !indo! only !ith a (ac ground shading (ecause this is a style o' (utton that the "rogram is res"onsi(le 'or dra!ing. The (utton indicates it needs dra!ing (y #&9D85#+T3& messages containing an l4aram message "arameter that is a "ointer to a structure o' ty"e D85#+T3&ST8.CT. These messages are also dis"layed in 1TN,%%K. +7ll discuss o!ner:dra! (uttons in more detail later in this cha"ter.
'unction returns a G;:(it value com"rising a !idth in the lo! !ord and a height in the high !ord. #hile 2et'ialog)ase1nits returns roughly the same values as can (e o(tained 'rom the 2et.extMetrics 'unction0 it7s some!hat easier to use and !ill ensure more consistency !ith controls in dialog (o4es. The child !indo! +D "arameter should (e uni)ue 'or each child !indo!. This +D hel"s your !indo! "rocedure identi'y the child !indo! !hen "rocessing #&9C%&&5ND messages 'rom it. Notice that the child !indo! +D is "assed in the $reate&indow "arameter normally used to s"eci'y the "rogram7s menu0 so it must (e cast to an -&3N.. The instance handle "arameter o' the $reate&indow call loo s a little strange0 (ut !e7re ta ing advantage o' the 'act that during a #&9C835T3 message l4aram is actually a "ointer to a structure o' ty"e C835T3ST8.CT (Icreation structureI* that has a mem(er h*nstance. So !e cast l4aram into a "ointer to a C835T3ST8.CT structure and get h*nstance out. (Some #indo!s "rograms use a glo(al varia(le named h*nst to give !indo! "rocedures access to the instance handle availa(le in &inMain. +n &inMain0 you need to sim"ly set h=nst ' h=nstance ; 2et&indow(ong to o(tain this instance handle: Yet8indo,Lon+ (h,nd# Y8L&?=;:(F;4P) 5ny o' these methods is 'ine.* 5'ter the $reate&indow call0 !e needn7t do anything more !ith these child !indo!s. The (utton !indo! "rocedure !ithin #indo!s maintains the (uttons 'or us and handles all re"ainting 6o(s. (The e4ce"tion is the (utton !ith the 1S9%#N38D85# styleL as +7ll discuss later0 this (utton style re)uires the "rogram to dra! the (utton.* 5t the "rogram7s termination0 #indo!s destroys these child !indo!s !hen the "arent !indo! is destroyed.
than to the main !indo!. -o!ever0 !hen the (utton control has the in"ut 'ocus0 it ignores all eystro es e4ce"t the S"ace(ar0 !hich no! has the same e''ect as a mouse clic .
P$sh B$ttons The 'irst t!o (uttons sho!n in 1TN,%%K are I"ushI (uttons. 5 "ush (utton is a rectangle enclosing te4t s"eci'ied in the !indo! te4t "arameter o' the $reate&indow call. The rectangle ta es u" the 'ull height and !idth o' the dimensions given in the $reate&indow or Move&indow call. The te4t is centered !ithin the rectangle. $ush:(utton controls are used mostly to trigger an immediate action !ithout retaining any ty"e o' on/o'' indication. The t!o ty"es o' "ush:(utton controls have !indo! styles called 1S9$.S-1.TT%N and 1S9D3/$.S-1.TT%N. The ID3/I in 1S9D3/$.S-1.TT%N stands 'or Ide'ault.I #hen used to design dialog (o4es0 1S9$.S-1.TT%N controls and 1S9D3/$.S-1.TT%N controls 'unction di''erently 'rom one another. #hen used as child !indo! controls0 ho!ever0 the t!o ty"es o' "ush (uttons 'unction the same !ay0 although 1S9D3/$.S-1.TT%N has a heavier outline.
5 "ush (utton loo s (est !hen its height is D/> times the height o' a te4t character0 !hich is !hat 1TN,%%K uses. The "ush (utton7s !idth must accommodate at least the !idth o' the te4t0 "lus t!o additional characters. #hen the mouse cursor is inside the "ush (utton0 "ressing the mouse (utton causes the (utton to re"aint itsel' using GD:style shading to a""ear as i' it7s (een de"ressed. 8eleasing the mouse (utton restores the original a""earance and sends a #&9C%&&5ND message to the "arent !indo! !ith the noti'ication code 1N9C,+CK3D. 5s !ith the other (utton ty"es0 !hen a "ush (utton has the in"ut 'ocus0 a dashed line surrounds the te4t and "ressing and releasing the S"ace(ar has the same e''ect as "ressing and releasing the mouse (utton. Nou can simulate a "ush:(utton 'lash (y sending the !indo! a 1&9S3TST5T3 message. This causes the (utton to (e de"ressed: :endKessa+e (h,ndIutton# IK&:P(:(F(P# 1# /) ; This call causes the (utton to return to normal: :endKessa+e (h,ndIutton# IK&:P(:(F(P# /# /) ; The hwnd)utton !indo! handle is the value returned 'rom the $reate&indow call. Nou can also send a 1&923TST5T3 message to a "ush (utton. The child !indo! control returns the current state o' the (utton: T8.3 i' the (utton is de"ressed and /5,S3 i' it isn7t de"ressed. &ost a""lications do not re)uire this in'ormation0 ho!ever. 5nd (ecause "ush (uttons do not retain any on/o'' in'ormation0 the 1&9S3TC-3CK and 1&923TC-3CK messages are not used. Chec+ Bo=es 5 chec (o4 is a s)uare (o4 !ith te4tL the te4t usually a""ears to the right o' the chec (o4. (+' you include the 1S9,3/TT3AT style !hen creating the (utton0 the te4t a""ears to the le'tL you7ll "ro(a(ly !ant to com(ine this style !ith 1S98+2-T to right:6usti'y the te4t.* Chec (o4es are usually incor"orated in an a""lication to allo! a user to select o"tions. The chec (o4 commonly 'unctions as a toggle s!itch: clic ing the (o4 once causes a chec mar to a""earL clic ing again toggles the chec mar o''. The t!o most common styles 'or a chec (o4 are 1S9C-3CK1%A and 1S95.T%C-3CK1%A. #hen you use the 1S9C-3CK1%A style0 you must set the chec mar yoursel' (y sending the control a 1&9S3TC-3CK message. The w4aram "arameter is set to = to create a chec mar and to F to remove it. Nou can o(tain the current chec state o' the (o4 (y sending the control a 1&923TC-3CK message. Nou might use code li e this to toggle the A mar !hen "rocessing a #&9C%&&5ND message 'rom the control: :endKessa+e ((?8;L) lCaram# IK&:P(4?P4X# (8CFUFK) O:endKessa+e ((?8;L) lCaram# IK&YP(4?P4X# /# /)# /) ;
Notice the J o"erator in 'ront o' the second 0endMessage call. The l4aram value is the child !indo! handle that is "assed to your !indo! "rocedure in the #&9C%&&5ND message. #hen you later need to no! the state o' the (utton0 send it another 1&923TC-3CK message. %r you can retain the current chec state in a static varia(le in your !indo! "rocedure. Nou can also initialiPe a 1S9C-3CK1%A chec (o4 !ith a chec mar (y sending it a 1&9S3TC-3CK message: :endKessa+e (h,ndIutton# IK&:P(4?P4X# 1# /) ; /or the 1S95.T%C-3CK1%A style0 the (utton control itsel' toggles the chec mar on and o''. Nour !indo! "rocedure can ignore #&9C%&&5ND messages. #hen you need the current state o' the (utton0 send the control a 1&923TC-3CK message: i4hec0 ' (int) :endKessa+e (h,ndIutton# IK&YP(4?P4X# /# /) ; The value o' iChec is T8.3 or nonPero i' the (utton is chec ed and /5,S3 or F i' not. The other t!o chec (o4 styles are 1S9GST5T3 and 1S95.T%GST5T3. 5s their names indicate0 these styles can dis"lay a third state as !ellSa gray color !ithin the chec (o4S!hich occurs !hen you send the control a #&9S3TC-3CK message !ith w4aram e)ual to ;. The gray color indicates to the user that the selection is indeterminate or irrelevant. The chec (o4 is aligned !ith the rectangle7s le't edge and is centered !ithin the to" and (ottom dimensions o' the rectangle that !ere s"eci'ied during the $reate&indow call. Clic ing any!here !ithin the rectangle causes a #&9C%&&5ND message to (e sent to the "arent. The minimum height 'or a chec (o4 is one character height. The minimum !idth is the num(er o' characters in the te4t0 "lus t!o. Radio B$ttons
5 radio (utton is named a'ter the ro! o' (uttons that !ere once )uite common on car radios. 3ach (utton on a car radio is set 'or a di''erent radio station0 and only one (utton can (e "ressed at a time. +n dialog (o4es0 grou"s o' radio (uttons are conventionally used to indicate mutually e4clusive o"tions. .nli e chec (o4es0 radio (uttons do not !or as togglesSthat is0 !hen you clic a radio (utton a second time0 its state remains unchanged. The radio (utton loo s very much li e a chec (o4 e4ce"t that it contains a little circle rather than a (o4. 5 heavy dot !ithin the circle indicates that the radio (utton has (een chec ed. The radio (utton has the !indo! style 1S985D+%1.TT%N or 1S95.T%85D+%1.TT%N0 (ut the latter is used only in dialog (o4es. #hen you receive a #&9C%&&5ND message 'rom a radio (utton0 you should dis"lay its chec (y sending it a 1&9S3TC-3CK message !ith w4aram e)ual to =: :endKessa+e (h,ndIutton# IK&:P(4?P4X# 1# /) ; /or all other radio (uttons in the same grou"0 you can turn o'' the chec s (y sending them 1&9S3TC-3CK messages !ith w4aram e)ual to F: :endKessa+e (h,ndIutton# IK&:P(4?P4X# /# /) ;
6ro$- Bo=es The grou" (o40 !hich has the 1S928%.$1%A style0 is an oddity in the (utton class. +t neither "rocesses mouse or ey(oard in"ut nor sends #&9C%&&5ND messages to its "arent. The grou" (o4 is a rectangular outline !ith its !indo! te4t at the to". 2rou" (o4es are o'ten used to enclose other (utton controls. Changing the B$tton %e=t
Nou can change the te4t in a (utton (or in any other !indo!* (y calling 0et&indow.ext: :et8indo,(e"t (h,nd# ps@:trin+) ; !here hwnd is a handle to the !indo! !hose te4t is (eing changed and psz0tring is a "ointer to a null:terminated string. /or a normal !indo!0 this te4t is the te4t o' the ca"tion (ar. /or a (utton control0 it7s the te4t dis"layed !ith the (utton. Nou can also o(tain the current te4t o' a !indo!: iLen+th ' Yet8indo,(e"t (h,nd# ps@Iuffer# iKa"Len+th) ; The iMax(ength "arameter s"eci'ies the ma4imum num(er o' characters to co"y into the (u''er "ointed to (y psz)uffer. The 'unction returns the string length co"ied. Nou can "re"are your "rogram 'or a "articular te4t length (y 'irst calling iLen+th ' Yet8indo,(e"tLen+th (h,nd) ;
5s + discussed0 !hen #indo!s s!itches the in"ut 'ocus 'rom one !indo! (such as a "arent* to another (such as a child !indo! control*0 it 'irst sends a #&9K+,,/%C.S message to the !indo! losing the in"ut 'ocus. The w4aram "arameter is the handle o' the !indo! that is to receive the in"ut 'ocus. #indo!s then sends a #&9S3T/%C.S message to the !indo! receiving the in"ut 'ocus0 !ith w4aram s"eci'ying the handle o' the !indo! losing the in"ut 'ocus. (+n (oth cases0 w4aram might (e N.,,0 !hich indicates that no !indo! has or is receiving the in"ut 'ocus.* 5 "arent !indo! can "revent a child !indo! control 'rom getting the in"ut 'ocus (y "rocessing #&9K+,,/%C.S messages. 5ssume that the array hwnd$hild contains the !indo! handles o' all child !indo!s. (These !ere saved in the array during the $reate&indow calls that created the !indo!s.* N.& is the num(er o' child !indo!s. case 8K&X=LL6D4V: 7 for (i ' / ; i < ;VK ; i**) if (h,nd4hild QiR '' (?8;L) ,Caram) { :et6ocus (h,nd) ; !rea0 ; return / ; +n this code0 !hen the "arent !indo! detects that it7s losing the in"ut 'ocus to one o' its child !indo! controls0 it calls 0et!ocus to restore the in"ut 'ocus to itsel'. -ere7s a sim"ler ((ut less o(vious* !ay o' doing it: case 8K&X=LL6D4V: 7 if (h,nd '' YetCarent ((?8;L) ,Caram)) :et6ocus (h,nd) ; return / ; 1oth these methods have a shortcoming0 ho!ever: they "revent the (utton 'rom res"onding to the S"ace(ar0 (ecause the (utton never gets the in"ut 'ocus. 5 (etter a""roach !ould (e to let the (utton get the in"ut 'ocus (ut also to include the 'acility 'or the user to move 'rom (utton to (utton using the Ta( ey. 5t 'irst this sounds im"ossi(le0 (ut +7ll sho! you ho! to accom"lish it !ith a techni)ue called I!indo! su(classingI in the C%,%8S= "rogram sho!n later in this cha"ter. 5 menu is "ro(a(ly the most im"ortant "art o' the consistent user inter'ace that #indo!s "rograms o''er0 and adding a menu to your "rogram is a relatively easy "art o' #indo!s "rogramming. Nou de'ine the menu in Develo"er Studio. 3ach selecta(le menu item is given a uni)ue +D num(er. Nou s"eci'y the name o' the menu in the !indo! class structure. #hen the user chooses a menu item0 #indo!s sends your "rogram a #&9C%&&5ND message containing that +D. 5'ter discussing menus0 +7ll conclude this cha"ter !ith a section on ey(oard accelerators0 !hich are ey com(inations that are used "rimarily to du"licate menu 'unctions.
Men$ Conce-ts
5 !indo!7s menu (ar is dis"layed immediately (elo! the ca"tion (ar. This menu (ar is sometimes called a "rogram7s Imain menuI or the Ito":level menu.I +tems listed in the to":level menu usually invo e dro":do!n menus0 !hich are also called I"o"u" menusI or Isu(menus.I Nou can also de'ine multi"le nestings o' "o"u"s: that is0 an item on a "o"u" menu can invo e another "o"u" menu. Sometimes items in "o"u" menus invo e a dialog (o4 'or more in'ormation. (Dialog (o4es are covered in the ne4t cha"ter.* &ost "arent !indo!s have0 to the 'ar le't o' the ca"tion (ar0 a dis"lay o' the "rogram7s small icon. This icon invo es the system menu0 !hich is really another "o"u" menu. &enu items in "o"u"s can (e Ichec ed0I !hich means that #indo!s dra!s a small chec mar to the le't o' the menu te4t. The use o' chec mar s lets the user choose di''erent "rogram o"tions 'rom the menu. These o"tions can (e mutually e4clusive0 (ut they don7t have to (e. To":level menu items cannot (e chec ed. &enu items in the to":level menu or in "o"u" menus can (e Iena(led0I Idisa(led0I or Igrayed.I The !ords IactiveI and IinactiveI are sometimes used synonymously !ith Iena(ledI and Idisa(led.I &enu items 'lagged as ena(led or disa(led loo the same to the user0 (ut a grayed menu item is dis"layed in gray te4t. /rom the "ers"ective o' the user0 ena(led0 disa(led0 and grayed menu items can all (e IselectedI (highlighted*. That is0 the user can clic the mouse on a disa(led menu item0 or move the reverse:video cursor (ar to a disa(led menu
item0 or trigger the menu item (y using the item7s ey letter. -o!ever0 'rom the "ers"ective o' your "rogram0 ena(led0 disa(led0 and grayed menu items 'unction di''erently. #indo!s sends your "rogram a #&9C%&&5ND message only 'or ena(led menu items. Nou use disa(led and grayed menu items 'or o"tions that are not currently valid. +' you !ant to let the user no! the o"tion is not valid0 ma e it grayed.
Men$ ,tr$ct$re
#hen you create or change menus in a "rogram0 it7s use'ul to thin o' the to":level menu and each "o"u" menu as (eing se"arate menus. The to":level menu has a menu handle0 each "o"u" menu !ithin a to":level menu has its o!n menu handle0 and the system menu (!hich is also a "o"u"* has a menu handle. 3ach item in a menu is de'ined (y three characteristics. The 'irst characteristic is !hat a""ears in the menu. This is either a te4t string or a (itma". The second characteristic is either an +D num(er that #indo!s sends to your "rogram in a #&9C%&&5ND message or the handle to a "o"u" menu that #indo!s dis"lays !hen the user chooses that menu item. The third characteristic descri(es the attri(ute o' the menu item0 including !hether the item is disa(led0 grayed0 or chec ed.
hKenu ' LoadKenu (h=nstance# KFXP=;(UP:DVU4P (=L&KP;V)) ; Nou can then s"eci'y this menu handle as the ninth "arameter to $reate&indow: h,nd ' 4reate8indo, ((PW( ("K%4lass")# (PW( ("8indo, 4aption")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# hKenu# h=nstance# ;VLL) ; +n this case0 the menu s"eci'ied in the $reate&indow call overrides any menu s"eci'ied in the !indo! class. Nou can thin o' the menu in the !indo! class as (eing a de'ault menu 'or the !indo!s (ased on the !indo! class i' the ninth "arameter to $reate&indow is N.,,. There'ore0 you can use di''erent menus 'or several !indo!s (ased on the same !indo! class. Nou can also have a N.,, menu name in the !indo! class and a N.,, menu handle in the $reate&indow call and assign a menu to a !indo! a'ter the !indo! has (een created: :etKenu (h,nd# hKenu) ; This 'orm lets you dynamically change a !indo!7s menu. #e7ll see an e4am"le o' this in the N%$%$.$S "rogram0 sho!n later in this cha"ter. 5ny menu that is attached to a !indo! is destroyed !hen the !indo! is destroyed. 5ny menus not attached to a !indo! should (e e4"licitly destroyed (y calls to 'estro#Menu (e'ore the "rogram terminates.
#f (o$ ha--en to $se the same #D codes for men$s and child window controls. (o$ can differentiate /etween them /( e=amining the val$e of l(aram0 !hich !ill (e F 'or a menu item. 2enus +ontrols ,%#%8D (w4aram*: &enu +D Control +D -+#%8D (w4aram*: F Noti'ication code l4aram: F Child !indo! handle The #&9SNSC%&&5ND message is similar to the #&9C%&&5ND message e4ce"t that #&9SNSC%&&5ND signals that the user has chosen an ena(led menu item 'rom the system menu: w4aram: &enu +D l4aram: F -o!ever0 i' the #&9SNSC%&&5ND message is the result o' a mouse clic 0 ,%#%8D ( l4aram* and -+#%8D (l4aram* !ill contain the x and # screen coordinates o' the mouse cursor7s location. /or #&9SNSC%&&5ND0 the menu +D indicates !hich item on the system menu has (een chosen. /or the "rede'ined system menu items0 the (ottom 'our (its should (e mas ed out (y 5NDing !ith F4///F. The resultant value !ill (e one o' the 'ollo!ing: SC9S+X30 SC9&%V30 SC9&+N+&+X30 SC9&5A+&+X30 SC9N3AT#+ND%#0 SC9$83V#+ND%#0 SC9C,%S30 SC9VSC8%,,0 SC9-SC8%,,0 SC95885N230 SC983ST%830 and SC9T5SK,+ST. +n addition0 w4aram can (e SC9&%.S3&3N. or SC9K3N&3N.. +' you add menu items to the system menu0 the lo! !ord o' w4aram !ill (e the menu +D that you de'ine. To avoid con'licts !ith the "rede'ined menu +Ds0 use values (elo! F4/FFF. +t is im"ortant that you "ass normal #&9SNSC%&&5ND messages to 'ef&indow4roc. +' you do not0 you7ll e''ectively disa(le the normal system menu commands. The 'inal message !e7ll loo at is #&9&3N.C-580 !hich isn7t really a menu message at all. #indo!s sends this message to your !indo! "rocedure in one o' t!o circumstances: i' the user "resses 5lt and a character ey that does not corres"ond to a menu item0 or0 !hen a "o"u" is dis"layed0 i' the user "resses a character ey that does not corres"ond to an item in the "o"u". The "arameters that accom"any the #&9&3N.C-58 message are as 'ollo!s: ,%#%8D (w4aram*: Character code (5SC++ or .nicode* -+#%8D (w4aram*: Selection code l4aram: -andle to menu The selection code is: I No "o"u" is dis"layed. M!_4>414 $o"u" is dis"layed. M!_0A0M,+1 System menu "o"u" is dis"layed. #indo!s "rograms usually "ass this message to 'ef&indow4roc0 !hich normally returns a F to #indo!s0 !hich causes #indo!s to (ee".
M0)*D0MOAC
2399999999999999999999999999999999999999999 KP;VLPKD.4 99 Kenu Lemonstration (c) 4harles Cet@old# 1SST 9999999999999999999999999999999999999999932 #include <,indo,s.h> #include "resource.h" #define =L&(=KPU 1
LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; (4?FU s@Fpp;ameQR ' (PW( ("KenuLemo") ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; ,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; s@Fpp;ame ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; h,nd ' 4reate8indo, (s@Fpp;ame# (PW( ("Kenu Lemonstration")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; :ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK lCaram) { static int id4olor Q.R ' { 8?=(P&IUV:?# L(YUFG&IUV:?# YUFG&IUV:?# LXYUFG&IUV:?# ILF4X&IUV:? ; static int i:election ' =LK&IXY;L&8?=(P ; ?KP;V hKenu ; s,itch (messa+e) { case 8K&4DKKF;L7
hKenu ' YetKenu (h,nd) ; s,itch (LD8DUL (,Caram)) { case =LK&6=LP&;P87 case =LK&6=LP&DCP;7 case =LK&6=LP&:F_P7 case =LK&6=LP&:F_P&F:7 Kessa+eIeep (/) ; return / ; case =LK&FCC&PW=(7 :endKessa+e (h,nd# 8K&4LD:P# /# /) ; return / ; case case case case case =LK&PL=(&V;LD7 =LK&PL=(&4V(7 =LK&PL=(&4DCG7 =LK&PL=(&CF:(P7 =LK&PL=(&4LPFU7 Kessa+eIeep (/) ; return / ; =LK&IXY;L&8?=(P7 =LK&IXY;L&L(YUFG7 =LK&IXY;L&YUFG7 =LK&IXY;L&LXYUFG7 =LK&IXY;L&ILF4X7 22 ;ote7 Lo+ic !elo, 22 assumes that =LK&8?=(P 22 throu+h =LK&ILF4X are 22 consecutive num!ers in 22 the order sho,n here.
4hec0Kenu=tem (hKenu# i:election# K6&V;4?P4XPL) ; i:election ' LD8DUL (,Caram) ; 4hec0Kenu=tem (hKenu# i:election# K6&4?P4XPL) ; :et4lassLon+ (h,nd# Y4L&?IUIF4XYUDV;L# (LD;Y) Yet:toc0D!$ect (id4olor QLD8DUL (,Caram) 9 =LK&IXY;L&8?=(PR)) ; =nvalidateUect (h,nd# ;VLL# (UVP) ; return / ; case =LK&(=KPU&:(FU(7 if (:et(imer (h,nd# =L&(=KPU# 1///# ;VLL)) { Pna!leKenu=tem (hKenu# =LK&(=KPU&:(FU(# K6&YUFGPL) ; Pna!leKenu=tem (hKenu# =LK&(=KPU&:(DC# K6&P;FILPL) ; return / ; case =LK&(=KPU&:(DC7 Xill(imer (h,nd# =L&(=KPU) ; Pna!leKenu=tem (hKenu# =LK&(=KPU&:(FU(# K6&P;FILPL) ; Pna!leKenu=tem (hKenu# =LK&(=KPU&:(DC# K6&YUFGPL) ; return / ; case =LK&FCC&?PLC7
Kessa+eIo" (h,nd# (PW( ("?elp not %et implementedO")# s@Fpp;ame# KI&=4D;PW4LFKF(=D; ^ KI&DX) ; return / ; case =LK&FCC&FIDV(7 Kessa+eIo" (h,nd# (PW( ("Kenu Lemonstration Cro+ram\n") (PW( ("(c) 4harles Cet@old# 1SST")# s@Fpp;ame# KI&=4D;=;6DUKF(=D; ^ KI&DX) ; return / ; !rea0 ; case 8K&(=KPU7 Kessa+eIeep (/) ; return / ; case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ;
M0)*D0MOARC 3e=cer-ts5
22Kicrosoft Leveloper :tudio +enerated resource script. #include "resource.h" #include "af"res.h" 222222222222222222222222222222222222222222222222222222222222222222222222 22222 22 Kenu KP;VLPKD KP;V L=:4FULFILP IPY=; CDCVC "]6ile" IPY=; KP;V=(PK "];e,"# KP;V=(PK "]Dpen"# KP;V=(PK "]:ave"# KP;V=(PK ":ave ]Fs..."# KP;V=(PK :PCFUF(DU KP;V=(PK "P]"it"# P;L CDCVC "]Pdit" IPY=; KP;V=(PK "]Vndo"# KP;V=(PK :PCFUF(DU KP;V=(PK "4]ut"# KP;V=(PK "]4op%"# KP;V=(PK "]Caste"# KP;V=(PK "Le]lete"# P;L CDCVC "]Iac0+round"
P;L
IPY=; KP;V=(PK "]8hite"# KP;V=(PK "]Li+ht Yra%"# KP;V=(PK "]Yra%"# KP;V=(PK "]Lar0 Yra%"# KP;V=(PK "]Ilac0"# P;L CDCVC "](imer" IPY=; KP;V=(PK "]:tart"# KP;V=(PK ":]top"# P;L CDCVC "]?elp" IPY=; KP;V=(PK "]?elp..."# KP;V=(PK "]F!out KenuLemo..."# P;L
=LK&FCC&?PLC =LK&FCC&FIDV(
R0,O*RC0A' 3e=cer-ts5
22 Kicrosoft Leveloper :tudio +enerated include file. 22 Vsed !% KenuLemo.rc #define =LK&6=LP&;P8 H///1 #define =LK&6=LP&DCP; H///2 #define =LK&6=LP&:F_P H///#define =LK&6=LP&:F_P&F: H///H #define =LK&FCC&PW=( H///. #define =LK&PL=(&V;LD H///M #define =LK&PL=(&4V( H///1 #define =LK&PL=(&4DCG H///T #define =LK&PL=(&CF:(P H///S #define =LK&PL=(&4LPFU H//1/ #define =LK&IXY;L&8?=(P H//11 #define =LK&IXY;L&L(YUFG H//12 #define =LK&IXY;L&YUFG H//1#define =LK&IXY;L&LXYUFG H//1H #define =LK&IXY;L&ILF4X H//1. #define =LK&(=KPU&:(FU( H//1M #define =LK&(=KPU&:(DC H//11 #define =LK&FCC&?PLC H//1T #define =LK&FCC&FIDV( H//1S The &3N.D3&%.8C resource scri"t should give you hints on de'ining the menu. The menu has a te4t name o' I&enuDemo.I &ost items have underlined letters0 !hich means you must ty"e an am"ersand (&* (e'ore the letter. The &3N.+T3& S3$585T%8 statement results 'rom chec ing the Se"arator (o4 in the &enu +tem $ro"erties dialog (o4. Notice that one item in the menu has the Chec ed o"tion and another has the 2rayed o"tion. 5lso0 the 'ive items in the 1ac ground "o"u" menu should (e entered in the order sho!n to ensure that the identi'iers are in numeric orderL the "rogram relies on this. 5ll the menu item identi'iers are de'ined in 83S%.8C3.-. The &3N.D3&% "rogram sim"ly (ee"s !hen it receives a #&9C%&&5ND message 'or most items in the /ile and 3dit "o"u"s. The 1ac ground "o"u" lists 'ive stoc (rushes that &3N.D3&% can use to color the (ac ground. +n the &3N.D3&%.8C resource scri"t0 the #hite menu item (!ith a menu +D o' +D&91K2ND9#-+T3* is 'lagged as C-3CK3D0 !hich "laces a chec mar ne4t to the item. +n &3N.D3&%.C0 the value o' i0election is initially set to +D&91K2ND9#-+T3.
The 'ive (rushes on the 1ac ground "o"u" menu are mutually e4clusive. #hen &3N.D3&%.C receives a #&9C%&&5ND message !here w4aram is one o' these 'ive items on the 1ac ground "o"u"0 it must remove the chec mar 'rom the "reviously chosen (ac ground color and add a chec mar to the ne! (ac ground color. To do this0 it 'irst gets a handle to its menu: hKenu ' YetKenu (h,nd) ; The $hec%Menu*tem 'unction is used to unchec the currently chec ed item: 4hec0Kenu=tem (hKenu# i:election# K6&V;4?P4XPL) ; The i0election value is set to the value o' w4aram0 and the ne! (ac ground color is chec ed: i:election ' ,Caram ; 4hec0Kenu=tem (hKenu# i:election# K6&4?P4XPL) ; The (ac ground color in the !indo! class is then re"laced !ith the ne! (ac ground color0 and the !indo! client area is invalidated. #indo!s erases the !indo!0 using the ne! (ac ground color. The Timer "o"u" lists t!o o"tionsSStart and Sto". +nitially0 the Sto" o"tion is grayed (as indicated in the menu de'inition 'or the resource scri"t*. #hen you choose the Start o"tion0 &3N.D3&% tries to start a timer and0 i' success'ul0 grays the Start o"tion and ma es the Sto" o"tion active: Pna!leKenu=tem (hKenu# =LK&(=KPU&:(FU(# K6&YUFGPL) ; Pna!leKenu=tem (hKenu# =LK&(=KPU&:(DC# K6&P;FILPL) ; %n recei"t o' a #&9C%&&5ND message !ith w4aram e)ual to +D&9T+&389ST%$0 &3N.D3&% ills the timer0 activates the Start o"tion0 and grays the Sto" o"tion: Pna!leKenu=tem (hKenu# =LK&(=KPU&:(FU(# K6&P;FILPL) ; Pna!leKenu=tem (hKenu# =LK&(=KPU&:(DC# K6&YUFGPL) ; Notice that it7s im"ossi(le 'or &3N.D3&% to receive a #&9C%&&5ND message !ith w4aram e)ual to +D&9T+&389ST58T !hile the timer is going. Similarly0 it7s im"ossi(le to receive a #&9C%&&5ND !ith w4aram e)ual to +D&9T+&389ST%$ !hile the timer is not going. #hen &3N.D3&% receives a #&9C%&&5ND message !ith the w4aram "arameter e)ual to +D&95$$951%.T or +D&95$$9-3,$0 it dis"lays a message (o4. (+n the ne4t cha"ter0 !e7ll change this to a dialog (o4.* #hen &3N.D3&% receives a #&9C%&&5ND message !ith w4aram e)ual to +D&95$$93A+T0 it sends itsel' a #&9C,%S3 message. This is the same message that 'ef&indow4roc sends the !indo! "rocedure !hen it receives a #&9SNSC%&&5ND message !ith w4aram e)ual to SC9C,%S3. #e7ll e4amine this more in the $%$$5D; "rogram sho!n near the end o' this cha"ter.
Men$ 0tiK$ette
The 'ormat o' the /ile and 3dit "o"u"s in &3N.D3&% is )uite similar to those in other #indo!s "rograms. %ne o' the o(6ectives o' #indo!s is to "rovide a user !ith a recogniPa(le inter'ace that does not re)uire relearning (asic conce"ts 'or each "rogram. +t certainly hel"s i' the /ile and 3dit menus loo the same in every #indo!s "rogram and use the same letters 'or selection in com(ination !ith the 5lt ey. 1eyond the /ile and 3dit "o"u"s0 the menus o' most #indo!s "rograms !ill "ro(a(ly (e di''erent. #hen designing a menu0 you should loo at e4isting #indo!s "rograms and aim 'or some consistency. %' course0 i' you thin these other "rograms are !rong and you no! the right !ay to do it0 no(ody7s going to sto" you. 5lso ee" in mind that revising a menu usually re)uires revising only the resource scri"t and not your "rogram code. Nou can move menu items around at a later time !ithout many "ro(lems. 5lthough your "rogram menu can have &3N.+T3& statements on the to" level0 these are not ty"ical (ecause they can (e too easily chosen (y mista e. +' you do this0 use an e4clamation "oint a'ter the te4t string to indicate that the menu item does not invo e a "o"u".
The menu is initially em"ty. /ppendMenu inserts items into the menu. Nou must o(tain a di''erent menu handle 'or the to":level menu item and 'or each "o"u". The "o"u"s are constructed se"aratelyL the "o"u" menu handles are then inserted into the to":level menu. The code sho!n creates a menu in this 'ashionL in 'act0 it is the same menu that + used in the &3N.D3&% "rogram. /or illustrative sim"licity0 the code uses 5SC++ character strings. $ code that creates the same menu as used in the M,+1',M> program but without requiring a resource script file. hKenu ' 4reateKenu () ; hKenuCopup ' 4reateKenu () ; FppendKenu FppendKenu FppendKenu FppendKenu FppendKenu FppendKenu (hKenuCopup# (hKenuCopup# (hKenuCopup# (hKenuCopup# (hKenuCopup# (hKenuCopup# K6&:(U=;Y# K6&:(U=;Y# K6&:(U=;Y# K6&:(U=;Y# K6&:PCFUF(DU# K6&:(U=;Y# =LK&6=LP&;P8# =LK&6=LP&DCP;# =LK&6=LP&:F_P# =LK&6=LP&:F_P&F:# /# =LK&FCC&PW=(# "];e,") ; "]Dpen...") ; "]:ave") ; ":ave ]Fs...") ; ;VLL) ; "P]"it") ;
FppendKenu (hKenu# K6&CDCVC# hKenuCopup# "]6ile") ; hKenuCopup ' 4reateKenu () ; FppendKenu FppendKenu FppendKenu FppendKenu FppendKenu FppendKenu FppendKenu (hKenuCopup# K6&:(U=;Y# =LK&PL=(&V;LD# (hKenuCopup# K6&:PCFUF(DU# /# (hKenuCopup# K6&:(U=;Y# =LK&PL=(&4V(# (hKenuCopup# K6&:(U=;Y# =LK&PL=(&4DCG# (hKenuCopup# K6&:(U=;Y# =LK&PL=(&CF:(P# (hKenuCopup# K6&:(U=;Y# =LK&PL=(&4LPFU# (hKenu# K6&CDCVC# hKenuCopup# "]Pdit") ; "]Vndo") ; ;VLL) ; "4u]t") ; "]4op%") ; "]Caste") ; "Le]lete") ;
hKenuCopup ' 4reateKenu () ; FppendKenu (hKenuCopup# "]8hite") ; FppendKenu (hKenuCopup# Yra%"); FppendKenu (hKenuCopup# "]Yra%") ; FppendKenu (hKenuCopup# Yra%"); FppendKenu (hKenuCopup# "]Ilac0") ; K6&:(U=;Ya K6&4?P4XPL# =LK&IXY;L&8?=(P# K6&:(U=;Y# K6&:(U=;Y# K6&:(U=;Y# K6&:(U=;Y# =LK&IXY;L&L(YUFG# "]Li+ht =LK&IXY;L&YUFG# =LK&IXY;L&LXYUFG# "]Lar0 =LK&IXY;L&ILF4X#
FppendKenu (hKenu# K6&CDCVC# hKenuCopup# "]Iac0+round") ; hKenuCopup ' 4reateKenu () ; FppendKenu (hKenuCopup# K6&:(U=;Y# =LK&(=KPU&:(FU(# "]:tart") ; FppendKenu (hKenuCopup# K6&:(U=;Y a K6&YUFGPL# =LK&(=KPU&:(DC# ":]top") ; FppendKenu (hKenu# K6&CDCVC# hKenuCopup# "](imer") ; hKenuCopup ' 4reateKenu () ; FppendKenu (hKenuCopup# K6&:(U=;Y# =LK&?PLC&?PLC# FppendKenu (hKenuCopup# K6&:(U=;Y# =LK&FCC&FIDV(# "]?elp") ; "]F!out KenuLemo...")
; FppendKenu (hKenu# K6&CDCVC# hKenuCopup# "]?elp") ; + thin you7ll agree that the resource scri"t menu tem"late is easier and clearer. +7m not recommending that you de'ine a menu in this !ay0 only sho!ing that it can (e done. Certainly you could cut do!n on the code siPe su(stantially (y using some arrays o' structures containing all the menu item character strings0 +Ds0 and 'lags. 1ut i' you do that0 you might as !ell ta e advantage o' the third method #indo!s "rovides 'or de'ining a menu. The (oadMenu*ndirect 'unction acce"ts a "ointer to a structure o' ty"e &3N.+T3&T3&$,5T3 and returns a handle to a menu. This 'unction is used !ithin #indo!s to construct a menu a'ter loading the normal menu tem"late 'rom a resource scri"t. +' you7re (rave0 you can try using it yoursel'.
POPM0)*AC
239999999999999999999999999999999999999999 CDCKP;V.4 99 Copup Kenu Lemonstration (c) 4harles Cet@old# 1SST 999999999999999999999999999999999999999932 #include <,indo,s.h> #include "resource.h" LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; ?=;:(F;4P h=nst ; (4?FU s@Fpp;ameQR ' (PW( ("CopKenu") ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; ,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# s@Fpp;ame) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ;
return / ; h=nst ' h=nstance ; h,nd ' 4reate8indo, (s@Fpp;ame# (PW( ("Copup Kenu Lemonstration")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; :ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK lCaram) { static ?KP;V hKenu ; static int id4olor Q.R ' { 8?=(P&IUV:?# L(YUFG&IUV:?# YUFG&IUV:?# LXYUFG&IUV:?# ILF4X&IUV:? ; static int i:election ' =LK&IXY;L&8?=(P ; CD=;( point ; s,itch (messa+e) { case 8K&4UPF(P7 hKenu ' LoadKenu (h=nst# s@Fpp;ame) ; hKenu ' Yet:u!Kenu (hKenu# /) ; return / ; case 8K&UIV((D;VC7 point." ' LD8DUL (lCaram) ; point.% ' ?=8DUL (lCaram) ; 4lient(o:creen (h,nd# ]point) ; (rac0CopupKenu (hKenu# (CK&U=Y?(IV((D;# point."# point.%# /# h,nd# ;VLL) ; return / ; case 8K&4DKKF;L7 s,itch (LD8DUL (,Caram)) { case =LK&6=LP&;P87 case =LK&6=LP&DCP;7 case =LK&6=LP&:F_P7 case =LK&6=LP&:F_P&F:7 case =LK&PL=(&V;LD7 case =LK&PL=(&4V(7
case =LK&PL=(&4DCG7 case =LK&PL=(&CF:(P7 case =LK&PL=(&4LPFU7 Kessa+eIeep (/) ; return / ; case case case case case =LK&IXY;L&8?=(P7 =LK&IXY;L&L(YUFG7 =LK&IXY;L&YUFG7 =LK&IXY;L&LXYUFG7 =LK&IXY;L&ILF4X7 22 ;ote7 Lo+ic !elo, 22 assumes that =LK&8?=(P 22 throu+h =LK&ILF4X are 22 consecutive num!ers in 22 the order sho,n here.
4hec0Kenu=tem (hKenu# i:election# K6&V;4?P4XPL) ; i:election ' LD8DUL (,Caram) ; 4hec0Kenu=tem (hKenu# i:election# K6&4?P4XPL) ; :et4lassLon+ (h,nd# Y4L&?IUIF4XYUDV;L# (LD;Y) Yet:toc0D!$ect (id4olor QLD8DUL (,Caram) 9 =LK&IXY;L&8?=(PR)) ; =nvalidateUect (h,nd# ;VLL# (UVP) ; return / ; case =LK&FCC&FIDV(7 Kessa+eIo" (h,nd# (PW( ("Copup Kenu Lemonstration Cro+ram\n") (PW( ("(c) 4harles Cet@old# 1SST")# s@Fpp;ame# KI&=4D;=;6DUKF(=D; ^ KI&DX) ; return / ; case =LK&FCC&PW=(7 :endKessa+e (h,nd# 8K&4LD:P# /# /) ; return / ; case =LK&FCC&?PLC7 Kessa+eIo" (h,nd# (PW( ("?elp not %et implementedO")# s@Fpp;ame# KI&=4D;PW4LFKF(=D; ^ KI&DX) ; return / ; !rea0 ; case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ;
POPM0)*ARC 3e=cer-ts5
22Kicrosoft Leveloper :tudio +enerated resource script. #include "resource.h" #include "af"res.h"
222222222222222222222222222222222222222222222222222222222222222222222222 22222 22 Kenu CDCKP;V KP;V L=:4FULFILP IPY=; CDCVC "K%Kenu" IPY=; CDCVC "]6ile" IPY=; KP;V=(PK "];e,"# KP;V=(PK "]Dpen"# KP;V=(PK "]:ave"# KP;V=(PK ":ave ]Fs"# KP;V=(PK :PCFUF(DU KP;V=(PK "P]"it"# P;L CDCVC "]Pdit" IPY=; KP;V=(PK "]Vndo"# KP;V=(PK :PCFUF(DU KP;V=(PK "4u]t"# KP;V=(PK "]4op%"# KP;V=(PK "]Caste"# KP;V=(PK "Le]lete"# P;L CDCVC "]Iac0+round" IPY=; KP;V=(PK "]8hite"# 4?P4XPL KP;V=(PK "]Li+ht Yra%"# KP;V=(PK "]Yra%"# KP;V=(PK "]Lar0 Yra%"# KP;V=(PK "]Ilac0"# P;L CDCVC "]?elp" IPY=; KP;V=(PK "]?elp..."# KP;V=(PK "]F!out CopKenu..."# P;L P;L P;L
=LK&FCC&?PLC =LK&FCC&FIDV(
R0,O*RC0A' 3e=cer-ts5
22 Kicrosoft Leveloper :tudio +enerated include file. 22 Vsed !% CopKenu.rc #define #define #define #define #define #define =LK&6=LP&;P8 =LK&6=LP&DCP; =LK&6=LP&:F_P =LK&6=LP&:F_P&F: =LK&FCC&PW=( =LK&PL=(&V;LD H///1 H///2 H///H///H H///. H///M
#define =LK&PL=(&4V( H///1 #define =LK&PL=(&4DCG H///T #define =LK&PL=(&CF:(P H///S #define =LK&PL=(&4LPFU H//1/ #define =LK&IXY;L&8?=(P H//11 #define =LK&IXY;L&L(YUFG H//12 #define =LK&IXY;L&YUFG H//1#define =LK&IXY;L&LXYUFG H//1H #define =LK&IXY;L&ILF4X H//1. #define =LK&FCC&?PLC H//1M #define =LK&FCC&FIDV( H//11 The $%$&3N..8C resource scri"t de'ines a menu similar to the one in &3N.D3&%.8C. The di''erence is that the to":level menu contains only one itemSa "o"u" named I&y&enuI that invo es the /ile0 3dit0 1ac ground0 and -el" o"tions. These 'our o"tions !ill (e arranged on the "o"u" menu in a vertical list rather than on the main menu in a horiPontal list. During the #&9C835T3 message in &nd4roc0 $%$&3N. o(tains a handle to the 'irst "o"u" menuSthat is0 the "o"u" !ith the te4t I&y&enuI: hKenu ' LoadKenu (h=nst# s@Fpp;ame) ; hKenu ' Yet:u!Kenu (hKenu# /) ; During the #&981.TT%N.$ message0 $%$&3N. o(tains the "osition o' the mouse "ointer0 converts the "osition to screen coordinates0 and "asses the coordinates to .rac%4opupMenu: point." ' LD8DUL (lCaram) ; point.% ' ?=8DUL (lCaram) ; 4lient(o:creen (h,nd# ]point) ; (rac0CopupKenu (hKenu# (CK&U=Y?(IV((D;# point."# point.%# /# h,nd# ;VLL) ; #indo!s then dis"lays the "o"u" menu !ith the items /ile0 3dit0 1ac ground0 and -el". Selecting any o' these o"tions causes the nested "o"u" menus to a""ear to the right. The menu 'unctions the same as a normal menu. +' you !ant to use the same menu 'or the "rogram7s main menu and !ith the .rac%4opupMenu0 you7ll have a (it o' a "ro(lem (ecause the 'unction re)uires a "o"u" menu handle. 5 !or around is "rovided in the &icroso't Kno!ledge 1ase article +D @BB^FC.
POORM0)*AC
2399999999999999999999999999999999999999999 CDDUKP;V.4 99 (he Coor Cerson[s Kenu (c) 4harles Cet@old# 1SST 9999999999999999999999999999999999999999932
LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; static (4?FU s@Fpp;ameQR ' (PW( ("CoorKenu") ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { ?KP;V hKenu ; ?8;L h,nd ; K:Y ms+ ; 8;L4LF:: ,ndclass ; 8ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ; h,nd ' 4reate8indo, (s@Fpp;ame# (PW( ("(he Coor9Cerson[s Kenu")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; ?Kenu ' Yet:%stemKenu (h,nd# 6FL:P) ; FppendKenu FppendKenu FppendKenu FppendKenu Fdditions")) ; (hKenu# (hKenu# (hKenu# (hKenu# K6&:PCFUF(DU# /# K6&:(U=;Y# =LK&:G:&FIDV(# K6&:(U=;Y# =LK&:G:&?PLC# K6&:(U=;Y# =LK&:G:&UPKD_P# ;VLL) ; (PW( ("F!out...")) ; (PW( ("?elp...")) ; (PW( ("Uemove
:ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; 8hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ;
return ms+.,Caram ; LUP:VL( 4FLLIF4X 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK lCaram) { s,itch (messa+e) { case 8K&:G:4DKKF;L7 s,itch (LD8DUL (,Caram)) { case =LK&:G:&FIDV(7 Kessa+eIo" (h,nd# (PW( ("F Coor9Cerson[s Kenu Cro+ram\n") (PW( ("(c) 4harles Cet@old# 1SST")# s@Fpp;ame# KI&DX ^ KI&=4D;=;6DUKF(=D;) ; return / ; case =LK&:G:&?PLC7 Kessa+eIo" (h,nd# (PW( ("?elp not %et implementedO")# s@Fpp;ame# KI&DX ^ KI&=4D;PW4LFKF(=D;) ; return / ; case =LK&:G:&UPKD_P7 Yet:%stemKenu (h,nd# (UVP) ; return / ; !rea0 ; case 8K&LP:(UDG7 CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ; The three menu +Ds are de'ined near the to" o' $%%8&3N..C: #define =LK&FIDV( 1 #define =LK&?PLC 2 #define =LK&UPKD_P 5'ter the "rogram7s !indo! has (een created0 $%%8&3N. o(tains a handle to the system menu: hKenu ' Yet:%stemKenu (h,nd# 6FL:P) ; #hen you 'irst call 2et0#stemMenu0 you should set the second "arameter to /5,S3 in "re"aration 'or modi'ying the menu. The menu is altered !ith 'our /ppendMenu calls: FppendKenu (hKenu# K6&:PCFUF(DU# /# ;VLL) ; FppendKenu (hKenu# K6&:(U=;Y# =LK&:G:&FIDV(# (PW( ("F!out...")) ; FppendKenu (hKenu# K6&:(U=;Y# =LK&:G:&?PLC# (PW( ("?elp...")) ; FppendKenu (hKenu# K6&:(U=;Y# =LK&:G:&UPKD_P# (PW( ("Uemove Fdditions")); The 'irst /ppendMenu call adds the se"arator (ar. Choosing the 8emove 5dditions menu item causes $%%8&3N. to remove these additions0 !hich it accom"lishes sim"ly (y calling 2et0#stemMenu again !ith the second "arameter set to T8.3: Yet:%stemKenu (h,nd# (UVP) ; The standard system menu has the o"tions 8estore0 &ove0 SiPe0 &inimiPe0 &a4imiPe0 and Close. These generate #&9SNSC%&&5ND messages !ith w4aram e)ual to SC983ST%830 SC9&%V30 SC9S+X30 SC9&+N+&.&0 SC9&5A+&.&0 and SC9C,%S3. 5lthough #indo!s "rograms do not normally do so0 you can "rocess these messages yoursel' rather than "ass them on to 'ef&indow4roc. Nou can also disa(le or remove some o' these standard o"tions 'rom the system menu using methods descri(ed (elo!. The #indo!s documentation also includes
some standard additions to the system menu. These use the identi'iers SC9N3AT#+ND%#0 SC9$83V#+ND%#0 SC9VSC8%,,0 SC9-SC8%,,0 and SC95885N23. Nou might 'ind it a""ro"riate to add these commands to the system menu in some a""lications.
i6la+s ' YetKenu:tate (hKenu# id# i6la+) ; 5gain0 i!lag is either &/91NC%&&5ND or &/91N$%S+T+%N. The i!lags "arameter is a com(ination o' all the current 'lags. Nou can determine the current 'lags (y testing against the &/9D+S51,3D0 &/9285N3D0 &/9C-3CK3D0 &/9&3N.1835K0 &/9&3N.1581835K0 and &/9S3$585T%8 identi'iers. %r may(e (y this time you7re a little 'ed u" !ith menus. +n that case0 you7ll (e "leased to no! that i' you no longer need a menu in your "rogram0 you can destroy it: Lestro%Kenu (hKenu) ; This 'unction invalidates the menu handle.
)OPOP*P,AC
239999999999999999999999999999999999999999999999999 ;DCDCVC:.4 99 Lemonstrates ;o9Copup ;ested Kenu (c) 4harles Cet@old# 1SST 999999999999999999999999999999999999999999999999932 #include <,indo,s.h> #include "resource.h" LUP:VL( 4FLLIF4X 8ndCroc (?8;L# V=;(# 8CFUFK# LCFUFK) ; int 8=;FC= 8inKain (?=;:(F;4P h=nstance# ?=;:(F;4P hCrev=nstance# C:(U s@4mdLine# int i4md:ho,) { static (4?FU ?8;L K:Y 8;L4LF:: s@Fpp;ameQR ' (PW( (";oCopVps") ; h,nd ; ms+ ; ,ndclass ; ' ' ' ' ' ' ' ' ' ' 4:&?UPLUF8 ^ 4:&_UPLUF8 ; 8ndCroc ; / ; / ; h=nstance ; Load=con (;VLL# =L=&FCCL=4F(=D;) ; Load4ursor (;VLL# =L4&FUUD8) ; (?IUV:?) Yet:toc0D!$ect (8?=(P&IUV:?) ; ;VLL ; s@Fpp;ame ;
,ndclass.st%le ,ndclass.lpfn8ndCroc ,ndclass.c!4lsP"tra ,ndclass.c!8ndP"tra ,ndclass.h=nstance ,ndclass.h=con ,ndclass.h4ursor ,ndclass.h!rIac0+round ,ndclass.lps@Kenu;ame ,ndclass.lps@4lass;ame
if (OUe+ister4lass (],ndclass)) { Kessa+eIo" (;VLL# (PW( ("(his pro+ram re5uires 8indo,s ;(O")# s@Fpp;ame# KI&=4D;PUUDU) ; return / ;
h,nd ' 4reate8indo, (s@Fpp;ame# (PW( (";o9Copup ;ested Kenu Lemonstration")# 8:&D_PULFCCPL8=;LD8# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# 48&V:PLP6FVL(# ;VLL# ;VLL# h=nstance# ;VLL) ; :ho,8indo, (h,nd# i4md:ho,) ; Vpdate8indo, (h,nd) ; ,hile (YetKessa+e (]ms+# ;VLL# /# /)) { (ranslateKessa+e (]ms+) ; LispatchKessa+e (]ms+) ; return ms+.,Caram ; LUP:VL( 4FLLIF4X 8ndCroc (?8;L h,nd# V=;( messa+e# 8CFUFK ,Caram# LCFUFK lCaram) { static ?KP;V hKenuKain# hKenuPdit# hKenu6ile ; ?=;:(F;4P h=nstance ; s,itch (messa+e) { case 8K&4UPF(P7 h=nstance ' (?=;:(F;4P) Yet8indo,Lon+ (h,nd# Y8L&?=;:(F;4P) ; hKenuKain ' LoadKenu (h=nstance# (PW( ("KenuKain")) ; hKenu6ile ' LoadKenu (h=nstance# (PW( ("Kenu6ile")) ; hKenuPdit ' LoadKenu (h=nstance# (PW( ("KenuPdit")) ; :etKenu (h,nd# hKenuKain) ; return / ; case 8K&4DKKF;L7 s,itch (LD8DUL (,Caram)) { case =LK&KF=;7 :etKenu (h,nd# hKenuKain) ; return / ; case =LK&6=LP7 :etKenu (h,nd# hKenu6ile) ; return / ; case =LK&PL=(7 :etKenu (h,nd# hKenuPdit) ; return / ; case case case case =LK&6=LP&;P87 =LK&6=LP&DCP;7 =LK&6=LP&:F_P7 =LK&6=LP&:F_P&F:7
!rea0 ; case 8K&LP:(UDG7 :etKenu (h,nd# hKenuKain) ; Lestro%Kenu (hKenu6ile) ; Lestro%Kenu (hKenuPdit) ; CostJuitKessa+e (/) ; return / ; return Lef8indo,Croc (h,nd# messa+e# ,Caram# lCaram) ;
)OPOP*P,ARC 3e=cer-ts5
22Kicrosoft Leveloper :tudio +enerated resource script. #include "resource.h" #include "af"res.h" 222222222222222222222222222222222222222222222222222222222222222222222222 22222 22 Kenu KP;VKF=; KP;V L=:4FULFILP IPY=; KP;V=(PK "KF=;7"# KP;V=(PK "]6ile..."# KP;V=(PK "]Pdit..."# P;L KP;V6=LP KP;V L=:4FULFILP IPY=; KP;V=(PK "6=LP7"# KP;V=(PK "];e,"# KP;V=(PK "]Dpen..."# KP;V=(PK "]:ave"# KP;V=(PK ":ave ]Fs"# KP;V=(PK "(]Kain)"# P;L KP;VPL=( KP;V L=:4FULFILP IPY=; KP;V=(PK "PL=(7"# KP;V=(PK "]Vndo"# KP;V=(PK "4u]t"# KP;V=(PK "]4op%"# KP;V=(PK "]Caste"# KP;V=(PK "Le]lete"#
P;L
KP;V=(PK "(]Kain)"#
=LK&KF=;
R0,O*RC0A' 3e=cer-ts5
22 Kicrosoft Leveloper :tudio +enerated include file. 22 Vsed !% ;oCopups.rc #define =LK&6=LP H///1 #define =LK&PL=( H///2 #define =LK&6=LP&;P8 H///#define =LK&6=LP&DCP; H///H #define =LK&6=LP&:F_P H///. #define =LK&6=LP&:F_P&F: H///M #define =LK&KF=; H///1 #define =LK&PL=(&V;LD H///T #define =LK&PL=(&4V( H///S #define =LK&PL=(&4DCG H//1/ #define =LK&PL=(&CF:(P H//11 #define =LK&PL=(&4LPFU H//12 +n &icroso't Develo"er Studio0 you create three menus rather than one. Nou7ll (e selecting 8esource 'rom the +nsert menu three times. 3ach menu has a di''erent te4t name. #hen the !indo! "rocedure "rocesses the #&9C835T3 message0 #indo!s loads each menu resource into memory: hKenuKain ' LoadKenu (h=nstance# (PW( ("KenuKain")) ; hKenu6ile ' LoadKenu (h=nstance# (PW( ("Kenu6ile")) ; hKenuPdit ' LoadKenu (h=nstance# (PW( ("KenuPdit")) ; +nitially0 the "rogram dis"lays the main menu: :etKenu (h,nd# hKenuKain) ; The main menu lists the three o"tions using the character strings I&5+N:I0 I/ile...I0 and I3dit...I -o!ever0 I&5+N:I is disa(led0 so it doesn7t cause #&9C%&&5ND messages to (e sent to the !indo! "rocedure. The /ile and 3dit menus (egin I/+,3:I and I3D+T:I to identi'y these as su(menus. The last item in each menu is the character string I(&ain*IL this o"tion indicates a return to the main menu. S!itching among these three menus is sim"le: case 8K&4DKKF;L 7 s,itch (,Caram) { case =LK&KF=; 7 :etKenu (h,nd# hKenuKain) ; return / ; case =LK&6=LP 7 :etKenu (h,nd# hKenu6ile) ; return / ; case =LK&PL=( 7 :etKenu (h,nd# hKenuPdit) ; return / ; [other pro"ram lines] !rea0 ; During the #&9D3ST8%N message0 N%$%$.$S sets the "rogram7s menu to the &ain menu and destroys the /ile and 3dit menus !ith calls to 'estro#Menu. The &ain menu is destroyed automatically !hen the !indo! is destroyed.
FOR MFC
8e'er to IYYSo'9serverYD9DriveY3:1oo sY$rogramming:,anguagesY$rogramming #indo!s !ith &/C ;nd 3ditionY$rogm'c;.chmI
FOR COM
$l 8e'er: +nside %le 1oo availa(le in the ,i(rary %8 'rom &SDN 5nd IYYSo'9serverYD9DriveY3:1oo sY$rogramming:,anguagesYDesigning Com"onent:1ased 5""licationsY.ndercom.chmI