C dla każdego (cz. 3.)
Okno na szary świat
Wykorzystanie portu okna prezentuje listing 5.
Użyliśmy w nim następujących, nie opisanych wcześniej, funkcji:
void DisplayBeep(struct Screen *screen);
Zadaniem tej funkcji jest "obudzenie" użytkownika. Polega ono na mignięciu ekranem
(jednym lub wszystkimi). Jedyny argument to wskażnik na ekran, w wypadku gdy zostanie
tam umieszczone zero, "budzenie" odbędzie się na wszystkich ekranach (o ekranach
będzie za mieśiąc). Od WB 2.1 na dyskach systemowych jest obecny program, dodający
do standardowego "mignięcia" funkcji DisplayBeep() również efekty dżwiękowe.
Jeśli komuś znudzi się tytuł okna, to powienien skorzystać z usług funkcji
Intuition:
void SetWindowTitle(struct Window *window, UBYTE *windowTitle, UBYTE *screenTitle);
Funkcja ta ustawia oba tytuły związane z oknem. Pierwszym argumentem jest okno,
w którym mają być dokonane zmiany. Drugi to nowy tytuł okna, wyświetlany na
jego listwie tytułowej (odpowiednik tagu WA_Title), a trzeci jest tytułem,
ktory będzie wyświetlony na listwie ekranu w czasie, gdy okno będzie aktywne
(odbędzie tagu WA_ScreenTitle). Zamiast jednego lub obu napisów można podać
zero, wówczas tytuł zostanie wyczyszczony, możliwe jest również pozostawienie
tytułu bez zmian, należy wtedy podać zamiast napisu wartość -1 (zrzutowaną
xa typ "wskaźnik na znak", a więc "STRPTR" bądź "char*").
Do komunikacji z użytkownikiem istnieje kilka funkcji, zaczniemy od tej,
która właściwie jest już zapomniana:
BOOL DisplayAlert(unsigned long alertNumber, UBYTE *string, unsigned long height);
Funkcja ta produkuje komunikaty typu "Guru Meditation" (OS 1.3) lub też
"Software Error" dla systemów nowszych. Pierwszy argument to typ komunikatu -
jego istnienie wynika z zastosowania funkcji do obwieszczania klęsk
żywiołowych przez system, ale nie tym będziemy się zajmować. Z naszego
punktu widzenia to pole wpływa na kolor ramki (RECOVERY_ALERT -ramka bursztynowa,
DEADEND_ALERT - ramka czerwona). Kolejnu argument to napis - jest to ciekawa
kompilacyjka tekstu i kodów sterujących. W pierwszych bajtach są zapisane
współrzędne początku napisu - dwa bajty na współrzędną x i jeden bajt na współrzędną y,
następnie jest tam umieszczony sam napis, zakończony standardowo - znakiem
o kodzie '\0'. Jeżeli po tym znaku wystąpi znak o kodzie różnymu od zera, to
oznacza to, że dalej jest kolejny napis w takim samym formacie - w przeciwnym
wypadku więcej napisów nie ma. Wygląda to może zawile, ale nie jest trudne -
proponuje zajrzeć do przykładu.
Ostatni argument to wysokość ramki. Mówiąc szczerze, długo zastanawialiśmy się
czy pisać o tej funkcji. Jej podtawową wadą jest to że wyświetla obraz
zawsze w rozdzielczości NTSC lub PAL. Ci, którzy mają podłączone do Amigi
monitory VGA, zobaczą w takim wypadku... kaszę (a ponoć niektóre monitory mogą
się nawet uszkodzić!).
Jednym z atutów tej funkcji w OS 1.3 były jej niewielkie wymagania pamięciowe
- na wyświetlenie komunikatu potrzeba było sosłownie kilku kilobajtów.
Tymczasem od OS 2.0 wymaga ona raczej powyżej 50 KB RAM! Nie polecamy więc
jej używania, opisujemy ją tutaj trochę przez sentyment (mówiąc krótko:
Darek się uparł).
UWAGA: w wypadku użycia funkcji DisplayAlert() radzimy dbać o współrzędne,
ponieważ jeśli tekst wyjdzie poza ramkę, funkcja może uszkodzić coś w systemie.
Do takiego błedu często prowadzi nieostrożna zmiana współrzędnych. Uczulamy:
po znaku "\" umieszcza się liczbę w kodzie ÓSEMKOWYM, czyli 0..7 (w czasie
pisania tego przykładu przez własną głupote wpisałem \28, bo chciałem,
aby tekst był dwa razy niżej niż górna linia. Cóż, spotkało mnie Guru,
choć na mojej Amidze już tak się nie nazywa).
Przejdźmy teraz do kolejnej funkcji, służącej do komunikowania się
z użytkownikiem. Funkcja ta pojawiła się w systemie operacyjnym 2.0. Są
dwa sposoby jej przywołania:
Long EasyRequestArgs(struct Window *window, struct EasyStruct *easyStruct, ULONG *idcmpPtr, APTR
args);
Long EasyRequest(struct Window *window, struct EasyStruct *easyStruct, ULONG *idcmpPtr);
Zadaniem tej funkcji jest zapytanie użytkownika o zdanie, lub też przekonanie go do
wykonania jakiejś czynności - robi to ona przy użyciu "okna dialogowego", zwanego popularnie
requesterem. Funkcja przekazuje sterowanie do programu w chwili, gdy zostanie puszczony
gadżet, lub w chwili, gdy nastąpi wydarzenie wskazane przez program.
Struktura "EasyRequest" opisuje requester, można ją znaleźć w pliku
"intuition/intuition.h"
struct EasyStruct
{
ULONG es_StructSize;
ULONG es_Flags;
ULONG es_Title;
ULONG es_TextFormat;
ULONG es_GadgetFormat;
};
Pole "es_StructSize" jest przygotowane na wyrost, to znaczy twórcy nastawili się na
rozszerzenie tej struktury w przyszłości - należy tam podać rozmiar użytej struktury
"EasyRequest", czyli sizeof(struct EasyRequest). Kolejne pole też jest przygotowane
"na wyrost", to znaczy, że jeszcze nie jest ono wykorzystywane (OS 3.1), i na razie
należy tam trzymać zero.
W polu "es_Title" znajduje się napis, który ma być nazwą okna requestera.
Napis "es_TextFormat" to treść komunikatu, wyświetlana wewnątrz okna. Mogą
w niej wystąpić znaki formatujące, podobne jak w przypadku standardowej printf(),
właśnie dlatego funkcja EasyRequest ma zmienną liczbę argumentów - po prostu należy
gdzieś podać dane do formatowanego napisu (UWAGA: nie są obsługiwane liczby
zmiennoprzecinkowe, a aby wyświetlić liczbę całkowitą trzeba użyć "%ld", a nie "%d").
Napis ten może zawierać kilka linii, należy je oddzielić znakiem nowej linii "\n".
Napis jest formatowany od lewej krawędzi requestera.
Możliwe odpowiedzi należy umieścić w napisie "es_GadgetFormat", napisy do kolejnych
gadżetów oddziela się pionowymi kreskami "|".
Napis ten nie może być pusty, musi zawierać przynajmniej jedną odpowiedż.
Jednym z argumentow funkcji EasyRequest() jest wskaźnik na okno, z którym ma byc związany requester.
Podając adres okna, wybiera się ekran, na którym requesterem się ukaże. W wypadku podania
wartości NULL requesterem ukaże się na standardowym ekranie publicznym. Gdy pole "es_Title"
będzie równe NULL, nazwa okna requestera będzie taka sama, jak okna podanego w parametrze "window"
bądź "SystemRequest", gdy i ten parametr będzie równy NULL.
Argument "IDCMP_ptr" to wskaźnik na zmienną typu ULONG, w której przechowywane są flagi,
opisujące, jakie wydarzenie ma spowodować automatyczne zamknięcie requestera (bez klikania
na którąkolwiek z odpowiedzi).
Wynikiem funkcji jest liczba typu LONG. Jej wartość to numer wybranej odpowiedzi, które
są numerowane od lewej do prawej, przy czym ta znajdująca się najbardziej z prawej
ma zawsze numer 0 - jest to odpowiedź negatywna. Najlepiej to zobaczyć: 1, 2, ..., N-1, 0
(gdzie N jest liczbą możliwych odpowiedzi). Funkcja może zwrócić wartość równą -1, gdy
nastąpiło wydarzenie opisane w parametrze "IDCMPptr".
Warto wpomnieć, że gdy kilka urządzeń logicznych korzysta z jednej stacji (sprzętowo),
to włożenie lub wyjęcie dysku powoduje kilkakrotne wygenerowanie wiadomości IDCMP_DISKINSERTED /
REMOVED. Zapewne przekonali się o tym Ci z Was, którzy korzystają z "PC0:" bądź "DS0:" -
listing 5 każe wtedy kilkakrotnie oddać wyjęty dysk.
Na dziś wystarczy, za miesiąc nauczymy się otwierać ekrany samodzielnie.