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.