Podstawy Programowania Wyk ad dwunasty: ł Modu crt i

Transkrypt

Podstawy Programowania Wyk ad dwunasty: ł Modu crt i
Podstawy Programowania
Wykład dwunasty:
Moduł crt i komunikacja z użytkownikiem
1. Obsługa klawiatur i ekranu w trybie tekstowym
Do interaktywnej pracy z komputerem służy jego użytkownikowi klawiatura
i monitor. Współczesne karty graficzne pozwalają wyświetlać informacje
w dwóch rodzajach trybów wyświetlania: graficznych, gdzie obraz jest złożony
z dużej ilości niewielkich punktów zwanych pikselami, oraz w tekstowych, gdzie
obraz jest podzielony na miejsca, które zajmuje dokładnie jeden znak. Moduł
crt zwiera procedur i funkcje, wraz z innymi elementami, które pozwalają na
„zarządzanie” zawartością ekranu w trybach tekstowych. Ponadto część z nich
związana jest z obsługą klawiatury i głośnika, jaki został wbudowany
w komputery PC (PC Speaker).
2. Tryby tekstowe
Do zmiany trybu tekstowego służy procedura textmode. Przyjmuje ona jeden
parametr wywołania, który jest wartością, wyrażeniem lub zmienną typu
integer. Najczęściej parametrem tym jest jedna z predefiniowanych w module
crt stałych, określających rodzaj trybu. Jeśli procedura textmode zostanie
wywołana ze stałą BW40, to ekran zostanie przełączony w czarno-biały tryb
tekstowy, o wymiarach: 40 kolumn i 25 wierszy (można na nim równocześnie
wyświetlić maksymalnie 1000 znaków)1. W przypadku wywołania opisywanej
procedury ze stałą CO40 wymiary pozostają bez zmian, ale można używać 16
kolorów. Przełączenie do trybów, w których ekran ma 80 kolumn i 25 wierszy
uzyskuje się za pomocą stałych BW80 i CO80. W przypadku pierwszej stałej
jest to tryb czarno-biały, a w przypadku drugiej kolorowy. Tryb o maksymalnej
2
rozdzielczości , 80 kolumn i 50 wierszy dla kart graficznych zgodnych ze
standardem EGA, możemy włączyć za pomocą stałej Font8x8. Istnieją jeszcze
trzy stałe, które mogą być parametrami wywołania textmode: Mono – która
włącza specyficzny tryb tekstowy nieużywanej już dziś karty oraz C40 i C80,
które są tożsame ze stałymi CO40 i CO80. Oczywiście stałe te posiadają
odpowiednie wartości: BW40 = 0, CO40=1, BW80=2, CO80=3, Mono=7,
Font8x8=256, C40=CO40, C80=CO80. W module crt zadeklarowana jest również
zmienna typu word o nazwie LastMode, która zapamiętuje numer trybu przed
jego zmianą. Aby przywrócić poprzedni tryb wyświetlania znaków wystarczy
więc wywołać textmode ze zamienną LastMode, jako parametrem wywołania.
1 Tak, jak i inne identyfikatory w Pascalu, nazwy tych stałych mogą być pisane zarówno dużymi,
jak i małymi literami.
2 W tym kontekście słowo to oznacza liczbę wyświetlanych równocześnie znaków na ekranie.
2
3. Kolory w trybach tekstowych
W kolorowych trybach tekstowych można używać maksymalnie 16 kolorów.
Możliwe jest określenie zarówno koloru znaku, za pomocą procedury textcolor,
jak i koloru tła, na którym znak jest wyświetlany. To ostatnie realizujemy przy
pomocy procedury textbackground. Obie procedury przyjmują jako parametr
wywołania zmienną, wyrażenie lub wartość typu byte, ale akceptowalne są
w przypadku textcolor tylko wartości od 0 do 15, a w przypadku textbackgroud
tylko wartości od 0 do 7. Możemy je podawać bezpośrednio lub użyć stałych
określających kolor, które również zostały zdefiniowane w module crt. Jest ich
piętnaście: Black=0 określa kolor czarny, Blue=1, określa kolor niebieski,
Green=2 określa kolor zielony, Cyan=3 określa kolor turkusowy, Red=4, określa
kolor czerwony, Magenta=5 określa kolor karmazynowy, Brown=6, określa
kolor brązowy, LightGray=7, określa kolor jasnoszary, DarkGray=8 określa
kolor ciemnoszary, LightBlue=9 określa kolor jasnoniebieski, LightGreen=10
określa kolor jasnozielony, LightCyan=11 określa kolor jasno turkusowy,
LightRed=12 określa kolor jasnoczerwony, LightMagenta=13 określa kolor jasno
karmazynowy, Yellow=14 określa kolor żółty, White=15, określa kolor biały.
Istnieje jeszcze stała Blink=128. Dodanie jej do stałej określającej kolor
powoduje, że znak o tym kolorze będzie migał na ekranie. Jeśli chcemy
zmniejszyć lub zwiększyć jasność znaków na ekranie możemy użyć
odpowiednio procedury LowVideo lub HighVideo. Obie te procedury są
bezparametrowe. Aby przywrócić „stare” ustawienia jasności znaków możemy
użyć również bezparametrowej procedury NormVideo. W module crt jest również
zadeklarowana zmienna typu byte o nazwie TextAttr, która pozwala na
„bezpośrednie” określenie atrybutów (koloru, koloru tła, migania) znaku, przy
czym najstarszy bit tej zmiennej odpowiada za migotanie (0 – nie miga, 1 –
miga), trzy następne za kolor tła, a cztery ostatnie za kolor znaku.
4. Wiersze
W module crt istnieją procedur pozwalające „manipulować” wierszami znaków,
które są wyświetlane na ekranie. Wszystkie te procedury nie wymagają żadnych
parametrów wywołania. Procedura clreol usuwa z ekranu wszystkie znaki
począwszy od bieżącej pozycji kursora, aż do końca wiersza. Procedura insline
wstawia wiersz wypełniony pustymi znakami za wierszem w którym jest kursor.
Procedura delline usuwa znaki z wiersza ekranu w którym jest kursor.
3
5. Okna
Moduł crt, umożliwia określenie na ekranie okien3, w obrębie których będą
wyświetlane znaki, jak również pozwala na określanie pozycji kursora w obrębie
tych okien. Do utworzenia na ekranie okna służy procedura window. Pobiera
ona cztery parametry wywołania. Pierwsza para tych parametrów określa
odpowiednio współrzędną poziomą i pionową lewego górnego rogu okna,
natomiast następna para określa odpowiednio współrzędną poziomą i pionową
prawego dolnego rogu okna. Parametry te mogą być wartościami, wyrażeniami
lub zmiennymi typu byte. Ich wartości nie powinny jednak przekraczać
maksymalnych wartości kolumny i wiersza, określonych dla danego trybu
tekstowego (współrzędna pozioma odpowiada za kolumny, pionowa za wiersze).
Współrzędne lewego górnego rogu bieżącego okna są przechowywane
w zmiennej WindMin typu word, a współrzędne prawego dolnego rogu są
przechowywane w zmiennej WindMax, też typu word. Starszy bajt tych
zmiennych zawiera wartość współrzędnej poziomej, młodszy współrzędnej
pionowej. Położenie kursora na ekranie możemy zmienić za pomocą procedury
gotoxy, która pobiera dwa parametry wywołania. Oba mogą być wartościami,
zmiennymi lub wyrażeniami typu byte, ale podobnie, jak ma to miejsce
w przypadku procedury window ich wartości nie powinny przekraczać
maksymalnego numeru wiersza i kolumny dla danego trybu tekstowego.
Pierwszy parametr określa współrzędną poziomą miejsca, w którym chcemy
umieścić kursor (kolumnę), druga określa współrzędną poziomą tego miejsca
(wiersz). Współrzędne te są liczone zawsze względem bieżącego okna, czyli jeśli
wywołanie tej procedury ma postać gotoxy(1,1), to położenie kursora będzie się
zależało od tego, czy wywołaliśmy wcześniej procedurę window i z jakimi
parametrami. Bieżące położenie kursora na ekranie możemy określić za
pomocą funkcji wherex i wherey. Nie pobierają one żadnych parametrów
wywołania, ale zwracają wartości typu byte, które określają odpowiednio
składową poziomą i pionową bieżącego położenia kursora. Położenie to jest
oczywiście liczone względem lewego górnego rogu bieżącego okna.
6. Obsługa klawiatury
W module crt zdefiniowane są dwie funkcje, które pozwalają na obsługę
klawiatury. Zanim przejdziemy do ich omówienia musimy dowiedzieć się, że
w pamięci komputera wyróżniony jest niewielki fragment, zwany buforem
klawiatury. Do tego fragmentu pamięci trafiają między innymi kody ASCII
znaków związanych z naciśniętymi klawiszami. Opisywane funkcje działają
3 Po przez termin okno rozumiemy w tym kontekście wydzielony obszar ekranu, a nie obiekt
znany między innymi z systemów operacyjnych Windows firmy Microsoft.
4
więc na zwartości tego bufora, a nie bezpośrednio na klawiaturze. Funkcja
KeyPressed nie pobiera żadnych parametrów wywołania, a zwraca wartość true
4
jeśli w buforze klawiatury znajduje się znak do odczytania . Funkcja readkey
również jest bezparametrowa, ale zwraca wartość typu char. Jest to znak
odpowiadający klawiszowi, który został naciśnięty. Warto przy okazji
omawiania tej funkcji napisać o pewnym problemie z nią związanym, który
dosyć często jest spotykany. Otóż funkcji tej można użyć do wstrzymania
wykonywania programu do czasu naciśnięcia przez użytkownika dowolnego
klawisza. Niestety nie zawsze ten sposób działa zgodnie z założeniami. Niektóre
klawisze zwracają do bufora dwa kody ASCII. Do tych klawiszy należą klawisze
kursorów i klawisze funkcyjne (od F1 do F12). Rozważmy następujący program:
uses crt;
begin
clrscr;
writeln('Pierwszy napis');
readkey;
writeln('Drugi napis');
readkey;
writeln('Trzeci napis');
readkey;
end.
Jeśli po ukazaniu się na ekranie pierwszego napisu naciśniemy dowolny
z klawiszy kursorów, to na ekranie pojawi się drugi i trzeci napis, a program
zatrzyma się dopiero na ostatnim readkey. „Tajemnica” tego zachowania jest
taka, że opisywana funkcja, w wyniku swego wywołania zwraca tylko jeden
znak, a klawisz kursora zapisuje do bufora klawiatury dwa znaku. Pierwsze
wywołanie readkey odczyta pierwszy z nich, a drugie nie będzie czekało na
naciśnięcie klawisza przez użytkownika, bo drugi znak już będzie gotów do
odczytania w buforze klawiatury. Rozwiązanie tego problemu polega na
umieszczeniu przed każdym wywołaniem readkey krótkiej pętli, która
czyściłaby bufor klawiatury:
while keypressed do readkey;
readkey;
Pętlę while możemy odczytać następująco: „dopóki jest w buforze klawiatur
jakiś znak, to go odczytaj”. Ta pętla gwarantuje nam, że następujące po niej
4 Według pomocy w środowisku Turbo Pascala, funkcja ta zwraca wartość true jeśli został
naciśnięty klawisz. Nie do końca odpowiada to prawdzie.
5
wywołanie readkey będzie musiało poczekać, aż użytkownik naciśnie jakiś
klawisz i zapisze tym samym przynajmniej jeden znak do bufora klawiatury.
Innymi słowy przed wywołaniem readkey bufor klawiatury będzie oczyszczony.
7. Inne procedury z modułu „crt”
Jeśli chcemy wstrzymać wykonanie pewnej grupy instrukcji programu na
określoną ilość czasu, to możemy posłużyć się procedurą delay. Jej wywołanie
musimy umieścić przed tą grupą instrukcji. Jako parametr wywołania ta
procedura przyjmuje wartość, zmienną lub wyrażenie typu word. Jeśli ta
wartość wynosi 1, to procedura wstrzyma wykonanie programu na jedną
milisekundę [ms]. Ponieważ maksymalną wartością dla typu word jest 65535,
to za pomocą jednokrotnego wywołania tej procedury możemy opóźnić program
na nieco dłużej niż jedną minutę i pięć i pół sekundy. Do sterowania
wbudowanym w komputer głośnikiem (PC Speaker) służy procedura sound.
Jako parametr wywołania może przyjąć zmienną, wartość lub wyrażenie typu
word. Określa ono częstotliwość dźwięku, jaki będzie emitowany przez głośnik.
Teoretycznie możliwe jest osiągnięcie dźwięków leżących poza zakresem
słyszalności człowieka (od 20 Hz do 20 kHz), ale ze względu na jakość głośnika
(a raczej jej brak) jest to mało prawdopodobne. Dźwięk wyłączamy wywołując
5
procedurę nosound . Jest to procedura bez parametrów. Opisane tu procedury
kończą listę procedur i funkcji modułu crt, z którymi się zapoznamy. Inne
elementy tego modułu nie będą tu już opisywane.
8. Przykłady
program okna_w_trybie_tekstowym;
uses
crt;
procedure okno(x1,y1,x2,y2:byte);
var
i:byte;
begin
window(x1,y1,x2,y2);
gotoxy(1,1);
5 Pisząc programy wykorzystujące dźwięk najlepiej mieć „w odwodzie” krótki program, składający
się tylko z wywołania nosound. Uruchomienie go, kiedy zawiesi się pisany przez nas program,
może zaoszczędzić irytacji osobom znajdującym się w naszym otoczeniu :-)
6
for i:=1 to 10 do
writeln('Napis w oknie');
delay(1000);
gotoxy(5,2);
clreol;
delay(1000);
gotoxy(1,3);
delline;
delay(1000);
gotoxy(1,4);
insline;
delay(1000);
end;
procedure wyswietl(zx,zy:byte);
var
x,y:byte;
begin
x:=random(zx-20);
y:=random(zy-20);
okno(x,y,x+20,y+20);
end;
begin
clrscr;
randomize;
textmode(font8x8);
wyswietl(80,50);
textmode(co80);
wyswietl(80,25);
textmode(co40);
wyswietl(40,25);
readln;
end.
7
Pierwszy przykładowy program wyświetla w losowo umieszczonym na ekranie
oknie dziesięć wierszy o treści „Napis w oknie”, po jednosekundowej przerwie
usuwa część znaków z piątego wiersza, po kolejnej sekundzie usuwa trzeci
wiersz i po upływie takiego samego odcinka czasu wstawia nowy wiersz
w miejscu, gdzie był czwarty wiersz, a następnie czeka jedną sekundę. Ta
czynność jest powtarzana dla trzech trybów graficznych. Procedura okno
wyświetla okno o współrzędnych przekazanych jej przez parametry, umieszcza
kursor w lewym górnym rogu tego okna i wypisuje dziesięć wierszy o podanej
wcześniej treści. Kolejne czynności wykonywane są z jednosekundowym
opóźnieniem między wykonaniem każdej z nich. Polegają one na usunięciu
części znaków z wiersza, usunięciu całego wiersza i wstawieniu nowego. Przed
powrotem z procedury komputer również czeka jedną sekundę. Procedura
wyswietl losuje współrzędne lewego górnego rogu okna, które są przekazywane
do procedury okno. Utworzone okno ma wymiary 20x20. Wymiary okna są
uwzględniane w parametrze wywołania funkcji random, tak aby wylosowane
współrzędne nie spowodowały wyświetlenie całości lub części okna poza
ekranem. W programie głównym procedura wyswietl jest wywoływana po
każdym przełączeniu ekranu w inny tryb tekstowy, z odpowiednimi dla danego
trybu parametrami wywołania, które określają liczbę wierszy i kolumn
w danym trybie.
program textdemo;
uses
crt;
var
a:word;
procedure demo(x1,y1,x2,y2:byte; migaj:boolean);
var
i:byte;
a:word;
begin
gotoxy(x1,y1);
window(x1,y1,x2,y2);
for i:=black to white do
begin
8
if i=0 then textbackground(white)
else textbackground(black);
if migaj then textcolor(i+blink) else textcolor(i);
write('tekst');
end;
while keypressed do readkey;
repeat until keypressed;
gotoxy(1,1);
for i:=black to lightgray do
begin
textbackground(i);
write('tekst');
delay(500);
end;
sound(1000);
delay(500);
nosound;
end;
begin
clrscr;
textmode(co40);
demo(20,5,24,21,false);
while keypressed do readkey;
readkey;
textmode(co80);
demo(40,5,44,21,false);
while keypressed do readkey;
readkey;
textmode(co40);
demo(20,5,24,21,true);
while keypressed do readkey;
readkey;
textmode(co80);
demo(40,5,44,21,true);
9
while keypressed do readkey;
readkey;
textmode(lastmode);
normvideo;
end.
Procedura demo przyjmuje pięć parametrów. Są to współrzędne okna oraz
znacznik określający, czy wypisywany tekst ma migać (true), czy nie. Pierwszą
czynnością jaką wykonuje procedura jest umieszczenie kursora w punkcie
6
o podanych współrzędnych i utworzenie okna o określonych wymiarach .
W oknie tym wypisywany jest wyraz „tekst” w kolejnych wierszach, za każdym
7
razem w innym kolorze . W zależności od parametru migaj do koloru dodawany
jest atrybut migania lub nie. Po wykonaniu tej czynności program oczekuje na
naciśnięcie przez użytkownika klawisza w pętli repeat until keypressed; co
można odczytać jako „nie rób nic tak długo aż użytkownik naciśnie jakiś
klawisz”. Przed wykonaniem tej pętli wykonywana jest pętla while keypressed
do readkey; aby oczyścić bufor klawiatury. Po naciśnięciu przez użytkownika
dowolnego klawisza kursor wraca do lewego górnego rogu okna i napis „tekst”
jest ponownie w nim umieszczany, tym razem jednak zmienia się kolor jego tła.
Po wykonaniu tej czynności program generuje dźwięk o częstotliwości 1 kHz
i trwający pół sekundy. W bloku programu głównego procedura demo jest
wywoływana cztery razy, dwukrotnie dla trybu CO80 i dwukrotnie dla trybu
CO40. Za drugim razem wyraz „tekst” po wypisaniu migocze. Między kolejnymi
wywołaniami tej procedury wykonanie programy jest zatrzymywane przy
pomocy funkcji readkey, do czasu naciśnięcia przez użytkownika dowolnego
klawisza. Przed wywołaniem tej funkcji wykonywana jest pętla czyszcząca
zawartość bufora klawiatury. Po wykonaniu opisanych czynności przywracany
jest poprzedni tryb tekstowy i wywoływana jest procedura normvideo.
program kursor;
uses crt;
procedure ruch;
var a:char;
begin
repeat
a:=readkey;
if a = #0 then
6 Wynikających z przekazanych do procedury współrzędnych.
7 Pierwszy wyraz jest wypisywany czarnymi znakami, więc został umieszczony na białym tle.
10
begin
a:=readkey;
if a=#60 then clrscr;
if a=#59 then write('x: ',wherex, ', y: ',wherey);
if a=#72 then gotoxy(wherex, (wherey - 1) mod (hi(windmax)+2));
if a=#75 then gotoxy((wherex-1) mod (lo(windmax)+2), wherey);
if a=#77 then gotoxy((wherex+1) mod (lo(windmax)+2), wherey);
if a=#80 then gotoxy(wherex,(wherey + 1) mod (hi(windmax)+2));
end;
until a=#27;
end;
begin
clrscr;
while keypressed do readkey;
ruch;
end.
Zanim rozpoczniemy opisywanie tego programu powinniśmy sobie
przypomnieć, że klawisze kursorów i klawisze funkcyjne zwracają dwa znaki.
Pierwszy znak, to jest znak o kodzie ASCII zero. Drugi znak jest unikalny dla
każdego z tych klawiszy. Dla klawisza F1 jest to znak o kodzie ASCII równym
59, dla F2 60, dla klawisza kursora „góra” 72, „dół” 80, „lewo” 75, „prawo” 77.
Powyższy program służy do poruszania się kursorem w obrębie ekranu za
pomocą klawiszy kursora. Najważniejsza część kodu znajduje się w procedurze
ruch. W pętli repeat, która jest kończona w momencie naciśnięcia przez
użytkownika klawisza Escape (kod ASCII 27), odczytywany jest jeden znak z
bufora klawiatury. Jeśli ten znak ma wartość zero, to odczytywany jest kolejny
znak. Jeśli ten znak odpowiada klawiszowi F1, to ekran jest czyszczony przy
pomocy procedury clrscr. Jeśli odpowiada klawiszowi F2, to wypisywana jest
bieżąca pozycja kursora. Jeśli został naciśnięty któryś z klawiszy kursora, to
kursor na ekranie jest przesuwany o jedną pozycję w górę, dół, lewo lub prawo.
Dzieje się to za pomocą procedury gotoxy. Nowe współrzędne kursora są
określane za pomocą funkcji wherex i wherey i operacji dodawania lub
odejmowania. Proszę zauważyć, że te operacje są wykonywane modulo liczba
kolumn lub liczba wierszy na ekranie plus dwa.
11
9. Parametry wywołania programu
W systemach operacyjnych takich jak Unix, Windows lub DOS istnieje
możliwość przekazania programowi tzw. parametrów wywołania, czyli
parametrów umieszczonych w wierszu poleceń. Przykładowo w systemie DOS
lub po uruchomieniu programu cmd w systemie Windows XP możemy wywołać
program dir z parametrem /w pisząc po prostu „dir /w”. Ciąg znaków
znajdujący się za nazwą programu traktowany jest jako jego parametr
wywołania. Takich parametrów możemy przekazać programowi więcej,
rozdzielając je znakami spacji lub tabulacji. W środowisku Turbo Pascala
parametry wywołania programu możemy określić za pomocą opcji
Run->Parameters. Aby odczytać w programie parametry jego wywołania
musimy posłużyć się dwiema funkcjami. Funkcja paramcount zwraca wartość
typu word określającą ile parametrów zostało przekazanych programowi
w wierszu wywołania. Ta funkcja nie przyjmuje żadnego parametru. Drugą
funkcją jest paramstr, która przyjmuje jeden parametr typu word. Tym
parametrem jest indeks parametru wywołania programu. Funkcja zwraca
wartość typu string, która jest wartością tego parametru. Jeśli wywołując tę
funkcję przekażemy jej zero, to zwróci ona nazwę programu. Oto krótki,
przykładowy program ilustrujący użycie tych funkcji:
program parametry_wywolania;
uses
crt;
procedure wypisz;
var
i:word;
begin
writeln('Program o nazwie: ',paramstr(0));
writeln('został wywołany z następującymi parametrami: ');
for i:=1 to paramcount do
write(paramstr(i),' ');
readln;
end;
begin
12
clrscr;
wypisz;
readln;
end.
10. Numerowanie wierszy i kolumn w trybach tekstowych
Wiersze i kolumny w trybach tekstowych są numerowane od jedynki. Kolumny
są numerowane z lewa na prawo, tj. skrajnie lewa kolumna ma numer 1,
skrajnie prawa numer maksymalny dla danego trybu, np. 80. Wiersze są
numerowane od góry do dołu, tj. najwyższy wiersz ma numer 1, najniższy ma
numer maksymalny dla danego trybu, np. 25. Sposób numerowania wierszy
i kolumn pokazuje również poniższa ilustracja.
1
80
1
ekran w trybie co80
25
13

Podobne dokumenty