visual c++ alapok

Upload: erzsebet-toeroek-fazekasne

Post on 18-Jul-2015

367 views

Category:

Documents


2 download

TRANSCRIPT

C++ ALAPOK

Bevezetmet nem kvnom tlsgosan elnyjtani, gy sszegzem: mindenkpen szksgnk van az objektum-orientlt programozsra s annak C++ ill. Java beli megismersre -, mert fejlett versenykpes termkeket csak korszer fejleszt eszkzkkel hozhatunk ltre. Ugyanakkor ezek objektum-orientlt nyelvek nagy segtsget nyjtanak egy rugalmasan, sokkal racionlisabban kezelhet, ttekinthetbb program elksztshez. Mindenek eltt a DOS-os Borland C++-szal ismerkednk meg - csak a legszksgesebbeket annak ellenre, hogy a DOS mr abszolt elavult platform. Tekintettel vagyunk mindenkire s pr cikk lesz a Borland C++-rl, majd jhet a Java (cikkeink java, a Java nyelv-).

Elkszletek a C++ nyelv objektum-orientltsgnak bevezetsreAvagy ami az abC rovatbl eddig kimaradt: Default argumentumok vltoz hossz paramterlista Overloading Generikus fggvnyek S ezek utn tejles gzzel az objekumok P

Default argumentumokMikor, mire s, hogyan hasznljuk ? Plda: void open_window(int ax=1, int ay=1, int bx=80, int by=25) Az gy deklarlt fggvnyt az albbiak szerint hvhatjuk meg: Jellegt tekintve inicializlt fggvnyparamtereknek tekinthetek Ekkor a fggvny formlis paramter-hez/eihez default / alaprtelmezs szerinti rtkeket rendelnk A fggvny meghvsakor jobbrl balra elhagyhatk az aktulis paramterek kzl azok a paramterek melyekhez rendeltnk alaprtelmezsi rtket gy az elhagyott paramter rtke a default / alaprtelmezs szerinti rtk helyettestdik be

1. open_window(2, 2, 6, 6); //gy a (2,2)-(6,6) pontokon elhelyezked ablakot nyitunk 2. open_window(2, 2, 6); //gy a (2,2)-(6,25) pontok lesznek a sarkok, hisz az utols koordittelhagytuk

3. open_window(2, 2); //A (2,2)-(80,25) koordintj pontokon lesz az ablak sarka, hisz az utols 4. 5. 6.kt paramtert elhagyva a kperny bal als sarkba lesz illesztett az ablak. open_window(2); //Az elzek alapjn nylvn (2,1)-(80,25) a mretezs open_window(); //S vgl egy teljes kpernynyi ablak: (1,1)-(80,25) open_window(, 2, 6, 6); //FIGYELEM: ez az ELRETTENT plda hisz ROSSZ. CSAK balrl jobbra hagyhatk el a paramterek !

1

Vgl pr adalk a default argumentum fggvnyek felptshez: Adott default argumentumot csak akkor tudunk fellrni, ha az sszes eltte lv paramtert mr megadtuk. gy vagy az sszes paramtert vagy annak csak egy rszt inicializljuk.

Ezek alapjn a paramterlistt gy kell sszelltani: Hogy nem inicializlt paramterekkel kezddjn, s Praktikus a leggyakrabban fellrand paramtert a default paramterek elejre tenni. (Kzvetlenl a nem inicializlt paramterek utn.) Ezek ltal egyrtelm paramterlistt kell ltrehozni (hogy a fordt eldnthesse mely paramter hova kerl.)

Plda: void open_window(int ax, int ay, int bx=80, int by=25) EZ J ! void open_window(int ax=1, int ay, int bx, int by=25) EZ ROSSZ !

Vltoz hosszsg paramterlistaSokszor elfordul, hogy nem tudjuk a fggvnynk paramtereinek pontos szmt. Vegynk egy pldt. (az egyszersg kedvrt a fiskoln bevlt pldt taglalom) Nos: Van egy fggvnynk mely a paramterknt tadott szmokat adja ssze. De mennyi paramternk lesz ? 3 vagy 10 vagy 100 ? Ez teljesen lnyegtelen a tovbbiakban. Lssuk a C++ ltal biztostott s ignyelt feltteleket: Ha nem tudjuk vagy akarjuk megadni a fggvny paramtereinek pontos szmt vagy tpust (lsd mg generikus fggvnyek) akkor a tpus ellenrzs felfggeszthet a direktvval. Ezen direktva jelzi a fordtnak, hogy ezen helyre elre nem deklarlt mennyisg s tpus paramter kerl ill. kerlhet. A fordt felttele, hogy a eltt legalbb egy fix formlis paramternek kell lennie, melynek megadtuk nevt, s tpust.

Gondoljuk vgig ! Vajon olyan rdngs dolog ez ? A csudkat, hisz a paramtereket simn lenyomja a fordt a stack-be, onnan meg brmelyiket ki lehet a fggvnyen bell szedni, csak a tpust, az indext hogy hnyadik kell ismerni. Az index megadsa az egyszersg kedvrt az utols ismert fix paramter utn kezddik. Lssuk a pldt: Deklarci: int plusz(int szam, ) Hvsa: x = plusz(1, 2, 3, 4) x = plusz(0) x = plusz(3 ,2 ,1)

A hasznlata: A fggvnyek melyekkel a vltoz hosszsg paramterlistt kezelni tudjuk a STDARG.Hban vannak. Ezek:

2

va_list: Ez egy tpus mellyel az adott index paramterre mutathatunk, az-az argumentum pointer. Deklarlsa: va_list paremeter_ponter_neve; va_start(va_list ap, ua): Ez lltja be a fent deklarlt argumentum pointer (ap) rtkt az els nem definilt paramterre.Els paramtre az ap: a fent deklarlt argumentum pointer Msodik paramtere az ua: a eltt utoljra deklarlt fix paramter neve. A fenti pldban a szam az azonost nv. va_arg(va_list ap, tpus): A 2. paramterben megadott tpusban adja vissza a kvetkez paramtert. Vigyzat ha egy paramternek rossz tpust adunk meg, akkor hibs lesz az sszes tbbi paramter, hisz a stack-bl trtn visszaolvass elveszti byte-sorrendjt.Pl: va_arg(ap, int asd); va_end(va_list ap): a vltoz hosszsg paramterlistval rendelkez fggvnybl kilps eltt rendraks cljbl kell meghvni. (BP-SP pontos visszalltsa.)

#include #include #include int plusz(int, ...); void main() { int x=5,y=3,osszeg; clrscr(); osszeg = plusz(3, 10, x, y); printf("\n\n10+%d+%d=%d", x, y, osszeg); getch(); } //main int plusz(int db, ...) { int i, szam, s=0; va_list ap; //argumentum pointer va_start(ap,db); //ap amit inicializlunk, ill. a db az utols ismert fix paramter for (i=0;i Ktrtelm egyezs. Lsd lent. max(x6, y6); // nincs egyeztets, lsd lent.

o o

o

o

Az els hrom fggvny hvs egyszer, hisz tpusukban abszolt megegyeznek a paramterek. A negyedik mr cikisebb, mert nincs pont megfelel. gy megprblkozik a konverzival, ha sikeres s egyrtelm, akkor van megfelel szignatra, ha nem vagy tbbrtelm akkor hiba. Lssuk: lehet e float ? double konverzit vgezni. Ht persze ! gy van megfelel szignatra. Az tdiknl is az az eset ll fent, hogy nincs pont megfelel szignatra, de megprblunk konverzival jt keresni. Az sszes szignatrt megprbljuk a mi 5. paramterlistnkra konverzival rhzni.Aktulis paramterlista a tpusokat tekintve: max(int, long); Ezt konverzival az (1)-bl s (2)-bl is elllthatjuk, hisz int ? long, ill. long ? int konverzi azonos prioritssal rendelkezik, gy ktrtelm egyeztets: Ambiguity between 'max(int, int)' and 'max(long, long)' in function main(). Utols hatodik esetben: nem tallt a fordt konverzi utn sem megfelel szignatrt, gy: Could not find match for max(int*, int*).

