Hangok

 

Előfordulhat, hogy egy adott tevékenységre hanggal is fel szeretnénk hívni a géphasználó figyelmét, főleg akkor, ha a felhasználónak be kellene avatkozni a program további menetébe. Ilyen lehet egy menüből való választás, vagy egy input lekezelése. Erre az esetre írjunk egy Duda nevű eljárást és tegyük azt a CrtPlus unitba:

 

Procedure Duda;

Begin

  Sound(1000);

  Delay(200);

  Nosound;

End;

 

Ha valaki dallamosabb hangot szeretne hallani, akkor azt egyéni ízlés szerint kialakíthatja. Ehhez a CrtPlus unitba elhelyezhetjük a zenei hangok frekvenciáit:

 

Const

  Hq=   1.059463;

  Ha=   440;

  Hc=   Round(Ha/Hq/Hq/Hq/Hq/Hq/Hq/Hq/Hq/Hq);

  Hcisz=Round(Hc*Hq);

  Hd=   Round(Hcisz*Hq);

  Hdisz=Round(Hd*Hq);

  He=   Round(Hdisz*Hq);

  Hf=   Round(He*Hq);

  Hfisz=Round(Hf*Hq);

  Hg=   Round(Hfisz*Hq); 

  Hgisz=Round(Ha/Hq);

  Hbe=  Round(Ha*Hq);

  Hh=   Round(Ha*Hq*Hq);

 

Ezek a frekvenciák kiszámolva:

 

Hc=   261;

Hcisz=232;

Hd=   294;

Hdisz=311;

He=   329;

Hf=   349;

Hfisz=370;

Hg=   392;

Hgisz=415;

Ha=   440;

Hbe=  466;

Hh=   494;

 

Szöveges képernyőmódok

 

 

35. Írjunk programot, amely bemutatja, hogy milyen szöveges képernyőmódokat tud kezelni a Turbo Pascal.

 

Program SzovKep;

Uses NewDelay, Crt, CrtPlus;

Var Eredeti: Byte;

