You are on page 1of 191

VGH Ladislav

PROGRAMOZS DELPHIBEN II.









Komrno, 2012
Selye Jnos Egyetem - Komrno
Elsz
A "Programozs Delphiben II." tanknyv a "Programozs
Delphiben I." cm knyv folytatsa. Azok szmra kszlt, akik
rszletesebben meg szeretnnek ismerkedni a Windows opercis
rendszer alatti, vizulis, esemnyvezrelt programozssal Borland
Delphi krnyezetben.
A tanknyv foglalkozik az osztlyok, objektumok ltrehozsval,
melyeket gyakorlati pldk segtsgvel is bemutat. A knyv tovbbi
rszei a DLL-ek ltrehozsnak, prhuzamos programozsnak, OLE s
DDE technolgik alkalmazsnak alapjait mutatja be. Az utols fejezet
egy olyan alkalmazst mutat be, amely segtsgvel knnyen
kszthetnk sgt a sajt programjainkhoz.
Az elmagyarzott feladatok forrskdjai megtallhatk a CD
mellkletben, ezek mappinak nevt egy kis CD ikon jelli a tanknyv
szvegben. Javasoljuk azonban, hogy a tanknyv olvassa kzben
prblja meg sajt maga elkszteni a lertak alapjn az egyes
alkalmazsokat s csak vgszksg esetn hasznlja a mellkletet.
A tanknyv vgn tovbbi, magyarzat nlkli gyakorl
feladatok tallhatk. Ezek elksztst teljes mrtkben az olvasra
bzzuk. Egy-egy mintamegolds azonban itt is megtallhat a CD
mellkletben.
Mint minden tanknyv els kiadsnak, ennek a tanknyvnek is
lehetnek hinyossgai. Ennek ellenre hisznk abban, hogy a knyv
mindenki szmra hasznos segdeszkzknt fog szolglni.
Tartalom
1 Objektum orientlt programozs................................................... 5
1.1 Az OOP alapelvei .......................................................................... 6
1.2 Adatrejts ...................................................................................... 7
1.3 Virtulis mez (property) ............................................................. 11
1.4 Constructor, destructor................................................................ 13
1.5 rkls ........................................................................................ 16
1.6 Virtulis metdus (virtual)............................................................ 18
1.7 Dinamikus metdus (dynamic).................................................... 24
1.8 Absztrakt metdus (abstract) ...................................................... 27
1.9 Tpuskompatibilits...................................................................... 29
1.10 Tpusellenrzs (is opertor) .................................................... 31
1.11 Tpuskonverzi (as opertor) .................................................... 32
1.12 Interface-k (interface) ................................................................ 32
1.13 Osztly-vltozk........................................................................ 35
1.14 Osztly-metdusok.................................................................... 39
1.15 Hivatkozs a pldnyra a self azonostval .............................. 40
2 OOP a gyakorlatban...................................................................... 42
2.1 Pattog labdk ............................................................................ 42
2.2 szkl alakzatok (kr, tglalap, hromszg) ............................ 51
3 Vizulis komponensek ltrehozsa s megszntetse a
program futsa kzben................................................................. 60
3.1 Nyomgombok ltrehozsa, megszntetse egrkattintskor ... 63
3.2 Vizulis komponensbl szrmaztatott osztly ............................ 65
4 DLL-ek hasznlata s ltrehozsuk ............................................ 69
4.1 DLL ksztse.............................................................................. 70
4.2 A DLL felhasznlsa alkalmazsunkban .................................... 74
4.3 Statikus s dinamikus importls................................................ 77
4.4 A DLL s a memria.................................................................... 82
4.5 Form trolsa DLL-ben ............................................................... 82
4.6 A DLL (s a benne trolt Form) felhasznlsa alkalmazs
ksztsekor Delphi-ben.................................................................... 85
4.7 A DLL (s a benne trolt Form) felhasznlsa a MS Excel makr
nyelvben (Visual Basic) ................................................................... 87
4.8 Erforrsok trolsa DLL-ben..................................................... 88
4.9 DLL-ben trolt erforrsok felhasznlsa ................................... 91

5 Prhuzamos programozs, szlak .............................................. 94
5.1 TThread osztly........................................................................... 94
5.2 Szakaszok prhuzamos kirajzolsa............................................ 98
5.3 Szlak szinkronizlsa vrakozs egy msik programszlra 102
5.4 Programszlak prioritsa........................................................... 106
5.5 Tbbszl MDI alkalmazs ....................................................... 112
6 OLE technolgia.......................................................................... 119
6.1 A Delphi s az OLE................................................................... 120
6.2 Els OLE-t hasznl alkalmazsunk......................................... 121
6.3 Az OleContainer tulajdonsgai.................................................. 128
6.4 Kulcsszavak lekrdezse s vgrehajtsa ............................... 130
6.5 OLE objektum beolvassa s mentse..................................... 132
6.6 Menk sszekapcsolsa........................................................... 134
6.7 Sajt Word, Excel, Paint, ...................................................... 137
7 OLE Automation.......................................................................... 142
7.1 MS Word irnytsa Delphi-bl ................................................. 142
7.2 MS Excel irnytsa Delphi-bl ................................................. 146
8 DDE Technolgia ........................................................................ 152
8.1 DDE a Delphiben....................................................................... 153
8.2 Els DDE szerver ...................................................................... 155
8.3 Els DDE kliens......................................................................... 157
8.4 Parancs kldse a szerverre..................................................... 159
8.5 A Microsoft Word, mint DDE kliens........................................... 164
9 Sg ltrehozsa alkalmazshoz .............................................. 168
9.1 Sg megnyitsa Delphi alkalmazsbl ................................... 176
10 Telept llomny ltrehozsa................................................... 179
Gyakorlatok ....................................................................................... 183
Irodalomjegyzk ................................................................................ 190


5
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;

6



var ElsoObj: TElso;
begin
ElsoObj := TElso.Create;
ElsoObj.Inicialas;

ElsoObj.Free;
end;

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).

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.

type TMasodik = class(TElso)

end;

TElso az sosztly (szl).

