Az egér használata
Az
egér egy olyan mutató eszköz, mellyel a számítógép használója beavatkozhat a
program futásának menetébe. A képernyőn megjelenő, az egér jeleit felfogni
képes objektumok reagálnak az egér mozgására, kattintásra, kettős kattintásra
vagy vonszolásra. Így aztán egérrel parancsot adhatunk, menüpontot aktivizálhatunk vagy átrendezhetjük a felhasználói
képernyőt. Ebben a fejezetben a karakteres képernyőn megjelenő egér
lehetőségeivel ismerkedünk meg. Az egérkurzor egy téglalap, melynek egy karakternyi
a mérete. Minden karakterhely fölé odavihető, bekapcsolt állapotban és jól
működő program esetén mindig látható. Az egér használatához szükség van:
természetesen egy egérre, egy meghajtó programra, amelyet az operációs
rendszernek kell installálni. Szükség van továbbá egy olyan programcsomagra,
amely esetünkben a Pascal nyelven belül megfogalmazza az egér megjelenésével és
lekérdezésével kapcsolatos eljárásokat és függvényeket. Megtehetnénk, hogy ez
utóbbi Unit-ot saját magunk megírjuk, de a Pascal nyelvben már van egy egység, amely ezeket tartalmazza, ezért mi ezt fogjuk
használni. Ennek az egységnek a neve Drivers. Programjainkban ezt az egységet
is használatba kell venni, ha egeret szeretnénk használni.
Nézzük a Drivers Unit egérkezelő
függvényeit és eljárásait. Mivel a Drivers a Pascal nyelv Turbo Vision részéhez
tartozik, néhány szót erről is kell ejtenünk. A Turbo Vision segítségével olyan
felépítésű programokat írhatunk, mint amilyen az IDE. Teljesen objektum orientált, eseményvezérelt, ablaktechnikára épülő,
menüvezérelt programokat. A későbbiekben, csak néhány program erejéig,
megismerkedünk a Turbo Vision lehetőségeivel is. A Drivers egység tartalmazza a
Turbo Vision eseménykezelő eljárásait és függvényeit, amelyet szintén használni
fogunk. Nézzük akkor első egérkezelő programunkat.
47.
Írjunk programot, amely bemutatja az egér működését programban. Kérdezzük le az
egér koordinátáit, vezessük egérrel az írókurzort, kattintással rakjunk
csillagokat a képernyőre, majd pedig írjuk minden pillanatban a képernyőre az egér összes
állapotát. Végül a Menu függvényünket (CrtPlus) tanítsuk meg az egér
használatára.
Első lépésként tehát a Drivers
egységet használatba kell venni. Egeret használó programunk első eljáráshívása
az InitEvents, amely inicializálja az eseménykezelőt. Második a ShowMouse,
amely az egeret jeleníti meg. Ha csak ennyi lenne a programunkban (és egy
végtelen ciklus), akkor az egér már látható lenne a képernyőn. Az egér képernyő
koordinátáit a MouseWhere rekord tartalmazza. Ennek a rekordnak két mezője van,
az x és az y, és az egér helyének két koordinátáját tartalmazza. Ez állandóan
frissül, csak az a feladatunk, hogy programjainkban lekérdezzük. Ez látható a
programunk első szakaszában. Ha megfigyeljük a futtatás eredményét,
megállapíthatjuk, hogy a GoToXY eljárással a koordináták nincsenek szinkronban.
A képernyő első helyének két egér koordinátája (0,0),
az utolsóé (79,24). Ha a MouseWhere két koordinátája alapján szeretnénk a
kurzort vezérelni, akkor mindkettőhöz egyet hozzá kell adni. Ez látható a
második szakaszban. A harmadik szakasz az egérkattintásra figyel. A
MouseButtons függvény értéke 1 ha kattintottak az
egérrel, 0 ha nem. A MouseButtons érték is folyamatosan frissül, tehát
lenyomott gombbal és mozgatással a program folyamatosan rajzol a képernyőre. A
negyedik szakaszban már a teljes megfigyelést valósítottuk meg. Ehhez szükség
van egy Esemeny változóra, melynek típusa TEvent, mely egy eseményrekordot
jelent. Az eseményrekord létrehozását a Drivers elvégzi helyettünk. Ha
billentyűzet eseményt szeretnénk bekérni, akkor GetKeyEvent(Esemeny),
ha egér eseményt, akkor a GetMouseEvent(Esemeny) eljárást kell meghívnunk. Az
esemény rekord What mezőjében található az, hogy mi történt. Az esemény Buttons
mezője azt tartalmazza, hogy a történés melyik egérgombbal következett be (bal
vagy jobb, mbLeftButton vagy mbRightButton). Az esemény Double mezője igaz, ha
dupla kattintás volt, és hamis ha szimpla. A
lehetséges egéresemények:
evMouseDown
= Gomb lenyomva.
evMouseUp = Gomb felengedve.
evMouseMove
= Az egér elmozdult.
eMouseAuto = Az egér lenyomott gombbal mozog.
evNothing
= Nincs esemény.
Program
EgerDemo;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Esemeny:
TEvent;
Mp: Byte;
Begin
TextMode(CO80);
InitEvents; ShowMouse; Szinek(1,15);
ClrScr; WriteXY(1,1,'Első
szakasz');
Repeat
With MouseWhere do Begin GotoXY(37,1);
Write(x:3,y:3) End;
Until
Keypressed;
ClrScr; WriteXY(1,1,'Második
szakasz'); KeyEmpty;
Repeat
GotoXY(MouseWhere.x+1,MouseWhere.y+1)
Until
KeyPressed;
ClrScr; WriteXY(1,1,'Harmadik
szakasz');
Gotoxy(1,1);
KeyEmpty;
Repeat
If
MouseButtons=1 then
Begin
WriteXY(MouseWhere.x+1,MouseWhere.y+1,'*');
GotoXY(WhereX-1,WhereY);
End;
Until
KeyPressed;
ClrScr; WriteXY(1,1,'Negyedik
szakasz'); KeyEmpty;
Repeat
GetMouseEvent(Esemeny);
Case
Esemeny.What Of
evMouseDown: Begin
WriteXY(1,9,'Gomb
lenyomva ');
If Esemeny.Double Then
WriteXY(1,13,'Dupla
kattintás ');
If Not Esemeny.Double Then
WriteXY(1,13,'Szimpla
kattintás');
End;
evMouseUp : WriteXY(1,9,'Gomb felengedve ');
evMouseMove: Begin
WriteXY(1,10,'Egér
elmozdult ');
gotoxy(20,1);
Write(MouseWhere.X:4,MouseWhere.Y:4);
End;
evMouseAuto: begin
WriteXY(1,10,'Lenyomott
gombbal mozog');
gotoxy(20,1);
Write(MouseWhere.X:4,MouseWhere.Y:4);
end;
evNothing : WriteXY(1,11,'Nincs esemény ');
End;
Case
Esemeny.Buttons of
mbLeftButton: WriteXY(1,12,'Bal
gomb lenyomva ');
mbRightButton:WriteXY(1,12,'Jobb
gomb lenyomva');
End;
Until
KeyPressed;
ClrScr; WriteXY(1,1,'Ötödik
szakasz'); KeyEmpty;
Tomb[1]:=' Első ';
Tomb[2]:='
Második ';
Tomb[3]:=' Harmadik
';
Tomb[4]:=' Vége ';
For
Mp:=1 to 4 do SzTomb[Mp]:=Mp;
Ablak(7,0,34,8,47,13,True,'Menű');
For
Mp:=1 to 4 Do WriteXY(36,8+Mp,Tomb[Mp]);
Mp:=Menu(7,0,Green,36,9,10,4,1);
Writexy(1,24,Tomb[Mp]);
Tunj; Varj;
End.
Ahhoz hogy programunk ötödik szakasza működjön, azaz a Menu függvényünk
megértse az egér üzeneteket, egy kicsit ki kell bővítenünk. Ehhez töltsük be a
CrtPlus-t, és javítsuk ki a következőképpen. A CrtPlus-ban is használatba kell
venni a Drivers Unit-ot. Fel kell venni egy Esemeny nevű Tevent típusú lokális
változót a Menu függvényben.
function menu(hsz,ksz,vsz,bfx,bfy,sh,ss,as:byte):byte;
var
i:integer;
ch:char;
Esemeny: TEvent;
begin
szinez(vsz,ksz,bfx,bfy+as-1,sh);
repeat
GetMouseEvent(Esemeny);
If
Esemeny.What=evMouseDown then With MouseWhere do
If
(X>bfx-2) And
(X<Bfx+sh-1) And
(Y>Bfy-2) And (Y<Bfy+ss-1) then
Begin
szinez(hsz,ksz,bfx,bfy+as-1,sh);
as:=Y-bfy+2;
szinez(vsz,ksz,bfx,bfy+as-1,sh); Menu:=as;
While
MouseButtons=1 do;
Exit;
End;
If
Keypressed then ch:=readkey;
if
ch=#0 then
begin
ch:=readkey;
if
ch in [#71,#72,#79,#80] then
szinez(hsz,ksz,bfx,bfy+as-1,sh);
case
ch of
#71:as:=1;
#72:if as>1 then dec(as) else
as:=ss;
#80:if as<ss then inc(as) else as:=1;
#79:as:=ss;
end;
if
ch in [#71,#72,#79,#80] then
szinez(vsz,ksz,bfx,bfy+as-1,sh);
end;
until
ch in [#13,#27,#75,#77];
if
ch in [#13,#75,#77] then menu:=as else menu:=0;
vch:=ch;
end;
Lényegében
csak az elején, a ch:= readkey karakterbeolvasás helyett kellett az egéresemény
kezelésével kapcsolatos sorokat megírnunk. A függvény végtelen ciklusába
bekerült az egéresemény-bekérő eljárás, valamint a programot megállító ch:=
readkey helyett, az If Keypressed Then ch:= Readkey sor került, mely
billentyűesemény hiányában szintén nem áll meg. Ez a megoldás biztosítja azt,
hogy a függvény mindkét eseményt kezelni tudja. Egeret használó programokban
megfigyelhetjük azt, hogy a parancs végrehajtása nem a kattintás pillanatában,
hanem az egérgomb elengedésekor hajtódik végre. Ezt szolgálja az Exit sor
előtti While MouseButtons=1 Do; üres ciklus. A Menu a visszaadott értékét az
egér helykoordinátáiból állapítja.
Programokban gyakran találkozunk
nyomógombbal, amelynek segítségével egérrel is tudunk
parancsot adni, funkciót aktivizálni. Készítsünk olyan általánosan használható
nyomógombot, mely megjelenésében és működésében a legjobban hasonlít az IDE
nyomógombjaihoz. Tegyük alkalmassá arra, hogy a nyomógomb funkcióját
billentyűzetről és egérrel is aktivizálhassuk. A nyomógombot a CrtPlus-ban
fogjuk deklarálni. Ehhez szükség van egy gombrekordra, amely a gomb típusát
(arra gondolva, hogy nemcsak nyomógomb lehet), helyét, méretét és forró
billentyű karakterét fogja tartalmazni.
Type GombRec= Record
tip:byte;
gx,gy,gsh:byte;
Key:char;
End;
A képernyőre egy időben több nyomógomb, illetve olyan látvány is
kikerülhet, amelynek ugyanilyen paraméterei lehetnek, illetve képesek az egérre
és a billentyűzetre egyaránt reagálni. Ezek maximális száma legyen gtmax=64. A
gombrekordokat egy tömbben fogjuk tárolni. Ezért a deklarációk a következők:
Const gtmax=64;
Var GombT:array[1..gtmax] of GombRec;
GombIndex:byte;
A gombindex a képernyő felépülése közben inkrementálódik, azaz
tartalmazza a képernyőn látható nyomógombok számát. Lesz egy gombkereső
eljárásunk, amely maximálisan eddig az indexig fogja keresni azt a gombot (vagy
egyéb egérkezelésre alkalmas látványt), amelyen a kattintás történt. A gomb
paraméterei: háttérszín, karakterszín, választószín (a forró billentyű
karakterszíne), kezdőhely x koordináta és y koordináta, a gomb hossza és a gomb
felirata. A felirat tartalmazhat egy tilde jelet, mely nem kerül
megjelenítésre, és a tilde jel utáni karakter lesz a forró billentyű jele. A
nyomógomb kattintás hatására benyomódik, a fekete árnyéka eltűnik, a címke
jobbra tolódik, elengedéskor az eredeti látvány áll vissza. A gomb eljárás a
megjelenésért és a regisztrálásért felelős.
Procedure gomb(hsz,ksz,vsz,x,y,sh:byte;s:string);
Begin
Kh:=Pos(chr(126),s);
if Kh<>0
Then
Begin
Gotoxy(x+1,y);
for
i:=1 to length(s)
do
if
s[i]<>chr(126) then Write(s[i]);
End
Else
Writexy(x+1,y,s);Szinez(hsz,ksz,x,y,sh);
If kh<>0
Then Szinez(hsz,vsz,x+kh,y,1);
hsz:=bkep[y,x+sh,2] div 16;
Szinek(hsz,0);Writexy(x+sh,y,chr(220));
For I:=x+1 to x+sh do Writexy(i,y+1,chr(223));
Inc(GombIndex);
With GombT[GombIndex]
do
begin
tip:=1;
gx:=x;gy:=y;gsh:=sh;Key:=#0;
if Kh<>0
then
Key:=AltKod[UpCase(s[Pos(chr(126),s)+1])];
End;
End;
A fenti listában található egy
AltKod tömbre való hivatkozás. Ez a táblázat kapcsolja össze az egér kezelésére
alkalmassá tett elem címkéjében megjelenő karaktert a billentyűzetről alt kód
segítségével beírt karakterrel, mint paranccsal. Azaz, ettől kezdve teljesen
mindegy, hogy a Case szerkezet számára a szelektor érték honnan származik, és
így csak egy szakaszt kell a végrehajtó szakaszban egy parancshoz megírni. Íme
a kérdéses tömb.
Const AltKod:Array[#42..'Z'] Of Char=
(#42,#43,#0,#45,#46,#47,
#129,#120,#121,#122,#123,#124,#125,#126,#127,#128,
#0,#0,#0,#61,#0,#0,#0,
#30,#48,#46,#32,#18,#33,#34,#35,#23,#36,#37,#38,#50,
#49,#24,#25,#16,#19,#31,#20,#22,#47,#17,#45,#21,#44);
A gomb forró billentyűjének megkeresését a gombkereső végzi el.
Szüksége van arra a helyre, amelyen az egérrel kattintottak. Visszaadott értéke
a kulcs karakter. Végignézi a regisztrált gombokat, megnézi, hogy a kattintás
melyiken történt, és visszaadja a Key mező tartalmát. A repeat until ciklus
addig állítja meg a programot, ameddig lenyomva tartjuk az egér gombját. Az
egyszerű nyomógomb típusa 1, tehát ha ennél nagyobb a típus-érték, akkor a
függvényből kilépünk, ha viszont nyomógombon történt a kattintás, akkor a
nyomógombnak be kell nyomódnia, ahogy azt fentebb már leírtuk. Ennek a
látványnak a megírását tartalmazza a függvény további része.
Function GombKereso(x,y:byte):Char;
Var i,j,hsz:byte;
Begin
GombKereso:=#0;
For i:=1 to gtmax do with GombT[i] do
if (gy=y) and (gx<=x)
and (x<gx+gsh) then
Begin
GombKereso:=Key;
if tip>1
then
Begin
Repeat Until MouseButtons<>1;
exit;
End;
For J:=gx+1 to gx+gsh do bkep[gy+1,j,1]:=32;
For j:=gx+gsh downto gx do
Begin
bkep[y,j,1]:=bkep[y,j-1,1];
bkep[y,j,2]:=bkep[y,j-1,2];
End;
bkep[y,gx,1]:=32;
Repeat Until MouseButtons<>1;
hsz:=bkep[y,gx,2] div 16;
For j:=gx to gx+gsh do
Begin
bkep[y,j,1]:=bkep[y,j+1,1];
bkep[y,j,2]:=bkep[y,j+1,2];
End;
Szinek(hsz,0);Writexy(gx+gsh,y,chr(220));
For J:=gx+1 to gx+gsh do Writexy(J,gy+1,chr(223));
tunj;
Exit;
End;
End;
48. Írjunk programot, amely a fentebb megírt
nyomógombot teszteli. A fehér képernyőn jelenjen meg két nyomógomb. Az egyik
felirata legyen Irjál, a másiké Vége. Ha az Irjál feliratú gombot megnyomjuk,
akkor a program a képernyő véletlen helyére véletlen színnel, két véletlen karaktert
jelenít meg, egy nagybetűt és egy számjegyet. A másik gomb megnyomására fejeződjön
be a program. A két forró billentyű az I és a V.
A program a véletlen
karaktermegjelenítést az Irogat eljárás végzi. A
főprogram először a látvány létrehozását végzi el. Kialakítja a hátteret,
kirakja a két nyomógombot, eltünteti a kurzort, inicializálja az eseménykezelőt
és a véletlen-szám generátort, majd megjeleníti az egérkurzort. Majd a program
egy végtelen repeat ciklusba kezd. Ha nincs sem
billentyű- sem egéresemény, akkor megáll. Ha megnyomtuk a billentyűzetet, akkor
beolvassa a ch változóba a karaktert. A program végrehajtó része a ch által
vezérelt többszörös elágazás. A ch a billentyüzet Alt-kódját várja, azaz az
írást Alt+I-vel, a végét Alt+V-vel lehet aktiválni. Gyakran a programból való
kilépésre, úgy mint az IDE esetén, Alt+X-et használják.
Programjainkban mi is így fogunk eljárni, ezért a kilépés Alt+X-szel is
elérhető.
Program GombPro;
Uses NewDelay, Crt,
CrtPlus, Drivers;
Var Ch: char;
Procedure Irogato;
Begin
Szinek(7,Random(16));Writexy(random(79)+1,Random(25)+1,
chr(Random(26)+65)+chr(Random(10)+48));tunj;
End;
Begin
TextMode(CO80);
Szinek(7,0); ClrScr;
Gomb(2,0,14,10,5,7,'~Irj l');
Gomb(2,0,14,20,10,6,'~Vége');
Tunj; InitEvents; Randomize; ShowMouse;
Repeat
while
(not keypressed) and (MouseButtons<>1)
do;
If
Keypressed Then Ch:=Readkey;
If
MouseButtons=1 then
Ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);
Case
Ch Of
#23: Irogato;
#45,#47: Halt;
End;
Until
False;
End.
Mivel a
továbbiakban hasonló felépítésű programokat fogunk írni, készítsünk el egy
olyan alap-képernyőt, amely az üres IDE-hez nagyon hasonlít, lehessen a
programból kilépni, azaz legyen a nyomógombhoz hasonló felülete és forró
billentyűje. Az üres IDE-t DeskTop-nak nevezi a Pascal rendszer, nevezzük mi is
így. A látványt a CrtPlus-ban kódoljuk le.
De mielőtt
ebbe belekezdenénk, néhány egyszerű, a képernyőn való műveletekkel kapcsolatos
eljárást és függvényt kell megírnunk, természetesen szintén a CrtPlus-ban, ezek a Töröl, a Tölt az Olvas és az ÍrXY modulok. A töröl
egy egysoros téglalapot töröl a képernyőn. A tölt egy
egysoros téglalapot tölt fel megadható karakterrel. Az
olvas a képernyő egy egysoros téglalapján lévő karakterekből egy stringet
készít, és ezt adja vissza. Az ÍrXY a képernyő egy adott helyére megadható
szöveget kiír úgy, hogy közben az ottani színek nem változnak meg, azaz nem
használja a Write aktuális színeit.
Procedure torol(x,y,sh:byte);
Var i:byte;
Begin
For i:=x to x+sh-1 do bkep[y,i,1]:=32;
End;
Procedure tolt(x,y,sh:byte;c:char);
var i:byte;
begin
for i:=x to x+sh-1 do bkep[y,i,1]:=ord(c);
end;
Function olvas(x,y,sh:byte):string;
Var i:byte;
ws:string;
Begin
ws:='';for i:=x to x+sh-1 do
ws:=ws+chr(bkep[y,i,1]);olvas:=ws;
End;
Procedure irxy(x,y:byte;sz:string);
Var i:byte;
Begin
For I:=1 to length(sz) do
bkep[y,x+i-1,1]:=ord(sz[i]);
End;
Íme a DeskTop modul:
Procedure DeskTop;
Var i:integer;
Szinek(7,1);ClrScr;
For
i:=2 to 24 do tolt(1,i,80,chr(176));
Szinek(7,0); WriteXY(1,25,'Alt-X Exit'); Tunj;
Szinez(7,4,2,25,5); Inc(GombIndex);
With
GombT[GombIndex] do
Begin
tip:=6;gx:=2;gy:=25;gsh:=5;Key:=AltKod['X'];
End;
InitEvents;ShowMouse;
End;
Ezek
után az Alap program listája a következő:
Program
Alap;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Ch:
Char;
Begin
TextMode(CO80);
DeskTop;
Repeat
While
(Not Keypressed) And (MouseButtons<>
1) Do;
If
KeyPressed Then Ch
:= ReadKey;
If
MouseButtons= 1 Then
Ch:= GombKereso(MouseWhere.X+1,
MouseWhere.Y+1);
Case
Ch Of
#45: Halt;
End;
Until
False;
End.
Minden új
programot úgy kezdhetünk írni, hogy ezt betöltjük, az új program nevével
kimentjük lemezre és már javíthatjuk, bővíthetjük új programunkat. Ehhez
legtöbb esetben a Case szakaszt kell bővíteni, illetve a DeskTop után a
látványokat a képernyőre kell helyezni.
49. Írjunk
programot, amely a képernyőn megjeleníti a DeskTop-ot egy elég nagy címkés
ablakkal, rajta két beviteli mezőt, egyikben egy számértéket, a másikban egy
növekmény lehessen beírni. Legyen a képernyőn továbbá
négy nyomógomb a következő funkciókkal. Az első növeli az értéket a léptékkel,
a második csökkenti, a harmadik törli mindkét beviteli mezőt, a negyedikkel
kiléphetünk a programból.
Mielőtt e programot megírnánk, meg
kell írni még két dolgot. Az egyik a CrtPlus Bevitel függvényének az
egérkezelését, valamint egy InputLine látványt. Kezdjük az elsővel.
function
bevitel(hsz,ksz,x,y,sh:byte):string;
var
ch:char; i,ax:byte; ovw:boolean; bszov:string;
begin
szinez(hsz,ksz,x,y,sh); ax:=x; gotoxy(ax,y);
ovw:=false;
repeat
while (not keypressed) and (MouseButtons<>1) do;
If MouseButtons<>1 Then
ch:=readkey;
case ch of
#0:begin
ch:=readkey;
case
ch of
#71:ax:=x;
#75:if ax>x then dec(ax);
#77:if ax<x+sh then inc(ax);
#79:begin
i:=x+sh;
repeat dec(i) until bkep[y,i,1]<>32;
ax:=i+1;
end;
#82:ovw:=ovw=false;
#83:if ax<x+sh then
begin
for i:=ax to x+sh-1 do
bkep[y,i,1]:=bkep[y,i+1,1];
bkep[y,x+sh-1,1]:=32;
end;
end;
end;
#8:if
ax<>x then
begin
for
i:=ax-1 to x+sh-1 do
bkep[y,i,1]:=bkep[y,i+1,1];
bkep[y,x+sh-1,1]:=32;
dec(ax);
end;
#9:;
#13:; #27:;
else if MouseButtons<>1
then if ax<x+sh then
begin
if not ovw then for i:=x+sh-1 downto ax+1 do
bkep[y,i,1]:=bkep[y,i-1,1];
bkep[y,ax,1]:=ord(ch);
inc(ax);
end;
end;
gotoxy(ax,y);
until (ch in [#13,#27,#9]) or (MouseButtons=1);
vch:=ch;
if ch=#27 then bevitel:='' else
begin
bszov:=''; i:=x+sh;
repeat dec(i);
until (bkep[y,i,1]<>32) or (i=x); ax:=i;
for i:=x to ax do bszov:=bszov+chr(bkep[y,i,1]);
bevitel:=bszov;
end; tunj;
end;
A függvényben
az aláhúzott részek oldják meg azt, hogy kattintásra a Bevitel függvény
elhagyható. A második egy InpuLine megírása. Az InputLine egy beviteli mezőből
és egy címkéből áll. A címke a beviteli sor felett van, a befogadó dobozban
érvényes színeket nem feszi figyelembe. Ezeket a
színeket tehát körültekintően adjuk meg. A címke a doboz területén van, és
rendelkezik forró billentyűvel. Az InputLine 2-es típusú egeres látvány.
Function InputLine(dhsz,dksz,dvsz,hsz,ksz,x,y,sh:byte;
s:string):String;
Var i,kh:byte;
Begin
Szinek(dhsz,dksz);
Kh:=Pos(chr(126),s);
if Kh<>0 Then
Begin
Gotoxy(x,y-1);
for i:=1 to length(s) do if
s[i]<>chr(126) then
Write(s[i]);
End Else Writexy(x,y-1,s);
If kh<>0 Then Szinez(dhsz,dvsz,x+kh-1,y-1,1);
Szinez(hsz,ksz,x,y,sh);
Inc(GombIndex);
With GombT[GombIndex] do
begin
tip:=2;gx:=x;gy:=y;gsh:=sh;Key:=#0;
if Kh<>0 then
Key:=AltKod[UpCase(s[Pos(chr(126),s)+1])];
End;
End;
Az InputLine
paraméterei: a befogadó doboz háttérszíne, a befogadó doboz karakterszíne, a
címke választószíne, a beviteli sor háttérszíne, a beviteli sor karakterszíne,
a beviteli sor kezdőhelye (x,y) és hossza, a címke
szövege, visszaadott érték String, amelyet most még nem használunk ki.
Ezek után a léptető program kódja:
Program
Lepteto;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Ch:
Char;
ErtekSt, LeptekSt: String;
Ertek, Leptek: Longint;
Kod: Integer;
Begin
TextMode(CO80);
DeskTop;
Ablak(7,15,15,5,65,20,True,'Léptető');
InputLine(7,0,14,1,15,25,7,8,'Érté~k:');
InputLine(7,0,14,1,15,50,7,8,'~Lépték:');
Gomb(2,0,14,36,7,10,'~Növel');
Gomb(2,0,14,36,9,10,'~Csökkent');
Gomb(2,0,14,36,11,10,'~Töröl');
Gomb(2,0,14,36,15,10,'~Vége');
Ertek:= 0; Leptek:= 0; Tunj;
Repeat
While
(Not Keypressed) And (MouseButtons<>
1) Do;
If
KeyPressed Then Ch
:= ReadKey;
If
MouseButtons= 1 Then
Ch:= GombKereso(MouseWhere.X+1,
MouseWhere.Y+1);
Case
Ch Of
#37: Val(Bevitel(1,15,25,7,8),
Ertek, Kod);
#38: Val(Bevitel(1,15,50,7,8),
Leptek, Kod);
#49: If
Leptek<>0 Then
Begin
Inc(Ertek,
Leptek); Str(Ertek, ErtekSt);
Torol(25,7,8);
IrXY(25,7,ErtekSt);
End;
#46: If
Leptek<>0 Then
Begin
Dec(Ertek,
Leptek); Str(Ertek, ErtekSt);
Torol(25,7,8);
IrXY(25,7,ErtekSt);
End;
#20: Begin
Ertek:= 0; Leptek:=0;
Torol(25,7,8);
Torol(50,7,8);
End;
#45,
#47: Halt;
End;
Until
False;
End.
50. Írjunk
programot, amely két beviteli és egy kimeneti InpuLine-al rendelkezik. Az két beviteli mezőbe beírhatunk két számot. A kimeneti
mező értékét a következő funkciójú gombok állíthatják: a két szám összege, a
két szám különbsége, a két szám szorzata, a két szám hányados, a két szám
számtani közepe és a két szám mértani közepe. Legyen nyomógomb a program
elhagyására is.
Új dolgokra már nincs szükség a CrtPlus-ban. A program
listája a következő:
Program
Muvelet;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Ch:
Char;
a,b,c:real;
kod:integer;
ws:string;
Begin
TextMode(CO80);
DeskTop;
Ablak(7,15,4,3,76,22,true,'Műveletek:');
InputLine(7,15,14,1,15,18,6,10,'''~A'' szám:');
InputLine(7,15,14,1,15,18,9,10,'''~B''
szám:');
InputLine(7,15,14,1,15,18,15,10,'
~Eredmény:');
Gomb(2,0,14,40,5,23,'A
két szám öss~zege');
Gomb(2,0,14,40,8,23,'A
két szám ~különbsége');
Gomb(2,0,14,40,11,23,'A
két szám szorza~ta');
Gomb(2,0,14,40,14,23,'A
két szám ~hányadosa');
Gomb(2,0,14,40,17,23,'~Számtani
közepük');
Gomb(2,0,14,40,20,23,'~Mértani
közepük');
Gomb(2,0,14,18,20,6,'~Vége');
tunj;
Repeat
while
(not keypressed) and (MouseButtons<>1)
do;
If
Keypressed Then Ch:=Readkey;If
MouseButtons=1 Then
ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);
val(validst(olvas(18,6,10)),a,kod);
val(validst(olvas(18,9,10)),b,kod);
Case
Ch Of
#30: Bevitel(1,15,18,6,10);
#48: Bevitel(1,15,18,9,10);
#44: c:=a+b;
#37: c:=a-b;
#20: c:=a*b;
#35: if
b<>0 then
c:=a/b else ws:=' Error';
#31: c:=(a+b)/2;
#50: if
a*b>=0 then c:=sqrt(a*b)
else ws:=' Error';
#47,
#45: halt;
End;
if
ws<>' Error'then str(c:10:4,ws);
While
ws[length(ws)]='0' do ws:=copy(ws,1,length(ws)-1);
If
ws[length(ws)]='.' then ws:=copy(ws,1,length(ws)-1);
torol(18,15,10);irxy(28-length(ws),15,ws);
Ws:='';
Until
False;
Tunj;
Varj;
End.
51. Írjunk
programot, amely zsebszámológépet jelenít meg. Legyen nyomógomb a
kikapcsolásra, minden adat törlésére, a kijelző törlésére, tudja a négy
alapműveletet és előjelváltást.
A gombok elhelyezését és címkézését,
ahol lehetett for ciklussal oldottuk meg. Az eddigieknél egy kicsit
összetettebb listát kaptunk, de a feladat sem egyszerű.
Program
ZsebSzam;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var I : Byte; Ch, MCh : Char;
os,as : Real; ws : String;
Kod : Integer; Volt, Elso, Vege, Hiba : Boolean;
Begin
TextMode(CO80);
Szinek(3,0);ClrScr;
Ablak(7,15,25,4,53,18,True,'Zsebszámológép');
InputLine(7,0,14,1,15,27,6,24,'E~redmény:');
Gomb(2,0,14,27,8,5,'~OFF');Gomb(2,0,14,34,8,5,'C~LR');
Gomb(2,0,14,41,8,5,'C~E');
Gomb(2,0,14,48,8,3,'~+');
For
I:=1 To 9 Do
Gomb(2,0,14,((I-1) Mod 3)*7+27,
((I-1) Div
3)*2+10,3,'~'+chr(48+I));
Gomb(2,0,14,48,10,3,'~-');Gomb(2,0,14,48,12,3,'~*');
Gomb(2,0,14,48,14,3,'~/');Gomb(2,0,14,27,16,3,'~0');
Gomb(2,0,14,34,16,3,'~.');Gomb(2,0,14,41,16,3,'~S');
Gomb(2,0,14,48,16,3,'~=');
InitEvents;ShowMouse;Tunj;
Elso:=True;Vege:=False;Hiba:=false;
Repeat
while
(not keypressed) and (MouseButtons<>1) do;
If
Keypressed Then Ch:=Readkey; If MouseButtons=1 then
Ch:=GombKereso(MouseWhere.x+1,MouseWhere.y+1);
Case
Ch Of
#18: Torol(27,6,24);
#19: Bevitel(1,15,27,6,24);
#120..#129: Begin
If Vege Then
Begin Vege:=False; Torol(27,6,24) End;
I:=27;
While (BKep[6,I,1]<>32)and(I<50)do Inc(I);
If ch=#129 Then
BKep[6,I,1]:=Ord(Ch)-81
Else BKep[6,I,1]:=Ord(Ch)-71;
End;
#46,#48..#57: Begin
If Vege Then
Begin Vege:=False; Torol(27,6,24) End;
I:=27;Volt:=false;
While (BKep[6,I,1]<>32) and
(I<50) do
Begin
If BKep[6,I,1]=46 then
volt:=true;Inc(I)
End;
If (Ch<>#46) or (Not Volt) Then
BKep[6,I,1]:=Ord(Ch);
End;
#38: Begin Torol(27,6,24);os:=0 End;
#31: Begin
If Bkep[6,27,1] in
[48..57,46] Then
Begin
For
I:=50 downto 28 do
Bkep[6,i,1]:=Bkep[6,i-1,1];
Bkep[6,27,1]:=32;
end;
If Bkep[6,27,1]=32 then
Bkep[6,27,1]:=45
else
If Bkep[6,27,1]=45 Then
Bkep[6,27,1]:=43
else
If Bkep[6,27,1]=43 Then
Bkep[6,27,1]:=45;
End;
#13,#61,
#42,#43,
#45,#47: Begin
ws:=ValidSt(Olvas(27,6,24));
Val(Ws,As,Kod); Torol(27,6,24);
If Elso Then
Begin os:=as;elso:=false;MCh:=ch End Else
Begin
Case Mch of
#42:os:=os*as;
#43:os:=os+as;
#45:os:=os-as;
#47:If as=0 then
Begin
IrXY(46,6,'Error'); Hiba:=true;
End else os:=os/as;
End;
MCh:=ch;
End;
If MCh in [#13,#61] Then
Begin
If not hiba then
Begin
Str(Os:24:6,ws);
While ws[length(ws)]='0' do
ws:=copy(ws,1,length(ws)-1);
If ws[length(ws)]='.' then
ws:=copy(ws,1,length(ws)-1);
IrXY(50-Length(ws),6,ws);
End;
Os:=0;Vege:=true;
Elso:=True;Hiba:=false;MCh:=#0;
End;
End;
#27,#24: Halt;
End;
Ch:=#0;
Until
False;
End.
52. Írjunk egy
kis egyszerű játékprogramot. A játék lényege: a gép véletlen számértékeket
mutat 1-től 6-ig (kockadobás). A játékos minden dobás után tippelhet, vajon a
következő véletlen szám a mutatotthoz képest milyen lesz: kisebb, nagyobb vagy
egyenlő. Ha eltalálta, akkor pontjai eggyel nőnek, ha nem, akkor a gép pontjai
nőnek eggyel. Ha sikerül a játékosnak előbb elérni a 10-et akkor nyer, ha a gépnek
akkor veszít. Az állást folyamatjelző jelezze a képernyőn.
A program kódja semmi újat nem tartalmaz.
Program Talalo;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Ch:
Char;
a, b, t, n: byte;
Ws: String;
St, Vege: Boolean;
Procedure
Start;
Begin
t:= 0; n:= 0; St:= True; Vege:= False;
Szinek(7,15);
WriteXY(37,13,'Talált:'); Szinez(7,1,37,14,10);
Tolt(37,14,10,chr(176)); WriteXY(37,16,'Nem
talált:');
Szinez(7,1,37,17,10);
Tolt(37,17,10,chr(176));
Torol(55,15,13);
Torol(10,8,12);Torol(55,8,12);
Tunj;
End;
Begin
TextMode(CO80);DeskTop;
Ablak(7,15,4,3,75,22,True,'Találó');
InputLine(7,15,13,1,15,10,8,12,'Az ''A''
szám:');
InputLine(7,15,13,1,15,55,8,12,'A ''B'' szám:');
Gomb(2,0,14,34,6,14,'~Kisebb mint');
Gomb(2,0,14,34,8,14,'~Egyenlő');
Gomb(2,0,14,34,10,14,'~Nagyobb mint');
Gomb(2,0,14,22,20,7,'~Start');
Gomb(2,0,14,55,20,7,'~Vége'); Start; St:=
False; Randomize;
Repeat
while
(not keypressed) and (MouseButtons<>1) do;
If
Keypressed Then Ch:= Readkey; If MouseButtons=1 Then
ch:=
GombKereso(MouseWhere.x+1,MouseWhere.y+1);
Case
Ch Of
#31: Begin
Start; A:=Random(6)+1; Str(A,Ws); IrXY(11, 8, Ws)
End;
#37: If
Not Vege Then
Begin
St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);
If A<B Then
Begin inc(t);IrXY(36+t,14,Chr(219))End Else
Begin inc(n);
IrXY(36+n,17,Chr(219)) End;
End;
#18: If
Not Vege Then
Begin
St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);
If A = B Then
Begin inc(t); IrXY(36+t,14,Chr(219)) End Else
Begin inc(n); IrXY(36+n,17,Chr(219)) End;
End;
#49: If
Not Vege Then
Begin
St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);
If A > B Then
Begin inc(t); IrXY(36+t,14,Chr(219)) End Else
Begin inc(n); IrXY(36+n,17,Chr(219)) End;
End;
#45,
#47: halt;
End;
If
Ch<>#0 Then
Begin
If
(T=10) Or (N=10) Then Vege:=True;
If
(Not St) And (Not Vege) Then
Begin
Delay(1000);A:=Random(6)+1;
Str(A,Ws);IrXY(11, 8, Ws);
Torol(55,8,10); Duda;
End;
If
Vege Then
Begin
Szinek(7,Blink);
If
T=10 Then
WriteXY(55,15,'Nyertél!!!')
Else
WriteXY(55,15,'Vesztettél!!!'); Tunj;
End;
End;
Until
False;
End.
53. Írjunk labdatartást folyamatosan számoló és
kijelző programot.
Ebben a kódlistában egyetlen új
dolog található. Mégpedig az, hogy ha nincs sem egér, sem billentyűzet esemény,
akkor is számolnia kell az eltelt időt, ezért az eddigi while (not keypressed) and (MouseButtons<>1) do szakasz most nem lesz üres. Itt
történik a számolás és a kijelzés.
Program
Labda;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Var Ch:
Char;
Anal: Boolean;
a, as, b, bs, n: Longint;
wsa, wsb: String;
Begin
TextMode(CO80); DeskTop;
Ablak(7,0,15,4,65,21,True,'Labdatartást
figyelő program');
InputLine(7,0,14,1,15,26,7,8,'A Csapat');
InputLine(7,0,14,1,15,46,7,8,'B Csapat');
Gomb(2,0,14,25,12,10,'~A Csapat');
Gomb(2,0,14,45,12,10,'~B Csapat');
Gomb(2,0,14,38,18,6,'~Vége');
Tunj;
Anal:= True;
Repeat
while
(not keypressed) and (MouseButtons<>1) do
Begin
Inc(n);
If
Anal Then
Begin
IrXY(32,10,'A-nál van a labda'); Inc(a) End
Else
Begin IrXY(32,10,'B-nél van a
labda'); Inc(b) End;
Str(Round(100*a/n):4,Wsa);
IrXY(26,7,Wsa+'%');
Str(Round(100*b/n):4,Wsb);
IrXY(46,7,Wsb+'%');
End;
If
Keypressed Then Ch:= Readkey;
If
MouseButtons=1 Then
ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);
Case
Ch Of
#30: Anal:= True;
#48: Anal:= False;
#45,
#47: halt;
End;
Until
False;
End.
54. Írjunk egy
tipizált lemezes állományt kezelő programot, például a Pascal nyelv nyelvi
elemeinek tárolására. Tároljunk kulcsszavakat, típusukkal együtt, jelezzük
milyen egységben találhatók, írjunk rá mintapéldát és magyarázatot. Az
állományon lehessen mozogni, lehessen beszúrni, törölni és javítani. Az
aktuális rekord mindig jelenjen meg a képernyőn.
Program
Help;
Uses NewDelay,
Crt, CrtPlus, Drivers;
Type
HelpRec= Record
Kulcsszo: String[20];
Tipus: String[10];
Egyseg: String[10];
Minta: String[64];
Megjegy: String[64];
End;
Var Ch : Char;
ARec, PRec : HelpRec;
FNev
: File Of HelpRec;
DNev
: String;
I, RS, AS
: Integer;
Ws,WW
: String;
Procedure
KezdoKep;
Begin
Ablak(7,15,4,3,74,22,True,
'Turbo Pascal Help-file kezelő
program');
InputLine(7,15,14,1,15,7,6,20,'~A keresett
kulcsszó:');
InputLine(7,15,14,1,15,7,9,10,'~Típusa:');
InputLine(7,15,14,1,15,7,12,10,'~Unit:');
InputLine(7,15,14,1,15,7,15,64,'~Példa:');
InputLine(7,15,14,1,15,7,18,64,'~Megjegyzés:');
InputLine(7,15,14,1,15,61,6,10,'Index:');
Gomb(2,0,14,7,20,11,'~Következő');
Gomb(2,0,14,21,20,7,'~Előző');
Gomb(2,0,14,31,20,8,'~Beszúr');
Gomb(2,0,14,42,20,7,'~Javít');
Gomb(2,0,14,52,20,7,'Tö~röl');
Gomb(2,0,14,64,20,6,'~Vége');
End;
Procedure
AdatTorles;
Begin
Torol(7,6,20);Torol(7,9,10);Torol(7,12,10);
Torol(7,15,64);Torol(7,18,64);
End;
Procedure
AdatKepre;
Begin
AdatTorles;
With
ARec Do
Begin
IrXY(7,6,Kulcsszo);IrXY(7,9,Tipus);IrXY(7,12,Egyseg);
IrXY(7,15,Minta);IrXY(7,18,Megjegy);
End;
End;
Procedure
AdatKeprol;
Begin
With
ARec Do
Begin
Kulcsszo := ValidSt(Olvas(7,6,20));
Tipus := ValidSt(Olvas(7,9,10));
Egyseg
:= ValidSt(Olvas(7,12,10));
Minta := ValidSt(Olvas(7,15,64));
Megjegy
:= ValidSt(Olvas(7,18,64));
End;
End;
Procedure
Lemezrol;
Begin
DNev:='Turbo.shl';Assign(FNev,DNev);{$I-}Reset(FNev);{$I+}
If
IOResult<>0 Then
RewRite(Fnev);RS:=FileSize(FNev);
AS:=0; If
RS>0 Then Begin Seek(FNev,AS);Read(Fnev,ARec) End;
End;
Begin
TextMode(CO80);DeskTop; KezdoKep; Lemezrol;
AdatKepre; Tunj;
Repeat
Str(RS,WS);Str(AS,WW);
IrXY(61,6,Copy(WW+'/'+WS+' ',1,10));
while
(not keypressed) and (MouseButtons<>1) do;
If
Keypressed Then
Begin
Ch:=Readkey;If ch=#0 Then Ch:=ReadKey End;
If
MouseButtons=1 Then
ch:=
GombKereso(MouseWhere.x+1,MouseWhere.y+1);
With
ARec Do
Case
Ch Of
#30:Kulcsszo:= Bevitel(1,15,7,6,20); {Kulcsszó}
#20:Tipus := Bevitel(1,15,7,9,10); {Típus}
#22:Egyseg := Bevitel(1,15,7,12,10); {Unit}
#25:Minta := Bevitel(1,15,7,15,64); {Példa}
#50:Megjegy :=
Bevitel(1,15,7,18,64); {Megjegyzés}
#73,
#37:If
AS<RS-1 Then {Következő}
Begin
Inc(AS);Seek(FNev,AS);Read(Fnev,ARec);AdatKepre
End
Else
Begin AdatTorles;If AS<RS Then Inc(AS) End;
#81,
#18:If
AS>0 Then {Előző}
Begin
Dec(AS);Seek(FNev,AS);Read(Fnev,ARec);Adatkepre
End;
#13,
#48:If
ValidSt(Olvas(7,6,20))<>'' Then
{Beszúr}
Begin
AdatKeprol;
If (RS=0) Or (AS=RS) Then Write(FNev,ARec)
Else
If AS=RS-1 Then
Begin
Read(FNev,PRec);Write(FNev,PRec);Seek(FNev,AS);
Write(FNev,ARec);Inc(RS);
End
Else
If AS<RS-1 Then
Begin
For I:=RS DownTo AS+1 Do
Begin
Seek(FNev,I-1);
Read(FNev,PRec);
Write(FNev,PRec)
End;
Seek(FNev,AS);Write(FNev,ARec);Seek(FNev,AS);
End;
Inc(RS);
End;
#36:If
ValidSt(Olvas(7,6,20))<>'' Then
{Javˇt}
Begin
AdatKeprol;Seek(FNev,AS);Write(Fnev,ARec)
End;
#19:If
Kerdezo(5,15,' Valóban törölni
akarja az aktuális
rekordot? ')
Then
If RS>0 Then {Töröl}
Begin
If RS=1 Then
ReWrite(FNev)
Else
If AS=RS Then Inc(RS)
Else
If AS=RS-1 Then
Truncate(FNev)
Else
If AS<RS-1 Then
Begin
For I:=AS+1 To RS-1 Do
Begin
Seek(FNev,I);Read(FNev,PRec);
Seek(FNev,I-1);Write(FNev,PRec);
End;
Seek(FNev,RS-1);Truncate(FNev);
If AS=RS then Dec(AS);
Seek(FNev,AS);Read(FNev,ARec);
AdatKepre;Seek(FNev,AS);
End;
Dec(RS);If RS=0 Then AdatTorles;
End;
#47,
#45: Begin
Close(FNev);Szinek(0,7);ClrScr;halt End;
End;
Tunj;
Until
False;
End.