Overloading s rvnyessgi kr: Plda: extern void print(char*) extern void print(double); void main() { Az adott nvhez tartoz fggvnyhalmaz deklarlst ugyanazon hatskrrel kell elvgezni. A loklisnak deklarlt fggvny eltakarja s nem tdefinilja a globlis fggvnyvltozatot.

5

extern void print(int); print(3); print("=X"); //? Could not find match for print(char *) } Amint lthatjuk a loklis print(int) eltakarja a modulra-globlis print(char*)-t gy nem tudjuk az utols sorban kirni a string-et.

A fggvnyek kirlya: Generikus fggvnyekMint megszoktuk, a magas szint programozsi nyelvekben az eljrsok paramtereinek meg kell adni a tpust. Ha ugyanazt az eljrst klnbz tpus paramterekre akarjuk meghvni, de maga az eljrs algoritmusa ugyanaz akkor eddig el kellet ksztennk minden tpusra ugyanazt az eljrst. gy minden eljrs ugyanaz volt, csak a paramterek, ill. esetleg a bels vltozk tpusban klnbzik. Pl. a matematikai mvelet eljrsoknl, vagy maximum / minimum meghatrozsnl, rendezsnl lehet ilyen problmnk. Ezt a sok kellemetlensget a C++-ban el lehet kerlni, s nem kell minden tpusra az egyszer megrt rutint tirogatni. A paramterek tpust is paramterknt kell tadni, gy a rutin majd az tadott tpussal fog dolgozni. A tpussal is paramterezett fggvnyeket generikus fggvnyeknek nevezzk. Az elzek alapjn nem overloading-gal fogjuk megoldani (az-az nem definilunk x klnbz tpussal x klnbz fggvnyt), hanem csak egy fggvnyt deklarlunk. Ezen fggvnyt sablonnak nevezzk, mert a paramternek nincs tpusa, mert a tpust is paramterknt adjuk t. Sablon definilsa: Sablont csak globlisan lehet definilni: template deklarci Az argumentumlista egy elemt a class kulcsszval azonostjuk: class azonost Plda: template T max(T a, T b) { return( a > b ) ? a : b; } A pldban egy paramterknt tadand tpust definilunk melyet T azonostval ltunk el, s ezt adjuk t paramterknt. Ezutn ezt a T tpust brhol hasznlhatjuk: brmely paramter tpusaknt, vagy a fggvny visszatrsi tpusaknt, vagy a fggvnyben loklis vltoz deklarcijakor annak tpusaknt. De hogyan jn ltre a trgykd ? A fordt a meghvsnak, a fggvny paramternek tpusnak megfelelen generlja a megfelel fggvnyt. Mi az sszefggs a generikus s overloading fggvnyek kztt ?

6

Ha van olyan overloading fggvny mely szignatrjnak pontosan megfelel az aktulis paramterlista akkor azt hvja meg, Ha nincs, akkor alkalmazza a sablont. De elkpzelhet, hogy gy sem lesz megfelel fggvny, gondoljunk az egyik overloading pldra: max(int, long); //Hibazenet: nincs egezs a max(int, long) paramterlistra. Could not find a match for max(int, long).

Nzznk egy utols pldt melyben tbb paramter van, gy a paramterek egymstl is klnbz tpusak lehetnek. Egy egyszer szorzs: template T szoroz(S x, T y) { return y*x; } Hogy a flrertst elkerljk, egy tnyleg utols plda melyben felhasznljuk a paramterknt tadott tpust loklis vltoz deklarcijra: template void csere(S *x, S *y) { S temp; temp=*x; *x=y; *y=temp; }

s vgre: Objektum orientlt programozs C++-banNos vgre elrkeztnk az objektumok trgyalshoz C++-ban. Nem kvnom az elmleti alapokat jra ttrgyalni, ugyanis az OOP rovat els szmaiban ezt megtettem. Most csak a C++ specifikus tmkat trgyaljuk t. Ezen cikkeimhez fsikolai jegyzeteimet is felhasznlom, melyhez ksznetet mondok Blintn Farkas Judit tanrnnek (JPTE-PMMK-Minf). Az objektum orientlt programozs (OOP) a 90-es vek uralkod stlusirnyzata, s egyre inkbb felvltja a - lassan mr elavultt vl, de ugyanakkor mg klasszikusnak is szmt strukturlt programozst. Az objektum-orientlt programozs jobban megkzelti, utnozza a valsgot, s jobban igazodik a trgyakhoz. Minden valsgos trgyat nemcsak alakja, elhelyezkedse jellemez, (Teht nem csak a r jellemz adatok mretek -.) hanem az is, hogyan viselkednek bizonyos krlmnyek kztt. gy a trgyakat minden jellemzivel egytt komplex egszknt tekintjk. (Az-az, az objektum az adatok s jellemzjk komplexe, elvlaszthatatlan egsze.) Amikor egy objektumot deklarlunk, akkor rjuk le szerkezett a mezkkel, msrszt azokat a szubrutinokat, amelyek lerjk az objektum viselkedst. gy az OOP-s nyelv: Sokkal modulrisabb, absztraktabb, strukturltabb,

az ltalnos strukturlt nyelveknl.

7

Ahogy az OOP rovat elejn is elmondtam, egy objektum orientlt nyelvnek hrom f jellemzje van: Egysgbezrs: az adat s kd egysge (encapsulation) rkls: a meglv osztlyokbl jabbak szrmaztathatak (inheritance) Tbbrtsg polimorfizmus (polymorphism) (ezt az OOP rovat elejn kt kln tmakrbe soroltuk) Egysgbezrs: Az adatokat s az adatokat kezel fggvnyeket (vagy Pascal terminolgia szerint metdusokat) egysgknt kezeljk mghozz gy, hogy a klvilg szmra kzmbs adat kd rszeket elzrjuk. gy megvalsul az adatrejts elve is. Az gy kapott egysgeket objektumnak nevezzk. C++-ban az objektumoknak megfelel trolsi egysg tpusa a class (osztly). (Megjegyeznm, hogy a struct trolsi egysg is ellthat hasonl funkcikat, mert lehetsg van a mezk mellett, metdusok elhelyezsre is. A class ill. record tpusok kztt csak az adatok kd elrsben van klnbsg.) rkls: Meglv osztlyokbl j osztlyok szrmaztathatak. A szrmaztatott j osztly rkli sei (a szrmaztatott s, ill. annak sei) sszes adat ill. metduskszlett. (Ez persze egyltaln nem azt jelenti, hogy el is rheti.) Az rklt mezket az j osztly t is definilhatja, vagy teljesen jakat is definilhat. Ezltal alakul ki az objektumok hierarchija. Polimorfizmus: Egy metdus azonostja tbbszr is elfordulhat az osztlyhierarchin bell ilyenkor, ha mr ltezik valamelyik sben, akkor az rklt metdust pontatlanul mondva fellbrljuk, az-az az azonos nev metdus specifikus lesz ebben, az j objektumban s annak utdaiban is. Virtulis metdusok alkalmazsval lehetsgnk nylik arra, hogy egy metdus konkrt vgrehajtsi mdja csak futs kzben dljn el. (Az-az a virtulisnak deklarlt metdus az adott objektum minden metdusban elsdleges lesz annak ellenre, hogy nem rtuk fell minden az eld metdust hasznl helyen. Ez a futs idben trtn metdus kivlaszts.)

Lssuk a C++-ban az objektum definilst: Amint fent emltettem a struct trolsi osztly is ellthat hasonl funkcit, a klnbsg a sszetevk (mezk s metdusok) alaprtelmezs szerinti elrsben van:Az albbi elrsi szintek vannak: public publikus elrhet ezen objektumbl s seibl is private privt kvlrl soha nem rhet el, s az utd objektumbl se protected vdett hasonl a privthoz, de az utd objektumbl elrhet struct:alaprtelmezs: minden mez s metdus publikus class:alaprtelmezs: minden mez s metdus privt

Ezek utn neknk kell az objektum definilsakor az adott mezk s metdusok elrsi szintjt. Az OOP elmlete szerint minden adat meznek privtnak kell lennie, hogy megvalsuljon az adatrejts elve, tovbb kell lenni publikus metdusoknak melyek az elz adat mezkn mveletet vgeznek. Az objektum bels metdusai melyeket csak az objektum hasznl privtnak kell lennik, hisz nem kvnatos a kvlrl trtn meghvs. Kvetkez szmunkban az objektumok rklsvel, konstruktorokkal s egyb szpsgekkel foglalkozunk. Ha valakinek brminem krdse lenne az elhangzottakkal kapcsolatban btran rjon az albbi eMail cmre:

OBJEKTUMOKrkls Konstruktorok C++-banrkls

8

A Pascal-ban megismertek szerint a rgi osztlyokbl jak szrmaztathatk. (St C++-ban egy osztlynak kt szlje is lehet.) A szrmaztatott j (utd) osztly rkli az se minden ltez adat s metdusmezit. (angol terminolgia szerint data-, s method- member; adat-, s metdus- tagok) Az j osztly az rklt metdusokat fell is brlhatja a polimorfizmus eredmnye kpen. Nylvn az j osztly eldeihez kpest ill. hasonlan j mezket is definilhat. C++-ban az objektum orientltsg ltal kialakthatunk egy egyrtelm objektum hierarchit, de nem vagyunk erre rszortva. Ez csak a j beltsunkon mlik. Az objektumok minden kpen valamilyen hierarchikus felptst fognak kvetni de lehet, hogy tbb egymstl fggetlen hierarchia is ltezhet, ami nylvn ellentmond az OOP elmletnek. Vegynk egy pldt: mivel nem vagyunk rszortva, hogy egy minden objektumnak egy vgs, a hierarchia tetejn ll se legyen (mint a Java-ban) gy azt a hatst rjk el, amit mr emltettem: C++-ban: fastruktrk erdejt kaphatjuk, Java-ban pedig egy, jlszervezett fastruktrt. Egy objektum struktra felptse annyibl ll, hogy egy rendszertan (~logika) alapjn ptnk a valsgot megkzelt objektumokat, alias a valsg modelljt. A kezdet az egy kzs stl (~a hierarchia gykere) illik, hogy szrmazzk. Ezen alacsony szinten alig van meghatrozott tulajdonsg. (Annyi fix, hogy objektum, s ltre lehet hozni ill. felszabadtani. Java-ban mg ennl is kevesebb.) Nos egy szinttel lejjebb, mr kezd specializldni a meghatrozs, ugyanis kezd valami konkrt feladat rsz megoldsa lenni, s ugye ehhez j ismeretek szksgesek. Ezen a szinten szoks az absztrakt objektumokat elkszteni, melyek nem mkd objektumok csak a kinzetet, a tulajdonsgokat definiljk. Ezeket Pascal-ben absztrakt objektumoknak nevezzk, C++-ban elvileg protokollnak, s Java-ban interface-nek. Termszetesen a Java-ban valsul meg az eredeti koncepci. A kvetkez szint az OOP elmletet kvetve akr mr konkrt feladatt ellt objektum is lehet. Ez mr szmos specilis tulajdonsggal, s persze a megvalstssal is rendelkezik. Nzznk egy biolgiai pldt:

s lehetne a vgtelensgig folytatni ... Hogy mirt nem neveztem meg az llnyek st ? Rszint nem akarok teolgiai vagy filozfiai vitba szllni senkivel de az biztos, hogy mint minden objektumnak az llnyeknek is van valami (valaki) se akitl ill. ahonnan szrmaztatni lehet, hisz: vilgegyetemnkben minden ok, okozati sszefggsben van. Ki van zrva, hogy valami csak gy magtl legyen. (Ennyit mr a blcsessg szeretetbl, ugyanis a filozfia, mint sz ennyit jelent.) Ha egy tulajdonsgot definiltunk az objektum hierarchia egy tagjban akkor az, az sszes alatta lvben jelen lesz. A tulajdonsg, a jellemz, mint olyan nem tntethet el, de rtelmezse a tulajdonsgot megtestest defincit megvltoztathatjuk. Pl. az llnyeknek van kltakarjuk. A

9

majomnak hmszvete s szre van. (Mivel lltlag az ember valahogy a majomtl szrmaztathat. Legalbb is a tudomny mai llsa szerint:) Ha az ember a majomtl szrmazik akkor neki is szre van. ? Ht igen elg cikis lenne, ha nem vltoztathatnnk meg ezt a tulajdonsgot, hisz hibs lenne az OOP elmlete. Teht ember ill. leszrmazottai esetn a kltakar legyen csak hmszvet. (az szrt a majomhoz kpest elhanyagolhatjuk) A tulajdonsg nem tnt el, csak mdosult. (Elg furcsn nznnk ki kltakar nlkl J ) Nzzk ezt az OOP nyelvn: Ha D osztly leszrmazottja B-nek, B | D Akkor D-t (le)szrmaztatott osztlynak (angol terminolgi szerint derived class) nevezzk. Ugyanakkor B-t snek (B-t a D, ill. annak utdai bizonyos fok snek), alaposztlynak (angol terminolgia szerint base class) nevezzk. Ha csak eggyel vissza ill. elre tekintnk az objektum hierarchiban akkor az els rend utdot kzvetlen leszrmazottnak (ang. term.: immediate descendants) nevezzk, mg ez a kzvetlen snek (immediate ancestor) a hierarchia pont eggyel feljebbi tagjt nevezi. Amint mr emltettem C++-ban (s szinte sehol ms nyelvben) a szrmaztatott osztly nem csak egy stl rklhet. Amikor a szrmaztatott tpus tbb stpusbl kerl levezetsre akkor tbbszrs rklsrl (ang. term.: multiple inheritance) beszlnk. Objektum orientlt programtervezs (hasonlan a modulris strukturlt tervezshez) a hierarchia megfelel kialaktsbl ill. a hierarchia egyes osztlyainak tulajdonsgainak definilsbl ll. A tervezs els lpse, hogy tudjuk mit is akarunk csinlni. Ekkor kiderl milyen osztlyok is kellenek. Ezeket a megfelel szempontok alapjn kell hierarchiba tmrteni. A hierarchit gy kell felpteni, hogy az egymstl csak kicsit eltr tagokat ne kln-kln definiljuk, hanem ezeknek egy kzs st hozzunk ltre. A kis klnbsgeket szrmaztats utn korrigljuk. gy ttekinthetbb, megbzhatbb kdunk van. (s az a kzs s is, jl jhet mg ksbb.)

Plda

a

hierarchia

felptsre

A plda tlete nem az enym, mr ezer helyen lttam, n most fiskolai jegyzetembl veszem. [1] Grafikus rendszert terveznk A grafikus elemeket (grafikus objektumokat) ki kell tudnunk rajzolni, Mozgatni kell, Trlni, Nagytani, kicsinyteni.

Lssuk a hierarchit: PONT | KR | NGYZET A hierarchia megtervezse PONT: j tagok: x, y

utn

az

egyes

osztlyok

tulajdonsgait

kell

megadnunk:

KR: rklt tagok: x, y

NGYZET: rklt tagok: x, y, r

10

rajz trls mozgats

rajz trls mozgats

j tagok: r nagyts kicsinyts

j tag:

rajz trls mozgats nagyts kicsinyts

a

A fent emltett mdon lehet egy absztrakt osztlyt definilni, pl. csak a koordintknak. (Ez persze nem klasszikus rtelemben vett absztrakt definci. Csak egy koordinta objektum. Mint Pascal-ban a TPoint objektum (mert nem csak TPoint rekord, hanem objektum is van.). Ezt az albbi mdon definiljuk: KOORDINTA | PONT | ... (a tbbi ugyanaz) Bevezethetnk a PONT osztlyba egy olyan boolean mezt mely megadja, vajon ltszik e a pont a kpernyn. Lssuk az objektum definilst, de a PONT osztlyt vesszk kzs sl: enum struct private: }; Nos me egy osztly konkrt deklarcija. Ahhoz, hogy ilyen tpus objektumot hozzunk ltre az albbi parancs szksgeltetik: struct pont p, *ptr; //C-ben a megads pont p, *ptr; //C++-ban a megads Ezek utn csak a C++-t vesszk alapul. Lthattuk a private kulcsszt amit mr elz szmunkban kivesztnk. Ez annyit tesz, hogy megvltoztattuk az objektum (struktra) minden tagjnak (itt mezjnek) hozzfrsi krs, s publikusrl (ami az alap struct esetn) privtra, hogy teljesljn az adatrejts elve. Ahhoz, hogy az mr deklarlt adatokat el is rhessk metdusokat kell deklarli. (metdus fggvnymez) Metdusnak nevezzk az osztly defincin bell deklarlt fggvnyt (fggvnymezt). E defincira kt md knlkozik: A definci az osztlydefinciban van implicite. Az osztlydefincin bell csak a deklarci van, s e trzsn kvl definiljuk, az-az kvl valstjuk meg. BOOLEAN pont int BOOLEAN x, {FALSE, TRUE}; { y; lathato;

Az x koordintt pl. a getx() metdussal krdezzk le.

11

Plda az implicit inline metdusra: struct private: int BOOLEAN public: int }; getx() { return x;} pont x, { y; lathato;

A msodik megolds: struct private: int BOOLEAN public: int }; int { return } getx(); pont::getx() x; pont x, { y; lathato;

Lthatjuk jelentsen eltr a kt definci md. A msodiknl ha osztlydefincin kvl kvnjuk definilni az adott metdus trzst akkor az albbi formula szerint kell a metdust kifejtennk: visszaadott_rtk_tpusa osztly_tpusnv::metdusnv(paramter_lista) { //parancsok } A visszaadott rtk tpust mr az osztlydefincinl is megadtuk, ugyanannak kell lennie. Az osztly tpus nv, melynek metdust kvnom definilni A metdus nv az adott metdus neve, s a paramter lista pedig az adott metdus paramter listja Aha: hogy mi az a dupla kettspont ? :: ez a hatskr definil opertor (ang. term: scope resolution operator.) Olyan, mint a struktra pontja, vagy Pascal-ban a pont.

Ha az osztlyok kvlrl akarjuk elrni akkor viszont a pont (.) vagy ? a megfelel opertor. Pl.: objektumnv.metdusnv(aktulis objektumnv? metdusnv(aktulis paramterek) paramterek)

Konstruktorok - destruktorok Eme rejtelmes szavak elegye nem egyebet tesz, mint az objektumok problmamentes inicializlst, ugyanis ltalnos problma az objektumok knnyed ltrehozsa ill. kezdrtkekkel val feltltse. Inicializljunk egy PONT objektumot. Ezt kt fle kpen tehetjk meg.

12

Vagy ezzel a favg mdszerrel (ami a fenti pldaprogramra nem is mkdik, hisz privtnak deklarltuk az adat mezket): egypont.x egypont.y egypont.lathato = FALSE; = = 3; 4;

Nos a mr kicsit haladbb programoz mr hasznlja az eszt, s egy rutinnal egyszerre az sszes adatot inicializlja. (persze ez csak a sima strukturlt programra igaz ahol mg nincs objektum) void init(pont *p, int ax, int ay) { p? p? p? } Ennek a rutinnak a meghvsa: pont init(&kp, 12, 40); kp; x=ax; y=ay; lathato=FALSE;

S vgl a nyer: a hasznlatos, szabvnyos inicializls objektumok esetn a konstruktornak nevezett metdussal trtnik. Ez nem csak a vltozk kezdrtkt lltja be, hanem mst is.: Az objektum felptst (VMT) Memria allokcijt Inicializcit A konstruktort vagy a felhasznl definilja, vagy ennek hinyban a fordt generl egy alaprtelmezs szerintit automatikusan.

Felettbb fontos, hogy a konstruktor neve mindig az osztly nevvel egyezik meg. Ebbl kvetkezen csak egy fajta konstruktora lehet egy objektumnak, de az overloading itt is megengedett. A megszokott mdon az aktulis paramterlista dnti el melyik paramterszignatrt alkalmazza a fordt. A konstruktornak nincs visszaadott rtke. (nem kell kirni semmit, mg a void-ot se.) A konstruktort kt fle kpen definilhatjuk:

Lssuk:

Osztlyon bell inline Ill. osztlyon kvli definci, amikor az osztlyon bell csak a prototpust definiljuk

struct int

pont x, BOOLEAN Pont(int,

{ y; lathato; int); int ay) lathato=FALSE;

}; pont::pont(int { x=ax; } Hvsa:

ax, y=ay;

13

Mivel paramterek is vannak a konstruktorban (ill. csak olyan konstruktorunk van ami paramterrel rendelkezik), ezrt a deklarci sorn az aktulis paramtereket is meg kell adni: pont p(3, 4); Hibs ebben az esetben ez a definci: pont q; Hibazenet: Couldnt find match for pont::pont() Ez persze kikszblhet az elz szmban emltett default argumentumok hasznlatval: pont::pont(int { x=ax; } gy mr hasznlhatjuk ez albbi defincik kzl brmelyiket: pont p(3, 4), q; ax=0, y=ay; int ay=0) lathato=FALSE;

Destruktor Mire j ? Pl.: pont::~pont( { argumentumok ) // utastsok } Nos ennyi eme metdusokrl, lssunk egy olyan tmt amirl mr beszltnk de rdemes sszefoglalni: Mezhozzfrs Szablyok: Az objektum felptst hatrozza meg. Akkor hvdik meg, ha meg akarjuk szntetni az objektumot. Hasonlan definiljuk a konstrukturhoz, ill. ha nem definilunk akkor automatikusan generl egyet a C++. A destruktor neve eltt prefixumknt a tilde jel: ~ ll, hogy megklnbztesse a konstruktortl.

1. Minden adatmezt el kell rejteni, az-az privtnak vagy protected-nek kell definilni. 2. Ltre kell hozni az adatmezk (csak annak amelyiknek szksges) kls elrst biztost 3. 4.metdusokat, melyeket lvn kvlrl el akarunk rni publikusnak definilunk. Az osztly tulajdonsgt alkot metdusokat melyeket kvlrl kell elrni azokat public-nak definiljuk Tovbb lteznek olyan metdusok is melyek csak az osztly bels mkdst segtik el, ezeket specifikussguktl fggen: privt, ill. protecteed-nek kell definilni.

Emlkeztetl, hogy melyik kulcssz mit is jelent: Pritate privt: Ezen mezket metdusokat (tagokat) csak az osztlyon belli metdusok rhetik el.

14

Protected vdett: Az gy deklarlt tagokat nem csak ezen osztlyon, hanem leszrmazott osztlyain bell is el lehet rni. (Ez egy szp jts a Pascal-lal szemben.) Public A tagok brhonnan, korltozs nlkl elrhetek. publikus:

Amit mg, mg egyszer elmondok, hogy a struc-tknt definilt objektumok tagjai alaprtelmezs szerint mind publikusak, mg a class-knt definiltak pedig mind privtak. gy mind a kt deklarcinl kell hozzfrst vltoztatni. A hozzfrs hatskrt gy kell felfogni, hogy azok a kulcsszavaktl, kulcsszavakig tartanak. Teht a struct elejn elkpzelhetjk a public-ot, ami addig tart mg fell nem brljuk.

A mezhozzfrs s rkls Lvn, hogy egyik osztlybl jat szrmaztathatunk rdemes elmondani az rkls menett: class D: hozzfrs-mdost struct D: hozzfrs-mdost ahol, D a szrmaztatott osztly az utd, s a B az s. Hozzfrs-mdost: Lehet public vagy private. Nem szksges megadni, de rdemes a gubanc elkerlse vgett, ugyanis a struct-ban publikus, mg a class-ban privt az alaprtelmezs szerinti hozzfrs-mdost. (Fontos megjegyezni, hogy csak szigortani, - s nem laztani - lehet egy tag hozzfrst. gy: Private Az s sszes protected, s public mezje privt lesz. Public Az s sszes mezje vltozathal marad, a hozzfrs nem vltozik. Javasolt mezhozzfrs: Adatmez protected (hisz az utdnak igen, de a klvilgnak nem szabad elrnie) Metdus public (mr amelyiket kvlrl el kell rni) Metdus bels hasznlatra a specifikussg mrtkben vagy protected esetleg privt. Szrmaztats public-knt. hozzfrs-mdost: B B {...}; {...};

hozzfrs-mdost:

Nos ezzel hla Istennek ki is vgeztk az OOP rovatot. Ezek utn javaslom a Java rovatot, hiszen csak azrt kontrkodtunk a C++-os OOP-be, hogy knnyebben menjen Java-ban. Persze ha brkinek krdse van btran rjon.

R4s

[1]: Ksznetet mondok fiskolai tanromnak (JPTE-PMMFK-Minf), Blintn Farkas Judit tanrnnek a felhasznlt irodalomrt jegyzetrt pldkrt, s segtsgrt. Ksznm !!!

15

VISUAL C ALAPOK

Akkor kezdjk egy kis elrettentssel: A Visual C windows-os programozsra val, ezen tulajdonsgnl fogva pedig erssen tmaszkodik az objektumorientlt programozsra. Aki nem jratos az objektumokban C-ben annak ajnlom az obkektumorientlt programozs C-ben (vagy valami ilyesmi) cm rovatunkat. Nzzk, eszik-e, vagy isszk. A C++ gpfggetlen volta, s windowsos programozsban val j hasznlhatsga miatt gyorsan elterjedt. A Visual C++ -t a Microsoft tallta ki a windows-os programozs megknnytsre. A Visual Basic utn dobta ki. A clja ugyanaz volt vele, a programozt megkmlni az automatizlhat felesleges rabszolgamunktl, kevert nyelven is programozhat grafikus fejleszti felletet ltrehozni, meggyorstani a programfejlesztst. (s mellkesen, hogy minl tbb program rdjon a windows al). A Visual C++a programfejleszts sorn felmerl egyes feladatok megoldshoz klnll eszkzcsoportokat ajnl fel, amik ltalban igen hasznosak. Szval itt mr nem arrl van sz, hogy az ember lel, megrja a programot, aztn lefordtja. Hanem, az ember lel, a gp megrja a program vzt (nem vicc!) , aztn miutn a programoz megrta a program lnyegt, le lehet fordtani. A program vza alatt az alapvet header file-ok, Cpp file-ok, s az objektumrendszer alapja rtend. Ennyit az elmletrl. Ugorjunk egyet a mlyvzbe. Kezdjnk el egy programot. Egy projectet (mert itt mr rg nem egy-egy programfjlrl van sz) a file menu new parancsval tudunk kezdeni. Lehet vlasztani kln file, project, workspace, vagy ms dokumentum. Klnll fileokat ebben a programnyelvben nem nagyon van rtelme rogatni, kezdjk a project-el. Ht van egy pr fajta. Attl fggen, milyen rszeket istallltunk, s milyen verzij a Viusual -C. a legfontosabbak: Win32 Application application Csak Windows alatt fut, a teljes grafikus felletet az API funkcikkal kihasznl projectek hozhatk ltre. Win32 Dynamic-Link Library Windows alatt fut programok ltal futs sorn meghvhat DLL llomnyok ltrehozsra val projectek Win32 Static Library Sajt knyvtrllomny (LIB file) ltrehozsra alkalmas llomnyok ltrehozsra alkalmas projectek. A projektlistn szerepl llomnyokbl linkelt OBJ file-ok egy LIB-be gyjtse. MFC AppWizard (exe) A Microsoft Foundation Classes hasznlatval egy project ltrehozsnak els lpseknt a program felptshez szksges minden llomnyt tartalmaz Visual Workbench kompatibilis llomnykszletet hoz ltre, s azokbl egy azonnal futtathat projektet kszt. MFC AppWizard (dll) A Microsoft Foundation Classes hasznlatval ltrehoz egy projectet minden llomnyval egytt, DLL-re fordthat.

16

ATL COM AppWizard ATL projectet hoz ltre objektumok nlkl, azokat neknk kell betenni a Classwiev-bl a New ATL Object paranccsal. Az MFC-t is hasznlhatjuk.

Custom AppWizard Egynileg llthat minta szerint kszt projectet. Vlaszthatjuk alapul a MFC AppWizard-ot, egy mr meglv projectet, vagy magunk belltgathatunk mindent Azn mg sorolhatnm. Ezekkel profibbnl profibb dolgokat lehet sszehozni, de vlasszuk a legegyszerbbet. Azaz, MFC AppWizard (exe). Ezzel a cuccal 4 lpsbl lehet projectet csinlni. Kezdjk. Elszr is vlasszuk ki a listrl, s rjuk be a megfelel helyre a project nevt. Aztn jn a 4 lps. Vlaszthatunk, Single document, Multiple Document, s Dialog Based. A legegyszerbb a Dialog Based. Legyen Ez. Itt mr tbb minden van. About box Legyen-e about Context-sesitive Help Minden menponthoz lehet Helpet rendelni 3D controls Valami ilyesmi, ha be van kapcsolva:

Automation Lehetv teszi ms programok objaktumainak elrst ActiveX ActiveX vezrls Windows Sockets A TCP/IP-hez kell Itt mr minden rthet. Megkrdezi, akarunk-e commenteket, az elre elksztett file-okban. Akarjunk. s mg egy fontos dolog. shared DLL futsidben rendeli hozz a knyvtri fggvnyeket. (takarkosabb) staticaly linked library Fordtsidben teszi meg. (hossz lesz az exe) Befejez lpsknt megmutatja, milyen class-okat hozott ltre, milyen nven, milyen file-ban.

Miutn megnyomtuk a finish-t, kapunk mg egy utols ttekintst a belltsokrl, majd az OK megnyomsval hozza ltre az Application Wizard a projectet, mindenestl. Az albbi file-ok mindig ltrehozsra kerlnek:

projetnv.clw

Ezt az llomnyt a ClassWizard hasznlja. Meglv osztlyok szerkesztshez, jak beillesztshez. Ez a project erforrsllomnya, az alapbellts menmeghatrozsait, az alapbellts about mezjt s tartalmazza az ikonllomny nevt.(ez ltalban res/projectnv.ico) A projecthez tartoz fejlcllomny

projectnv.rc resource.h

projectnv.dsp Maga a project file projectnv.dsw Workspace file Az gy ltrehozott project azonnal lefordthat (build/build projectnv.exe), s elindthat (build/execute projectnv.exe). Azrt gy kapsbl mg ne indtsuk el, nzznk kicsit szt a kpernyn. Nagyon fontos a workspace

17

window. Knnyen meg lehet tallni, ha ltrehozunk egy projectet, ez lesz az egyetlen ablak a kpernyn. gy nz ki:

Ngy fle bellts leehtsges. ClassView (a kpen), ekkor az objektumok szerkezett, s egymshoz val kapcsolatukat lehet nagyon jl ttekinteni. Brmelyik sorra rkattintva Megnyitja az llomnyt, amiben az objektum / member megtallhat (ltalban minden objektum sajt file-ban van) , s kapsbl rpozcionl. Most mg ne nagyon szerkezgessnk bele, nem biztos, hogy jl sl el. Mindenesetre mly megdbbenssel vegyk tudomsul , hogy ugyan mg egy bett nem programoztunk, mgis megvan a programunk, minden alapvet file-al s objektummal. ResourceView, ekkor az erforrsok szerkezett nzhetjk meg. Ez a projectnv.rc file. Amint lthatjuk, Itt van eltrolva az sszes ablak adata (hol van mekkora, holvan rajta gomb, stb...), az iconfile neve, karaktertbla, s a Version Info. Brmelyikre rkkattintunk, eljn egy megfel szerkesztprogram, s mris trajzolhatjuk az icon-t/ trakhatjuk a gombokat, s ami szem-szjnak ingere. FileView, itt a programunk file-jait klnbz csoportokra osztva ltjuk. Termszetesen brmelyikre kattintva, rgtn szerkeszthetjk is. InfoView, itt mindenrl informcit kaphatunk, elg hatkony help. Ezen kvl mg sokminden van a kpernyn, de ezeket rrnk ksbb. A men, meg a kis ikonok gyis magtl rtetdek. Na, miutn ezzel megvagyunk, akr csinlhatnnk is valamit. Menjnk a ResourceView-ra, s szerkezgessk meg a Dialog-okat. Dupla kattints a szerkeszteni hajtott adatra, s mris itt van egy szerkeszt.

18

Itt aztn brki kedvre eljtszhat. Minden objektum kln-kln kijellhet, mozgathat, szthzhat, trhat, trlhet, beszrhat... Szval minden ami kell. Ha jobb gombot nyomunk egy objektumra, eljn egy men, ahol nagyon sok fontos dolgot lehet csinlni. Msolni, kivgni, beilleszteni, kezelfggvnyt rendelni hozz. (Event handler) Egyenlre ezekbe nem folyunk bele, rrnk arra mg. Ajnlom a properties ment, ahol minden elkpzelhett t lehet lltani. A General-ban az ID-azonostt adhatjuk meg, Lthat lengyen-e, Meglljon -e rajta a tab, Lehet-e vlasztani. A Legjobb a Captipon. Ide kell berni, mi legyen a szveg. A Style s Extented style ablakokban az objektum stlust adhatjuk meg. Van itt minden. Lehet prblkozni. Ha meguntuk a jtszst, akkor Menjnk a BUILD/BUILD projrctnv.exe (F7) menpontra, aztn meg a BUUILD/EXECUTE projectnv.exe (CTRL-F5) menpontra. A program mkdni fog. Megnzhetjk mit csinltunk.

MFC ALAPOKMiutn van mr mkd programunk , igaz nem valami fenomenlis, megnzhetnnk, hogy tulajdonkppen mirt is mkdik. Mivel a programunk MFC-vel kszlt (Nem tudom mirt ppen azzal, de ha mr elkezdtem... ), tisztzni kne, hogy mi is az.

Az MFC a Microsoft Foundation Classes rvidtse. Nem ms, mint egy objektumrendszer, ami a windows-os programozst hvatott megknnyteni. Eltakarja ellnk a valdi API-t (Application Program Interface) s hasznlja helyettnk. Ezen kvl a dokumentunkezelsekre, OLE-re, DAO-ra, s mg sokmindenre vannak sajt cuccai. Ennek fejben neknk az szablyai szerint kell jtszanunk. Mit jelent ez? Meg vannak elre adva az objektumok tpusai. Pl.: a dilalgusablak, a szerkesztablak, gombok stb... Ezek tulajdonkppen megadjk a programunk 'csontvzt'. A mi dolgunk 'csak' annyi, hogy hozzrjuk azt a rszt, amit csak mi tudunk, hogy minek kell lennie, ami mr nem ltalnosthat, a program specifikus jegyei. Ennyi elg is lesz az elmletbl, nzzk a gyakorlatot. Csinljunk egy programot.

19

Ugyangy, mint az elz szmban, MFC Appwizard, Dialog Based, stb stb... Azzal a kis klnbsggel, hogy most ne krjnk About Box-ot. gy egyszerbben t fogjuk ltni a dolgot. Na eddig jutottunk az elz szmban is. A program ugyan mr most is mkdik, de neknk nem sok kznk van hozz. Nzzk milyen forrs -s fejlcllomnyok vannak, anlkl, hogy belefolynnk a rszletekbe:

Ezeket alapveten 2 rszre oszthatjuk. Van, amibe nem nagyon kell belenylni: second.rc : ebben van eltrolva az sszes ablak minden adata, miden bitmap, az iconfile neve stb.. resource.h : itt van konkrt rtk adva a klnbz ID-knek. stdafx.h : az MFC cuccokat include-olja be stdafx.cpp : MFC-t include-ol Amibe bele lehet, s ha programozunk, bele is kell nylni: Second.h Ebben van definilva az application objektum tpusa. A CWinApp-bl van szrmaztatva

seconddlg.h Ebben van definilva maga a kezd dialgusablak. A CDialog class-bl van szrmaztatva. Fontos, hogy itt van megadva az IDD-je. Ez annyit tesz, hogy a resources-nl ezen cm alatt lehet szerkeszteni az ablakot. enum { IDD = IDD_SECOND_DIALOG }; Teht, a ResourceView-nl az IDD_SECOND_DIALOG-ra rclickelve a kezd dialgusablak szerkeszthet.

20

*. cpp File-okban a hozzjuk tartoz header-ekben definilt fggvnyek megvalstsa tallhat.

Na, azt hiszem sikerlt elg felletes lenni ahoz, hogy mg krdsek se tudjanak felmerlni. Nehogymr ne lssuk a ftl az erdt, akkor inkbb mr a ft se!

Csinljunk mr valami jat is. Mondjuk egy j dialgusablakot. Kt dolgot kell csinlnunk.

1. Elszr a Resource View-nl be kell insertelni egy j dialog-ot. A jobb egrgombra eljn, hogy asszongya:

Erre aztn nem is krdez semmit, ott fog teremni egy jabb dialgusablak szerkesztstl. Miutn az ablakot mindenki knye kedve szerint sszeszerkesztette, felmerl a krds, hogy legyen ms a neve. A ResourceView nl jobb gombbal rkatt, s properties. Itt ms ID-t is berhatunk. Ez utn jn a msodik lps. 2. Az j ablakhoz ltre kell hozni egy j Class-t is. Fmen Insert/New Class.

21

Ami nagyon fontos, hogy a Dialog ID-hez az imnt szerkesztett Dialog ID-jt rjuk be. A base class pedig legyen CDialog. A filename lehet brmi, a class type legyen MFC.

Megvan a class, sajt kis header, meg cpp file-al. Megvan maga a dialog. mr csak azt kne elrni, hogy a program futsa sorn eljjjn.

Kicsit bele kell nylni a msik dialgusablakba is.

Nzznk ki egy szimpatikus gombot rajta, s nyomjunk r egy jobb clicket, s vlasszuk az Events... menpontot. (nlam ez egy kilp nev gomb volt)

22

Szval a bal oldalon azok kzl az esemnyek kzl lehet vlasztani, amik bekvetkezhetnek. Ez egy gombnl nem tl bonyolult, lehet egy click, meg kett. A jobboldalon fell a mr ltez handler-ek vannak. A jobb oldalon alul pedig azt kell kivlasztani, mivel akarjuk lekezelni. Az Add Handler csak Hozzad egy handlert, az Add and edit -nl pedig rgtn szerkeszthetjk is. Ezek az Event Handlerek nagyon fontosak, ugyanis ez az egyik ritka mdja annak, hogy az ltalunk rt programrszekre tudjuk adni a vezrlst, az id tbbi rszben a WIN32s vagy az MFC vgzi a dolgokat. Akkor Add and Edit. Rkrdez a ltrehozand fggvny nevre, majd rgtn megjelenik a szerkesztablakban. Most jn azon ritka pillanatok egyike, hogy belerhatunk a programunka. Kezdjk azzal, hogy az include-ok kz berjuk a meghvand dialgusablak header-jt. Ugyanis itt van definilva a tpusa. pl.: #include "newdlg.h" A handler pedig csak ennyi lesz: void CSecondDlg::OnKilep() { newdlg dlg; //dlg egy newdlg tpus vltoz dlg.DoModal(); //meghvjuk azt a fggvnyt, ami elindtja. } Teht mivel a class-ok csak tpusok, nem adhatjuk rjuk a vezrlst (nem hvhatjuk fggvnyeiket). Kell csinlni egy vltozt abbl a tpusbl. s a vltoz DoModal() fggvnyvel tudjuk odaadni a vezrlst.

23

s mr be is iktattunk egy jabb ablakot. Nem olyan bonyolult.

ADAT BEVITELNa, nzzk. Miutn ablakot mr tudunk kirakni, prbljunk meg adatot bekrni. Na persze ez nem nemgy csak gy ripsz-ropsz. Mivel adatokrl van sz, azokat ugye stlszeren vltozkban illik trolni. Ezrt most elszr nem csak ide-oda kattintgatunk a menkben, hanem egy kis elmletet kell nzni. Mgpedig azt, hogy milyen vltozkat enged meg a Visual C. A dolog ott kezddik, hogy itt mr nem csak a klasszikus rtelemben vett vltozk lteznek, hanem mr objektumok is. Az adaton kvl az adott tpusra jellemz konverzis s kezelfggvnyeket is tartalmazzk. Persze minden adattrolsnak azrt az alaptpusok, potosabban az gynevezett egyszer tpusok (Simple types) az alapjai. Teht jjjenek az egyszer tpusok. Termszetesen a C-ben s a C++-ban hasznlt sszes tpus hasznlhat. Ezeken kvl csak azt rom le, ami j. Na persze nem mind a 3 oldalt, csak a gyakrabban hasznlatosakat. Ezeket a tpusokat tulajdonkppen csak a paramtertadsnl, visszatrsi rtkeknl, message handlereknl hasznljuk. J rszket csak a szabvny knyvtri hivsoknl kell elvennnk. Egy sima szm trolsa itt is egy egyszer int el trtnik. A string-ek trolsnl nagyobb vltozsok trtntek. Itt van az az objektumos dolog. Na de nzzk akkor a gyakrabban hasznlt egyszer tpusokat. BOOL Boolean value BSTR 32-bit character pointer BYTE 8-bit integer that is not signed. COLORREF 32-bit value used as a color value. DWORD 32-bit unsigned integer or the address of a segment and its associated offset. LONG 32-bit signed integer. LPARAM 32-bit value passed as a parameter to a window procedure or callback function. LPCSTR 32-bit pointer to a constant character string. LPSTR 32-bit pointer to a character string. LPCTSTR 32-bit pointer to a constant character string that is portable for Unicode and DBCS. LPTSTR 32-bit pointer to a character string that is portable for Unicode and DBCS. LPVOID 32-bit pointer to an unspecified type. LRESULT 32-bit value returned from a window procedure or callback function. UINT 16-bit unsigned integer on Windows versions 3.0 and 3.1; a 32-bit unsigned integer on Win32. WNDPROC 32-bit pointer to a window procedure. WORD 16-bit unsigned integer. WPARAM value passed as a parameter to a window procedure or callback function: 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32.

A P-vel, vagy LP-vel kezdd vltozk nem valdi pointerek, hanem csak gynevezett handle-ek. Ez a handle egy cmtblzat egy elemre mutat, ami a cucc valdi cmt tartalmazza. Szval Visual C-ben, ahogy mellesleg JAVA-ban is, mr nincsenek klasszsikus pointerek, amik meghatrozott memriaterletre mutatnakak. Ezek lennnek a lnyegesebbek. A tbbi tpust azrt nem rom le, mert vagy ezekbl, vagy az alaptpusokbl szrmaztathatak, vagy nem nagyon van r szksgnk.

24

Objektum tpusbl (Simple value type) mr kevesebb van. Ezekre az Objektumokra az a jellemz, hogy nincsenek sehonnan szrmaztatva. Nem gy, mint az a msik tezer, aminek mind a CObject az alapja. Mint emltettem, itt mr nem csak az adat van trolva, hanem egypr r jellemz fggvny is. Egyszer rtk tpusok: CPoint Egy abszolt koordinta trolsra val. (x,y) CRect Egy tglalap alak terlet bal fels s jobb als koordintit tartalmazza CSize Egy relatv koordinta trolsa. X s Y irny mret CString Egy String trolsra val. CTime Abszolt id s dtum CTimeSpan Relatv id s dtum

Logikailag nmileg nem stimmel, viszont knyelmi okokbl maga az adat nem az objektum egy tagja (vltozja), hanem egyszeren az objektum nevnek lersval hivatkozunk r. Ennyi elmlet utn csinljunk valami programot. Ugyangy kezdjk, mint eddig, Egy kis Application Wizard. Aztn rajzoljuk meg a kezd ablakot. Mivel adatbekrst szeretnnk, nem rt, ha egy pr edit line-t is rakunk. Ezekutn eressznk r egy Classwizard-ot a Dialog ablak Class-ra. Rllunk a Classview-ban, s View/Classwizard. Itt az Add Variable-re kattintva brmelyik Control (Gomb, edit line stb) -hoz rendelhetnk vltozkat. Aminek az rtkt ksbb fel akarjuk hasznlni, ahhoz rendeljnk. Csak a vltloz nevt, kell berni, a felknlt tpus midig megfelel. A Classwizard elintzi a vltozk defincijt a class-hoz tartoz header-ben, a vltoz elksztst a Class els fggvnyben, az adatcsert pedig a DoDataExchange-ben. Ha meg akarjuk tudni a vltozhoz rendelt elemek rtkeit, az Update nev fggvnyt kell hvni TRUE-val. Update(TRUE); Ez a fggvny a Cwind objektum tagja, a Cdialog a Cwind-bl szrmazik, teht simn hvhatjuk. Ez a fggvny vgzi az adatcsert a vltozk s a hozzjuk rendelt Control-ok kztt. Ha TRUE-val hvjuk, a vltozkat feltlti az adatokkal, Ha FALSE-al, a vltozkban trolt adatokat rakja be az ablakba. Mgpedig gy, hogy kzvetve meghvja a DoDataExchange-t. Mi ezt soha ne tegyk, mert elszll a program. Ha ezzel megvagyunk, ksztsnk egy j Dialgusablakot. Egy pr Static Text-el. Mindegyiknek legyen sajt ID-je. Ide fogjuk berni az tvett adatokat. A hozz tartoz Class-ot ClassWizard-dal elksztjk gy, hogy a static text-ekhez vltozkat rendelnk. Ha ez megvan, mrcsak egy olyan fggvnyt kell hozzadni a Class-hoz, ami ezeknek a vltozknak rtket ad. Balgomb a ClassView-nl s add member function.

25

Itt meg kell adni a Fggvny tpust, a deklarcijt, az elrst. Ha csak egy sima fggvny, akkor az alapbelltsokat el lehet fogadni. Ha ez megvan, csak meg kell rni a fggvnyt, s a msik Class-bl meghvni. A fggvny: void CInfOutDlg::SetMyData(LPCSTR nev,LPCTSTR szam,LPCTSTR cim) { //Adatok atvetele m_cim = cim; m_nev = nev; m_szam = szam; } Ezt egy Handler-bl meghvva: void CMythirdDlg::OnNext() { // TODO: Add your control notification handler code here UpdateData(TRUE); //Adatok behuzasa a valtozokba InfWin.SetMyData(nev,szam,cim); //Adatok atadasa InfWin.DoModal(); //Ablak Inditasa cim = _T(""); szam = _T(""); nev = _T(""); UpdateData(FALSE); } A program mkdik. . //Kezdo adatok

//toroljuk a beirt adatokat.

26

LISTBOX HASZNLATA

Feketelistakszt program ksztseMiutn modlis(modal) dialgusablakok gyrtsban mr otthonosan mozgunk, ksztsnk nem modlisat (modeless). Mert eddig ugyan nem fordtottunk r klnsebb figyelmet, de bizony a dialgusablakok modlisak voltak. Ez egyszeren annyit jelent, hogy addig nem tudunk visszalpni az elzre, amg az ppen aktvat be nem zrtuk. Ez a bezrs praktikusan az OK, vagy CANCEL gomb lenyomsval szokott trtnni. A nem modlis dialgusablak onnan ismerszik meg, hogy nem ktelez bezrni, az elzre mindig visszalphetnk. Ez eddig elg egyszernek hangzik, de azrt ennek messzemen kvetkezmnyei vannak. A legszembetnbb problma az, hogy mg a modlis ablak automatikusan eltnik, mivelhogy tudja, hogy el kell tnnie, neknk nem sokat kell az ablak megsemmistsvel (destroy) foglalkozni. Most viszont lesz dolgunk ez gyben. Aztn az adatcsernl is vltozsok lesznek. Eddig nagyon j volt a DDX, meg a DDV, ezekkel ki tudtuk szedni az adatot vltozkba, s feldolgozni. Most viszont mivel mind a kt dialgusablak egyszerre ltezik, az is, ahonnan indtottunk, meg az is, ami indult, az adatcsere egyms control-jainak kzvetlen elrsvel sokkal egyszerbb. Akkor a tlem mr megszokott bre eresztett elmlet utn a gyakorlat. Az egsz projektet ugyangy kell kezdeni, mint eddig (AppWizard,MFC,..), megrajzoljuk a dialgusablakokat. Eddig mg nem hasznltuk a List Box-ot, de gondolom senkinek nem jelent klnsebb akadlyt kivlasztani az eszkztrbl s berajzolni a helyre. Az jonnan rajzolt ablakhoz ltre kell hozni egy j Class-t. Persze ClassWizard-dal a legegyszerbb. (dupla kattints a vadi zsr dialgusablakunkon) Mindent ugyangy kell belltani, mint eddig, csak most a member fggvnyeknl lesz egy kis eltrs. Pontosan krlbell gy fog kinzni:

27

Eddig nem gy ksztettk a kezel (handler) fggvnyeket, de ez sem bonyolultabb. Ki kell vlasztani az Object Ids ablakban annak az azonostjt, amihez akarjuk rendelni a fggvnyt, a Messages ablakban, hogy milyen esemnyhez, s r kell bkni az Add Function Gombra. Amint a mellkelt bra is mutatja 4 kezelfggvnynk lesz. Ebbl egy mr eddig is ltezett a DoDataExchange. Ezzel most nem is kel trdni. A kt gombhoz kellett rendelni j fggvnyeket, meg a PostNcDestroy mr ltez fggvnybl egy jat csinlni, ami persze nem rja fell a rgit, mert virtulis. A kt gombon nem sokat kell magyarzni, de ez a PostNcDestroy elg homlyos. Nos ez a fggvny a CWnd objektum tagja (member). Mellkesen ebbl az objektumbl szrmazik mindenfle ablak. Akkor hvdik meg, ha az ablak eltntette magt, s az automatikusan ltrehozott cuccokat megsemmistette. Tipikusan arra val, hogy az ltalunk foglalt memrit felszabadtsuk, s eltntessk a maradk dolgokat. Eddig nem nagy kaland. A hzsabb rsz akkor kezddik, mikor a ltrehozott fggvnyeket meg kell rni. Rajta. Lssuk a Hozzad gomb lenyomsakor lefut OnHOZZAAD nev fggvnyt. void CAdderDialog::OnHOZZAAD() { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_NEWNAME); CListBox* pList = (CListBox*) (m_pParent->GetDlgItem(IDC_LIST)); ASSERT(pList != NULL); ASSERT(pEdit != NULL); //ha nulla, akkor hibajelzs

if (pList != NULL && pEdit != NULL) {

28

CString str; pEdit->GetWindowText(str); pList->AddString(str); } } Nmi magyarzatra szorul.

Kell kt vltoz, egy Cedit objektumra mutat pointer, Ez fog mutatni az editline-ra meg egy ClistBox objektumra mutat pointer, ez fog mutatni a szl (ahonnan indtottuk, m_pParent mutat r) ablak ListBox-ra. Az adatcsert a kt objektum kztt fogjuk elvgezni egy Cstring tpus vltoz segtsgvel. A CEdit GetWindowTExt fggvnyvel bekrjk az editline-ban szerepl stringet az str-be, a ClistBox AddString fggvnyvel pedig berakjuk a ListBox-ba. Teht az adatcsere nem DDX-el trtnt. A Ksz gombra aktivizld OnKESZ fggvny: void CAdderDialog::OnKESZ() { ((CMainDlg*)m_pParent)->BoxDone(); DestroyWindow(); }

Ez csak annyit csinl, hogy meghvja a kezd dialgusablak BoxDone fggvnyt, ami jra engedlyezi a nem modlis ablak aktivizldsnl letiltott Hozzad gombot. Erre a jtkra azrt van szksg, mert erre a gombra indul a nem modlis ablak, s ahnyszor rnyomnnk mindig jbl megjelenne. Ezekutn meghvja a DestroyWindow() fggvnyt, ami a Cwind tagja. Amint a neve is mutatja az ablak megsemmistsre, azaz bezrsra val.

A PostNcDestroy fggvnynk: void CAdderDialog::PostNcDestroy() { delete this; }

Nos a sor nem igazn emlkeztet egy C++-ben rt sorra, pedig mkdik. A this egy konstans pointer, amit nem kell definilnunk, mindig hivatkozatunk r. Mindig az t tartalmaz fggvny objektumra mutat.

A delete egy opertor, ami felszabadtja az utna szerepl pointer segtsgvel cmzett, s termszetesen lefoglalt memrit. Teht az objektumnak minden apr porcikjt szmztk a memribl.

Ezzel megvolnnk, de van mg egy apr problma amit eddig elhalgattam. Nem modlis dialgusablakot a Create fggvnnyel kell ltrehozni. Ez a Cdialog Class tagja. Meg kell neki adni az ablak ID-jt, meg a Parent Class cmt. Teht: BOOL CAdderDlg::Create() {

29

return CDialog::Create(m_nID, m_pParent); }

Termszetesen az m_nID, s m_pParent vltozkat ltre kell hozni, s rtkket a Class konstruktorban be kell lltani. (A Class konstruktora a Classal azonos nev fggvny).

Ezzel megvolnnk,, mr csak a kezd dialgusablakkal kell tudatni, hogy itt van rajta kvl mg valaki. Kell egy vltoz, pontosabban egy pointer, ami a nem modlis dilagusablakra fog mutatni.: CAdderDlg* m_pModeless; Ezt persze egy add member variable-val el lehet intzni. Aztn mr csak el kell indtani amit eddig mveltnk. void CMainDlg::OnOK() { if (m_pModeless == NULL) { m_pModeless = new CAdderDlg(this); if (m_pModeless->Create() == TRUE) GetDlgItem(IDOK)->EnableWindow(FALSE); } else m_pModeless->SetActiveWindow(); } Teht a new opertorral hoztuk ltre az objektumot, ezrt kell majd a delete opertorral megsemmisteni. A this pointer mr ismers. A konstruktornak tadjuk a parent , teht a sajt cimnk. Miutn megvan a dialgusablak, csak le kell tiltani azt az gy gombot.

SDI ABLAKOKMiutn dialgusablakokban mr profik vagyunk, most a norml ablakok kvetkeznek. Az az egyszer egy men, egy kis keret, meg a menbl nyl dialgusablakok. Az ilyen stlus alkalmazst SDI-nek (Single Document Interface) is szoks nevezni.

30

Szval a helyzet gy nz ki, hogy van egy Frame Window, ami maga az alkalmazs ablaka. Rsze a rendszermen, a mensor, az esetleges ikonsor s a fejlc. Magba foglalja az u.n. Client Area t. Ez az res terlet az, ahol a dokumentum megjelenik, s a felhasznl dolgozhat vele. A Client-Area-hoz hozz van rendelve, egy View, ami a megjelentst vgzi. Maga a dokumentum pedig a View-val tart kapcsolatot. A Frame-hez, pontosabban a menpontjaihoz pedig Dialgusablakok rendelhetk. Az ilyen menpontok ltalban -ra vgzdnek. Az SDI lnyege teht az, hogy egy Frame Window-hoz egy Dokumentum van rendelve. Ami a pldaprogramot illeti, aClient Area-t nem ktelez View-hoz rendelni, a Frame -bl is rhatunk r. gy termszetesen Dokumentum sem lesz, de gy a klyhtl indulunk el. A mostani program sszehozshoz most nem nyjt olyan rugalmas segtsget az AppWizard, de azrt mg mindig egyszerbb, mint mindent jbl kezdeni. Teht MFC AppWizard, Single Document. Az egyszersg kedvrt klnbz extrkkal nem kell agyontuningolni. Ha ez megvan, tisztogatni kell egy kicsit. Az AppWizard ltal ltrehozott View s Doc Classokat egy az egyben le lehet szedni. Mivel a ClassView-bl nem lehet trlni, a file-jaikat kell eltvoltani. Ezek utn a program sszesen 3 Class-t tartamaz.

CSDIApp CMainFrame CAboutDlg

az alkalmazs Class-a a Frame Window Class-a az about ablak.

Az alkalmazs objektumban csak az InitInstance fggvnyre van szksgnk, s esetleg az AboutBox Message Handler-re. Az InitInstance tartalmazza a FrameWindow meghvst: m_pMainWnd=new CMainFrame; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow();

31

A new paranccsal ltrehozunk egy FrameWindow-t, amit kirajzoltatunk, s tadjuk r a vezrlst. A lnyeges dolgok innentl a FrameWindow-ban zajlanak.A Konstruktorban van egy dolog, amit mindenkpp meg kell tenni.: LoadFrame(IDR_MAINFRAME); //Frame betoltese A Frame-hez tartoz sszes resources (erforrs) itt kerl betltsre. Ilyenek a mensor, az Ikonok, a Gyorsbillentyk, s a string tbla. A leggyakrabban hasznlt ezek kzl a mensor. A szerkesztse nagyon egyszer, a Resource View-ban csak r kell kattintani. Minden menn bell ltrehozhatunk menpontokat, s tovbbnyl Pop-Up menket. A Pop-Up menkkel semmi dolgunk nincs, azok kezelst a rendszer teljesen magtl vgzi. A menpontok az rdekesek. Mindegyikhez tartozik egy ID. Kezelfggvnyeket rendelhetnk az ltaluk kivltott zenetekhez. A ktfle zenet lehetsges: COMMAND UPDATE_COMMAND_UI A COMMAND zenethez Handler-t, azaz kezelfggvnyt lehet rendelni. Pldul az Open menponthoz egy olyan fggvny tartozna, ami elindt egy dialgusablakot, amiben bekri a file nevt, majd megnyitja azt. Szval ez a fggvny a parancs vgrehajtsra val. Az UPDATE_COMMAND_UI zenethez callback fggvny rendelhet. A Callback fggvny olyan fajta fggvny, amit csak az alkalmazson kvlrl lehet hvni. A menponthoz tartoz CallBack fggvny akkor fog meghvdni (szp magyar szval), ha a menpont llapota vltozik. Ami azt jelenti, hogy rnyomtunk. Tipikusan arra val, hogy a kivlasztott menpontot megjelljk egy pipval, vagy ms menpontokat inaktvv tegynk. Rviden mindkt zenet a menpont kivlasztsnl generldik, de teljesen ms cllal. Ezrt a hozzjuk rendelt fggvnyeket sem j sszekeverni. Ezeknek a hozzrendelseknek a megvalstsa legknnyebben a ClassWizard-dal rhet el. Kivlasztjuk a menpont ID-jt, az zenetet (COMMAND/UPDATE_COMMAND_UI), s egy Add Function-nal mr meg is jelent. Ennek megfelelen egy plda a Handler fggvnyre: void CMainFrame::OnSettext() { CNewTextDlg dialog; dialog.m_NewText=Text; if (dialog.DoModal()==IDOK) Text=dialog.m_NewText; MyUpDate(); } Minden dolog ismert benne, meghv egy dialgusablakot, ami bekr egy stringet, s a sajt vltozjban eltrolja. Onnan kiszedhetjk, hiszen attl, hogy az ablak mr eltnt a memribl, a vltozi mg megvannak. Egy plda a CallBack fggvnyre: void CMainFrame::OnUpdatePos(CCmdUI* pCmdUI) { pCmdUI->SetCheck(pCmdUI->m_nID == Pos);

32

} Amint lthat a fggvny kap paramterknt egy CCmdUI Class-ra mutat pointert. Ennek segtsgvel tudjuk a ment vltoztatni. Vltozs esetn a rgi menponttl leszedi a pipt, az jra meg felteszi. Csak azrt lehetsges, mert az sszes menpont CallBack fggvnye egy szemlyben, akit vltoztatni kell az adott Pop-Up menn bell. A program egy stringet pozcionl a kpernyn a menben kivlasztott helyre. Ehhez rni kell a Client Area-ra. Ilyenkor leggyakrabban az WM_PAINT zenethez rendelt fggvnnyel lehet clba rni. Az WM_PAINT zenet akkor generldik, ha az ablak jrarajzoldik. Ebben az estben pedig nyugodtan rhatunk. void CMainFrame::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetTextAlign(TA_BASELINE | TA_CENTER); dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); dc.SetBkMode(TRANSPARENT); dc.TextOut(TextX, TextY, Text); } A CPaintDC Class segtsgvel rhatunk ki nem az ablakhoz (most a Client Area-hoz) tartoz szveget. Tetszleges koordintkra, tetszleges sznnel. A koordintatengelyek:

Termszetesen a helyes koordintk kiszmolshoz ismernnk kell az ablak mrett, a szveg mreteit kppontokban. Ezen kvl minden alkalommal, amikor jramretezzk az ablakot, jra kell szmolni a koordintkat. Egy plda a Client Area mreteinek lekrdezsre: CRect rect; //negyzet koord CSize WindSize; GetClientRect(rect);//Ablak koord. lekerd WindSize.cx=rect.right; WindSize.cy=rect.bottom; A Crect Class egy ngyzet jellemz kt koordintjt trolja. A bal felst s a jobb alst. Hasonl Class a CSize is, ez x s y mretet trol. A GetClientRect fggvny egy CRect Classba adja vissza a ClientArea mreteit, innen pedig knyelmesen ki lehet pakolni. Egy plda a szveg mreteinek lekrdezsre: CPaintDC dc(this); // device context for painting

33

CSize TextSize; TextSize=dc.GetTextExtent(Text); Szintn a CPaint segtsgvel. A GetTextExtent fggvny kpernypontokban adja vissza a string mrett. Emltettem, hogy az jramretezsnl is mindent elrl kell kezdeni. Kell egy Handler-t rni a WM_SIZE zenetre. Akkor hvdik meg, mikor az ablak j mretet kapott. Plda: void CMainFrame::OnSize(UINT nType, int cx, int cy) { CFrameWnd::OnSize(nType, cx, cy); WindSize.cx=cx; WindSize.cy=cy; MyUpDate(); } A fggvny kapsbl megkapja az j mretet, csak el kell trolni, s jraszmolni a szveg koordintit. gy rzem minden rszletre kitrtem. Azt inkbb nem rom le, hogy kell kiszmolni egy ngyzet kzept, meg a szleit. Azt hiszem eddig ez a leghosszabb VisualC-s cikkem. Nem baj gyis jubillunk, mert ez a 20. (vagy a 21.) PCX-USER. [Ez a 24. Szerk.] :-)

