PO RAZ OSTATNI... Proszë o minutë ciszy. Okazja do powspominania jest niebywaîa. Otóû koïczy sië minikurs jëzyka E. Rafaî Wiosna Okazaîo sië, ûe miesiâc temu skîamaîem i nie zamieôciîem wszystkich opisów wiadomoôci IDCMP. Artykuî w pierwotnej formie sië nie zmieôciî, dlatego teû w tym odcinku naprawdë dokoïczë opisywanie wnëtrznoôci Intuition. IDCMP_... IDCMP_CHANGEWINDOW -- wiadomoôê wysyîana aplikacji w chwili zmiany wymiarów lub poîoûenia okna. Moûe to zrobiê uûytkownik lub sam program, uûywajâc funkcji SizeWindow(), MoveWindow(), ChangeWindowBox() lub ZipWindow(). IDCMP_MENUHELP -- bardzo ciekawy typ wiadomoôci. Aplikacja otrzyma jâ, gdy uûytkownik naciônie klawisz [Help] podczas wybierania jakiejô opcji z menu. MENUHELP dziaîa nawet wówczas, gdy opcja jest niedostëpna (ghosted). Wiadomoôci tego typu bëdâ wysyîane tylko wtedy, gdy w tagach, przekazywanych funkcji OpenWindowTagList() znajduje sië tag WA_MenuHelp. (Nie ma odpowiednika tego tagu wôród flag typu WFLG_!) Programista moûe odczytaê, który element menu zostaî "wybrany" w polu code. Jeûeli ûadna opcja nie znajdowaîa sië pod kursorem myszy, w chwili gdy uûytkownik naciskaî [Help], wartoôê pola code bëdzie wynosiîa MENUNULL. IDCMP_GADGETHELP -- (nowoôê w systemie V39, czyli 3.0) wiadomoôê wysyîana wtedy, gdy kursor myszy znajduje sië nad gadûetami. Aby z tego skorzystaê, naleûy uûyê funkcji HelpControl() w celu wîâczenia moûliwoôci otrzymywania wiadomoôci typu IDCMP_GADGETHELP. W jej polu code jest numer gadûetu, nad którym znajduje sië kursor myszy. To mniej wiëcej wszystkie typy wiadomoôci, które moûe otrzymaê aplikacja. Zajmijmy sië teraz flagami, którymi okreôla sië parametry i stan nowo otwieranego okna. WFLG_... WFLG_SIZEGADGET -- decyduje o obecnoôci gadûetu, umoûliwiajâcego zmianë rozmiaru okna. WFLG_DRAGBAR -- okno bëdzie miaîo listwë, umoûliwiajâcâ jego przesuwanie. Jeûeli nie uûyjesz tej flagi, okna nie bëdzie moûna przesunâê. WFLG_DEPTHGADGET -- gadûet umoûliwiajâcy ustawianie okna wzglëdem innych. WFLG_CLOSEGADGET -- gadûet umoûliwiajâcy zamkniëcie okna. Jeûeli nie uûyjesz tej flagi, Twojego okna nie bëdzie moûna zamknâê (aplikacja nie otrzyma wiadomoôci IDCMP_CLOSEWINDOW nawet, gdy zaûâdasz, aby jâ przysyîano!). WFLG_SIZEBRIGHT -- okno bëdzie miaîo dodatkowâ listwë po prawej stronie (np. na suwaki). WFLG_SIZEBBOTTOM -- okno bëdzie miaîo dodatkowâ listwë u doîu (np. na suwaki). WFLG_SMART_REFRESH -- flaga dotyczâca odtwarzania zawartoôci okna, kiedy zmieniâ sië jego parametry, np. wielkoôê. Tym razem zadba o to system. WFLG_SIMPLE_REFRESH -- jw., ale o odtwarzanie zawartoôci okna dba aplikacja. WFLG_SUPER_BITMAP -- jw., w tym wypadku system magazynuje zawartoôê okna (która moûe byê wiëksza niû samo okno) w specjalnym buforze, dziëki czemu odôwieûanie zawartoôci (tak jak w wypadku WFLG_SMART_REFRESH i WFLG_SIMPLE_REFRESH) jest wîaôciwie niepotrzebne. Wiëcej o odôwieûaniu okien napisaîem w 12. odcinku cyklu. WFLG_BACKDROP -- okreôla specjalny typ okna. Jest ono otwierane pod wszystkimi innymi "normalnymi" oknami, ale nad innymi oknami backdrop. Zwykle ten typ okna okreôla sië jeszcze flagâ WLFG_BORDERLESS (o tym za chwilë), dziëki temu okno jest niewidoczne na ekranie. Tym sposobem uzyskuje sië zîudzenie dziaîania pustego ekranu tak jak okna -- wszak ekrany nie otrzymujâ wiadomoôci IDCMP... Okno o tych samych rozmiarach co ekran, bez nazwy i otworzone z flagami WFLG_BORDERLESS+WFLG_BACKDROP pozwala na zrealizowanie podobnych rozwiâzaï interfejsu uûytkownika, jak np. w PowerPackerze czy programach malarskich. Jedynym gadûetem systemowym w tej sytuacji, którego moûna uûyê, jest gadûet zamkniëcia okna (gadûet zmiany wielkoôci jest bez sensu, a zmiany gîëbokoôci zasîoni jego odpowiednik na ekranie). WFLG_REPORTMOUSE -- aplikacja bëdzie otrzymywaîa wiadomoôci typu IDCMP_MOUSEMOVE i/lub IDCMP_DELTAMOVE. WFLG_GIMMEZEROZERO -- okreôla poîoûenie poczâtku koordynat okna. W normalnej sytuacji znajduje sië on w lewym górnym rogu ramki okna. Uûywajâc GZZ moûna go umieôciê w lewym górnym rogu wewnëtrznego obszaru okna. Poczâtkujâcy programiôci robiâ bîad, nie uûywajâc tej techniki do lokalizacji gadûetów, tekstów i innych elementów graficznych. Gdy uûytkownik zmieni wielkoôci domyôlnych czcionek, czësto sië zdarza, ûe napis "wychodzi" na ramkë. (Przy okazji: poîoûenia kursora myszy, zwracane przez wiadomoôci typu IDCMP_MOUSEMOVE, sâ zawsze relatywne do ramki okna, niezaleûnie od tego, czy uûyto flagi WFLG_GIMMEZEROZERO. W strukturze otwartego okna znajdujâ sië dwa pola --- gzzmousex i gzzmousey, które podajâ poîoûenie kursora w stosunku do rogu obszaru roboczego.) WFLG_BORDERLESS -- okno nie bëdzie miaîo obwódki. Jeûeli chcesz, ûeby okno nie byîo w ogóle widoczne, nie moûesz uûyê flagi WFLG_DRAGBAR oraz flag umieszczajâcych w jego ramce gadûety. Pamiëtaj teû, aby tytuî okna byî pusty. WFLG_ACTIVATE -- okno po otworzeniu bëdzie aktywne (normalnie -- nie zostanie uaktywnione). WFLG_RMBTRAP -- po wciôniëciu prawego przycisku myszy menu nie zostanie pokazane. Aplikacja powinna sama zadbaê o to, aby dostëp do menu zostaî zapewniony (np. Deluxe Paint). WFLG_NOCAREREFRESH -- programistë nie obchodzi odôwieûanie okna (aplikacja nie otrzyma wiadomoôci IDCMP_REFRESHWINDOW). Istniejâ jeszcze inne flagi, ale przeznaczone sâ one dla zaawansowanych programistów. Resztki Pozostaîo jeszcze kilka wbudowanych w Amiga E rozkazów, które trzeba omówiê. Pierwszy z nich to: CloseW(windowptr) gdzie windowptr to wskaúnik struktury okna, zwracany przez OpenW(), oraz systemowe funkcje zajmujâce sië otwieraniem okien. Jedynâ róûnicâ miëdzy tym rozkazem a systemowâ funkcjâ CloseWindow() jest fakt, ûe tutaj moûna podaê NIL jako argument (podajâc NIL, czyli zero do CloseWindow() moûna sië od razu przygotowaê na wizytë naszego czerwonego migajâcego przyjaciela). Jest to uîatwienie dla programisty, gdyû nie musi on sprawdzaê, czy okno, które chce zamknâê, w ogóle zostaîo otworzone. Ot, kilkanaôcie bajtów mniej w kodzie úródîowym... Przy okazji CloseW() ustawia standardowe wartoôci wewnëtrznej zmiennej stdrast, uûywanej przez E do wskazania uûywanego rastportu. kod:=Mouse() Instrukcja ta jest przydatna, gdy nie chcemy bawiê sië w wiadomoôci IDCMP, a programista ma chëê sprawdziê, czy i który klawisz myszki zostaî wciôniëty. Funkcja ta zwraca wartoôê 1, gdy wciôniëto LMB, 2, gdy wciôniëto RMB i 3, gdy wciôniëto oba. 0 zwracane jest wtedy, gdy uûytkownik nie wcisnâî ûadnego klawisza myszki. Warto zauwaûyê, ûe Mouse() nie pozwala na sprawdzenie stanu trzeciego klawisza myszki, jeûeli taki akurat mamy. Przy okazji pewna uwaga. Otóû Mouse() nie korzysta z intuition.library, ale siëga (jako jedyna w Amiga E) bezpoôrednio do rejestrów sprzëtowych Amigi. Otóû uûywanie tej funkcji nie jest mile widziane w aplikacjach otwierajâcych wîasne GUI! Jeûeli tak rozwiâûesz kwestië rozpoznawania stanu klawiszy myszy, Twoja aplikacja bëdzie reagowaê na klikniëcia, majâce miejsce w innych programach! Ogólnie mówiâc, nie uûywaj tej funkcji, gdy Twój program ma byê przyjazny dla systemu operacyjnego. Moûesz za to skorzystaê z nastëpujâcej funkcji i rozkazu: stan:=LeftMouse(windowptr) WaitLeftMouse(windowptr) które nie uûywajâ rejestrów sprzëtowych, ale systemu operacyjnego. Pierwsza funkcja zwraca stan wciôniëcia lewego klawisza myszki (0 -- nie wciôniëty, 1 -- wciôniëty), druga natomiast czeka, aû uûytkownik go naciônie. Obie wymagajâ podania jako argumentu wskaúnika do struktury okna. Wartoôê ta zwracana jest przez wewnëtrzny rozkaz OpenW(), jak i systemowe funkcje otwierania okna. Nastëpne dwie funkcje: x:=MouseX(windowptr) y:=MouseY(windowptr) Zwracajâ poîoûenie kursora myszy w stosunku do lewego górnego rogu okna, do kórego struktury przekazywany jest wskaúnik jako argument. Jednâ z bardzo przydatnych funkcji E jest: klasa:=WaitIMessage(windowptr) która przekazuje aplikacji klasë wiadomoôci IDCMP, jaka pojawiîa sië dla okna. Dziëki temu moûna zdecydowanie uproôciê aplikacjë, dla której waûne sâ wiadomoôci bezargumentowe (np. IDCMP_CLOSEWINDOW). Jak zwykle w takich sytuacjach argumentem funkcji jest wskaúnik do struktury okna, które chcemy "podsîuchiwaê". Aby dokîadniej wyjaôniê, co WaitIMessage() robi, przytoczë kawaîek kodu, który odpowiada wywoîaniu tej funkcji: PROC waitimessage(windowptr:PTR TO window) DEF port,mes:PTR TO intuimessage,class,code,qual,iaddr port:=windowptr.userport IF (mes:=GetMsg(port))=NIL REPEAT WaitPort(port) UNTIL (mes:=GetMsg(port))<>NIL ENDIF class:=mes.class code:=mes.code qual:=mes.qualifier iaddr:=mes.iaddress ReplyMsg(mes) ENDPROC class Jak widaê, funkcja zwraca klasë ostatniej wiadomoôci, jaka pojawiîa sië w messageporcie okna. Uzupeîniajâce funkcje to: kod:=MsgCode() kwal:=MsgQualifier() iaddr:=MsgIaddr() zwracajâce odpowiednie pola wiadomoôci, którâ rozpoznaîa funkcja WaitIMessage(). * To by byîo tyle. Przez ponak rok nauczaîem Was, jak programowaê w E, korzystajâc z systemu operacyjnego Amigi. Pamiëtaj, NIGDY nie posîuguj sië wartoôciami bezpoôrednimi (np. $00F5). Gdy coô przekazujesz funkcjom systemowym, uûywaj zawsze staîych zdefiniowanych w moduîach. Ta maniera odda Ci nieoczekiwane przysîugi, gdy bëdziesz sië staraî odpluskwiê swój program lub powrócisz do niego po kilkumiesiëcznej przerwie. Nauka programowania w systemie Amigi to bardzo mocna podstawa, którâ moûesz wykorzystaê w przyszîoôci. Idea architektury klient-serwer (klientem jest aplikacja, serwerem -- system operacyjny, wzajemnie przekazujâ sobie róûne informacje w postaci wiadomoôci itp.) jest bardzo podobna dla wszystkich nowoczesnych platform komputerowych -- Windows (brrr...), Windows NT, OS/2, Unix... Oczywiôcie, to nie to samo, ale to, czego nauczyîeô sië na Amidze, pozwoli Ci swobodnie napisaê program np. pod OS-a lub przenieôê na niego aplikacjë amigowskâ. Pominâîem w kursie programowanie obiektowe. Gîównie ze wzglëdu na to, ûe jest ono na poczâtku trudne do zrozumienia. Zresztâ, o zawiîoôci tej techniki niech ôwiadczy fakt, ûe wydana przez nasze Wydawnictwo ksiâûka o programowaniu obiektowym w C++ liczy niemal 600 stron! A to tylko wprowadzenie... Amiga E jest wspaniaîym jëzykiem dla poczâtkujâcych, ale takûe zaawansowani programiôci znajdâ tu coô dla siebie. Nie wspomniaîem w tym cyklu ani sîowem o komórkach, strukturze danych, znanej z jëzyka LISP. Pominâîem teû milczeniem fakt, ûe E obsîuguje format zmiennoprzecinkowy. Nie byîo teû sîowa o najnowszej modzie -- GUI adaptujâcym sië do ustawieï uûytkownika, a taki mechanizm jest dostëpny w pakiecie EasyGUI, który jest skîadnikiem pakietu Amiga E. Wszystko to zostawiam na deser, a raczej podwieczorek, gdyû tak naprawdë na deser zarezerwowaîem sobie omówienie najnowszej, w chwili obecnej, wersji. Amiga E 3.2a Nowoôci w tej wersji to: ^* moûliwoôê tworzenia bibliotek (.library), ^* nowe moûliwoôci debuggera EDBG, ^* nowe moûliwoôci pakietu EasyGUI, ^* ochrona skompilowanego programu przed zawieszeniem sië z powodu korzystania z nie zainicjowanych danych (takich, których wartoôciâ jest NIL, czyli 0; wszystkie odwoîania przez "." oraz przez "[]" mogâ byê sprawdzane przed uûyciem), ^* moduîy do Kickstartu w wersji 40, ^* nowe moduîy E -- Src, Class, ScrollWin, etc., ^* zaktualizowana dokumentacja, tym razem wszystko w formie AmigaGuide, ^* przykîady z ksiâûki Rom Kernel Manual: Libraries przepisane na Amiga E (sic!). Poniûej przedstawiam metryczkë Amiga E: wersja data wielkoôê kompilatora (KB) v0.3 wrzesieï 91 5 v1.0 maj 92 20 v2.0 paúdziernik 92 38 v2.1a styczeï 93 44 v2.1b kwiecieï 93 45 v3.0a lipiec 94 82 v3.0b wrzesieï 94 82 v3.0e listopad 94 83 v3.1a grudzieï 94 85 v3.2a lipiec 95 85