7
TMasodik az j, szrmaztatott osztly (gyerek).
Egy sbl tbb szrmaztatott osztlyt is ltrehozhatunk. Minden
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
jrars nlkl is.
Ezt virtulis (vagy dinamikus) metdusokkal rhetjk el.

type TElso = class

procedure Akarmi; virtual;
end;

TMasodik = class(TElso)

procedure Akarmi; override;
end;

1.2 Adatrejts
Public
Ide kerlnek olyan attribtumok, melyek nem ignyelnek
specilis szablyozst. Az ilyen attribtumok rtkeinek
megvltoztatsa nem okozhat problmt az objektum mkdsben.
Az itt felsorolt metdusokat a klvilg meghvhatja.

8

Private
Az itt felsorolt attribtumokhoz a klvilg nem frhet hozz. Ide
rjuk ltalban azokat a vltozkat, melyek rtkeit szablyozni akarjuk.
Tovbb ide kerlnek a segdvltozk is.
Az itt szerepl metdusokat a klvilg nem hvhatja meg, csak
az adott osztly metdusaibl rhetk el.

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
private
nev: string;
eletkor: integer;
public
procedure Valami;
end;



var
Peti: TSzemely;
begin

Peti.eletkor := 18; { ez NEM mukodik !!! }

end;

9

Adatrejts elnyei:
A mezkhz a hozzfrs szablyozhat.

Adatrejts htrnyai:
Nem szablyozhat, hogy csak az olvasst, vagy csak az rst
engedlyezzk, illetve tiltjuk. Csak egy idben lehet mindkt elrst
engedlyezni / tiltani.

Adatok nem elrejtsnek a htrnya:
type TSzemely = class
public
eletkor: integer;

end;



begin

Peti.eletkor := -400; { HIBS rtk }

end;

Adatrejts htrnyai:
type TSzemely = class
private
eletkor: integer;

end;



10

begin

Peti.eletkor := -400; { ez nem mkdik }
writeln(Peti.eletkor); { de EZ SEM megy }

end;

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); { hibajelzs }
Peti.SetEletkor(18); { rendben }
writeln(Peti.GetEletkor); { rendben }

end;

11
1.3 Virtulis mez (property)
A virtulis mezk (property) segtsgvel jobban megoldhatk
az elz problmk az adatrejtsnl:

type
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; { hibajelzs }
Peti.Eletkor := 18; { rendben }
writeln(Peti.Eletkor); { rendben }

end;

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

12
a read utn rhatunk egy ugyanolyan tpus fizikai mezt,
a read utn rhatunk egy paramter nlkli fggvnyt,
melynek visszatrsi rtke megegyezik a virtulis mez
tpusval.

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.

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.


13
1.4 Constructor, destructor
A konstruktor (constructor) specilis metdus, amely feladata
az objektum ltrehozsa az osztlybl s annak alaphelyzetbe lltsa
(mezk kezdrtkeinek belltsa).

type
TSzemely = class
private
fEletkor: integer;
public
constructor Create;

end;



constructor TSzemely.Create;
begin
fEletkor := 0;

end;



var
Peti: TSzemely;
begin
Peti := TSzemely.Create;

end;

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

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

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;


15
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.
A destruktor neve ltalban Destroy. A destruktor meghvhatjuk
ezzel a nvvel, vagy meghvhatjuk a Free metdus segtsgvel, amely
leellenrzi, 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;



var
Peti: TSzemely;
begin
Peti := TSzemely.Create;

Peti.Free; { vagy: Peti.Destroy; }
end;


16
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.

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

17
(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); { eredmny: 10 }
writeln(p.Akarmi(1)); { eredmny: 11.5 }
p.free;
end;


18
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:

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

19
pa := TAOszt.Create;
pb := TBOszt.Create;
writeln(pa.Masodik); { Mennyit r ki? 2-t }
writeln(pb.Masodik); { Mennyit r ki? 2-t }

end;

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;
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;

20
end;



var
pa:TAOszt;
pb:TBOszt;
begin
pa := TAOszt.Create;
pb := TBOszt.Create;
writeln(pa.Masodik); { Mennyit r ki? 2-t }
writeln(pb.Masodik); { Mennyit r ki? 11-t }

end;

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

21
szrmaztatott osztlyban valsznleg fell fogjk definilni. A
szrmaztatott osztlyban (s abbl szrmaztatott osztlyokban is) a
felldefinilt eljrshoz override; kulcsszt kell kitenni.

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); { Mennyit r ki? 2-t }
writeln(pb.Masodik); { Mennyit r ki? 11-t }

22

end;

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.:

type TElso = class
procedure A;
procedure B;
procedure C; virtual;
procedure D; virtual;
end;

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

23
A leszrmazott osztly VMT-je gy jn ltre, hogy:
lemsoljuk 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
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),
ahogy haladunk lefel az rkldsi grfban, gy a
VMT-k egyre hosszabbak s hosszabbak 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)
ugyanaz a VMT-ja.

24
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).
A konstruktorban a VMT hozzrendelse az objektumhoz a
konstruktor elejn trtnik (a Delphiben), gy a konstruktor belsejben
mr lehet virtulis metdust hvni.
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!

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.

type
TAOszt = class
public
function Elso:integer; dynamic;
function Masodik:integer;
end;


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


A mkdse a programban ugyanaz, mint ha virtulis metdust
hasznltunk volna. A klnbsg a memriafoglalsban s a
gyorsasgban van.
A dinamikus metdusok a VMT-tl egy kicsit eltr, Dinamikus
Metdus Tblt (Dynamic Method Table) hasznlnak a legjabb
verzij metdus megtallshoz. Ennek felptst is egy pldn
szemlltetjk:

type TElso = class
procedure A;
procedure B;
procedure C; dynamic;
procedure D; dynamic;
end;

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

Ezekhez az osztlyokhoz tartoz DMT-k:



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

26
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
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 DMT-
jben, 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 dinamikus s virtulis metdusokat lehet keverni egy
osztlyon bell. Teht egy osztlyban lehetnek dinamikus 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 hasznlni.

27
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.

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

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

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;

