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

  1. ******************************************
  2. UWAGA DO SKÎADU: PROSZË PRZY WLEWANIU TEGO TEKSTU WYÎÂCZYÊ KONWERSJË
  3. CUDZYSÎOWÓW, TAK, ABY PAGEMARKER NIE ZMIENIAΠPOCZÂTKOWYCH CUDZYSÎOWÓW
  4. NA DOLNE.
  5. ******************************************
  6.  
  7.  
  8. C dla kaûdego (cz. 2.)
  9. ----------------------
  10.  
  11. OKNO NA SZARY ÔWIAT
  12.  
  13. <lead>Najwyûszy czas zabraê sië do konkretnej pracy. Dziô
  14. zajmiemy sië oknami, obracaê sië wiëc bëdziemy w krëgu
  15. biblioteki Intuition, która zarzâdza GUI.
  16.  
  17. <a>Kamil Iskra, Dariusz Ûbik
  18.  
  19. <txt>Zacznijmy od, dostëpnych dopiero po otwarciu biblioteki
  20. Intuition, funkcji do otwierania okien. Dawniej istniaîa tylko
  21. jedna taka funkcja:
  22.  
  23. <l>struct Window *OpenWindow( struct NewWindow *newWindow );
  24.  
  25. <txt>Obecnie (od systemu 2.0) istnieje teû druga:
  26.  
  27. <l>struct Window *OpenWindowTagList( struct NewWindow *newWindow, struct TagItem *tagList );
  28.  
  29. struct Window *OpenWindowTags( struct NewWindow *newWindow, unsigned long tag1Type, ... );
  30.  
  31. <txt>Pewnie cisnâ sië Wam na usta dwa pytania: co robiâ powyûej
  32. dwa prototypy funkcji, skoro miaî byê tylko jeden, i co oznaczajâ
  33. parametry tych funkcji. Pierwszy parametr to wskaúnik na
  34. zainicjowanâ wczeôniej strukturë informacyjnâ, w której
  35. umieszczaîo sië informacje o tym, jaki miaî byê rozmiar okna,
  36. jakie miaîo mieê ono gadûety, tytuî itp. Piszemy w czasie
  37. przeszîym, poniewaû parametru tego w dzisiejszych czasach juû sië
  38. wîaôciwie nie uûywa (jako pierwszy parametr podaje sië po prostu
  39. NULL, czyli 0). Struktura NewWindow zostaîa wyparta przez tagi.
  40.  
  41. <sr>Dlaczego tagi?
  42.  
  43. <txt>System sië rozwija. Od czasu pierwszej Amigi duûo zostaîo
  44. zrobione. Niestety, nawet pomimo duûej liczby "furtek",
  45. pozostawionych przez twórców systemu, niektóre struktury staîy
  46. sië w koïcu zbyt ciasne -- klasycznym przykîadem jest wîaônie
  47. struktura NewWindow. Zastëpowanie ich w kaûdym systemie nowymi
  48. nie ma sensu. Wîaônie dlatego pojawiîy sië tagi. Za ich pomocâ
  49. moûna przekazywaê do funkcji nieograniczone iloôci informacji,
  50. bez posîugiwania sië sztywnymi strukturami, tagi umoûliwiajâ teû
  51. bezproblemowe dodawanie nowych elementów do systemu operacyjnego.
  52. Argumenty podaje sië parami (strukturami TagItem) -- pierwszy
  53. element pary to wîaônie TAG, który jest po prostu staîâ
  54. informujâcâ, co oznacza dana przekazana w drugim elemencie pary,
  55. moûe to byê np. szerokoôê okna, jego tytuî (wskaúnik na nazwë)
  56. itd. Po pierwszej parze moûe nastâpiê druga, trzecia i nastëpne.
  57.  
  58. Funkcje korzystajâce z tagów mogâ byê wywoîane na dwa sposoby.
  59. Istniejâ dwie deklaracje tej samej funkcji bibliotecznej
  60. (róûniâce sië zwykle koïcówkâ nazwy -- tak jak w wypadku
  61. OpenWindowTagList() i OpenWindowTags()). Pierwszym ze sposobów
  62. wywoîania takiej funkcji jest podanie jej wskaúnika na tablicë
  63. tagów w charakterze argumentu (w naszym wypadku chodzi o ostatni
  64. argument funkcji OpenWindowTagList()). Tablica taka jest
  65. wypeîniona strukturami TagItem. W drugim sposobie
  66. (OpenWindowTags()) zamiast wskaúnika na zdefiniowanâ wczeôniej
  67. tablicë podaje sië po prostu pary jako kolejne parametry do
  68. funkcji o zmiennej liczbie argumentów (na podobnej zasadzie, jak
  69. w "printf()"). Oba sposoby sâ równowaûne, w rzeczywistoôci
  70. funkcja przyjmuje argumenty w tej pierwszej postaci, a druga jest
  71. po prostu "tîumaczona", przez kompilator, na pierwszâ, a istnieje
  72. dlatego, ûe jest wygodniejsza w uûyciu.
  73.  
  74. Warto wspomnieê o tagu, który MUSI sië pojawiê na koïcu, w
  75. tablicy struktur TagItem, lub jako ostatni argument funkcji. Jest
  76. nim TAG_END, nazywany równieû TAG_DONE (równy 0). Wîaônie ten tag
  77. informuje funkcjë, ûe nie ma juû wiëcej danych. Jeôli go
  78. zabraknie, to nieszczësna funkcja nadal bëdzie czytaê dane z
  79. przypadkowego obszaru pamiëci i moûe sië naczytaê bzdur. Dlatego
  80. uczulamy Was: PAMIËTAJCIE o stawianiu tagu TAG_END. Wykrycie
  81. takiego bîëdu nie zawsze jest proste, gdyû program moûe czasami
  82. "chodziê" caîkiem normalnie (bo akurat znajdzie w pamiëci zero).
  83.  
  84. Obie opisane powyûej funkcje do otwierania okien zwracajâ adres
  85. struktury opisujâcej otwarte okno (struktura Window) lub NULL, w
  86. wypadku gdy spotka je niepowodzenie.
  87.  
  88. Zastosowanie tych funkcji moûna zobaczyê w listingu 4.
  89.  
  90. Przypominamy, ûe listingi nie sâ kompletne! Naleûy doîâczyê
  91. funkcjë check_os() z poprzedniej czëôci kursu oraz definicje
  92. staîych "OS_xx", deklaracjë zmiennej "SysBase" i pliki nagîówkowe
  93. "exec/execbase.h" oraz "stdlib.h".
  94.  
  95. Warto wytîumaczyê, co oznaczajâ uûyte w tym przykîadzie tagi:
  96.  
  97. WA_Left -- wspóîrzëdna lewej krawëdzi okna,
  98.  
  99. WA_Top -- wspóîrzëdna górnej krawëdzi okna,
  100.  
  101. WA_Width -- rozmiar okna w poziomie,
  102.  
  103. WA_Height -- rozmiar okna w pionie.
  104.  
  105. W wypadku Amigi wspóîrzëdne sâ podawane wzglëdem lewego górnego
  106. rogu, który ma wspóîrzëdne (0, 0), ekran zaô jest poîoûony
  107. niejako w czwartej êwiartce ukîadu wspóîrzëdnych. Nie naleûy sië
  108. sugerowaê programami graficznymi, w wypadku których wyôwietlane
  109. wspóîrzëdne sâ przeliczane w taki sposób, ûe ekran jest przez
  110. uûytkownika widziany jako pierwsza êwiartka kartezjaïskiego
  111. ukîadu wspóîrzëdnych. Ta sama zasada obowiâzuje w wypadku okien.
  112. Wspóîrzëdne w oknie oblicza sië wzglëdem lewego górnego rogu
  113. okna.
  114.  
  115. WA_Title -- tytuî okna (wyôwietlany na jego listwie),
  116.  
  117. WA_Flags -- flagi dotyczâce gîównie wyglâdu okna:
  118.  
  119. -- WFLG_SIZEGADGET -- okno ma mieê gadûet do zmieniania wielkoôci,
  120.  
  121. -- WFLG_DRAGBAR -- okno ma mieê listwë do przesuwania za pomocâ myszy,
  122.  
  123. -- WFLG_DEPTHGADGET -- okno ma mieê gadûet przód/tyî,
  124.  
  125. -- WFLG_CLOSEGADGET -- okno ma mieê gadûet zamykania,
  126.  
  127. -- WFLG_ACTIVATE -- okno ma zostaê automatycznie uaktywnione po
  128. otwarciu,
  129.  
  130. -- WFLG_RMBTRAP -- naciskanie prawego przycisku menu (RMB --
  131. Right Mouse Button) nie ma powodowaê rysowania listwy menu.
  132.  
  133. Niektóre flagi majâ swoje odpowiedniki wôród tagów. Moûna je
  134. wywoîywaê bezpoôrednio, podajâc po nich wartoôê TRUE. Przykîadami
  135. takich flag mogâ byê: WA_SizeGadget, WA_DepthGadget,
  136. WA_CloseGadget. Dokîadny ich wykaz, wraz z definicjami staîych,
  137. znajduje sië w pliku "intuition/intuition.h".
  138.  
  139. WA_ScreenTitle -- napis wyôwietlany na górnej listwie ekranu, gdy
  140. okno jest aktywne.
  141.  
  142. W programie zostaîa uûyta pewna funkcja z biblioteki "dos.library".
  143. Jej skîadnia jest bardzo prosta:
  144.  
  145. <l>void Delay( long timeout );
  146.  
  147. <txt>Za pomocâ tej funkcji moûna chwileczkë odczekaê. Dîugoôê
  148. chwileczki jest podawana w jednostkach nazywanych ticks, 50
  149. takich jednostek to jedna sekunda. Uwaûny Czytelnik zapewne sië
  150. zastanawia, jakim prawem woîamy funkcjë z biblioteki
  151. dos.library bez jej otwarcia. Moûemy pozwoliê sobie na të
  152. "zbrodnië", poniewaû bibliotekë të otwiera dla nas moduî
  153. startowy, doîâczany przez linkera, i podstawia pod zmiennâ
  154. "DOSBase" (wiëcej o module startowym powiemy w przyszîoôci).
  155.  
  156. Moûna wiëc chyba uznaê, ûe otwarcie okna mamy za sobâ. Teraz
  157. naleûy sië nauczyê z nim komunikowaê. Jest to rozwiâzane za
  158. pomocâ tak zwanych portów (struktur MsgPort), bëdâcych czymô w
  159. rodzaju skrzynek kontaktowych. Jeden program umieszcza w porcie
  160. wiadomoôê (strukturë Message), a drugi po chwili jâ odbiera --
  161. daje sië tu wyraúnie odczuê multitasking.
  162.  
  163. Program bëdâcy wîaôcicielem okna sam decyduje, jakie wiadomoôci
  164. chce za jego pomocâ uzyskiwaê. Moûe go np. zupeînie nie
  165. interesowaê, czy uûytkownik nacisnâî jakiô klawisz na klawiaturze
  166. albo czy wyjâî dyskietkë ze stacji. To, jakie wiadomoôci program
  167. ma otrzymywaê, ustala sië podczas otwierania okna, za pomocâ tagu
  168. "WA_IDCMP" (ta "wpadajâca w pamiëê" nazwana jest skrótem od
  169. Intuition Direct Communication Message Port). Jako dane dla tego
  170. tagu podaje sië staîe symboliczne, oznaczajâce poszczególne klasy
  171. wiadomoôci, jakie program ma otrzymywaê. Jest ich mnóstwo.
  172. Bëdziemy je podawaê stopniowo (ûeby Was nie dobiê). W tej czëôci
  173. uûyjemy w przykîadach nastëpujâcych klas:
  174.  
  175. IDCMP_CLOSEWINDOW -- klikniëcie na gadûet zamykania okna.
  176.  
  177. IDCMP_DISKINSERTED -- wîoûenie dysku.
  178.  
  179. IDCMP_DISKREMOVED - wyjëcie dysku.
  180.  
  181. IDCMP_MOUSEBUTTONS -- naciôniëcie bâdú zwolnienie któregoô z
  182. przycisków myszy (tylko przy aktywnym oknie).
  183.  
  184. W wypadku okien adres portu znajduje sië w strukturze Window, w
  185. polu o nazwie "UserPort". Program pragnâcy otrzymaê wiadomoôê nie
  186. musi co chwilë sprawdzaê, czy uûytkownik wykonaî jakâô operacjë
  187. (np. kliknâî myszâ). Wystarczy, ûe poprosi system o
  188. poinformowanie go, kiedy coô takiego nastâpi. W programach bardzo
  189. czësto zachodzi potrzeba oczekiwania na wydarzenie, do tego celu
  190. sîuûy funkcja Execa:
  191.  
  192. <l>struct Message *WaitPort( struct MsgPort *port );
  193.  
  194. <txt>Funkcja ta oczekuje na pojawienie sië jakiejkolwiek
  195. wiadomoôci w podanym porcie, jest ona wykonywana aû do czasu
  196. pojawienia sië wiadomoôci, wówczas przekazuje sterowanie z
  197. powrotem do programu. Funkcja ta zwraca wskaúnik na pierwszâ
  198. wiadomoôê umieszczonâ w porcie, choê moûe byê ich w porcie
  199. wiëcej. Naleûy pamiëtaê, ûe funkcja ta czeka "do upadîego".
  200. Jeôli ûadna wiadomoôê do portu nie dotrze, to program dalej "nie
  201. pójdzie". Nierzadkim bîëdem jest oczekiwanie na wiadomoôci od
  202. okna, które ûadnych wiadomoôci przysîaê nie moûe (ma pole
  203. IDCMPFlags==0). Na szczëôcie trudno taki bîâd przegapiê.
  204.  
  205. Kiedy juû stwierdzimy, ûe w porcie jest jakaô wiadomoôê, to
  206. naleûy jâ odebraê. Posîuûymy sië w tym celu funkcjâ Execa:
  207.  
  208. <l>struct Message *GetMsg( struct MsgPort *port );
  209.  
  210. <txt>Funkcja ta usuwa z portu pierwszâ ze znajdujâcych sië w nim
  211. wiadomoôci i jej adres zwraca naszemu programowi. W wypadku, gdy
  212. port jest pusty, funkcja zwraca NULL.
  213.  
  214. W otrzymanej w ten sposób wiadomoôci znajdziemy wiele cennych
  215. informacji. Omówimy je za chwilë. W wypadku operacji na portach
  216. waûny jest poôpiech, tak wiëc istotne dla nas informacje naleûy
  217. sobie w pomocniczych zmiennych zapamiëtaê, a wiadomoôê jak
  218. najszybciej zwróciê nadawcy. Naleûy pamiëtaê, aby niczego w
  219. otrzymanej wiadomoôci nie zmieniaê, bo mogâ wystâpiê problemy.
  220. Wiadomoôê odsyîamy za pomocâ funkcji Execa:
  221.  
  222. <l>void ReplyMsg( struct Message *message );
  223.  
  224. <txt>Funkcja ta odsyîa wiadomoôê do "macierzystego" portu. Po
  225. odesîaniu wiadomoôci NIE WOLNO juû z niej korzystaê. System moûe
  226. zrobiê z niâ, co zechce, np. zwolniê zajmowanâ przez niâ pamiëê,
  227. przez co dane by po prostu znikîy i naczytalibyômy sië bzdur.
  228.  
  229. W wypadku wiadomoôci pochodzâcych od okien mamy do czynienia z
  230. rozszerzonymi strukturami Message o nazwie IntuiMessage.
  231. Postëpowanie jest takie samo, jak w wypadku rozszerzonych
  232. struktur Library. I tym razem pierwszym polem struktury
  233. IntuiMessage jest struktura Message, moûna wiëc swobodnie
  234. zastosowaê rzutowanie typów. Zawartoôciâ struktury Message
  235. zajmiemy sië póúniej, przy dokîadnym omawianiu portów (sâ to
  236. zresztâ systemowe zawiîoôci, bez których moûna sië obejôê). Teraz
  237. omówmy pozostaîe pola struktury IntuiMessage.  Zajrzyjmy do niej
  238. -- znajduje sië ona w pliku "intuition/intuition.h".
  239. Najwaûniejsze pola to:
  240.  
  241. ULONG Class -- Informuje o klasie (rodzaju) wiadomoôci, która
  242. dotarîa do portu. Sâ to te same staîe, których uûywa sië
  243. wczeôniej w tagu WA_IDCMP (IDCMP_CLOSEWINDOW itd.).
  244.  
  245. UWORD Code -- Zawiera dodatkowe informacje, zaleûne od rodzaju
  246. wiadomoôci, np. dla wiadomoôci IDCMP_MOUSEBUTTONS pole to zawiera
  247. informacje o tym, który przycisk myszy zostaî wciôniëty lub
  248. zwolniony (dokîadniej o tym za chwilë). Niektóre rodzaje
  249. wiadomoôci w ogóle nie uûywajâ tego pola, np. IDCMP_CLOSEWINDOW.
  250.  
  251. UWORD Qualifier -- To pole zawiera nie przetworzone informacje,
  252. dostarczone przez program systemowy o nazwie input.device,
  253. zajmujâcy sië obsîugâ wejôcia/wyjôcia. Jest ono rzadko
  254. wykorzystywane. Moûna tu znaleúê np. informacje o tym, czy gdy
  255. wystâpiîo zdarzenie, byî wciôniëty lewy klawisz [Shift]
  256. (IEQUALIFIER_LSHIFT), albo czy dana cyfra zostaîa wpisana na
  257. klawiaturze numerycznej (IEQUALIFIER_NUMERICPAD) itp. --
  258. odpowiednie staîe sâ zdefiniowane w pliku "devices/inputevent.h".
  259.  
  260. APTR IAddress -- Zawiera adres obiektu, bëdâcego przyczynâ
  261. wysîania wiadomoôci, jest zaleûne od jej rodzaju, np. w wypadku
  262. wiadomoôci o gadûetach zawiera adres gadûetu.
  263.  
  264. WORD MouseX, MouseY -- Zawierajâ poîoûenie myszy w chwili
  265. wystâpienia zdarzenia, wspóîrzëdne sâ podawane wzglëdem lewego
  266. górnego rogu okna. Jeôli w polu IDCMPFlags okna byî ustawiony
  267. znacznik IDCMP_DELTAMOVE, wspóîrzëdne bëdâ podawane wzglëdem
  268. poprzednio meldowanego poîoûenia (wektor przesuniëcia).
  269.  
  270. ULONG Seconds, Micros -- Zawierajâ czas systemowy, w którym
  271. zdarzenie nastâpiîo (bardzo przydatne, gdy chcemy sprawdziê, czy
  272. miaî miejsce tzw. double-click, czyli szybkie, dwukrotne,
  273. klikniëcie myszâ).
  274.  
  275. Jak juû wczeôniej pisaliômy, wiadomoôci otrzymane od Intuition
  276. naleûy jak najszybciej zwróciê. W zwiâzku z tym najwygodniej jest
  277. skopiowaê caîâ strukturë lub tylko te pola, które nas interesujâ.
  278. Przetrzymywanie informacji od Intuition moûe wpîynâê na
  279. spowolnienie dziaîania systemu. Po wykonaniu kopii i zwróceniu
  280. wiadomoôci moûemy sië swobodnie i bez poôpiechu zastanawiaê, co
  281. poczâê dalej. Nieocenionâ pomocâ jest instrukcja "switch". Na
  282. poczâtku naleûy rozpoznaê rodzaj wiadomoôci, czyli zerknâê do
  283. pola "Class", a nastëpnie, w zaleûnoôci od jego zawartoôci,
  284. analizowaê pozostaîe pola.
  285.  
  286. W wypadku gdy otrzymamy informacjë typu IDCMP_CLOSEWINDOW, wiemy,
  287. co sygnalizuje uûytkownik -- pozostaîe pola nie zawierajâ
  288. istotnych informacji. Podobnie jest w wypadku IDCMP_DISKINSERTED
  289. i IDCMP_DISKREMOVED -- nie ma sensu patrzeê na zawartoôê
  290. pozostaîych pól (jeûeli ktoô nie pisze programu sprawdzajâcego,
  291. jak szybko moûna zmieniê dyski, wówczas potrzebne byîyby pola
  292. Seconds i Micros, ale sadyzmu nie popieramy).
  293.  
  294. Zupeînie innaczej wyglâda sytuacja z wiadomoôciami o
  295. "przyciôniëciu myszy" (IDCMP_MOUSEBUTTONS). W tym wypadku pole
  296. "Code" zawiera uûyteczne informacje:
  297.  
  298. SELECTDOWN -- wciôniëto lewy przycisk myszy,
  299.  
  300. SELECTUP -- zwolniono lewy przycisk myszy,
  301.  
  302. MENUDOWN -- wciôniëto prawy przycisk myszy,
  303.  
  304. MENUUP -- zwolniono prawy przycisk myszy,
  305.  
  306. MIDDLEDOWN -- wciôniëto ôrodkowy przycisk myszy,
  307.  
  308. MIDDLEUP -- zwolniono ôrodkowy przycisk myszy.
  309.  
  310. Wiadomoôci tej klasy docierajâ tylko do jednego okna -- do tego,
  311. które jest aktywne.
  312.  
  313. Amiga obsîuguje trzeci przycisk myszy, choê czësto go nie ma,
  314. natomiast pecety majâ go prawie zawsze, ale i tak ogromna
  315. wiëkszoôê programów uûywa tylko jednego przycisku -- lewego (dla
  316. zainteresowanych dodam, ûe w Amidze trzeci przycisk myszy naleûy
  317. podîâczyê do wyprowadzenia numer 5 oraz do masy, czyli
  318. wyprowadzenia numer 8).
  319.  
  320. Za miesiâc przedstawië wykorzystanie portu okna.
  321.