3.19. Nastavování výšky matky a otce v našem programu
Připomeňme si, jak budeme v našem programu nastavovat výšku matky a otce - budeme mít tři přepínače obsahující číslice stovek, desítek a jednotek centimetrů. Vpravo od nich budou dvě opakovací tlačítka: jedno pro zvětšení vybrané číslice a druhé pro její zmenšení.
U každé trojice přepínačů (stovky, desítky a jednotky centimetrů) je uvedeno jiné číslo skupiny. Připomeňme, že z každé skupiny přepínačů může být aktivní jen jeden. Na zprávy těchto přepínačů nemusíme nijak reagovat.
Budou nás však zajímat zprávy opakujících tlačítek pro zmenšení nebo zvětšení hodnoty. Po stisknutí jednoho z těchto tlačítek budeme muset změnit číslici ve vybraném přepínači o jedničku nahoru nebo dolů. Jednotlivé součásti programu si rozebereme podrobněji.
Pomocné funkce
V našem programu budeme používat jedinou pomocnou funkci, a to funkci Objekt(), která vrátí ukazatel na datovou strukturu objektu v závislosti na jeho jednoznačné identifikaci. Tuto funkci jsme již v této kapitole uvedli a nebudeme se jí dále zabývat.
Přepínače jsou uspořádané do skupin
V souboru prostředků aplikace při definování formuláře nesmíme zapomenout uvést u obou trojic přepínačů odlišné číslo skupiny (vlastnost GROUP). Výhodné je použít k tomu konstantu, která byla definována v hlavičkovém souboru:
FORM ID FormularHlavni AT (0 0 160 160) BEGIN ... PUSHBUTTON "" ID TlacitkoMatka100cm AT (...) GROUP SkupinaMatka PUSHBUTTON "" ID TlacitkoMatka10cm AT (...) GROUP SkupinaMatka PUSHBUTTON "" ID TlacitkoMatka1cm AT (...) GROUP SkupinaMatka ... END |
Podobně je uvedeno číslo skupiny (které má hodnotu SkupinaOtec) i u tlačítek pro zadávání výšky otce. Jako text tlačítek můžeme u všech těchto tlačítek ponechat prázdný řetězec; budeme jej nastavovat v programu sami.
Bude se měnit text přepínačů
Protože text uvedený v přepínačích (číslice) se bude měnit, musíme pro každé tlačítko deklarovat vlastní globální řetězcovou proměnnou, ve které bude uložen ukazatel na text tlačítka. Pokud hodnotu této proměnné změníme a překreslíme tlačítko (vymažeme a znovu nakreslíme funkcemi CtlEraseControl() a CtlDrawControl()), změní se i zobrazený text tlačítka.
Jména globálních proměnných budou vždy začínat malým písmenem "g". Definice těchto proměnných na začátku programu je v následujícím rámečku. Proměnným přiřazujeme počáteční hodnoty, které musí být číselné.
Char gMatka100cm[2] = "1"; Char gMatka10cm[2] = "7"; Char gMatka1cm[2] = "0"; Char gOtec100cm[2] = "1"; Char gOtec10cm[2] = "8"; Char gOtec1cm[2] = "0"; |
Na začátku programu tedy musíme nastavit ukazatel na text každého tlačítka tak, aby ukazoval na příslušnou globální proměnnou. Toto nastavení provedeme ve funkci formuláře při zpracování události frmOpenEvent voláním funkce CtlSetLabel(). Nejlepší místo pro toto nastavení je před vykreslením formuláře funkcí FrmDrawForm().
Nastavení ukazatelů na text tlačítek
Připomeňme si, že zpráva frmOpenEvent je zaslána naší aplikaci v okamžiku, kdy je formulář inicializován a připraven k vykreslení na displeji. Tuto zprávu zpracováváme ve funkci formuláře, kde na ni většinou reagujeme případnou inicializací datových struktur a poté vykreslením formuláře.
case frmOpenEvent: CtlSetLabel((ControlPtr)Objekt(TlacitkoOtec1cm), gOtec1cm); CtlSetLabel((ControlPtr)Objekt(TlacitkoOtec10cm), gOtec10cm); ... FrmDrawForm(FrmGetActiveForm()); zpracovano = true; break; |
V našem programu zavoláme při zpracování této události funkci CtlSetLabel() pro každý přepínač, jehož text budeme v měnit. V ukázce si povšimněte použití pomocné funkce Objekt(). Tato funkce vrací ukazatel na datovou strukturu objektu formuláře (v tomto případě přepínače) a její vrácenou hodnotu musíme převést na správný typ (pro přepínač je to ControlPtr).
Změna textu tlačítka
Stiskne-li uživatel jedno z opakovacích tlačítek pro změnu některé z číslic výšky, musíme vybranou číslici změnit. Tuto změnu budeme provádět ve funkci, které jako parametr předáme dvě hodnoty: označení skupiny tlačítek (jednu z konstant SkupinaOtec nebo SkupinaMatka) a hodnotu, o kolik chceme číslici změnit.
V této funkci pak musíme udělat následující:
- zjistit, které tlačítko ze skupiny je vybrané (funkcí FrmGetControlGroupSelection())
- vyzvednout ukazatel na text vybraného přepínače (funkcí CtlGetLabel())
- změnit číslici v textu přepínače
- překreslit tlačítko (funkcemi CtlEraseControl() a CtlDrawControl())
V následujícím rámečku je uvedena popsaná funkce pro změnu textu tlačítka.
static void UpravTlacitko(UInt16 skupina, Int16 pricti) { UInt16 indexTlacitka; UInt16 prvekTlacitka; Char* textTlacitka; FormPtr formular; Int16 cisloTlacitka; Boolean zmena = false; // Pokud je v teto skupine nejake tlacitko nastavene, vrati // funkce FrmGetControlGroupSelection() jeho index. formular = FrmGetActiveForm(); indexTlacitka = FrmGetControlGroupSelection(formular, skupina); // Pokud bylo nejake tlacitko ve skupine zvyraznene, muzeme // jej menit. if(indexTlacitka != frmNoSelectedControl) { // V kazdem tlacitku je ulozen ukazatel na jeho text, // ktery muzeme vyzvednout pomoci funkce CtlGetLabel(). textTlacitka = (Char*)CtlGetLabel((ControlPtr)FrmGetObjectPtr(formular, indexTlacitka)); // Provedeme zmenu textu v pameti a podle ni nastavime // promennou informujici nas o zmene hodnoty tlacitka. // Zkontrolujeme pritom, aby v tlacitku byla cislice od // nuly do devitky. cisloTlacitka = (textTlacitka[0] - '0') + pricti; zmena = (cisloTlacitka >= 0) && (cisloTlacitka <= 9); if(zmena) { textTlacitka[0] = '0' + cisloTlacitka; // Prekresleni tlacitka } } } |
Tlačítko překreslíme voláním funkce CtlEraseControl(), která jej vymaže z displeje, a funkce CtlDrawControl(), která tlačítko vykreslí s novým textem. Zkuste sami vymyslet, jak bude možné tyto funkce volat se správnými parametry (toto zadání má více řešení: zkuste nalézt alespoň dvě).
Opakovací tlačítka
Při zpracování zpráv ctlRepeatEvent, které generují opakovací tlačítka, budeme volat právě popsanou funkci UpravTlacitko(). Funkci UpravTlacitko() předáme příslušné parametry: číslo skupiny, které se změna týká, a hodnotu +1 nebo -1 podle toho, zda číslici upravujeme směrem nahoru nebo směrem dolů.
case ctlRepeatEvent: switch(udalost->data.ctlRepeat.controlID) { case OpakujOtecPlus: UpravTlacitko(SkupinaOtec, 1); break; case OpakujOtecMinus: UpravTlacitko(SkupinaOtec, -1); break; case OpakujMatkaPlus: UpravTlacitko(SkupinaMatka, 1); break; case OpakujMatkaMinus: UpravTlacitko(SkupinaMatka, -1); break; } break; |
Důležité je, že při zpracování opakujících tlačítek musí funkce formuláře vracet nulovou hodnotu, aby mohl operační systém tlačítka správně zvýrazňovat a mazat. Proto při zpracování zprávy ctlRepeatEvent nenastavujeme hodnotu proměnné zpracovano na hodnotu true.
Teď již tlačítka pro nastavování výšky matky a otce fungují tak, jak od nich očekáváme. Zde si můžete stáhnout zdrojový text i s dvěma příklady řešení překreslení přepínačů.
Příště náš program doplníme o vlastní výpočet cílové výšky - zkuste si ale sami rozmyslet, co všechno k tomu budete potřebovat a co ještě v programu postrádáte.