De ez NEM J MEGOLDS, mert amikor ebbl
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:

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

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

Az ilyen osztlybl tilos objektum ltrehozsa (pldnyosts),
az ilyen osztly csak azrt van ltrehozva, hogy abbl szrmaztassunk
j osztlyokat. 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
kell lennie, klnben hibazenetet kapunk.
Ezzel elrtk azt, hogy a fordtprogram figyelmeztet
bennnket, ha elfelejtettk felldefinilni a szrmaztatott osztlyokban
az absztrakt metdusokat (Kirajzol, Letorol) legksbb akkor, amikor a
TKor osztlybl objektumot akarunk ltrehozni.

1.9 Tpuskompatibilits
Milyen objektumokat lehet tadni az albbi eljrsnak?

procedure JobbraMozdit(graf: TGrafObj);
begin
graf.Mozgat(graf.x + 1, graf.y);
end;


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

var
k: TKor;
n: TNegyzet;
begin

JobbraMozdit(k);
JobbraMozdit(n);
end.

Teht: a gyermek-osztlyok fellrl kompatibilis tpusok az s-
osztlyukkal, 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 TObject-
el.
Viszont a JobbraMozdit eljrs az albbi paramterezssel nem
mkdik, mivel a TObject-nek nincs Mozgat metdusa.

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

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


31
1.10 Tpusellenrzs (is opertor)
Elfordulhat azonban, hogy nem sikerl tallni a fenti
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.:

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

A then gra akkor kerl a vezrls, ha a graf objektum
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,
ugyanis a graf-rl az eljrs mg mindig gy tudja, hogy TObject s
ennek nincs Mozgat metdusa.

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-!

32
1.11 Tpuskonverzi (as opertor)
A fenti problma megoldsra alkalmazhat az as opertor.
Ennek hasznlata: objektumnv AS osztlynv. Pl:

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

vagy egy msik megolds:

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

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!

1.12 Interface-k (interface)
Kpzeljk el, hogy a kvetkez helyzet ll el:


33
TObject

TKor TLabda
(van Mozgat) (van Mozgat)

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
koordintkra helyezzk. A TObject osztlynak (s osztlynak) viszont
nincs ilyen Mozgat metdusa. Milyen tpust adjunk meg ilyenkor az
albbi eljrs paramtereknt?

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);

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.

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

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,
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
interface-ek.
Miutn definiltuk az interface-t, az objektumokat, melyek
implementljk ezt az interface-t a kvetkez kppen definilhatjuk:


35
type

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

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

Az ArrebRak eljrsunk pedig gy mdosul:

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

A tpuskompatibilitst teht kibvthetjk: az osztly
kompatibilis az seivel s az interface-ekkel is, melyeket megvalst.
Egy osztlynak mindig csak egy se lehet, de tetszleges
szm interface-t implementlhat. Pl.:

type
TKor = class(TGrafObj, IMozgathato, ITorolheto)

end;

1.13 Osztly-vltozk
Hogyan hozhatunk ltre olyan mezt, amely pl. azt szmolja,
hogy mennyi objektumot ksztettnk az adott osztlybl. Legyen ennek

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

type TAkarmi = class

constructor Create;

end;

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

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:

unit Sajat;

interface

type TAkarmi = class

constructor Create;

end;

implementation

var darab: integer;

constructor TAkarmi.Create;
begin
darab := darab + 1;

37
end;



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.
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

38

darab := 0;

end.

Ms programozsi nyelveken erre ltezik egy .n. osztly szint
konstruktor, mely a program indulsnak elejn hvdik meg.
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:

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

39
result := darab;
end;



initialization

darab := 0;

end.

Ez azonban nem a legjobb megolds, mivel a Darabszam
fggvny hasznlathoz ltre kell hoznunk egy objektumot a TAkarmi
osztlybl:

var x: TAkarmi;
begin
x := TAkarmi.Create;
Write(Eddig ,x.Darabszam, objektum van.);

end;

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;


40


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



Ezt a fggvnyt most mr pldnyosts nlkl is tudjuk
hasznlni:

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

41
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;


42
2 OOP a gyakorlatban
Ebben a rszben nhny gyakorlati pldn keresztl
szemlltetjk 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


43


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;

44
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;

45
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
sznt 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).




46
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, y-
hoz 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 hozzrendeli 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
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 Form-jn 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.

47
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

48

{$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;

49

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 vletlen adatokkal. Minden labda ltrehozsa utn
ellenrizzk, hogy nem tkzik-e valamelyik mr eltte ltrehozott

50
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 kirajzoljuk a labdt, s jhet a kvetkez labda
ltrehozsa
A Timer OnTimer esemnyben mindegyik labdnak
meghvjuk a Mozgat metdust, majd leellenrizzk 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 nyilak jellik az tkzs eltti rgi irnyokat (melyek
dx, dy segtsgvel vannak meghatrozva), a piros nyilak jellik az j

51
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, mindegyik alakzatnak lesz
egy sajt irnya.




52
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
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
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

53
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
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


54
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;
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);

55
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
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;

56
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;


end.

Ami rdekes a TGrafObj osztlynl s mg nem tallkoztunk
vele az elz feladatban, az a Letorol s Kirajzol metdusok, melyek itt
virtulis, absztrakt 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 plusz mezje, ami a kr sugart
jelli (s). A Create metdusban belltjuk ennek a meznek a kezdeti
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
osztlyokat, melyeket szintn a TGrafObj osztlybl szrmaztatunk.
Miutn elksztettk az egyes osztlyokat, megrhatjuk az
alkalmazst, amely ezeket hasznlja fel. Hasonlan az elz feladathoz

57
itt is egy Image komponensen fogjuk megjelenteni az objektumokat s
az objektumok mozgatst egy Timer komponens segtsgvel
valstjuk meg.
Az alkalmazs forrskdja:

unit Unit1;

interface

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
{ 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;

58
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),
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

59
lehetsges, mivel ezt a tmbt TGrafObj tpusnak deklarltuk, s a
TGrafObj kompatibilis az sszes leszrmaztatott osztllyal.
A Form OnCreate esemnyben ltrehozzuk az egyes
objektumokat vletlen 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.