MDI ABLAKOKMDIMulti Document Interface. Segtsgvel egyszerre tbb dokumentumablak szerkeszthet. Ezket az egy alaklmazshoz tartoz ablakokat child window-nak nevezzk. Evileg vgtelen szm nyithat meg egy egy tpusbl. Teht ugyanabbl a Class-bl egyszerre brmennyi vltoz lehet. gy ltrehozsuk dinamikusan futs idben a (new opertorral) trtnik, s termszetesen kapcsolatot kell tartaniuk az ket ltrehoz szl (Parent) ablakkal. gy elljrban csak ennyit. Nzzk kicsit kpletesebben.

34

Ahogy az SDI-nl, a fablak itt is egy frame window. Ennek egy specilis child ablaka az MDICLIENT window. Ez kezeli a mr SDI-nl is ltez CLIENT Area-t, belertve az sszes child window-al. A child window szerkezete tulajdonkppen megegyezik a mr megismert Frame window-al. A Frame (Most Child) window szerkezete:

A figyelmesebbek szrevehetik, hogy az bra pontosan ugyanaz, mint az SDI-s frame window. Teht, mint ltszik, a Child window szinte ugyanolyam mint az eddig mr megismert Frame window, csak ugye egyszerre tbb lehet belle, s van szl ablaka. Mely szl a Main Frame. Normlis esetben a megjelntst egy View Class vgzi, mikzben a Dokumentummal kapcsolatot tart. Az egyszersg kedvrt most View s Dokumentumkezelst kihagyom, ezekrl majd ksbb bvebben. Teht a pldaprogram a legegyszerbb esetet prblja feldolgozni, gy taln mg meg is lehet rteni. Hogyan is kell elkezdeni egy ilyen programot. Els nekifutsra az AppWizard a legegyszerbb megolds. Ugyangy, ahogy eddig, a tpusnl pedig rtelemszeren MDI-t kell vlasztani. Nem kell mindenfle extrt beixelni, nem biztos, hogy tlthatbb teszi a problmt. Ha ez megvan, tisztogatnunk kell egy kicsit. Trlni kell a View s Doc Class-okat, mivel nem lesz rjuk szksg. Ha minden megvan, a kvetkez Classok fognak ltszani:

35

Class Feladata Az alkalmazs A Fablak A Child Window

Szrmaztatjuk: CwinApp CMDIFrameWnd CMDIChildWnd

A programban: CMDIApp CMainFrame CChildFrame

Ezeken kvl termszetesen mg sok-sok ms lehetne, de ez a vz. Mint lthat minden egyes Class-nak jl definilt feladata van. Nzzk elszr a legegyszerbbet, s legismersebbet, az alkalmazs objektumt.: class CMDIApp : public CWinApp { public: CMDIApp(); //{{AFX_VIRTUAL(CMDIApp) public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CMDIApp) afx_msg void OnAppAbout(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; Van itt egy konstruktor, egy kezelfggvny, ami az About-ot nyitja, meg az InitInstance. Ezek kzl egyedl az InitInstance() rdekes igazn. Mint nevbl is kiderl, itt kell megteremteni a kezdfeltteleket. BOOL CMDIApp::InitInstance() { #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif Eddig csak a 3d Control betltse kerlt sorra, de ezutn jnnek a fontos dolgok. CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; Ltrehozzuk a MainFrame-et (Ld. Az bra), azaz a fablakot. Ez dinamikusan, new opertorral trtnik. A fablak cmt a CWinApp m_pMainWnd vltozjba kell tenni, tulajdonkppen itt kapcsoldik az ablak az alkalmazssal. Az ablakhoz termszetesen be kell tletni a hozz tartoz erforrst, ez a LoadFrame fggvnnyel trtnik, s egyszeren az azonostt kell megadni. Az erforrs itt, s ltalban a Frame ablakoknl egy egyszer mensor, vagy ikonsor. pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow();

36

return TRUE; Miutn megvan az ablak erforrssval egytt, meg kell jelenteni. A ShowWindow fggvnyt meghvva kirajzoldik az ablak. Egyedl a fablaknl kell meghvni ezt a fggvnyt, teht egy alklamazs sorn csak egyszer. Ezekutn az Update meghvsval kivltunk egy WM_PAINT zenetet, melynek hatsra a Client Area jrarajzoldik. Esetnkben megjelenik. A MainFrame objektuma: CMainFrame: class CMainFrame : public CMDIFrameWnd { public: CMainFrame(); //konstruktor public: virtual ~CMainFrame(); //destruktor protected: //{{AFX_MSG(CMainFrame) afx_msg void OnNew(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; Egy konstruktor, egy destruktor, meg egy zenetkezelfggvny. A konstruktor s a destruktor jelen esetben res. Az zenetkezel fggvny vgzi a Child ablakok ltrehozst, szempontunkbl ez az rdekes. Elszr az ablak objektumnk ltrehozsa a new paranccsal. Az objektumra mutat pointert kapunk. CChildFrame *pChildWnd = new CChildFrame; //Ez lesz a Child Window Ahoz, hogy egy ltalunk ltrehozott Class-bl ablak legyen, regisztrltatni kell az ablakot. Ez annyit tesz, hogy a framework bejegyzi az ablakot a megadott tulajdonsgokkal. Ez az AfxRegisterWndClass fggvnnyel trtnik. LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 ); Visszatrsi rtke egy C tpus string, amely az azonostt tartalmazza. U.n. class name. Erre majd szksg lesz az ablak ltrehozsnl. A Paramterek: nClassStyle Az ablak stlusa. A stlusok kombinciit kell megadni a bitenknti vagy (|) opertorral. Ezek a stlusok elre meghatrozott konstansok. Van bellk egy halom, a help-ben brki megtallja. A jelnleg hasznltak a CS_HREDRAW, s a CS_VREDRAW. Azt biztostjk, hogy mind horizontlis, mind vertiklis mretvltozskor az ablak jrarajzoldjon. hCursor A kurzor azonostja. Lehet ltalunk gyrtott is, de ltalban a LoadCursor fggvny ltal betlttt szabvny kurzorokat hasznljuk. Errl majd a tovbbiakban. hbrBackground A httr. Meghatrozza a kitltsi sznt s mintt. Tpusa szerint HBRUSH, ami egy CBrush objektum handlere. hIcon Az ikon handlere. Hogy ezt megkapjuk, a kurzorhoz hasonlan gy kell betlteni, a LoadIcon fggvny segtsgvel.

37

A megemltett tovbbi fggvnyek:A kurzor betltshez: HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName ) Visszatrsi rtke a kurzor handlere Paramterek: hInstance Annak a DLL-nek, vagy EXE-nek,vagy erforrsllomnynak az azonostja, amely a kurzort tartalmazza. Szabvnyos kurzorokk betltsnl ez NULL. lpCursorName kurzor azonostja. Elre meghatrozott konstansok: IDC_APPSTARTING nyl+homokra IDC_ARROW sima nyl IDC_CROSS Crosshair IDC_IBEAM I-beam IDC_ICON megrajzolt ikon IDC_NO nincs kurzor IDC_SIZE mretezsi kurzor IDC_SIZEALL mretezsi kurzor ngyfel nyllal IDC_SIZENESW jobbra fel,balra le nyllal IDC_SIZENS fel-le nyllal IDC_SIZENWSE balra fel, jobbra le IDC_SIZEWE jobbra-balra IDC_UPARROW felfele mutat nyl IDC_WAIT Mindenki kedvence, a homokra Az Ikon betltse: HICON LoadIcon( HINSTANCE hInstance, LPCTSTR lpIconName) Vissztrsi rtke az Icon handlere Paramterek: hInstance Ahogy a kurzorbetltsnl, annak az erforrsnak az azonostja, ahol az Ikon van. Ez ltalban a sajt programunk. A sajt programunk handle-t a AfxGetInstanceHandle() fggvnnyel tudjuk meg.

lpIconName Az ikon azonostja (name je). A MAKEINRESOURCE makrval tudunk az ID bl name-t csinlni.

Teht egy plda az ablak bejegyzsre, s name-jnek eltrolsra: LPCTSTR lpszChildClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, LoadCursor(NULL, IDC_NO), (HBRUSH)(COLOR_WINDOW+1), LoadIcon(AfxGetInstanceHandle(), Ez nem egy egyszer dolog, de mg mieltt az ablak megjelenne, a menu-t is be kell tlteni.

38

A CWnd menu.LoadMenu fggvnyvel trtnik. Menu betltse: pChildWnd->menu.LoadMenu(IDR_LINEFRAME); Ezekutn a Child window m_hMenuShared tagvltozjnak is meg kell adni a menut. Mivel ez a vltoz protected, csak az objektumon bellrl lehet trni. m_hMenuShared = menu.m_hMenu; Ha ez megvan, hozzuk ltre az ablakot. A CWnd Create fggvnyvel. virtual BOOL Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); Visszatrsi rtk nem nulla, ha sikeres, nulla ha sikertelen. Paramterek: lpszClassName dwStyle Az AfxRegisterWndClass ltal adott Class Name. Az ablak stlusnak tovbbi attributumai. Van belle egy pr. Alaprtelmezsben: WS_CHILD | WS_VISIBLE | WS OVERLAPPEDWINDOW Az ablak pozcija. Legknyelmesebb a rectDefault, ekkor az elhelyezs automatikus lesz. A szl ablak cme. Simn this. Az ablak Context-je. Ezt ltalban kell megadni, alaprtelmezs NULL

lpszWindowName C tpus string, amely a cmet tartalmazza.

rect pParentWnd pContext Egy plda:

pChildWnd->Create(lpszChildClass, _T("I'm a Child"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, rectDefault, this); } s mr meg is van a Child Window.

A VIEW S A DOKUMENTUM KAPCSOLATAHa valaki egyszer elmagyarzn, hogyan kell bevezett rni... :-) [ Szerk.: n tudom... :-) ]

