You are on page 1of 94

Tartalom

1 Objektum orientlt programozs................................................... 1 1.1 Az OOP alapelvei .......................................................................... 2 1.2 Adatrejts ...................................................................................... 3 1.3 Virtulis mez (property) ............................................................... 7 1.4 Constructor, destructor.................................................................. 9 1.5 rkls ........................................................................................ 12 1.6 Virtulis metdus (virtual)............................................................ 14 1.7 Dinamikus metdus (dynamic).................................................... 20 1.8 Absztrakt metdus (abstract) ...................................................... 23 1.9 Tpuskompatibilits...................................................................... 25 1.10 Tpusellenrzs (is opertor) .................................................... 27 1.11 Tpuskonverzi (as opertor) .................................................... 28 1.12 Interface-k (interface) ................................................................ 28 1.13 Osztly-vltozk ........................................................................ 31 1.14 Osztly-metdusok.................................................................... 35 1.15 Hivatkozs a pldnyra a self azonostval .............................. 36 2 OOP a gyakorlatban...................................................................... 38 2.1 Pattog labdk ............................................................................ 38 2.2 szkl alakzatok (kr, tglalap, hromszg) ............................ 47 3 Vizulis komponensek ltrehozsa s megszntetse a program futsa kzben ....................................................................... 56 3.1 Nyomgombok ltrehozsa, megszntetse egrkattintskor ... 59 3.2 Vizulis komponensbl szrmaztatott osztly ............................ 61 4 DLL-ek hasznlata s ltrehozsuk ............................................ 65 4.1 DLL ksztse.............................................................................. 66 4.2 A DLL felhasznlsa alkalmazsunkban .................................... 70 4.3 Statikus s dinamikus importls................................................ 73 4.4 A DLL s a memria.................................................................... 78 4.5 Form trolsa DLL-ben ............................................................... 78 4.6 A DLL (s a benne trolt form) felhasznlsa alkalmazs ksztsekor Delphi-ben.................................................................... 81 4.7 A DLL (s a benne trolt form) felhasznlsa a MS Excel makr nyelvben (Visual Basic) ................................................................... 83 4.8 Erforrsok trolsa DLL-ben ..................................................... 84 4.9 DLL-ben trolt erforrsok felhasznlsa ................................... 87 5 Prhuzamos programozs, szlak .............................................. 90

PaedDr. Vgh Lszl

Programozs Delphi-ben 2

Komrom, 2009. prilis 30.

PaedDr. Vgh Lszl, 2006-2009 http://www.prog.ide.sk

5.1 TThread osztly........................................................................... 90 5.2 Szakaszok prhuzamos kirajzolsa ............................................ 94 5.3 Szlak szinkronizlsa vrakozs egy msik programszlra .. 98 5.4 Programszlak prioritsa........................................................... 102 5.5 Tbbszl MDI alkalmazs ....................................................... 108 6 OLE technolgia.......................................................................... 115 6.1 A Delphi s az OLE ................................................................... 116 6.2 Els OLE-t hasznl alkalmazsunk......................................... 117 6.3 Az OleContainer tulajdonsgai.................................................. 123 6.4 Kulcsszavak lekrdezse s vgrehajtsa ............................... 125 6.5 OLE objektum beolvassa s mentse..................................... 127 6.6 Menk sszekapcsolsa ........................................................... 130 6.7 Sajt Word, Excel, Paint, ...................................................... 133 7 OLE Automation .......................................................................... 137 7.1 MS Word irnytsa Delphi-bl ................................................. 137 7.2 MS Excel irnytsa Delphi-bl ................................................. 141 8 DDE Technolgia ........................................................................ 147 8.1 DDE a Delphiben....................................................................... 148 8.2 Els DDE szerver ...................................................................... 150 8.3 Els DDE kliens......................................................................... 152 8.4 Parancs kldse a szerverre..................................................... 154 8.5 A Microsoft Word, mint DDE kliens ........................................... 159 9 Sg ltrehozsa alkalmazshoz .............................................. 162 9.1 Sg megnyitsa Delphi alkalmazsbl ................................... 170 10 Telept llomny ltrehozsa ................................................... 173 Gyakorlatok:....................................................................................... 177 Irodalomjegyzk: ............................................................................... 184

1 Objektum orientlt programozs


Osztly egy felhasznl ltal ksztett tpus (pl. TElso). Objektum az osztlybl hozzuk ltre, az osztly egy pldnya (pl. ElsoObj). Attribtum az osztly egy mezje, melyben adatot

trolhatunk, miutn az osztlybl egy objektumot ksztettnk (pl. x,y). Metdus az osztly egy eljrsa, mely az adott osztly attribtumaival vgez valamilyen mveletet. (pl. Hozzaad) Pldnyosts egy osztlybl egy konkrt objektum ksztse (pl. ElsoObj := TElso.Create;). Inicializls az objektum-attribtumok kezdrtkeinek

belltsa (pl. ElsoObj.Inicialas; ).

type TElso = class x,y: integer; procedure Hozzaad(xp,yp:integer); procedure Inicialas; end; procedure TElso.Hozzaad; begin x := x + xp; y := y + yp; end; procedure TElso.Inicialas; begin x := 0; y := 0; end;
1

TMasodik az j, szrmaztatott osztly (gyerek). Egy sbl tbb szrmaztatott osztlyt is ltrehozhatunk. Minden var ElsoObj: TElso; begin ElsoObj := TElso.Create; ElsoObj.Inicialas; ElsoObj.Free; end; szrmaztatott osztlynak csak egy se lehet.

Sokalaksg (polymorphism) Ugyanarra a metdusra a klnbz objektumok

klnbzkppen reagljanak. A szrmaztats sorn az sosztlyok metdusai kpesek legyenek az j, tdefinilt metdusok hasznlatra

1.1 Az OOP alapelvei


Egysgbezrs (encapsulation) Az adatokat s a hozzjuk tartoz eljrsokat egyetlen egysgben (osztlyban) kezeljk. Az osztly adatmezi troljk az adatokat, a metdusok kommuniklnak a klvilggal (az osztly adatmezit csak a metdusokon keresztl vltoztathatjuk meg).

jrars nlkl is. Ezt virtulis (vagy dinamikus) metdusokkal rhetjk el.

type TElso = class procedure Akarmi; virtual; end; TMasodik = class(TElso) procedure Akarmi; override; end;

rkls (inheritance) Az osztly tovbbfejlesztse. Ennek sorn a szrmaztatott osztly rkli az sosztlytl az sszes attribtumot, metdust. Ezeket azonban jakkal is kibvthetjk, ill. bizonyos szablyok mellett az rklt metdusokat (metdusok trzst) is megvltoztathatjuk.

1.2 Adatrejts
Public

type TMasodik = class(TElso) end;

Ide kerlnek olyan attribtumok, melyek nem ignyelnek specilis szablyozst. Az ilyen attribtumok rtkeinek megvltoztatsa nem okozhat problmt az objektum mkdsben.

TElso az sosztly (szl).


2

Az itt felsorolt metdusokat a klvilg meghvhatja.

Private Az itt felsorolt attribtumokhoz a klvilg nem frhet hozz. Ide rjuk ltalban azokat a vltozkat, melyek rtkeit szablyozni akarjuk. Tovbb ide kerlnek a seggvltozk is.

Adatrejts elnyei: A mezkhz a hozzfrs szablyozhat.

Adatrejts htrnyai: Az itt szerepl metdusokat a klvilg nem hvhatja meg, csak az adott osztly metdusaibl rhetk el. Nem szablyozhat, hogy csak az olvasst, vagy csak az rst engedlyezzk, illetve tiltjuk. Csak egy idben lehet mindkt elrst engedlyezni / tiltani. Protected Olyan attribtumok, melyekhez a klvilg nem frhet hozz, de a leszrmazott osztlyok metdusai hozzfrhetnek. Az itt feltntetett metdusokat a klvilg nem hvhatja meg, de a leszrmaztatott osztlyok metdusaibl meghvhatk. type TSzemely = class public eletkor: integer; end; type TSzemely = class private nev: string; eletkor: integer; public procedure Valami; end; var Peti: TSzemely; begin Peti.eletkor := 18; end; Adatrejts htrnyai: type TSzemely = class private eletkor: integer; end;
4 5

Adatok nem elrejtsnek a htrnya:

begin Peti.eletkor := -400; end;

{ HIBS rtk }

{ ez NEM mukodik !!! }

begin Peti.eletkor := -400; writeln(Peti.eletkor); end;

1.3 Virtulis mez (property)


{ ez nem mkdik } { de EZ SEM megy } A virtulis mezk (property) segtsgvel jobban megoldhatk az elz problmk az adatrejtsnl:

type Megolds a Set s Get metdusok bevezetsvel: type TSzemely = class private eletkor: integer; public procedure SetEletkor(e:integer); function GetEletkor: integer; end; procedure TSzemely.SetEletkor; begin if (e>0) and (e<100) then eletkor := e else { hiba jelzse} end; function TSzemely.GetEletkor:integer; begin Result := eletkor; end; begin Peti.SetEletkor(-400); Peti.SetEletkor(18); writeln(Peti.GetEletkor); end;
6

TSzemely = class private fEletkor: integer; public procedure SetEletkor(e:integer); property Eletkor:integer read fEletkor write SetEletkor; end; procedure TSzemely.SetEletkor; begin if (e>0) and (e<100) then fEletkor := e else { hiba jelzse} end; begin Peti.Eletkor := -400; Peti.Eletkor := 18; writeln(Peti.Eletkor); end;

{ hibajelzs } { rendben } { rendben }

{ hibajelzs } { rendben } { rendben }

A read utn meg kell adnunk, hogy ha a virtulis mezt (Eletkor) olvassk, mit tegyen a program. Itt kt lehetsgnk van:

a read utn rhatunk egy ugyanolyan tpus fizikai mezt,

1.4 Constructor, destructor


a read utn rhatunk egy paramter nlkli fggvnyt, melynek visszatrsi rtke megegyezik a virtulis mez tpusval. A konstruktor (constructor) specilis metdus, amely feladata az objektum ltrehozsa az osztlybl s annak alaphelyzetbe lltsa (mezk kezdrtkeinek belltsa). A write utn szintn meg kell adnunk mi legyen a teend, ha a virtulis mezbe (Eletkor) j rtket akarnak belerakni. Itt is kt lehetsgnk van: a write utn megadhatunk egy ugyanolyan tpus fizikai mezt, a write utn berhatunk egy eljrst, melynek egyetlen paramtere van s ez ugyanolyan tpus, mint a virtulis mez tpusa. constructor TSzemely.Create; begin fEletkor := 0; end; var Peti: TSzemely; begin Peti := TSzemely.Create; end; type TSzemely = class private fEletkor: integer; public constructor Create; end;

A property kulcssznl nem ktelez megadnunk mindkt mdot (read, write). Ha csak az egyiket adjuk meg, akkor a virtulis mez csak olvashat ill. csak rhat lesz. Tovbb nem ktelez, hogy a virtulis mez mgtt egy fizikai mez lljon. Lehet az olvass s az rs is egy fggvny ill. eljrs segtsgvel megoldva, amelyek valami ms alapjn adnak vissza / lltanak be rtkeket.

A konstruktor neve ltalban Create vagy Init, s br tetszleges nv adhat neki, j betartani ezt a szablyt. Egy osztlyban tbb

konstruktor is ltezhet, de ilyenkor jellemz, hogy ezeknek ms-ms a paramtere.

A destruktor (destructor) szintn egy specilis feladat metdus, amely feladata az objektum megszntetse s a memria felszabadtsa. Itt mg lehetsgnk van a lefoglalt erforrsok (file-ok, memria, hlzati kapcsolatok, ) felszabadtsra.

type TSzemely = class private fEletkor: integer; public constructor Create; constructor Init(kor:integer); end; constructor TSzemely.Create; begin fEletkor := 0; end; constructor TSzemely.Init; begin fEletkor := kor; end; var Peti, Jani: TSzemely; begin Peti := TSzemely.Create; Jani := TSzemely.Init(20); end; var Peti: TSzemely; begin Peti := TSzemely.Create; Peti.Free; { vagy: Peti.Destroy; } end; A destruktor neve ltalban Destroy. A destruktor meghvhatjuk ezzel a nvvel, vagy meghvhatjuk a Free metdus segtsgvel, amely leelenrzi, hogy az objektum ltezik, majd meghvja a Destroy nev destruktort.

type TSzemely = class private fEletkor: integer; public destructor Destroy; override; end; constructor TSzemely.Destroy; begin end;

10

11

Fontos, hogy a programunkban ha egy objektumot mr nem hasznlunk, akkor meghvjuk a Free metdust vagy kzvetlenl a destruktort mieltt kilpnnk a programbl. Ha ezt nem tesszk meg, beragadhat a memriba a lefoglalt terlet s az erforrsok (file, hlzat, ) foglalva maradhatnak.

(sben) szerepl metdust (ilyenkor, ha az j metdus elfedi a rgit, az sosztly nem tudja hasznlni az j metdust).

type TOs = class public function Akarmi:integer; end; TSzarm = class(TOs) public function Akarmi(x:real):real; overload; end; function TOs.Akarmi:integer; begin result := 10; end; function TSzarm.Akarmi(x:real):real; begin result := x + 10.5; end; var p:TSzarm; begin p := TSzarm.Create; writeln(p.Akarmi); writeln(p.Akarmi(1)); p.free; end;

1.5 rkls
Az osztly fejlesztst nem kell nullrl kezdennk, mivel az osztly az stl rkli az sszes mezt, metdust. Ehhez mindssze az sosztly nevt kell feltntetnnk az j (szrmaztatott) osztly deklarlsakor. snek legjobb azt az osztlyt vlasztani, amely legkzelebb ll a mi osztlyunkhoz, amelybl a legkevesebb mdostssal ltre tudjuk hozni az j osztlyt. Ha az osztly deklarlsakor nem vlasztunk st, akkor alaprtelmezsbl a TObject osztly lesz az snk. Mindenkinek a kzs se a TObject. Ebben alapbl van nhny hasznos metdus, pl. Destroy nev destruktor, Free metdus. gyeljnk arra, hogy a szrmaztatott osztlyban ne vezessnk be ugyanolyan nev mezket, mint amilyen mr az sben szerepel, ezek ugyanis elfednk az rklteket. Ugyanolyan nev metdus bevezetse lehetsges, amennyiben ms a paramterezse. Ekkor mindkt metdus elrhet lesz s az aktulis paramterezs dnti el melyiket hvjuk ppen meg. A szrmaztatott objektumban az ugyanolyan nev, de ms paramter metdust overload; szval kell feltntetnnk klnben elfedi az eltte

{ eredmny: 10 } { eredmny: 11.5 }

12

13

1.6 Virtulis metdus (virtual)


Gyakran megtrtnhet, hogy egy osztly metdusa hasznl egy msik metdust ugyanabban az osztlyban. Mi trtnik, ha az ilyen osztlybl leszrmaztatunk egy j osztlyt, s megvltoztatjuk azt a metdust, amelyet a msik hasznl? Pldul:

pa := TAOszt.Create; pb := TBOszt.Create; writeln(pa.Masodik); writeln(pb.Masodik); end;

{ Mennyit r ki? 2-t } { Mennyit r ki? 2-t }

Mi lehetne erre a megolds? Pldul lerhatjuk jra a Masodik fggvnyt is a szrmaztatott osztlyba:

type TAOszt = class public function Elso:integer; function Masodik:integer; end; TBOszt = class(TAOszt) public function Elso:integer; end; function TAOszt.Elso:integer; begin Result := 1; end; function TAOszt.Madosik:integer; begin Result := Elso + 1; end; function TBOszt.Elso:integer; begin Result := 10; end; var pa:TAOszt; pb:TBOszt; begin
14

type TAOszt = class public function Elso:integer; function Masodik:integer; end; TBOszt = class(TAOszt) public function Elso:integer; function Masodik:integer; end; function TAOszt.Elso:integer; begin Result := 1; end; function TAOszt.Madosik:integer; begin Result := Elso + 1; end; function TBOszt.Elso:integer; begin Result := 10; end; function TBOszt.Madosik:integer; begin Result := Elso + 1;
15

end; var pa:TAOszt; pb:TBOszt; begin pa := TAOszt.Create; pb := TBOszt.Create; writeln(pa.Masodik); writeln(pb.Masodik); end;

szrmaztatott

osztlyban

valsznleg

fell

fogjk

definilni.

szrmaztatott osztlyban (s abbl szrmaztatott osztlyokban is) a felldefinilt eljrshoz override; kulcsszt kell kitenni.

{ Mennyit r ki? 2-t } { Mennyit r ki? 11-t }

type TAOszt = class public function Elso:integer; virtual; function Masodik:integer; end; TBOszt = class(TAOszt) public function Elso:integer; override; end; function TAOszt.Elso:integer; begin Result := 1; end; function TAOszt.Madosik:integer; begin Result := Elso + 1; end; function TBOszt.Elso:integer; begin Result := 10; end; var pa:TAOszt; pb:TBOszt; begin pa := TAOszt.Create; pb := TBOszt.Create; writeln(pa.Masodik); writeln(pb.Masodik);
17

J megolds ez? Ez mkdik, de EZ NEM J MEGOLDS, mivel: Az s osztly (TAOszt) fggvnynek programkdjt nem biztos, hogy a TBOszt programozja ismeri. Ha ismeri, ez akkor is felesleges programkd msols (copy-paste) A Masodik fggvny ktszer is szerepel a lefordtott EXE llomnyban, ezrt ennek a hossza is megnagyobbodott. Ha a TAOszt osztly programozja vltoztat a Masodik fggvny kdjn, akkor jra az egszet msolni kell a msik osztlyba is (copy-paste).

A j megolds: virtulis metdus hasznlata. Ez egy olyan metdus, mint brmelyik msik metdus, a virtulis jelzt a programoznak kell rtennie egy virtual; sz hozzrsval az eljrshoz az sosztlyban. Ez azt jelzi a fordtnak, hogy a metdust a

{ Mennyit r ki? 2-t } { Mennyit r ki? 11-t }

16

end;

A leszrmazott osztly VMT-je gy jn ltre, hogy: lemsuljuk az s VMT-jt, ha a leszrmaztatott osztlyban van OVERRIDE, akkor azt a sort kicserljk, ha a leszrmaztatott osztlyban van VIRTUAL, akkor j sort adunk a tblzat vghez. Milyen lesz gy a virtulis metdusok tblja? ugyanazon metdus a tblzatban (sk s

Mit is jelent valjban ez a kulcssz? Az ilyen, virtulis metdusokat a fordt mskpp kezeli. A virtulis metdus hvsnak pillanatban az objektum ismeretben megkeresi a legfejlettebb verzit az adott metdusbl, s ez hvdik meg. Teht az, hogy melyik vltozat Elso fggvny kerl meghvsra, menet kzben dl el. Ezt nevezik sokalaksgnak (polymorphism). Honnan tudja a program eldnteni, hogy melyik vltozatot kell meghvnia, melyik a legfrissebb vltozat? Ebben segt a virtulis metdus tbla (VMT). Minden osztlyhoz kszl egy ilyen tbla, melyben szerepel a virtulis metdus neve s annak elrhetsge. A VMT-ban csak a virtulis metdusok szerepelnek. Pl.:

leszrmazottak VMT-iban) mindig ugyanazon sorban fog szerepelni, a szrmaztatott VMT-ja legalbb annyi elem lesz, mint az s, de ennl hosszabb is lehet (ha van benne j virtulis metdus),

type TElso = class procedure procedure procedure procedure end;

A; B; C; virtual; D; virtual;

ahogy haladunk lefel az rkldsi grfban, gy a VMT-k egyre hosszabbak s hosszabak lesznek.

A VMT elnye: gyors, mivel nem kell keresni a tblzatban, ha az s VMT-ben egy metdus az N. helyen van, akkor minden leszrmazottjnl is az N. sorban lesz. A VMT htrnya: sok memrit ignyel (bejegyzsenknt 4 byte). Minden osztlyhoz 1 VMT tartozik (nem pldnyonknt 1 drb), teht ugyanazon osztlybl ltrehozott objektumnak (pldnynak)

TMasodik = class (TElso) procedure A; procedure C; override; Procedure E; virtual; end;

Ezekhez az osztlyokhoz tartoz VMT-k: TElso.VMT metdus C = TElso.C metdus D = TElso.D TMasodik.VMT metdus C = TMasodik.C metdus D = TElso.D metdus E = TMasodik.E
18

ugyanaz a VMT-ja.

19

Az objektumhoz a VMT hozzrendelst a konstruktor vgzi, ezt a kdrszletet a Delphi generlja bele a konstruktor lefordtott kdjba. A konstruktor nem lehet virtulis, mivel a konstruktor hvsakor mg nem mkdik a mechanizmus (ksi kts).

TBOszt = class(TAOszt) public function Elso:integer; override; end;

A mkdse a programban ugyanaz, mint ha virtulis metdust A konstruktorban a VMT hozzrendelse az objektumhoz a konstruktor elejn trtnik (a Delphiben), gy a konstruktor belsejben mr lehet virtulis metdust hvni. A dinamikus metdusok a VMT-tl egy kicsit eltr, Dinamikus A destruktor (Destroy metdus) mindig virtulis, ezrt tudja a Free metdus meghvni mindig a megfelel destruktort. A virtulis metdus paramterezse s visszatrsi rtke nem vltozhat, mert akkor az s metdusa nem lenne kpes meghvni ezt a felldefinilt vltozatot! type TElso = class procedure procedure procedure procedure end; A; B; C; dynamic; D; dynamic; Metdus Tblt (Dynamic Method Table) hasznlnak a legjabb verzij metdus megtallshoz. Ennek felptst is egy pldn szemlltetjk: hasznltunk volna. A klnbsg a memriafoglalsban s a gyorsasgban van.

1.7 Dinamikus metdus (dynamic)


A dinamikus metdusok hasonlan a virtulis metdusokhoz a polimorfizmus futs kzbeni tmogatsra szolglnak. A Delphiben a dinamikus metdusokat hasonlan tudjuk kialaktani, mint a virtulis metdusokat, csak itt a virtual sz helyett a dynamic szt hasznljuk. Pl.

TMasodik = class (TElso) procedure A; procedure C; override; Procedure E; dynamic; end;