60
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
Form-ra, 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:

var MyButton: TButton;

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


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

61
gomb tulajdonosa az a Form lesz, amely tartalmazza a fent lert
programkdot. Termszetesen Self helyett rhattunk volna Form1-et is,
ha ez a neve a Form-unknak.
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 Form-unk 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
Form-jt jelenti. Itt is megadhattuk volna helyette pl. a Form1-et, vagy
akr Panel1-et, ha van panel komponensnk a Form-on.
Vgl megadjuk a gomb elhelyezkedst a Top s Left
tulajdonsgok segtsgvel, s a gombon megjelentend szveget 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:

type
TForm1 = class(TForm)

62
FormMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState;
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.


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

63
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 Form-ra 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 }

64
end;

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.

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 nyomgombra kattintskor azrt ezt az esemnyt
hasznltunk az OnClick esemny helyett, mert ez utn az esemny utn

65
mr nincs kritikus kd, teht ebben megtrtnhet a gomb felszabadtsa
a Free metdusnak a segtsgvel.
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 osztlyokbl ltrehozott objektumok. Ezrt
minden rvnyes rjuk, amit az els fejezetben elmondtunk az objektum
orientlt programozsrl.
Az ilyen komponens-osztlyokbl 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.

66
A kvetkez mintaplda egy olyan nyomgomb-osztly
ltrehozst mutatja be, amely azon kvl, hogy rendelkezik a
hagyomnyos Button sszes tulajdonsgval s metdusval, tartalmaz
mg nhny tulajdonsgot (dx, dy) s egy Mozgat metdust, melynek
meghvsval a nyomgomb mozogni fog a Form-on a dx-szel s dy-nal
megadott irnyba.
Pelda04
Ezt az j osztlyt (TMyButton) a TButton osztlybl
szrmaztattuk. A Form ltrehozsakor az j osztlybl ltrehoztunk 10
darab objektumot. Ha valamelyik ilyen nyomgombra rkattintunk, azt
felszabadtjuk a memribl.
Alkalmazsunk tervezsi nzetben a Form-on 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

67
{ Public declarations }
end;

TMyButton = class(TButton)
private
dx,dy: integer;
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

68
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);
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.

A forrskdban most is vastaggal emeltk ki a fontosabb
programrszeket.


69
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
futtathatk, 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 DLL-
eket hasznlni? Ehhez nzzk meg a DLL-ek felhasznlhatsgt s
azok fbb elnyeit:
Tbb program hasznlhatja ugyanazt 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 programozsi
nyelven kszlt alkalmazsokban is felhasznlhatjuk. Teht
a DLL-ben tallhat fggvnyeket, eljrsokat

70
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.

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



71

Ekkor megjelent egy res dinamikus 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
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 nlkli 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 DLL-
fggvnyt 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:


72
library dll_pelda;

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;

73
begin
a1 := 1;
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 Delphi-
ben 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.

74
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).

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

75
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
alkalmazsunkat 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



76

Ahhoz, hogy a DLL-ben definilt alprogramokat elrhetv
tegyk, importlnunk kell ket. Minden DLL-ben tallhat 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:




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';


77
function Fibonacci:int64; stdcall; external
'dll_pelda.dll';

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.

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

78
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 dinamikus 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 LoadLibrary(KonyvtarNeve: PAnsiChar): HModule;

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, egybknt a betlttt modul azonostjt
kapjuk vissza.
Ha a DLL-t sikerlt betltennk a memriba, akkor
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;

79

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 FreeLibrary(hLibModule: HModule): Bool;

Paramterknt a LoadLibrary fggvny meghvsakor kapott
azonostt kell megadnunk.
Nzzk meg egy plda segtsgvel, hogyan hasznlhatjuk a
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 futtatni fogjuk).
Az alkalmazsunk most csak egy res Memo s egy Button
komponenseket tartalmazzon. A nyomgomb megnyomsakor a DLL-
fggvny segtsgvel kiszmoljuk, majd kirjuk a Memo komponensbe
8 s 12 legnagyobb kzs osztjt, legkisebb kzs tbbszrst s az
els 10 Fibonacci szmot.

Pelda07


80


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');

81
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 adhatjuk meg, illetve krdezhetjk
le.

82
4.4 A DLL s a memria
A dinamikus csatols knyvtrak alaphelyzetben nem
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.

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

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

Pelda08



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



procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
Label2.Caption := IntToStr(ScrollBar1.Position);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ModalResult := mrOk;
end;

84

procedure TForm1.Button2Click(Sender: TObject);
begin
ModalResult := mrCancel;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
Left := (Screen.Width - Width) div 2;
Top := (Screen.Height - Height) div 2;
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:

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);

85
{ form megjelenitese - adatbekeres }
if Form.ShowModal = mrOk then
result := Form.ScrollBar1.Position
else
result := -1;
{ form felszabaditasa }
Form.Free;
end;

Exports
AdatBekeres;

begin
end.

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 Form-ot.

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 DLL-
fggvny (Form) segtsgvel bekr egy szmot. A DLL-fggvny ltal
visszaadott szmot jelentsk meg egy Label komponensben.


86

Pelda09



Az alkalmazsunk forrskdja:



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.

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 DLL-
fggvny vgzi el.

87

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
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
szmot rakja be az aktv cellba a 15 helyett.
Pelda10
A feladat megoldshoz a makr Visual Basic-ben rt
forrskdjt gy mdostsuk:

Declare Function AdatBekeres
Lib "dll_form.dll" () As Integer

Sub Makro1()
ActiveCell.FormulaR1C1 = AdatBekeres
End Sub

Ltjuk, hogy hasonlan a Delphi programozsi nyelvhez, itt is
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.

88

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




89
A feliratokat s a kpet erforrs fjlokban fogjuk trolni,
melyeket hozzcsatolunk a DLL-ekhez. A feliratokhoz sztringtblt
definilunk.

Az eng.rc fjl tartalma:

kep BITMAP "en.bmp"

STRINGTABLE DISCARDABLE
BEGIN
1 "Calculation"
2 "Exit"
3 "Datainput"
4 "Result"
END