A View s a Dokumentum kapcsolataInduljunk el a klyhtl: A CDocument Class biztostja az alapvet dokumentumkezelsi funkcikat. Az ltalunk ebbl

39

szrmaztatott Class-ok fogjk kezelni a dokumentumot. A dokumentum azt az adategysget jelenti, amit a felhasznl ltlban egy Open File-al nyit meg. Teht fizikailag valjban egy file. Azonban a dokumentum kezelsre szolgl Class-ban egy Archive-ot kezelnk. Ez egy kicsit hasonl, mint Cben a Stream.(De persze azrt egsz ms .) A CView Class szolgl alapjul a View kezelsre ltrehozott Class-oknak. Teht egy ilyen Class-bl kell szrmaztatni a sajt View Class-unkat. Tulajdonkppen egy kzvett szerepet jtszik a Dokumentum s a felhasznl kztt. A View jelenti meg a dokumentum egy rszt, s a felhasznl ltal eszkzlt mdostsokat kzvetti a dokumentum fel. Szintn a View feladata a nyomtats, s a nyomtatsi nzet (Print PreView). Aki eddig rtette, azt az albbi bra remlem vgleg sszezavarja:

A Document-View prostsnak az az elnye, hogy elvlasztjuk a dokumentumot kezel cuccokat, a dokumentumot megjeltktl. gy tlthatbb programot kapunk. Ebbl a sztvgsbl aztn rgtn az a htrny kvetkezik, hogy a View-nak, s a Dokumentum-nak llandan kapcsolatot kell tartaniunk egymssal. Azt lssuk a kpernyn, ami a tnyleges adat, s az legyen a tnyleges adat, amit a kpernyre bertunk. Ez az oda-vissza jtk nha elg bonyolult tud lenni. (De mint tudjuk, olyat mg senki nem tallt ki, hogy mindenkinek j legyen ) Akkor az adatkezelsrl kicsit bvebben. Ahogy emltettem a Dokumentumot kezel Classbl nem kzvetlenl rjk el a file-t, hanem egy Archive-on keresztl. Ez a CArchive Class, amely lehetsget ad Objektumok, Objektumhlzatok trolsra (mondjuk egy file-ban) binris formban. Az Objektumok megsznsk utn innen visszallthatak. Ezt az Objektum elmentst, visszatltst Serialization-nek hvjuk. (Prbltam magyarra lefordtani, de a megsorosts volt a legjobb verzi). Teht mikor a dokumentumot kezeljk, nem lesz filekezelssel dolgunk, csak serialization-nel. Ez jval knyelmesebb a szoksos filekezelsnl, meg Recordok olvasgatsnl. Mikor a felhasznl megnyit egy file-t, az automatikusan deserializldik(szpen magyarul), azaz visszalltdik minden elmentett Objektum. Ebben van a dolog htrnya, hiszen gy jval tbb memrit hasznlunk. Termszetesen a rgi bevlt Rekord-os kezels is megoldhat, csak ki kell trkkzni a Serializationt. Az is lnyeges, hogy csak azok az objektumok Serializlhatak, amik erre fel vannak ksztve. Azaz ltezik Serialize() fggvnyk. Ezenkvl hasznlniuk kell az IMPLEMENT_SERIAL, s DECLARE_SERIAL makrkat.

