next up previous
Next: Záverečná lekcia alebo "Čo Up: grafika Previous: Zvukové efekty alebo "Chcelo

Dialógy alebo "Stlačte OK!"

Ak programujete hru (alebo čokoľvek iné), niekedy sa ocitnete v situácii, kedy je potrebné užívateľovi poskytnúť možnosť niečo si nastaviť. A na to je užitočné mať k dispozícii systém tlačidiel, menu, editovacích boxov a vôbec všetkých možných vymožeností, ktoré sa označujú GUI (General User Interface) a ktoré dôverne poznáte z väčšiny okienkoidných programov.

Na programovanie dialógov sa častejšie používajú objektovo orientované jazyky ako C++, Java, Delphi či Smalltalk. Knižnica Allegro ale poskytuje možnosť naprogramovať jednoduchý dialóg aj v jazyku C. V tejto lekcii sa nachádza stručný náčrt toho, ako sa to robí. Ide však o pomerne rozsiahlu tému a tak čo sa týka ďalších detailov odkazujeme čitateľa na dokumentáciu ku knižnici Allegro.

Pri tvorbe dielógu sú dôležité niektoré pojmy: Objekt je vec na obrazovke, ktorú vidíte, môžete na ňu klikať, niečo do nej písať alebo si vyberať z ponúknutých možností. Objekty sú napr. button (tlačidlo) alebo editbox. Udalosť je vec, ktorá sa môže objektu prihodiť. V systéme, ktorý používa Allegro to môže byť napríklad MSG_DRAW ktorá objektu povie, že sa má prekresliť, alebo MSG_CLICK, ktorá objektu povie, že sa na neho kliklo myšou. Rôznych udalostí je veľa a ich úplný zoznam nájdete v manuáli. Posledným dôležitým pojmom je správca udalostí (alebo message handler). Je to funkcia, ktorá má daný objekt na starosti -- ak objekt dostane správu, že sa má prekresliť, funkcia to obstará, ak dostane správu, že sa na neho kliklo, funkcia zaistí patričnú odozvu. Správcov niektorých typov udalostí už Allegro obsahuje, iných si môžete vyrobiť sami.

Každý dialóg v Allegre je reprezenvovaný poľom štruktúr typu DIALOG, ktorého posledná položka obsahuje samé nuly. Štruktúra DIALOG vyzerá takto:

typedef struct DIALOG
{
   int (*proc)(int, DIALOG *, int); - správca udalostí
   int x, y, w, h;                  - pozícia a veľkosť objektu
   int fg, bg;                      - farba popredia a pozadia
   int key;                         - ASCII klávesová skratka
   int flags;                       - príznaky stavu objektu
   int d1, d2;                      - čokoľvek, čo sa vám hodí
   void *dp, *dp2, *dp3;            - smerníky na ďálšie dáta
                                      týkajúce sa objektu
} DIALOG;

Prvá zložka štruktúry je handler daného objektu. Potom nasledujú súradnice ľavého horného rohu, šírka a výška objektu, farba popredia a pozadia, klávesová skratka (písmeno, ktoré keď stlačíte, objekt obdrží patričnú akciu), maska príznakov (tu sa dá objektu povedať, že má byť neaktívny (D_DISABLED) alebo že po stlačení tlačidla sa má celý dialóg skončiť (D_EXIT), ďalšie podrobnosti v manuáli.) Posledných päť parametrov slúži na odovzdávanie dát objektu. Napríklad reťazec, ktorý má byť napísaný v tlačidle sa uvedie ako parameter dp.

Handler objektu je funkcia, ktorá musí mať nasledovnú podobu:

  int nejaky_moj_handler(int msg, DIALOG *d, int c);
Je to teda funkcia, ktorá má tri parametre. Prvý je udalosť, ktorá volanie funkcie vyvolala, druhý je smerník na objekt, ktorého sa udalosť týka (to je užitočné zvlášť vtedy, ak je jedna funkcia handlerom viacerých objektov; vtedy si vďaka tomuto smerníku vie funkcia zistiť, kto ju vlastne volal). Tretí parameter sa týka len udalostí vyvolaných klávesnicou a momentálne sa mu nebudeme venovať. Handler podľa typu udalosti urobí to, čo má a vráti hodnotu. Táto je obyčajne D_O_K. Ak treba celý dialóg prekresliť vráti hodnotu D_REDRAW a ak jeho činnosť treba ukončiť, hodnotu D_CLOSE (sú ešte ďalšie možnosti -- znovu je odporúčané čítať manuál). Niektoré handlery už knižnica Allegro obsahuje. Sú to napríklad d_box_proc, ktorý vie nakresliť obdľžnik, d_button_proc, ktorý vie vyrobiť a spravovať tlačidlo a d_edit_proc, ktorý spravuje editovateľný riadok.