A hun.rc fjl tartalma:

kep BITMAP "hu.bmp"

STRINGTABLE DISCARDABLE
BEGIN
1 "Szmols"
2 "Kilps"
3 "Adatbevitel"
4 "Eredmny"
END

Ezeket a fjlokat a Delphi rszeknt megtallhat brcc32.exe
fordtval lefordtjuk .res kiterjeszts llomnyokk:
brcc32.exe eng.rc
brcc32.exe hun.rc

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

library dll_hu;

uses
SysUtils,
Classes;

{$R *.res}

{$R hun.res}

begin
end.

Az angol nyelvt pedig a dll_en.dll-be:

library dll_en;

uses
SysUtils,
Classes;

{$R *.res}

{$R eng.res}

begin
end.

Ezzel elksztettk a kt DLL llomnyt (magyar s angol),
melyeket a kvetkez feladatban fogunk felhasznlni.

91
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
ngyzetre, majd az eredmnyt jelentse meg a msik Edit
komponensben.

Pelda12



A Form-ra helyezzk el a szksges komponenseket
(MainMenu1, Label1, Label2, Edit1, Edit2, Button1, Button2, Image1),
majd lltsuk be ezek fontosabb tulajdonsgait s rjuk meg az
esemnyekhez tartoz programkdot:



implementation

92

{$R *.dfm}

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;

93

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

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

end.

A 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.


94
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.

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
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

95
kivlasztjuk a Thread Object-ot. Ez utn megadjuk annak az osztlynak
a nevt, melyet a TThread osztlybl szeretnnk szrmaztatni:



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

unit Unit2;

interface

uses
Classes;

type
TVonalSzal = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;

implementation

{ }

96

procedure TVonalSzal.Execute;
begin
{ Place thread code here }
end;

end.

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 meghvsnl 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

97
az rtke igaz (true), akkor az Execute metdus befejezdjn, s ezzel
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
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 llapthatjuk meg.
A programszl teljes lelltst a Terminate metdus
segtsgvel vgezhetjk el, amely valjban a 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.
Egy msik megolds a programszl memribl val
felszabadtsra, hogy mg az elejn (pl. ltrehozs utn) belltjuk a
FreeOnTerminate tulajdonsg rtkt true-ra. Ilyenkor ha a
programszl futsa befejezdik, automatikusan felszabadul a
memribl (nem kell meghvnunk a Free metdust).


98
5.2 Szakaszok prhuzamos kirajzolsa
Ksztsnk alkalmazst, amely vletlen hely s szn
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.

99
Nzzk meg elszr a programszlunkat tartalmaz unit
forrskdjt:

unit Unit2;

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;

100

end.

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 alkalmazsunk komponenseinek esemnyeihez tartoz
forrskd:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, , Unit2;



var
Form1: TForm1;
Szal: TVonalSzal;

implementation


101
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
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.

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.

102
A Button1 OnClick esemnyben miutn belltottuk a
nyomgombok elrhetsgt, a Resume metdus segtsgvel
elindtjuk a programszlat.
A Button2 OnClick esemnyhez tartoz eljrsban ennek a
programszlnak a futst a Suspend metdus segtsgvel
felfggesztjk.
A Form OnDestroy esemnyben a Form memribl val
felszabadtsa eltt, ha a programszlunk futsa fel volt fggesztve,
akkor elindtjuk, majd a Terminate metdus meghvsval a
programszlunk futst (Execute eljrst) befejezzk. Vgl a Free
metdus segtsgvel felszabadtjuk a programszlnak lefoglalt
memrit.

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 alkalmazsunk 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.

103

Pelda14



Miutn ltrehoztuk az alkalmazst, hozzunk ltre egy
programszlat j unitban (THozzaadSzal), majd ebbe a unitba berjuk
manulisan a msik programszlunkat is (TSzor2Szal). Ennek a
modulnak a programkdja gy nz ki:

unit Unit2;

interface

uses
Classes;

type
THozzaadSzal = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;

TSzor2Szal = class(TThread)
private
{ Private declarations }
protected

104
procedure Execute; override;
procedure LabelFrissites;
end;


implementation

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.

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,

105
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:

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.

A Szor2Szal programszl a ltrehozsa utn rgtn elindul
(mivel a konstruktor paramterben false rtket adtunk meg).

106
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:



5.4 Programszlak prioritsa
A programszl ltrehozsa utn megadhatjuk a Priority
tulajdonsg segtsgvel a programszl futsi prioritst. A nagyobb
priorits programszl tbb processzoridt kap az opercis
rendszertl, gy az gyorsabban le tud futni mint a kisebb priorits. Tl
nagy prioritst azonban csak indokolt esetben adjuk egy
programszlnak, ugyanis az jval lelasstja a tbbi programszl futst.

107
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.
tpLower A norml prioritsnl egy ponttal alacsonyabb.
tpNormal Norml priorits szl.
tpHigher A norml prioritsnl egy ponttal magasabb.
tpHighest 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.



108

Pelda15

A Form-on helyezznk el kt Image komponenst (golyk) s
hrom Button komponenst.
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 komponenst s a
prioritst a programszlnak.
A programszl forrskdja:

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;


109
implementation

Uses Unit1, Forms;

constructor TGolyoSzal.Create;
begin
inherited Create(false);
FGolyo := AGolyo;
FXKoord := FGolyo.Left;
Priority := APrioritas;
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.