40

A View: A View tulajdonkppen Child-ja egy Frame Window-nak. Egy Frame ablakon bell tbb View is ltezhet, pldul felosztott ablakoknl. Egy View csak egy Documenthez rendelhet, viszont egy Document-hez tbb View is. A View a hozz rendelt Document-et a GetDocument() fggvny segtsgvel ri el. Ha a Document-ben vltozs trtnt, teht vltozott az adat, egy kis segtsggel a View OnUpDate fggvnye hvdik meg. Itt lehet elintzni, hogy a mdostott adatok kirdjanak. A View-Class-unkat a Cview-bl kell szrmaztatni, vagy egy abbl szrmaztatott Class-bl. Ebbl tbbfle van, ami szemnek szjnak ingere.

CCtrlView, Control-okat tartalmaz view (tree, list, rich edit controls). CDaoRecordView, adatbzisrekordokat tartalmaz view CEditView, Egy egyszer text editor. CFormView, dialog-box control-okat tartalmaz View, egy dialog template resource-bl szedi a control-okat. CListView, list controls. CRecordView, adatbzisrekordokat kezel view CRichEditView, rich edit controlt tartalmaz View CScrollView, egyszer, grgethet ablak CTreeView, Tree View

A programban a CFormView-t fogjuk hasznlni. A Document: A CDocument alapban tartalmazza a File Open, File Save, stb.. parancsokat. St kilpskor magtl megkrdezi, hogy mentsen-e. Egy alkalmazson bell tbbfle Document is lehet. Minden Document Class-nak van egy Document Template-je. Ez tartalmazza a Document hozzrendelseit, milyen menket hasznl, milyen ikont, stb Az UpDateAllViews fggvny hatsra hvdnak meg a View-okban az OnUpdate fggvnyek. gy elljrban ennyit. Nzznk egy programot. Egy igen buta telefonknyv. Nem eredeti tlet, de elsnek megteszi. A program vzt megkaphatjuk az AppWizard-tl (Single Document, stb) Az els fontos dolog az Application InitInstance-ben: CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CTkDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CTkView)); AddDocTemplate(pDocTemplate); Itt trtnik a Document Template elksztse. ssze kell rendelni a dokumentumot a View-al, s a Frame window-al. A CsingleDocTemplate objektum csak SDI alkalmazsoknl hasznlhat. Csinlunk egy ilyen tpus pointert, a new opertorral tnylegesen is ltrehozzuk a Class-t, majd az AddDocTemplate fggvnnyel bejegyeztetjk. Kell egy Objektum, ami a menteni kvnt adatokat tartalmazza. class CTkRecord : public CObject