Ezekhez az osztlyokhoz tartoz DMT-k: type TAOszt = class public function Elso:integer; dynamic; function Masodik:integer; end; TElso.DMT s = nil metdus C = TElso.C metdus D = TElso.D TMasodik.DMT s = TElso.DMT metdus C = TMasodik.C metdus E = TMasodik.E

20

21

Mindegyik tblban szerepel az is, hogy melyik osztlybl lett szrmaztatva az j osztly. Ha nincs ilyen osztly, akkor ennek a mutatnak az rtke nil (s = nil). A szrmaztatott osztly DMT-ja a kvetkez kppen alakul ki: a DMT tartalmazza az s DMT cmt (s = TElso.DMT), kezdetben nem msoljuk le az s DMT-jt, hanem csak override esetn vagy dynamic esetn egy j sort szrunk be, A DMT tbla teht csak vltoztatsokat tartalmaz. gy

Melyik metdus legyen dinamikus s melyik virtulis? A DMT akkor kerl kevesebb memriba, ha ritkn van felldefinilva. Ha minden leszrmazott osztlyban felldefiniljuk, akkor tbb memrit ignyel! Msik fontos szempont a vlasztskor, hogy a DMT mindig lassabb! Ezrt dinamikus legyen egy metdus, ha szmtunk arra, hogy ritkn lesz csak felldefinilva, tovbb gy gondoljuk, hogy a metdus ritkn kerl meghvsra, s ezrt nem szmt a sebessgcskkens. Virtulis legyen egy metdus minden ms esetben, teht ha srn felldefiniljuk, vagy a metdust srn hvjuk (pl. egy ciklusban) s fontos a sebessg.

lehetsges, hogy valamelyik metdusra utal bejegyzs nem is szerepel csak az sben, vagy annak az sben (amennyiben a leszrmazott osztlyokban nem lett flldefinilva az override segtsgvel). A fentiekbl addik, hogy futs kzben a DMT-k kztt lehet, hogy keresni kell. Ha nincs az adott dinamikus metdusra utals az objektumhoz tartoz DMT tblban, akkor meg kell nzni az s DMTjben, ha ott sincs, akkor annak az snek a DMT-jben, stb. A DMT elnye: kevesebb memrit ignyel, mivel nincs az s egsz DMT-je lemsolva, csak a vltoztatsok vannak bejegyezve. A DMT htrnya: a keress miatt lassabb. A dinamukus s virtulis metdusokat lehet keverni egy osztlyon bell. Teht egy osztlyban lehetnek dinamukus s virtulis metdusok is. Azt, hogy valamelyik metdus milyen lesz, a metdus legels bevezetsekor kell megadni a virtual vagy dynamic kulcssz segtsgvel. A ksbbiekben (leszrmazottakban) a felldefinilshoz mindig az override-t kell hasznni.

1.8 Absztrakt metdus (abstract)


Nzzk meg, hogyan nzhetne ki egy osztly, amelyet azrt hozunk ltre, hogy ksbb ebbl szrmaztassunk j osztlyokat, pl. kr, ngyzet, tglalap grafikus objektumok osztlyait.

type TGrafObj = class private x,y: integer; public procedure Kirajzol; virtual; procedure Letorol; virtual; procedure Mozgat(ujx, ujy: integer); end; procedure TGrafObj.Mozgat; begin

22

23

Letorol; x := ujx; y := ujy; Kirajzol; end;

procedure Mozgat(ujx, ujy: integer); end;

Az ilyen oszlybl tilos objektum ltrehozsa (pldnyosts), az ilyen osztly csak azrt van ltrehozva, hogy abbl szrmaztassunk j osztlyakat. Ha mgis megprblkoznnk vele, a fordt figyelmeztet bennnket, hogy az osztly absztrakt metdust tartalmaz. A szrmaztatott osztlyoknl az absztrakt metdusokat az override kulcssz segtsgvel rhatjuk fell. Nem ktelez rgtn mindegyiket fellrni, de akkor megint nem lehet pldnyostani (objektumot ltrehozni belle). Az absztrakt metdusnak mindig virtual vagy dynamic-nak

A krds az, hogyan nzzen ki a Kirajzol s Letrl metdusok programkdja. Konkrt esetben (teht az ebbl leszrmaztatott osztlyokban) tudjuk, hogy egy kr, ngyzet, tglalap, stb., de ltalnos esetben ezt nem tudjuk. Ezrt itt ez a kvetkez mdon nzhetne ki, mivel ez a leszrmazottakban gyis fell lesz definilva (kr, ngyzet, tglalap, stb. kirajzolsra):

procedure TGrafObj.Kirajzol; begin end;

kell lennie, klnben hibazenetet kapunk. Ezzel mert amikor ebbl elrtk azt, hogy a fordtprogram figyelmeztet

bennnket, ha elfelejtettk felldefinilni a szrmaztatott osztlyokban De ez NEM J MEGOLDS, az absztrakt metdusokat (Kirajzol, Letorol) legksbb akkor, amikor a TKor osztlybl objektumot akarunk ltrehozni. tovbbfejlesztnk pl. egy TKor osztlyt, akkor a fordtprogram nem fog szlni, hogy ezen kt metdust ktelez neknk felldefinilni! gy elfeledkezhetnk rla! Erre az esetre szolgl az absztrakt metdus, amely egy olyan metdus, melynek trzst nem kell megrnunk, csak az osztly definilsnl kell felsorolnunk: procedure JobbraMozdit(graf: TGrafObj); begin graf.Mozgat(graf.x + 1, graf.y); end;

1.9 Tpuskompatibilits
Milyen objektumokat lehet tadni az albbi eljrsnak?

type TGrafObj = class private x,y: integer; public procedure Kirajzol; virtual; abstract; procedure Letorol; virtual; abstract;
24

25

Az eljrsnak tadhat minden olyan objektum, amely a TGrafObj osztlybl vagy annak valamelyik gyerekosztlybl kszlt.

1.10 Tpusellenrzs (is opertor)


Elfordulhat azonban, hogy nem sikerl tallni a fenti

var k: TKor; n: TNegyzet; begin JobbraMozdit(k); JobbraMozdit(n); end.

kvetelmnynek megfelel tpust. Ilyenkor olyan tpust kell megadni, amelyikkel minden szba jhet pldny kompatibilis (ez legrosszabb esetben a TObject), s az eljrson bell if-ek (elgazsok) segtsgvel kell eldnteni, hogy a paramterknt megadott pldny valjban milyen tpusba tartozik. A tpus vizsglathoz az is opertor hasznlhat a kvetkez kppen: objektumnv IS osztlynv. Pl.:

Teht: a gyermek-osztlyok fellrl kompatibilis tpusok az sosztlyukkal, s azok seivel is: biztos, hogy megvannak nekik is ugyanazon nev mezk s metdusok, mint az snek (mivel rklte ket). Ebbl kvetkezik, hogy minden osztly kompatibilis a TObjectel.

procedure JobbraMozdit(graf: TObject); begin if graf is TKor then end;

A then gra akkor kerl a vezrls, ha a graf objektum Viszont a JobbraMozdit eljrs az albbi paramterezssel nem mkdik, mivel a TObject-nek nincs Mozgat metdusa. kompatibilis a TKor osztllyal. Vagyis ha a graf egy TKor vagy annak valamelyik leszrmazott osztlybl ltrehozott objektum. De az albbi mdon az eljrs mg mindig nem mkdik, procedure JobbraMozdit(graf: TObject); begin graf.Mozgat(graf.x + 1, graf.y); end; ugyanis a graf-rl az eljrs mg mindig gy tudja, hogy TObject s ennek nincs Mozgat metdusa.

Teht a tpus megvlasztsnl mindig azon osztly nevt kell megadni, amelyik mr tartalmazza az sszes olyan metdust s mezt, amelyekre az eljrs trzsben hivatkozunk.

procedure JobbraMozdit(graf: TObject); begin if graf is TKor then graf.Mozgat(graf.x + 1, graf.y); end;

Az is opertor csak egy ellenrz fggvny, nem alaktja t a TObject-et TKor-!


26 27

1.11 Tpuskonverzi (as opertor)


A fenti problma megoldsra alkalmazhat az as opertor. Ennek hasznlata: objektumnv AS osztlynv. Pl:

TObject

TKor (van Mozgat)

TLabda (van Mozgat)

procedure JobbraMozdit(graf: TObject); begin if graf is TKor then (graf as TKor).Mozgat(graf.x + 1, graf.y); end;

Van egy TKor osztlyunk, melyet a TObject-bl szrmaztattunk s van egy TLabda osztlyunk, melyet szintn a TObject-bl szrmaztattunk. Mindkt szrmaztatott osztlynak van Mozgat metdusa, mellyel a megadott osztlybl ksztett objektumot adott x,y

vagy egy msik megolds: procedure JobbraMozdit(graf: TObject); begin if graf is TKor then TKor(graf).Mozgat(graf.x + 1, graf.y); end;

koordintkra helyezzk. A TObject osztlynak (s osztlynak) viszont nincs ilyen Mozgat metdusa. Milyen tpust adjunk meg ilyenkor az albbi eljrs paramtereknt?

Ilyenkor a kifejezs idejre az objektumot a fordtprogram gy tekinti, mintha az adott osztlybl kszlt pldny lenne. Ha az as opertort helytelenl alkalmazzuk (pl. az objektum nem kompatibilis a megadott osztllyal), akkor futs kzben hibazenetet kapunk! Ezrt az as opertort az is opertorral val vizsglat utn alkalmazzuk!

procedure ArrebRak(x: ); begin x.Mozgat(12,17); end;

Eddigi ismereteink alapjn az egyetlen szba jhet osztly a TObject, viszont ekkor az eljrs belsejt meg kell vltoztatnunk a kvetkezre:

if (x is TKor) then (x as TKor).Mozgat(12,17); if (x is TLabda) then (x as TLabda).Mozgat(12,17);

1.12 Interface-k (interface)


Kpzeljk el, hogy a kvetkez helyzet ll el: Ez azonban nem a legjobb megolds, ugyanis ksbb ha jabb osztlyok kerlnek el, melyeknek van Mozgat metdusuk, azokra jabb if-ekkel kell kiegszteni az eljrst.
28 29

Az ilyen esetekben a megolds az interface hasznlata lehet. Segtsgvel azt lehet lerni, hogy klnbz gakon lev osztlyokban mi a kzs:

type TKor = class(IMozgathato) public procedure Mozgat(x,y: integer); end; TLabda = class(IMozgathato) public procedure Mozgat(x,y: integer); end;

type IMozgathato = interface procedure Mozgat(x,y: integer); end;

Az interface olyan osztlynak ltsz valami, melyben: csak a metdusok fejrsze van lerva, de soha nincs kidolgozva egyetlen metdus sem, tartalmazhat property-ket is, de szintn nincsenek kidolgozva, csak a property neve van megadva, tpusa, s az, hogy rhat vagy olvashat, mezket viszont nem tartalmazhat az interface, szintn nem tartalmazhat konstruktort s destruktort,

Az ArrebRak eljrsunk pedig gy mdosul:

procedure ArrebRak(x: IMozgathato) begin x.Mozgat(12,17); end;

tpuskompatibilitst

teht

kibvthetjk:

az

osztly

kompatibilis az seivel s az interface-ekkel is, melyeket megvalst. Egy osztlynak mindig csak egy se lehet, de teszleges szm minden rsz az interface-ben automatikusan publikus, ms nem lehetsges, a metdusokat nem lehet megjellni virtual, dynamic, abstract, override kulcsszavakkal, az interface-eknek lehetnek sei, melyek szintn type TKor = class(TGrafObj, IMozgathato, ITorolheto) end; interface-t implementlhat. Pl.:

interface-ek. Miutn definiltuk az interface-t, az objektumokat, melyek implementljk ezt az interface-t a kvetkez kppen definilhatjuk: Hogyan hozhatunk ltre olyan mezt, amely pl. azt szmolja, hogy mennyi objektumot ksztettnk az adott osztlybl. Legyen ennek
30 31

1.13 Osztly-vltozk

a meznek a neve darab. Ekkor az osztly a kvetkez kppen nzhet ki:

end; end.

type TAkarmi = class constructor Create; end; constructor TAkarmi.Create; begin darab := darab + 1; end;

A Delphi-ben teht az ilyen mezk valjban egyszer globlis (statikus) vltozk. Ms nyelveken, mint pl. a Java, C# az ilyen jelleg mezket az osztly rszv lehet tenni, termszetesen megjellve, hogy azok csak egy pldnyban kellenek. Erre ltalban a static mdost sz hasznlhat.

De hol deklarljuk a darab mezt? A TAkarmi osztlyon bell nem deklarlhatjuk, mivel ekkor minden pldnyostsnl egy j mez jn ltre, melynek rtke kezdetben meghatrozatlan. A megolds, hogy nem az osztlyban, hanem a Unit-ban deklarljuk:

A kvetkez krds, hogy hogyan lehet az ilyen vltozk kezdrtkt megadni. Ezt a unit inicializcis rszben tehetjk meg:

unit Sajat; interface type TAkarmi = class constructor Create; end; implementation var darab: integer; constructor TAkarmi.Create; begin darab := darab + 1; end; initialization
33

unit Sajat; interface type TAkarmi = class constructor Create; end; implementation var darab: integer; constructor TAkarmi.Create; begin darab := darab + 1;
32

darab := 0; end.

result := darab; end; initialization

Ms programozsi nyelveken erre ltezik egy .n. osztly szint konstruktor, mely a program indulsnak elejn hvdik meg.

darab := 0; end.

Hogyan tudjuk az ilyen mezk rtkt lekrdezni? Ha a mez a unit interface rszben lenne deklarlva, akkor egyszeren elrhet a unit-on kvlrl is. Ha az implementation rszben van deklarlva, mint a mi esetnkben is, akkor nem rhet el kvlrl, teht kell hozz ksztennk egy fggvny, amely kiolvassa az rtkt: var x: TAkarmi; begin x := TAkarmi.Create; Write(Eddig ,x.Darabszam, objektum van.); end; Ez azonban nem a legjobb megolds, mivel a Darabszam fggvny hasznlathoz ltre kell hoznunk egy objektumot a TAkarmi osztlybl:

unit Sajat; interface type TAkarmi = class constructor Create; function Darabszam: integer; end; implementation var darab: integer; constructor TAkarmi.Create; begin darab := darab + 1; end; function TAkarmi.Darabszam; begin
34

1.14 Osztly-metdusok
Az osztly szint metdusok segtsgvel megoldhat a fenti problma, mivel az ilyen metdusok hvhatk pldnyosts nlkl is. Az osztly-metdusok a class mdost szval vannak megjellve.

type TAkarmi = class class function Darabszam: integer; end;

35

class function TAkarmi.Daraszam; begin result := Darab; end;

Vesztett(nyertes: TJatekos); procedure Gratulal(gratulalo: TJatekos); end; procedure TJatekos.Vesztett; begin penz := penz 1000; nyertes.penz := nyertes.penz + 1000; nyertes.Gratulal(self); end; procedure TJatekos.Gratulal; begin writeln(Gratulalt nekem: ,gratulalo.nev); end;

Ezt a fggvnyt most mr pldnyosts nlkl is tudjuk hasznlani:

begin Write(Eddig ,TAkarmi.Darabszam, drb van.); end;

A ilyen osztly szint metdusok belsejben csak osztly szint mezket hasznlhatunk, pldny szintt (melyek az osztly belsejben vannak definilva) nem hasznlhatunk!

1.15 Hivatkozs a pldnyra a self azonostval


Az objektumra a sajt metdusnak belsejben a self (ms nyelvekben this) azonostval hivatkozhatunk. Pl:

type TJatekos = class nev: string; penz: integer; procedure


36 37

2 OOP a gyakorlatban
Ebben a rszben nhny gyakorlati pldn keresztl szemlltejk az objektum orientlt programozs alapjait. A gyakorlatban az osztlyokat (azok deklarcijt s

metdusainak implementcijt) mindig kln Unit-ba tegyk, gy programunk ttekinthet lesz s be lesz biztostva az adatrejts is az alkalmazson bell. j unitot az alkalmazsba a File New Unit - Delphi for Win32 menpont segtsgvel tehetnk.

2.1 Pattog labdk


Ebben az alkalmazsban ksztnk egy TLabda osztlyt, melyet kihasznlva runk egy olyan programot, melyben labdkat jelentnk meg. Mindegyik labda valamilyen irnyba mozog, ha elri a kp szlt, akkor visszapattan. Ha valamelyik labda tkzik egy msik labdval, akkor elpattannak egymstl. Pelda01 Nzzk elszr is mit tartalmaz a TLabda osztlyunk, melyet a Unit2 modulban rtunk meg:

unit Unit2; interface uses ExtCtrls, Graphics; type TLabda = class private hova:TImage; sz:integer;
38 39

public x,y,dx,dy:integer; constructor Create(kx, ky, kdx, kdy, ksz:integer; khova:TImage); procedure Kirajzol; procedure Letorol; procedure Mozgat; end; implementation constructor TLabda.Create; begin x:=kx; y:=ky; dx:=kdx; dy:=kdy; sz:=ksz; hova:=khova; end; procedure TLabda.Kirajzol; begin hova.Canvas.Pen.Color := sz; hova.Canvas.Pen.Width := 2; hova.Canvas.Brush.Color := sz; hova.Canvas.Ellipse(x-20,y-20,x+20,y+20); end; procedure TLabda.Letorol; begin hova.Canvas.Pen.Color := clWhite; hova.Canvas.Pen.Width := 2; hova.Canvas.Brush.Color := clWhite; hova.Canvas.Ellipse(x-20,y-20,x+20,y+20); end; procedure TLabda.Mozgat; begin Letorol; x:=x+dx; y:=y+dy; if (x+dx+20>hova.Width) or (x+dx-20<0) then dx:=-dx;
40

if (y+dy+20>hova.Height) or (y+dy-20<0) then dy:=-dy; Kirajzol; end; end.

A TLabda osztlyunk hova mezjben jegyezzk meg azt az Image komponenst, ahov a labdt kirajzoljuk. Az sz mezben a labda sznet troljuk. Az x, y mezkben vannak a labda aktulis koordinti a kphez viszonytva, a dx s dy mezkben pedig azt jegyezzk meg, hogy a labda j helyzete az elz helyzethez kpest mennyivel legyen arrbb (ezek rtke valjban csak -1, 0, 1 pixel lehet, melyek megadjk egyben a labda mozgsnak az irnyt is).

41

Az brn a szrke kr jelli a labda rgi helyt, a fekete a labda j helyt egy elmozduls utn. Lthatjuk, hogy a labda j x, y koordintit gy szmthatjuk ki, hogy az x-hez hozzadjuk a dx-et, yhoz pedig a dy-t. Az osztlyban definiltunk egy Create konstruktort, melynek paramtereknt megadjuk a kezdeti x, y, dx, dy rtkeket, ahol a labda a ltrehozskor megjelenjen, a labda sznt s azt, hogy hova akarjuk a labdt kirajzolni (melyik Image komponensre). A konstruktorunk valjban csak annyibl ll, hogy ezeket a paramterben megadott rtkeket hozzrndeli az objektum megfelel mezihez. A Kirajzol metdus kirajzol a hova mezben megjegyzett image komponensre egy 20 pixel sugar krt az sz-ben trolt sznnel. A Letorol metdus egy ugyanilyen krt rajzol ki, csak fehr sznnel. Teht valjban letrli a krt. A Mozgat metdus letrli a krt a Letorol metdus

Az alkalmazsunkban lesz egy 10 elem TLabda tpus tmb, mely valjban a 10 pattog labda objektumunk lesz. Ezt a 10 objektumot a Form OnCreate esemnyben fogjuk ltrehozni. A labdk mozgatst a Timer OnTimer esemnyben vgezzk el. Vgl a programbl val kilpskor a Form megszntetsekor a Form OnDestroy esemnyben felszabadtjuk az objektumoknak lefoglalt memrit. Alkalmazsunk forrskdja gy nz ki:

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Unit2; type TForm1 = class(TForm) Image1: TImage; Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation
43

meghvsval, majd kiszmolja a labda j x s y koordintit figyelembe vve azt, hogy ha a labda mr kimenne a kp szln, akkor a dx vagy dy-t az ellenttesre vltoztatja. Vgl kirajzolja a labdt a Kirajzol metdus meghvsval. Ezt a TLabda osztlyt fogjuk most az alkalmazsunkban felhasznlni. Ehhez az alkalmazsunk formjn hozzunk ltre egy Image komponenst, melyre a labdkat fogjuk kirajzoltatni (Image1) s egy Timer komponenst (Timer1), amely a labdk arrbb mozdtst a megadott idkzkben elvgzi. Ezt az intervallumot lltsuk be 10 ezredmsodpercre. Ne felejtsk el a programunk uses rszt kibvteni a Unit2 modullal, melyben a TLabda osztlyt ksztettk el.

42

{$R *.dfm} var l:array [1..10] of TLabda; function Utkozik(a,b:TLabda):boolean; begin if Sqrt(Sqr(a.x-b.x)+Sqr(a.y-b.y))<=40 then result := true else result := false; end; procedure TForm1.FormCreate(Sender: TObject); var i,j,kdx,kdy:integer; ok:boolean; begin randomize; for i:=1 to 10 do begin repeat kdx:=random(3)-1; kdy:=random(3)-1; until (kdx<>0) or (kdy<>0); l[i]:=TLabda.Create(random(Image1.Width-60)+30, random(Image1.Height-60)+30, kdx, kdy, RGB( random(256), random(256), random(256)), Image1); repeat ok:=true; for j:=1 to i-1 do if utkozik(l[i],l[j]) then ok:=false; if not ok then begin l[i].x := random(Image1.Width-60)+30; l[i].y := random(Image1.Height-60)+30; end; until ok; l[i].Kirajzol; end; end;
44

procedure TForm1.Timer1Timer(Sender: TObject); var i,j,k:integer; begin for i:=1 to 10 do begin l[i].Mozgat; for j:=i+1 to 10 do if Utkozik(l[i],l[j]) then begin k:=l[i].dx; l[i].dx:=l[j].dx; l[j].dx:=k; k:=l[i].dy; l[i].dy:=l[j].dy; l[j].dy:=k; end; end; end; procedure TForm1.FormDestroy(Sender: TObject); var i:integer; begin for i:=1 to 10 do l[i].Free; end; end.

A programban ltrehoztunk egy Utkozik nev fggvnyt, melynek mindkt paramtere TLabda tpus. Ez a fggvny