A Create konstruktorban ltrehozzunk az s konstruktornak
meghvsval a programszlat, melyet rgtn futtatunk is (false

110
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 hosszabb ideig tart mveletet. Klnben a legbonyolultabb
mvelet a goly mozgatsa lenne, amit a fprogramszl vgez el (a
Kirajzol metdus szinkronizlsval), gy a priorits nem lenne
rzkelhet.
A Kirajzol metdus arrbb 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:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, , Unit2;



implementation

{$R *.dfm}

var
g1, g2: TGolyoSzal;

procedure TForm1.FormCreate(Sender: TObject);
begin

111
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;
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.

Lthatjuk, hogy a kt goly mozgatst vgz programszlra
kt globlis vltozt vezettnk be (g1, g2). A Form ltrehozsakor

112
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 alkalmazsbl.
A Form OnDestroy esemnyben, ha a programszlak ppen
felfggesztett llapotban vannak, akkor elindtjuk ket, majd a
Terminate metdus segtsgvel befejeztetjk a futsukat. Vgl
felszabadtjuk a szmukra lefoglalt memrit a Free metdus
meghvsval.

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

113


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.
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.

114
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, Windows;

type
TSzal = class(TThread)
private
{ 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;

115
begin
repeat
x1 := random(img.Width);
y1 := random(img.Height);
x2 := random(img.Width);
y2 := random(img.Height);
szin := random($FFFFFF);
Synchronize(Kirajzol);
Sleep(1);
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;


116
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: TObject; var
Action: TCloseAction);
begin
Action := caFree;
Szal.Terminate;
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.

A Form osztlynak private deklarcijba ne felejtsk el berni
a programszlunkat (Szal:TSzal;).

117
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 Form-unkhoz 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):

unit Unit1;

interface

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;

118
n: integer;

implementation

{$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
n := 1;
end;

end.

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
menpontjt kivlasztva hozzuk ltre a Create konstruktor segtsgvel.
Az j ablak tulajdonosnak az MDI Form-ot (self) lltjuk be.


119
6 OLE technolgia
Az OLE (Object Linking and Embedding = objektum csatolsa
s beszrsa) egy rdekes technolgia, melyet a Microsoft fejlesztett ki.
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
alkalmazsunkban elhelyezni olyan objektumot, amely egy msik
alkalmazsban van definilva.

120
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 llomnnyal fogunk.

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 mkdni fog a

121
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 Form-on egy ilyen komponenst,
melyben a kivlasztott objektum fog megjelenni. Ez utn meghvhatjuk
az InsertObjectDialog metdust, amely egy dialgusablakot 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
alkalmazsunkban megjelenteni Word, Excel, Paint, stb.
dokumentumokat.
Pelda17
A Form-ra 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

122
fennmarad rszt, majd lltsuk be mind a ngy Anchors tulajdonsgt
true-ra. Ezzel az alkalmazsunk tervezsvel megvagyunk.



rjuk meg az egyes esemnyekhez tartoz programkdot:



procedure TForm1.Button1Click(Sender: TObject);
begin
OleContainer1.InsertObjectDialog;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
{ az OLE objektum merete az ablak

123
atmeretezeskor valtozzon }
OleContainer1.Anchors :=
[akLeft, akTop, akRight, akBottom];
{ az OLE objektum ne 3D, hanem egyszeru
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. Ha ezt mr megtettk az alkalmazs
tervezsekor, akkor itt nem szksges. Ezek utn belltottuk az
OleContainer Ctl3D tulajdonsgt false-ra. Ez sem felttlenl
szksges, csak a kontainer klalakjt vltoztatja meg. Termszetesen
ezt a tulajdonsgot is bellthattuk volna tervezsi idben.
Az alkalmazsunk leglnyegesebb rsze az Objektum
beszrsa gomb megnyomsakor trtnik. Ennek a gombnak az
OnClick esemnyben az OleContainer InsertObjectDialog
metdusnak segtsgvel megnyitunk egy dialgusablakot, melyben a
felhasznl kivlaszthatja, hogy milyen objektumot s milyen formban
(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.

124
Tovbb ebben a dialgusablakban megadhatjuk azt is, hogy
az objektumot eredeti formban (tartalmt) akarjuk megjelenteni, vagy
csak az ikonjt szeretnnk megjelenteni az OLE kontainerben.



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.


125


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



126

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.

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 tartoz
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 }

127
OleContainer1.AllowInPlace := false;
end;



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.




128
6.3 Az OleContainer tulajdonsgai
Az OleContainer-nek sok sajt tulajdonsga van, ezek kzl
felsorolunk egypr gyakrabban hasznlt tulajdonsgot:
Az AllowInPlace tulajdonsg segtsgvel bellthatjuk, ahogy
azt mr az elz programunkban is tettk, hogy az objektum
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).

129
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.


130
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.
Az alkalmazsunk tartalmazzon egy ListBox komponenst,
melyben megjelentjk az sszes objektum ltal tmogatott kulcsszt.
Tovbb alkalmazsunkon legyen egy Panel komponens 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




131
Az alkalmazs tervezsnl elszr a panelt helyezzk el a
Form-on, ennek Align tulajdonsgt lltsuk be alBottom-ra. Erre a
panelre helyezzk el a nyomgombokat.
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.
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.

132

6.5 OLE objektum beolvassa s mentse
A kvetkez alkalmazsunk egy Panel-t, rajta ngy
nyomgombot s egy OleContainert fog tartalmazni. Az egyes
nyomgombok segtsgvel fogjuk szemlltetni a dokumentum
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.



Az egyes nyomgombokhoz tartoz esemnyek:



procedure TForm1.Button1Click(Sender: TObject);
begin
OleContainer1.CreateObjectFromFile(
ExpandFileName('teszt.doc'), false);
end;

133

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);
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,
hanem OLE objektum, akkor azt csak a LoadFromFile metdus
segtsgvel tudjuk beolvasni.
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.

134
Lehet hogy egy kicsit furcsnak tnik, mirt van ilyen nagy
klnbsg a hagyomnyos llomny (Word dokumentum, bitmap, )
kztt s az OLE objektumot tartalmaz llomny formtuma 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 fog szolglni. Tovbb tegynk a Form-ra egy
OleContainer s egy MainMenu komponenst. lltsuk be a
komponensek tulajdonsgait, majd alaktsuk ki az brn lthat
menszerkezetet a MainMenu komponensnl.


135


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.



136

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.
Most ennek a tulajdonsgnak egy tovbbi felhasznlsval
ismerkedhetnk meg. A GroupIndex segtsgvel azt is
befolysolhatjuk, hogy a menk 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 ezen menpontjai nem lesznek
megjelentve.
Prbljuk meg most tlltani az alkalmazsunk MainMenu
komponensben a Szerkeszts menpont GroupIndex tulajdonsgt 1-
re. Ha gy elindtjuk az alkalmazsunkat, akkor az objektum
szerkesztsnl a mi Szerkeszts mennk mr nem lesz lthat.