41

{ // Construction public: CTkRecord(LPCTSTR NewName,LPCTSTR NewAddress,LPCTSTR NewNumber); protected: CTkRecord(); DECLARE_SERIAL(CTkRecord) // Attributes public: CString Name; CString Address; CString Number; // Operations public: virtual void Serialize(CArchive& ar); // Implementation public: virtual ~CTkRecord(); }; Az Objektum a CObject-bl van szrmaztatva. A 3 adatmez hivatott a kezelend adatok trolsban. A paramterek nlkli konstruktor s a DECLARE_SERIAL makr a ksbbi lementshez kell. Az igazi konstrukornak meg tudjuk adni az adatmezk rtkt. A Serialize fggvny lehet rdekes: void CTkRecord::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar > Address; ar >> Number; } } Ez a fggvny vgzi az objektum llapotnak elmentst. Paramterknt megkapja az Archive-ot. Az els szembetl dolog a ketts kacsacsr. Ezt a specilis opertort csak a CArchive class-nl hasznlhatjuk. A > jelenti az Archive-bl val olvasst. Akr lementjk az Objektum llapott, akr visszatltjk, ez a fggvny hvdik meg. Hogy ppen rni kell-e, vagy olvasni, azt az Archive IsStoring() s IsLoading() fggvnyeivel tudjuk meg. rtelemszeren az els az rst, a msodik az olvasst jelzi. A Document Class-ban ilyen objektumokat fogunk kezelni. Tulajdonkppen egy ilyen objektum rekordknt is felfoghat, hiszen az adatmezi hordozzk a fontos informcit. A Document Class-

42

ban ezekbl az objektumokbl tmbt kpezve knyelmesen kezelhetek az adatok. CTypedPtrArray m_RecordList; A CTypedPtrArray csak egy segd Class. CObArray tmbt csinl, melynek CTkRecord tpus elemei lesznek. Abban klnbzik, a sima megadstl, CObArray CTkRecord hogy gy jobb hibakezelst kapunk, biztonsgosabb. A Serialize fggvny: void CTkDoc::Serialize(CArchive& ar) { m_RecordList.Serialize(ar); } Mivel mr a recordot tartalmaz objektumban megoldottuk a mentst, visszatltst, csak ezt kell meghvnunk. Ezzel a ments, visszatlts mr le is van tudva. De azrt akadnak egyb problmk. A View s a Doc kztti adatcsere. A Document Class oldalrl mikor mdosul a kirand adat (pl. rnyomunk hogy kvetkez), mindig meg kell hvni az UpdateAllViews fggvnyt. De csak azutn, ha mr lekrdeztk a View-ban mdostott adatokat. void UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL ); Paramterknt meg kell adni a View-ot. NULL, ha az sszeset. Ezenkvl a mdosts tpust is meg lehet adni, s egy objektumot, ami lerja, de ez mr nem ktelez. void CTkDoc::OnNext() { WriteBack(); ActualIndex++; ActualRecord=m_RecordList[ActualIndex]; CDocument::UpdateAllViews(NULL); } void CTkDoc::WriteBack() { CView* pView; POSITION pos = GetFirstViewPosition(); while (pos != NULL) { pView = GetNextView(pos); CTkView* pTkView = DYNAMIC_DOWNCAST(CTkView, pView); if (pTkView != NULL) pTkView->WriteBack(); } } A WriteBack hvja meg a View azonos nev fggvnyt, amely visszarja az adatokat a Document ActulRecord-jba. A dolog nehzsge, hogy a View-ot nem lehet csak gy meghvni, meg kell tallni. Esetnkben egy egyszerbb fggvny is megtette volna, mivel csak egy View van ,de sosem lehet tudni Elszr le kell krdezni az els View pozcijt, a GetFirstViewPosition fggvnyel. Majd ezt kveten megkapjuk a View-ra mutat pointert, a GetNextView fggvnnyel. Ha ez megvan, csak t kell Cast-olni a CView-ra mutat pointert CTkView-ra mutatra. Ez a DYNAMIC_DOWNCAST

43

makrval trtnik. Ezutn mr meg is tudjuk hvni az ominzus fggvnyt. Ahol void CTkView::WriteBack() { UpdateData(TRUE); CTkDoc* doc=GetDocument(); doc->ActualRecord->Address=m_address; doc->ActualRecord->Number=m_number; doc->ActualRecord->Name=m_name; } Az UpateData fggvny behzza a bert rtkeket a vltozkba. (Meghvdik a DoDataExchange) Ha TRUE-t adunk paramterknt bekri az adatokat, ha FALSE, akkor rja. A GetDocument fggvnnyel megkapjuk a Doc cmt, s berhatjuk a vltoziba a bert adatokat. Visszafele az adatcsere az UpDateAllViews meghvsa utn: void CTkView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { CTkDoc* doc=GetDocument(); m_address=doc->ActualRecord->Address; m_name=doc->ActualRecord->Name; m_number=doc->ActualRecord->Number; UpdateData(FALSE); Invalidate(); } Lekrjk a GetDocument()-el a Doc cmt, amivel elrjk a Document vltozit. Kivesszk ami kell, majd az UpdateData fggvnnyel berdik a Controllok-ba. Az Invalidate hatsra jrarajzoldik a frame a mr j adatokkal. Ennyi Lenne.

INI file kezels s MDI Document-View kapcsolatKezdjk az egyszerbbelAz INI file-ok programunk belltsainak trolsra szolglnak. Az llomny kznsges ASCII szvegfjl, ennek megfelelen elrse egyszer. A Windows 3.1-ig kzvetlenl is elrhettk programunkbl a sajt INI llomnyunkat, azonban klnbz adatvdelmi okokbl ezt mr a Windows 95, 98 s NT nem engedi. A hozzfrst a win32s API fggvnyei biztostjk szmunkra. Egy INI file felptse: [IniFileSection1] IniFileEntry1=valami IniFileEntry2=akarmi . . [IniFileSection2] IniFileEntry1=valami IniFileEntry2=akarmi

44

. .

s gy tovbb. Teht az INI file Section-okbl (fejezetekbl) ll, a section neve van szgletes zrjellel bezrva. Minden fejezet Entry-k sorozatt tartalmazza. Az Entry nevt egyenlsgjel kveti, s a hozz eltrolt rtk (Profile String). Az INI file-t nem kell ltrehozni, az INI file-ba val rskor, ha nem ltezik a file, ltrehozza helyettnk a framework (programkeret). A kezelst vgz MFC fggvnyek: CWinApp::LoadStdProfileSettings void LoadStdProfileSettings( UINT nMaxMRU = _AFX_MRU_COUNT ); Az InitInstance-bl kell hvni. A framework az ltala automatikusan az INI file-ba elmentett rtkeket engedlyezi, s tlti be. Ilyen tipikusan a Recent File List (elzleg hasznlt file-ok listja). Az nMaxMRU paramter a betltsre s trolsra engedlyezett filenevek szma. Ha nullt adunk meg paramterknt, le tudjuk tiltani az egszet. CWinApp::GetProfileString CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL ); A fggvny az elmentett string-et olvassa be, s visszaadja visszatrsi rtkknt. Paramterknt a Section s az Entry nevt kell megadni. Ha a fggvny nem tallja az rtket, lpszDefault -ot ad vissza. CWinApp::GetProfileInt UINT GetProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault ); Ugyanaz, mint az elz fggvny, csak most egy stringknt bert szmot integer-knt olvasunk be. CWinApp::WriteProfileString BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue ); A paramterknt megadott Section s Entry ltal meghatrozott helyre berja az lpszValue-t. Ha az Entry, vagy a Section nem ltezik, akkor ltrehozza. Ha nem sikerlt berni a visszatrsi rtk nulla, egybknt nem nulla. Egyszer plda: CString INIFileSection="Last used file"; CString INIFileEntry="File"; void CTkApp::PutDocFileToINI(LPCTSTR DocFile) { WriteProfileString(INIFileSection,INIFileEntry,DocFile); } CString CTkApp::GetDocFileFromINI() { return GetProfileString(INIFileSection,INIFileEntry); }

45

MDI Document-View kapcsolatAz SDI Document-View kapcsolathoz hasonlan itt is Document Template-el rendeljk ssze a dokumentumot a View-al. Azzal a klnbsggel, hogy itt egyszerre tbb template-nk lesz. A template-eket az application class kezeli s tartja nyilvn. A sajt kis listjn mindegyik template-re mutat egy pointer. Az alkalmazs annyi template-et kezel, ahny fle dokumentumot kezel. Egy template egy dokumentumtpust hatroz meg. Minden Template-bl tetszleges szm dokumentum lehet nyitva. Egy plda template ltrehozsra: formTemplate = new CMultiDocTemplate( IDR_FORMFRAME, RUNTIME_CLASS(CTkDoc), RUNTIME_CLASS(CTkFrame), RUNTIME_CLASS(CTkView)); AddDocTemplate(formTemplate); A CmultiDocTemplate objektumot hozzuk dinamikusan ltre. A konstruktornak a Frame Id-jt, a Document, Frame, s View classokat kell megadni. Ha nincs szksgnk r, hogy kln Frame window-t szrmaztassunk, CMDIChildFrame-et is megadhatunk a frame class-hoz. A Frame window ID-jre azrt van szksg, mert a string tblban hozz rendelt rtk adja meg a megnyitand dokumentum tpust, az ablak cmt, a file kiterjesztst, stb.. A template bejegyzse az AddDocTemplate fggvnnyel trtnik. Termszetesen az egszet az application InitInstance fggvnyben kell megtennnk. me egy bra, hogy sszezavarjon mindenkit:

Ennyi flrevezets utn foglaljuk ssze, ki kivel van:

A document Class listt vezet a sajt View-okrl, s egy pointere van ami az t ltrehoz template-re mutat. A View a frame window child-ja, s van egy pointere a hozz rendelt document-hez. s nylvn a frame window is tudja, hogy melyik View van benne. Ezen kvl a Document template szmontartja az ltala ltrehozott dokumentumokat, ahogy az alkalmazs is a template-ket.

Igazn egyszer. Ahogy az lenni szokott, hiba ismerik egymst a dokumentumkezelsben rsztvev Class-ok, akrki akrkinek mgsem kldzgethet akrhogy. Ahogy azt az Sdi-dokumentumkezelsnl is tapasztaltuk.

46

Egy kis sszefoglals: Adatcsere lehetsge a CDocument Class-bl: A GetFirstViewPosition s GetNextView fggvnyekkel elrhetjk a View-okat, s meghvhatjuk, amit szabad. A GetDocTemplate fggvnnyel megtudjuk a ltrehoz template-et.