megllaptja, hogy a paramterekben megadott labdk tkznek-e. Valjban ezt gy llaptjuk meg, hogy kiszmoljuk a kt labda kztti tvolsgot, s ha ez kisebb vagy egyenl mint 40 (mivel minden labdnak a sugara 20), akkor tkzs ll fenn. A Form OnCreate esemnyben sorban ltrehozzuk a labdkat vletlenszer adatokkal. Minden labda ltrehozsa utn ellenrizzk, hogy nem tkzik-e valamelyik mr eltte ltrehozott
45

labdval. Ha tkzs van, akkor az j labdnak ms vletlen koordintkat generlunk ki s jbl leellenrizzk, nem tkzik-e valamelyik labdval. Ezt mindaddig ismtelgetjk, amg nem sikerl olyan koordintkat kigenerlnunk, melynl mr a labda nem tkzik egyik eltte ltrehozott labdval sem. Vgl a Kirajzol metdus segtsgvel ltrehozsa A Timer OnTimer esemnyben mindegyik labdnak kirajzoljuk a labdt, s jhet a kvetkez labda

irnyokat (melyek valjban a kt labda dx, dy mezinek felcserlsvel jttek ltre). A Form OnDestroy esemnyben csupn egy ciklus segtsgvel meghvjuk az sszes objektum Free metdust, gy felszabadtjuk a lefoglalt memrit.

2.2 szkl alakzatok (kr, tglalap, hromszg)


A kvetkez feladatban ksztnk egy alkalmazst, melynek ablakn (egy image komponensen) klnbz alakzatok (krk, tglalapok, hromszgek) fognak mozogni, midegyik alakzatnak lesz egy sajt irnya. Az alakzatok egymson keresztlmehetnek, nem fogjuk figyelni az egymssal val tkzsket. Ha azonban az alakzat kzepe kimenne az alkalmazs ablaknak (pontosabban az image komponensnek) valamelyik szln, akkor az irnyt megvltoztatjuk gy, hogy az alakzat visszapattanjon. Pelda02

meghvjuk a Mozgat metdust, majd leelenrizzk hogy a labda az j helyen nem tkzik-e valamelyik utna kvetkez labdval. Ha tkzs ll fenn, akkor egyszeren kicserljk a kt labda dx, dy adatait, gy gy nz ki, mintha a kt labda elpattanna egymstl (amelyik irnyba mozgott az egyik labda, abba fog mozogni a msik s amelyikbe mozgott a msik, abba az irnyba fog mozogni az elz labda).

A szrke nylak jellik az tkzs eltti rgi irnyokat (melyek dx, dy segtsgvel vannak meghatrozva), a piros nyilak jellik az j

46

47

a krt, tglalapot s hromszget megvalst osztlyokat. Ennek az ltalnos grafikus osztlynak a programunkban a TGrafObj nevet adtuk. Ebbl az osztlybl hozzuk ltre az rklst felhasznlva a TKor, TTeglalap s THaromszog osztlyokat. Az osztlyokat tartalmaz Unit2 modulunk gy nz ki:

unit Unit2; interface uses ExtCtrls,Graphics; type TGrafObj = class private x,y: integer; dx,dy: integer; kep: TImage; public constructor Create(kx, ky, kdx, kdy: integer; kkep: TImage); procedure kirajzol; virtual; abstract; procedure letorol; virtual; abstract; procedure mozdul; end; TKor = class (TGrafObj) private s:integer; public constructor Create(kx, ky, kdx, kdy, ks: integer; kkep: Timage); procedure kirajzol; override; procedure letorol; override; end; TTeglalap = class (TGrafObj) private a,b:integer; public
49

Az egyes alakzatok valjban objektumok lesznek. Mindegyik objektumnak lesz x, y koordintja, dx, dy mezi, melyek megadjk az alakzat mozgsnak irnyt (ahogy az elz feladatban). Tovbb mindegyik objektumnak lesz egy mozdul metdusa, amely ugyangy fog kinzni a krnl, tglalapnl s hromszgnl is. Ennek egyetlen feladata lesz: letrlni az alakzatot, kiszmolni az j koordintkat s kirajzolni az alakzatot. Lthatjuk, hogy valjban a kr, tglalap s hromszg objektumok nagyon hasonltanak egymsra, csupn abban klnbznek, hogy mit rajzolnak ki a kpernyre. Ezrt mindenekeltt ltrehozunk egy ltalnos grafikus osztlyt, melybl majd szrmaztatjuk
48

constructor Create(kx, ky, kdx, kdy, ka, kb: integer; kkep: Timage); procedure kirajzol; override; procedure letorol; override; end; THaromszog = class (TGrafObj) private a,m:integer; public constructor Create(kx, ky, kdx, kdy, ka, km: integer; kkep: TImage); procedure kirajzol; override; procedure letorol; override; end; implementation constructor TGrafObj.Create; begin x := kx; y := ky; dx := kdx; dy := kdy; kep := kkep; kirajzol; end; procedure TGrafObj.mozdul; begin letorol; if (x+dx>kep.Width) or (x+dx<0) then dx := -dx; x := x + dx; if (y+dy>kep.Height) or (y+dy<0) then dy := -dy; y := y + dy; kirajzol; end; constructor TKor.Create; begin s := ks; inherited Create(kx,ky,kdx,kdy,kkep); end; procedure TKor.kirajzol;
50

begin kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clRed; kep.Canvas.Ellipse(x-s,y-s,x+s,y+s); end; procedure TKor.letorol; begin kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clWhite; kep.Canvas.Ellipse(x-s,y-s,x+s,y+s); end; constructor TTeglalap.Create; begin a := ka; b := kb; inherited Create(kx,ky,kdx,kdy,kkep); end; procedure TTeglalap.kirajzol; begin kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clGreen; kep.Canvas.Rectangle(x - a div 2, y - b div 2, x + a div 2, y + b div 2); end; procedure TTeglalap.letorol; begin kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clWhite; kep.Canvas.Rectangle(x - a div 2, y - b div 2, x + a div 2, y + b div 2); end; constructor THaromszog.Create; begin a := ka; m := km; inherited Create(kx,ky,kdx,kdy,kkep); end; procedure THaromszog.kirajzol; begin
51

kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clBlack; kep.Canvas.MoveTo(x - a div 2, y + m div 2); kep.Canvas.LineTo(x + a div 2, y + m div 2); kep.Canvas.LineTo(x, y - m div 2); kep.Canvas.LineTo(x - a div 2, y + m div 2); kep.Canvas.FloodFill(x,y,clBlack,fsBorder); kep.Canvas.Pen.Color := clBlue; kep.Canvas.MoveTo(x - a div 2, y + m div 2); kep.Canvas.LineTo(x + a div 2, y + m div 2); kep.Canvas.LineTo(x, y - m div 2); kep.Canvas.LineTo(x - a div 2, y + m div 2); end; procedure THaromszog.letorol; begin kep.Canvas.pen.Width := 2; kep.Canvas.Pen.Color := clWhite; kep.Canvas.MoveTo(x - a div 2, y + m div 2); kep.Canvas.LineTo(x + a div 2, y + m div 2); kep.Canvas.LineTo(x, y - m div 2); kep.Canvas.LineTo(x - a div 2, y + m div 2); end;

rtkt, majd az

inherited

Create(kx,ky,kdx,kdy,kkep);

parancs segtsgvel meghvjuk az s (TGrafObj) osztly Create metdust, amely elvgzi a tbbi belltst s kirajzolja az alakzatot. Tovbb megrjuk a TKor Kirajzol s Letorol metdusait. A Kirajzol metdus egy fehr belsej, piros krvonal, 2 vonalvastagsg krt rajzol ki. A Letorol metdus valjban ugyanazt a krt rajzolja ki, csak piros helyett fehr sznnel. Hasonlan ksztjk el a TTeglalap s THaromszog

osztlyakat, melyeket szintn a TGrafObj osztlybl szrmaztatunk. Miutn elksztettk az egyes osztlyakat, megrhatjuk az alkalmazst, amely ezeket hasznlja fel. Hasonlan az elz feladathoz itt is egy Image komponensen fogjuk megjelentteni az objektumokat s az objektumok mozgatst egy Timer komponens segtsgvel valstjuk meg. Az alkalmazs forrskdja:

end. unit Unit1; Ami rdekes a TGrafObj osztlynl s mg nem tallkoztunk vele az elz feladatban, az a Letorol s Kirajzol metdusok, melyek itt virtulis, abstrakt metdusok. Teht itt csak felsoroljuk ket, de azt, hogy konkrtan mit csinljanak ezek a metdusok, nem adjuk meg (nem implementljuk ket). Ez rthet, hiszen itt ez csak egy ltalnos grafikus osztly, melynl mg nem tudjuk mit fog kirajzolni s letrlni. Ezt a TGrafObj osztlyt csupn azrt ksztettk, hogy ebbl knnyel ltrehozhassuk a msik hrom osztlyt. A TKor osztlynak lesz egy plussz mezje, ami a kr sugart jelli (s). A Create metdusban belltjuk ennek a meznek a kezdeti uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Unit2; type TForm1 = class(TForm) Image1: TImage; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Timer1Timer(Sender: TObject); private
53

interface

52

{ Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} var k: array [1..15] of TGrafObj; procedure TForm1.Timer1Timer(Sender: TObject); var i: integer; begin for i:=1 to 15 do k[i].mozdul; end; procedure TForm1.FormCreate(Sender: TObject); var i: integer; mx,my: integer; begin randomize; for i:=1 to 15 do begin repeat mx:=random(5)-2; my:=random(5)-2; until (mx<>0) or (my<>0); if i mod 3 = 0 then k[i]:=TKor.Create(random(Image1.Width), random(Image1.Height), mx, my, random(20)+10, Image1) else if i mod 3 = 1 then k[i]:=TTeglalap.Create(random(Image1.Width), random(Image1.Height), mx, my, random(50)+10, random(50)+10, Image1) else k[i]:=THaromszog.Create(random(Image1.Width), random(Image1.Height),
54

mx, my, random(50)+10, random(50)+10, Image1); end; end; procedure TForm1.FormDestroy(Sender: TObject); var i:integer; begin for i:=1 to 15 do k[i].Free; end; end.

Megfigyelhetjk, hogy a programban ugyanazt a tmbt hasznljuk a TKor, TTeglalap, THaromszok objektumokra is. Ez azrt lehetsges, mivel ezt a tmbt TGrafObj tpusnak deklarltuk, s a TGrafObj kompatibilis az sszes leszrmaztatott osztllyal. A Form OnCreate esemnyben ltrehozzuk az egyes objektumokat vletlenszer rtkekkel. Attl fggen, hogy a

ciklusvltoz 3-al val osztsi maradka 0, 1 vagy 2, a tmb adott elemhez TKor, TTeglalap vagy THaromszog osztlyokbl hozunk ltre objektumot. A Timer OnTimer esemnyben mindegyik objektumnak meghvjuk a Mozdul metdust, amely az adott alakzatot eggyel arrbb helyezi. A Form OnDestroy esemnyben megszntetjk az egyes objektumokat a Free metdusuk segtsgvel, ezzel felszabadtjuk a lefoglalt terletet a memriban.

55

3 Vizulis komponensek ltrehozsa s megszntetse a program futsa kzben


Mivel a vizulis komponensek is objektumok, amelyek bizonyos osztlyokbl lettek ltrehozva, ezrt ezeknl is felhasznlhatjuk ez elz fejezetekben tanultakat. Amikor pldul tervezsi nzetben egy nyomgombot tesznk a formra, melynek neve Button1 lesz, akkor valjban a TButton osztlybl hozunk ltre egy pldnyt (objektumot), amely a Button1. Vizulis komponenseket a program futsa alatt is brmikor ltre tudunk hozni. Pldul egy nyomgomb a program futsa alatt a kvetkez nhny sorral hozhat ltre:

programkdot. Termszetesen Self helyett rhattunk volna Form1-et is, ha ez a neve a formunknak. Amikor a nyomgomb tulajdonosa felszabadul a memribl (teht a mi esetnkben a form), akkor automatikusan a nyomgomb is felszabadul. Ebben az esetben teht nem kell trdnnk a nyomgombunk felszabadtsval, amennyiben azt szeretnnk, hogy az ltezzen addig, amg a formunk ltezik. Termszetesen, ha elbb meg szeretnnk szntetni a nyomgombot, akkor azt felszabadthatjuk a MyButton.Free metdussal. A gomb ltrehozsa utn meg kell adnunk a gomb szljt (MyButton.Parent). Amit megadunk a gomb szljnek, azon a komponensen fog elhelyezkedni a nyomgomb. A mi esetnkben itt szintn Self-et adtunk meg, ami ebben az esetben az alkalmazsunk formjt jelenti. Itt is megadhattuk volna helyette pl. a Form1-et, vagy

var MyButton: TButton; MyButton := TButton.Create(Self) MyButton.Parent := Self; MyButton.Left := 10; MyButton.Top := 10; MyButton.Caption := 'Katt ide';

akr Panel1-et, ha van panel komponensnk a formon. Vgl megadjuk a gomb elhelyezkedst a Top s Left tulajdonsgok segtsgvel, s a gombon megjelentend szvegget a Caption tulajdonsg segtsgvel. A futsidben ltrehozott nyomgombhoz is adhatunk meg esemnyeket. Ha pldul azt szeretnnk, hogy a felhasznlnak a gombunkra kattintskor trtnjen valami, akkor elbb meg kell rnunk az OnClick esemnyhez tartoz eljrst, majd ezt az eljrst hozzrendelni a mi nyomgombunk OnClick esemnyhez. Ehhez a kvetkez sorokkal kell kibvtennk alkalmazsunk forrskdjt:

Mivel a TButton az StdCtrls unitban van definilva, ezrt ha nem hasznlunk mshol nyomgombot, ezzel a unittal ki kell bvtennk a programunk uses rszt. A nyomgomb ltrehozsakor a Create konstruktor

paramtereknt meg kell adnunk azt a vizulis komponenst, amely a nyomgomb tulajdonosa legyen. Ha itt Self-et adunk meg, akkor a gomb tulajdonosa az a form lesz, amely tartalmazza a fent lert

type TForm1 = class(TForm) FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;


57

56

X, Y: Integer); private { Private declarations } procedure MyButtonClick(Sender:TObject); public { Public declarations } end; implementation {$R *.dfm} procedure TForm1.MyButtonClick(Sender:TObject); begin { ide jn az a programrsz, amely a gomb megnyomsakor tortnjen } end; procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var MyButton: TButton begin MyButton := TButton.Create(Self) MyButton.Parent := Self; MyButton.Left := X; MyButton.Top := Y; MyButton.Caption := 'Katt ide'; MyButton.OnClick := MyButtonClick; end; end.

Hasonlan a nyomgombhoz ltrehozhatunk futsidben ms vizulis komponenseket is, pldul Label-t, Edit-et, Image-t, stb.

3.1 Nyomgombok ltrehozsa, megszntetse egrkattintskor


A kvetkez pldaprogram segtsgvel megmutatjuk a gyakorlatban is a nyomgomb ltrehozst s megszntetst. A feladatban a program indtsakor csak egy res form-unk lesz. Ha egrrel erre a formra kattintunk, akkor a kattints helyre ltrehozunk egy nyomgombot. Ha a ltrehozott nyomgombok valamelyikre kattintunk, akkor az adott nyomgombot megszntetjk (felszabadtjuk a memribl). Pelda03 Alkalmazsunk forrskdja a kvetkezket fogja tartalmazni:

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private { Private declarations } procedure ButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); public { Public declarations } end;

Termszetesen nem csak az OnClick, hanem brmelyik esemnyt megrhatjuk gy.

58

59

var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin (Sender as TButton).Free; end; procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin With TButton.Create(Self) do begin Parent := Self; Left := X - Width div 2; Top := Y - Height div 2; Caption := 'Click'; OnMouseUp := ButtonMouseUp; end; end; end.

Ha az OnMouseUp helyett az OnClick esemnyt hasznltuk volna, s ebben szabadtottuk volna fel a gombot, akkor a nyomgomb felszabadtsakor hibajelentst kaptunk volna. Ennek oka az, hogy a gomb lenyomsakor bekvetkezik az OnMouseDown, OnClick s vgl az OnMouseUp esemny. Ha azonban az OnClick-ben felszabadtjuk a nyomgombot, akkor az OnMouseUp esemny mr nem tud bekvetkezni utna, ami hibhoz vezet. Mivel az egyes ltrehozott gombokat nem szksges kln megjegyeznnk, ezrt a nyomgombokra nem hasznltunk kln vltozkat (teht a ltrehozott objektumokra nincs hivatkozsunk, mint amilyen az elz fejezetben volt a MyButton). Helyette a with parancs segtsgvel oldottuk meg a kezdeti tulajdonsgok belltst rgtn a gomb ltrehozsa utn.

3.2 Vizulis komponensbl szrmaztatott osztly


Amint mr mondtuk, a vizulis komponensek (nyomgomb, kp, beviteli doboz, stb.) is osztlyakbl ltrehozott objektumok. Ezrt minden rvnyes rjuk, amit az els fejezetben elmondtunk az objektum orientlt programozsrl.

A forrskdban a vastag betkkel rtakat kellett neknk bernunk, a tbbit a Delphi rta be helyettnk, ahogy azt mr megszokhattuk. Lthatjuk, hogy ltre kellett hoznunk egy egsz eljrst (TForm1.ButtonMouseUp), melyet a program futsa kzben mindegyik nyomgomb OnMouseUp esemnyhez rendeltnk hozz. A programban a nyomgomra kattintskor azrt ezt az esemnyt hasznltunk az OnClick esemny helyett, mert ez utn az esemny utn mr nincs kritikus kd, teht ebben megtrtnhet a gomb felszabadtsa a Free metdusnak a segtsgvel.
60

Az ilyen komponens-osztlyakbl teht kszthetnk egy sajt, szrmaztatott osztlyt is. Pldul a TImage osztlybl szrmaztathatunk egy sajt, TMyImage osztlyt, ami (mivel TImage-bl szrmaztatott) mindent fog tartalmazni amit a TImage osztly tartalmaz, de mi a sajt osztlyunkat kibvthetjk mg tovbbi metdusokkal, tulajdonsgokkal is. Ennek sokszor nagy hasznt vehetjk a programozs sorn. A kvetkez mintaplda egy olyan nyomgomb-osztly

ltrehozst mutatja be, amely azon kvl, hogy rendelkezik a


61

hagyomnyos Button sszes tulajdonsgval s metdusval, tartalmaz mg nhny tulajdonsgot (dx, dy) s egy Mozgat metdust, melynek meghvsval a nyomgomb mozogni fog a formon a dx-szel s dy-nal megadott irnyba. Pelda04 Ezt az j osztlyt (TMyButton) a TButton osztlybl

public procedure Mozdul; end; var Form1: TForm1; implementation {$R *.dfm} var a:array[1..10] of TMyButton; procedure TMyButton.Mozdul; begin if (Left+dx+30>Parent.ClientWidth) or (Left+dx<0) then dx:=-dx; if (Top+dy+30>Parent.ClientHeight) or (Top+dy<0) then dy:=-dy; Left:=Left+dx; Top:=Top+dy; end; procedure TForm1.ButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var i:integer; begin for i:=1 to 10 do if a[i]=Sender then FreeAndNil(a[i]); end; procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin randomize; for i:=1 to 10 do begin a[i] := TMyButton.Create(Self); a[i].Parent:=Self; a[i].Width:=30; a[i].Height:=30; a[i].Caption:='Click!'; a[i].Left:=Random(Form1.ClientWidth-30);
63

szrmaztattuk. A form ltrehozsakor az j osztlybl ltrehoztunk 10 darab objektumot. Ha valamelyik ilyen nyomgombra rkattintunk, azt felszabadtjuk a memribl. Alkalmazsunk tervezsi nzetben a formon csak egy Timer komponenst fog tartalmazni, amely a gombok mozgatst vgzi el. A programunk forrskdja:

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } procedure ButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); public { Public declarations } end; TMyButton = class(TButton) private dx,dy: integer;
62

a[i].Top:=Random(Form1.ClientHeight-30); repeat a[i].dx:=random(3)-1; a[i].dy:=random(3)-1; until (a[i].dx<>0) or (a[i].dy<>0); a[i].OnMouseUp:=ButtonMouseUp; end; end; procedure TForm1.Timer1Timer(Sender: TObject); var i:integer; begin for i:=1 to 10 do if a[i]<>nil then a[i].Mozdul; end; end.

4 DLL-ek hasznlata s ltrehozsuk


A Windows-ban ktfle futtathat llomnyok lteznek: programok (EXE fjlok) s dinamikus csatols knyvtrak (Dynamic Link Libraries = DLL fjlok). Br a DLL fjlok kzvetlenl nem futtathtk, mgis tartalmaznak programkdot (fggvnyeket, eljrsokat), tovbb tartalmazhatnak erforrsokat (kpeket, hangokat, szvegtblkat), akrcsak a programok. Amikor egy Delphi alkalmazst runk, akkor egy programfjlt ksztnk. Ez a programfjl felhasznlhatja a DLL-ekben tallhat fggvnyeket, eljrsokat, erforrsokat. De mirt is j, ha nem mindent egy programfjlba rakunk, hanem DLL-be is, s mikor rdemes DLLeket hasznlni? Ehhez nzzk meg a DLL-ek felhasznlhatsgt s azok fbb elnyeit: Tbb program hasznlhatja ugynazt a DLL-t. Ha teht ksztnk egy DLL-t olyan fggvnyekkel, eljrsokkal, erforrsokkal, melyeket gyakran hasznlunk a programjainkban, akkor ksbb brmelyik alkalmazsban felhasznlhatjuk ezt. Ha tbb program fut egyszerre, melyek ugyanazt a DLL-t hasznljk, akkor a DLL csak egyszer tltdik be a memriba. gy teht memrit is takarthatunk meg. A Delphi-ben elksztett DLL-eket ms a DLL-ben tallhat fggvnyeket, programozsi eljrsokat

A forrskdban most is vastaggal emeltk ki a fontosabb programrszeket.

nyelven kszlt alkalmazsokban is felhasznlhatjuk. Teht

64

65