Takže toľko teória, poďme sa pozrieť, ako to všetko vyzerá v praxi.

  1   #include <allegro.h>
  2
  3   char retazec[20] = "Juchacha!";
  4   int farba = 65535;
  5
  6
  7   int tlacidielko(int msg, DIALOG *d, int c);
  8
  9
 10   DIALOG dialog[] = {
 11   /* proc,  x,  y,  w, h, fg, bg, 
 12                      key, flag, d1, d2, dp, dp2, dp3 */
 13                   
 14   {d_box_proc, 200, 100, 240, 280, 65535, 0,
 15                             0, 0, 0, 0, NULL, NULL, NULL},
 16                           
 17   {tlacidielko, 210, 110, 90, 20, 31, 0,
 18                     'c', 0, 1, 0, "&Cervena", NULL, NULL},
 19                  
 20   {tlacidielko, 330, 110, 90, 20, 2016, 0,
 21                      'z', 0, 2, 0, "&Zelena", NULL, NULL},
 22                   
 23   {tlacidielko, 275, 140, 90, 20, 65535, 0,
 24                    's', 0, 3, 0, "&Standard", NULL, NULL},
 25                 
 26   {d_edit_proc, 210, 200, 190, 20, 65535, 0,
 27        0,  0,  sizeof(retazec)-1, 0, retazec, NULL, NULL},
 28     
 29   {d_button_proc, 275, 240, 90, 20, 65535, 0,
 30                    'o', D_EXIT, 0, 0, "&OK", NULL, NULL },
 31                 
 32   {NULL,            0,   0,  0,  0,  0,  0,
 33                            0,  0, 0, 0, NULL, NULL, NULL}
 34   }; 
 35
 36
 37   int tlacidielko(int msg, DIALOG *d, int c)
 38   {
 39       if (msg == MSG_CLICK || msg == MSG_KEY)
 40       {
 41           switch (d -> d1)
 42           {
 43           case 1:
 44               clear_to_color(screen,makecol(255,0,0));
 45               farba = makecol(255,0,0);
 46               break;
 47           case 2:
 48               clear_to_color(screen,makecol(0,255,0));
 49               farba = makecol(0,255,0);
 50               break;
 51           case 3:
 52               clear_to_color(screen,makecol(128,128,128));
 53               farba = makecol(255,255,255);
 54           }
 55           return D_REDRAW;
 56       }
 57       else
 58           return d_button_proc(msg, d, c);
 59   }
 60
 61
 62   main()
 63   {
 64      allegro_init();
 65      install_keyboard();
 66      install_mouse();
 67      install_timer();
 68      set_color_depth(16);
 69      set_gfx_mode(GFX_SAFE, 640, 480, 0, 0);
 70   
 71      clear_to_color(screen,makecol(128,128,128));
 72      popup_dialog(dialog,-1);
 73      clear_to_color(screen,makecol(0,0,0));
 74      textout_centre(screen,font,retazec,320,240,farba);
 75      while(!key[KEY_ESC]);
 76   }
 77   END_OF_MAIN();
Dialóg v uvedenom príklade je definovaný na riadkoch 10-34. Prvá položka je rámik. Ako handler je použitá funkcia d_box_proc, ktorá sa stará hlavne o jeho vykreslenie. Vo vnútri rámiku budú tri tlačítka na zmenu farby (druhá, tretia a štvrtá položka poľa). Text na tlačítkach bude Cervena, Zelena a Standard. Písmená, pred ktorými je znak & (teda C,Z a S) budú podčiarknuté. Handlerom týchto tlačidiel bude funkcia tlacidielko. Táto v podstate všetku prácu zvalí na funkciu d_button_proc, iba v prípade, že sa jedná o akciu MSG_CLICK (kliknutie myšou) alebo MSG_KEY (zavolanie cez klávesovú skratku), funkcia si podľa položky d1 zistí ktoré tlačidlo ju vlastne zavolalo a podľa toho nastaví hodnotu premennej farba a celú obrazovku premaľuje. V tomto prípade musí funkcia vrátiť hodnotu D_REDRAW, aby sa premaľovaný dialóg znovu zobrazil.

Štvrtá položka dialógu je editovací riadok. Spravuje ho funkcia
d_edit_proc. V tomto riadku sa dá meniť obsah reťazca retazec. Ako prvok d1 treba uviesť maximálnu dĺžku textu (a treba pamätať aj na ukončovaciu nulu reťazca) a ako prvok dp treba uviesť smerník na reťazec, ktorý sa bude meniť.

Piata položka je tlačidlo OK. V parametri flag má uvedené D_EXIT, aby po jeho stlačení dialóg ukončil činnosť. Handler je rovno d_button_proc.

Vo funkcii main sa naštartuje a prichystá všetko možné a potom sa dialóg spustí funkciou popup_dialog. (Táto funkcia vracia index objektu, ktorý spôsobil ukončenie dialógu, teda v našom prípade 5.) Keď práca dialógu skončí, zmaže sa obrazovka a zvolenou farbou sa vypíše zvolený text. Na konci je prázdny cyklus, ktorý sa cyklí až kým niekto nestlačí klávesu ESC.

Úloha č.1 Prečítajte trikrát (najmenej, lebo je to ťažké!!!), pochopte a vyskúšajte. Čo to spraví ak vo funkcii tlačidielko vrátite miesto hodnoty D_REDRAW hodnotu D_O_K?

Úloha č.2 Doplňte ďalšie tlačítko s prefarbovaním na bledomodro.

Úloha č.3 Doplňte tlačítko Cancel po ktorého stlačení program rovno skončí.

Úloha č.4 Doplňte tesne pred koniec programu riadok

   alert("E pericoloso sporgersi",NULL,NULL,"OK",NULL,0,0);
Čo to spraví? Ako sa to zmení, ak miesto NULL nasledujúcom po "OK" vložíte "Cancel"?
next up previous
Next: Záverečná lekcia alebo "Čo Up: grafika Previous: Zvukové efekty alebo "Chcelo
Anino Belan
anino(at)smnd.sk