137



Hasonlan a menkhz, az eszkztrak is sszekapcsolhatk.
Alaprtelmezett belltsoknl az OLE szerver eszkztra fellrja az
alkalmazsunk eszkztrt. Ha ezt el szeretnnk kerlni, lltsuk be az
alkalmazsunk eszkztrnak Locked tulajdonsgt True rtkre.

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

138
Az alkalmazsunk indtsakor egy OleContainer-t s egy
MainMenu-t fog tartalmazni. Ennek a MainMenu komponensnek csak
egy fmenpontja lesz, a File. A tbbi menpontot a beolvasott
objektumhoz taroz OLE szerver fogja berakni.



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 Form-on jelenjen meg.
Tovbb ne felejtsk el megadni az OleContainer SizeMode
tulajdonsgt smScale-ra. Ezzel elrjk, hogy az egsz dokumentum

139
lthat lesz a kontainerben (arnyosan lekicsinytve vagy felnagytva a
kontainer mrethez).
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(

140
SaveDialog1.FileName);
end;

procedure TForm1.Bezrs1Click(Sender: TObject);
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.


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


142
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 irnytani.

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


143


Az sszes fontos parancs knnyen megrthet az
alkalmazsunk forrskdjbl. Amit azonban fontos megjegyeznnk:
az alkalmazs uses rszt ki kell bvtennk a ComObj
unittal,
definilnunk kell egy globlis vltozt a Word alkalmazsra
(w), melynek tpusa Variant lesz.
Mieltt ttekintennk az alkalmazsunk nyomgombjaihoz
tartoz programkdot, ismerkedjnk meg a variant tpus hasznlatval,
mellyel eddig mg nem tallkoztunk.
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 objektum-
modellhez (COM) val csatlakozs volt. A varins vltozk hasznlata
knyelmes, hiszen bizonyos tpusok kzti talaktsok automatikusan

144
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.
Most, hogy mr tudjuk milyen a varins tpus, nzzk meg az
alkalmazsunk forrskdjt, melyben a Word alkalmazsunk objektuma
egy ilyen varins tpus:

unit Unit1;

interface

uses
Windows, Messages, , Dialogs, StdCtrls, ComObj;



implementation

{$R *.dfm}

var
w: Variant;

procedure TForm1.FormCreate(Sender: TObject);
begin
FormStyle := fsStayOnTop;
end;


145
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

146
begin
w.Quit(false); { false = kilepeskor a
'Menti a valtozasokat?'
kerdesre a valasz nem }
w := Unassigned;
end;
end;

end.

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
feljtsszuk az adott mveletet, majd megnzzk a makro Visual Basic-
ben rt forrskdjt gy megtudhatjuk milyen objektum, melyik
tulajdonsgt kell megvltoztatnunk, melyet utna 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.

147

Pelda23



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;

148

procedure TForm1.FormCreate(Sender: TObject);
begin
FormStyle := fsStayOnTop;
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;


149
end.

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 a Word-hoz, az Excel objektumainak
tulajdonsgairl s metdusairl sok informcit megtallhatunk az
Excel sgjnak Visual Basic rszben. Konkrt mveletek
elvgzshez tartoz objektumok s tulajdonsgok meghatrozsban
itt is segtsgnkre lehet az Excel makrja.

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




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

unit Unit1;

interface

uses
Windows, Messages, , Spin, ComObj;



implementation

{$R *.dfm}

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;

151
end;

end.

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 egyb 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!


152
8 DDE Technolgia
A DDE (Dynamic Data Exchange) a Microsoft ltal kifejlesztett
protokoll. 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
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.

153
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).
elem (item) az tadott adatok legpontosabb
identifikcija. Egy tmhoz tbb elem is tartozhat. A
Delphi-ben az elem neveknt a DDE szerver
elemkomponensnek a nevt kell megadnunk
(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.

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

154
elemhez hozzfrni. Legfontosabb tulajdonsga a Text,
amelyben a DDE kommunikciban 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 kliensknt mkdjn. Fontos tulajdonsga a
DdeConv, amely segtsgvel megadhat, hogy melyik
kliens tmhoz tartozzon az elem. Tovbbi 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 SetLink megprbl kapcsolatot kialaktani.
o CloseLink befejezi az aktulis konverzcit.
o ExecuteMacro parancsot kld a szervernek.
Az albbi bra szemllteti egy egyszer DDE konverzcihoz
szksge tulajdonsgok s metdusok belltst a szerveren s a
kliensen:


155


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 kialaktsakor a szolgltats, tma s
elem nevt pontosan gy adjuk meg a kliensen, ahogy a szerveren
szerepel. Itt fontos a kis- s nagybet is!

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

156



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:



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;

end.


157
A Form Create esemnyben belltjuk a kezdeti
belltsokat: kitrljk a szvegdoboz tartalmt s sszekapcsoljuk a
DdeServerItem1 komponenst a DdeServerConv1 komponenssel.
Amint a forrskdbl is lthatjuk, ha megvltozik a
szvegdobozunk tartalma, azonnal megvltoztatjuk a DdeServerItem1
Text tulajdonsgt is az j tartalomra.
Ezzel 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.

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 Edit-
be runk).
Pelda26



158

Az egyes komponensek, illetve a Form esemnyeihez tartoz
programkd:



implementation

{$R *.dfm}

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.

A nyomgomb megnyomsakor a SetLink metdus
segtsgvel megprblunk csatlakozni a szerverhez. Ha ez a metdus

159
igaz rtket ad vissza, akkor a kapcsolat ltrejtt. Egyb 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
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).


160


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 paramter
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

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

Szerver ltrehozsa
A szervernk nagyon hasonl lesz az els DDE szerverhez,
csupn annyival lesz kiegsztve, hogy ha bekvetkezik a
DdeServerConv1 komponens OnExecuteMacro esemnye, 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;