felhasznlhatjuk akr C, Visual Basic, stb. nyelvekben rt alkalmazsok ksztsnl is. A kvetkez nhny oldalon megismerkedhetnk azzal, hogyan kszthetnk dinamikus csatols knyvtrakat, s hogyan hasznlhatjuk ezeket alkalmazsainkban. Ekkor megjelent egy res dinamukus csatols knyvtr forrskdja. Ebbe rhatjuk bele azokat a fggvnyeket s eljrsokat, melyeket szeretnnk, ha a DLL-nk tartalmazna. Ksztsnk most egy olyan dinamikus csatols knyvtrat, amely tartalmazni fog egy fggvnyt kt szm legnagyobb kzs osztjnak meghatrozsra (lko), egyet pedig a legkisebb kzs

4.1 DLL ksztse


Ha dinamikus csatols knyvtrat szeretnnk ltrehozni, vlasszuk ki a Delphi fejlesztkrnyezetben a File New Other menpontot. A megnyl ablakban vlaszzuk ki a Delphi Projects kategria alatt a DLL Wizard-ot, majd klikkeljnk az OK gombra.

tbbszrs meghatrozsra (lkt). Tovbb a DLL tartalmazzon mg egy paramter nlkli fggvnyt, amelynek meghvsval megkapjuk a Fibonacci szmsor (1, 1, 2, 3, 5, 8, 13, 21, ) kvetkez elemt (fibo) s egy paramter nkli eljrst, melynek segtsgvel belltjuk a Fibonacci szmok generlst az elejre (fiboinit). Pelda05 Az egyes eljrsok s fggvnyek megrsa utn fontos, hogy azokat a fggvnyeket s eljrsokat, melyeket kvlrl (a programokbl, melyek a DLL-t hasznlni fogjk) is meg kvnunk hvni, felsoroljuk az exports zradk utn. Itt adhatunk a fggvnyeknek s eljrsoknak ms nevet is (ahogy ezt tettk a fibo-nl s fiboinit-nl), vagy hagyhatjuk azt a nevet, melyen a DLL-ben a fggvnyt megrtuk. Ha j nevet adunk, akkor az alkalmazsokbl, melyekben a DLLfggvnyt vagy eljrst hasznlni akarjuk, az j nven rhetjk majd el. Ha ms fejleszti rendszerbl is el szeretnnk rni a DLL exportlt eljrsait s fggvnyeit, akkor a Delphi-ben alaprtelmezett register paramtertadsi md helyett a stdcall szabvnyos Win32 paramtertadsi mdot kell hasznlnunk. Nzzk most meg, hogyan is nz ki a knyvtr forrskdja:

library dll_pelda;

66

67

uses SysUtils, Classes, Math; {$R *.res} {ket szam legnagyobb kozos osztoja} function lko(a,b: integer): integer; stdcall; var i: integer; begin i := min(a,b); while (a mod i > 0) or (b mod i > 0) do dec(i); result := i; end; {ket szam legkisebb kozos tobbszorose} function lkt(a,b: integer): integer; stdcall; var i: integer; begin i := max(a,b); while (i mod a > 0) or (i mod b > 0) do inc(i); result := i; end; {Fibonacci szamok} var a1, a2, ssz: int64; {a Fibonacci szamsor kovetkezo eleme} function fibo: int64; stdcall; begin if ssz<=2 then result := 1 else begin result := a1 + a2; a1 := a2; a2 := result; end; inc(ssz); end; {a Fibonacci szamgenerator inicializalasa} procedure fiboinit; stdcall; begin a1 := 1;
68

a2 := 1; ssz := 1; end; {exportalando alprogramok listaja} exports lko, lkt, fibo name 'Fibonacci', fiboinit name 'StartFibonacci'; {a DLL inicializalasa} begin fiboinit; beep(); end.

A forrskd vgn a begin s end kztt trtnik a DLL inicializlsa. Az ide lert program csak egyszer fut le, mieltt brmelyik fggvnyt hasznlnnk. A mi programunkban itt inicializljuk a Fibonacci szmgenertort majd a beep fggvnnyel megszlaltatjuk a hangszrt gy majd halljuk mikor fut le az alkalmazsunkban ez az inicializcis rsz. Amik nem kzvetlenl a dinamikus csatols knyvtrakhoz tartoznak, de eddig mg nem biztos, hogy tallkoztunk velk, az a min s max fggvnyek, melyek a Math unitban tallhatk. Ezek kt szm kzl visszaadjk a kisebb, illetve nagyobb szmot. Ami mg a forrskdban j lehet, az az int64 tpus. Ez a Delphiben hasznlhat legnagyobb egsz szm tpus. Azrt hasznltuk ezt az integer tpus helyett, mivel a Fibonacci szmok generlsakor nagyon hamar elrhetnk olyan rtkeket, melyeket mr az integer tpusban nem tudunk trolni.

69

A megrt forrskdot a Project Compile (Ctrl+F9) menpont segtsgvel tudjuk lefordtani s gy ltrehozni a DLL kiterjeszts fjlt. Ha mr megrtuk volna azt az alkalmazst, amely a dinamikus csatols knyvtrat hasznlja, akkor azt futtatva tesztelhetjk a DLL futst is a kzvetlenl a Delphi-bl. Ehhez elg a DLL mappjba (ahova elmentettk) tmsolnunk a lefordtott EXE fjlt s a Run Parameters menpontot kivlasztva a Host application alatt megadni ezt az alkalmazst. Ezutn a DLL-t tesztelhetjk a belltott alkalmazsunk segtsgvel a Run fmenpontot kivlasztva (pl. Run Run menponttal).

A mi esetnkben most a legegyszerbb a lefordtott DLL llomnyt oda tmsolni, ahova az alkalmazsunkat menteni fogjuk s ahol ltrejn majd az alkalmazsunk EXE fjlja (teht ahonnan betltdik az alkalmazsunk). Gondolom termszetes, hogy ha a ksz alkamazsunkat majd terjeszteni szeretnnk, akkor az EXE llomnnyal egytt a DLL llomnyt is terjesztennk kell, mivel az nlkl a programunk nem fog mkdni. De nzzk meg, hogyan is tudjuk az alkalmazsunkban felhasznlni a megrt dinamikus csatols knyvtrat. Ksztsk el az albbi alkalmazst, melyben felhasznljuk az elz feladatban megrt DLL llomnyt. Ne felejtsk el a lefordtott DLL fjl (dll_pelda.dll) tmsolni abba a mappba, ahov az alkalmazsunkat menteni fogjuk! Pelda06

4.2 A DLL felhasznlsa alkalmazsunkban


Ahhoz, hogy a ksz dinamikus csatols knyvtr fggvnyeit s eljrsait fel tudjuk hasznlni alkalmazsainkban, a lefordtott DLL llomnyt MS Windows XP rendszer esetben az albbi alknyvtrak valamelyikben kell elhelyeznnk: abba a knyvtrba, ahonnan az alkalmazs betltdik, az aktulis knyvtrban, Windows\System32 knyvtrban, Windows\System knyvtrban, Windows knyvtrban a path krnyezeti vltozban felsorolt knyvtrak

valamelyikben

70

71

function Fibonacci:int64; stdcall; external 'dll_pelda.dll'; Ahhoz, hogy a DLL-ben definilt alprogramokat elrhetv tegyk, importlnunk kell ket. Minden DLL-ben tallat rutin kls definci a programunk szmra (external). A Delphi-ben az importls lehet az alprogram neve alapjn, pl.: function lko(a,b: integer):integer; stdcall; external 'dll_pelda.dll'; vagy akr ltanunk megadott nv alapjn (tnevezssel), pl.: function LegkKozTobb(a,b: integer):integer; stdcall; external 'dll_pelda.dll' name 'lkt'; Ezek utn az lko s LegkKozTobb fggvnyeket brhol felhasznlhatjuk a programunkban. A fenti kt plda esetben fontos, hogy az lko s lkt nevek szerepeljenek a dll_pelda modul exports rszben! Az alkalmazsunkhoz tartoz forrskd fontosabb rsze: procedure TForm1.Button1Click(Sender: TObject); var x,y: integer; begin x := StrToInt(Edit1.Text); y := StrToInt(Edit2.Text); ShowMessage('Legnagyobb kzs oszt: ' + IntToStr(lko(x,y))); end; procedure TForm1.Button2Click(Sender: TObject); var x,y: integer; begin x := StrToInt(Edit1.Text); y := StrToInt(Edit2.Text); ShowMessage('Legkisebb kzs tbbszrs: ' + IntToStr(LegkKozTobb(x,y))); end; procedure TForm1.Button3Click(Sender: TObject); begin StartFibonacci; end; procedure TForm1.Button4Click(Sender: TObject); begin Memo1.Text := Memo1.Text + IntToStr(Fibonacci) + ', '; end; end.

implementation {$R *.dfm} function lko(a,b: integer):integer; stdcall; external 'dll_pelda.dll'; function LegkKozTobb(a,b: integer):integer; stdcall; external 'dll_pelda.dll' name 'lkt'; procedure StartFibonacci; stdcall; external 'dll_pelda.dll';

4.3 Statikus s dinamikus importls


A DLL eljrsaink s fggvnyeink importlst statikus s dinamikus mdon is elvgezhetjk.

72

73

Az eddigiek sorn a statikus importlst hasznltuk. A statikus importls esetn a rendszer a dinamikus csatols knyvtrat akkor tlti be a memriba, amikor az azt hasznl program els pldnya elindul. Minden tovbbi a knyvtrra hivatkoz alkalmazs, a mr betlttt knyvtr alprogramjait hasznlja. A dinamukus importls esetn az alkalmazs futsa sorn sajt magunk tltjk be a memriba a dinamikus csatols knyvtrat. Ha a knyvtrra mr nincs szksgnk, akkor egyszeren felszabadtjuk azt. A betlts s felszabadts mvelethez a Windows API-fggvnyeket hasznljuk, melyek a Windows unitban tallhatk. A dinamikus importls els lpse a knyvtr betltse a memriba. Ezt a LoadLibrary() fggvny segtsgvel tehetjk meg: function FreeLibrary(hLibModule: HModule): Bool; A fggvny paramtereknt meg kell adnunk az elz fggvny visszatrsi rtkeknt kapott DLL modul azonostjt s az alprogram (DLL-fggvny vagy eljrs) nevt. A fggvny visszatrsi rtkeknt megkapjuk a paramterben megadott alprogram cmt. Ha nincs ilyen alprogram a DLL-ben, akkor visszatrsi rtkknt nil-t kapunk. Ha mr nincs szksgnk az alkalmazsban a betlttt dinamikus csatols knyvtrra, akkor azt a FreeLibrary fggvny meghvsval szabadthatjuk fel a memribl:

function LoadLibrary(KonyvtarNeve: PAnsiChar): HModule;

Paramterknt a LoadLibrary fggvny meghvsakor kapott azonostt kell megadnunk. Nzzk meg egy plda segtsgvel, hogyan hasznlhatjuk a

A fggvny paramtereknt csak a knyvtr nevt kell megadni elrsi tvonal nlkl. Ha a fggvny 0 (nulla) rtkkel tr vissza, akkor sikertelen volt a betlts, egybbknt a betlttt modul azonostjt kapjuk vissza. Ha a DLL-t sikerlt betltennk a memriba, akkor

dinamikus importlst az alkalmazsunkban. A programban a 3.1. fejezetben ltrehozott DLL-t fogjuk felhasznlni, ezrt ezt a fjlt (dll_pelda.dll) ne felejtsk el tmsolni abba a knyvtrba, ahov az alkalmazst el fogjuk menteni (ahonnan futtani fogjuk). Az alkalmazsunk most csak egy res Memo s egy Button komponenseket tartalmazzon. A nyomgomb megnyomsakor a DLLfggvny segtsgvel kiszmoljuk, majd kirjuk a Memo komponensbe 8 s 12 legnagyobb kzs osztjt, legkisebb kzs tbbszrst s az els 10 Fibonacci szmot. Pelda07

hivatkozhatunk a DLL-ben trolt fggvnyekre s eljrsokra. A hivatkozshoz azonban meg kell tudnunk a DLL-fggvny vagy eljrs belpsi pontjnak cmt. A cm lekrdezshez a GetProcAddress() fggvnyt hasznlhatjuk:

function GetProcAddress(hLibModule: HModule; AlprogNeve: LPCStr): FARProc;


74 75

Az alkalmazsunk nyomgombjnak OnClick esemnyhez tartoz forrskd:

procedure TForm1.Button1Click(Sender: TObject); { megfelelo mutatotipusok es fuggvenyek az eljarasok hivasahoz } type TLkoLkt = function (a,b:integer):integer; stdcall; TFibo = function:int64; stdcall; TFiboStart = procedure; stdcall; var lko, lkt: TLkoLkt; fibo: TFibo; fibostart: TFiboStart; i: integer; HLib: THandle; begin Memo1.Clear; { konyvtar betoltese } HLib := LoadLibrary('dll_pelda.dll');
76

if hlib = 0 then ShowMessage('A dll_pelda.dll betoltese sikertelen volt!') else try { belepesi pontok lekerdezese } addr(lko) := GetProcAddress(HLib,'lko'); addr(lkt) := GetProcAddress(HLib,'lkt'); addr(fibostart) := GetProcAddress(HLib, 'StartFibonacci'); addr(fibo) := GetProcAddress(HLib,'Fibonacci'); { fuggvenyek hivasa } if addr(lko)<>nil then Memo1.Lines.Add('LKO(8,12) = ' + IntToStr(lko(8,12))); if addr(lkt)<>nil then Memo1.Lines.Add('lkt(8,12) = ' + IntToStr(lkt(8,12))); if addr(fibostart)<>nil then fibostart; if addr(fibo)<>nil then begin Memo1.Lines.Add('Elso 10 Fibonacci szam: '); for i:=1 to 10 do Memo1.Text := Memo1.Text + IntToStr(fibo) + ', '; end; finally { konyvtar felszabaditasa } FreeLibrary(HLib); end; end;

Amivel az eddigi programozsunk sorn nem tallkoztunk, az a fggvny s eljrs tpusok definilsa. Az gy definilt fggvnyeknek s eljrsoknak a programban meg kell adnunk a belpsi cmket (ahol a memriban a fggvny s alprogram tallhat). A fggvny cmt az addr opertor segtsgvel addhatjuk meg, illetve krdezhetjk le.

77

4.4 A DLL s a memria


A dinamukus csatols knyvtrak alaphelyzetben nem

egy ScrollBar segtsgvel bellthatunk 0-255 kztti szmot, majd az O.k. gomb megnyomsval a fggvny ezt az rtket adja vissza. Ha a formbl a Mgsem nyomgombbal lpnk ki, akkor a fggvny -1 rtket adjon vissza. Pelda08

tmogatjk a hossz sztringek paramterknt, illetve fggvnyrtkknt val tadst. Amennyiben erre szksg van, mind a DLL, mind pedig az alkalmazs uses rszben az els helyen meg kell adnunk a ShareMem unitot, a lefordtott programhoz pedig csatolnunk kell a memriakezelst vgz borlndmm.dll knyvtrat. Egyszerbb megoldshoz jutunk, ha az AnsiString (String) tpus helyett a PChar (nullvg sztring) vagy ShortString (max. 255 hossz string) tpust hasznljuk. A nullvg sztring hasznlata klnbzik a megszokott string tpustl. A ShortString tpus hasznlata hasonl, a klnbsg csupn az, hogy ebben a tpusban maximum 255 karakter hossz sztringet trolhatunk.

A fent lert mdon hozzuk ltre elbb a DLL-t, majd ehhez adjunk hozz egy Form-ot. Rakjuk r a formra a szksges komponenseket s lltsuk be az esemnyeket. A Form s rajta lev

4.5 Form trolsa DLL-ben


A Form DLL-be val helyezsekor ugyangy kell eljrnunk, mint ha norml alkalmazsba szeretnnk j formot tenni. Teht miutn ltrehoztuk a dinamikus csatols knyvtrat (File New Other Delphi Projects DLL Wizard), hozztesznk ehhez a knyvtrhoz egy formot a File New Form - Delphi for Win32 menpont segtsgvel. A dinamikus knyvtr azon fggvnyben vagy eljrsban, melyben szeretnnk hasznlni ezt a formot, ltrehozzuk, megnyitjuk (ltalban modlisan), majd megszntetjk. Ksztsnk egy DLL-t, amely tartalmaz egy AdatBekeres fggvnyt. Ez a fggvny nyisson meg modlisan egy formot, amelyen

komponensek esmnyeihez tartoz programkd:

procedure TForm1.ScrollBar1Change(Sender: TObject); begin Label2.Caption := IntToStr(ScrollBar1.Position); end; procedure TForm1.Button1Click(Sender: TObject); begin ModalResult := mrOk; end; procedure TForm1.Button2Click(Sender: TObject); begin ModalResult := mrCancel; end;
79

78

procedure TForm1.FormShow(Sender: TObject); begin Left := (Screen.Width - Width) div 2; Top := (Screen.Height - Height) div 2; end;

{ form felszabaditasa } Form.Free; end; Exports AdatBekeres; begin end.

Ezzel megrtuk a ScrollBar1 OnChange, Button1 OnClick, Button2 OnClick esemnyekhez tartoz eljrsokat. A Form1 OnShow esemnyhez is rtunk programkdot, amely a form helyt lltja be, amikor megnyitjuk modlisan (az ablakunkat a kperny kzepn jelenti meg). Nzzk most a DLL-t, melyben ezt a Form-ot ltrehozzuk, megnyitjuk modlisan, belltjuk a fggvny visszatrsi rtkt, majd felszabadtjuk a Form-nak lefoglalt memrit: A form ltrehozsakor a form tulajdonosnak az Application objektumot adjuk meg, ami valjban az az alkalmazs lesz, amely a DLL-fggvnyt hasznlni fogja. Ahhoz, hogy az Application objektumot s az mrOk konstanst hasznlni tudjuk a DLL-fggvnyben, ki kellett egsztennk a dinamikus csatols knyvtr uses rszt a Forms s Controls unitokkal. A Unit1 modult a Delphi automatikusan berta a knyvtr uses sorba amikor hozzraktuk a formot. library dll_form; uses SysUtils, Classes, Forms, Controls, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} function AdatBekeres:Integer; stdcall; var Form: TForm1; begin { form letrehozasa } Form := TForm1.Create(Application); { form megjelenitese - adatbekeres } if Form.ShowModal = mrOk then result := Form.ScrollBar1.Position else result := -1;
80

4.6 A DLL (s a benne trolt form) felhasznlsa alkalmazs ksztsekor Delphi-ben


Az elz fejezetben ltrehozott DLL-t felhasznlva ksztsnk egy egyszer alkalmazst, amely egy gomb megnyomsa utn a DLLfggvny (form) segtsgvel bekr egy szmot. A DLL-fggvny ltal visszaadott szmot jelentsk meg egy Label komponensben. Pelda09

81

4.7 A DLL (s a benne trolt form) felhasznlsa a MS Excel makr nyelvben (Visual Basic)
Prbljuk felhasznlni az gy megrt DLL-t ms programozsi nyelvben. Ksztsnk a MS Excel-ben egy egyszer makrt (Eszkzk Makr ), amely csupn annyit tesz, hogy az aktv cellba ber egy szmot, pl. a 15-t. Mentsk el az llomnyunkat s az aktv knyvtrba Az alkamazsunk forrskdja: msoljuk mell a 3.5. fejezetben elksztett DLL llomnyunkat. Majd szerkesszk a makrt s rjuk t benne azt a rszt, ami a 15-s szmot rja be az aktv cellba gy, hogy a DLL-fggvnynk ltal bekrt implementation {$R *.dfm} function AdatBekeres:integer; stdcall; external 'dll_form.dll'; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption := 'Beolvasott szm: ' + IntToStr(AdatBekeres); end; end. Ltjuk, hogy hasonlan a Delphi programozsi nyelvhez, itt is Lthatjuk, hogy ezt a DLL-fggvnyt is ugyangy hasznlhatjuk, mint az els dinamikus csatols knyvtrunkban trolt fggvnyeket s eljrsokat. A form modlis megjelentst valjban mr a maga DLLfggvny vgzi el. elbb deklarlnunk kell a fggvnyt. A deklarcinl meg kell adnunk, melyik DLL llomny tartalmazza a fggvnynket (dll_form.dll). Ezek utn a makrban mr egyszeren meghvhatjuk a fggvnynket. Declare Function AdatBekeres Lib "dll_form.dll" () As Integer Sub Makro1() ActiveCell.FormulaR1C1 = AdatBekeres End Sub szmot rakja be az aktv cellba a 15 helyett. Pelda10 A feladat megoldshoz a makr Visual Basic-ben rt

forrskdjt gy mdostsuk:

82

83

4.8 Erforrsok trolsa DLL-ben


Az alkalmazsunk hatkony mkdse rdekben nha a programkd helyett erforrsokat (kp, hang, szveg, ) trolunk a dinamikus csatols knyvtrakban. Ksztsnk kt DLL-t (dll_en.dll, dll_hu.dll), melyekben az adott nyelven a program feliratait s az adott nyelvhez tartoz zszlt (hu.bmp s en.bmp kpek) troljuk. A kvetkez feladatban (3.9. fejezetben) majd az alkalmazsunk ezekbl a DLL-ekbl tlti be a feliratokat a kivlasztott nyelven s a nyelvhez tartoz zszlt. Pelda11

Az eng.rc fjl tartalma:

kep BITMAP "en.bmp" STRINGTABLE BEGIN 1 2 3 4 END DISCARDABLE "Calculation" "Exit" "Datainput" "Result"

A hun.rc fjl tartalma:

kep BITMAP "hu.bmp" STRINGTABLE BEGIN 1 2 3 4 END DISCARDABLE "Szmols" "Kilps" "Adatbevitel" "Eredmny"

Ezeket a fjlokat a Delphi rszeknt megtallhat brcc32.exe fordtval lefordtjuk .res kiterjeszts llomnyokk: A feliratokat s a kpet erforrs fjlokban fogjuk trolni, melyeket hozzcsatolunk a DLL-ekhez. A feliratokhoz sztringtblt definilunk. brcc32.exe eng.rc brcc32.exe hun.rc

84

85

Ezek utn a binris erforrsfjlokat (.res) a $R fordtsi direktvval beptjk a dinamikus csatols knyvtrakba: A magyar nyelvt a dll_hu.dll-be:

4.9 DLL-ben trolt erforrsok felhasznlsa


Ksztsk el a fenti kt DLL-t hasznl alkalmazst. A nyelvet fmen segtsgvel lehessen vltoztatni. Az alkalmazs a Szmols nyomgomb megnyomsakor az egyik Edit-be bert szmot emelje

library dll_hu; uses SysUtils, Classes; {$R *.res} {$R hun.res} begin end.