Begin

  Eredeti:= LastMode;

  TextAttr:= 15;

  ClrScr;

  TextMode(0);

  Write(’BW40=0: fekete-fehér 40*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(1);

  Write(’CO40=1: színes 40*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(2);

  Write(’BW80=2: fekete-fehér 80*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(3);

  Write(’CO80=3: színes 80*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(7);

  Write(’MONO=7: fekete-fehér 80*25, monokróm adapteren’);

  Tunj;

  Varj;

  TextMode(3+256);

  Write(’3+Font8x8=259: színes 80*43 ill. 80*50, EGA/VGA adapteren’);

  Tunj;

  Varj;

  TextMode(eredeti);

End.

 

A megjelenítési módokat a TextMode paraméteres eljárással állíthatjuk be. A LastMode változó a legutoljára beállított üzemmódot tartalmazza.

 

 

36. Írjunk bemutató programot a képernyő megjelenítés különböző eljárásaira, írassuk ki és értelmezzük a WindMin és WindMax változók értékét. Mutassuk be az InsLine és DelLine eljárások működését.

 

 

A képernyőn való szövegmegjelenést a LowVideo, HighVideo, NormVideo eljárásokkal szabályozhatjuk. Hatásukat jól szemlélteti a következő rövid program. A LowVideo alacsony intenzitásúra, a HighVideo magas intenzitásúra állítja a karakter színeit. NormVideo a program indításakor detektált attributumokat tartalmazza.

 

Program Kepernyo;

Uses NewDelay, Crt, Crtplus;

Var I: Byte;

Begin

  TextMode(CO80);

  Szinek(1,5);

  Clrscr;

  Write(’Funkció....’);

  HighVideo;

  Write(’F1’);

  Tunj;

  Varj;

  WriteXY(1,5,’N’);

  LowVideo;

  Write(em’);

  Tunj;

  Varj;

  Normvideo;

  WriteXY(1,10,’Vége is lehetne, de nincs ...’);

  Tunj;

  Varj;

  GoToXY(1,15);

  Writeln(WindMin,’  ’,WindMax);

  Writeln(Lo(WindMin)+1,’  ’,Hi(WindMin)+1);

  WriteLn(Lo(WindMax)+1,’  ’,Hi(WindMax)+1);

  WriteXY(30,20,'*');

  Write(WhereX,’  ’,WhereY,’ Helyen volt a kurzor’);

  Tunj;

  Varj;

  GotoXY(1,1);

  For I:= 1 To 5 Do

  Begin

    Varj;

    DelLine;

  End;

  Varj;

  GoToXY(1,10);

  For i:= 1 to 5 do

  Begin

    Varj;

    InsLine;

  End;

  Tunj;

  Varj;

End.

 

A programot futtatva a WindMin és WindMax értékét és a belőlük származó ablakkoordinátákat kaphatjuk meg. A WhereX és WhereY segítségével a kurzor pozícióját kérdezhetjük le. Az InsLine és DelLine működését a két For ciklus szemlélteti.

 

 

A DOS unit

 

 

37.  Írjunk programot, amely kilistázza az aktuális könyvtár tartalmát, majd kiírja a a lemez szabad kapacitását.

 

A lemezkezelő eljárások többségét a DOS unit tartalmazza, ezért ezt használatba kell venni. A Katalogus az aktuális könyvtárnak a neve. A ChDir könyvtárcserét végez, a DOS parancsoknak megfelelően. A FindFirst az  első, a FindNext a további bejegyzéseket keresi az aktuális könyvtárban. A bejegyzések Record típusúak, és a Bejegyzes-ben  tároljuk őket. A DosError a lemezműveleteknél fellépő futás idejű hibákat tartalmazza. 0 esetén nincs hiba. A Bejegyzes Record Name mezőjében a név, az Attr mezőjében az attributum található. A DiskFree függvény visszaadott értéke a lemez szabad kapacitása. A típusa miatt csak 2Gb-ig mutat helyes értéket.

 

Program Director;

Uses NewDelay, Crt, CrtPlus, Dos;

Var Bejegyzes: SearchRec;

    Katalogus: String;

    Meret, Szabad: longint;

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  ChDir('..');

  GetDir(0,Katalogus);

  If Katalogus[Length(Katalogus)]<>'\' then Katalogus:= Katalogus+'\';

  Katalogus:= Katalogus+'*.*';

  WriteLn(Katalogus,' könyvtár tartalma:');

  FindFirst(Katalogus, AnyFile, Bejegyzes);

  If DosError<>0 Then WriteLn('Hiba') Else

  While DosError=0 Do

  Begin

    Write(Bejegyzes.Name);

    If Bejegyzes.Attr And Directory=Directory Then

    WriteXY(14,WhereY,'<DIR>');

    WriteLn;

    FindNext(Bejegyzes);

  End;

  WriteLn;

  Szabad:= DiskFree(Ord(Katalogus[1])-Ord('A')+1);

  Szabad:= DiskSize(Ord(Katalogus[1])-Ord('A')+1);

  WriteLn(Meret,' Byte-ból ');

  WriteLn(Szabad,' Byte szabad');

  Tunj;

  Varj;

End.

 

 

Gyakran igény van arra, hogy egy program futása közben, valamely lemez illetve könyvtár tartalmát megnézzük. Például azért, hogy az ott lévő file-okból válogassunk. Egy könyvtár tartalmának elolvasásához a DOS standard Unit használata szükséges. A következő feladatunk e témában az lesz, hogy egy általános file-keresőt írjunk, amelyet a CrtPlus-ban szeretnénk elhelyezni. Ehhez először a lista elején lévő Uses sor bővítendő:

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt, Dos;

. . .

 

38. Írjunk olyan függvényt, amely egy általunk megadott meghajtó aktuális könyvtárának a tartalmát úgy listázza ki, hogy csak a megadott kiterjesztéssel rendelkező file-okat jeleníti meg.

 

A feladat értelmében a függvény paraméterei a következők:

HSz: Háttérszin;

KSz: Karakterszin;

VSz: Választószin;

Dr: a lemezes egység száma (0: aktuális, 1: A:\; 2:B:\; 3: C:\; 4: D:\; …);

Ext: a keresési maszkhoz a file kiterjesztése.

A függvényt a CrtPlus-ban helyezzük el.

 

Function FileKereso(HSz,KSz,DSz,Dr: Byte; Ext: String): String;

Var I, V, Sh: Integer;

    Bejegyzes: SearchRec;

    Katalogus: String;

Begin

  For I:= 0 To max do Tomb[I]:= '';

  GetDir(Dr,Katalogus);

  If Katalogus[Length(Katalogus)]<>'\' Then Katalogus:= Katalogus+'\';

  Katalogus:= Katalogus+'*.'+Ext;

  FindFirst(Katalogus,AnyFile,Bejegyzes);

  If DosError<>0 Then Begin FileKereso:=''; Exit End;

  I:= 1;

  While DosError=0 Do

  Begin

    Tomb[I]:= ' '+Bejegyzes.Name;

    FindNext(Bejegyzes);

    Inc(I);

  End;

  Dec(I);

  Sh:= Length(Katalogus)+5;

  If Sh<17 Then Sh:=17;

  V:= Listazo(HSz,KSz,VSz,Round(40-Sh/2),6,Sh,I,11,1,True, Katalogus);

  FileKereso:= ValidSt(Tomb[V]);

End;

 

A GetDir (System Unit) eljárás a Katalogus stringbe tölti a Dr által meghatározott lemezes egység aktuális könyvtárának a nevét. Ha nem a gyökérkönyvtárban vagyunk, akkor a '\' jel hiányozni fog a bejárási út végéről, ezért a vizsgálat és a hozzáfűzés. A '*.'+ext -el adjuk meg a kiterjesztést. A FindFirst (Dos Unit) eljárás, a Katalogus-ban megadott könyvtárban keresi, az AnyFile attributumu első file-t, és ha megtalálja a Bejegyzes-ben helyezi el. Az első DosError vizsgálat eredményes volta akkor következik be, ha a kapott elérési út érvénytelen, vagy hiányzik a megfelelő lemezes egység, vagy üzemképtelen. A FindNext (Dos Unit) eljárás az előző eljárásban már megkezdett katalógus bejegyzéseit tovább olvassa. Hiba esetén az olvasás befejeződik (mert nincs több bejegyzés). A Bejegyzéseket a Tomb-ben helyezzük el. A Listazo függvénnyel a katalógust megnézhetjük, sőt még választhatunk is belőle. A SearchRec tipus és az AnyFile konstans a Dos Unitban vannak deklarálva. További, az állományok állapotát leíró konstansok: ReadOnly, Hidden, SysFile, VolumeID, Directory és Archive. A megírt függvényt a következő kis program teszteli:

 

Program DirProba;

Uses NewDelay, Crt, CrtPlus;

Var FileNev: String;

Begin

  TextMode(CO80);

  Szinek(1,14);

  ClrScr;

  FileNev:= FileKereso(7,0,Green,0,'*');

  WriteXY(1,24,filenev);

  Tunj;

  Varj;

End.

 

 

39. Irjunk programot, amely a főkönyvtárban könyvtárakat (mappákat) hoz létre, és mindegyikben egy file-bejegyzést. A file most lehet üres is.

 

A program olyan egyszerű, hogy magyarázat nélkül is könnyen érthető. A könyvtárkészítő parancs teljesen megegyezik a DOS-beli megfelelőjével.

 

Program DirsMake;

Uses NewDelay, Crt, CrtPlus, Dos;

Var Ch: Char;

Procedure DirMake(D: String);

Var FNev: Text;

    DNev: String;

Begin

  ChDir('\');

  DNev:= 'user.dat';

  MkDir(D);

  ChDir(D);

  Assign(FNev,DNev);

    ReWrite(FNev);

  Close(FNev);

End;

Begin

  For Ch:='a' To 'f' Do DirMake(Ch);

End.

 

40. Írjunk programot, amely egy megadott könyvtár alatti összes könyvtár tartalmát kilistáz, és közben egy adott nevű file-t minden könyvtárból töröl (természetesen csak onnan, ahol volt).

 

 

Program DirList;

Uses NewDelay, Crt, Dos;

Var Katalogus: DirStr;

    Bejegyzes: SearchRec;

    F: File;

    D, HD: String;

Procedure KatalogusLista(Katalogus: DirStr);

Var Bejegyzes: SearchRec;

Begin

  WriteLn(Katalogus);

  If WhereY>23 Then Begin ReadLn; ClrScr End;

  If Katalogus[Length(Katalogus)]='\'

  Then Delete(Katalogus,Length(Katalogus),1);

  FindFirst(Katalogus+'\*.*',AnyFile,Bejegyzes);

  While (DosError=0) And (Bejegyzes.Name[1]='.') Do FindNext(Bejegyzes);

  While DosError=0 Do

  Begin

    If (Bejegyzes.Attr And Directory)=Directory Then

    KatalogusLista(Katalogus+'\'+Bejegyzes.Name)

    Else WriteLn(Katalogus,'\',Bejegyzes.Name);

    If WhereY>23 Then Begin Readln; ClrScr End;

    FindNext(Bejegyzes);

    If Bejegyzes.Name=D Then

    Begin

      HD:= Katalogus+'\'+Bejegyzes.Name;

      Assign(F,HD);

      Erase(F);

    End;

  End;

End;

Begin

  TextMode(CO80);

  D:= 'USER.DAT';

  ClrScr;

  Write('Katalógusnév: ');

  ReadLn(Katalogus);

  FindFirst(Katalogus + '\*.*',AnyFile,Bejegyzes);

  If DosError=3 Then WriteLn('Nincs ilyen katalógus')

  Else KatalogusLista(Katalogus);

  ReadLn;

End.

 

A program az eddigiek alapján könnyen érthető, ezért elemzésétől eltekintünk. A KatalogusLista rekurzív hívással jut el a mélyebb könyvtárakba.

 

41. Írjunk programot, amely a lemez kapacitásával, DOS verzióval, a dátummal és az idővel kapcsolatos eljárásokat és függvények használatát mutatja be.

 

Program DosDemo;

Uses NewDelay, Crt, CrtPlus, Dos;

Const Honap: Array[1..12] Of String=

      ('Jan','Febr','Márc','Ápr','Máj','Jún',

       'Júl','Aug','Szept','Okt','Nov','Dec');

      Het: Array[0..6] Of String=

('Vasárnap','Hétfő','Kedd','Szerda','Csütörtök','Péntek','Szombat');

Var Ev, Ho, Nap, HetNap: Word;

    Ora, Perc, Mp, Mp100: Word;

    Ch: Char;

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  WriteXY(1,7,'d: új dátum, t: új idő');

  GoToXY(1,1);

  WriteLn('Az aktuális lemez kapacitása ',DiskSize(0)/1024/1024:8:2,' Mbyte.');

  WriteLn('Az aktuális lemezen ',DiskFree(0),' byte szabad.');

  WriteLn('Dos Vezió: ',Lo(DosVersion),'.',Hi(DosVersion));

  GetDate(Ev, Ho, Nap, HetNap);

  WriteLn('A mai nap: ',Ev,'. ',Honap[Ho],'. ',Nap,', ',Het[HetNap],'.');

  Repeat

    GetTime(Ora, Perc, Mp, Mp100);

    Write('A pontos idő: ',Ora,' óra ',Perc,' perc ',Mp,' másodperc.');

    Delay(1000);

    GoToXY(1,WhereY);

  Until KeyPressed;

  Ch:= ReadKey;

  Case Ch Of

    'd': Begin

           WriteXY(1, 9,'Új év : '); ReadLn(Ev);

           WriteXY(1,10,'Új hó : '); ReadLn(Ho);

           WriteXY(1,11,'Új nap: '); ReadLn(Nap);

           SetDate(Ev, Ho, Nap);

         End;

    't': Begin

           WriteXY(1, 9,'Új óra  : '); ReadLn(Ora);

           WriteXY(1,10,'Új perc : '); ReadLn(Perc);

           WriteXY(1,11,'Új mperc: '); ReadLn(Mp);

           SetTime(Ora, Perc, Mp, 0);

         End;

  End;

End.

 

 

42. Írjunk programot, amely a felhasználó által meghatározható, de az operációs rendszer által elfogadható évre vonatkozóan kártyanaptárt készít. Végül el lehessen dönteni, hogy a képernyőt kimenjük-e lemezre, vagy kinyomtatjuk nyomtatón, esetleg egyiket sem, csak egyszerűen kilépünk a programból.

 

Első lépésként a képernyőtervet kell elkészíteni. Egy hónapra vonatkozóan csak egyszer kellene kiirni a napok nevét, pontosabban a napok nevének az első kezdőbetűjét. Mivel a 12 hónapnevet egymás mellé, a hónapok napjait pedig egymás alá írva nem férnek el a képernyőn, ezért célszerű egy-egy téglalap alakú területet egy hónapra fenntartani. A hónapokat hetekre bontva a függőleges méret minimum 7 +1 a hónap nevének. A kérdéses téglalap tehát 8 karakter magas, amiből 3 fér egy oszlopba. A 12 hónapból tehát 4-et kell egy sorban elhelyezni. Mivel a képernyő 80 karakteres, egy hónapra 20 karakter széles terület jut. Elfér-e ezen egy hónap? Szerencsére pontosan elfér. Ha ugyanis alaposan megnézünk egy naptárat, akkor láthatjuk, hogy egy hónap maximum 6 hétre nyúlhat szét. Mert ha mondjuk, szombatra esik elseje egy 31 napos hónapban, akkor abban 5 szombat van, de még az ötödik mindig csak a hónap 29 napja, tehát 30-a vasárnap és 31-e hétfő, azaz valóban 6 hétre nyúlik szét. Mivel a napok sorszáma a hónapokon belül maximum két számjegyű, kihagyásokat is figyelembe véve 6*3, azaz 18 karakter széles hely kell neki, plusz a hét napnevének az első betűje plusz egy kihagyás, az összesen 6*3+2=20. Tehát éppen elfér a naptár a képernyőn. A többi magyarázatot a programlista tartalmazza.

 

Program OrokNap;

Uses NewDelay, Crt, Crtplus, Dos, Printer;

     {Mivel nyomtatni is szeretnénk, használnunk kell a Printer Unit-ot}

Const Honap: Array[1..12] Of String=

      ('Január','Február','Március','Április',

       'Május','Június','Július','Augusztus',

       'Szeptember','Október','November','December');

      Het: Array[0..6] Of String= ('V','H','K','S','C','P','S');

Var Ev,Ho,Nap,NapNev,Oldev,Oldho,Oldnap: Word;

    I,J,Hoszam,Napszam,Elsonap,Anap,Vv: Integer;

    Szoko: Boolean;

    Hh: Array[1..12] Of Byte;

    Ch: Char;

    ws: String;

    FNev: Text;

    DosNev: String;

Begin

  Hh[1]:=31;Hh[2]:=28;Hh[3]:=31;Hh[4]:=30;Hh[5]:=31;Hh[6]:=30;

  Hh[7]:=31;Hh[8]:=31;Hh[9]:=30;Hh[10]:=31;Hh[11]:=30;Hh[12]:=31;

  ClrScr;

  GetDate(Ev,Ho,Nap,NapNev);

  Oldev:= ev; Oldho:= ho; Oldnap:= nap;

  GoToXY(38,1); Write(Ev);

  WriteXY(24,2,'Akarsz-e évet változtatni (i/n)?');

  Repeat

    Ch:= ReadKey;

    Ch:= UpCase(ch);

  Until Ch In ['I','N'];

  If Ch='I' Then

  Begin

    WriteXY(31,3,'Kérem az évszámot: ');

    ReadLn(Ev);

    SetDate(Ev,Ho,Nap);

    GetDate(Ev,Ho,Nap,NapNev);

    SetDate(Oldev,Oldho,Oldnap);

    {Hogy minél kevesebb ideig éljen a program miatti új időpont}

  End;

  Szoko:= False;

  If (Ev Mod 4)=0 Then Szoko:= True;

  If (Ev Mod 100)=0 Then Szoko:= False;

  If (Ev Mod 400)=0 Then Szoko:= True;

  If Szoko Then Hh[2]:= 29;

  {Ez volt a szökőév megállapítás}

  Hoszam:=1; Napszam:= 0;

  While Hoszam<ho Do

  Begin

    Inc(Napszam,Hh[Hoszam]);

    Inc(Hoszam);

  End;

  Inc(Napszam,Nap);

  {Napszam= a kérdéses évben a mai nap sorszáma}

  Napszam:= Napszam Mod 7;

  {A maradékképzéssel hét lehetséges esetre vezetjük vissza az első nap napnevének a megállapítását:}

  Case Napszam Of

       0: Elsonap:= (NapNev+1) Mod 7;

       1: Elsonap:= NapNev;

    2..6: While Napszam>1 Do

          Begin

            Dec(Napszam);

            Dec(NapNev);

            If NapNev>6 Then NapNev:=6; {Mivel a NapNev Word típusú}

            Elsonap:= NapNev;

          end;

  End;

  {Elsonap= az év első napja erre a napra esett, 0=V, 1=H, 2=K ... 6=S}

  Anap:= Elsonap;

  {Az Anap-ban tároljuk azt, hogy az aktuális kiíráskor nap a hét melyik napja}

  Szinek(1,15);

  ClrScr;

  GoToXY(38,1);

  Write(ev);

  For I:= 1 To 12 Do WriteXY(((I-1) Mod 4)*20+7,((I-1) Div 4)*8+2,Honap[I]);

  For I:= 1 To 12 Do For J:= 0 To 6 Do

  WriteXY(((I-1) Mod 4)*20+1,((I-1) Div 4)*8+3+J,Het[J]);

  For I:= 1 To 12 Do

  Begin

    Vv:= 0;

    For J:= 1 To Hh[I] Do

    Begin

      GoToXY(((I-1) Mod 4)*20+3+Vv,((I-1) Div 4)*8+3+Anap);

      Inc(Anap);

      Anap:= Anap Mod 7;

      If Anap=0 Then Inc(Vv,3);

      Write(J:2);

    End;

  End;

  {A Vv változó szerepe az íráshelyek vízszintes széthúzása}

  GoToXY(1,1);

  Write('(F: File  P: Printer)');

  Tunj;

  Ch:= ReadKey;

  GoToXY(1,1);

  Write('                     ');

  {Ha file-ba mentjük a képernyőt az op-rendszerbeli neve legyen az évszám + .txt kiterjesztés:}

  If Ch='F' Then

  Begin

    Str(Ev,DosNev);

    DosNev:= DosNev+'.txt';

    Assign(FNev,DosNev);

      ReWrite(FNev);

      For I:= 1 To 25 Do

      Begin

        Ws:= '';

        For J:= 1 To 79 Do Ws:= Ws+Chr(BKep[I,J,1]);

        WriteLn(FNev,Ws);

      End;

    Close(FNev);

  End;

  {Ha kinyomtatjuk a képernyőt:}

  If Ch='P' Then

  Begin

    For I:= 1 To 25 Do

    Begin

      Ws:= '';

      For J:= 1 To 80 Do Ws:= Ws+Chr(BKep[I,J,1]);

      WriteLn(Lst,Ws);

      {Nyomtatóra tehát ugyanúgy írunk, mint szöveges file-ba}

    End;

  End;

End.