A View- bl: A GetDocument fggvnnyel megkapjuk a Document-et. Ezzel elrjk az sszes adatt, amibl knnyen frissteni tudjuk a kpet. Ha a Frame window-ra is szksgnk lenne, azt a GetParentFrameel kapjuk meg. A frame window-bl A View-ot a GetActiveView-al kapjuk meg, az aktv dokumentumot, meg a GetActiveDocument el. MDI frame window-bl: Az ppen aktv child window-t a MDIGetActive fggvnnyel kapjuk. Ha ennek fnyben megrjuk a View s Document Class-okat, mg nem vgeztnk mindennel. Ha a template mr be van jegyezve, a dokumentumokat s a hozz tartoz View-okat mr csak ltre kell hozni. Ha a dokumentumhoz csak egy View van rendelve, a View-ot a framework magtl ltrehozza. Azonban, ha tbb View hasznlja ugyanazt az dokumentumot, csak az elst fogja ltrehozni, a tbbirl magunknak kell gondoskodni. Legpraktikusabb az application OpenDocument fggvnyben. CDocument* CTkApp::OpenDocumentFile(LPCTSTR lpszFileName) { CTkDoc* pDoc = (CTkDoc*)CWinApp::OpenDocumentFile(lpszFileName); if (pDoc == NULL) return NULL; CFrameWnd* pNewFrame = listTemplate->CreateNewFrame(pDoc, NULL); if (pNewFrame == NULL) return pDoc; listTemplate->InitialUpdateFrame(pNewFrame, pDoc); ASSERT_KINDOF(CMDIChildWnd, pNewFrame); CMDIFrameWnd* pMDIFrameWnd = ((CMDIChildWnd*)pNewFrame)->GetMDIFrame(); ASSERT(pMDIFrameWnd != NULL); pMDIFrameWnd->MDITile(MDITILE_HORIZONTAL); return pDoc; } Az eredeti fggvnyt persze meg kell hvni, ami visszaadja a Document-re mutat pointert. Ezek utn a template segtsgvel meg kell nyitni a Frame windowt. A CreatNewFrame hatsra a template hozza ltre a frame window-t. Az InitialUpdateFrame kivlt egy InitialUpdate zenetet a frame szmra, s az OnInitialUpdate fggvny fog lefutni, ami a mi initalizcis kdunkat tartalmazza. Az ablak tulajdonkppen mr kint van, de ha mretezni akarjuk, meg kell tudnunk az MDI Chlid window cmt. Ez a GetMDIFrame fggvnnyel lehetsges. Az MDI ablak MDITitle fggvnye vgzi a kpernyn val rendezst. A Document Class szempontjbl szinte teljesen mindegy, hny View hasznlja, ezrt ott nem is kell vltoztatni.

47

A Beillesztett j View is nagyon egyszer. Ha adatbekrsre nem hasznljuk, a Dokumentum-na nem kell lland kapcsolatot tartania a View-al, elg, ha a View ltja a Dokumentum adatait. Ennek megfelelen csak a Dokumentum ltal kldtt Update zenetre kell j handlert rni. void CTkListView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { Invalidate(); } Nagyon egyszer. Az Invalidate hatsra Draw zenet generldik, s meghvdik az OnDraw, ahol a kirst vgezzk. void CTkListView::OnDraw(CDC* pDC) { CTkDoc* pDoc = (CTkDoc*)GetDocument(); TEXTMETRIC tm; pDC->GetTextMetrics(&tm); int CharWidth = tm.tmAveCharWidth; int CharHeight = tm.tmHeight; CRect Area; GetClientRect(Area); pDC->TextOut(Area.Width()/2-10*CharWidth, Area.Height()/2-CharHeight, _T("Nv : ")+pDoc->ActualRecord->Name); pDC->TextOut(Area.Width()/2-10*CharWidth, Area.Height()/2, _T("Cm : ")+pDoc->ActualRecord->Address); pDC->TextOut(Area.Width()/2-10*CharWidth, Area.Height()/2+CharHeight, _T("Szm : ")+pDoc->ActualRecord->Number); } Be kell krni a karakterek magassgt, s szlessgt, hiszen a kiratsnl egysgkoordintkat kell megadni, nem sort s oszlopot. Ezutn tulajdonkppen kszen is vagyunk.

Statusbar, Tool Bar, Docking Tool Bar, ToolTipEgy pr olyan dologrl lesz sz, ami szinte mindegyik windows programnak rsze, mgis szinte szre sem vesszk ket, csak akkor, ha mgsincsenek. Az Eddigi pldaprogramok is mind hasznltk ezeket, de mgsem ejtettem szt rluk. Taln azrt, mert az AppWizard egy rszket magtl ltrehozza, kezelskkel nem sok gond van.

A Statusbar

A Statusbar az ablak legals svjban helyezkedik el. Egy sor, amely un. Output panelekbl ll. Itt jelezzk a Num Lock, Scroll Lock, s egyb billentyk llapott, de ebben a sorban jelenik meg

48

pldul a menpontokhoz rendelt rvid help is. MFC-ben a CStatusBar class kezeli. Az alkalmazsunkban a MainFrame Class-ban jelenik meg. Ha hasznlunk StatusBar-t, elszr egy CStatusBar tpus vltozt kell deklarlnunk a class-ban. Ha ez megvan, a CMainFrame OnCreate fggvnybl kell ltrehozni a Statusbart, s belltani a panelek szvegt, szmt, stb.. Ezek utn a dolog magtl mkdik, ha nem akarunk extrkat, nem is kell trdni vele. A framework a paneleket, s azok szvegt (Indicators) egy tmbben trolja. Az elemek sorrendjk szerint kerlnek ki a Statusbar-ra balrl jobbra haladva Alaprtelmezs szerint a legels elem mrete nincs meghatrozva, elasztikus. Ez a tbbi indicator ltal nem hasznlt szabad terletet foglalja el. Teht a panelek jobbra lesznek igaztva, mivel baloldalon ez lefoglalja a szabad helyet. Ha traknnk az utols helyre, akkor termszetesen minden balra lenne igaztva. Ltrehozskor egy ilyen tmbt adunk meg paramterknt, az elemek String ID-k. Az MFC a kvetkez ID-ket tudja, s kezeli is magtl.

ID_INDICATOR_CAPS : CAP lock indicator ID_INDICATOR_NUM : NUM lock indicator ID_INDICATOR_SCRL : SCRL lock indicator ID_INDICATOR_KANA : KANA lock indicator (Csak Japn rendszereken. Hogy mi az pontosan, nem tudom, de izgatja a fantzim)

Ezeket az Indicatorokat a rendszer magtl kivillantja, ha kell. A megvalstsuk a CFrameWnd::OnUpdateKeyIndicator fggvnyben van. Ha ettl klnbz Id-ket hasznlunk, azoknak elrejtst s kivillantst magunknak kell csinlni.

A CSstatusBar fggvnyei:A StatusBar ltrehozsa: CStatusBar::Create BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR ); Paramterknt elg csupn a Mainframe cmt megadni, hiszen a tbbi paramternek van alaprtelemzse, s csak ezeknek az rtkeknek van rtelmk. Nem hiszem hogy valaki pldul lthatatlan statusbar-t szeretne, vagy olyat, ami a frame tetejre van igaztva. A visszatrsi rtke nem nulla, ha sikeres volt. Az Inicator-ok szvegnek belltsa: CStatusBar::SetIndicators BOOL SetIndicators( const UINT* lpIDArray, int nIDCount ); Paramterknt az ID-ket tartalmaz tmb cmt, s az elemek szmt kell megadni. A fggvny kiszedi a String tblbl az ID-hez tartoz rtket, s arra lltja be az inidicator szvegt. A nulladik elem trsa:

49

CWnd::SetWindowText void SetWindowText( LPCTSTR lpszString ); A paramterknt megadott pointer egy C tpus string-re mutat, erre rja t a 0. Inidcator rtkt. Ez ltalban az res bal oldali sv.

Tetszleges elem trsa: CStatusBar::SetPaneText BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE); A paramterknt megadott szm indexet trja a megadott nvre. A harmadik paramter alaprtelmezs szerint TRUE, teht a panel jrardik. Egy egyszer plda a StatusBar ltrehozsra: static UINT indicators[] = { ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, }; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { m_wndStatusBar.Create(this); m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); . . .

A ToolBarAz ablak fels svjban helyezkedik el, apr ikonok (Bitmap-ek) sora, melyek lenyomsa egy-egy parancsot helyettest. Az ikonok mkdhetnek egyszer pushbutton-knt, radio button-knt, vagy checkbox-knt. Az MFC ToolBar tmozgathat, a Parent window brmelyik oldalhoz odaragaszthat (docking ToolBar), vagy bemozgathat az ablak belsejbe, ekkor lebeg (floating) toolbarrrl beszlnk. Ilyenkor egy sajt kis Frame Window-t nyit magnak, amley tmretezhet s bezrhat. A ToolBar ikonjaihoz ugyangy lehet ID-t s kezelfggvnyeket rendelni, mint a menpontokhoz. Sokszor ugyanazt az ID-t adjuk meg, mint egy menpontnl, gy ugyanaz a handler fut le, mint a men hatsra. A ToolBar ikonaihaoz rendelhetk gynevezett ToolTip-eket. Ezek azok a kis feliratok, amik megjelennek, ha sokat csorgunk egy ikon felett. A ToolBar ltrehozsa, s szerkesztse nagyon egyszeren a ToolBar editorral trtnik. Ha ToolTipet is szeretnnk, a Prompthoz a szveg utn /n-el elvlasztva rhatjuk a tooltip szveget. A ToolBart a CToolBar Class kezeli. A Fggvnyei:

50

Egy ToolBart ktflekppen is elkszthetnk: Egy ToolBar Resource-t ksztnk a Toolar Editorral Egy CToolBar Class tpus objektum ltrehozsa A ToolBar ltrehozsa a Create fggvnnyel A LoadToolBar fggvnnyel betltjk a ToolBar resurce-t.

Pl.: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { m_wndToolBar.Create(this); m_wndToolBar.LoadToolBar(IDR_MAINFRAME) . . Vagy: Pl.: Az ID-ket a String tblban definilni kell. A hozzjuk rendelt rtk a Status Bar-on megjelen Prompt, s \n-el elvlasztva a ToolTip szveg. static UINT BASED_CODE MainButtons[] = { ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, ID_SEPARATOR, ID_EDIT_CUT, ID_EDIT_COPY, ID_EDIT_PASTE, }; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { m_wndMainBar.Create(this, WS_CHILD | WS_VISIBLE; IDW_MAIN_BAR); m_wndMainBar.LoadBitmap(IDR_MAINBAR); m_wndMainBar.SetButtons(MainButtons, sizeof(MainButtons)/sizeof(UINT)); . . . Egy Bitmap Resource elksztse, amely a toolbar kpt trolja. Egy CToolBar tpus objektum ltrehozsa A Bitmap betltse a LoadBitmap fggvnnyel A tulajdonsgok belltsa a SetButtons fggvnnyel.

Ez ilyen rvidre sikerlt

NZETEKA view (nzet) megvalstsa51

A view az MFC programnak az a rsze, amely kezeli a nzetablakot, feldolgozza a felhasznli inputot, s megjelenti a dokumentum adatait a nzetablakban, s minden ms eszkzn (nyomtat). Az sszes nzetosztly a CView osztlybl van szrmaztatva. Nzeteket mr eddig is hasznltunk, az AppWizard is kszt neknk egyet, igaz ez kevs kivteltl eltekintve nem sok mindent csinl, azrt a vzat megadja. A legegyszerbb mdja az, amikor egyszeren leszrmaztatjuk egy mr mkd nzet osztlybl a sajtunkat. Ezt mr az AppWizard-bl is megtehetjk. Ilyen pldul a CEditView osztly. A belle szrmaztatott nzet mr egy egyszer szvegszerkeszt. ltalban ilyen ksz osztlyt nem tallunk a megoldand feladat megoldsra, neknk kell a nzetet megvalstani. Ilyenkor a nzetosztlyunkat valamelyik ltalnosabb cl MFC nzetosztlybl szrmaztatjuk, s hozzrjuk amit kell. Egy ilyen ltalnosan hasznlt nzetosztly a CScrollView, aminek segtsgvel grdthet nzeteket kszthetnk. (A pldaprogramban a CTkListView egy ilyen nzet.) A nzetek fontosabb fggvnyei, melyeket ltalban fell kell definilnunk: A Konstruktor: Itt lehet belltani a vltozk kezdeti rtkt, egrkurzort betlteni stb.. PreCreateWindow: az ablak ltrehozsa eltt fut le, az ablak stlust lehet belltani. Alaprtelmezett egrkurzor belltsa, httr. OnInitialUpdate: A nzet els megrajzolsnl fut le. Itt tudjuk lekrdezni a kirajzolshoz majd szksges adatokat. Pl. karaktermagassg, sorok szma OnDraw: Ez a fggvny fut le, akrhnyszor jra kell rajzolni a nzetet. Teht itt kell megvalstani a nzet megrajzolst. Paramterknt megkapunk egy CDC (Device Context) osztly pointert, ezzel tudunk rajzolni. OnUpdate: CDocument::UpdateAllViews fggvny hatsra minden nzet OnUpdate fggvnye meghvdik. Itt kell gondoskodni a nzet jrarajzolsrl. Azonban nem gy, hogy csak nekillunk s megrajzoljuk, hanem az invalidate fggvnyt meghvjuk, minek hatsra majd lefut az OnDraw fggvny. Ezen kvl lekrdezhetjk a dokumentum mrett, mert ha vltozott, jra kell lltani a ScrollBar-t. OnSize: A nzetablak mretvltoztatsakor hvdik meg, ha hasznlunk grdtsvokat, azokat jra kell lltani. Innen nem kell az jrarajzolssal trdni, hiszen az automatikusan lefut. A Destruktor: A lefoglalt memriaterleteket fel kell szabadtani.

Egyszerbb nzeteket mr eddig is hasznltunk, most a grdthet nzetekkel foglalkozunk. Grdthet nzetek megvalstsa: A Grdts a fggleges s vzszintes grdtsvok segtsgvel trtnik. A grdts azon alapszik, hogy a nzetablakban nem az egsz nzet jelenik meg, hanem csak az a rsze, ami belefr az ablakba. Ez azt jelenti, neknk a nzet kirajzolsnl nem