162
procedure TForm1.DdeServerConv1ExecuteMacro(Sender:
TObject; Msg: TStrings);
begin
if Msg[0]='torold' then
begin
ShowMessage('A kliens kri a szvegdoboz
trlst.');
Edit1.Text := '';
end;
end;

end.

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



Az egyes esemnyekhez tartoz forrskd:



implementation

163

{$R *.dfm}

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.

Miutn elkszltek a szerver s kliens alkalmazsaink, azok
elindtsval, majd a kliens kapcsoldsval a szerverhez
kiprblhatjuk a torold parancs kldst is a szervernek.

164

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 komponenseket s egy Button komponenst fog
tartalmazni.



A szerver a Memo-ba rt szveget fogja szolgltatni a kliensnek.
Teht amikor megvltozik a Memo komponensben a szveg, akkor azt
berakjuk a DdeServerItem1 Text tulajdonsgba is.

165
A nyomgomb megnyomsval lemsoljuk a
CopyToClipboard metdus segtsgvel a DdeServerItem1
komponens tartalmt. gy nem csak a szveget msoljuk le a vglapra,
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:

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;

166
DdeServerItem1.CopyToClipboard;
Clipboard.Close;
end;

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 megjelen ablakban vlasszuk ki a
Csatols lehetsget s a szveg formtumaknt jelljk be a Nem
formzott szveg-et. Majd kattintsunk az OK gombra.




167
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.

168
9 Sg ltrehozsa alkalmazshoz
Alkalmazsunkhoz 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, amely egy ingyenesen (freeware)
alkalmazs.
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:




169
Itt j sg ltrehozshoz vlasszuk ki a New lehetsget.
Ekkor megjelenik egy j ablak, melyben pr lpsben ltrehozhatjuk a
sg vzlatt. Elszr 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.


170


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.


171


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!


172


A SajatHelpem rszre kattintva a bal oldali svban
megadhatjuk az egsz sgra vonatkoz belltsokat. Itt rdemes
foglalkoznunk a General rsszel (fllel) s a Website egyes rszeivel.
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.


173


Tovbbi hasznos belltsi lehetsgeket tallunk mg a
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.


174


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 kattintsunk a bal oldali svban
(Document Map) valamelyik lapra (pl. Bevezet), majd az eszkztrbl
vlasszuk ki a ikont. Ezzel a Bevezet oldal belltsaihoz
jutottunk. Itt lltsuk t a Help Context Number rtkt 0-rl 1-re.


175


Hasonlan lltsuk be ezt az rtket az j dokumentum-nl 2-
re, 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 ltrejn egy .chm
kiterjeszts llomnyunk (_tmphhp almappban), amely valjban a
sg sszes rszt tartalmazza. Ezt az egyetlen CHM kiterjeszts

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

9.1 Sg megnyitsa Delphi alkalmazsbl
Most, hogy megvan a sg fjlunk (.chm), msoljuk t ezt a fjlt
az Delphi-ben rt alkalmazsunk knyvtrba.
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



A programunkbl a sgt ktfle kppen nyithatjuk meg:

177
gy, hogy a sg kezdoldala jelenjen meg,
gy, hogy rgtn az adott szm (Help Context Number)
oldal jelenjen meg.
Ha az alkalmazs Sg Sg menpontjra kattintva azt
szeretnnk, hogy jelenjen meg a sg a kezdoldallal, akkor a menhz
a kvetkez programkdot kell bernunk:

HtmlHelp(handle,'sajathelpem.chm',0,0);

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);

178
end;



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).


179
10 Telept llomny ltrehozsa
Miutn elksztettk az alkalmazsunkat, melyet terjeszteni
szeretnnk, rdemes elkszteni a felhasznlk szmra egy telept
llomnyt (setup).
Ennek a telept llomnynak kne tartalmaznia az
alkalmazsunk sszes llomnyt tmrtett formban.
Ha a felhasznl elindtja a teleptst 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.


180


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


181


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


182


A telept llomny ltrehozshoz (lefordtshoz) vlasszuk ki
az eszkztrbl a ikont vagy a menbl a Build Compile
menpontot.
Ekkor ltrejn egy EXE kiterjeszts llomny, amely
segtsgvel a felhasznlk telepthetik az alkalmazsunkat a sajt
gpkre. Terjesztskor elg ezt az egyetlen llomnyt forgalomba
hoznunk.

183
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
vletlen genertor segtsgvel egy 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 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



184


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


185


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.


186

Gyak03



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). Tartalmazzon egy Mozgat metdust, melynek
meghvsakor a ngyzet egy pixellel lejjebb "pottyan" a kpernyn.
rjuk t az osztlyhoz tartoz konstruktort is, melynek
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
tartalmazhat.
A program indtsakor ebbl az osztlybl ksztsen 10
objektumot, melyeket helyezzen el egy Image komponensen. Az
alkalmazs bezrsakor ne felejtse el felszabadtani az
objektumoknak lefoglalt memrit.

187
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
kperny tetejrl "jjjn be" ms x koordintval, ms mrettel s
ms sznnel (vletlen genertorral kigenerlt).

Gyak04



5. Ksztsnk egy dinamikus csatols knyvtrat (DLL-t), amely
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.

188
A megrt DLL-t felhasznlva ksztsk el az albbi alkalmazst,
amely egy nyomgomb megnyomsakor megvizsglja, hogy az Edit
komponensben megadott szm prmszm-e.

Gyak05



6. Ksztsnk alkalmazst prmszmok generlsra, amely egy
nyomgombot, egy ListBox-ot s egy Gauge komponenst 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

189




190
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: 80-
7226-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-9301-
66-3, Kiskapu Kft., Budapest, 2003











ISBN 978-80-8122-051-7
EAN 9788081220517
Szerz:

PaedDr. VGH Ladislav
Cm:
PROGRAMOZS DELPHIBEN II.

Kiad:

Selye Jnos Egyetem, Komrno, Szlovkia

Brlk:

RNDr. GUBO tefan, PhD.
Ing. NAGY Zoltn, PhD.

Terjedelem:
191 oldal

Megjelens ve:
2012



Els kiads