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;

Begin

  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.