home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1997 #3 / amigamamagazinepolishissue03-1 / ma_1995 / 12 / ami043.txt < prev    next >
Text File  |  1997-04-07  |  10KB  |  213 lines

  1. C dla kaûdego (cz. 7.)
  2. ----------------------
  3.  
  4. MALOWANIA CIÂG DALSZY
  5.  
  6. <lead>W dzisiejszym odcinku opiszemy to, co zaprezentowane
  7. zostaîo w listingu z poprzedniej czëôci.
  8.  
  9. <a>Kamil Iskra, Dariusz Ûbik
  10.  
  11. <txt>Wystëpuje oczywiste powiâzanie pomiëdzy trybem pracy
  12. programu, klawiszem powodujâcym jego wywoîanie i opisujâcym go
  13. tekstem. Stworzyliômy wiëc wîasnâ strukturë o nazwie "operacja",
  14. która îâczy te trzy elementy: pole "name" zawiera opis trybu, a
  15. "key" literë, wywoîujâcâ dany tryb. Trzecie pole -- "fun" -- moûe
  16. byê czymô nowym dla niezbyt doôwiadczonych programistów -- jest
  17. to wskaúnik na funkcjë pobierajâcâ argumenty, "wskaúnik na
  18. strukturë IntuiMessage" oraz "wskaúnik na strukturë Window", a
  19. nie zwracajâcâ niczego (void) -- peîniejsze wiadomoôci znajdziesz
  20. w ksiâûce "Jëzyk ANSI C". W programie definiowana jest tablica
  21. takich struktur: "op_tab", w pola "fun" jest wpisywany adres
  22. funkcji obsîugujâcych dany tryb programu, a to, w jakim trybie
  23. program znajduje sië w danym momencie, jest odnotowane w zmiennej
  24. "op_pos", której wartoôê jest po prostu indeksem tablicy
  25. "op_tab". Aby wywoîaê funkcjë, której adres znajduje sië w polu
  26. "fun", naleûy postâpiê tak samo, jakby sië wywoîywaîo normalnâ
  27. funkcjë. My w programie robimy po prostu:
  28.  
  29. <l> op_tab[op_pos].fun(&msg, window);
  30.  
  31. <txt>Deklaracjë zmiennych mamy juû za sobâ, nastëpnie otwarcie
  32. bibliotek i okna, pëtla "for", wykonujâca sië do koïca programu,
  33. oraz "rutynka", czyli oczekiwanie na informacje z portu okna, a
  34. póúniej jakieô "cuda": "__STDC__" i inne.
  35.  
  36. Zastosowaliômy wyraûenie, które nie jest znane wszystkim
  37. kompilatorom, a mianowicie przypisanie jednej struktury do
  38. drugiej za pomocâ pojedynczego przypisania. Taki zapis jest
  39. zgodny z normâ ANSI jëzyka C, ale niektóre starsze kompilatory
  40. mogâ mieê z nim problemy. Z tego powodu uûyliômy dyrektyw
  41. preprocesora, powodujâcych warunkowâ kompilacjë: jeûeli jest
  42. zdefiniowana staîa "__STDC__" i jest ona róûna od 0 (#if
  43. __STDC__), co oznacza, ûe dany kompilator jest zgodny z normâ
  44. ANSI, to uûywamy wyûej opisanej instrukcji, w przeciwnym wypadku
  45. (#else) jawnie kopiujemy jednâ strukturë do drugiej. Warto moûe w
  46. tym momencie wspomnieê o kilku innych standardowo zdefiniowanych
  47. staîych, np. __SASC i AMIGA dla SAS/C, AZTEC_C i MCH_AMIGA dla
  48. Aztec C, __GNUC__ i AMIGA dla GNU CC -- dziëki temu moûna tworzyê
  49. programy, dziaîajâce na kilku platformach sprzëtowych oraz
  50. moûliwe do skompilowania na róûnych kompilatorach.
  51.  
  52. Wprawdzie nie wszyscy bëdâ zmuszeni do woîania funkcji CopyMem() z
  53. biblioteki Exec, jednak wszyscy znaê jâ powinni:
  54.  
  55. <l> void CopyMem( APTR source, APTR dest, unsigned long size );
  56.  
  57. <txt>Zadaniem funkcji jest skopiowanie obszaru pamiëci,
  58. wskazywanego przez wskaúnik "source", do obszaru wskazywanego
  59. przez "dest". Rozmiar kopiowanego "kawaîka", podany w bajtach,
  60. jest trzecim argumentem. UWAGA! Kolejnoôê parametrów "source" i
  61. "dest" jest ODWROTNA niû w standardowych funkcjach kopiujâcych
  62. jëzyka "C", takich jak "strcpy", "memcpy" itd.
  63.  
  64. Po wykonaniu kopii przybyîej wiadomoôci i zwrocie oryginaîu
  65. "rozpakowujemy prezent" od Intuition.
  66.  
  67. <sr>Klasa wiadomoôci IDCMP_VANILLAKEY:
  68.  
  69. <txt>Flaga ta powoduje dostarczanie do programu informacji o
  70. uûyciu klawiatury. Informacja tego typu zawiera w polu "Code" kod
  71. znaku, jaki znajdowaî sië pod przyciôniëtym przyciskiem.
  72. Obsîugiwane jest aktualne obîoûenie klawiatury, ustawione przez
  73. uûytkownika za pomocâ systemowego programu "Input". VANILLAKEY
  74. dostarcza tylko pojedynczych znaków. Nie jest moûliwe odczytanie
  75. ciâgów zdefiniowanych pod przyciskami, nie moûna dowiedzieê sië o
  76. przycisku HELP, kursorach... Moûliwe jest jednak odczytanie
  77. wciôniëcia klawisza [Esc], poniewaû jest on pojedynczym znakiem o
  78. kodzie 27.
  79.  
  80. W programie po otrzymaniu informacji o naciôniëciu przycisku
  81. sprawdzamy, czy jest to [Esc]. Jeôli tak, to opuszczamy program,
  82. w przeciwnym wypadku przeglâdamy tablicë operacji, sprawdzajâc,
  83. czy któraô z nich nie ma skrótu z klawiatury identycznego z
  84. naciôniëtym przyciskiem. Ten przydîugawy warunek w pëtli "for"
  85. pozwala przejrzeê wszystkie elementy tablicy "op_tab". Poniewaû
  86. operator "sizeof" zwraca rozmiar obiektu w bajtach, naleûy
  87. wielkoôê të podzieliê przez rozmiar pojedynczego elementu.
  88. Operator "sizeof" podaje rozmiar obiektu podczas kompilacji
  89. programu, w zwiâzku z tym wyraûenie w warunku pëtli "for" otrzyma
  90. staîâ wartoôê.
  91.  
  92. Po otrzymaniu informacji IDCMP_CLOSEWINDOW woîamy funkcjë:
  93.  
  94. <l> BOOL DoubleClick( ULONG sSeconds, ULONG sMicros, ULONG cSeconds, 
  95. ULONG cMicros);
  96.  
  97. <txt>Jej zadaniem jest sprawdzenie, czy dwa podane czasy mieszczâ
  98. sië w tzw. double-clicku. Jeôli róûnica pomiëdzy podanymi czasami
  99. jest mniejsza od double-clicku, to zostanie zwrócona wartoôê
  100. TRUE, w przeciwnym wypadku FALSE. Czas do funkcji podaje sië w
  101. postaci sekund i mikrosekund pierwszego i drugiego wydarzenia.
  102. Czas moûna znaleúê w strukturze "IntuiMessage".
  103.  
  104. Dziëki funkcji DoubleClick() opuszczenie programu nastâpi dopiero
  105. po dwukrotnym klikniëciu na gadûecie zamykania. W wypadku
  106. pojedynczego naciôniëcia zostanie zmieniony tryb pracy programu
  107. (tak, wiemy, to nie jest intuicyjne).
  108.  
  109. W wypadku, gdy system dostarczy informacji o przyciskach myszy
  110. (IDCMP_MOUSEBUTTONS), zostanie wywoîana bieûâca funkcja z tablicy
  111. "op_tab".
  112.  
  113. Wewnâtrz instrukcji "switch" pojawiîa sië kolejna, nie omówiona
  114. dotychczas, klasa informacji IDCMP, a mianowicie IDCMP_MOUSEMOVE.
  115. Klasa ta powoduje przekazywanie do portu aktywnego okna
  116. informacji o kaûdym ruchu myszy (trzeba je obsîugiwaê szybko, bo
  117. przy nagîych ruchach myszâ przybywa naprawdë sporo informacji!).
  118. Do jej funkcjonowania konieczne jest umieszczenie w polu "Flags"
  119. okna flagi WFLG_REPORTMOUSE. Program w prezentowanej wersji nie
  120. robi nic w wypadku stwierdzenia takiej klasy wiadomoôci,
  121. umieôciliômy jâ jednak, aby umoûliwiê jego rozbudowë, która bez
  122. znajomoôci tej klasy informacji mogîaby byê kîopotliwa.
  123.  
  124. Poniewaû w funkcji "main" nie znajdziemy juû nic ciekawego, omówië
  125. jedynie funkcje zawarte w tablicy "op_tab":
  126.  
  127. linia() -- Zawiera funkcjë z biblioteki "graphics.library":
  128.  
  129. <l>void Draw( struct RastPort *rp, long x, long y );
  130.  
  131. <txt>Jej zadaniem jest narysowanie linii pomiëdzy obecnym poîoûeniem
  132. kursora a podanymi wspóîrzëdnymi. Zmieniane jest poîoûenie kursora
  133. graficznego na wartoôci x i y.
  134.  
  135. punkt() -- Zawiera dwie funkcje biblioteczne:
  136.  
  137. <l>LONG WritePixel( struct RastPort *rp, long x, long y );
  138.  
  139. <txt>Rysuje punkt o wspóîrzëdnych (x, y). Funkcja zwraca zero,
  140. gdy wszystko byîo OK, lub -1, gdy podany punkt jest poza
  141. RastPortem. Jako jedna z niewielu nie zmienia poîoûenia kursora
  142. graficznego.
  143.  
  144. <l> void Move( struct RastPort *rp, long x, long y );
  145.  
  146. <txt>Przesuwa kursor graficzny w podane miejsce, bez
  147. jakiegokolwiek efektu wizualnego.
  148.  
  149. napis() -- Odwoîuje sië do funkcji systemowej:
  150.  
  151. <l> LONG Text( struct RastPort *rp, STRPTR string, unsigned long count );
  152.  
  153. <txt>Umieszcza ona tekst, wskazywany przez "string", w
  154. RastPorcie. Napis jest umieszczany w bieûâcym miejscu (cp_x,
  155. cp_y) i rysowany bieûâcâ czcionkâ. Jest pisany zarówno poniûej,
  156. jak i powyûej poîoûenia kursora (dlaczego tak jest, powiemy za
  157. chwilë). Po zakoïczeniu dziaîania funkcji kursor graficzny
  158. znajduje sië na koïcu tekstu. Funkcja ta wymaga podania liczby
  159. znaków do wypisania. Sîuûy do tego ostatni argument.
  160.  
  161. drmd() -- Funkcja ta zmienia tryb rysowania po przyciôniëciu
  162. lewego przycisku myszy. Systemowe narzëdzia, sîuûâce do tego
  163. celu, opisaliômy wczeôniej. Wystëpujâca tu przydîugawa i
  164. skomplikowana konstrukcja, która jest drugim argumentem funkcji
  165. SetDrMd() powoduje, ûe tryb rysowania zostanie ustalony na
  166. kolejny lub odliczanie rozpocznie sië od poczâtku. Postëpujâc
  167. zgodnie z kolejnoôciâ operatorów najpierw zostanie wykonana
  168. konstrukcja warunkowa, zwracajâca numer obecnego trybu (jej
  169. zadanie byîo omówione wczeôniej) -- po jego zwiëkszeniu o jeden
  170. otrzymamy numer kolejnego trybu. Poniewaû argument funkcji
  171. SetDrMd(), bëdâcy równoczeônie indeksem tablicy names[], powinien
  172. byê istniejâcym trybem, naleûy zadbaê o to, aby wartoôê ta nie
  173. przekraczaîa 7, poniewaû po zsumowaniu masek bitowych wszystkich
  174. trybów rysowania, otrzymamy takâ wîaônie wartoôê (patrz
  175. "graphics/rastport.h"). Do zapisania liczby z przedziaîu 0..7
  176. wystarczâ trzy najmîodsze bity -- wîaônie w tym celu wykonujemy
  177. bitowâ operacjë I (AND) z flagâ 7 (bitowo 0111). Dziëki temu
  178. przetrwajâ jedynie najmîodsze bity i zapisanie liczby wiëkszej od
  179. 7 nie bëdzie moûliwe. Uzyskamy wiëc cyklicznie zmieniajâcy sië
  180. tryb graficzny.
  181.  
  182. color() -- Zmienia kolor tîa po przyciôniëciu prawego przycisku
  183. oraz atramentu po przyciôniëciu lewego.
  184.  
  185. kwadrat() -- Rysuje wypeîniony prostokât od poîoûenia kursora
  186. graficznego do poîoûenia myszy w momencie klikniëcia. Zwie sië
  187. niezbyt zgodnie z prawdâ, poniewaû kolega Darek nie odróûnia
  188. prostokâtów od kwadratów. Funkcja ta korzysta z funkcji
  189. biblioteki graficznej:
  190.  
  191. <l>void RectFill( struct RastPort *rp, long xMin, long yMin, long 
  192. xMax, long yMax );
  193.  
  194. <txt>Jej zadaniem jest wypeînienie prostokâtnego obszaru. Uznaje
  195. aktualne kolory i tryb rysowania. Wspóîrzëdne lewego górnego rogu
  196. prostokâta (xMin, yMin) MUSZ byê mniejsze lub równe od
  197. wspóîrzëdnych prawego dolnego rogu (xMax, yMax).
  198.  
  199. elipsa() -- Funkcja rysuje elipsë, dîugoôci póîosi sâ równe
  200. wspóîrzëdnym wektora îâczâcego punkt (cp_x, cp_y) z punktem, nad
  201. którym "przyciôniëto" mysz. Biblioteczna funkcja do rysowania
  202. elipsy wyglâda nastëpujâco:
  203.  
  204. <l>void DrawEllipse( struct RastPort *rp, long xCenter, long yCenter, 
  205. long a, long b );
  206.  
  207. <txt>xCenter i yCenter to wspóîrzëdne ôrodka elipsy, a i b to póîosie
  208. elipsy (muszâ byê wiëksze od zera). Wspóîrzëdne cp_x i cp_y nie sâ
  209. zmieniane.
  210.  
  211. Za miesiâc zajmë sië czcionkami.
  212.  
  213.