ngyzetre,

majd

az

eredmnyt

jelentse

meg

msik

Edit

komponensben. Pelda12

Az angol nyelvt pedig a dll_en.dll-be:

library dll_en; uses SysUtils, Classes; {$R *.res} {$R eng.res} begin end.

formra

helyezzk

el

szksges

komponenseket

(MainMenu1, Label1, Label2, Edit1, Edit2, Button1, Button2, Image1), majd lltsuk be ezek fontosabb tulajdonsgait s rjuk meg az esemnyekhez tartoz programkdot:

Ezzel elksztettk a kt DLL llomnyt (magyar s angol), melyeket a kvetkez feladatban fogunk felhasznlni. {$R *.dfm} implementation

86

87

procedure TForm1.Button2Click(Sender: TObject); begin Close; end; procedure TForm1.Button1Click(Sender: TObject); begin Edit2.Text := IntToStr(Sqr(StrToInt(Edit1.Text))); end; procedure LoadResource(lib:string); var DLLleiro: THandle; Puffer: PChar; { nullvegu (#0) string } Bmp: TBitmap; begin { konyvtar beolvasasa } DLLleiro := LoadLibrary(PChar(lib)); if DLLleiro = 0 then ShowMessage('Nincs meg a(z) '+lib+' fjl.') else begin { string-ek beolvasasa } Puffer := StrAlloc(100+1); LoadString(DLLleiro,1,Puffer,100); Form1.Button1.Caption := Puffer; LoadString(DLLleiro,2,Puffer,100); Form1.Button2.Caption := Puffer; LoadString(DLLleiro,3,Puffer,100); Form1.Label1.Caption := Puffer; LoadString(DLLleiro,4,Puffer,100); Form1.Label2.Caption := Puffer; StrDispose(Puffer); { kep beolvasasa } Bmp := TBitmap.Create; Bmp.Handle := LoadBitmap(DLLleiro,'kep'); Form1.Image1.Canvas.Draw(0,0,Bmp); Bmp.Free; { konyvtar felszabaditasa } FreeLibrary(DLLleiro); end; end; procedure TForm1.MagyarHungarian1Click( Sender: TObject);
88

begin LoadResource('dll_hu.dll'); end; procedure TForm1.EnglishAngol1Click(Sender: TObject); begin LoadResource('dll_en.dll'); end; end.

kivlasztott

DLL-bl

az

erforrsok

(feliratok,

kp)

betltshez ltrehoztunk egy LoadResource nev eljrst, melynek paramtereknt megadjuk a DLL fjl nevt. Ez az eljrs betlti a DLL-t a memriba, majd ebbl beolvassa a szksges adatokat a LoadString(), LoadBitmap() fggvnyek segtsgvel, vgl felszabadtja a dinamikus csatols knyvtrnak lefoglalt memrit.

89

kivlasztjuk a Thread Object-ot. Ez utn megadjuk annak az osztlynak

5 Prhuzamos programozs, szlak


A tbbprogramos 32-bites Windows rendszerek mkdsk kzben nem az egyes programokat, hanem a programszlakat kezelik. A programszl a Windows szempontjbl nll program, az opercis rendszer hatrozza meg, hogy mikor kap a szl processzoridt. Tbbprocesszoros rendszer esetben az egyes programszlak futtatst kln processzor is elvgezheti. Egy alkalmazs llhat egy programszlbl (mint pl. az eddigi alkalmazsaink) vagy tbb programszlbl is. A programszlak prhuzamosan vgzik tevkenysgket. Pldul a MS Word alkalmazs mkdse kzben a helyesrs ellenrz egy kln programszlon fut, ezrt tud folyamatosan (prhuzamosan) dolgozni, mikzben a felhasznl szerkeszti a dokumentumot.

a nevt, melyet a TThread osztlybl szeretnnk szrmaztatni:

Majd rkattintunk az OK gombra. Ezzel ltrehoztunk egy j unitot, melyben mindjrt szerepel a mi osztlyunk vzlata.

5.1 TThread osztly


Ha tbbszl alkalmazst szeretnnk kszteni a Delphi-ben, egyszeren ltrehozunk egy szrmaztatott osztlyt a TThread (programszl) osztlybl. Ezt megtehetjk kt fle kppen. Az els lehetsgnk, hogy manulisan berjuk a szksges programkdot (legjobb egy kln unit-ba). A msodik lehetsgnk, hogy miutn ltrehoztuk az

unit Unit2; interface uses Classes; type TVonalSzal = class(TThread) private { Private declarations } protected procedure Execute; override; end; implementation { }
90 91

alkalmazst (File New VCL Form Application - Delphi for Win32), a Delphi fmenjbl kivlasztjuk a File New Other menpontot, majd a megnyl ablakban a Delphi Projects Delphi Files alatt

az rtke igaz (true), akkor az Execute metdus befejezdjn, s ezzel procedure TVonalSzal.Execute; begin { Place thread code here } end; end. a programszlunk is befejezdjn. A programszlunk (Execute metdus) a szl ltrehozsa utn automatikusan elindul, ha a konstruktor paramterben false (hamis) rtket adtunk meg. Ha a ltrehozskor a konstruktor paramtereknt igaz (true) rtket adunk meg, akkor a programszl ltrehozsa utn a Neknk ezek utn csak ezt kell kiegsztennk, illetve mdostanunk. Fontos, hogy a programszl f rszt, teht azt a programot, amit a programszlnak el kell vgeznie az Execute metdus implementcijban kell megadnunk. A ltrehozott szlbl elrhetjk, mdosthatjuk a vizulis komponenseket (VCL) is. Ha csak olvasni akarjuk valamelyik komponens tulajdonsgt, azt megtehetjk az Execute metdusban is. Ha viszont meg szeretnnk vltoztatni vizulis komponensek brmelyik tulajdonsgt, azt nem vgezhetjk el kzvetlenl az Execute metdusban, mivel a kperny aktualizlsrt kizrlag az alkalmazs f programszlja a felels. A programszlunknak ltezik azonban egy Synchronize metdusa, melynek meghvsvl jelezhetjk a f programszlnak, hogy mit szeretnnk elvgezni a vizulis komponenseken (a Synchronize metdus paramterben azt az eljrst kell megadnunk, amelyben a vizulis komponensekkel val mveletek szerepelnek). A f programszl a Synchronize meghvsa utn a megadott mveleteket a komponenseken automatikusan elvgzi. Amint mr emltettk, TThread osztly legfontosabb metdusa az Execute, amely azt a programot tartalmazza, melyet a szlnak el kell vgezni. Ez a metdus felels azrt, hogy TThread Terminated tulajdonsgt folyamatosan ellenrizze, s ha ennek a tulajdonsgnak Egy msik megolds tulajdonsg a programszl true-ra. memribl Ilyenkor val ha a a felszabadtsra, hogy mg az elejn (pl. ltrehozs utn) belltjuk a FreeOnTerminate programszl rtkt futsa befejezdik, automatikusan felszabadul szl felfggesztett llapotban marad, teht nem kezddik el automatikusan az Execute metdus futsa. Ebben az esetben a programszl futst a Resume metdus meghvsval indthatjuk el. A fut szlat a Suspend metdus meghvsval szneteltethetjk

(fggeszthetjk fel). Az Execute metdust soha ne hvjuk meg kzvetlenl! Azt, hogy egy programszl ppen fut-e vagy szneteltetve van, a Suspended tulajdonsg segtsgvel llapthatujuk meg. A programszl teljes el, lelltst amely a Terminate a metdus

segtsgvel

vgezhetjk

valjban

Terminated

tulajdonsgot lltja igaz (true) rtkre. Az Execute metdusban ezrt fontos, hogy idkznknt ellenrizzk a Terminated tulajdonsg rtkt, s ha ez igaz, akkor fejezzk be a program futst. A programszlat, miutn befejezdtt a futsa, a memribl felszabadthatjuk a mr megszokott Free metdus segtsgvel.

memribl (nem kell meghvnunk a Free metdust).

92

93

unit Unit2;

5.2 Szakaszok prhuzamos kirajzolsa


Ksztsnk alkalmazst, amely vletlen hely s szn

interface uses Classes, Graphics; type TVonalSzal = class(TThread) private x1,y1,x2,y2: integer; Szin: TColor; protected procedure Execute; override; procedure KepFrissitese; end; implementation uses Unit1; procedure TVonalSzal.Execute; begin repeat x1 := Random(Form1.Image1.Width); y1 := Random(Form1.Image1.Height); x2 := Random(Form1.Image1.Width); y2 := Random(Form1.Image1.Height); Szin := Random($FFFFFF); Synchronize(KepFrissitese); until Terminated = true; end; procedure TVonalSzal.KepFrissitese; begin Form1.Image1.Canvas.Pen.Color := Szin; Form1.Image1.Canvas.MoveTo(x1,y1); Form1.Image1.Canvas.LineTo(x2,y2); end; end.

szakaszokat fog kirajzolni egy kln programszl segtsgvel egy image komponensre. Az gy megrt programunk a kirajzols alatt is fog reaglni az esemnyekre, pl. a kirajzols kzben is t tudjuk majd helyezni az alkalmazs ablakt, mivel a rajzols egy kln, a fprogramszllal prhuzamos szlon fut. Pelda13

Hozzunk ltre egy j alkalmazst, melyre helyezznk el egy Image komponenst s kt nyomgombot. Az egyik nyomgombbal fogjuk a mi programszlunkat elindtani, a msikkal felfggeszteni. Nzzk meg elszr a programszlunkat tartalmaz unit forrskdjt:

94

95

Bevezettnk nhny privt vltozt (x1, y1, x2, y2, szin) melyek a kirajzoland vonal helyt s sznt hatrozzk meg. Azt, hogy a programszlunk pontosan mit vgezzen el, az Execute metdusban kell megadnunk. Lthatjuk, hogy itt kigenerlunk vletlen szmokat, majd a KepFrissitese eljrs segtsgvel kirajzoljuk a vonalat a kpernyre. Ez addig fog krbe-krbe futni egy repeat..until ciklus segtsgvel, amg nem lltjuk le a programszlat a Terminate metdussal (ez a metdus lltja be a Terminated tulajdonsgot, melyet a ciklusban vizsglunk). A komponensre val kirajzolst a f programszlnak kell elvgeznie, ezrt a KepFrissitese eljrst a Synchronize metdus segtsgvel vgezzk el. Az forrskd: alkalmazsunk komponenseinek esemnyeihez tartoz

Szal := TVonalSzal.Create(True); end; procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled := False; Button2.Enabled := True; Szal.Resume; end; procedure TForm1.Button2Click(Sender: TObject); begin Button1.Enabled := True; Button2.Enabled := False; Szal.Suspend; end; procedure TForm1.FormDestroy(Sender: TObject); begin if Szal.Suspended then Szal.Resume; Szal.Terminate; Szal.Free; end; end.

unit Unit1; interface uses Windows, Messages, SysUtils, , Unit2; var Form1: TForm1; Szal: TVonalSzal; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin A programban lesz egy globlis objektumunk (Szal), amely TVonalSzal osztly tpus lesz. A Form OnCreate esemnyben ltrehozzunk az j programszlat (teht Szal objektumot). A Create konstruktor true paramtere azt jelzi, hogy a ltrehozs utn a programszl felfggesztett llapotban legyen, teht ne fusson. A Button1 OnClick esemnyben miutn belltottuk a nyomgombok elrhetsgt, a Resume metdus segtsgvel

elindtjuk a programszlat.

96

97

A Button2 OnClick esemnyhez tartoz eljrsban ennek a programszlnak felfggesztk. A Form OnDestroy esemnyben a form memribl val felszanbadtsa eltt, ha a programszlunk futsa fel volt fggesztve, akkor elindtjuk, majd a Terminate metdus meghvsval a Miutn ltrehoztuk az alkalmazst, hozzunk ltre egy programszlunk futst (Execute eljrst) befejezzk. Vgl a Free metdus memrit. segtsgvel felszabadtjuk a programszlnak lefoglalt programszlat j unitban (THozzaadSzal), majd ebbe a unitba berjuk manulisan a msik programszlunkat is (TSzor2Szal). Ennek a modulnak a programkdja gy nz ki: a futst a Suspend metdus segtsgvel

5.3 Szlak szinkronizlsa vrakozs egy msik programszlra


A programszlak hasznlatakor sokszor szksgnk lehet a szlak szinkronizlsra pldul egy szlban kiszmtott eredmnyre szksge lehet egy msik programszlnak. Ilyenkor a legegyszerbb szinkronizlsi mdszer a vrakozs a msik programszl futsnak befejezsre. Erre ksztnk egy pldaprogramot. Az alkalmazasunk tartalmazzon egy Label komponenst s kt nyomgombot. Az els nyomgomb megnyomsakor egy kisebb szmtst fogunk elvgezni kt programszl segtsgvel. Az egyik programszl a Label-ben lev szmhoz hozzad 1-et, kzben a msik szl vrakozik erre az eredmnyre, majd beszorozza 2-vel. A msodik nyomgomb csupn az alkalmazs bezrsra fog szolglni. Pelda14 unit Unit2; interface uses Classes; type THozzaadSzal = class(TThread) private { Private declarations } protected procedure Execute; override; end; TSzor2Szal = class(TThread) private { Private declarations } protected procedure Execute; override; procedure LabelFrissites; end; implementation
98 99

uses Unit1, SysUtils; var szam: int64; procedure THozzaadSzal.Execute; begin szam := szam + 1; end; procedure TSzor2Szal.Execute; var HozzaadSzal: THozzaadSzal; begin szam := StrToInt(Form1.Label1.Caption); HozzaadSzal := THozzaadSzal.Create(false); HozzaadSzal.WaitFor; HozzaadSzal.Free; szam := 2 * szam; Synchronize(LabelFrissites); end; procedure TSzor2Szal.LabelFrissites; begin Form1.Label1.Caption := IntToStr(szam); end; end.

unit Unit1; interface uses Windows, Messages, , Unit2; var Form1: TForm1; Szor2Szal: TSzor2Szal; implementation {$R *.dfm} procedure TForm1.Button2Click(Sender: TObject); begin Close; end; procedure TForm1.Button1Click(Sender: TObject); begin Szor2Szal := TSzor2Szal.Create(false); Szor2Szal.FreeOnTerminate := true; end; end.

Lthatjuk, hogy a TSzor2Szal Execute metdusban miutn a Label komponensben szerepl szmot trtuk a szam vltozba, ltrehozunk egy THozzaadSzal tpus objektumot. A WaitFor metdus segtsgvel vrakozunk ennek a HozzaadSzal-nak a befejezdsre, majd ezt a szlat felszabadtjuk s a kapott szam-ot beszorozzuk kettvel. Vgl az gy kapott eredmnyt kirjuk a Label komponensbe. Nzzk most a nyomgombok OnClick esemnyeihez tartoz programkdokat: A Szor2Szal programszl a ltrehozsa utn rgtn elindul (mivel a konstruktor paramterben false rtket adtunk meg). A ltrehozs utn belltottuk a programszl FreeOnTerminate tulajdonsgt true-ra. Ezzel elrtk, hogy a programszl futsnak befejezse utn automatikusan felszabaduljon a memribl. A szlak ltrehozst s lettartamt az id fggvnyben az albbi bra szemllteti:
100 101

tpLower tpNormal tpHigher tpHighest

A norml prioritsnl egy ponttal alacsonyabb. Norml priorits szl. A norml prioritsnl egy ponttal magasabb. A norml prioritsnl kt ponttal magasabb.

tpTimeCritical A legmagasabb priorits szl. Ksztsnk alkalmazst, melyben megmutatjuk kt klnbz priorits programszl prhuzamos mkdst. Az alkalmazs ablakn kt golyt fogunk mozgatni. Mindegyik goly mozgatst kln szl fogja vgezni. Attl fggen, hogy a kt szlnak milyen a prioritsa, az egyik goly gyorsabban vagy lassabban fog mozogni, mint a msik. Pelda15

5.4 Programszlak prioritsa


A programszl ltrehozsa utn megadhatjuk a Priority tulajdonsg segtsgvel a programszl futsi prioritst. A nagyobb priorits nagy programszl tbb processzoridt indokolt kap esetben az opercis adjuk egy rendszertl, gy az gyorsabban le tud futni mint a kisebb priorits. Tl prioritst azonban csak programszlnak, ugyanis az jval lelasstja a tbbi programszl futst. A priorits meghatrozsnl a kvetkez rtkek adhatk meg: tpIdle A szl csak akkor indul el, ha a Windows vrakoz llapotban van. tpLowest A norml prioritsnl kt ponttal alacsonyabb. A Form-on helyezznk el kt Image komponenst (golyk) s hrom Button komponenst.

102

103

Hozzunk ltre egy j programszlat a golyk mozgatsra. Mindegyik szlban meg kell jegyeznnk melyik golyt (melyik Image komponenst) fogja a szl mozgatni (FGolyo) s a goly (Image komponens) aktulis koordintjt a Form-hoz viszonytva (FXKoord). Ezek kezdeti rtkeinek belltshoz ksztnk egy konstruktort. Az j konstruktor paramtereknt megadjuk az Image komponest s a prioritst a programszlnak. A programszl forrskdja:

end; procedure TGolyoSzal.Execute; var i: integer; begin repeat { bonyolultabb szamitas helyett } for i:=0 to 1000000 do FXKoord := FXKoord + 1; FXKoord := FXKoord - 1000000; { ha kimenne a kepernyorol, a masik oldalra atrakjuk } if FXKoord > Form1.ClientWidth-FGolyo.Width then FXKoord := 2; { golyo kirajzolasa } Synchronize(Kirajzol); until Terminated; end; procedure TGolyoSzal.Kirajzol; begin { golyo athelyezese } FGolyo.Left := FXKoord; { tovabbi esemenyek feldolgozasa } Application.ProcessMessages; end; end.

unit Unit2; interface uses Classes, ExtCtrls; type TGolyoSzal = class(TThread) private FGolyo: TImage; FXKoord: integer; protected procedure Execute; override; procedure Kirajzol; public constructor Create(AGolyo: TImage; APrioritas: TThreadPriority); end; implementation Uses Unit1, Forms; constructor TGolyoSzal.Create; begin inherited Create(false); FGolyo := AGolyo; FXKoord := FGolyo.Left; Priority := APrioritas;
104

A Create konstruktorban ltrehozzunk az s konstruktornak meghvsval a programszlat, melyet rgtn futtatunk is (false paramter). Ezutn belltjuk az FGolyo s FXKoord mezk kezdeti rtkeit s a programszl prioritst. Az Execute metdusba tettnk egy ciklust, amely 1000001-szer hozzad az FXKoord mez rtkhez egyet, majd kivon belle 1000000-t. Erre azrt volt szksg, hogy a programszl vgezzen valamilyen hosszab ideig tart mveletet. Klnben a legbonyolultabb

105

mvelet a goly mozgatsa lenne, amit a fprogramszl vgez el (a Kirajzol metdus szinkronizlsval), gy a priorits nem lenne rzkelhet. A Kirajzol mtdus arrb teszi a golyt, majd feldolgozza az alkalmazs tovbbi esemnyeit. Erre az Application.ProcessMessages parancsra csak azrt van szksg, mert ha tlltannk a prioritst magasra, akkor a golyk mozgatsa olyan nagy prioritst kapna, hogy az alkalmazs a tbbi esemnyre nem tudna idben reaglni. Az alkalmazs esemnyeihez tartoz eljrsok forrskdja:

g2.Terminate; g1.Free; g2.Free; end; procedure TForm1.Button1Click(Sender: TObject); begin g1.Resume; g2.Resume; Button1.Enabled := false; Button2.Enabled := true; end; procedure TForm1.Button2Click(Sender: TObject); begin g1.Suspend; g2.Suspend; Button1.Enabled := true; Button2.Enabled := false; end; procedure TForm1.Button3Click(Sender: TObject); begin Close; end; end.

unit Unit1; interface uses Windows, Messages, SysUtils, , Unit2; implementation {$R *.dfm} var g1, g2: TGolyoSzal; procedure TForm1.FormCreate(Sender: TObject); begin DoubleBuffered := true; g1 := TGolyoSzal.Create(Image1, tpLower); g2 := TGolyoSzal.Create(Image2, tpLowest); end; procedure TForm1.FormDestroy(Sender: TObject); begin if g1.Suspended then g1.Resume; if g2.Suspended then g2.Resume; g1.Terminate;
106

Lthatjuk, hogy a kt goly mozgatst vgz programszlra kt globlis vltozt vezettnk be (g1, g2). A form ltrehozsakor ltrehozzuk ezt a kt programszlat is, az elst alacsony, a msodikat ennl eggyel alacsonyabb prioritssal. Az egyik gomb sznetelteti (felfggeszti) mindkt szl futst, a msik elindtja mindkt szlat. A harmadik nyomgomb segtsgvel kilphetnk az alkalamzsbl. A Form OnDestroy esemnyben, ha a programszlak ppen felfggesztett llapotban vannak, akkor elindtjuk ket, majd a

107

Terminate metdus segtsgvel befejeztetjk a futsukat. Vgl felszabadtjuk meghvsval. a szmukra lefoglalt memrit a Free metdus

Ehhez elszr is a Delphi-ben hozzunk ltre a mr megszokott mdon egy j alkalmazst (File New VCL Form Application - Delphi for Win32). Erre helyezznk el egy fmen (MainMenu) komponenst, melynek lltsuk be a szksget tulajdonsgait. Tovbb ne felejtsk el belltani a Form FormStyle tulajdonsgt fsMDIForm rtkre.

5.5 Tbbszl MDI alkalmazs


Az eddig ltrehozott alkalmazsaink mindig csak egy, kett, maximum hrom programszlat hasznltak. A kvetkez feladatban olyan MDI alkalmazst ksztnk, melynek mindegyik gyermek ablaka kln szlat fog hasznlni, gy az alkalmazsunk tbb szlat is hasznlhat majd. Ksztsnk MDI alkalmazst, amelyben minden MDI-gyermek ablakra egy j szl segtsgvel prhuzamosan fogunk kirajzolni vletlen helyzet s szn szakaszokat. Pelda16

Ezek utn hozzuk ltre a gyermek ablakot. Ehhez hozzunk ltre egy j Form-ot (File New Form - Delphi for Win32), melyre helyezznk el egy Image komponenst. Az Image komponens Align tulajdonsgt lltsuk be alClient-re. A Form FormStyle tulajdonsgt ennl a form-nl fsMDIChild rtkre lltsuk. Vgl hozzunk ltre a mr megszokott mdon egy Thread Object-et egy j unitban (File New Others Delphi Projects Delphi Files Thread Object). Az j programszlunk neve legyen TSzal. Fontos, hogy minden egyes gyermek ablak pontosan tudja melyik programszl fog neki dolgozni, s hasonlan minden egyes szl tudja, melyik Form-ra (pontosabban melyik Image komponensre) fogja kirajzolni a vonalakat. Ehhez a gyermek ablakban (Form-ban) meg fogjuk adni a hozz tartoz programszlat, s minden programszlban pedig azt az Image komponenst, amelyre a szakaszokat kirajzolja. Nzzk elszr a programszlunkat tartalmaz modult (Unit3):

unit Unit3; interface uses Classes, Graphics, ExtCtrls; type TSzal = class(TThread) private
108 109

{ Private declarations } x1,y1,x2,y2: integer; szin: TColor; img: TImage; protected procedure Execute; override; procedure Kirajzol; public constructor Create(iimg: TImage); end; implementation constructor TSzal.Create; begin inherited Create(false); img := iimg; priority := tpLowest; end; procedure TSzal.Execute; begin repeat x1 := random(img.Width); y1 := random(img.Height); x2 := random(img.Width); y2 := random(img.Height); szin := random($FFFFFF); Synchronize(Kirajzol); until Terminated; end; procedure TSzal.Kirajzol; begin img.Canvas.Pen.Color := szin; img.Canvas.MoveTo(x1,y1); img.Canvas.LineTo(x2,y2); end; end.

A programszl x1, y1, x2, y2 meziben jegyezzk meg a kirajzoland vonal koordintit, a szin mezben a vonal sznt s az img mezben azt az image komponenst, melyre a szakaszokat a szl rajzolni fogja. Ez utbbit a konstruktor segtsgvel adjuk meg a programszlnak. Nzzk most meg, hogy nz ki az MDI-gyermek ablakhoz tartoz programkd (Unit2):

unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, unit3; type TForm2 = class(TForm) Image1: TImage; procedure FormResize(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } Szal: TSzal; public { Public declarations } end; implementation {$R *.dfm} procedure TForm2.FormClose(Sender: Action: TCloseAction); begin Action := caFree; Szal.Terminate; TObject; var

110

111

Szal.Free; end; procedure TForm2.FormCreate(Sender: TObject); begin DoubleBuffered := true; Szal := TSzal.Create(Image1); end; procedure TForm2.FormResize(Sender: TObject); begin Image1.Picture.Bitmap.Width := Image1.Width; Image1.Picture.Bitmap.Height := Image1.Height; end; end.

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, Unit2; type TForm1 = class(TForm) MainMenu1: TMainMenu; Menu1: TMenuItem; jablak1: TMenuItem; N1: TMenuItem; Kilps1: TMenuItem; procedure FormCreate(Sender: TObject); procedure jablak1Click(Sender: TObject); procedure Kilps1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; n: integer; implementation

A form osztlynak private deklarcijba ne felejtsk el berni a programszlunkat (Szal:TSzal;). Ezt a programszl-objektumot a form ltrehozsakor a Form OnCreate esemnyben hozzuk ltre. A Form OnClose esemnyben belltjuk, hogy a form bezrsa utn felszabaduljon a szmra lefoglalt memria, majd lelltjuk s megszntetjk a formunkhoz tartoz programszlat is. A Form - Resize esemnyben csupn a kpnk bitmapjnak a mrett lltjuk be, hogy a rajzols a form tmretezsekor a teljes kpre trtnjen. Vgl nzzk meg az MDI Form-hoz tartoz programkdot is (Unit1):

{$R *.dfm} procedure TForm1.Kilps1Click(Sender: TObject); begin Close; end; procedure TForm1.jablak1Click(Sender: TObject); var Form2: TForm2; begin Form2 := TForm2.Create(self); Form2.Caption := 'Ablak' + IntToStr(n); inc(n); end; procedure TForm1.FormCreate(Sender: TObject); begin

unit Unit1; interface


112

113

n := 1; end; end.

6 OLE technolgia
Az OLE (Object Linking and Embedding = objektum csatolsa s beszrsa) egy rdekes technolgia, melyet a Microsoft fejlesztett ki.

Ebben a modulban hasznltunk egy globlis n vltozt, amely csupn arra szolgl, hogy a ltrehozott gyermek ablak feliratba be tudjuk rni, hnyadik ablak jtt ppen ltre. Az MDI-gyermek ablakot az alkalmazsunk megfelel

Ennek segtsgvel megjelenthetnk, st szerkeszthetnk bitmap-okat a programunkban az nlkl, hogy ezt kln be kne programoznunk. Valjban ezt a technolgit hasznljuk ki akkor is, amikor pldul a MS Word-be rt dokumentumba egy Paintban rajzolt kpet vagy egy MS Excel-ben elksztett tblzatot rakunk be. Ha az ilyen objektumra dupln rkattintunk, akkor az megnylik szerkeszthet formban a Paint, ill. MS Excel programban. Az OLE technolgia a munkjhoz .n. OLE szervereket hasznl. Ne gondoljunk itt most kln szerver szmtgpekre! Az OLE szerverek a sajt gpnkben fut alkalmazsok (egyszeren megfogalmazva), melyek ms alkalmazsok (nevezzk ezeket OLE klienseknek) rszre felknljk a szolgltatsaikat s mkdsket. Az alkalmazs (OLE kliens) kihasznlhatja valamelyik, a szmtgpen elrhet OLE szervert olyan tevkenysgek elvgzsre, melyre sajt maga nem kpes. Ha van pldul MS Word szervernk, amely felknlja DOC formtum dokumentumok megjelentst, akkor a mi alkalmazsunkbl ezt a szervert meghvhatjuk s gy a sajt alkalmazsunkban Word dokumentumot jelenthetnk meg az nlkl, hogy a programunkban ezt sajt magunk implementltuk volna. Az OLE teht egy olyan mechanizmus, amely lehetsget ad az alakamazsunkban elhelyezni olyan objektumot, amely egy msik alkalmazsban van definilva.

menpontjt kivlasztva hozzuk ltre a Create konstruktor segtsgvel. Az j ablak tulajdonosnak az MDI Form-ot (self) lltjuk be.

114

115

Jelenleg az OLE 2-es verzija hasznlt a gyakorlatban. Ez lehetsget ad teht ms alkalmazsban definilt objektum megjelentsre a sajt programunkban. Ha ezt az objektumot a programunkban szerkeszteni szeretnnk (dupla kattintssal aktivlva), akkor vagy egy j ablakban, vagy a programunk belsejben nylik meg az objektumhoz tartoz alkalmazs (pl. MS Word). Az OLE-val val munknk sorn megklnbztetnk: Beszrst (Enbedding) az objektum fizikailag is az alkalmazsba kerl. Ha pldul van a merevlemeznkn egy teszt.doc, melyet az alkalmazsba beszrunk, akkor ez a fjl fizikailag t lesz msolva a helyrl az alkalmazsba. Csatolst (Linking) az alkalmazsba nem lesz beszrva fizikailag az objektum, csak egy hivatkozs r. Az llomny teht meg fog jelenni az alkalmazsunkban, de fizikailag dolgozni a merevlemezen lev llomnyal fogunk.

szmtgpnkn. Ha ugyanis a szmtgpen nincs pldul MS Word, akkor nem tudunk MS Word dokumentumot megjelenteni az alkalmazsunkban. Az OleContainer komponenssel val munknk sorn

mindenekeltt el fogunk helyezni a formon egy ilyen komponenst, melyben a kivlasztott objektum fog megjelenni. Ez utn meghvhatjuk az InsertObjectDialog metdust, amely egy dialdusablakot nyit meg, melyben a felhasznl kivlaszthatja a szmtgpen lev sszes elrhet OLE objektum kzl, hogy milyent akar elhelyezni. Ha az objektumot a programbl, teht nem dialgusablak segtsgvel szeretnnk beszrni vagy linkelni, akkor a beszrshoz az OleContainer komponens CreateObject, CreateObjectFromFile vagy CreateObjectFromInfo metdusai kzl vlaszthatunk, csatolshoz pedig a CreateLinkToFile metdust hasznlhatjuk.

6.2 Els OLE-t hasznl alkalmazsunk


Egy egyszer plda segtsgvel megmutatjuk, hogyan lehet az

6.1 A Delphi s az OLE


Az OLE-vel val munknk alapkomponense a System palettn tallhat OleContainer. Ez a komponens jelkpezi az OLE szervereket a Delphi-ben ltrehozott alkalmazsban. Az OleContainer lehetsget ad brmilyen OLE objektum kivlasztsra s elhelyezsre vagy csatolsra (linkelsre) az alkalmazsunkban. Az objektumok szma, melyek kzl vlaszthatunk, a szmtgpen teleptett programoktl fgg. Ezrt az albbi mintafeladatok kzl nem biztos, hogy mindegyik fog mkdni a

alkalmazsunkban

megjelenteni

Word,

Excel,

Paint,

stb.

dokumentumokat. Pelda17 A formra helyezznk el egy Panel komponenst, melynek Align tulajdonsgt lltsuk be alBottom-ra. Erre a Panel-ra tegynk r kt Button komponenst, egyet az objektum beszrsra, egyet pedig a programbl val kilpsre. Vgl a Panel fl tegynk be egy OleContainer komponenst. Mretezzk t gy, hogy kitltse a fennmarad rszt, majd lltsuk be mind a ngy Anchors trulajdonsgt true-ra. Ezzel az alkalmazsunk tervezsvel megvagyunk.

116

117

feher 2D hatteren legyen } OleContainer1.Ctl3D := false; end; procedure TForm1.Button2Click(Sender: TObject); begin Close; end; end.

A Form OnCreate esemnyben belltottuk az OleContainer Anchors tulajdonsgt. Ctl3D Ha ezt mr megtettk Ez az sem alkalmazs felttlenl tervezsekor, akkor itt nem szksges. Ezek utn belltottuk az OleContainer tulajdonsgt false-ra. szksges, csak a kontainer klalakjt vltoztatja meg. Termszetesen ezt a tulajdonsgot is bellthattuk volna tervezsi idben. Az OnClick rjuk meg az egyes esemnyekhez tartoz programkdot: alkalmazsunk esemnyben leglnyegesebb az OleContainer rsze az Objektum

beszrsa gomb megnyomsakor trtnik. Ennek a gombnak az InsertObjectDialog metdusnak segtsgvel megnyitunk egy dialgusablakot, melyben a felhasznl kivlaszthatja, hogy milyen objektumot s milyen formban procedure TForm1.Button1Click(Sender: TObject); begin OleContainer1.InsertObjectDialog; end; procedure TForm1.FormCreate(Sender: TObject); begin { az OLE objektum merete az ablak atmeretezeskor valtozzon } OleContainer1.Anchors := [akLeft, akTop, akRight, akBottom]; { az OLE objektum ne 3D, hanem egyszeru
118

(beszrva, csatolva) szeretne az alkalmazsunk OLE kontainerben megjelentetni. A csatols termszetesen csak akkor lehetsges, ha nem j objektumot hozunk ltre, hanem egy ltez fjlbl jelentjk meg az objektumot. Tovbb ebben a dialgusablakban megadhatjuk azt is, hogy az objektumot eredeti formban (tartalmt) akarjuk megjelenteni, vagy csak az ikonjt szerennk megjelenteni az OLE kontainerben.

119

Az OLE azonban ennl tbbre is kpes. Ha dupln rkattintunk a dokumentumunkra, akkor azt szerkeszthetjk is az alkalmazsunk MS Word- vlik.

Az alkalmazsunk elindtsa utn prbljunk meg beszrni pl. egy Word dokumentumot az alkalmazsunkba a fenti dialgusablak segtsgvel. Lthatjuk, hogy ez a dokumentum megjelent az alkalmazsunk OLE kontainerben.

Men megjelentse Lthattuk, hogy hinyzik a MS Word fmenje a dokumentum szerkesztsekor. Ezt nagyon egyszeren megoldhatjuk. Elg, ha az alkalmazsunkra elhelyeznk egy MainMenu komponenst. gy ebben a komponensben automatikusan megjelenik majd a MS Word menje az OLE objektum aktivlsakor.

120

121

Aktivls j ablakban Megfigyelhettk azt is, hogy brmilyen dokumentumot (Word, Paint, ) helyeznk el az OLE kontainerben, aktivlskor (szerkesztskor) mindig a Microsoft Word, Paint, az alkalmazsunk ablakban jelenik meg. Ezen is tudok vltoztatni. Elg, ha az OleContainer AllowInPlace tulajdonsgt belltjuk false-ra s a dokumentumunkat mris j ablakban szerkeszthetjk majd. Egsztsk ki teht az elz alkalmazsunk Form OnCreate esemnyhez tarroz eljrst ennek a tulajdonsgnak a belltsval:

procedure TForm1.FormCreate(Sender: TObject); begin { az OLE objektum merete az ablak atmeretezeskor valtozzon } OleContainer1.Anchors := [akLeft, akTop, akRight, akBottom]; { az OLE objektum ne 3D, hanem egyszeru feher 2D hatteren legyen } OleContainer1.Ctl3D := false; { duplakattintasnal az OLE objektumra a szerkesztes ne a form-on, hanem uj ablakban nyiljon meg } OleContainer1.AllowInPlace := false; end;

6.3 Az OleContainer tulajdonsgai


Most indtsuk el az alkalmazst, majd tltsnk be egy kpet. Utna kattintsunk dupln erre a kpre a szerkesztshez. Lthatjuk, hogy most mr kln ablakban szerkeszthetjk a kpet, s brmilyen vltoztats azonnal megjelenik az alkalmazsunkban lthat kpen is. Az OleContainer-nek sok sajt tulajsonsga van, ezek kzl felsorolunk egypr gyakrabban hasznlt tulajdonsgot: Az AllowInPlace tulajdonsg segtsgvel bellthatjuk, ahogy azt mr az elz programunkban is tettk, hogy az objektum

122

123

szerkesztst az alkalmazsunk OLE kontainern bell (true) vagy kln ablakban (false) szeretnnk elvgezni. Ha a szerkesztst j ablakban vgezzk el, akkor kln ablakban megnylik az objektumhoz tartoz alkalmazs, melyben az objektumon trtn vltoztatsok azonnal megjelennek az alkalmazsunk ablakban (OleContainer-ben) is. A SizeMode tulajdonsg segtsgvel megadhatjuk, hogyan jelenjen meg az objektumunk az OLE kontainerben. Lehetsges rtkek: smClip alaprtelmezett rtk az objektum eredeti mretben jelenik meg, az objektum azon rsze, amely nem fr bele a komponensbe nem lthat. smCenter az objektum eredeti mretben jelenik meg, de a komponensben kzpre lesz igaztva, teht az elzhz kpest az objektumnak nem a bal fels rsze, hanem a kzepe lesz lthat. smScale megvltoztatja az objektum mrett az oldalak arnyt betartva gy, hogy a komponensbe belefrjen. smStretch hasonlan az elzhz megvltoztatja az objektum mrett gy, hogy a komponensbe belefrje, de az oldalak arnyt nem tartja be (szthzza az objektumot az egsz komponensre). smAutoSize az objektumot eredeti mretben jelenti meg s a komponens mrett lltja t gy, hogy az egsz objektum belefrjen.

Az

OleContainer

State

tulajdonsgnak

kiolvassval

megtudhatjuk, hogy az OLE objektum ppen milyen llapotban van. Lehetsges rtkek: osEmpty az OLE kontainer res, nincs benne semmilyen objektum. osLoaded az OLE kontainerben van megjelentve objektum, de nem aktv a hozz tartoz OLE szerver nem fut. osRunning az OLE kontainerben van megjelentett objektum s ennek OLE szervere fut. osOpen az OLE objektum a sajt alkalmazsnak ablakban (j ablakban) van megjelentve. osInPlaceActive az OLE objektum helyben van aktivlva, de mg nincs sszekapcsolva az sszes men s eszkztr. Amint a teljes aktivls befejezdik, az rtke osUIActive-ra vltozik. osUIActive az OLE objektum helyben lett aktivlva, jelenleg is aktv s az ssze men s eszkztr ssze lett kapcsolva.

6.4 Kulcsszavak lekrdezse s vgrehajtsa


Ha meg szeretnnk tudni, milyen kulcsszavakat tmogat az OLE kontainerben lev objektum, hasznlhatjuk az ObjectVerbs tulajdonsgot. Ezeket a kulcsszavakat mint szveget kapjuk meg, gy tartalmazhatnak & jelet is, melyek a gyors billentyelrst jellik.

124

125

Az alkalmazsunk tartalmazzon egy ListBox komponenst, melyben megjelentjk az sszes objektum ltal tmogatott kulcsszt. Tovbb alkalmazsunkon legyen egy Panel komopnens is, melyre elhelyeznk hrom nyomgombot: egyet az objektum beolvassra, egyet a kulcsszavak megjelentsre s egyet a listbl kivlasztott kulcssz vgrehajtsra. s termszetesen vgl alkalmazsunk tartalmazni fog egy OleContainer komponenst is. Pelda18 Az alkalmazs tervezsnl elszr a panelt helyezzk el a formon, ennek Align tulajdonsgt lltsuk be alBottom-ra. Erre a panelre helyezzk el a nyomgombokat.

Az

alkalmazs

nyomgombjaihoz

tartoz

esemnyek

programkdja:

procedure TForm1.Button1Click(Sender: TObject); begin OleContainer1.InsertObjectDialog; end; procedure TForm1.Button2Click(Sender: TObject); begin ListBox1.Items.Assign(OleContainer1.ObjectVerbs); end; procedure TForm1.Button3Click(Sender: TObject); begin OleContainer1.DoVerb(ListBox1.ItemIndex); end; end.

Lthatjuk, hogy a kulcsszavakat az ObjectVerb tulajdonsg segtsgvel krdeztk le. A kivlasztott kulcssz vgrehajtst a DoVerb metdussal vgeztk el, melynek paramtereknt a kulcssz sorszmt adtuk meg.

Az objektum beszrsa utn a Kulcsszavak nyomgomb megnyomsval megjelentjk a ListBox-ban a kulcsszavakat. Ezek kzl valamelyiket kivlaszthatjuk, majd a Parancs vgrehajtsa nyomgomb segtsgvel vgrehajthatjuk.

6.5 OLE objektum beolvassa s mentse


A kvetkez alkalmazsunk fogjuk egy Panel-t, a rajta ngy

nyomgombot s egy OleContainert fog tartalmazni. Az egyes nyomgombok segtsgvel szemlltetni dokumentum

126

127

beolvasst, OLE objektum beolvasst fjlbl, OLE objektum mentst s a dokumentum mentst fjlba. Pelda19 A programban az egyszersg kedvrt mindig a teszt.doc fjt fogjuk beolvasni, illetve ilyen nev llomnyba fogunk menteni.

begin OleContainer1.SaveAsDocument('teszt.doc'); end;

Az els nyomgombnl a CreateObjectFromFile segtsgvel beolvassuk a Word dokumentumot a kontainerbe. Ha a teszt.doc llomnyban valban Word dokumentum van, akkor ez hiba nlkl vgrehajtdik. A paramterben az ExpandFileName fggvnyt azrt kellett hasznlnunk, mivel ennek a metdusnak az llomny nevt a teljes tvonallal egytt kell tadnunk. A metdus msodik paramtere azt adja meg, hogy az objektum csak ikon formjban jelenjen meg (true) vagy lthat legyen a tartalma (false). Ha a teszt.doc llomnyban nem Word dokumentum van, Az egyes nyomgombokhoz tartoz esemnyek: hanem OLE objektum, akkor azt csak a LoadFromFile metdus segtsgvel tudjuk beolvasni. procedure TForm1.Button1Click(Sender: TObject); begin OleContainer1.CreateObjectFromFile( ExpandFileName('teszt.doc'), false); end; procedure TForm1.Button2Click(Sender: TObject); begin OleContainer1.LoadFromFile('teszt.doc'); end; procedure TForm1.Button3Click(Sender: TObject); begin OleContainer1.SaveToFile('teszt.doc'); end; procedure TForm1.Button4Click(Sender: TObject);
128 129

Az OLE kontainerben megjelentett objektumot a SaveToFile segtsgvel menthetjk el gy, mint Word tpus OLE objektum. A SaveAsDokument metdussal az objektumot elmenthetjk mint Word dokumentum. Lehet hogy egy kicsit furcsnak tnik, mirt van ilyen nagy klnbsg a hagyomnyos llomny (Word dokumentum, bitmap, ) kztt s az OLE objektumot tartalmaz llomny formtumja kztt, amikor az els pldnkban minden gond nlkl be tudtunk olvasni dokumentumot az OLE kontainerbe. Ez azrt volt, mivel ott a beolvasst az InsertObjectDialog metdus segtsgvel hajtottuk vgre, amely automatikusan elvgezte a dokumentum talaktst OLE objektumm.

6.6 Menk sszekapcsolsa


Az els pldnkban lthattuk, hogy ha elhelyeznk egy MainMenu komponenst a form-on, akkor az objektum szerkesztsekor ebben megjelennek az OLE szerverhez tartoz menpontok. De mi van akkor, ha az alkalmazsunkban is szeretnnk sajt ment kialaktani? Erre nzznk most egy mintafeladatot. Pelda20 Hozzunk ltre egy j alkalmazst, melyre helyezznk el egy Panel komponens, arra egy nyomgombot, amely az objektum beolvassra OleContainer fog s szolglni. egy Tovbb tegynk a formra be egy a MainMenu komponenst. lltsuk

Ha most elindtjuk a programunkat s beszrunk valamilyen objektumot, majd dupln rkattintunk a szerkesztshez, akkor a mi mennk is megmarad s az objektum OLE szervernek menje is elrhet lesz.

komponensek tulajdonsgait, majd alaktsuk ki az brn lthat menszerkezetet a MainMenu komponensnl.

szrevehetjk, hogy ez azrt nem mindig a legjobb megolds, ugyanis most pldul kt Szerkeszts menpontunk van a mienk s az OLE szerver is. Ebben az esetben taln jobb lenne, ha a mi mennknek a Szerkeszts menpontja nem lenne lthat. Ezzel a problmval a Delphi-ben knnyen boldogulhatunk. A menpontoknak ugyanis van GroupIndex tulajdonsguk, melyet eddig a menpontok logikai csoportokba sorolsra hasznltunk.

130

131

Most ennek a tulajdonsgnak egy tovbbi felhasznlsval ismerkedhetnk befolysolhatjuk, meg. hogy A a GroupIndex menk segtsgvel azt is sszekapcsolsakor melyik

menpontunk legyen lthat s melyik nem: Az alkalmazsunk fmenjnek azon menpontjai,

melyeknek GroupIndex rtke 0, 2, 4, mindig lthatak lesznek s nem lesznek fellrva az OLE szerver menjvel (ez a helyzet llt el az elz pldban is, ahol a GroupIndex rtke mindegyik menpontnl 0 volt). Az alkalmazsunk fmenjnek azon menpontjai,

melyeknek GroupIndex rtke 1, 3, 5, , az OLE szerver menjvel fell lesznek rva, teht amikor az OLE szerver menje lthat lesz (objektum szerkesztsekor), akkor az alkalmazsunknak megjelentve. Hasonlan a menkhz, az eszkztrak is sszekapcsolhatk. Prbljuk meg most tlltani az alkalmazsunk MainMenu komponensben a Szerkeszts menpont GroupIndex tulajdonsgt 1re. Ha gy elindtjuk az alkalmazsunkat, akkor az objektum szerkesztsnl a mi Szerkeszts mennk mr nem lesz lthat. Alaprtelmezett belltsoknl az OLE szerver eszkztra fellrja az alkalmazsunk eszkztrt. Ha ezt el szeretnnk kerlni, lltsuk be az alkalmazsunk eszkztrnak Locked tulajdonsgt True rtkre. ezen menpontjai nem lesznek

6.7 Sajt Word, Excel, Paint,


Ksztsnk az OLE-t felhasznlva egy alkalmazst, amelyben Word, Excel, Paint, stb. dokumentumokat tudunk megnyitni s szerkeszteni, majd elmenteni is. Pelda21 Az alkalmazsunk indtsakor egy OleContainer-t s egy MainMenu-t fog tartalmazni. Ennek a MainMenu komponensnek csak

132

133

egy fmenpontja lesz, a File. A tbbi menpontot a beolvasott objektumhoz taroz OLE szerver fogja berakni.

A menpontok OnClick esemnyeihez tartoz eljrsok:

procedure TForm1.Beszrs1Click(Sender: TObject); begin OleContainer1.InsertObjectDialog; end; procedure TForm1.Dokumentummegnyitsa1Click(Sender: TObject); begin if OpenDialog1.Execute then OleContainer1.CreateObjectFromFile( OpenDialog1.FileName,false); end; procedure TForm1.OLEobjektummegnyitsa1Click(Sender: TObject); begin if OpenDialog1.Execute then OleContainer1.LoadFromFile(OpenDialog1.FileName); end; procedure TForm1.Mentsmintdokumentum1Click(Sender: TObject); begin if (OleContainer1.State <> osEmpty) and (SaveDialog1.Execute) then OleContainer1.SaveAsDocument( SaveDialog1.FileName); end; procedure TForm1.MentsmintOLEobjektum1Click(Sender: TObject); begin if (OleContainer1.State <> osEmpty) and (SaveDialog1.Execute) then OleContainer1.SaveToFile( SaveDialog1.FileName); end; procedure TForm1.Bezrs1Click(Sender: TObject);
134 135

Az alkalmazsra helyezznk el mg egy OpenDialog s egy SaveDialog komponenst a fjlok beolvasshoz s mentshez (pontosabban a beolvasand s elmentend llomny nevnek s helynek meghatrozshoz). A tervezskor lltsuk be az OleContainer Align tulajdonsgt alClient-ra, hogy az OLE kontainer az egsz formon jelenjen meg. Tovbb ne felejtsk el megadni az OleContainer SizeMode tulajdonsgt smScale-ra. Ezzel elrjk, hogy az egsz dokumentum lthat lesz a kontainerben (arnyosan lekicsinytve vagy felnagytva a kontainer mrethez).

begin OleContainer1.DestroyObject; end; procedure TForm1.Aktivls1Click(Sender: TObject); begin if OleContainer1.State <> osEmpty then OleContainer1.DoVerb(ovShow); end; procedure TForm1.Deaktivls1Click(Sender: TObject); begin if OleContainer1.State <> osEmpty then OleContainer1.DoVerb(ovHide); end; procedure TForm1.Vgolapramsols1Click(Sender: TObject); begin if OleContainer1.State <> osEmpty then OleContainer1.Copy; end; procedure TForm1.Beillesztsvglaprl1Click(Sender: TObject); begin if OleContainer1.CanPaste then OleContainer1.Paste; end; procedure TForm1.Kilps1Click(Sender: TObject); begin Close; end; end.

7 OLE Automation
Az OLE Automation olyan technolgia, amely lehetsget ad egy alkalmazs kpessgeit kihasznlni egy msik alkalmazsbl. Az OLE Automation a Microsoft ltal bevezetett Component Object Model-t (COM) hasznlja ki. Az OLE Automatizlst felhasznlva lehetsgnk van

objektumokat hasznl alkalmazsokat ltrehozni s az alkalmazs objektumait egy msik alkalmazs segtsgvel irnytni.

7.1 MS Word irnytsa Delphi-bl


A most kvetkez mintaplda segtsgvel megismerkedhetnk az OLE Automatizlssal a gyakorlatban. A programunk t nyomgombot fog tartalmazni. Az els nyomgomb elindtja a Microsoft Word alkalmazst, a msodik ltrehoz egy j dokumentumot, a harmadik ebbe az res dokumentumba ber kt sort, a negyedik elmenti ezt a dokumentumot level.doc nven (mivel tvonalat nem adunk meg, ezrt az alaprtelmezett mappba a Dokumentumok-ba menti), az tdik nyomgomb pedig bezrja a Microsoft Word alkalmazst. Pelda22

Az alkalmazsunkat mg lehetne tovbb szptgetni, el lehetne jtszani a menpontok Enabled tulajdonsgaival, hogy ne lehessen pldul aktivlni az objektumot, ha a kontainer res.

136

137

vgbemennek, azonban a szoksosnl tbb memrit ignyelnek (16 byte), tovbb a varins tpusok alkalmazsa lasstja a program mkdst. Ezrt prbljuk ezek hasznlatt kizrlag a COM objektum-modellek programozsra szkteni! A varins tpus vltoz akkor is tartalmaz informcit, ha nincs rtke (unassigned), illetve ha rtke semmilyen tpussal nem azonosthat (null). A fenti llapotok tesztelsre a VarIsEmpty(), illetve a VarIsNull() logikai fggvnyeket hasznlhatjuk. A VarType() fggvny segtsgvel azonosthatjuk a varins vltozban trolt adat tpust. Az sszes fontos parancs knnyen megrthet az Most, hogy mr tudjuk milyen a varins tpus, nzzk meg az alkalmazsunk forrskdjt, melyben a Word alkalmazsunk objektuma egy ilyen varins tpus:

alkalmazsunk forrskdjbl. Amit azonban fontos megjegyeznnk: az alkalmazs uses rszt ki kell bvtennk a ComObj unittal,

unit Unit1; definilnunk kell egy globlis vltozt a Word alkalmazsra (w), melynek tpusa Variant lesz. Mieltt ttekintennk az alkalmazsunk nyomgombjaihoz interface uses Windows, Messages, , Dialogs, StdCtrls, ComObj; implementation A variant (varins) tpus felrgja az Object Pascal nyelv tpusossgt, ugyanis egy variant tpus vltozban tetszleges tpus adatot trolhatunk, a rekord, halmaz, statikus tmb, llomny, osztly, osztlyhivatkozs, mutat s int64 tpusok kivtelvel. A varins tpus bevezetsnek elsdleges clja a Microsoft ltal kifejlesztett objektummodellhez (COM) val csatlakozs volt. A varins vltozk hasznlata knyelmes, hiszen bizonyos tpusok kzti talaktsok automatikusan {$R *.dfm} var w: Variant; procedure TForm1.FormCreate(Sender: TObject); begin FormStyle := fsStayOnTop; end;

tartoz programkdot, ismerkedjnk meg a variant tpus hasznlatval, mellyel eddig mg nem tallkoztunk.

138

139

procedure TForm1.Button1Click(Sender: TObject); begin if VarIsEmpty(w) then begin w := CreateOleObject('Word.Application'); w.Visible := true; w.Caption := 'Delphi-bl megnyitott Word'; end; end; procedure TForm1.Button2Click(Sender: TObject); begin if not VarIsEmpty(w) then w.Documents.Add; end; procedure TForm1.Button3Click(Sender: TObject); begin if (not VarIsEmpty(w)) and (w.Documents.Count>0) then begin w.Selection.TypeText('Ez egy egyszer dokumentum,'); w.Selection.TypeParagraph; w.Selection.Font.Size := 14; w.Selection.TypeText('melyet a '); w.Selection.Font.Bold := true; w.Selection.TypeText('Delphi'); w.Selection.Font.Bold := false; w.Selection.TypeText('-bl hoztunk ltre.'); w.Selection.TypeParagraph; end; end; procedure TForm1.Button4Click(Sender: TObject); begin if (not VarIsEmpty(w)) and (w.Documents.Count>0) then begin w.ActiveDocument.SaveAs('level.doc'); end; end; procedure TForm1.Button5Click(Sender: TObject); begin if not VarIsEmpty(w) then
140

begin w.Quit(false); w := Unassigned; end; end; end.

{ false = kilepeskor a 'Menti a valtozasokat?' kerdesre a valasz nem }

A form ltrehozsakor belltottuk a FormStyle tulajdonsgt fsStayOnTop rtkre, mellyel elrtk, hogy a Word megnyitsa utn is a mi alkalmazsunk lesz fell (lthat marad). A Word objektumainak tulajdonsgairl s metdusairl,

melyeket a fenti pldban hasznltunk bvebb informcit az MS Word sgjnak Visual Basic rszben olvashatunk. Ha szeretnnk valamilyen mveletet vgrehajtani Delphi-bl Word-ben az OLE Automatizls segtsgvel, de nem tudjuk pontosan, hogy a Word melyik objektumait, metdusait hasznlhatjuk ehhez, akkor nagy segtsg lehet a Word makrja is. Elg, ha a makr segtsgvel feljtszuk az adott mveletet, majd megnzzk a makro Visual Basicben rt forrskdjt gy megtudhatjuk milyen objektum, melyik tulajdonsgt kell megvltoztatnunk, melyet utnna egy kis szintax trssal a Delphibl is megtehetnk.

7.2 MS Excel irnytsa Delphi-bl


Az elz alkalmazshoz hasonlan bemutatjuk azt is, hogyan lehet a Microsoft Excel alkalmazst megnyitni, adatokkal feltlteni majd bezrni Delphi-bl. Pelda23

141

end; procedure TForm1.Button1Click(Sender: TObject); begin if VarIsEmpty(e) then begin e := CreateOleObject('Excel.Application'); e.Visible := True; e.Caption := 'Delphi-bl megnyitott Excel'; e.WorkBooks.Add; end; end; procedure TForm1.Button2Click(Sender: TObject); var i,j: integer; begin if (not VarIsEmpty(e)) and (e.WorkBooks.Count>0) then begin for i:=1 to 10 do for j:=1 to 3 do e.ActiveSheet.Cells[i,j] := i+(j-1)*10; e.ActiveSheet.Cells[12,3].Formula := '=SUM(A1:C10)'; ShowMessage('Excel-ben kiszmolt sszeg: ' + IntToStr(e.ActiveSheet.Cells[12,3])); end; end; procedure TForm1.Button3Click(Sender: TObject); begin if (not VarIsEmpty(e)) then begin e.DisplayAlerts := false; e.Quit; e := Unassigned; end; end; end.

Alkalmazsunk most csak hrom nyomgombot fog tartalmazni: egyet az Excel megnyitsra s egy j munkafzet ltrehozsra, egyet az adatok bersra a munkafzetbe, s vgl egyet az Excel alkalmazs bezrsra. Az egyes nyomgombok OnClick esemnyeihez tartoz programkd:

unit Unit1; interface uses Windows, Messages, , Dialogs, StdCtrls, ComObj; implementation {$R *.dfm} var e: Variant; procedure TForm1.FormCreate(Sender: TObject); begin FormStyle := fsStayOnTop;
142

143

Ebben a pldban az Excel DisplayAlert tulajdonsgnak false-ra lltsval rtk el, hogy az Excel bezrsakor ne krdezze meg, hogy szeretnnk-e a munkafzetet menteni. Hasonlan Excel sgjnak a Visual Word-hoz, Basic az Excel objektumainak mveletek unit Unit1; interface uses Windows, Messages, , Spin, ComObj; implementation {$R *.dfm} Szorztbla bersa MS Excel-be Delphi-bl Az albbi egyszer plda szintn az Excel irnytst fogja bemutatni. Az Delphi-ben rt alkalmazsunk segtsgvel megadott mret szorztblt fogunk az Excel-be berni (kigenerlni). Pelda24 var Excel: Variant; procedure TForm1.Button1Click(Sender: TObject); var i,j: integer; begin Excel := CreateOleObject('Excel.Application'); Excel.Interactive := False; Excel.Visible := true; Excel.WorkBooks.Add; for i:=1 to SpinEdit1.Value do begin Excel.ActiveSheet.Cells[i+1,1].Font.Bold := True; Excel.ActiveSheet.Cells[i+1,1] := i; end; for i:=1 to SpinEdit2.Value do begin Excel.ActiveSheet.Cells[1,i+1].Font.Bold := True; Excel.ActiveSheet.Cells[1,i+1] := i; end; for i:=1 to SpinEdit1.Value do for j:=1 to SpinEdit2.Value do Excel.ActiveSheet.Cells[i+1,j+1] := i*j; Excel.Interactive := True; end; end.

tulajdonsgairl s metdusairl sok informcit megtallhatunk az rszben. Konkrt elvgzshez tartoz objektumok s tulajdonsgok meghatrozsban itt is segtsgnkre lehet az Excel makrja.

Alkalmazsunk kt Label komponenst, kt SpinEdit komponenst s egy nyomgombot fog tartalmazni. A nyomgomb OnClick esemnyhez tartoz programkd:

144

145

A Excel objektum interactive tulajdonsgt rgtn az Excel alkalmazs ltrehozsa (megnyitsa) utn belltottuk false-ra, majd csak az sszes adat bersa utn lltottuk vissza true-ra. Ez egy nagyon hasznos tulajdonsg az OLE automatizls hasznlatnl, ugyanis ennek segtsgvel elrtk, hogy az adatok bersa alatt a felhasznl az Excellel ne tudjon dolgozni, gy nem tudja az adatok berst s egybb Excel mveletek elvgzst sem megszaktani. Fontos, hogy ha ezt a tulajdonsgot hasznljuk, akkor az Excellel val mveletek befejezse utn ne felejtsk el visszalltani true rtkre! A DDE (Dynamic Data Exchange) a Microsoft ltal kifejlesztett protokol. A DDE ma mr egy kicsit elavult technolgia, az jabb alkalmazsokban mr helyette fleg az OLE automatizlst vagy ms COM-on alapul technolgit hasznlnak. Ennek ellenre elssorban az egyszersge vgett rdemes a DDE-vel megismerkednnk. A DDE szerver az az alkalmazs, amely informcit nyjt ms alkalmazsoknak. A DDE kliens ezeket az informcikat hasznlja, szksg esetn kri az adatokat a szervertl. Egy DDE szerver tbb kliens rszre is szolgltathat

8 DDE Technolgia

informcikat, s hasonlan egy DDE kliens-alkalmazs tbb szervertl is kaphat informcikat. A DDE kliens felels a kapcsolat kialaktsrt, majd krvnyt kld a szervernek az adatokrt, esetleg valamilyen parancs vgrehajtst kri a szervertl. Ahhoz, hogy megmutathassuk, hogyan alakthatunk ki

kapcsolatot kt alkalmazs kztt, mindenekeltt fontos megrtennk az albbi hrom fogalmat: szolgltats (service) ez valjban az alkalmazsunk neve (br ez nem felttel). Ha pldul egy DATUM.EXE alkalmazsunk lesz a DDE szerver, akkor a szolgltats neve a DATUM. A Delphi-ben ehhez a projektet DATUM.DPR nven kell elmentennk.

146

147

tma (topic) a kommunikci pontosabb definilsa. Egy szerver tbb tmban is szolgltathat informcikat. Ha csatlakozni akar a kliens a szerverhez, a kliensnek mindig meg kell adnia a tmt, amelyben a szerverrel trsalogni akar. A Delphi-ben a tma neveknt a szerver konverzcis komponensnek a nevt kell megadnunk (DdeServerConv).

elemhez hozzfrni. Legfontosabb tulajdonsga a Text, amelyben a DDE komunikciban lev szveges adatok vannak. Msik fontos tulajdonsga a ServerConv, amely segtsgvel megadhat, hogy az elem melyik tmhoz tartozzon. DdeClientItem a kliens tmjnak egy eleme. Egytt a DdeClientConv komponenssel bebiztostja, hogy a program DDE kliens kliensknt tmhoz mkdjn. tartozzon az Fontos elem. tulajdonsga Tovbbi a DdeConv, amely segtsgvel megadhat, hogy melyik fontos tulajdonsga a DdeItem, amely a DDE szerveren lev elem nevt tartalmazza. A DdeItem megadsa utn a Text tulajdonsg tartalmazza a DDE kommunikci adatait. A Text tulajdonsg automatikusan frisstve vannak a DDE szerver ltal. DdeClientConv a DDE kliens tmja. Ez a komponens reprezentlja a kommunikcit a DDE szerverrel. Ennek a komponensnek van nhny fontos metdusa is: o o o SetLink megprbl kapcsolatot kialaktani. CloseLink befejezi az aktulis konverzcit. ExecuteMacro parancsot kld a szervernek.

elem

(item) az

az elem a

tadott neveknt nevt

adatok a kell

legpontosabb DDE szerver

identifikcija. Egy tmhoz tbb elem is tartozhat. A Delphi-ben elemkomponensnek (DdeServerItem). Mg a kliens mindig a konkrt szerverrel kommunikl (ismeri a szervert), a szerver a konkrt klienseket nem ismeri. A szerver csak zeneteket kld a klienseknek, az adatok a megosztott memrin keresztl vannak tovbbtva a kliensek fel. megadnunk

8.1 DDE a Delphiben


A Delphiben a DDE-el val munkhoz ngy komponens ltezik. Szerver ltrehozsakor ezek kzl a kt szerver komponenst, kliens ltrehozsakor a kliens komponenseket hasznljuk. Mind a ngy komponens a System kategria alatt tallhat: DdeServerConv a szerver tmja. A kliensek ehhez a tmhoz a komponens nevnek megadsval csatlakozhatnak. DdeServerItem a szerver tmjnak egy eleme. A kliensek szintn a komponens neve alapjn tudnak az

Az albbi bra szemllteti egy egyszer DDE konverzcihoz szksge tulajdonsgok s metdusok belltst a szerveren s a kliensen:

148

149

Fontos, hogy a projektet DDESzerver.dpr nven mentsk el, ugyanis ebben az esetben lesz a futtathat llomny neve DDESzerver.exe, melyre mint szolgltatsra (a kiterjeszts nlkl) fogunk a DDE kliensben hivatkozni. Az ablak, illetve komponensek egyes esemnyeihez tartoz programkd: A kapcsolat ltrehozsa utn amilyen adatot a szerver ber a DdeServerItem1.Text tulajdonsgba, az automatikusan benne lesz a kliens DdeClientItem.Text tulajdonsgban is. Fontos, hogy a kapcsolat kialaktsakot a szolgltats, tma s elem nevt pontosan gy adjuk meg a kliensen, ahogy a szerveren szerepel. Itt fontos a kis- s nagybet is! procedure TForm1.FormCreate(Sender: TObject); begin Edit1.Text := ''; DdeServerItem1.ServerConv := DdeServerConv1; end; procedure TForm1.Edit1Change(Sender: TObject); begin DdeServerItem1.Text := Edit1.Text; end; end. implementation {$R *.dfm}

8.2 Els DDE szerver


Az els DDE szervernk egy DdeServerConv, DdeServerItem s egy Edit komponenst fog tartalmazni. A szerver feladata az lesz, hogy amit berunk az Edit komponensbe, azt a szveget szolgltassa a klienseknek. Pelda25

150

151

Form

Create

esemnyben

belltjuk

kezdeti

Az egyes komponensek, illetve a form esemnyeihez tartoz programkd:

belltsokat: kitrljk a szvegdoboz tartalmt s sszekapcsoljuk a DdeServerItem1 komponenst a DdeServerConv1 komponenssel. Amint a forrskdbl is lthatjuk, ha megvltozik a

implementation {$R *.dfm}

szvegdobozunk tartalma, azonnal megvltoztatjuk a DdeServerItem1 Text tulajdonsgt is az j tartalomra. Ezze a szervernk ksz is van, br egyenlre nem tudjuk hasznlni, mivel nincs mg elksztve a kliens-alkalmazsunk. Fordtsuk le a szerver-alkalmazst, majd lssunk neki a kliens-alkalmazs ltrehozsnak.

procedure TForm1.FormCreate(Sender: TObject); begin Label1.Caption := ''; DdeClientItem1.DdeConv := DdeClientConv1; end; procedure TForm1.Button1Click(Sender: TObject); begin if DdeClientConv1.SetLink('DDESzerver', 'DdeServerConv1') then begin ShowMessage('A kapcsolat ltrejtt.'); DdeClientItem1.DdeItem := 'DdeServerItem1'; end else ShowMessage('A kapcsolatot nem sikerlt ltrehozni.'); end; procedure TForm1.DdeClientItem1Change(Sender: TObject); begin Label1.Caption := DdeClientItem1.Text; end; end.

8.3 Els DDE kliens


Els DDE kliensnk a kvetkez komponenseket fogja

tartalmazni: DdeClientConv, DdeClientItem, Button s Label. A nyomgomb megnyomsakor fogunk csatlakozni a szerverhez, a Label komponensben pedig a csatlakozs utn minden egyes vltozskor megjelentjk a szerver ltal nyjtott szveget (amit a szerveren az Editbe runk). Pelda26

nyomgomb

megnyomsakor

SetLink

metdus

segtsgvel megprblunk csatlakozni a szerverhez. Ha ez a metdus

152

153

igaz rtket ad vissza, akkor a kapcsolat ltrejtt. Egybb esetben hamis rtket kapunk vissza. Kapcsolds utn ha a szerveren megvltozik a

DdeServerItem.Text tulajdonsg rtke, azonnal megvltozik a mi kliens alkalmazsunk DdeClientItem.Text tulajdonsga is. Ezt a vltozst a DdeClientItem OnChange esemnynek bekvetkezse is rzkelteti, melyet a programunkban felhasznlunk a Label komponens frisstsre. Most mr kiprblhatjuk a szerver s kliens alkalmazsok kzti kommunikcit. Indtsuk el az elz fejezetben ltrehozott szervernket, majd a most ltrehozott klienssel csatlakozzunk hozz. Amint Amint az brn is lthat a kliens a DdeClientConv komponens ExecuteMacro metdust hasznlhatja fel parancs (makro) kldsre. Ennek a metdusnak ez els paramtere maga a parancs (a mi esetnkben a torold sz, amivel a szerver szvegdoboznak trlst krjk), a msodik paramter pedig ltalban false ez a paremter adja meg, hogy vrnia kelljen-e a kliensnek a kvetkez DDE mvelet hvsval arra, hogy a szerver befejezze ennek a makrnak a vgrehajtst. Ha a msodik paramter true lenne, akkor a kliens kvetkez DDE hvst a szerver nem fogadn mindaddig, amg ezt az elzt nem hajtotta vgre. Az ExecuteMacro metdus true rtket ad vissza, ha a parancsot a szerver elfogadta, false rtket ha valamilyen hiba trtnt. Az, hogy a parancsot a szerver elfogadta, nem jelenti azt, hogy vgre is hajtja! Ha valamelyik kliens parancsot (makrt) kld a szervernek, akkor a szerveren bekvetkezik a DdeServerConv komponensnek egy megvltoztatjuk a szerver Edit1 komponensben a szveget, azonnal megvltozik a kliens alkalmazsunkban is a Label komponens tartalma. Egy szerver alkalmazshoz tbb kliens alkalmazssal is csatlakozhatunk. Ezt is kiprblhatjuk, ha tbbszr elindtjuk a DDE kliensnket s mindegyikkel csatlakozunk a szerverhez.

8.4 Parancs kldse a szerverre


Eddig csak a DDE szervertl a DDE kliensig folyt a kommunikci, azonban a kliens is kldhet parancsot (makrt) a szervernek. Termszetesen minden esetben a szerver dnti el, hogy a kliens ltal kldtt krelmet teljesti-e vagy nem. Az albbi bra szemllteti hogyan kldhet a kliens a szervernek valamilyen parancsot (krelmet).

154

155

OnExecuteMacro

esemnye.

Ennek

az

esemnynek

Msg

paramterben tallhat a kliens ltal kldtt makr (makrk). A mi esetnkben a torold parancs pontosan a Msg paramter els sorban lesz (Msg[0]).

begin if Msg[0]='torold' then begin ShowMessage('A kliens kri a szvegdoboz trlst.'); Edit1.Text := ''; end; end; end.

Szerver ltrehozsa A szervernk nagyon hasonl lesz az els DDE szerverhez, csupn annyival lesz kiegsztve, hogy ha bekvetkezik esemnye, a

Kliens ltrehozsa Kliensnk is hasonl lesz az els DDE klienshez, csak tartalmazni fog mg egy nyomgombot, melynek megnyomsval a kliens kri a szervert a szvegdoboz kitrlsre. Pelda28

DdeServerConv1

komponens

OnExecuteMacro

akkor

megvizsgljuk az esemny eljrshoz tartoz Msg paramter els sort (Msg[0]). Ha ez egyenl a torold szval, akkor kitrljk az Edit komponens Text tulajdonsgt. Pelda27 Az esemnyekhez tartoz programkd:

implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Edit1.Text := ''; DdeServerItem1.ServerConv := DdeServerConv1; end; procedure TForm1.Edit1Change(Sender: TObject); begin DdeServerItem1.Text := Edit1.Text; end; procedure TForm1.DdeServerConv1ExecuteMacro(Sender: TObject; Msg: TStrings);

Az egyes esemnyekhez tartoz forrskd:

implementation {$R *.dfm}

156

157

procedure TForm1.FormCreate(Sender: TObject); begin Label1.Caption := ''; DdeClientItem1.DdeConv := DdeClientConv1; end; procedure TForm1.Button1Click(Sender: TObject); begin if DdeClientConv1.SetLink('DDESzerver', 'DdeServerConv1') then begin ShowMessage('A kapcsolat ltrejtt.'); DdeClientItem1.DdeItem := 'DdeServerItem1'; end else ShowMessage('A kapcsolatot nem sikerlt ltrehozni.'); end; procedure TForm1.DdeClientItem1Change(Sender: TObject); begin Label1.Caption := DdeClientItem1.Text; end; procedure TForm1.Button2Click(Sender: TObject); begin if DdeClientConv1.ExecuteMacro('torold',false) then ShowMessage('A makrot a szerver elfogadta.') else ShowMessage('Hiba a makr fogadsnl a szerveren.'); end; end.

8.5 A Microsoft Word, mint DDE kliens


Vgezetl megmutatunk egy rdekessget. Ksztnk egy DDE szerver-alkalmazst, de a DDE kliens most a MS Word lesz. Pelda29 Az alkalmazsunk egy Memo komponenst, DdeServerConv, DdeServerItem tartalmazni. komponenseket s egy Button komponenst fog

A szerver a Memo-ba rt szveget fogja szolgltatni a kliensnek. Teht amikor megvltozik a Memo komponensben a szveg, akkor azt Miutn elkszltek a szerver s kliens alkalmazsaink, azok berakjuk a DdeServerItem1 Text tulajdonsgba is. A nyomgomb metdus megnyomsval segtsgvel a lemsoljuk a

elindtsval,

majd

kliens

kapcsoldsval

szerverhez

kiprblhatjuk a torold parancs kldst is a szervernek.

CopyToClipboard

DdeServerItem1

komponens tartalmt. gy nem csak a szveget msoljuk le a vgolapra,

158

159

de a kapcsolatot is a szerver elemre. Mivel ezzel a paranccsal tbb klnbz adatot is msolunk (szveg s kapcsolat), a vglapot a Clipboard.Open, illetve a Clipboard.Close parancsokkal meg kell nyitnunk a msols eltt, illetve be kell zrnunk a msols utn. Mivel a vglapot is hasznljuk ebben a programban, ne felejtsk el a modulunk uses rszt kiegszteni a Clipbrd unittal! Az alkalmazsunk esemnyeihez tartoz forrskdok:

end.

Miutn lefuttattuk a programot, prbljunk meg berni a Memo komponensbe pr sornyi szveget. Utna kattintsunk a DdeServerItem1 msolsa gombra. Ezzel lemsoltuk a szveget a kapcsolattal egytt. Indtsuk el az MS Word-ot, ahol kattintsunk a Szerkeszts Irnytott beilleszts menpontra. A megjel ablakban vlasszuk ki a Csatols lehetsget s a szveg formtumaknt jelljk be a Nem formzott szveg-et. Majd kattintsunk az OK gombra.

unit Unit1; interface uses Windows, Messages, SysUtils, , StdCtrls, Clipbrd; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin DdeServerItem1.ServerConv := DdeServerConv1; end; procedure TForm1.Memo1Change(Sender: TObject); begin DdeServerItem1.Text := Memo1.Text; end; procedure TForm1.Button1Click(Sender: TObject); begin Clipboard.Open; DdeServerItem1.CopyToClipboard; Clipboard.Close; end;

Ezzel beillesztettk a msolt szvegnket a kapcsolattal egytt az MS Word-be. Ha most az alkalmazsunk Memo komponensben megvltoztatjuk a szveget, az automatikusan meg fog vltozni az MS Word-ben is.

160

161

9 Sg ltrehozsa alkalmazshoz
Alkalamzsunkhoz ltrehozhatunk sgt tbbfle kppen. A sg ltrehozsnak egyik legegyszerbb mdja, ha valamilyen direkt erre a clra ltrehozott programot hasznlunk. Az egyik ilyen jl hasznlhat program a HelpMaker, melyet ingyenesen (freeware) letlthetnk a www.vizacc.com cmen. Ebben a programban WinHelp s HtmlHelp tpus sgt is kszthetnk, azonban itt most csak a HtmlHelp-el fogunk foglalkozni s ilyen tpus sgt fogunk ltrehozni, ugyanis ez az jabb tpus, a rgebbi WinHelp manapsg mr nem nagyon hasznlt. A program teleptse, majd indtsa utn a kvetkez kpet lthatjuk:

Itt j sg ltrehozshoz vlasszuk ki a New lehetsget. Ekkor megjelenik egy j ablak, melyben pr lpsben ltrehozhatjuk a sg vzlatt. Elsszr meg kell adnunk a projekt tpust. Itt hagyjuk a Create a new HelpMaker Solution lehetsget, majd kattintsunk a Next nyomgombra.

A kvetkez kpernyn adjuk meg a projekt mentsnek a helyt s a projekt nevt (Project Name). A projekt neve ne tartalmazzon kezetes betket s szkzt sem. Ugyanez a nv kerl a Filename mezbe is. A nv megadsa utn kattintsunk a Next gombra.

162

163

A kvetkez ablakban megadhatjuk a sgnk szerkezett. Termszetesen ezen a szerkezeten mg ksbb is vltoztathatunk. gyeljnk arra, hogy mg itt sem hasznljunk kezetes betket, csak az angol ABC betit s szkzket, ugyanis ezeken a neveken fogja a program a HTML oldalakat ltrehozni s itt az kezetes betkkel gondok lehetnek. Az kezeteket ahol majd szksges, ksbb kirakhatjuk a sg szerkesztsekor. Amelyik oldalakat valamilyen csoporton bellre szeretnnk tenni, azt beljebb rjuk a jobb oldalon tallhat gombok segtsgvel. Ha sszelltottuk a sgnk vzlatt, kattintsunk a Finish nyomgombra.

Ezek utn a program bal szln megjelent a szerkezet, melyet megadtunk (ezeket itt mr tnevezhetjk gy, hogy tartalmazzanak kezetes betket is rkattintunk az egr jobb gombjval, majd Edit / Rename (F2)). Itt brmelyik rszre kattintva megadhatjuk a hozz tartoz tartalmat is a program jobb rszn tallhat

szvegszerkeszt segtsgvel. Itt mr hasznljunk kezetes betket is!

164

165

Tovbbi hasznos belltsi lehetsgeket tallunk mg a A SajatHelpem rszre kattintva a bal oldali svban Window List Main alatt, ahol megadhatjuk a httr sznt, a sg ablaknak kezdeti mrett s elhelyezkedst, tovbb itt a HtmlHelp Options alatt egyszer jellngyzetek segtsgvel azt is, hogy a sgnk ablaknak melyik rszei legyenek lthatk. A General rsznl megadhatjuk a sg cmt (Help Title), tovbb azt, hogy melyik oldal legyen a kezdoldal (Default Topic) s rhatunk hozz szerzi jogokat jelz sort is (Copyright). A Website rsznl (flnl) egy kis HTML tudssal szinte teljesen megvltoztathatjuk a sg lapjainak klalakjt.

megadhatjuk az egsz sgra vonatkoz belltsokat. Itt rdemes foglalkoznunk a General rsszel (fllel) s a Website egyes rszeivel.

166

167

A programozs szempontjbl nagyon fontos szmunkra, hogy a sg mindegyik oldalnak legyen egy egyedi azonostja, mellyel majd tudunk hivatkozni r a Delphibl. Ez az azonost a Help Context Number. Ezek megadshoz kattitntunk a bal oldali svban (Document Map) valamelyik lapra (pl. Bevezet), majd az eszkztrbl vlasszuk ki a ikont. Ezzel a Bevezet oldal belltsaihoz jutottunk. Itt

Hasonlan lltsuk be ezt az rtket az j dokumentum-nl 2re, a Dokumentum megnyits-nl 3-ra, stb. Az oldalhoz tartoz belltsokbl (Control) vissza az oldal szerkesztshez a belltsok alatt tallhat Back nyomgombbal mehetnk. Miutn elksztettk a sgt, azt hasonlan, mint a Delphi alkalmazsokat, le kell fordtanunk. Ezt megtehetjk az eszkztrbl a gomb kivlasztsval vagy a menbl a Tools Compile (F9) menpont kivlasztsval. Fordts utn rgtn megjelenik a sgnk s letrejn egy .chm kiterjeszts llomnyunk (_tmphhp almappban), amely valjban a sg sszes rszt tartalmazza. Ezt az egyetlen CHM kiterjeszts

lltsuk t a Help Context Number rtkt 0-rl 1-re.

168

169

llomnyt kell majd a Delphi-ben megrt alkalmazsunkkal egytt terjesztetnk.

gy, hogy rgtn az adott szm (Help Context Number) oldal jelenjen meg.

Ha az alkalmazs Sg Sg menpontjra kattintva azt

9.1 Sg megnyitsa Delphi alkalmazsbl


Most, hogy megvan a sg fjlunk (.chm), msoljuk t ezt a fjlt az Delphi-ben rt alkalmazsunk knyvtrba.

szeretnnk, hogy jelenjen meg a sg a kezdoldallal, akkor a menhoz a kvetkez programkdot kell bernunk:

HtmlHelp(handle,'sajathelpem.chm',0,0); Indtsuk el a Delphit, s itt nyissuk meg azt az alkalmazst, melyhez a sgt ksztettk. A mi pldnkban ez egy egyszer menvezrelt szvegszerkeszt program. Pelda30 Ahol az els paramter valjban az alkalmazsunk ablaknak azonostja (form1.handle), a msodik paramter pedig a sg fjl neve. A harmadik s negyedik paramterben a 0 rtk most azt jelenti, hogy a sg a kezdoldallal jelenjen meg. Prbljuk meg most belltani azt, hogy ha a Memo

komponensnk az aktv s megnyomjuk az F1 billentyt, akkor a sg Szveg rsa rsznl jelenjen meg. Ennek a rsznek a Help Context Number-ja 5. Ehhez a Memo komponens OnKeyUp esemnyt fogjuk felhasznlni:

procedure TForm1.Memo1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_F1 then HtmlHelp(handle,'sajathelpem.chm', HH_HELP_CONTEXT,5); end;
170 171

A programunkbl a sgt ktfle kppen nyithatjuk meg:

gy, hogy a sg kezdoldala jelenjen meg,

Miutn megvizsgltuk, hogy az F1 gomb volt-e lenyomva, hasonlan az elz pldhoz a HtmlHelp paranccsal megnyitjuk a sgt. Itt azonban mr harmadik paramternek HH_HELP_CONTEXT konstanst adunk meg, negyedik paramternek pedig az oldalunk azonostjt (Help Context Number).

10 Telept llomny ltrehozsa


Miutn elksztettk az alkalmazsunkat, melyet terjeszteni szeretnnk, rdemes elkszteni a felhasznlk szmra egy teplept llomnyt (setup). Ennek a telept llomnynak kne tartalmazznia az

alkalmazsunk sszes llomnyt tmrtett formban. Ha a felhasznl elindtja a tepeltst ezen llomny

segtsgvel, akkor pr lpsben tmsolja a szmtgpre a szksge llomnyokat, berakja a programot a Start menbe esetleg kitesz egy ikont az asztalra is. Termszetesen mi is rhatunk sajt teleptt, de hasznlhatunk ksz, ingyenes programokat is ilyen telept llomny elksztshez. Az egyik ilyen legelterjedtebb freeware program az Inno Setup Compiler, amely letlthet a www.innosetup.com cmrl. A telepts utn indtsuk el ezt a programot.

172

173

Majd vlasszuk ki a File New menpontot. Megjelenik egy j ablak, melyben pr egyszer krds segtsgvel bellthatjuk a teleptnk paramtereit.

Miutn mindezt megtettk s vgigmemtnk az sszes lpsen, a programban megjelennek egy szkript formjban a belltsok. Ezeket mg szksg szerint itt is mdosthatjuk.

174

175

Gyakorlatok:
1. Ksztsnk egy TCsepp osztlyt, amely egy escseppet (krt) rajzol ki a megadott Image komponensre. A TCsepp osztlynak rjuk meg a konstruktort, mely csak egy paramtert tartalmazzon annak az Image (ExtCtrls unitban tallhat) komponensnek a nevt, ahov az escseppet ki akarjuk rajzolni. A konstruktor generljon ki egy vletlenszer koordintt ezen a kpen (Image-en) s egy vletlen sugarat (0-tl 29-ig). Majd rajzolja ki az escseppet erre a koordintra. Az osztly tartalmazzon mg egy kirajzol s egy letrl eljrst, amely kirajzolja a krt az objektumhoz tartoz koordintra az objektumhoz tartoz sugrral. A kirajzolst bsClear (graphics unitban tallhat) ecsetstlussal s RGB(sugr*8, sugr*8, 100+sugr*5) (windows unitban tallhat) kk sznrnyalat krvonallal vgezzk. Az osztlynak legyen mg egy nvekszik A telept llomny ltrehozshoz (lefordtshoz) vlasszuk ki az eszkztrbl a menpontot. Ekkor ltrejn egy EXE kiterjeszts llomny, amely ikont vagy a menbl a Build Compile metdusa, amely letrli az escseppet, nveli a sugart, majd megnzi hogy a sugr nem rte-e el a 30 pixelt. Ha elrte, akkor belltja 0-ra s j koordintkat generl ki az objektumnak. Vgl kirajzolja az escseppet. Ezt az osztlyt felhasznlva ksztsnk egy programot, amely megjelent 30 escseppet s 25 szzad-msodpercenknt nveli azok nagysgt (amg nem rik el a 30-at, utna egy msik helyen 0 sugrral jelennek meg). Gyak01

segtsgvel a felhasznlk telepthetik az alkalmazsunkat a sajt gpkre. Terjesztskor elg ezt az egyetlen llomnyt forgalomba hoznunk.

176

177

2. Ksztsnk egy TDeszka osztlyt, majd ennek segtsgvel azt az alkalmazst, melyben vletlen hosszsg deszkk szklnak a vzen. Az els sor balra, a msodik jobbra, a harmadik megint balra, a negyedik megint jobbra, az tdik sor pedig ismt balra sszon. gyeljnk arra, hogy kt egyms melletti deszka kztt mindig legyen egy kis hely. Az egyik szln kisz deszkk a msik szln sszanak be (ne hirtelen jelenjenek meg). Gyak02

3. Ksztsnk TCsillag osztlyt, amely kirajzol egy vletlen mret (pl. 1-tl 5-ig) csillagot. Az osztlynak legyen egy olyan metdusa, melynek meghvsval a csillag eggyel nagyobb mret s vilgosabb kk szn lesz. Ha elri az 5-s mretet, akkor tnjn el s egy j, vletlen helyen jelenjen meg 1-es mrettel s sttkk sznnel. A TCsillag osztly segtsgvel ksztsnk egy kpernyvdt, amely teljes kpernyn kirajzol 100 csillagot, majd ezek mrett s fnyessgt a megrt metdus segtsgvel nveli (ha valamelyik csillag elri a maximum mrett, akkor egy msik helyen jelenjen meg kis mretben). Az alkalmazs brmelyik billenty megnyomsval fejezdjn be. Gyak03

178

179

kperny tetejrl "jjjn be" ms x koordintval, ms mrettel s ms sznnel (vletlenszer). Gyak04

4. Definiljon kln unitban egy TNegyzet osztlyt, melynek legyenek kvetkez tulajdonsgai: x, y koordintja, oldalnak hossza, kitlts szne (termszetesen ms tulajdonsga is lehet, ha szksges). rjuk t az Tartalmazzon osztlyhoz egy tartoz Mozgat metdust, is, melynek melynek meghvsakor a ngyzet egy pixellel lejjebb "pottyan" a kpernyn. konstruktort paramtereknt adjuk megy hogy melyik Image komponensre szeretnnk kirajzolni a ngyzeteket. A konstruktor generljon ki vletlen szmokat az x, y koordintkra, az oldalhosszra s a kitlts sznre. Szksg szerint tovbbi metdusokat is 5. Ksztsnk egy dinamikus csatols knyvtrat (DLL-t), amely indtsakor ebbl az osztlybl ksztsen 10 tartalmaz egy prmszm fggvnyt. Ez a fggvny a paramterben megadott egsz szmrl dntse el, hogy az prmszm-e s ettl fggen adjon vissza igaz vagy hamis rtket. A megrt DLL-t felhasznlva ksztsk el az albbi alkalmazst, amely egy nyomgomb megnyomsakor megvizsglja, hogy az Edit komponensben megadott szm prmszm-e. Gyak05 tartalmazhat. A program

objektumot, melyeket helyezzen el egy Image komponensen. Az alkalmazs bezrsakor ne felejtse el felszabadtani az

objektumoknak lefoglalt memrit. Az objektumok Mozgat metdusainak folyamatos meghvsval a ngyzetek "potyogjanak" a kpernyn amg a program fut. Ha valamelyik ngyzet teljesen elhagyja a kperny aljt, akkor a

180

181

6. Ksztsnk alkalmazst prmszmok generlsra, amely egy nyomgombot, egy ListBox-ot s egy Gauge komponest tartalmaz. A nyomgomb megnyomsa utn a program a ListBox-ba generlja ki az els 20000 prmszmot. A Gauge komponens folyamatosan jelezze, hogy a 20000 prmszmnak eddig hny szzalka tallhat a ListBox-ban. A nyomgomb megnyomsa utn a prmszmok generlst (majd berst a ListBox-ba s a Gauge komponens frisstst) egy kln programszlban vgezzk el! Prbljuk gy megrni az algoritmust, hogy az a szmok generlst minl hamarabb elvgezze. Gyak06

182

183

Irodalomjegyzk:
[1] Vclav Kadlec: Delphi Hotov een, ISBN: 80-251-0017-0, Computer Press, Brno, 2003 [2] Steve Teixeira, Xavier Pacheco: Mistrovstv v Delphi 6, ISBN: 807226-627-6, Computer Press, Praha, 2002 [3] Kuzmina Jekatyerina, Dr. Tams Pter, Tth Bertalan:

Programozzunk Delphi 7 rendszerben!, ISBN: 963-618-307-4, ComputerBooks, Budapest, 2005 [4] Marco Cant: Delphi 7 Mesteri szinten, I. ktet, ISBN: 963-930166-3, Kiskapu Kft., Budapest, 2003

184

You might also like