Úvod do programování pro PalmOS MUDr. Petr Lesný Praha 2003
První vydání
Tato kniha představuje první pokus o napsání uceleného českého úvodu do PalmOS. Je zcela zdarma; nikdo vám nebude bránit si ji přečíst nebo vytisknout. Pokud si však tuto knihu ponecháte a naučíte-li se podle ní programovat, můžete mi převést na konto u Komerční banky číslo 943115610267/0100 finanční dar odpovídající možné ceně knihy jako projev uznání téměř roční práce na této knize a podporu tvorby dalších knih o PalmOS. Jediná internetová stránka, na které smí být tato kniha umístěna je http://palmos.wz.cz. Na této stránce jsou uvedeny zdrojové texty příkladů, errata a další informace o připravovaných publikacích. MUDr. Petr Lesný
tuto knihu věnuji své ženě, bez jejíž lásky a trpělivosti bych ji nikdy nedokončil Petr Lesný
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Obsah Úvod .................................................................................................................................................8 Fenomén Palm Pilota a tato kniha............................................................................................8 Omezení operačního systému....................................................................................................8 PalmOS a Windows CE .............................................................................................................9 Základy návrhu aplikací pro PalmOS .....................................................................................9 Požadavky na čtenáře a jeho počítač......................................................................................10 Česká a anglická terminologie ................................................................................................10 Vývojová prostředí...................................................................................................................12 Instalace a vyzkoušení..............................................................................................................12 Úvod do programování systému PalmOS .....................................................................................14 Hlavičkové soubory (header files)...........................................................................................14 Základní datové typy ...............................................................................................................14 Funkce PilotMain .....................................................................................................................15 Aktivní aplikace........................................................................................................................16 Zpracování událostí..................................................................................................................16 Systémové události (events) .....................................................................................................17 Smyčka zpracování událostí....................................................................................................18 Zpracování události aplikací ...................................................................................................19 Strukturování aplikace ............................................................................................................21 Ukončení aplikace ....................................................................................................................22 Jednoznačný identifikátor aplikace (Creator ID) .................................................................22 Databáze prostředků aplikace.................................................................................................24 Soubor prostředků aplikace ....................................................................................................24 Číslo prostředku .......................................................................................................................25 Systémové informace v souboru prostředků aplikace ..........................................................25 Ikony aplikace...........................................................................................................................26 Čísla chyb v PalmOS................................................................................................................28 Překlad první aplikace...................................................................................................................29 Součásti vývojového prostředí.................................................................................................29 Překlad zdrojového textu C/C++ ............................................................................................29 Překlad souboru prostředků aplikace ....................................................................................31
3
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Překlad aplikace .......................................................................................................................32 Vyzkoušení první aplikace.......................................................................................................33 Ladění aplikace.........................................................................................................................34 Program make ..........................................................................................................................36 Soubor Makefile .......................................................................................................................37 Důležité skupiny funkcí.................................................................................................................39 Rozdělení funkcí v PalmOS.....................................................................................................39 Práce s řetězci (strings) v PalmOS..........................................................................................40 Příklad použití řetězců v PalmOS: .........................................................................................41 Operační paměť .......................................................................................................................41 Uspořádání operační paměti ...................................................................................................42 Bloky paměti (chunks) .............................................................................................................43 Nepřemístitelné bloky paměti .................................................................................................43 Přemístitelné bloky paměti......................................................................................................44 Kontrola verze operačního systému .......................................................................................45 Čísla s pohyblivou desetinnou čárkou ....................................................................................47 Uložení stavu aplikace (preferences) .....................................................................................48 Ladící hlášky v PalmOS...........................................................................................................50 Texty v souboru prostředků aplikace.....................................................................................51 Datum a čas...............................................................................................................................51 Zajímavé systémové funkce.....................................................................................................53 Základy uživatelského rozhraní ....................................................................................................54 Návrh uživatelského rozhraní .................................................................................................54 Základní prvky uživatelského rozhraní .................................................................................54 Definice v souboru prostředků aplikace.................................................................................55 Velikost a umístění na displeji.................................................................................................56 Formuláře a dialogy .................................................................................................................60 Definice formulářů ...................................................................................................................60 Zobrazení formulářů na displeji............................................................................................61 Události formuláře a funkce formuláře .................................................................................62 Přepínání mezi formuláři ........................................................................................................63 Definice dialogů ........................................................................................................................66 Použití dialogů ..........................................................................................................................67
4
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Předávání dat mezi formuláři .................................................................................................68 Výzvy (alerts) ............................................................................................................................70 Menu..........................................................................................................................................72 Systémové události menu.........................................................................................................73 Prvky formuláře a dialogu ............................................................................................................75 Přehled.......................................................................................................................................75 Definice a společné vlastnosti ..................................................................................................76 Práce s prvky dialogů a formulářů.........................................................................................78 Statický text ..............................................................................................................................80 Tlačítka......................................................................................................................................80 Políčka k zaškrtnutí a přepínače.............................................................................................80 Opakující tlačítka.....................................................................................................................83 Změna textu v tlačítku .............................................................................................................84 Tlačítko volby textu..................................................................................................................84 Seznam (List) ............................................................................................................................85 Změna obsahu seznamu...........................................................................................................87 Vyskakovací seznam (Popup list)............................................................................................88 Uživatelsky kreslený seznam ...................................................................................................88 Tlačítko volby ze seznamu.......................................................................................................89 Políčka pro vstup textu ............................................................................................................90 Stránkování pomocí opakovacích tlačítek .............................................................................93 Posuvníky ..................................................................................................................................95 Stránkování pomocí posuvníků...............................................................................................97 Spolupráce se schránkou .........................................................................................................98 Tabulky ........................................................................................................................................101 Definice v souboru prostředků aplikace...............................................................................101 Základ použití tabulek ...........................................................................................................101 Typy dat buňky.......................................................................................................................103 Obecné základy.......................................................................................................................105 Inicializace tabulky ................................................................................................................105 Aktualizace dat tabulky .........................................................................................................107 Spolupráce tabulky s posuvníkem ........................................................................................108 Stránkování tabulky pomocí hardwarových kláves............................................................109
5
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Práce se statickými buňkami pro zobrazení čísla, data a textu .........................................110 Práce s uživatelsky kreslenými buňkami .............................................................................111 Práce s buňkami obsahujícími políčka k zaškrtnutí a výběr ze seznamu.........................113 Práce s buňkami pro editaci textu ........................................................................................114 Základy grafiky............................................................................................................................117 Začínáme kreslit .....................................................................................................................117 Vykreslení textu......................................................................................................................118 Změna písma...........................................................................................................................119 Výřezy (Rectangles)................................................................................................................121 Ořezávání (clipping)...............................................................................................................122 Okna (windows)......................................................................................................................123 Souřadnice doteku pera na displeji ......................................................................................125 Neviditelná okna (offscreen windows)..................................................................................127 Rastrové obrázky (bitmaps) ..................................................................................................129 Rastrové obrázky ve formuláři .............................................................................................131 Kreslení rastrových obrázků.................................................................................................131 Databáze.......................................................................................................................................132 Ochrana databází ...................................................................................................................133 Číslo vnitřní paměťové karty ................................................................................................134 Chyby při práci s databázemi ...............................................................................................135 Vytvoření databáze ................................................................................................................135 Otevření a zavření databáze..................................................................................................136 Záznamy databáze..................................................................................................................137 Vytvoření nového záznamu ...................................................................................................138 Úsporné uložení záznamů......................................................................................................139 Čtení a zapisování do záznamů databáze.............................................................................141 Smazání záznamu a databáze................................................................................................141 Seřazení databáze ...................................................................................................................143 Vkládání záznamů do databáze ............................................................................................144 Propojení databáze s tabulkou..............................................................................................144 Závěr ............................................................................................................................................148 Příloha A: Instalace nástrojů pro vývoj......................................................................................149 Vývojové prostředí Cygwin a balík prc-tools ......................................................................149
6
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
PalmOS SDK ..........................................................................................................................153 Dokončení instalace................................................................................................................154 Příloha B: Vybrané funkce PalmOS ..........................................................................................158 Funkce pro práci s tlačítky....................................................................................................158 Funkce data.............................................................................................................................158 Databázové funkce .................................................................................................................159 Funkce pro zpracování chyb .................................................................................................166 Funkce fronty systémových událostí ....................................................................................166 Funkce políček ........................................................................................................................166 Funkce pracující s čísly v pohyblivé desetinné čárce ..........................................................168 Funkce pracující s písmy .......................................................................................................168 Funkce pro práci s formuláři ................................................................................................169 Funkce pro vlastnosti (features)............................................................................................173 Funkce pro práci se seznamy ................................................................................................173 Funkce pro správu paměti.....................................................................................................175 Funkce pro práci s menu .......................................................................................................176 Funkce pro práci s uživatelským nastavením (preferences) ..............................................177 Funkce pracující s výřezy ......................................................................................................177 Funkce pro práci s posuvníkem ............................................................................................178 Funkce pro práci s řetězci .....................................................................................................178 Systémové funkce ...................................................................................................................180 Funkce pro práci s tabulkami ...............................................................................................181 Funkce pro práci s časem ......................................................................................................186 Funkce správce oken..............................................................................................................187 Příloha C: Příklady .....................................................................................................................190 Příloha D: Seznam prvků formuláře ..........................................................................................192
7
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Úvod Fenomén Palm Pilota a tato kniha Mobilní výpočetní technika si získává stále více uživatelů. Když byly na trh uvedeny první modely kapesních počítačů Palm Pilot III, získaly si rázem mnoho oddaných příznivců. Velký zájem uživatelů o počítače s operačním systémem PalmOS trvá dodnes. Uživatele přitahuje nízká cena a jednoduché ovládání, nevadí jim černobílý displej, malé rozlišení a nepřítomnost multimediálních funkcí u starších modelů. Operační systém PalmOS je navržen velmi úsporně a jeho programování je méně náročné, než psaní aplikací pro jiná grafická prostředí, ať už se jedná o Microsoft Windows (v libovolné verzi) nebo systém X-Window. Po přečtení této knihy budete tomuto operačnímu systému rozumět a budete schopni vytvořit základní aplikaci pro počítače Palm Pilot a kompatibilní. V této knize se budeme věnovat programování kapesních počítačů s operačním systémem PalmOS do verze 4.1 a pomineme novější multimediální modely s procesorem ARM a PalmOS verze 5.0. Všechny aplikace, které navrhneme však budou kompatibilní s PalmOS 5.0. Pokročilým tématům, jako je například synchronizace s desktopem, zvuk a barevná grafika, se budeme věnovat v jiné knize.
Omezení operačního systému Prostředky, kterými disponují počítače Palm Pilot a kompatibilní jsou velmi omezené. Při jejich návrhu vycházeli konstruktéři z předpokladu, že uživatel bude používat Palm Pilot společně se stolním počítačem. Úlohy, které budou náročné na výpočet, zpracuje stolní počítač a Palm Pilot poslouží jen jako inteligentní diář a prohlížeč. Proto jako základ zvolili 16bitový procesor firmy Motorola MC68000, taktovaný na 16 MHz (pokud vzpomínáte na Atari ST a Amigu tak máte pravdu). V novějších modelech je frekvence procesoru dvojnásobná, v modelech s PalmOS 5.0 je již použit procesor ARM taktovaný na vysokých frekvencích. Místo klávesnice byl pro vstup znaků zvolen systém Graffiti (později Graffiti 2); tato změna přinesla významné snížení ceny. Zápis textů pomocí Graffiti je pomalejší než přes klávesnici, ale počítače Palm Pilot nebyly navrženy k psaní dlouhých textů. Na dělání si poznámek po cestě pak Graffiti zcela stačí. Velký důraz je kladen na ovládání pomocí dotekového displeje. Rozlišení displeje většiny počítačů Palm Pilot je 160 na 160 obrazových bodů (pixel); displej je přitom velký 5 – 6 cm. Ve většině aplikací je na displeji 6 – 11 řádků textu podle velikosti písma; text je přitom dostatečně čitelný. I při dvojnásobném rozlišení některých novějších modelů počítačů s operačním systémem PalmOS je vysoké rozlišení využito jen k lepšímu prokreslování písma a nikoliv ke zvýšení počtu řádků textu na displeji. Při posuzování kapesních počítačů podle množství operační paměti vychází modely počítačů s PalmOS (dnes průměrně 8 MB) jako chudší příbuzní. Je však potřeba vzít do úvahy, že při spuštění aplikace ji operační systém nepotřebuje kopírovat do jiné části paměti a spouští ji „na místě“. Z 8 MB paměti RAM je tak využito 512 kB pro zásobník a proměnné operačního systému a zbylých 7,5 MB je možné zcela zaplnit aplikacemi a daty. Průměrná velikost aplikace pro PalmOS se navíc pohybuje okolo 50 kB. Velký důraz je kladen na komunikaci počítačů s PalmOS s okolím. Kromě sériového a infračerveného portu je od verze PalmOS 2.0 implementována rodina protokolů TCP/IP pro komunikaci přes internet.
8
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
PalmOS a Windows CE Není možné říci, který z operačních systémů je lepší. Operační systém Windows CE a jeho nástupci (Pocket PC) představují pokus implementovat plně multitaskingový operační systém Microsoft Windows na kapesních počítačích. Paměť počítačů s Windows CE je rozdělena na operační paměť a systém souborů, uspořádaných podobně jako u verzí Microsoft Windows pro stolní počítače. Samozřejmostí je možnost přehrávat zvuk a video. To vše klade vysoké nároky na použitý procesor a na velikost operační paměti. Uživatelé kapesních počítačů s Windows CE jsou zvyklí na to, že kapesní počítač slouží k prohlížení a editaci dokumentů pořízených v programech Microsoft Word a Microsoft Excel. Kapesní počítač se pro ně stává „zmenšenou verzí stolního počítače“ a jsou na něj kladeny podobné nároky. Počítače s operačním systémem PalmOS do verze 4.1 nejsou určeny pro multimediální aplikace. Na prvním místě při návrhu aplikací stojí jednoduchost, rychlost reakce a úsporné ovládání, nároky na paměť a rychlost procesoru jsou výrazně menší. Spektrum uživatelů těchto počítačů se rekrutuje z lidí, kteří potřebují mít při ruce kapesní počítač, na kterém ocení jednoduchost použití a možnost komunikace s okolím. Uživatelé počítačů Palm Pilot a kompatibilních neočekávají na svých počítačích rozsáhlé balíky aplikací a kapesní počítač považují spíše za elektronický diář a chytrou kalkulačku. Ocení naopak robustnost a spolehlivost aplikací a úsporné uložení dat. Můžeme říci, že oba dva systémy, PalmOS a Windows CE si zatím konkurují jen zcela okrajově. Zlehčeně lze říct, že bude-li uživatel chtít kapesní diář s funkcemi počítače, sáhne po Palm Pilotech a kompatibilních počítačích; pokud bude chtít kapesní počítač s funkcemi diáře, koupí si pravděpodobně stroj s Windows CE.
Základy návrhu aplikací pro PalmOS Z předchozích několika odstavců vyplývá, co všechno musí vzít programátor do úvahy při návrhu aplikací pro PalmOS. • Velikost displeje. Z hlediska návrhu uživatelského rozhraní je třeba stále počítat s displejem velikosti 160 * 160 obrazových bodů. Pokud budete místo na displeji používat rozumně tak zjistíte, že je ho dostatek. Vhodné je, rozmyslet si návrh uživatelského rozhraní tak, aby uživateli byly informace prezentovány v logických celcích. Návrhu uživatelského rozhraní se budeme podrobně věnovat ve čtvrté kapitole. • Rychlost reakce. Při používání stolního počítače je většina uživatelů zvyklá na pomalý start některých aplikací. Málokterý z nich by však podobné zdržení toleroval při práci s kapesním počítačem. Zejména u počítačů Palm Pilot a kompatibilních uživatel očekává, že bezprostředně po každé akci – ať už je to spuštění aplikace nebo stisknutí tlačítka – následuje odpovídající reakce. • Omezení vstupu textu. Psaní dlouhých textů nebo zadávání číslic pomocí Graffiti je nepohodlné. Uživateli je nutné co nejvíce zjednodušit zadávání dat – například pomocí výběru ze seznamu, numerické klávesnice zobrazené na displeji a podobně. • Nedostatek paměti. Vždy je potřeba postupovat tak, aby množství paměti, které zabere aplikace a její databáze bylo co nejmenší. Toto pravidlo platí i při návrhu aplikací pro nejnovější modely s velkou operační pamětí. Spíše je dobré omezit funkce aplikace na nezbytné minimum, aby se zachovaly malé nároky na operační paměť. • Kompatibilita. Již při návrhu aplikace je třeba si uvědomit, které vlastnosti operačního systému potřebuje aplikace ke své činnosti. Vzhledem k velmi dobré zpětné kompatibilitě jednotlivých modelů je nejlepší navrhovat aplikaci pro nejnižší verzi operačního systému, která již obsahuje požadované vlastnosti. 9
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
S rychlostí reakce souvisí ukládání stavu aplikace. Na počítačích vybavených operačním systémem PalmOS je vždy právě jedna aplikace v popředí. Tato aplikace komunikuje s uživatelem. V okamžiku, kdy ji uživatel opustí (například stiskem hardwarového tlačítka) musí aplikace v popředí rychle uložit svůj stav, aby se uživatel mohl později vrátit k rozdělané práci. Ukládání stavu aplikace se budeme věnovat ve čtvrté kapitole.
Požadavky na čtenáře a jeho počítač Čtenář této knihy by měl mít základní znalosti jazyka C nebo C++. Nemusí se však orientovat v programování Microsoft Windows ani jiného stávajícího operačního systému. V ideálním případě by čtenář měl být schopen dohledat chybějící informace v anglicky psaných manuálech. Pro programování počítačů s operačním systémem PalmOS je zapotřebí vlastnit stolní počítač s Windows 98/NT/2000 nebo operačním systémem UNIX/Linux. Instalace vývojového prostředí podle přílohy A zabere na harddisku 60 – 100 MB. Aplikace pro Palm Piloty a kompatibilní počítače je možné testovat v simulátoru na stolním počítači. Přesto se vyplatí mít alespoň jeden počítač s PalmOS, čím novější tím lepší – nejlépe PalmV nebo novější model.
Česká a anglická terminologie Každý autor české knihy o počítačích je postaven před nelehký úkol vypořádat se s anglickou terminologií. Nejjednodušší cestou je důsledně přejímat anglickou terminologii (což vede například k podivně znějící frázi „uložíme jako feature“). Druhá možnost je zavedení terminologie vlastní, české. V této knize bude česká terminologie použita pro většinu pojmů, se kterými se setkáme. Za prvním výskytem českého termínu bude vždy uveden v závorce jeho anglický překlad, který je nezbytný k tomu, aby uživatel mohl vyhledávat v anglické dokumentaci. Několik základních termínů, které budeme v knize používat shrnuje následující tabulka: Česky Databáze
Anglicky Database
Databáze prostředků aplikace
Resource database
Soubor prostředků aplikace
Resource file
Databáze záznamů
Record database
Popis Soubor jednotlivých záznamů v paměti Palm Pilota. Databáze se dělí na databáze prostředků aplikace, které obsahují zejména spustitelné programy pro PalmOS a databáze záznamů, které obsahují vlastní data. Struktura uložená v paměti Palm Pilota, která obsahuje jednotlivé prostředky aplikace – tj. části spustitelné aplikace (instrukce strojového kódu, definici uživatelského rozhraní, ikony a obrázky). Na stolním počítači jsou databáze prostředků aplikace uloženy v souborech s příponou *.prc. Textový soubor, který obsahuje popis uživatelského rozhraní, textové řetězce, konstanty a obrázky, které aplikace využívá ke své funkci. Soubor záznamů, uložený v paměti Palm Pilota, který obsahuje data aplikace. Tato data jsou na stolním počítači uložena v souborech s příponou *.pdb.
10
Úvod do programování PalmOS Záznam
Record
Událost
Event
Menu
Menu
Okno
Window
Formulář
Dialog
Form
Dialog
MUDr. Petr Lesný, 2003 Databáze je sestavena ze záznamů. Záznamy jsou řazeny za sebou a každý záznam má své pořadí a své jedinečné číslo, které jej v databázi identifikuje. Zpráva, kterou zasílá operační systém aplikaci. Některé zprávy jsou zasílány jako odpověď na akce uživatele – například dotek perem na displeji, vstup znaku; jiné události (zprávy) zasílá systém aplikaci aby ovlivnil její chování – třeba příkaz k ukončení aplikace. Nabídka, která se zobrazí po stisknutí levého dolního tlačítka nebo po ukázání na titulek formuláře.
Pravoúhlý výřez displeje, který je na nejnižší úrovni používán k vykreslení prvku uživatelského rozhraní apod. Základní okno je velké 160 * 160 obrazových bodů a zabírá celý displej Palm Pilota. Další okna můžeme na displeji vytvářet my. Základní prvek uživatelského rozhraní Palm Pilota. Na displeji musí být vždy zobrazen formulář, který obsahuje prvky uživatelského rozhraní (tlačítka, políčka pro vstup textu, tabulky a podobně). Grafická podoba formulářů je definována v souboru prostředků aplikace.
Dotaz na vstupní data, který se objevuje „nad“ formulářem a který musí uživatel potvrdit nebo zrušit stisknutím některého z tlačítek. Dialog je definován v souboru prostředků aplikace stejně, jako formulář (liší se tím, že u definice dialogu je použito klíčové slovo MODAL, které způsobí odlišný vzhled dialogu). Také grafická podoba dialogu je definována v souboru prostředků aplikace.
11
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Výzva
Alert
Jednoduché varování nebo informace, kterou musí uživatel potvrdit.
Řetězec
String
Pole znaků, ukončených znakem ‘\0‘.
Vývojová prostředí Oficiálním vývojovým prostředím pro počítače Palm Pilot a kompatibilní je CodeWarrior pro PalmOS firmy Metrowerks (www.metrowerks.com). V tomto – velmi komfortním – vývojovém prostředí byl napsán celý operační systém PalmOS a vytvořeny všechny aplikace uložené v paměti ROM. Nevýhodou tohoto vývojového prostředí je jeho cena, která se pohybuje v řádu stovek dolarů. Pro zájemce nabízí firma Metrowerks ke stažení testovací verzi vývojového prostředí, která však do každé aplikace vloží varování, že aplikace nesmí být distribuována. Programování v Metrowerks CodeWarrior je pohodlné, ale natolik odlišné od použití bezplatných (freeware) programovacích nástrojů, že nemá smysl se s ním učit zacházet, pokud nemáte 600 dolarů na koupi plné verze. Vzhledem k vysokému zájmu technicky zdatných uživatelů o počítače Palm Pilot a kompatibilní se na internetu záhy objevil volně dostupný balík aplikací prc-tools. Jednalo se o standardní GNU kompilátor jazyka C/C++, který byl upraven pro vytváření aplikací pro procesory Motorola 68000. Balík aplikací prc-tools je šířen v licenci GPL (GNU general public licence), jejíž český překlad si můžete přečíst na adrese http://www.gnu.cz/gplcz. Stručný výtah z licenčních podmínek je následující: je-li program šířen pod licencí GPL, můžete jej používat zdarma a bez jakéhokoliv omezení k čemukoliv, včetně psaní komerčních aplikací. Společnost 3Com, která v té době produkovala počítače Palm Pilot, začala prc-tools neoficiálně podporovat a psaní aplikací pro PalmOS se stalo oblíbenou zábavou mnoha programátorů. Vzhledem k jednoduchosti programování jsou dnes na internetu tisíce freeware aplikací pro počítače Palm Pilot a kompatibilní, vytvořených pomocí prc-tools. Z počáteční experimentální podoby se balík prc-tools vyvinul až do současné verze 2.2, kterou můžete instalovat podle přílohy A. Tato verze umí nejen komfortně překládat aplikace pro operační systém PalmOS, ale poradí si i s programováním procesoru ARM počítačů s PalmOS 5.0. Pro použití prc-tools musíte mít na počítači nainstalováno volně dostupné vývojové prostředí Cygwin, jehož instalaci si popíšeme v příloze A.
Instalace a vyzkoušení Instalace vývojového prostředí z přiloženého CD ROM je podrobně popsána v příloze A této knihy. Po instalaci restartujte počítač a klikněte na ikonu označenou Cygwin, kterou instalační program umístil na desktop. Mělo by se objevit okno, ve kterém můžete zadávat příkazy. Zkuste spustit některé z programů, které jsou součástí instalovaného vývojového prostředí. Zadejte postupně příkazy, které jsou tučně uvedeny v následujícím rámečku. 12
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
$ palmdev-prep Checking SDKs in /PalmDev sdk-4 headers in 'include', libraries in 'lib' sdk-5 headers in 'include', libraries in 'lib' When GCC is given no -palmos options, SDK '5' will be used by default Writing SDK details to target specs files... ...done $ m68k-palmos-gcc -v Reading specs from /usr/lib/gcc-lib/m68k-palmos/2.95.3-kgpd/specs Reading specs from /usr/lib/gcc-lib/m68k-palmos/specs gcc version 2.95.3-kgpd 20010315 (release) $ pilrc –v PilRC v2.8 patch release 6 Copyright 1997-1999 Wes Cherry (
[email protected]) Copyright 2000-2001 Aaron Ardiri (
[email protected]) This program is free software; you may redistribute it under the terms of the GNU General Public License. This program has absolutely no warranty, you use it AS IS at your own risk. usage: pilrc {
} infile [outfiledir] ...
Pokud se po spuštění programů palmdev-prep, m68k-palmos-gcc a pilrc zobrazí text podobně jako v uvedeném rámečku, jsou všechny aplikace pro překlad správně instalovány.
13
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Úvod do programování systému PalmOS Hlavičkové soubory (header files) Hlavičkové soubory (header files) pro operační systém PalmOS verze 5.0 jsme v předchozí kapitole nainstalovali do adresáře C:\cygwin\PalmDev\sdk-5\include. V tomto adresáři by se měl vyskytovat soubor PalmOS.h, což je jediný hlavičkový soubor, který musíte vložit na začátek vaší aplikace pro PalmOS: #include <PalmOS.h>
Soubor PalmOS.h zajistí vložení všech základních definic z dalších hlavičkových souborů. Jednak ze souboru PalmTypes.h, ve kterém jsou definovány základní datové type a jednak ze souborů, které se nachází ve vnořených adresářích Core\System a Core\UI. V adresáři Core\System se nachází definice jednotlivých součástí operačního systému: například v souboru MemoryMgr.h (zkratka z Memory Manager API) jsou uvedeny funkce pracující s pamětí. Podobně se v adresáři Core\UI nachází definice struktur a funkcí pro součásti uživatelského rozhraní.
Základní datové typy Vzhledem k přenositelnosti aplikací mezi jednotlivými vývojovými prostředími je doporučeno využívat místo standardních datových typů jazyka C/C++ (int, char) výhradně datové typy definované v souboru PalmTypes.h. Tyto datové typy jsou přehledně shrnuty v následujících dvou tabulkách:
1bytová 2bytová 4bytová
Celá čísla se znaménkem Int8 Int16 Int32
Boolean Coord Err MemPtr MemHandle LocalID
Velikost 1bytová 2bytová 2bytová 4bytová 4bytová 4bytová
Celá čísla bez znaménka UInt8 UInt16 UInt32
Znaky Char Wchar
Popis Logické hodnoty true a false. Označení souřadnic na displeji. Číslo chyby. Ukazatel (pointer) do paměti (obdoba void* v C/C++) Ovladač pohyblivého bloku paměti. Ovladač databázového záznamu.
V hlavičkových souborech je také definováno mnoho strukturovaných datových typů. Ve většině případů začíná jméno struktury velkým písmenem a končí ...Type. Ukazatel na tuto strukturu pak končí namísto toho písmeny ...Ptr (například EventType a EventPtr).
14
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce PilotMain Vstupním bodem vašeho programu (podobně jako je v jazyce C/C++ funkce main) je při psaní aplikací pro PalmOS funkce PilotMain. Operační systém volá tuto funkci když uživatel spustí aplikaci dotekem pera na ikoně nebo hardwarovým tlačítkem. Funkce PilotMain je volána i v řadě jiných případů: například když si uživatel přeje najít nějaká data pomocí globálního vyhledávání, jsou postupně spuštěny všechny aplikace (jsou volány funkce PilotMain všech aplikací) a dostanou možnost přidat do seznamu nalezených záznamů svá data. Podobně když uživatel změní čas nebo datum tak jsou volány všechny aplikace (funkce PilotMain všech aplikací) a dostanou možnost na tuto změnu zareagovat. V parametru cmd je funkci PilotMain předán důvod spuštění aplikace (launch code). Několik možných důvodů spuštění aplikace je v následující tabulce; v této knize se budeme zabývat pouze prvním z nich, který označuje normální spuštění aplikace: Důvod spuštění sysAppLaunchCmdNormalLaunch
sysAppLaunchCmdExgAskUser
sysAppLaunchCmdExgReceiveData sysAppLaunchCmdSyncNotify sysAppLaunchCmdSystemReset sysAppLaunchCmdTimeChange
Význam Normální start programu způsobený tím, že uživatel spustil program ukázáním na jeho ikonu, přes klávesovou zkratku nebo pomocí hardwarového tlačítka. Takto je aplikace spuštěna, když prostřednictvím infračerveného spojení nabídne druhý počítač objektová data (beaming). Podle hodnoty, kterou funkce PilotMain() vrátí jsou pak data buď přijata nebo odmítnuta. Funkce PilotMain() je spuštěna protože jsou prostřednictvím infračerveného spojení přijata data určená pro aplikaci. Aplikace je volána po skončení procedury HotSync, protože byla změněna její data. S tímto kódem jsou volány všechny aplikace před restartem systému. Funkce PilotMain() je volána při změně systémového data a času.
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { if(cmd == sysAppLaunchCmdNormalLaunch) { // Příkaz ke spuštění aplikace } }
return 0;
Pro většinu našich aplikací postačí, budeme-li testovat parametr cmd a při jakémkoliv jiném důvodu spuštění než sysAppLaunchCmdNormalLaunch funkci ukončíme. Pokud vše proběhlo bez chyb, vrátí funkce PilotMain nulovou hodnotu; jakákoliv jiná hodnota bude interpretována jako číslo chyby (o číslech chyb více v této kapitole). 15
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Aktivní aplikace Na počítačích vybavených operačním systémem PalmOS může být v každém okamžiku spuštěna právě jedna aplikace. Při používání Palm Pilota to sice vypadá, jako bychom se mohli mezi jednotlivými aplikacemi přepínat, ale to je jen zdání, vyvolané tím, že dobře napsaná aplikace ukládá do paměti stav, ve kterém jsme ji opustili a při svém spuštění se k němu vrací. Pokud tedy máte spuštěný MemoPad a stisknete tlačítko spouštějící aplikaci DateBook dojde k následující posloupnosti akcí: 1. 2. 3. 4. 5. 6.
Aplikace MemoPad dostane příkaz skončit, … takže uloží rozepsaný text, pozici kursoru a kategorii … a skončí. Je spuštěna aplikace DateBook, … proto zkontroluje uložený stav, aby měl uživatel pocit rozdělané práce … a zobrazí rozdělanou práci.
Mechanismem, který zajišťuje ukončení aplikace jsou systémové události (events), které operační systém PalmOS zasílá aktivní aplikaci. Aktivní aplikace si vybírá, které systémové události zpracuje a které bude ignorovat.
Zpracování událostí Většina programů potřebuje komunikovat jak s uživatelem tak s operačním systémem. V operačním systému PalmOS je tato komunikace vyřešena prostřednictvím tzv. systémových událostí (events). Použití systémových událostí si probereme na příkladu komunikace s uživatelem. Dejme tomu, že uživatel stiskne pravé hardwarové tlačítko a spustí aplikaci MemoPad. Z hlediska operačního systému a aplikací se stane následující: 1. Operační systém čeká ve smyčce zpracování událostí co se stane (a při tomto čekání má velice malé nároky na baterie). 2. Uživatel stiskne hardwarové tlačítko. 3. Operační systém vytvoří systémovou událost keyDownEvent (která znamená, že byl napsán znak, stisknuto hardwarové tlačítko apod.) a zašle ji právě aktivní aplikaci. 4. Aktivní aplikace tuto zprávu ignoruje (pokud se nejedná například o hru, která je ovládána hardwarovými tlačítky a která zpracovává jejich události). 5. Zpráva se vrátí operačnímu systému jako nezpracovaná. Operační systém dospěje k názoru, že v takovém případě je potřeba spustit aplikaci MemoPad. 6. Operační systém pošle aktivní aplikaci systémovou událost appStopEvent (příkaz k ukončení aplikace). 7. Aktivní aplikace tuto událost povinně zpracuje a skončí (opustí funkci PilotMain). 8. Operační systém spustí funkci PilotMain aplikace MemoPad. 9. Operační systém zase čeká ve smyčce zpracování událostí (tentokrát aplikace MemoPad) na to, co se stane. Komunikace s uživatelem prostřednictvím zpracování událostí je pro operační systém velmi výhodná. Nejvíce času stráví uživatel prohlížením informací na displeji a v této době operační systém pouze čeká až se něco stane – až uživatel napíše znak Graffiti, dotkne se displeje nebo stiskne hardwarové tlačítko. Při tomto čekání je procesor v režimu s velmi malými nároky na baterie. 16
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Systémová událost je pak zaslána té aplikaci, která je právě aktivní - která právě komunikuje s uživatelem a jejíž data jsou zobrazena na displeji. (Připomeňme si, že v každém okamžiku je na Palm Pilotu aktivní pouze jedna aplikace.) Aktivní aplikace se poté postará o zpracování této události. Popisovaný princip je velmi jednoduchý. Vyžaduje však, aby byly všechny vaše aplikace vystavěny na podobném základě. Srdcem každého programu musí být takzvaná smyčka zpracování událostí, ve které zpracováváme zprávy o systémových událostech, které byly naší aplikaci doručeny operačním systémem. Pokud aplikace přestane zpracovávat události, dojde k „zatuhnutí“ počítače a nutnosti jej restartovat. Operační systém PalmOS udržuje zprávy o událostech ve frontě, do které se na jedné straně zprávy postupně ukládají a na straně druhé jsou aktivní aplikací nebo operačním systémem postupně a různě rychle odebírány. (PalmOS ve skutečnosti udržuje fronty dvě: první pro pohyb pera po plošce Graffiti, který generuje mnoho událostí, a druhou pro všechny ostatní události systému).
Systémové události (events) Systémová událost je uložena v datové struktuře EventType. V této struktuře je uložen jednak typ systémové události (příkaz k ukončení aplikace, oznámení o stisknutí tlačítka) a jednak upřesňující údaje. Zjednodušená definice této datové struktury je (kompletní definici naleznete v souboru Core\UI\Event.h): typedef struct EventType { // datové prvky společné pro všechny systémové události eventsEnum eType; ... Int16 screenX; Int16 screenY; // datové prvky specifické pro tu kterou událost union { struct frmOpen { UInt16 formID; }; struct ctlSelect { UInt16 controlID; struct ControlType *pControl; Boolean on; }; ... } data; } EventType; typedef EventType *EventPtr;
17
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
V prvku eType je uložen kód systémové události; údaje, které jsou pro událost specifické, jsou uloženy v datové struktuře data typu union. K těmto údajům můžeme přistupovat například takto: EventType udalost; typ = udalost.eType; id = udalost.data.frmOpen.formID; id = udalost.data.ctlSelect.controlID;
Kompletní seznam systémových událostí naleznete v referenční příručce k operačnímu systému PalmOS. V další kapitole naší knihy se budeme věnovat systémovým událostem, které pro nás budou důležité z hlediska programování uživatelského rozhraní. Následující tabulka obsahuje příklad důležitých systémových událostí, které nás budou v knize provázet: Kód události appStopEvent
nilEvent
penDownEvent penMoveEvent penUpEvent menuEvent
Popis Příkaz k ukončení aplikace. Tuto systémovou událost musí povinně zpracovat každá aplikace. Tato zpráva je poslána naší aplikaci když vyprší časový interval předaný funkci EvtGetEvent a nestalo se nic jiného. Spuštění pera na displej, pohyb perem po displeji a zvednutí pera z displeje. Tyto systémové události většinou zpracovává operační systém PalmOS. Uživatel vybral příkaz z menu.
ctlSelectEvent
Uživatel stiskl tlačítko nakreslené na displeji.
keyDownEvent
Uživatel zapsal znak Graffiti nebo stisknul hardwarové tlačítko. Požadavek na zobrazení formuláře.
frmLoadEvent
Upřesňující údaje
V prvcich screenX a screenY je poloha pera na displeji nebo na plošce pro zápis Graffiti. Identifikátor vybraného příkazu je uložen v prvku data.menu.itemID. Identifikátor stisknutého tlačítka je uložen v prvku data.ctlSelect.controlID. V prvku data.keyDown.chr je ASCII kód zapsaného znaku. V prvku data.frmLoad.formID je uložen identifikátor formuláře, který je potřeba zobrazit na displeji.
Smyčka zpracování událostí Smyčka zpracování událostí je povinnou součástí každé aplikace. V této smyčce čeká naše aplikace na systémovou událost (funkce EvtGetEvent) a po jejím přijetí tuto událost nejprve 18
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
nabídne ke zpracování operačnímu systému (funkce SysHandleEvent) a poté ji zpracuje sama. Druhý parametr funkce EvtGetEvent udává dobu v setinách sekundy, po kterou bude funkce EvtGetEvent na událost čekat (konstanta evtWaitForever znamená, že bude čekat neomezeně dlouho). Druhá nejjednodušší funkce PilotMain, která již obsahuje smyčku zpracování událostí, vypadá takto (příklad 1): UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { EventType udalost; if (cmd == sysAppLaunchCmdNormalLaunch) { // Toto je smyčka zpracování událostí do {
EvtGetEvent(&udalost, evtWaitForever); if(!SysHandleEvent(&udalost)) { // Událost může zpracovat naše aplikace }
} while(udalost.eType != appStopEvent); } }
return 0;
Pokud tuto aplikaci přeložíme a spustíme, tak se po doteku perem na ikoně displej vymaže a neděje se nic. Pokud stiskneme tlačítko pro návrat do správce aplikací nebo hardwarové tlačítko tak naší aplikaci korektně opustíme.
Zpracování události aplikací Už víme, že hlavní součástí naší aplikace bude smyčka zpracování událostí a uvedli jsme si nejjednodušší příklad, ve kterém jsme systémové události jenom předávali operačnímu systému. Nyní musíme do naší aplikace doplnit vlastní zpracování událostí. V následující kapitole si ukážeme, jak je vytvářeno uživatelské rozhraní. Zjednodušeně lze říci, že v každém okamžiku je na displeji umístěn jeden formulář (form), který obsahuje prvky uživatelského rozhraní. Jedna aplikace může obsahovat více formulářů. Například vestavěná aplikace MemoPad obsahuje formuláře dva: (1) seznam poznámek a (2) text jedné poznámky. Pro každý z formulářů je ve zdrojovém kódu programu definována funkce formuláře, která se jednoduše stará o zpracování systémových událostí, které generují prvky uživatelského rozhraní formuláře – například stisknutí tlačítka ve formuláři se seznamem poznámek vede k vytvoření nové poznámky a zobrazení formuláře pro její úpravu.
19
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Zpracování událostí v aplikaci probíhá následujícím způsobem: pokud se nejedná o systémovou událost, která ovlivňuje chování aplikace jako celku (třeba konec aplikace) tak je zpráva předána přímo funkci formuláře, který je zobrazen na displeji. Výjimku tvoří přepínání mezi formuláři, které musí být ošetřeno centrálně. Funkce formuláře zpracovává systémové události, ke kterým došlo v době, kdy byl formulář zobrazen na displeji. Většinou se jedná o reakci na činnosti uživatele – stisknutí tlačítek, výběr kategorie nebo zapsání znaku. Smyčka zpracování událostí 90% aplikací pro PalmOS vypadá podobně jako na následujícím příkladu: void ZpracovaniUdalosti() { EventType udalost; Err chyba; do { EvtGetEvent(&udalost, evtWaitForever); if(!SysHandleEvent(&udalost)) { if(!MenuHandleEvent(NULL, &udalost, &chyba)) { if(udalost.eType == frmLoadEvent) { NahrajFormular(udalost.data.frmLoad.formID); } else { FrmDispatchEvent(&udalost); } } }
} while(udalost.eType != appStopEvent); }
Funkce SysHandleEvent zpracuje systémové události (například přeloží tah perem na plošce Graffiti na událost vstupu znaku) a funkce MenuHandleEvent se stará o ošetření událostí, které vytváří a zpracovává uživatelská nabídka (menu). Pokud ani jedna z těchto funkcí událost nezpracovala, dostává příležitost naše aplikace.
20
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
V takovém případě nejprve testujeme, zda se nejedná o důležitou zprávu frmLoadEvent, která představuje požadavek na zobrazení jiného formuláře. Pokud ano, nahrajeme nový formulář . Všechny ostatní události posíláme pomocí funkce FrmDispatchEvent aktivnímu (právě zobrazenému) formuláři nebo dialogu.
Strukturování aplikace Kdybychom nechali všechny příkazy ve funkci PilotMain, ztratil by náš program přehlednost. Proto se ve většině programů setkáte s rozdělením činnosti aplikace do více funkcí; tyto funkce tvoří „jádro zdrojového kódu“ a zůstávají stejné, program od programu. UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { if (cmd == sysAppLaunchCmdNormalLaunch) { Err chyba; if((chyba = ZacatekProgramu()) != 0) { return chyba; } ZpracovaniUdalosti(); KonecProgramu(); } }
return 0;
Ve funkci ZacatekProgramu provedeme základní kroky inicializace, načtení uloženého stavu aplikace; pokud tato funkce vrátí nenulovou hodnotu (číslo chyby), je aplikace ukončena. Ve funkci ZacatekProgramu také vybereme první zobrazený formulář funkcí FrmGotoForm. Data a stav aplikace uložíme ve vlastní funkci KonecProgramu, ve které zavoláme funkci FrmCloseAllForms pro uzavření všech formulářů naší aplikace, které zůstaly inicializovány. Err ZacatekProgramu() { inicializace
}
if(inicializace proběhla správně, je dostatek paměti apod.) { FrmGotoForm(první zobrazený formulář); return 0; } return nenulové číslo chyby.
void KonecProgramu() { FrmCloseAllForms(); }
ulož nastavení
21
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Zpracování systémových událostí je pro lepší orientaci v kódu v samostatné funkci ZpracovaniUdalosti, kterou jsme si již uvedli. Mechanismus prohazování formulářů je v některých aplikacích pomocí výběru z tabulky, někde je definována vlastní funkce ApplicationHandleEvent, která ošetřuje události významné pro aplikaci jako celek (většinou opět pouze výměnu formulářů).
Ukončení aplikace Na základě znalosti zpracování událostí v operačním systému PalmOS bychom již měli vědět, jak napsat funkci, která ukončí právě běžící program (jinak, než přepnutím do jiné aplikace). Provedeme to tak, že do fronty událostí sami zařadíme událost appStopEvent pomocí funkce EvtAddEventToQueue. void VyvolejKonecAplikace() { EventType udalost; MemSet(&udalost, sizeof(EventType), 0); udalost.eType = appStopEvent; EvtAddEventToQueue(&udalost); }
Jednoznačný identifikátor aplikace (Creator ID) Každá aplikace pro Palm Pilota má přiřazeno vlastní unikátní 32bitové číslo (to je ona jednoznačná identifikace), které ji odlišuje od ostatních. Pokud na Palm Pilota instalujete aplikaci, která má stejný jednoznačný identifikátor jako starší aplikace, která už je přítomna, tak je stará aplikace nahrazena tou novější. Různé verze aplikace mohou mít stejný jednoznačný identifikátor a je to velmi výhodné - instalujete-li novější verzi, je stará automaticky přemazána. 32bitová hodnota jednoznačného identifikátoru bývá většinou vyjadřována jako čtyřpísmenná hodnota: #define CREATOR_ID ‘NECO’
Tento jednoznačný identifikátor označuje i bloky v paměti, databáze a uživatelské nastavení, které aplikace uložila. Smažete-li proto na Palm Pilotovi aplikaci, jsou automaticky smazána i všechna její data. Tento systém je výhodný z hlediska správy aplikací operačním systémem, programátorům však komplikuje život tím, že si musí svůj jednoznačný identifikátor registrovat na webových stránkách společnosti Palm, Inc., která zdarma archivuje a přiděluje tyto jednoznačné identifikace na internetové adrese http://www.palmos.com/dev/tech/palmos/creatorid nebo http://dev.palmos.com/creatorid/reg.cfm. Formulář pro registraci nového jednoznačného identifikátoru aplikace vypadá takto:
22
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Pro všechny aplikace popsané v této knize již byl registrován jednoznačný identifikátor 'NECO'; proto už nemusíte pro programy z této knihy žádné další své jednoznačné identifikace registrovat. Z toho že mají všechny v knize popsané aplikace stejnou jednoznačnou identifikaci však mimo jiné vyplývá, že pokud tuto hodnotu u některé z aplikací v této knize nezměníte, tak můžete mít na svém Palm Pilotovi pouze jednu z těchto ukázkových aplikací. Jednoznačné identifikace, ve kterých jsou použita pouze malá písmena anglické abecedy jsou vyhrazeny pro vývojáře společnosti Palm, Inc.. Některé známější programy mají (pro vaší informaci) registrovány následující jednoznačné identifikace:
23
Úvod do programování PalmOS
Jednoznačný identifikátor aplikace ‘CZcz’ ‘QEDi’ ‘LSdb’ ‘NECO’
MUDr. Petr Lesný, 2003
Aplikace Čeština GNU. Textový editor QEd. List (freewarová databáze). Všechny programy v této knize.
Databáze prostředků aplikace Soubor s příponou *.prc, uložený na stolním počítači, obsahuje databázi prostředků aplikace. Soubor je při instalaci zkopírován do paměti Palm Pilota. V tomto souboru je uloženo vše, co aplikace potřebuje ke spuštění na počítačích Palm Pilot, zejména: • Vlastní strojový kód aplikace která bude spuštěna, a data pro inicializaci globálních proměnných, přeložený ze zdrojových souborů jazyka C/C++ pomocí překladače m68k-palmos-gcc. • Základní údaje o aplikaci: jméno, jednoznačná identifikace aplikace (Creator ID), verze aplikace a ikony, které budou zobrazeny ve správci aplikací. Tyto údaje jsou definovány v souboru prostředků aplikace a překládány programem pilrc. • Definici prvků uživatelského rozhraní – formuláře, obrázky, nápověda atd. Uživatelské rozhraní je definováno v souboru prostředků aplikace a překládáno programem pilrc. K vytvoření databáze prostředků aplikace slouží program build-prc, který poskládá výstup z překladače jazyka C/C++ a přeložený soubor prostředků aplikace a vytvoří výsledný soubor s příponou *.prc. V databázi prostředků aplikace je každý prostředek aplikace (ikona, strojový kód aplikace, nápověda) jednoznačně popsán dvěma údaji: typem a číslem. Typ prostředku aplikace je 32bitová konstanta, vyjadřovaná často jako čtyři písmena (například ‘tAIB’ je typ označující ikonu, typ ‘code’ označuje strojový kód aplikace). Kromě typu má každý prostředek přidělen i své 16bitové číslo; toto číslo slouží k rozlišení jednotlivých prostředků stejného typu.
Soubor prostředků aplikace Již několikrát jsme uvedli, že uživatelské rozhraní aplikace a základní informace o aplikaci jsou popsány v souboru prostředků aplikace. Soubor prostředků aplikace je jednoduchý textový soubor, který můžeme editovat buď přímo v textovém editoru nebo v některém programu pro grafický návrh uživatelského rozhraní (z freeware produktů doporučuji například program pilrcedit). Na začátek si uvedeme jednoduchý příklad souboru prostředků aplikace: // Soubor prostředků aplikace, který vytvořil Petr Lesný 2003 // // Komentáře jsou uvozeny podobně jako v jazyce C++ #include „aplikace.h“ APPLICATIONICONNAME ID 1000 "Priloha" VERSION ID 1000 "1.0" APPLICATION ID 1000 "NECO" ICON "ikona.bmp"
24
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Definice nejjednoduššího formuláře FORM ID HlavniFormular AT (0 0 160 160) BEGIN TITLE "Priloha" END
Soubor prostředků aplikace je čten po řádcích; prázdné řádky a řádky obsahující komentáře jsou ignorovány. Do souboru je pomocí příkazu #include možné vložit definice z hlavičkového souboru jazyka C++ (Hlavičkový soubor musí mít příponu *.h a jeho jméno je uzavřeno v uvozovkách.) Pokud v souboru prostředků aplikace uvádíme textové konstanty, uzavíráme je do uvozovek a používáme podobný zápis jako v jazyce C/C++ (například kombinace znaků \n označuje přechod na nový řádek). Pokud je řádek příliš dlouhý, můžeme jej ukončit znakem zpětné lomítko a pokračovat na dalším řádku.
Číslo prostředku Už jsme si uvedli, že každý z prostředků aplikace musí mít přiřazeno jedinečné číslo, pomocí kterého jej systém může vyhledat. Tato čísla mohou být od 1000 do 16383; čísla prostředků menší než 1000 používají vývojáři operačního systému PalmOS. Jediný požadavek je, aby každý prostředek stejného typu v aplikaci měl jiné číslo; čísla nemusí jít v pořadí ani po sobě. Čísla prostředků můžete definovat třemi způsoby. První z nich je uvést slovo ID a za ním přímo číslo prostředku aplikace: APPLICATION ID 1000 "NECO"
Můžeme také nechat program pilrc aby některým prostředkům přiřadil jejich čísla automaticky. To dosáhneme, uvedeme-li na místě kde je očekáváno číslo prostředku klíčové slovo AUTOID. Tento způsob můžeme použít u prostředků, jejichž čísla nepotřebujeme znát. Program pilrc automaticky čísluje od čísla 9000 po jedné nahoru. Pokud však v naší aplikaci potřebujeme s příslušným prostředkem pracovat, musíme mít k číslům prostředků přístup i v našem zdrojovém kódu. Toho můžeme dosáhnout buď tak, že konstanty pro čísla prostředků definujeme v hlavičkovém souboru, který vložíme příkazem #include do souboru prostředků aplikace, i do zdrojového textu v jazyce C/C++. Mnohem elegantnější způsob, kterým zabráníme nutnosti zapisovat ručně všechny konstanty, je využít schopností programu pilrc vytvářet hlavičkové soubory (uvedeme-li na příkazové řádce parametr –H). V takovém případě nepotřebujeme do souboru prostředků aplikace vkládat žádné hlavičkové soubory a soubor prostředků aplikace překládáme příkazem: pilrc -ro -H aplikace.h aplikace.rcp
Tento příkaz způsobí, že program pilrc přečte soubor prostředků aplikace a sám vytvoří příslušný hlavičkový soubor (aplikace.h), který můžeme vložit na začátek zdrojového textu C/C++.
Systémové informace v souboru prostředků aplikace V souboru prostředků aplikace musí být uvedeno několik informací o aplikaci, které využívá správce aplikací pro správné zobrazení jména a ikony. Tyto povinné informace zahrnují
25
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
jednoznačný identifikátor aplikace, jméno aplikace a číslo verze. Definice v souboru prostředků aplikace je následující: APPLICATIONICONNAME ID 1000 "Jméno aplikace" APPLICATION ID 1000 "NECO" VERSION ID 1000 "1.1"
Na prvním řádku (APPLICATIONICONNAME a číslo ID 1000) je uvedeno jméno, které se zobrazí pod ikonou v manažeru aplikací. Další řádek (APPLICATION) obsahuje jednoznačnou identifikaci aplikace a na posledním řádku (VERSION) je číslo verze, které se zobrazí v nabídce Info manažeru aplikací.
Ikony aplikace Protože operační systém PalmOS je grafické prostředí, musí každá aplikace povinně obsahovat alespoň jednu ikonu, která je zobrazena ve správci aplikací. Základní ikona, kterou by měla obsahovat každá aplikace je černobílý rastrový obrázek velikosti 32 x 32 obrazových bodů. Kromě základní ikony může aplikace obsahovat ikon víc, lišících se barevnou hloubkou (4 stupně šedi, 16 stupňů šedi a 256 barev). Spodní část každé ikony je při jejím zobrazení přepsána jménem aplikace. Proto je u každé ikony využito pouze horních 22 obrazových bodů. Základem ikon standardních aplikací pro PalmOS je inverzní, šedý nebo světle modrý kruh v horní části ikony, podobně jako na následujícím obrázku:
Aplikace může také obsahovat zmenšené ikony velikosti 15 x 9 obrazových bodů, které jsou využity při zobrazení seznamu aplikací. Také zmenšené ikony mohou být uloženy v popsaných čtyřech barevných variantách. Pokud není zmenšená ikona definována, použije správce aplikací standardní obrázek. Vzhledem k omezené velikosti zmenšené ikony neexistuje žádná „klasická“ podoba; fantazii programátora se meze nekladou.
26
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Pro definici černobílé ikony slouží v souboru prostředků aplikace příkaz ICON, za kterým následuje jméno souboru, ve kterém je ikona uložena. Podobně definujeme zmenšenou ikonu pomocí příkazu SMALLICON. ICON „velka.bmp“ SMALLICON „mala.bmp“
Pokud připravujeme aplikaci pro více verzí operačního systému PalmOS a přejeme si uvést jinou ikonu pro každé barevné rozlišení, použijeme příkazy ICONFAMILY a SMALLICONFAMILY. Za každým z nich následují čtyři jména obrázků: první z nich je pro černobílou verzi, další dva pro verzi ikony se 4 a 16 odstíny šedi a poslední z nich je pro barevnou verzi ikony. Pro obrázky v odstínech šedi můžeme použít ten samý obrázek: program pilrc jej sám upraví na požadované rozlišení. Typ ikony černobílá 4 odstíny šedi
16 odstínů šedi
barevný
Typ souboru *.bmp Černobílý obrázek 32 x 32 obrazových bodů. Barevný obrázek 32 x 32 bodů nebo obrázek v odstínech šedi. Program pilrc jej upraví na čtyři odstíny šedi sám. Barevný obrázek 32 x 32 bodů nebo obrázek v odstínech šedi. Program pilrc jej upraví na šestnáct odstínů šedi sám. Indexovaný barevný obrázek 32 x 32 bodů, nejlépe využívající standardní paletu barev Palm Pilota.
Doporučení Pozadí bílé, ikona černá. Pozadí bílé, ikona tmavě šedá; světle šedá a černá barva jsou použity k vykreslení ikony. Pozadí bílé.
Měl by obsahovat nejvýše 256 barev, mezi nimi jednu „průhlednou“ barvu pozadí.
U černobílé ikony a ikon v odstínech šedi je pozadí bílé. Pokud však uvádíme barevnou ikonu, měli bychom pozadí vyplnit barvou, která se nevyskytuje v ikoně a do příkazu uvést index nebo RGB hodnoty „průhledné“ barvy. K definici RGB hodnot průhledné barvy slouží vlastnost TRANSPARENT. Tam, kde bude v obrázku tato „průhledná barva“ bude ve správci aplikací barva pozadí. Pokud nepoužijeme průhlednou barvu a uděláme pozadí bílé, bude ve správci aplikací kolem ikony bílý rámeček; nastavit bílou barvu jako „průhlednou“ můžeme pomocí: ICONFAMILY "cb.bmp" "seda.bmp" "seda.bmp" "barevna.bmp" TRANSPARENT 255 255 255
Prohlédněte si soubor prostředků aplikace příkladu 1, ve kterém jsou různé ikony definovány a zkuste jej instalovat do simulátoru. Změňte několikrát barevnou hloubku displeje a prohlédněte
27
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
si, která ikona je vykreslena. Při definici ikon ve svých aplikacích můžete používat ikony z příkladu 1 jako základ a upravovat je ve svém oblíbeném grafickém editoru.
Čísla chyb v PalmOS Pokud se vyskytne neočekávaná situace, vrací mnoho funkcí operačního systému PalmOS chybovou hodnotu. Pro uložení čísla chyby slouží 16bitový datový typ Err, definovaný v PalmTypes.h. Nulová hodnota je vyhrazena pro návrat funkce bez chyby; hlavičkové soubory PalmOS ji definují jako konstantu noError. Číslování chyb je jednotné: každá součást operačního systému má vyhrazen vlastní rozsah čísel chyb. Tento mechanismus umožňuje používat univerzální funkci SysErrString pro získání textu odpovídajícího příslušnému číslu chyby. // Jednoduchá funkce, která zobrazí chybovou hlášku pokud je jí předáno // číslo chyby void BezChyby(Err chyba) { Char text[MAX_DELKA];
}
if(chyba) { SysErrString(chyba, text, MAX_DELKA]; ErrDisplay(text); }
// Použití: BezChyby(DmCloseDatabase(gDatabaze));
28
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Překlad první aplikace Součásti vývojového prostředí Při instalaci vývojového prostředí zkopíruje instalátor na váš harddisk řadu programů, které budete využívat při překladu aplikací pro počítače vybavené operačním systémem PalmOS. V následující tabulce jsou uvedeny programy, které budete při překladu využívat: Program palmdev-prep m68k-palmos-gcc m68k-palmos-gdb pilrc build-prc
make rm soubory cp co kam pilot-xfer
Popis Jednoduchý pomocný program, pomocí kterého vyberete, pro kterou verzi operačního systému PalmOS budete psát svoji aplikaci. Stačí jej spustit jednou v průběhu instalace. Překladač zdrojového textu v jazyce C/C++ pro operační systém PalmOS. Ladící program, který ve spolupráci s emulátorem POSE nebo xcopilot slouží k nacházení chyb, které jste udělali při psaní programu. Překladač souboru prostředků aplikace. Program, který poskládá přeložený zdrojový text C/C++ a přeložený soubor prostředků aplikace a vytvoří soubor s příponou *.prc, obsahující databázi prostředků aplikace, kterou můžete přímo instalovat do Palm Pilota. Univerzální program pro automatizaci překladu. Program pro mazání souborů. Program pro kopírování souborů. Instaluje nebo zálohuje databáze do Palm Pilota přes sériový port. Na rozdíl od dodávaného programu HotSync umožňuje rychle instalovat jednotlivé aplikace aniž by byla synchronizována všechna ostatní data (instalace aplikací je rychlejší než pomocí programu HotSync). Umí instalovat databáze přes infračervené rozhraní, neporadí si však s USB.
V této kapitole se postupně seznámíme s těmito programy a naučíme se je využívat. Větší část vývojového prostředí, ve kterém budeme pracovat, se ovládá z příkazové řádky a je kompatibilní se stejně pojmenovanými programy pro operační systém UNIX/Linux. Podrobnější dokumentaci ke všem programům najdete v adresáři C:\cygwin\usr\doc. Postup překladu, který zde detailně popíšeme je možné (a jednoduché) zcela automatizovat pomocí programu make, který zmíníme na závěr této kapitoly.
Překlad zdrojového textu C/C++ K překladu zdrojového textu používáme překladač m68k-palmos-gcc. Jedná se o standardní GNU překladač jazyka C/C++, který byl upraven na produkci kódu pro procesory Motorola 68000 a operační systém PalmOS. Překladač je spouštěn z příkazové řádky a jeho hlavním parametrem je jméno souboru, který obsahuje příkazy jazyka C/C++; v následující tabulce je několik dalších parametrů, které můžeme programu m68k-palmos-gcc předat:
29
Úvod do programování PalmOS Parametr -o soubor -Wall
-Očíslo
-g
--help -Dmakro -Dmakro=parametr -Umakro -x c nebo –x c++
MUDr. Petr Lesný, 2003
Význam Určuje jméno souboru, do kterého bude uložen výsledek práce překladače. Pokud tento přepínač neuvedeme, bude výstup směrován (z historických důvodů) do souboru se jménem a.out. Informuje uživatele o všech možných chybách, které při psaní zdrojového textu mohl udělat - zapíná všechna varování překladače. Seznam varování si můžete prohlédnout v originální anglické dokumentaci překladače. Zapíná a vypíná takzvanou „optimalizaci“ - proces který sice zpomalí překlad, ale výsledný přeložený program je zato rychlejší a menší (třeba tak, že překladač při překladu pozná nepoužívané proměnné, nebo přemístí konstantní výrazy mimo cyklus). Možné hodnoty parametru -O jsou následující: • -O0 optimalizaci vypíná (také pokud přepínač -O neuvedeme). Programy je pak možné lépe odlaďovat resp. nacházet v nich chyby. • -O1 zapíná některé volby optimalizace • -O2 zapíná (zatím) nejvyšší úroveň optimalizace pro rychlost i velikost programu • -Os zmenší velikost přeloženého programu na úkor jeho rychlosti. Uloží při překladu do objektového souboru důležité informace pro ladící program (debugger): jména všech proměnných, místa jejich použití v programu, přiřadí čísla řádků v souborech zdrojového textu jednotlivým místům přeloženého kódu. Vypíše nápovědu (v angličtině) k některým možnostem programu. Definuje makro podobně jako příkaz #define. V prvním případě má makro hodnotu 1, ve druhém případě je jeho hodnota rovna parametru za rovnítkem. Ruší definici makra podobně jako příkaz #undef. Umožňuje zvolit, zda bude překlad probíhat v jazyce C nebo C++. Pokud tento přepínač neuvedete, rozhodne se překladač podle koncovky souboru: soubory s příponou *.c budou přeloženy v jazyce C s rozšířenými vlastnostmi GNU, soubory s příponami *.cpp a *.cc budou přeloženy v jazyce C++.
Nyní vytvoříme zdrojový text prvni.c, který bude obsahovat funkci PilotMain a smyčku zpracování událostí. Zatím nečekejme, že naše aplikace bude dělat zázraky; stačí, že se ji podaří nainstalovat a spustit. Na začátek kódu vložíme hlavičkový soubor s definicemi funkcí a konstant pro operační systém PalmOS: #include <PalmOS.h>
30
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Poté vložíme funkci PilotMain, ve které budeme reagovat na kód spuštění sysAppLaunchCmdNormalLaunch a spustíme nejjednodušší verzi smyčky pro zpracování událostí – pouze zpracujeme systémové události funkcí SysHandleEvent a událost ukončení aplikace appStopEvent. UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { EventType udalost; if (cmd == sysAppLaunchCmdNormalLaunch) { do { EvtGetEvent(&udalost, evtWaitForever);
} }
SysHandleEvent(&udalost); } while(udalost.eType != appStopEvent);
return 0;
Zdrojový text přeložíme pomocí překladače m68k-palmos-gcc, kterému předáme následující parametry, kterými zapneme varování (-Wall), určíme jméno výstupního souboru (-o prvni) a vložíme do objektového souboru i ladící informace (-g): m68k-palmos-gcc –g –Wall prvni.c –o prvni
V adresáři by nám měl vzniknout soubor se jménem prvni (bez přípony), obsahující přeložený zdrojový kód aplikace (objektový soubor). Tento přeložený kód nejde zatím spustit; musíme jej spojit s prostředky aplikace a vytvořit soubor s příponou *.prc.
Překlad souboru prostředků aplikace Nejprve si připravíme „minimální“ soubor prostředků aplikace, který nazveme prvni.rcp. V tomto souboru musíme uvést jméno aplikace, jednoznačnou identifikaci aplikace a černobílou ikonu. Ikonu nakreslíme v programu pbrush v Microsoft Windows: vytvoříme nový černobílý obrázek velikosti 32 x 32 obrazových bodů a v jeho horní části (horních 22 bodů) nakreslíme černé podkladové kolečko a číslici jedna. ICON "ikona.bmp" APPLICATIONICONNAME ID 1000 "Prvni" APPLICATION ID 1000 "NECO" VERSION ID 1000 "1.X"
ikona.bmp
Ke komfortnímu překladu souboru prostředků aplikace slouží program pilrc. Také program pilrc voláme z příkazové řádky s parametry, upřesňujícími překlad. Některé důležité parametry programu pilrc jsou v následující tabulce:
31
Úvod do programování PalmOS
Parametr -H soubor.h
-ro
-q -o soubor.ro
-L jazyk
MUDr. Petr Lesný, 2003
Význam Pokud tento parametr uvedeme, tak narazí-li při překladu souboru prostředků aplikace program pilrc na nedefinovaný identifikátor, automaticky mu přiřadí hodnotu. Program pilrc poté vytvoří hlavičkový soubor soubor.h obsahující definice všech automaticky přiřazených hodnot. Pokud parametr –H neuvedeme a program pilrc narazí na nedefinovaný identifikátor, ohlásí chybu. Program pilrc pracuje ve dvou režimech. V prvním z nich uloží každý přeložený prostředek aplikace do vlastního souboru s automaticky vytvořeným jménem a příponou *.bin. Uvedeme-li přepínač –ro tak program pilrc automaticky vytvoří pouze jeden soubor s příponou *.ro, který bude obsahovat všechny přeložené prostředky aplikace. V našich aplikacích budeme používat výhradně tento způsob volání programu pilrc. Pokud tento parametr neuvedeme, program pilrc podrobně vypisuje všechny akce, které provádí. Uvedení parametru –q způsobí, že program pilrc vypisuje pouze chybová hlášení. Pomocí parametru –o je možné změnit jméno výstupního souboru. Pokud tento parametr neuvedeme, je výstup automaticky uložen do souboru se stejným jménem, jako má soubor prostředků aplikace, ale s příponou *.ro. V souboru prostředků aplikace může být více jazykových variant. Pomocí parametru –L vybíráte požadovaný výstupní jazyk.
Soubor prostředků aplikace přeložíme pomocí programu pilrc, kterému předáme jediný parametr: -ro. Tento parametr zajistí, že přeložený soubor prostředků aplikace bude uložen do jediného souboru prvni.ro. (Pokud bychom parametr –ro nepoužili, budou přeložené prostředky aplikace uloženy v mnoha souborech s automaticky vytvořenými názvy APPL03e8.bin, tAIB03e8.bin, tAIN03e8.bin a tver03e8.bin.) pilrc –ro prvni.rcp
Po zadání tohoto příkazu by nám měl v adresáři vzniknout soubor se jménem prvni.ro, který bude obsahovat přeložené prostředky aplikace. V dalších příkladech budeme program pilrc volat ještě s parametrem –H, pomocí kterého vytvoříme automaticky hlavičkový soubor s definicemi konstant, které jsme použili v souboru prostředků aplikace.
Překlad aplikace Nyní máme objektový soubor prvni, ve kterém je přeložený strojový kód aplikace (včetně ladících informací) a soubor prvni.ro, ve kterém jsou přeložené prostředky aplikace. Ke spojení těchto dvou souborů do souboru s příponou *.prc použijeme program build-prc, který je součástí balíku programů prc-tools. Program build-prc je (jako všechny programy popisované zde) volán z příkazové řádky a vyžaduje následující parametry:
32
Úvod do programování PalmOS Parametr -o soubor.prc
-c XXXX
-n “Jmeno”
MUDr. Petr Lesný, 2003 Význam Tento parametr určuje, jak se bude jmenovat vytvořená databáze prostředků aplikace. Pokud jej neuvedeme, bude její jméno určeno automaticky ze jména prvního předaného souboru (jméno nebo jméno.ro). Tento povinný parametr určuje, jaká bude jednoznačná identifikace aplikace. Musí být uvedená stejná čtyřpísmenná kombinace, jako za klíčovým slovem APPLICATION v souboru prostředků aplikace. Druhý povinný parametr, který určuje jméno databáze na počítači Palm Pilot. Jméno databáze nemá vliv na zobrazení aplikace ve správci aplikací; je ale využito například při zálohování databází na stolním počítači.
Abychom dostali svoji úplně plně fungující aplikaci pro počítače Palm Pilot a kompatibilní, stačí nám jenom napsat poslední příkaz, kterým spojíme soubory prvni a prvni.ro do výsledného souboru prvni.prc. build-prc –c NECO
–n “Prvni“
prvni
prvni.ro
Stačily tři jednoduché kroky a v adresáři se nám objevil soubor prvni.prc, který obsahuje přeloženou aplikaci. Předtím, než jej synchronizujeme do svého počítače Palm Pilot tak bychom jej měli vyzkoušet v emulátoru POSE. Abychom nemuseli opakovaně zapisovat jednotlivé kroky překladu, můžeme příkazy uvést v dávkovém souboru, například: @echo off m68k-palmos-gcc -g -Wall prvni.c -o prvni pilrc -ro prvni.rcp build-prc -c NECO -n "Prvni aplikace" prvni prvni.ro
Na konci kapitoly si uvedeme mnohem elegantnější způsob automatizace překladu s využitím programu make a souboru Makefile.
Vyzkoušení první aplikace Spustíme emulátor POSE a přeneseme myší soubor prvni.prc na emulátor (můžeme také kliknout pravým tlačítkem myši a zvolit „Install Application/Database...“). Emulátor POSE neumí správně aktualizovat zobrazené ikony: pokud se nám ikona ve správci aplikací nezobrazí, spusťte jinou aplikaci – třeba kalkulačku – a vraťte se do správce aplikací. Uvidíte ikonu jako na obrázku vlevo. Na obrázku vpravo je dialog s informacemi o aplikacích, ve kterém si můžete zkontrolovat číslo verze.
33
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Pokud kliknete na ikonu naší aplikace, zobrazí se pouze prázdný displej. Aplikace zatím nezobrazuje žádné formuláře a sama nic nedělá. Je v ní však smyčka pro zpracování událostí, a proto je možné aplikaci korektně opustit.
Ladění aplikace K ladění aplikací slouží program m68k-palmos-gdb. Uživatelé se zkušenostmi s operačním systémem UNIX/Linux nebudou mít s jeho ovládáním potíže, neboť se jedná o klon programu gdb. Chceme-li použít ladící program, musíme naši aplikaci přeložit s parametrem –g, který způsobí, že do objektového souboru (soubor bez přípony) budou uloženy ladící informace o uložení proměnných, adrese první instrukce na každém řádku zdrojového textu a podobně. Žádné z těchto ladících informací však nejsou ukládány do souborů s příponou *.prc. m68k-palmos-gcc –g –Wall prvni.c –o prvni
K ladění budeme používat emulátor POSE, protože program m68k-palmos-gdb zatím neumí spolupracovat se simulátorem PalmOS. Pro správnou funkci emulátoru budete potřebovat kopii paměti ROM svého počítače; návod k zkopírování paměti Palm Pilota do stolního počítače naleznete v dokumentaci k emulátoru. Základní kroky při ladění aplikace jsou následující: 1. Přeložte vaši aplikaci s parametrem –g. 2. Spusťte emulátor POSE a instalujte do něj vytvořený soubor *.prc. 3. Spusťte program m68k-palmos-gdb a jako parametr mu předejte jméno objektového souboru m68k-palmos-gdb prvni
4. Napište příkaz target pilot localhost:2000, kterým propojíte ladící program s emulátorem.
34
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
5. Spusťte vaši aplikaci kliknutím na její ikonu v emulátoru. Aplikace předá kontrolu ladícímu programu a čeká na náš příkaz.
Ladící program se ovládá příkazy, které zapisujeme v textovém okénku. Základní příkazy, které můžeme použít jsou v následující tabulce:
35
Úvod do programování PalmOS
Příkaz ke zjišťování stavu list list číslo_řádku list jméno_funkce print jméno_proměnné backtrace bt frame číslo break číslo_řádku break jméno_funkce delete číslo_zarážky help help co quit
MUDr. Petr Lesný, 2003
Popis Vypíše 10 řádků zdrojového textu (bez parametru), určený řádek zdrojového textu nebo začátek funkce. Zobrazí hodnotu proměnné. Vypíše seznam funkcí, které jsou v zásobníku. Vybere příslušnou úroveň zásobníku – vhodné pro usnadnění přístupu k lokálním proměnným. Nastaví zarážku (breakpoint) na příslušném řádku nebo v určené funkci. Vymaže zarážku, jejíž číslo zadáme. Zobrazí seznam možných příkazů nebo nápovědu k některému z nich. Ukončí ladění programu a opustí ladící program.
Další příkazy ovládají běh programu. Abychom je nemuseli zadávat opakovaně, obsahuje ladící program historii již zadaných příkazů, kterými můžeme listovat pomocí šipky nahoru a dolů. Další příjemná vlastnost je, že odeslání prázdného řádku způsobí zopakování předchozího příkazu. Příkaz continue cont next step
Popis Pokračuje dokud program neskončí, nebo dokud nenarazí na některou z definovaných zarážek. Vykoná řádek zdrojového textu a přejde na následující řádek. Jako předchozí, ale je-li na řádku volání funkce tak skočí na její první řádek.
Při možnostech ladění programu nesmíme zapomenout na možnost vkládat do programu volání ladících funkcí ErrDisplay a ErrNonFatalDisplayIf, (obdoba makra assert v C/C++) popsaných v následující kapitole.
Program make Program make byl poprvé uveden jako součást operačního systému Unix, sloužící ke zjednodušení a zrychlení překladu složitých programů. Tyto programy sestávaly z několika souborů zdrojového kódu, které bylo potřeba přeložit v pevném pořadí a spojit s knihovnami. Dokud se k řízení překladu používaly jednoduché dávkové soubory, tak – pokud jsme změnili byť jenom jeden soubor zdrojového kódu – bylo potřeba všechny soubory projektu znovu přeložit a spojit s knihovnami. Pak někdo prosadil následující pravidla: (1) bylo by dobré, kdyby se překládaly jen ty soubory, které se od posledního překladu změnily; (2) nechť tedy programátor vytvoří soubor, popisující závislosti jednotlivých součástí programu na sobě a konečně (3) budiž program, který přečte tento soubor závislostí a na jeho základě určí, které soubory je zapotřebí překládat,
36
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
spojovat s knihovnami, kopírovat atd. a které z nich jsou aktuální. A vznikl program make, který má všechno tohle za úkol. Program make po spuštění přečte soubor Makefile, který se nachází v aktuálním adresáři a na základě pravidel v něm popsaných určí, které soubory je potřeba přeložit (nebo aktualizovat) a které programy k tomu použít. Soubor Makefile je tvořen skupinami „závislostí“ a „pravidel“. „Závislost“ je dána cílem (souborem, který se má vytvořit) a skupinou souborů, na nichž vytvoření cíle závisí (které když se změní tak je potřeba cíl vytvořit znovu). „Pravidla“ popisují postup jak vytvořit cíl ze souborů na nichž závisí. Skupin závislost-pravidlo může být v souboru Makefile libovolné množství. Program make určuje na základě seznamu závislostí a pravidel pořadí, ve kterém mají být cíle vytvořeny a správnou posloupnost pravidel, která k tomu mají být použita. Narazí-li program make kdykoliv během provádění pravidel na chybu (tj. na program, který skončí s jiným návratovým kódem než je 0) tak zastaví překlad. Program make voláme také z příkazové řádky. Hlavním parametrem programu make je jméno cíle, který má být vytvořen. Pokud jméno cíle neuvedete, vytvoří program make první cíl, který je v souboru Makefile definován.
Soubor Makefile Popíšeme si zjednodušenou syntaxi souboru Makefile. Pro podrobný popis syntaxe se podívejte do literatury o operačním systému Unix nebo do popisu programu make v dokumentaci libovolného překladače jazyka C/C++ (Visual C, Borland, Watcom). 1. Pokud řádek začíná znakem mřížka (#), jedná se o komentář a program make jej ignoruje. 2. Na začátku souboru Makefile mohou být definována makra; každá definice má tvar jméno_makra=hodnota a musí být na samostatném řádku. Jméno makra (před rovnítkem) bude při překladu nahrazeno jeho hodnotou (textem od rovnítka až ke konci řádku). Makra můžete použít kdekoliv v souboru Makefile; při jejich použití je uvádíte jako $(jmeno_makra); tato konstrukce bude při překladu nahrazena hodnotou makra. 3. Poté následují jednotlivé bloky závislost-pravidlo, kterým se budeme věnovat dále. Syntaxe bloků závislost pravidlo je: cíl: seznam závislostí pravidlo1 pravidlo2 ... pravidloN
Cíl je jméno souboru, který má být vytvořen a seznam závislostí obsahuje jména souborů, na kterých vytvoření cíle závisí. Pravidlo1 až PravidloN jsou příkazy, které je postupně potřeba provést, aby byl cíl vytvořen. Příklad jednoduchého souboru Makefile, který vykonává stejné činnosti jako dříve popsaný dávkový program je: #Jednoduchý soubor Makefile prvni.prc: prvni prvni.ro build-prc -c NECO -n "Prvni aplikace" prvni prvni.ro
37
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
prvni: prvni.c prvni.ro m68k-palmos-gcc -g -Wall prvni.c -o prvni prvni.ro: prvni.rcp pilrc -ro prvni.rcp –H prvni.h
Všechna pravidla v souboru Makefile musí být uvedena na řádcích, které začínají tabulátorem, jinak jim program make nebude rozumět. Tato skutečnost může způsobit zdánlivě „neodstranitelné“ chyby – v řadě editorů vypadá několik mezer a tabulátor úplně stejně. Pokud vám program make nebude vykonávat jednotlivá pravidla po sobě tak jak by měl, velmi pravděpodobně je vina právě v tom, že jste místo tabulátoru napsali několik mezer. V takovém případě otevřete soubor Makefile v poznámkovém bloku (notepad) ve Windows a ujistěte se, že řádky, na kterých jsou pravidla, začínají skutečně tabulátory a ne mezerami. V souboru Makefile je možné uvádět i řádky s tzv. falešnými cíli tj. cíli, které neoznačují pravá jména souborů. Takto můžeme využít program make i ke smazání pomocných souborů. Uvedeme-li v souboru Makefile následující blok závislost-pravidla, tak když napíšeme příkaz „make uklid“ budou programem rm vymazány pomocné soubory prvni a prvni.ro. uklid:
rm
prvni prvni.ro
38
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Důležité skupiny funkcí Rozdělení funkcí v PalmOS Z hlediska programátora je důležitou součástí operačního systému popis funkcí, které může ve svých aplikacích použít. Při psaní programů pro operační systém PalmOS využíváme ve svých programech téměř výlučně funkce, které jsou součástí operačního systému. Tento přístup vede k maximální úspoře paměti a jednoduchosti našich aplikací. V hlavičkových souborech, které do našeho zdrojového textu vkládá soubor PalmOS.h jsou definovány stovky funkcí obsažených v jádře operačního systému. Tyto funkce jsou pro přehlednost rozčleněny do skupin, podle činnosti, kterou vykonávají. Každá skupina funkcí má společný prefix jména: například všechny funkce pracující s pamětí začínají na Mem... (MemPtrNew, MemPtrFree a podobně). V následující tabulce jsou skupiny funkcí, kterým se budeme věnovat v této knize. Nebudeme nahrazovat referenční příručku a proto si musíte podrobnější popis funkcí najít v referenční příručce. Jména funkcí začínají CategoryXXX(... CtlXXX(...
FldXXX(... FrmXXX(... LstXXX(... SclXXX(... TblXXX(... MenuXXX(... DmXXX(... ErrXXX(... FlpXXX(... FntXXX(... MemXXX(...
Popis Funkce ulehčující práci s kategoriemi záznamů v databázích. Tyto funkce se starají o správné zobrazení jména kategorie, výběr kategorie a editace seznamu kategorií. Funkce pracující obecně s prvky uživatelského rozhraní ve formuláři nebo v dialogu. Například jsou zde funkce pro zobrazení a skrytí prvku formuláře a funkce pro nastavení textu a stavu tlačítek. Funkce pracující s políčky textu (fields). Funkce pracující s formuláři a dialogy. Jsou zde funkce pro vykreslení formuláře, zjištění aktivního formuláře nebo dialogu, nalezení prvků ve formuláři a dialogu atd. Práce se seznamy – vykreslení seznamu, zobrazení daného prvku seznamu nebo nastavení pozice a velikosti seznamu. Funkce pro nastavení vlastností posuvníků (scrollbar). Funkce pro manipulaci s tabulkami. Manipulace s menu. Z této skupiny funkcí využíváme funkci MenuHandleEvent pro zpracování událostí menu. Funkce pro práci s databázemi; těmto funkcím je věnována samostatná kapitola. Ladící funkce a funkce pro zpracování chyb. Některé z nich uvedeme dále v této kapitole. Základní funkce pracující s čísly v pohyblivé desetinné čárce; práci s typy float a double se budeme věnovat v této kapitole. Funkce pracující s písmy (fonts). Práce s operační pamětí. O práci s operační pamětí si povíme dále v této kapitole.
39
Úvod do programování PalmOS
PrefXXX(...
FtrXXX(... RctXXX(... StrXXX(... EvtXXX(... SysXXX(...
VFSXXX(... WinXXX(...
MUDr. Petr Lesný, 2003
Zde jsou funkce, které manipulují s uloženým stavem aplikace (preferences). Aplikace pro PalmOS by měla být schopna při ukončení uložit svůj stav tak, aby se uživatel mohl při jejím opětovném spuštění vrátit do rozdělané práce. Zjišťování vlastností operačního systému. V této kapitole se naučíme zejména zjišťovat verzi operačního systému. Funkce pracující s obdélníkovými výřezy na displeji (rectangles). Tyto výřezy je možné definovat a provádět s nimi jednoduché operace – posuv, změna velikosti a podobně. Práce s řetězci. Při psaní programů pro PalmOS je výhodnější používat tyto funkce, spíše než standardní funkce z <string.h>. Zpracování událostí – v této knize používáme pouze funkci pro vyzvednutí další události EvtGetEvent, ale události je možné do fronty událostí také vkládat, měnit jejich vlastnosti apod. Funkce, začínající tímto prefixem jsou základní funkce operačního systému. Jedná se o značně nesourodou skupinu funkcí, které zajišťují vše od spuštění aplikace po zpracování událostí na nejnižší úrovni. Funkce pracující se systémem souborů na paměťové kartě SD/MMC (virtual file system). Tato skupina funkcí zajišťuje kreslení na displeji a manipulaci s plochami pro kreslení – okny (windows).
Ve zbytku této kapitoly se budeme věnovat některým skupinám funkcí, jejichž znalost vám pomůže orientovat se ve zbytku této knihy. Předpokládám, že při dalším studiu knihy se k této kapitole budete pravidelně vracet.
Práce s řetězci (strings) v PalmOS Před popisem uživatelského rozhraní se musíme zmínit o tom, jak operační systém PalmOS zachází s řetězci. Při programování v jazyce C si uživatel zvykne na uložení textu v řetězcích (pole znaků, ukončených znakem s kódem 0) a použití funkcí strlen, strcpy apod. pro jejich zpracování. Tyto funkce jsou poté vybrány ze standardních knihoven a připojeny k výsledné aplikaci. Aby bylo možné pracovat v programech pro PalmOS s řetězci a vyhnout se připojování funkcí ze standardních knihoven, obsahuje paměť ROM přímo funkce pro práci s řetězci. Tyto funkce jsou implementovány přímo v jádře operačního systému; jejich parametry jsou totožné s parametry jejich protějšků v jazyce C. Funkce jsou definovány v hlavičkovém souboru Core\System\StringMgr.h. C strlen strcpy strncpy
PalmOS StrLen StrCopy StrNCopy
strcat
StrCat
Popis Vrací délku řetězce. Kopíruje řetězec. Kopíruje maximálně prvních n znaků řetězce. Připojí druhý řetězec na konec prvního.
40
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
strncat
StrNCat
strcmp
StrCompare
strncmp
StrNCompare
stricmp
StrCaselessCompare
strnicmp
StrNCaselessCompare
atoi itoa
StrAToI StrIToA
strchr strstr sprintf
StrChr StrStr StrPrintF
Připojí druhý řetězec na konec prvního, kontroluje však maximální délku. Porovná dva řetězce a vrátí hodnotu –1, 0 nebo +1 podle výsledku porovnání. Porovná dva řetězce, nejvýše však prvních n znaků. Porovná dva řetězce bez zřetele na malá a velká ASCII písmena. Porovnání prvních n znaků řetězců bez zřetele na malá a velká ASCII písmena. Převod řetězce na celé číslo. Převod celého čísla na řetězec. Maximální délka řetězce je maxStrIToALen. Index výskytu znaku v řetězci. Index výskytu podřetězce v řetězci. Formátovaný výstup textu. Rozeznává kombinace %d, %u, %x, %s, %c a prefixy +, -, * a l. Neumí pracovat s čísly v pohyblivé desetinné čárce.
Příklad použití řetězců v PalmOS: Char* konstanta = „Toto je text ... “; Char pole[100], cislo[maxStrIToALen]; StrCopy(pole, „A bude to „); StrCat(pole, konstanta); StrCat(pole, StrIToA(cislo, 13)); if(StrCompare(cislo, „13“) == 0) { StrPrintF(pole, „Cislo je %d, %s\n“, 13, cislo); }
Operační paměť Jednou z předností počítačů založených na PalmOS je jejich úsporné hospodaření s pamětí. První modely Palm Pilotů využívaly pouze 128 kB paměti RAM pro uživatelská data a aplikace a 512 kB paměti ROM obsahující systém a aplikace vestavěné. Velikost paměti se postupně zvětšovala, dnes se už pomalu na trhu přestávají objevovat modely s 2 MB paměti RAM a lze předpokládat, že i dnes obvyklých 8 MB se ukáže v budoucnosti jako nedostačujících. Operační systém PalmOS využívá velmi jednoduchý způsob práce s daty a programy. Místo systému souborů organizovaných v adresářích jsou data i aplikace uložena přímo v operační paměti v databázích záznamů (data) a databázích prostředků aplikace (programy). Je-li aplikace spuštěna, je spuštěna přímo na místě - není nikam kopírována. Tento přístup zjednodušuje hospodaření s daty a šetří operační paměť. Na rozdíl od stolních počítačů, u kterých je možné jednoduchým způsobem paměť rozšiřovat, je operační paměť většiny zatím existujících modelů Palm Pilota možné rozšířit jen za cenu určitých obtíží. Proto budeme vždy dodržovat zásadu, že programy, které budeme psát, budou využívat co nejméně operační paměti. 41
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Uspořádání operační paměti Procesor Motorola 68328, který je v Palm Pilotech použit je vystavěn na 32-bitové architektuře, používá 32-bitové adresy a to znamená, že umí přímo obsloužit 4 GB paměti. Tato paměť je v počítačích Palm Pilot organizována do 14 „paměťových karet“ (memory cards). Na paměťové karty se můžeme dívat jen jako na logické konstrukce, kterým je praktické se přizpůsobit, aby naše programy byly použitelné i na počítačích, které budou mít paměťové karty vyměnitelné. Jediné místo, kde budeme uvažovat o těchto „paměťových kartách“, bude kapitola věnovaná databázím. Uvedené „paměťové karty“ nemají žádnou spojitost s SD/MMC nebo MemoryStick rozšiřujícími kartami, které můžete dokoupit. Každá karta může obsahovat paměť RAM, paměť ROM nebo oba druhy paměti. Paměťový prostor počítačů Palm Pilot a kompatibilních tedy vypadá jako v následující tabulce, přičemž maximální velikost jedné paměťové karty je 228 byte (256 MB): Paměť od-do 0x00000000 – 0x0FFFFFFF 0x10000000 – 0x1FFFFFFF ... 0xE0000000 – 0xEFFFFFFF 0xF0000000 – 0xFFFFFFFF
Obsah Systémová oblast – vektory přerušení. Paměťová karta 0 – základní ROM i RAM u většiny modelů. Paměťová karta 14. Systémová oblast - registry procesoru pro ovládání hardware apod.
Už jsme uvedli, že paměťová karta může obsahovat nejvýše 256MB paměti a že na této kartě může být paměť RAM, paměť ROM nebo oba dva druhy. Paměť RAM na každé kartě je systémem rozdělena na dvě části: paměť dynamickou, což je obdoba pracovní paměti u stolních počítačů, a paměť pro uložení databází (storage), která podobně jako harddisk počítače obsahuje vaše data, instalované aplikace atd. Část dynamické paměti zabere operační systém, zbytek je použitelný pro uživatelské aplikace. V operačním systému PalmOS 2.0 byla velikost dynamické „operační“ paměti pouze 64 kB a z toho pouze 12 kB bylo k dispozici uživateli (zbytek byl vyhrazen pro databáze); v počítačích s PalmOS 4.0 a novějších je uživateli k dispozici 180 kB dynamické paměti. Paměť pro uložení databází (všechna zbylá paměť) slouží k trvalému uskladnění aplikací a jejich dat. Na rozdíl od paměti dynamické je chráněna proti náhodnému přepsání pomocí hardwarové pojistky. Pokud se pokusíme přímo zapisovat do paměti pro uložení databází, vyvoláme velmi nepřátelskou chybovou hlášku a Palm Pilot se restartuje (podobně jako při stisknutí tlačítka reset). Paměť pro uložení databází může být vymazána ve dvou případech: • Dojdou baterie. • Při restartu Palm Pilota držíme tlačítko pro zapnutí a zvolíme si možnost vymazat všechna data. Díky nepřetržitému napájení paměť RAM uchovává data, která jsou v ní uložená, i když je Palm Pilot „vypnut“ (displej je vypnutý, odběr je snížen na minimum). Po restartu počítače je vymazána pouze dynamická paměť; vše co zbylo v paměti pro uložení databází – aplikace i jejich data – zůstává za normálních okolností na svém místě.
42
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Bloky paměti (chunks) Dynamická paměť i paměť pro uložení databází je operačním systémem uspořádána v blocích (chunk). Blok paměti je spojitá oblast větší nebo rovna 1 byte a menší než 64 kB. Může se přitom jednat o paměť RAM i ROM. S pamětí hospodaří manažer paměti PalmOS, který přiděluje aplikacím dva druhy bloků paměti: • Bloky nepřemístitelné (nonmovable chunks), které zůstávají na svém pevně daném místě v paměti po celou dobu. • Bloky přemístitelné (movable chunks), které může operační systém přemisťovat. Tyto bloky je možné dočasně uzamknout, aby z nich bylo možné číst data. Operační systém PalmOS sám přesouvá přemístitelné bloky v paměti tak, aby optimalizoval její využití – tento způsob práce s pamětí se objevil nejprve na počítačích Apple Macintosh. Manažer paměti operačního systému PalmOS také udržuje přehled o umístění bloků v paměti. Každý blok paměti nese navíc informaci o tom, která aplikace jej od systému získala. Bloky paměti mohou být pevně umístěné, nepřemístitelné (například ty uložené v paměti ROM nebo bloky obsahující vykonávané instrukce procesoru) nebo přemístitelné, které může operační systém – resp. manažer paměti PalmOS – podle potřeby přemisťovat v operační paměti. Pokud si přejeme pracovat s přemístitelným blokem paměti můžeme jej na krátkou dobu uzamknout na místě: během této doby nebude možné tento blok posunout jinam (a vznikne z něj nepřemístitelný blok paměti). Po skončení práce s blokem paměti jej musíme odemknout a tak umožnit manažeru paměti aby mohl v případě potřeby tento blok paměti přesunout jinam podle potřeby. Manažer paměti PalmOS udržuje přehled o tom, kterým aplikacím jednotlivé bloky paměti patří. Pokud při ukončení aplikace zjistí, že tato aplikace operačnímu systému nevrátila všechny bloky paměti, tak je uvolní pro potřeby dalších aplikací sám. Přesto však patří k dobrým zvyklostem programátorů vrátit na konci aplikace operačnímu systému všechny bloky paměti, které aplikace od systému získala.
Nepřemístitelné bloky paměti Manipulace s nepřemístitelnými bloky je jednoduchá. Pomocí funkce MemPtrNew požádáme operační systém o přidělení bloku paměti požadované velikosti. Pokud tato funkce vrátí adresu bloku paměti, byl v dynamické paměti inicializován nepřemístitelný blok paměti dané velikosti, patřící naší aplikaci, a tento blok můžeme okamžitě používat. Po skončení práce s blokem paměti jej musíme vrátit operačnímu systému voláním funkce MemPtrFree. MemPtr blok = MemPtrNew(100); if(blok) { MemSet(blok, 100, ‘\0‘); Char* text = (Char*)blok; StrCopy(text, „...“); ... MemPtrFree(blok); }
43
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce MemSet slouží k vyplnění bloku paměti jedním byte, funkce MemMove kopíruje obsah paměti. Datový typ MemPtr je definován (podobně jako v C/C++ typ void*) jako adresa v paměti, která může být bezpečně přetypována.
Přemístitelné bloky paměti V podmínkách omezeného množství paměti, které panují na počítačích Palm Pilot a kompatibilních je výhodnější používat přemístitelné bloky paměti, které může operační systém uspořádávat v paměti podle potřeby. Přestože používání přemístitelných bloků paměti je z hlediska programátora o něco málo obtížnější tak tato technika umožní snížit nároky na paměť. Manažer paměti PalmOS optimalizuje využití paměti (uspořádává v případě potřeby přemístitelné bloky v paměti), a dovolí ve měnit jejich velikost. Žádáme-li systém o nepřemístitelný blok paměti tak funkce MemPtrNew vrátí přímo jeho adresu v paměti. Tento přístup u přemístitelných bloků zjevně nemůže fungovat, protože jejich adresa se může kdykoliv bez varování změnit. Místo toho používáme ovladače bloků paměti (memory handle). Požadujeme-li od operačního systému blok přemístitelné paměti tak manažer paměti tento blok vytvoří a vrátí ovladač bloku paměti (datový typ MemHandle). K získání bloku paměti slouží funkce MemHandleNew; pokud tato funkce vrátí nulovou hodnotu, nepodařilo se blok paměti získat. Funkce MemHandleFree vrátí blok paměti zpět operačnímu systému. MemHandle blok = MemHandleNew(1000); ... MemHandleFree(blok);
Jak se však dostaneme k obsahu tohoto bloku paměti? Velmi jednoduše. Ve chvíli, kdy si přejeme z tohoto bloku číst nebo do něj zapisovat tak jej uzamkneme na místě. Je-li přemístitelný blok paměti uzamčen na místě tak jej manažer paměti po dobu uzamčení nemůže přemisťovat. Po skončení práce blok paměti odemkneme a tím opět dovolíme operačnímu systému tento blok posouvat po operační paměti. K uzamčení bloku paměti slouží funkce MemHandleLock a k jeho odemčení funkce MemHandleUnlock. Blok může být uzamčen i vícekrát, aby jej však mohl manažer paměti přemisťovat tak musí být stejněkrát i odemčen – operační systém udržuje pro každý blok paměti údaj o tom, kolikrát byl uzamčen. Návratová hodnota funkce MemHandleLock může být bezpečně přetypována na cokoliv. Uzamčený blok paměti je možné odemknout i pomocí funkce MemPtrUnlock, která místo ovladače vyžaduje adresu počátku bloku paměti. Funkce MemHandleSize vrací velikost přemístitelného bloku paměti a funkce MemHandleResize nám dovoluje odemčený přemístitelný blok paměti zvětšit nebo zmenšit. Jednoduchý příklad použití je například předání přemístitelného bloku paměti jako parametru funkce: // Vytvoření přemístitelného bloku paměti MemHandle blok = MemHandleNew(60); if(!blok) //chyba...
44
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Uzamčení bloku + zápis dat + odemčení bloku Char* text = (Char*)MemHandleLock(blok); StrCopy(text, „Pokus“); MemHandleUnlock(blok); // Předání bloku jako parametru funkci MojeFunkce(blok); // Vrácení bloku paměti zpět operačnímu systému MemHandleFree(blok);
Ve funkci MojeFunkce pak můžeme s předaným blokem paměti pracovat zcela dle potřeb – pomocí funkce MemHandleSize zjistíme jeho velikost a případně můžeme funkcí MemHandleResize jeho velikost změnit. void MojeFunkce(MemHandle blok) { UInt16 delka = MemHandleSize(blok); if(delka < 100) { MemHandleResize(blok, 100); } StrCat((Char*)MemHandleLock(blok), „ a dalsi text.“); MemHandleUnlock(blok); }
Dosud popsané postupy zacházení s přemístitelnými a nepřemístitelnými bloky paměti se vztahovaly zatím pouze na dynamickou (operační) paměť. Pokud v naší aplikaci potřebujeme použít větší množství paměti, než kolik se nám vejde do oblasti dynamické paměti, musíme bloky paměti alokovat v oblasti určené pro uložení databází. O tom si povíme v deváté kapitole, která bude věnována databázím.
Kontrola verze operačního systému V jednotlivých verzích operačního systému PalmOS postupně přibývaly další a další funkce jádra systému. Před použitím některých funkcí, popsaných v této knize, bychom měli zkontrolovat, zda je naše aplikace spuštěna na počítači, který obsahuje určitou verzi operačního systému PalmOS. Pro usnadnění této (a podobných) kontrol, obsahuje operační systém PalmOS tabulku systémových vlastností (features). Z této tabulky můžeme zjistit charakteristiky počítače, na kterém je aplikace spuštěna - od typu procesoru a verze operačního systému až po výrobce počítače a displeje. Systémová vlastnost je 32-bitové číslo (většinou organizované jako bitové pole), které popisuje nějakou součást vašeho počítače nebo operačního systému, která je důležitá pro jiné programy. Systémová vlastnost je v tabulce charakterizována jednoznačnou identifikací aplikace, která ji „publikovala“ (Creator ID, 32-bitová konstanta vyjadřovaná často jako 4 písmena) a svým 16-bitovým číslem.
45
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Libovolná aplikace však může publikovat svoji vlastnost (přidat do tabulky vlastností) a tak umožnit ostatním aplikacím zjistit, že je nainstalována, popřípadě předat jiné důležité informace. Při odinstalování aplikace jsou systémové vlastnosti, které aplikace přidala do tabulky, vymazány. Některé vlastnosti však publikuje sám operační systém (jednoznačná identifikace systému má hodnotu sysFtrCreator); tyto vlastnosti nelze změnit a budou nás nejvíce zajímat. Některé aplikace využívají tabulku vlastností k uložení jednoduchého, často se měnícího nastavení. Vlastnost zjišťujeme voláním funkce FtrGet; funkce FtrGet vrací hodnotu 0 pokud byla vlastnost úspěšně vyzvednuta nebo hodnotu ftrErrNoSuchFeature v případě neúspěchu. UInt32 SystemovaVlastnost(UInt16 cislo) { UInt32 vlastnost;
}
if(FtrGet(sysFtrCreator, cislo, &vlastnost) == 0) { return vlastnost; } else { return 0; }
Zjišťujeme-li systémové vlastnosti, předáme jako první parametr funkci hodnotu sysFtrCreator a na místě druhého parametru například hodnotu z následující tabulky (pro úplný seznam systémových vlastností se podívejte do souboru Core/System/SystemMgr.h: Hodnota Význam a použití sysFtrNumROMVersion Hodnota této systémové vlastnosti je 0xMMmfsbbb, kde MM je hlavní číslo verze PalmOS, m je vedlejší číslo verze a f, s a bbb označuje podtypy paměti ROM. K práci se systémovou vlastností slouží makra sysGetROMVerMajor, sysGetROMVerMinor a sysMakeROMVersion. sysFtrNumProcessorID V horních 16 bitech je kód označující typ procesoru (M68328, M68EZ328, ARM, Xscale, Intel x86); tyto kódy jsou definovány v souboru SystemMgr.h. Tam jsou také definována makra sysFtrNumProcessorIs68K a sysFtrNumProcessorIsARM, která slouží k pohodlné práci s hodnotou této systémové vlastnosti. Pokud tato systémová vlastnost není definována, jedná se o PalmOS 1.0 s nejstarší verzí procesoru. sysFtrNumBacklight Pokud je nastaven nejnižší bit systémové vlastnosti, umožňuje hardware Palm Pilota podsvícení displeje. sysFtrDefaultFont Od verze PalmOS 3.0; obsahuje číslo písma, které je standardně použito k vykreslení tlačítek, textů atd. sysFtrNumDisplayDepth Od verze PalmOS 3.0; obsahuje barevnou hloubku displeje v počtu bitů na jeden obrazový bod. 46
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
UInt32 procesor, system; // Vlastnost popisující operační systém je definována vždy FtrGet(sysFtrCreator, sysFtrNumROMVersion, &system); // Kontrola na nejstarší typ procesoru if(FtrGet(sysFtrCreator, sysFtrNumROMVersion, &procesor) != 0) { procesor = sysFtrNumProcessor328; } if(sysFtrNumProcessorIs68K(procesor) && system >= sysMakeROMVersion(3,5,0,0,0)) { // Program běží na počítači s PalmOS verzí alespoň 3.5 a procesorem // Motorola }
Kontrolu verze operačního systému najdete v příkladech 1 a 2. Vaše aplikace může nastavit vlastní systémovou vlastnost pomocí funkce FtrSet, které předá vlastní jednoznačnou identifikaci, číslo vlastnosti a její 32bitovou hodnotu. Spolupracující programy pro PalmOS pak mohou jednoduše zjistit, zda je vaše aplikace instalována, případně v jaké verzi.
Čísla s pohyblivou desetinnou čárkou Kromě celočíselných proměnných potřebujeme často ve svých programech využívat i reálná čísla. Na většině počítačích s operačním systémem PalmOS je práce s celými čísly výrazně rychlejší; pro jednodušší výpočty se vyplatí používat čísla v pevné desetinné čárce (hodnota 1354 uložená v proměnné znamená 13.54, při násobení a dělení upravujeme počet desetinných míst). Operační systém PalmOS obsahuje (od verze 2.0) součást pro práci s čísly v pohyblivé desetinné čárce (typ double). V předchozích verzích PalmOS bylo potřeba tuto část operačního před použitím inicializovat. Od verze PalmOS 2.0 můžeme tato čísla standardním způsobem definovat a využívat základní aritmetické operátory bez nutnosti inicializace. double x = 3 / (2 * 3.1415927 * y);
Pro práci s čísly v pohyblivé desetinné čárce můžeme použít i několika jednoduchých funkcí, obsažených v operačním systému. Vzhledem k tomu, že hlavní proud designu počítačů s operačním systémem PalmOS směřuje do oblasti kapesních diářů, je soubor funkcí v paměti ROM pracujících s čísly v pohyblivé desetinné čárce velmi malý. Funkce operačního systému používají pro ukládání výsledků datový typ FlpCompDouble, který je binárně kompatibilní s numerickým typem double. Zjednodušená definice typu a příklad použití při volání funkce FlpFToA pro převod čísla v pohyblivé desetinné čárce na text je: typedef union { double d; FlpDouble fd; } FlpCompDouble;
47
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
... FlpCompDouble x, pi; double y; Char buffer[50]; pi.d = 3.1415927; x.d = 3.0 * pi.d * y; // Práce s čísly typu double FlpFToA(x.fd, buffer);
// Předání funkci PalmOS
Pro převod textu na číslo v pohyblivé desetinné čárce slouží funkce FlpBufferAToF, podobná jazyka C/C++. Poslední dvě funkce, které si uvedeme jsou funkci atof FlpBufferCorrectedAdd a FlpBufferCorrectedSub. Tyto funkce slouží ke sčítání a odčítání čísel v pohyblivé desetinné čárce, při kterém je výsledek, který se blíží k nule opraven na nulu; funkcím předáváme parametr, který udává o kolik se musí lišit exponenty menšího ze sčítaných nebo odčítaných čísel a výsledku, aby byl výsledek zaokrouhlen na nulu. Char* cislo_a=“12.3“; FlpCompDouble a, b, c; FlpBufferAToF(&a.fd, cislo_a); b.d = 12.3001; FlpBufferCorrectedSub(&c.fd, a.fd, b.fd, 16); // c.d je zaokrouhleno hodnotu 0.0
Práci s čísly v pohyblivé desetinné čárce ilustruje příklad 3. Komplikovanější aritmetické a geometrické funkce v paměti ROM nenajdeme; pokud je potřebujeme využít, používáme freewarovou knihovnu MathLib.
Uložení stavu aplikace (preferences) Programy spuštěné na počítačích Palm Pilot a kompatibilních vzbuzují v uživateli dojem multitaskingu. Při přepnutí hardwarovým tlačítkem do jiné aplikace nebo do správce aplikací však náš program regulérně skončí (je mu zaslána zpráva appStopEvent). Pokud se uživatel do programu „vrátí“ (opětovně jej spustí) tak očekává, že vše nalezne v takovém stavu, v jakém aplikaci opustil. Podle pořadí důležitosti je to: • Uložené uživatelské nastavení • Stejný formulář jako ten, ve kterém se nacházel při opuštění aplikace. • Hodnoty přepínačů a políček pro vstup textu jsou stejné jako byly, když uživatel aplikaci opustil. • Kursor je ve stejném políčku na stejném místě jako když uživatel aplikaci ukončil; pokud uživatel nějaký text v políčku označil, označení zůstává. Jednoduchým prostředkem, který pro toto ukládání dat poskytuje operační systém PalmOS je databáze nastavení (Preferences). Aplikace mohou při skončení uložit svůj stav (podle seznamu nahoře) do databáze nastavení a při opětovném spuštění jej z této databáze přečíst. Popsaným mechanismem vzbuzují aplikace pro PalmOS dojem, že běží „současně“. K načtení uživatelského nastavení použijeme funkci PrefGetAppPreferences, která se pokusí nahrát nastavení programu z databáze uživatelského nastavení (příklad 4). Výhodné je mít vlastní strukturu pro uložení dat aplikace:
48
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
typedef struct { ... } DataProgramu; DataProgramu DATA; ... #define ID_APLIKACE #define TYP_DAT
‚NECO‘ 1000
... UInt16 velikostDat = sizeof(DataProgramu); verze = PrefGetAppPreferences(ID_APLIKACE, TYP_DAT, &DATA, &velikostDat, true); if(verze != VERZE || velikostDat != sizeof(DataProgramu)) { MemSet(&DATA, sizeof(DataProgramu), 0); // vlastní inicializace dat }
Funkce PrefGetAppPreferences se musí vyrovnat s odlišnými verzemi aplikací, které mohou být spuštěny a odlišnými strukturami pro uložení dat. Aby se zmenšilo riziko chyby, je každé uživatelské nastavení kontrolováno podle velikosti dat a čísla verze. Při volání funkce PrefGetAppPreferences jí předáme ukazatel na číslo, obsahující velikost datové struktury; funkce vrátí číslo verze uloženého nastavení. Podle tohoto čísla verze může nová verze naší aplikace například využít část nastavení uložené starší verzí aplikace. Pokud chceme jenom zjistit verzi a velikost uloženého nastavení, uděláme to následujícím způsobem: UInt16 velikostDat = 0; cisloVerze = PrefGetAppPreferences(ID_APLIKACE, TYP_DAT, NULL, &velikostDat, true); // V databázi uživatelského nastavení jsou data aplikace verze cisloVerze a jejich // velikost je velikostDat
Uložení vlastních dat do databáze uživatelského nastavení je jednodušší; používáme k tomu funkci PrefSetAppPreferences, které předáme potřebné parametry. Vhodný čas pro uložení dat je bezprostředně před ukončením aplikace. PrefSetAppPreferences(ID_APLIKACE, TYP_DAT, VERZE, &DATA, sizeof(DataProgramu), true);
Poslední parametr obou zmíněných funkcí označuje, zda se jedná o zálohovaná data (pokud má hodnotu true). Operační systém PalmOS obsahuje ve skutečnosti dvě databáze uživatelského nastavení; jednu, která je zálohována při každé synchronizaci (saved preferences) a druhou, která je pouze dočasná (unsaved preferences). Prohlédněte si příklad 4, ve kterém si naše aplikace „pamatuje“ rozdělanou práci. V tomto příkladu vyzvedáváme data po spuštění aplikace a ukládáme je před jejím ukončením. Druhý přístup by byl ukládat data pro každý formulář zvlášť (pak by byla data načtena z databáze nastavení nebo inicializována při zpracování systémové události frmOpenEvent a ukládána při frmCloseEvent). 49
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Ladící hlášky v PalmOS Při klasickém ladění programů v jazyce C/C++ často vypisujeme ladící informace, které nám pomáhají sledovat průběh programu a hodnoty proměnných. Hlavičkový soubor Core/System/ErrMgr.h, který je automaticky vložen do zdrojového kódu vaší aplikace, definuje užitečná makra, která můžeme použít při programování PalmOS k výpisům ladících informací: Makro
Popis Zobrazí na displeji chybový dialog se zprávou. Po stisknutí tlačítka na spodku dialogu pokračuje běh programu. ErrFatalDisplay(zpráva) Zobrazí na displeji chybový dialog se zprávou a ErrFatalDisplayIf(podmínka, zpráva) s tlačítkem Reset. Po stisknutí tlačítka Reset se restartuje počítač. Funkce ErrFatalDisplayIf zobrazí chybu pouze je-li podmínka splněna. ErrNonFatalDisplay(zpráva) Zobrazí na displeji chybový dialog se zprávou; ErrNonFatalDisplayIf(podmínka, zpráva) po stisknutí tlačítka v dialogu pokračuje běh programu. Funkce ErrNonFatalDisplayIf zobrazí chybu pouze je-li podmínka splněna. ErrDisplay(zpráva)
Makra ErrFatal... používáme pro kritické chyby, u kterých nelze pokračovat dál v běhu programu; makra ErrNonFatal... slouží k ohlášení méně závažných chyb, které dovolí pokračovat v běhu programu. Uvedeme si příklad použití uvedených maker ke kontrole parametrů funkce a k jednoduššímu zápisu programu: void PouzijRetezec(Char* text) { ErrFatalDisplayIf(!text, “Špatný parametr funkce PouzijRetezec“); ErrNonFatalDisplayIf(StrLen(text) == 0, “Prázdný řetězec“); ErrNonFatalDisplayIf(StrLen(text) > 50, “Příliš dlouhý text“); } ... MemHandle ovladac = MemHandleNew(1000); ErrFatalDisplayIf(!ovladac, “Malo pameti“);
Chování těchto maker je možné ovlivnit nastavením makra ERROR_CHECK_LEVEL podle následující tabulky (makro ERROR_CHECK_LEVEL musí být definováno před vložením souboru PalmOS.h):
50
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Definice makra
ErrDisplay
ErrFatal...
ErrNonFatal...
#define ERROR_CHECK_LEVEL ERROR_CHECK_NONE
ignorováno zobrazí chybu zobrazí chybu
ignorováno zobrazí chybu zobrazí chybu
ignorováno ignorováno
#define ERROR_CHECK_LEVEL ERROR_CHECK_PARTIAL #define ERROR_CHECK_LEVEL ERROR_CHECK_FULL
zobrazí chybu
#define ERROR_CHECK_LEVEL ERROR_CHECK_PARTIAL #include <PalmOS.h>
Texty v souboru prostředků aplikace V souboru prostředků aplikace můžeme uvádět nejen definice formulářů, dialogů a dalších součástí uživatelského rozhraní, ale můžeme v něm uvést i texty, které bude naše aplikace využívat. V předchozí kapitole jsme si ukázali, jak tyto texty využít jako nápovědu dialogu nebo výzvy. Text libovolné délky definujeme v souboru prostředků aplikace za klíčovým slovem STRING. Text zapisujeme v uvozovkách; můžeme používat zvláštní znaky \n a \t pro nový řádek a tabulátor, znaky \000 až \377, kterými zadáváme přímo ASCII kód znaku v osmičkové soustavě i češtinu. Text může být i na více řádcích; v takovém případě musí být řádky ukončeny znakem zpětné lomítko. STRING ID KratkyText “kratky text“ STRING ID DlouhyText “Toto je dlouhý text, který může být použit jako “ \ “nápověda k některé funkci formuláře.\n\n“ \ “\tPoslední řádek je odsazen tabulátorem.“
V naší aplikaci můžeme text buď zobrazit, k čemuž slouží funkce FrmHelp, nebo jej zkopírovat do naší řetězcové proměnné funkcí SysCopyStringResource. void FrmHelp(UInt16 id) void SysCopyStringResource(Char *kam, Int16 id)
Uvedení všech textů pohromadě v souboru prostředků aplikace oceníme například při překladu našeho programu do jiného jazyka.
Datum a čas Práce s datem a časem ve většině operačních systémů je komplikována tím, že používají vlastní struktury pro jejich uložení. V operačním systému PalmOS může být datum použito ve třech základních formátech:
51
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Datový typ
Popis
typedef struct { Int16 second; // Int16 minute; // Int16 hour; // Int16 day; // Int16 month; // Int16 year; Int16 weekDay; } DateTimeType; typedef struct { UInt16 year :7; UInt16 month :4; UInt16 day :5; } DateType; UInt32
Struktura pro uložení kompletní informace o datu a čase.
0-59 0-59 0-23 1-31 1-12
Funkce PalmOS, které tento datový typ používají TimDateTimeToSeconds TimSecondsToDateTime
DateSecondsToDate Uložení data v 16bitové celočíselné proměnné. V prvku DateToInt year je rok uložen jako počet let, které uplynuly od roku 1904.
Počet vteřin od začátku dne prvního ledna 1904.
DateSecondsToDate TimDateTimeToSeconds TimSecondsToDateTime TimGetSeconds
Aktuální čas zjistíme pomocí funkce TimGetSeconds, která vrací počet vteřin od půlnoci 1. 1. 1904 jako 32bitovou hodnotu. Chceme-li zjistit datum a čas v konvenčnějších jednotkách, můžeme převést počet vteřin na datum pomocí funkce DateSecondsToDate nebo na datum a čas pomocí funkce TimSecondsToDateTime. Pro převod data, uloženého ve struktuře DateTimeType zpět na počet vteřin od půlnoci 1. 1. 1904 využijeme funkci TimDateTimeToSeconds. Příklad použití funkcí, které pracují s datem a časem je: DateTimeType cas; Char text[40]; TimSecondsToDateTime(TimGetSeconds(), &cas); StrPrintF(text, “je rok %d“, cas.year);
Pro převod data a času na text můžeme použít funkce operačního systému pro práci s řetězci. Operační systém PalmOS však umožňuje uživateli v aplikaci Preferences nastavit způsob zobrazení data a času a uživatel očekává, že aplikace na jeho Palm Pilotu se tomuto nastavení přizpůsobí. Proto je nejvýhodnější použít pro převod data a času na text funkce DateToAscii a TimeToAscii, které převádí datum nebo čas na řetězec s použitím některého z předdefinovaných formátů uložených v paměti ROM. Pro zjištění toho, jakému způsobu zobrazení data a času dává uživatel přednost využijeme funkci PrefGetPreference, která zjišťuje uživatelské nastavení. Tuto funkci použijeme pro zjištění formátu data (parametr má hodnotu prefDateFormat pro den a měsíc nebo prefLongDateFormat pro den, měsíc a rok) a času (prefTimeFormat).
52
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Char datum_text[50], hodiny_text[50]; DateTimeType cas; TimSecondsToDateTime(TimGetSeconds(), &cas); DateFormatType formatData = (DateFormatType)PrefGetPreference(prefLongDateFormat); TimeFormatType formatHodin = (TimeFormatType)PrefGetPreference(prefTimeFormat); DateToAscii(cas.month, cas.day, cas.year, formatData, datum_text); TimeToAscii(cas.hour, cas.minute, formatHodin, hodiny_text);
Zajímavé systémové funkce Na závěr si uvedeme několik systémových funkcí, které můžeme v naší aplikaci použít a které nepatří do žádné z ostatních skupin. První dvě funkce zobrazí na displeji klávesnici, resp. nápovědu k systému Graffiti. Typy klávesnice pro funkci SysKeyboardDialog jsou uvedeny v souboru Core/UI/Keyboard.h; typ kbdDefault slouží k zobrazení standardní klávesnice podle typu editovaného políčka. Jediný typ nápovědy Graffiti, který předáváme funkci SysGraffitiReferenceDialog je typ referenceDefault. Funkce SysReset restartuje operační systém. Operační systém PalmOS obsahuje i funkci pro generování pseudonáhodných čísel SysRandom. Pokud této funkci předáme jinou hodnotu parametru než 0, nastaví počátek řady náhodných čísel na tuto hodnotu. Potřebujeme-li v našem programu použít generátor náhodných čísel, tak po spuštění programu nastavíme generátor například takto: #ifdef TEST SysRandom(129102); // Pro testovací účely bude generována vždy stejná sekvence náhodných čísel #else SysRandom(TimGetSeconds()); // Při každém spuštění programu budou generována jiná náhodná čísla #endif
53
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Základy uživatelského rozhraní Návrh uživatelského rozhraní Prohlédněte si několik aplikací pro počítače Palm Pilot a kompatibilní a všimněte si úsporného způsobu, kterým je vytvářeno uživatelské rozhraní. Oficiální dokumentace operačního systému PalmOS obsahuje několik důležitých doporučení pro návrh uživatelského rozhraní, která si uvedeme na začátku této kapitoly. Nejdůležitější doporučení se týká velikosti displeje. Vzhledem k malému prostoru na displeji, musí aplikace zobrazovat svá data maximálně úsporným způsobem. Dosahuje se toho několika následujícími postupy: • Menu je schováno a objeví se na displeji až po doteku příslušného tlačítka v levém dolním rohu plošky pro zápis Graffiti. • Není vhodné používat (podobně jako na počítačích s Windows CE a stolních počítačích) nabídkové pruhy ikon, umístěné trvale na displeji. V novějších verzích PalmOS (od verze 4.0) se nabídkový pruh ikon zobrazí po nakreslení znaku pro zkratku (shortcut). • Používejte standardní uspořádání ovládacích prvků na displeji: tlačítka při dolním okraji, titulek formuláře a seznam kategorií nahoře. • Pokud musíte zobrazit více informací, vyhněte se oběma extrémům – jak přeplnění displeje informacemi, tak nutnosti příliš často zobrazení přepínat. Už jsme uvedli, že pro vstup dat je lepší používat tlačítka a výběr ze seznamu než zápis textu, který je na kapesních počítačích velmi pomalý. Doporučení jak usnadnit zadávání dat pro uživatele zahrnují ještě: • Minimalizujte počet kliknutí, nezbytných k provedení požadované akce. Uživatel by se měl ve vaší aplikací orientovat pokud možno intuitivním způsobem. • Pro akce, které bude dělat začátečník používající vaši aplikaci, zvolte tlačítka na spodním okraji displeje. Ostatní příkazy umístěte do menu. Využijte všechny prostředky, které máte k dispozici – jak celou plochu displeje, tak i hardwarová tlačítka pro pohyb nahoru a dolů. • Nezapomeňte, že v každém formuláři, ve kterém zadáváte text, musí být v pravém dolním rohu ukazatel stavu Graffiti. Nezapomeňte v těchto formulářích doplnit standardní kartu menu, obsahující příkazy pro práci se schránkou (clipboard). Chování všech aplikací na počítačích Palm Pilot a kompatibilních by mělo být konzistentní. Aplikace by měly při ukončení uložit svůj stav tak, aby měl uživatel při jejich opětovném spuštění dojem multitaskingu.
Základní prvky uživatelského rozhraní Základní prvky uživatelského rozhraní na počítačích Palm Pilot a kompatibilních jsou čtyři. V následující tabulce si uvedeme jejich přehled.
54
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Základní prvek uživatelského rozhraní PalmOS je formulář (form). Každá aplikace musí obsahovat alespoň jeden formulář, pomocí kterého zobrazuje data uživateli. Formulář zabírá celou plochu displeje; nahoře má titulek a dole (většinou) tlačítka pro základní akce uživatele. Formulář může obsahovat menu, které se objeví po stisknutí tlačítka v levém dolním okraji plošky pro zápis Graffiti.
Pomocí výzvy (alert) upozorňuje aplikace uživatele na závažná rozhodnutí, případně mu dává možnost odpovědět na jednoduchou otázku stiskem tlačítka vespod. Výzva je na displeji zobrazena do té doby, než ji uživatel stisknutím tlačítka potvrdí. V pravém horním rohu (písmeno i) je tlačítko pro vstup do nápovědy. Třetím základním prvkem uživatelského rozhraní je dialog (dialog, modal form). Dialog je většinou menší než formulář a je zobrazen „nad“ formulářem. Má společné prvky s výzvou (zůstává na displeji dokud uživatel nestiskne tlačítko) i s formulářem (může obsahovat libovolnou kombinaci prvků uživatelského rozhraní). Také dialog může obsahovat menu, dostupné po stisknutí příslušného tlačítka. V pravém horním rohu (písmeno i) je tlačítko pro vstup do nápovědy. Menu může být asociováno s formulářem i s dialogem. Je zobrazeno po doteku na tlačítku v levém dolním rohu plošky pro zápis Graffiti nebo na jménu formuláře.
Definice v souboru prostředků aplikace Už jsme uvedli, že základní informace o aplikaci a jejím uživatelském rozhraní definujeme v souboru prostředků aplikace. Soubor prostředků aplikace můžeme buď zapisovat ručně, nebo můžeme využít některý z programů pro grafický návrh uživatelského rozhraní. Na přiloženém CD ROM je uveden freeware program pilrcedit, napsaný v jazyce Java. Příklad návrhu formuláře v programu pilrcedit je na následujícím obrázku. Program pilrcedit ve verzi 0.42 obsahuje zatím řadu drobných chyb, které budou opraveny v dalších verzích.
55
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
V naší knize však budeme jednoduchá uživatelské rozhraní navrhovat přímo v textové podobě, bez použití grafických nástrojů. Při překladu budeme program pilrc používat s přepínačem –H, který zajistí, že program pilrc sám vytvoří hlavičkový soubor s definicemi použitých konstant. Spolu s využitím pomocných proměnných pro velikost a umístění prvků na displeji (o kterých si řekneme za chvíli) je návrh uživatelského rozhraní pomocí přímé editace souboru prostředků aplikace nejjednodušší.
Velikost a umístění na displeji Je asi zbytečné připomínat, že displej Palm Pilota má rozměry 160 × 160 obrazových bodů. Souřadnice jsou na obou osách číslovány od nuly do 159, počátek číslování je v levém horním rohu displeje. Souřadnice x a y jednotlivých obrazových bodů na displeji uvádí následující obrázek:
56
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003 0, 0
159, 0
0, 159
159, 159
Už jsme zmínili, že hlavními prvky uživatelského rozhraní aplikací pro PalmOS jsou formuláře. Formuláře jsou v podstatě všechno to co vidíte na obrazovce a prostřednictvím čeho komunikujete s aplikací: ve formulářích vyplňujete data, vybíráte z nabídky možností, používáte tlačítka apod. Zvláštním případem formulářů jsou dialogy, které slouží pro vstup dat. V každé aplikaci pro PalmOS, která komunikuje s uživatelem, musí být použit alespoň jeden formulář. Formuláře jsou v souboru prostředků aplikace definovány za klíčovým slovem FORM a jsou poskládány z jednotlivých prvků formuláře (tlačítko, přepínač, políčko pro úpravu textu apod.) Více si o formulářích povíme za chvíli. U jednotlivých prvků formulářů je nutné uvést jejich umístění na obrazovce (souřadnice levého horního rohu) a v některých případech i jejich velikost. Při uvádění těchto údajů je možné zadat jak jednoduché aritmetické výrazy tak několik pomocných proměnných, které nám tento úkol usnadňují. Definování pozice prvku na obrazovce a jeho velikosti v souboru prostředků aplikace následuje vždy po klíčovém slovu AT a jsou vždy uvedeny v závorkách a odděleny mezerou. Pokud uvádíme jen pozici levého horního rohu tak zadáváme na prvním místě pozici na ose X a na druhém místě pozici na ose Y. Pokud je potřeba zadat i velikost, následuje šířka a po ní výška prvku. Příklad obou definic, první u nastavení velikosti celého formuláře, druhá při umístění nápisu (prvek LABEL): FORM ID PrvniFormular AT ( vlevo nahore sirka vyska ) BEGIN LABEL "Text" AUTOID AT ( vlevo nahore ) END
Při uvádění pozice levého horního rohu na obrazovce můžeme použít jednoduché aritmetické výrazy a následující pomocné proměnné, které nám usnadňují logické umisťování prvků formuláře a jejich zarovnávání. (Formulář je v souboru prostředků aplikace definován po řádcích a předchozím prvkem se myslí ten který je uveden v souboru prostředků aplikace na řádku nad právě definovaným prvkem formuláře.) Pomocná proměnná CENTER
Význam Umístí prvek formuláře horizontálně (je-li uvedena na místě souřadnice na ose X) nebo vertikálně (je-li na místě souřadnice pro osu Y) na střed obrazovky. Nemůže být použita jako součást aritmetického výrazu a nemůže být použita pro obrázky.
57
Úvod do programování PalmOS
CENTER@číslo
RIGHT@číslo
BOTTOM@číslo
PREVLEFT PREVRIGHT PREVTOP PREVBOTTOM PREVWIDTH PREVHEIGHT
MUDr. Petr Lesný, 2003
Umístí prvek formuláře tak, aby jeho střed byl na uvedené pozici číslo. Můžeme uvést na místě souřadnice na ose X i souřadnice na ose Y. Nemůže být použita jako součást aritmetického výrazu ani pro umisťování obrázků do formulářů. Může být použita jen při uvádění souřadnice na ose X - umístí prvek formuláře tak, aby byl svojí pravou hranou na uvedené pozici číslo. Nemůže být použita jako součást aritmetického výrazu ani pro umisťování obrázků. Může být použita jen při uvádění souřadnice na ose Y - umístí prvek formuláře tak, aby byl svojí spodní hranou na uvedené pozici číslo. Nemůže být použita jako součást aritmetického výrazu ani pro umisťování obrázků. Pozice na ose X levé hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X pravé hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X horní hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X spodní hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Šířka předchozího prvku formuláře. Může být v aritmetických výrazech. Výška předchozího prvku formuláře. Může být v aritmetických výrazech.
Při zadávání údajů o velikosti objektu můžeme také použít pomocné proměnné. Jejich seznam uvádí následující tabulka: Pomocná proměnná AUTO PREVLEFT PREVRIGHT PREVTOP PREVBOTTOM PREVWIDTH PREVHEIGHT
Význam Doplní šířku nebo výšku objektu automaticky podle šířky/výšky písma použitého při vykreslení objektu. Nemůže být použita jako součást aritmetického výrazu Pozice na ose X levé hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X pravé hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X horní hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Pozice na ose X spodní hrany předchozího prvku formuláře. Může být v aritmetických výrazech. Šířka předchozího prvku formuláře. Může být v aritmetických výrazech. Výška předchozího prvku formuláře. Může být v aritmetických výrazech.
58
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Příklad návrhu formuláře (budeme používat jména několika prvků uživatelského rozhraní, o kterých si řekneme v následující kapitole: TITLE pro nadpis formuláře, BUTTON pro tlačítko, PUSHBUTTON pro přepínač, LABEL pro text, CHECKBOX pro políčko k zaškrtnutí a FIELD pro políčko pro editaci textu; u všech těchto prvků následuje jejich pozice a velikost v závorce za klíčovým slovem AT). FORM ID HlavniFormular AT (0 0 160 160) BEGIN TITLE "Priklad" LABEL "Priklad umisteni prvku formulare" AUTOID AT (5 20) LABEL "Barva:" AUTOID AT (5 PREVTOP+PREVHEIGHT+20) PUSHBUTTON "Cervena" AUTOID AT (PREVRIGHT+4 PREVTOP AUTO AUTO) PUSHBUTTON "Modra" AUTOID AT (PREVRIGHT+1 PREVTOP AUTO AUTO) PUSHBUTTON "Zelena" AUTOID AT (PREVRIGHT+1 PREVTOP AUTO AUTO) LABEL "Text:" AUTOID AT (5 PREVTOP+PREVHEIGHT+4) FIELD AUTOID AT (RIGHT@130 PREVTOP 80 AUTO) EDITABLE UNDERLINED BUTTON "?" AUTOID AT (140 PREVTOP AUTO AUTO) LABEL "Dalsitext:" AUTOID AT (5 PREVTOP+PREVHEIGHT+4) FIELD AUTOID AT (RIGHT@130 PREVTOP 80 AUTO) EDITABLE UNDERLINED BUTTON "?" AUTOID AT (140 PREVTOP AUTO AUTO) CHECKBOX "Prvni zaskrtavatko" AUTOID AT (5 PREVTOP+PREVHEIGHT+4 AUTO AUTO) CHECKBOX "Druhe zaskrtavatko" AUTOID AT (5 PREVTOP+PREVHEIGHT+4 AUTO AUTO) BUTTON "?" AUTOID AT (140 PREVTOP AUTO AUTO) BUTTON "Ulozit" AUTOID AT (5 BOTTOM@158 AUTO AUTO) BUTTON "Neukladat" AUTOID AT (PREVRIGHT+4 PREVTOP AUTO AUTO) END
Jednotlivé skupiny ovládacích prvků formuláře jsou odděleny pouze prázdnými řádky, protože uvnitř definice formuláře nejsou povolené komentáře. Výsledný formulář vypadá takto:
59
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Formuláře a dialogy Základním prvkem uživatelského rozhraní jsou formuláře a dialogy. Formuláře tvoří „hlavní obrazovky“ vaší aplikace. Zaujímají celou plochu displeje a v levém horním rohu mají titulek. Ve většině aplikací se mezi formuláři můžeme „přepínat“.
Při vstupu dat může být nad formulářem zobrazen dialog. Dialogy bývají většinou menší, než je plocha displeje a zastaví provádění vaší aplikace dokud uživatel nestiskne některé z tlačítek. Po dobu zobrazení dialogu není možné pracovat s formulářem na pozadí. Formulář v pozadí
Dialog
Formuláře i dialogy se v souboru prostředků aplikace definují totožně pomocí klíčového slova FORM, za kterým následuje číslo prostředku a pozice na displeji. FORM ID čísloProstředku AT (x y šířka výška) vlastnosti formuláře nebo dialogu BEGIN součásti formuláře END
Definice formulářů Formuláře musí zabírat celou plochu displeje. Jejich pozice musí být definována jako AT (0 0 160 160). Po řádku, na kterém je klíčové slovo FORM může následovat řádek uvozený klíčovým slovem MENUID, který k formuláři přiřazuje příslušné menu, které je definováno v souboru prostředků aplikace. FORM ID čísloProstředku AT (0 0 160 160) MENUID čísloProstředkuMenu BEGIN TITLE “Titulek” součásti formuláře END
60
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Zobrazení formulářů na displeji Popíšeme si typické použití formulářů v aplikaci pro operační systém PalmOS. Formuláře jsou uloženy v databázi prostředků aplikace v komprimované podobě; každý formulář je označen svým číslem prostředku (ID). Pomocí funkce FrmInitForm, které předáme číslo prostředku formuláře, vytvoříme v paměti strukturu formuláře FormType, na kterou se dále odkazujeme pomocí ukazatele FormPtr. Formulář můžeme zobrazit na displeji pomocí funkce FrmDrawForm. Máme-li v paměti vytvořenou datovou strukturu formuláře, můžeme pomocí funkce FrmSetActiveForm sdělit operačnímu systému, že tento formulář má být aktivní – to znamená, že komunikuje s uživatelem. V naší aplikaci můžeme vyzvednout ukazatel na data aktivního formuláře pomocí funkce FrmGetActiveForm. Každý formulář musí mít definovánu příslušnou funkci formuláře, která zpracovává systémové události (typicky vstup od uživatele) v době, kdy je formulář aktivní. Funkci formuláře musíme nastavit pomocí FrmSetEventHandler. Datovou strukturu formuláře můžeme smazat pomocí funkce FrmDeleteForm; při běžném použití formulářů to však za nás udělá automaticky operační systém PalmOS. Typická funkce, která nastaví nový aktivní formulář se musí postarat o inicializaci dat formuláře a o nastavení správné funkce formuláře: void NahrajFormular(UInt16 cisloProstredku) { // Inicializuj data formuláře a nastav formulář jako aktivní FormPtr formular = FrmInitForm(cisloProstredku); FrmSetActiveForm(formular); // Nastav funkci formuláře
}
if(cisloProstredku == PrvniFormular) { FrmSetEventHandler(formular, FunkcePrvnihoFormulare); } else if(cisloProstredku == DruhyFormular) { FrmSetEventHandler(formular, FunkceDruhehoFormulare); } // atd.
Vyskytne-li se požadavek na zobrazení nového aktivního formuláře, zašle operační systém PalmOS naší aplikaci systémovou událost frmLoadEvent. V položce data.frmLoad.formID je uloženo číslo prostředku formuláře, který má naše aplikace zobrazit. Událost frmLoadEvent musíme ošetřit přímo ve smyčce zpracování událostí. Úplná podoba smyčky zpracování událostí, která se v různých obměnách vyskytuje ve všech aplikacích pro PalmOS je tedy: void SmyckaZpracovaniUdalosti() { EventType udalost; Err chyba;
61
Úvod do programování PalmOS
do {
MUDr. Petr Lesný, 2003
EvtGetEvent(&udalost, evtWaitForever); if(!SysHandleEvent(&udalost)) { if(!MenuHandleEvent(NULL, &udalost, &chyba)) { if(udalost.eType == frmLoadEvent) { NahrajFormular(udalost.data.frmLoad.formID); } else { FrmDispatchEvent(&udalost); } } }
}
} while(udalost.eType != appStopEvent);
V této smyčce vyzvedneme funkcí EvtGetEvent novou systémovou událost z fronty událostí a nabídneme ji ke zpracování operačnímu systému (funkce SysHandleEvent a MenuHandleEvent). Pokud PalmOS událost nezpracuje tak otestujeme zda se nejedná o systémovou událost frmLoadEvent, kterou když přijmeme tak musíme nastavit nový aktivní formulář na displeji. Všechny ostatní události pak pomocí funkce FrmDispatchEvent zašleme funkci aktivního formuláře.
Události formuláře a funkce formuláře Již jsme zmínili systémovou událost frmLoadEvent, která vyzývá naší aplikaci k nahrání nového aktivního formuláře. Tuto systémovou událost zpracováváme přímo ve smyčce zpracování událostí. Všechny ostatní události, spojené se zobrazením formulářů již jsou doručeny přímo správné funkci formuláře. Každý formulář, který naše aplikace používá, musí mít definovánu svoji funkci formuláře. Jednoduše lze říci, že ve funkci formuláře zpracováváme systémové události, ke kterým dojde v době, kdy je příslušný formulář aktivní – například stisknutí tlačítka ve formuláři. Minimální funkce formuláře je definována takto: Boolean FunkcePrvnihoFormulare(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); return true;
}
}
default: // Všechny ostatní události nás nezajímají return false;
62
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce formuláře vrací logickou hodnotu true tehdy, pokud systémovou událost zpracuje; vrácená logická hodnota false znamená, že systémovou událost má zpracovat operační systém PalmOS. V každé funkci formuláře musíme povinně zpracovat jedinou systémovou událost a tou je frmOpenEvent. Tato událost je vůbec první systémovou událostí, kterou funkce formuláře dostane; může ji využít k inicializaci prvků formuláře a k vykreslení aktivního formuláře na displeji funkcí FrmDrawForm. Odpovídající systémovou událostí frmCloseEvent, která je naopak poslední událostí, kterou funkce formuláře obdrží, se ve většině případů nemusíme zabývat. Operační systém PalmOS tuto událost zpracuje sám a odstraní aktivní formulář z paměti. Při běžném použití formulářů nemusíme funkci FrmDeleteForm volat sami. Události frmOpenEvent a frmCloseEvent se navzájem doplňují. Pokud potřebujeme mít po dobu zobrazení formuláře přístup k velkému bloku paměti, můžeme jej získat od operačního systému při zpracování události frmOpenEvent a vrátit jej operačnímu systému při zpracování frmCloseEvent. MemHandle gDataFormulare; Boolean FunkcePrvnihoFormulare(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: gDataFormulare = MemHandleNew(10000); FrmDrawForm(FrmGetActiveForm()); return true; case frmCloseEvent: MemHandleFree(gDataFormulare); return false;
}
}
default: // Všechny ostatní události nás nezajímají return false;
Při zpracování události frmCloseEvent musí funkce formuláře vrátit logickou hodnotu false, která informuje operační systém o tom, že má tuto událost zpracovat. Pokud bychom vrátili true, operační systém bude tuto událost ignorovat a nevymaže data formuláře z paměti. Podobný mechanismus můžeme použít pro vyzvednutí a uložení uživatelského nastavení pro každý formulář zvlášť, pro vytvoření a smazání oken (viz kapitola o kreslení) ve formuláři a podobně.
Přepínání mezi formuláři Poté, co jsme vyřešili práci s formuláři na nejnižší úrovni, můžeme v naší aplikaci použít pro jednoduché přepínání mezi formuláři funkci FrmGotoForm. Této funkci předáme číslo prostředku formuláře, který si přejeme zobrazit; funkce uloží do fronty událostí následující tři systémové události: 63
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
1. frmCloseEvent – tato systémová událost je zaslána právě aktivnímu formuláři a způsobí, že jej operační systém vymaže z paměti a z displeje. 2. frmLoadEvent – tuto systémovou událost v naší aplikaci zpracujeme ve smyčce zpracování událostí tak, že inicializujeme nový aktivní formulář a nastavíme příslušnou funkci formuláře. 3. frmOpenEvent – tato systémovou událost již je doručena funkci nového aktivního formuláře a v naší aplikaci na ní reagujeme tak, že formulář vykreslíme na displeji funkcí FrmDrawForm. Funkci FrmGotoForm typicky voláme po spuštění aplikace pro výběr prvního zobrazeného formuláře. Na závěr naší aplikace pak zavoláme funkci FrmCloseAllForms, která zašle systémovou událost frmCloseEvent všem formulářům, které jsou inicializovány. Jednoduchá funkce PilotMain tedy může vypadat: UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { if (cmd == sysAppLaunchCmdNormalLaunch) { FrmGotoForm(PrvniFormular); // Výběr prvního zobrazeného formuláře ZpracovaniUdalosti(); // Smyčka zpracování událostí FrmCloseAllForms(); // Zrušení všech aktivních formulářů } }
return 0;
Vytvoříme nyní jednoduchou aplikaci, která bude přepínat mezi dvěma formuláři (příklad 2). Trochu předběhneme a řekneme si, že dotkneme-li se perem displeje tak operační systém PalmOS zašle naší aplikaci systémovou událost penDownEvent. Vytvoříme nyní aplikaci, která při doteku perem přepíná mezi dvěma formuláři na displeji. Nejprve vytvoříme soubor prostředků aplikace, ve kterém budou definovány dva formuláře (klíčové slovo LABEL slouží ke zobrazení textu ve formuláři; jeho pozice je za AT a AUTOID znamená, že nás číslo prostředku tohoto textu nezajímá): APPLICATIONICONNAME ID 1000 "Priloha" VERSION ID 1000 "1.0" APPLICATION ID 1000 "NECO" ICON "main.bmp" FORM ID BEGIN TITLE LABEL LABEL END
PrvniFormular AT (0 0 160 160) "Prvni" "Toto je PRVNI formular" AUTOID AT (20 50) "dotkni se dipleje..." AUTOID AT (20 140)
64
Úvod do programování PalmOS FORM ID BEGIN TITLE LABEL LABEL END
MUDr. Petr Lesný, 2003
DruhyFormular AT (0 0 160 160) "Druhy" "Toto je DRUHY formular" AUTOID AT (20 70) "dotkni se dipleje..." AUTOID AT (20 140)
Při překladu tohoto souboru prostředků aplikace nesmíme zapomenout volat program pilrc s parametrem –H. Tak zajistíme, že program pilrc vytvoří hlavičkový soubor obsahující definici konstant PrvniFormular a DruhyFormular. Tento hlavičkový soubor vložíme příkazem #include do zdrojového textu naší aplikace. Pro každý z formulářů pak definujeme vlastní funkci formuláře: #include <PalmOS.h> #include "main.h" UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { if (cmd == sysAppLaunchCmdNormalLaunch) { FrmGotoForm(PrvniFormular); ZpracovaniUdalosti();
}
FrmCloseAllForms(); } return 0;
void ZpracovaniUdalosti() { // Definována výše } void NahrajFormular(UInt16 id) { // Definována výše } Boolean FunkcePrvnihoFormulare(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); return true; case penDownEvent: FrmGotoForm(DruhyFormular); return true;
}
}
default: return false;
65
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Boolean FunkceDruhehoFormulare(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); return true; case penDownEvent: FrmGotoForm(PrvniFormular); return true;
}
}
default: return false;
Po spuštění aplikace přejdeme do prvního formuláře. Dotkneme-li se v prvním formuláři displeje, je aktivován a zobrazen druhý formulář. Dotkneme-li se ve druhém formuláři displeje, vrátíme se zpět do formuláře prvního. Při přechodu z jednoho formuláře do druhého můžeme vyzvednout nebo naopak uložit data a podobně.
Definice dialogů Dialogy jsou definovány podobně jako formuláře, pomocí klíčového slova FORM. Při definici nezáleží na jejich velikosti. Uživatelé jsou zvyklí, že dialogy se objevují „nad“ formuláři, je proto výhodné definovat šířku a výšku dialogů menší, než je velikost displeje. Dialogy bývají většinou zarovnány s dolním okrajem displeje. Rozdíl proti formulářům je v uvedení klíčového slova MODAL mezi vlastnostmi formuláře/dialogu. Podobně jako při definici formuláře můžeme uvést klíčové slovo MENUID, za kterým bude následovat číslo prostředku menu, které můžeme vyvolat při zobrazení tohoto dialogu. Novou vlastností dialogů je možnost připojit nápovědu. Nápověda je v souboru prostředků aplikace definována jako textová konstanta (klíčovým slovem STRING). Pokud mezi vlastnostmi dialogu uvedeme klíčové slovo HELPID, následované číslem prostředku textu nápovědy, je v pravém horním rohu titulku zobrazeno písmeno i pro zobrazení nápovědy.
66
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
STRING ID TextNapovedy “Toto je text napovedy, ktery se zobrazi “ \ “po kliknuti na pismeno (i) v pruhu titulku” FORM ID čísloProstředkuFormuláře AT (5 80 150 78) MODAL MENUID čísloProstředkuMenu HELPID TextNapovedy DEFAULTBTNID čísloProstředkuTlačítka BEGIN TITLE “Titulek” součásti dialogu END
Další důležitá vlastnost dialogu, kterou bychom měli definovat je označení tlačítka, jehož stisknutí bude simulováno při ukončení aplikace (DEFAULTBTNID). Připomeňme si, že dialog zůstává na displeji do té doby, dokud jej stiskem tlačítka nezrušíme. Pokud ukončíme naší aplikaci v době, kdy je na displeji zobrazen dialog, bude operační systém simulovat stisknutí tlačítka, jehož číslo prostředku nastavíme za klíčovým slovem DEFAULTBTNID. Většinou takto simulujeme stisk tlačítka pro zrušení změn.
Použití dialogů Ke zobrazení dialogů na displeji slouží funkce FrmDoDialog. Před použitím této funkce musíme dialog inicializovat (FrmInitForm) a nastavit počáteční hodnoty ovládacích prvků dialogu: hodnoty přepínačů, texty políček a podobně. Pak vyvoláme funkci FrmDoDialog, která zobrazí dialog na displeji a nechá uživatele hodnoty změnit. Když uživatel stiskne některé tlačítko tak funkce FrmDoDialog smaže dialog z displeje a vrátí číslo prostředku tlačítka, které uživatel stisknul. Po použití musíme dialog vymazat z paměti funkcí FrmDeleteForm. Příklad 3 uvádí jednoduché použití dialogu ve vaší vlastní aplikaci. V souboru prostředků aplikace je definován jednoduchý dialog (klíčové slovo BUTTON slouží ke vložení tlačítka; číslo prostředku tlačítka následuje za ID a pozice na displeji za AT): STRING ID NapovedaDialogu "Toto je napoveda k dialogu" FORM ID PrvniDialog AT (5 80 150 78) MODAL HELPID NapovedaDialogu DEFAULTBTNID TlacitkoZrus BEGIN TITLE "Dialog" BUTTON "Potvrd" ID TlacitkoPotvrd AT (10 60 AUTO AUTO) BUTTON "Zrus" ID TlacitkoZrus AT (PREVRIGHT+5 PREVTOP AUTO AUTO) END
Pro použití definovaného dialogu v naší aplikaci definujeme novou funkci ZavolejDialog, ve které dialog vytvoříme, zobrazíme a po použití zrušíme. Funkci ZavolejDialog poté spustíme z funkce formuláře při zpracování události penDownEvent (dotek pera na displeji):
67
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void ZavolejDialog() { FormPtr formular = FrmInitForm(PrvniDialog); // Tady muzeme nastavit ovladaci prvky dialogu if(FrmDoDialog(formular) == TlacitkoPotvrd) { // Uzivatel stiskl tlacitko "Potvrd" - zjistime // hodnoty ovladacich prvku formulare a treba je uložíme } FrmDeleteForm(formular); }
Po spuštění aplikace se zobrazí formulář, podobný předchozímu příkladu. Dotkneme-li se perem formuláře, PalmOS pošle naší aplikaci systémovou událost penDownEvent a funkce ZavolejDialog zobrazí dialog na displeji. Po stisknutí jednoho ze dvou tlačítek se vrátíme do původního formuláře. V dialogu můžeme použít nápovědu.
Předávání dat mezi formuláři Typická aplikace je tvořena více formuláři a dialogy. Jako příklad si můžeme uvést vestavěnou aplikaci MemoPad, která je tvořena dvěma základními formuláři: tabulkou poznámek a zobrazením jedné poznámky. Mezi formuláři se přepínáme pomocí funkce FrmGotoForm.
Při psaní zdrojového textu aplikace musíme mít stále na paměti, že většina činností programu musí být i v tomto případě přiřazena k některému z formulářů aplikace a k některé události, kterou formulář zpracovává. Naše aplikace nikdy nemá přístup ke dvěma formulářům současně. 68
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Proto musíme pro předávání dat mezi formuláři využít globální proměnné, jako v následujícím zjednodušeném příkladu: Char gTextFormulare[500]; Boolean FunkceFormulareSeznam(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); return true; case ctlSelectEvent: if(udalost->data.ctlSelect.controlID == TlacitkoUprav) { // ulož do proměnné gTextFormulare text z databáze ... FrmGotoForm(FormularUprav); } return true;
}
}
default: return false;
Boolean FunkceFormulareUprav(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: // Nastav text ve formuláři z globální proměnné gTextFormulare ... FrmDrawForm(FrmGetActiveForm()); return true; case ctlSelectEvent: if(udalost->data.ctlSelect.controlID == TlacitkoUloz) { // ulož změněný text do databáze ... FrmGotoForm(FormularSeznam); } else if(udalost->data.ctlSelect.controlID == TlacitkoZrus) { // Návrat beze změny FrmGotoForm(FormularSeznam); } return true;
}
}
default: return false;
69
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Při volání dialogů je situace jednodušší. Dialog voláme z funkce formuláře a můžeme nastavit jeho ovládací prvky podle potřeby:
V naší aplikaci je to řešeno jednodušeji: Boolean FunkceFormulareUprav(EventPtr udalost) { switch(udalost->eType) { ... case ctlSelectEvent: if(udalost->data.ctlSelect.controlID == TlacitkoDetaily) { FormPtr novyFormular = FrmInitForm(DialogDetaily); if(FrmDoDialog(novyFormular) == TlacitkoOK) { // ulož změněné detaily } FrmDeleteForm(novyFormular); } return true;
}
}
default: return false;
Výzvy (alerts) Prostřednictvím výzev komunikuje naše aplikace s uživatelem: předkládá mu informace, varování a jednoduché dotazy. Výzva je zobrazena – podobně jako dialog – „nad“ právě aktivním formulářem; podobně jako dialog má titulek (s možností tlačítka nápovědy) a jedno až tři tlačítka. V souboru prostředků aplikace definujeme výzvu pomocí klíčového slova ALERT.
70
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
ALERT ID číslo prostředku výzvy typ výzvy (INFORMATION, CONFIRMATION, ERROR nebo WARNING) DEFAULTBUTTON pořadové číslo tlačítka zleva HELPID číslo prostředku textu nápovědy BEGIN TITLE "Titulek" MESSAGE "Text, který je v těle výzvy" BUTTONS "Prvni" "Druhe" "Treti" END
Když se uživatel rozhodne opustit naší aplikaci v době, kdy je výzva zobrazena na displeji, simuluje operační systém stisk tlačítka, jehož pořadové číslo zleva jsme zadali za DEFAULTBUTTON. Přejeme-li si doplnit nápovědu, definujeme ji v souboru prostředků aplikace (pomocí klíčového slova STRING) a uvedeme číslo tohoto prostředku za klíčovým slovem HELPID. Jednotlivé typy výzev se liší ikonou, která je zobrazena vlevo vedle textu. Uživatel je většinou zvyklý na jednotný vzhled aplikací a proto vždy pečlivě volte typ výzvy podle následující tabulky: Klíčové slovo INFORMATION
Popis Pomocí této výzvy sdělujeme uživateli jednoduchou informaci – například upozornění pokud udělá chybný nebo nelogický krok. Většinou uvádíme jediné tlačítko s textem „OK“.
CONFIRMATION
U tohoto typu výzvy uvádíme tlačítek více; uživateli klademe potvrzující dotaz na nedestruktivní činnost programu. Tlačítko „OK“ bývá většinou vlevo. Varování nebo upozornění na destruktivní činnost programu. Většinou jej používáme pro varování uživatele před nevratnými kroky. U tohoto typu výzvy nesmíme zapomenout uvést správné číslo tlačítka za DEFAULTBUTTON. Chyby uživatele nebo aplikace. Můžeme zde mít jak jediné tlačítko „OK“, tak i více tlačítek, například pro opakování nebo zrušení požadované akce.
WARNING
ERROR
Příklad
V naší aplikaci pak výzvu zavoláme pomocí funkce FrmAlert, které předáme číslo ¨prostředku výzvy. Funkce pak vrátí pořadové číslo stisknutého tlačítka zleva. if(FrmAlert(DotazNaVymazani) == 0) { // vymaž... }
71
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce FrmCustomAlert umožňuje vkládat vlastní řetězce do textu výzvy. Pokud v textu výzvy uvedeme zástupné znaky “^1“ až “^3“, budou nahrazeny odpovídajícím parametrem (druhým až čtvrtým) funkce FrmCustomAlert. Pokud použijeme v textu výzvy zástupné znaky a nepoužijeme ke zobrazení výzvy funkci FrmCustomAlert, dojde k chybě a k restartu operačního systému. Také funkce FrmCustomAlert vrací pořadové číslo stisknutého tlačítka zleva. ALERT ID UniverzalniChyba ERROR DEFAULTBUTTON 0 BEGIN TITLE "Chyba" MESSAGE "Doslo k chybe ^1." BUTTONS "Hmm" END
Takto definovanou výzvu musíme zobrazit pomocí funkce FrmCustomAlert; prvním parametrem funkce je číslo prostředku, které označuje zobrazenou výzvu. Druhý až čtvrtý parametr musí být definován, pokud použijeme odpovídající zástupný znak; pokud zástupný znak nepoužijeme, musí mít odpovídající parametr hodnotu NULL. Char textChyby[40]; FrmCustomAlert(UniverzalniChyba, textChyby, NULL, NULL);
Menu Vlevo dole u plochy pro zápis Graffiti je na počítačích Palm Pilot a kompatibilních umístěné tlačítko sloužící k vyvolání uživatelské nabídky menu. U novějších modelů s PalmOS 3.5 je možné menu vyvolat i dotekem na titulku formuláře. Příklad uživatelské nabídky v programu MemoPad je na následujícím obrázku: Jednotlivé karty menu. Aktivní karta je zvýrazněna.
Zkratky pro vyvolání příkazů (shortcuts) Oddělovač (separator)
Příkazy na kartě menu.
Pro definování menu v souboru prostředků aplikace používáme klíčové slovo MENU, za kterým následuje číslo prostředku menu. Menu je uspořádáno do jednotlivých karet (klíčové slovo PULLDOWN), podobně jako bude zobrazeno na displeji. Definice menu je následující:
72
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
MENU ID čísloProstředkuMenu BEGIN PULLDOWN "První" BEGIN jednotlivé příkazy menu END PULLDOWN "Druhá" BEGIN jednotlivé příkazy menu END END
Pro definici jednoho příkazu menu používáme klíčové slovo MENUITEM, za kterým následuje jméno příkazu a číslo prostředku příkazu (tuto hodnotu předá PalmOS naší aplikaci při výběru z menu). Na konci řádku může být písmeno pro zkrácenou formu příkazu (shortcut). Kombinace klíčových slov MENUITEM SEPARATOR vykreslí oddělující čáru. MENUITEM "Jméno" ID čísloProstředkuMenu [ "Z" ] MENUITEM SEPARATOR
Ke každé položce menu může být přiřazen zkrácený příkaz. Zkrácené příkazy vyvoláme tahem Graffiti , za kterým následuje jedno písmeno nebo číslice. Pro programátora jsou zkrácené příkazy zajímavé hlavně tím, že se jimi nemusí zabývat. Operační systém PalmOS, který řídí zobrazování menu na displeji a reaguje na akce uživatele, zpracuje zkrácený příkaz sám. Pokud uživatel zvolí zkrácený příkaz, je vyvolána událost menuEvent úplně stejně jako když zvolí příslušný příkaz z uživatelské nabídky. Pro správné použití menu ve vaší aplikaci můžeme uvést čtyři základní doporučení: 1. Příkazy na jednotlivých kartách menu by měly být seskupeny podle logické souvislosti. 2. Pokud je nějaká funkce dostupná pomocí tlačítka ve formuláři, neuvádíme ji v menu. 3. Je-li ve formuláři uvedeno políčko pro editaci textu, musí být v menu uvedena karta Editace, obsahující příkazy pro práci se schránkou (více v následující kapitole). 4. U programů, které jsou distribuovány jako shareware nebo freeware by měl být součástí uživatelské nabídky příkaz nazvaný O programu, který bude uživatele informovat o podmínkách šíření programu.
Systémové události menu Poté co uživatel zvolí příkaz menu (nebo použije zkrácenou volbu příkazu), zašle operační systém naší aplikaci zprávu menuEvent. Zprávu menuEvent budeme většinou zpracovávat ve funkci formuláře, ke kterému je menu připojeno. Jediný datový prvek zprávy, který nás bude zajímat je data.menu.itemID, ve kterém je uloženo číslo prostředku příkazu menu, který byl zvolen. Pokud naše aplikace zpracovává události menu, musí být ve smyčce zpracování událostí použita funkce MenuHandleEvent, která řídí zpracování událostí menu nezávislých na naší aplikaci. Nesmíme zapomenout na klíčové slovo MENUID ve vlastnostech formulářů a dialogů,
73
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
které budou příslušné menu používat (jedno menu může být společné pro více formulářů). Ve funkci formuláře zpracováváme menu například takto: Boolean FunkceHlavnihoFormulare(EventPtr udalost) { switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); return true;
} }
case menuEvent: if(udalost->data.menu.itemID == MenuOProgramu) { FrmAlert(VyzvaOProgramu); return true; } else if(udalost->data.menu.itemID == MenuOKnize) { FrmAlert(VyzvaOKnize); return true; } break; ...
return false;
74
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Prvky formuláře a dialogu Přehled V následující tabulce si uvedeme přehled prvků, které mohou být umístěny na formulářích nebo v dialozích. Chování všech prvků je společné: pokud s nimi uživatel pracuje (píše text, stiskne tlačítko) tak operační systém PalmOS zasílá naší aplikaci příslušné systémové zprávy. Některé zprávy (například při psaní textu) můžeme ignorovat; na jiné zprávy v naší aplikaci reagujeme. Pomocí funkcí, které si uvedeme, můžeme nastavovat a číst hodnoty prvků dialogu, které si pamatují svoji hodnotu: políček pro zápis textu, přepínačů atd. Mezi řádky obsahujícími začátek a konec seznamu prvků formuláře (BEGIN a END) nesmí být uvedeny komentáře. Definice každého prvku formuláře, včetně všech jeho vlastností, musí být uvedena na jednom řádku. Referenční kartičku, která obsahuje seznam základních prvků formuláře naleznete v příloze D. Prvek formuláře Titulek
Klíčové slovo, pomocí kterého jej definujeme v souboru prostředků aplikace TITLE
Text
LABEL
Tlačítko Opakující tlačítko Přepínač Políčko k zaškrtnutí Tlačítko volby ze seznamu Tlačítko volby textu Klouzající tlačítko Políčko pro vstup textu
BUTTON REPEATBUTTON PUSHBUTTON CHECKBOX POPUPTRIGGER
Seznam
LIST
Obrázek
FORMBITMAP
Tabulka
TABLE
Posuvník
SCROLLBAR
Ukazatel stavu graffiti
GRAFFITISTATEINDICATOR
SELECTORTRIGGER SLIDER FIELD
75
Příklad
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Definice a společné vlastnosti Prvky formulářů a dialogů definujeme mezi klíčovými slovy BEGIN a END; každý prvek musí být definován na samostatném řádku. Řádek obsahující prvek začíná klíčovým slovem z předchozí tabulky a pokračují jednotlivé vlastnosti prvku. Vlastnost ID čísloProstředku AUTOID AT ( x y šířka výška )
USABLE NONUSABLE DISABLED
LEFTANCHOR RIGHTANCHOR FONT čísloPísma
Význam Konstanta nebo 16bitové číslo, které jednoznačně identifikuje prvek v rámci dialogu nebo formuláře. Musí být uvedeno jako první vlastnost prvku. Můžeme uvést místo identifikace prvku, pokud nás jeho číslo nezajímá. Program pilrc přiřadí prvku automatické číslo, které však nikam neukládá. Pozice a velikost prvku na displeji. Při definici pozice i velikosti můžeme s výhodou používat pomocné proměnné, uvedené v předchozí kapitole. Musí být uvedené jako druhá vlastnost prvku. Pokud chceme, aby byl prvek při zobrazení formuláře také zobrazen. Tuto vlastnost nemusíme uvádět, rozumí se automaticky. Pokud chceme, aby při zobrazení formuláře byl příslušný prvek skryt. Prvky, které mají tuto vlastnost, jsou zobrazeny ve formuláři, ale nereagují na vstup uživatele (například pokud používáme políčko pro vstup textu k zobrazení výsledků). Při změně velikosti po nastavení nového textu (tlačítko pro výběr ze seznamu, tlačítko volby textu) bude ponechána levá hranice prvku. Při změně velikosti po nastavení nového textu bude ponechána pravá hranice prvku a prvek se bude „zvětšovat“ směrem doleva. Nastaví písmo, které bude použito k vykreslení textu v prvku formuláře nebo dialogu. Pokud tuto volbu neuvedeme, bude použito standardní písmo (FONT 0).
Podrobněji se písmům, které můžeme používat na počítačích s operačním systémem PalmOS budeme věnovat v osmé kapitole při popisu grafiky. Zde si jen uvedeme tabulku základních osmi typů písem, které můžeme při definování ovládacích prvků formuláře nebo dialogu použít: Definice typu písma FONT 0
Příklad
Poznámka Úplně obyčejné a nejběžnější písmo, které PalmOS používá. Toto písmo bude použito pokud neuvedete jiné. Tučné písmo - stejně vysoké jako předchozí, ale výraznější. Často se používá pro zobrazení jmen políček.
FONT 1
76
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
FONT 2 FONT 3-5
Vysoké písmo. Tři písma se symboly, které jsou ukázány v následující tabulce.
77
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
FONT 6
Velké tučné číslice (použité v aplikaci PalmOS kalkulačka). Velké a tučné, opravdu výrazné písmo (od verze PalmOS 3.0).
FONT 7
Při uvádění symbolů používáme v řetězci standardní C/C++ zápis čísla v osmičkové soustavě. V následující tabulce jsou uvedeny symboly, které můžeme použít, spolu s příslušnou oktalovou konstantou.
Pro zobrazení dvou opakovacích tlačítek (REPEATBUTTON), která budou vedle sebe a budou obsahovat plnou šipku zpět a dopředu použijeme například následující definici: REPEATBUTTON "\002" ID TlacitkoZpet AT (30 100 AUTO AUTO) FONT 4 REPEATBUTTON "\003" ID TlacitkoVpred AT (PREVRIGHT+1 PREVTOP AUTO AUTO) FONT 4
Práce s prvky dialogů a formulářů Abychom mohli používat prvky dialogů a formulářů (číst a nastavovat text prvků, stav tlačítek a podobně) používáme funkce operačního systému PalmOS. Pro zkomplikování práce programátorů asi polovina funkcí pracujících s prvky formuláře používá pořadové číslo (index) prvku ve formuláři nebo dialogu. Parametrem druhé poloviny funkcí je naopak identifikační číslo prvku formuláře (uvedeno za ID). Pro převod mezi pořadovým číslem prvku a jeho identifikačním číslem slouží funkce FrmGetObjectId a FrmGetObjectIndex. Obě tyto funkce vyžadují jako první parametr ukazatel na data formuláře, s jehož prvky pracují; nejsnazší cestou jak tento ukazatel zjistit je volat funkci FrmGetActiveForm, která vrátí ukazatel na data právě aktivního formuláře. Mějme například definován následující formulář: FORM ID FormularZakladni AT (0 0 160 160) BEGIN TITLE "Akce" LABEL "Vyberte akci" AUTOID AT (CENTER@80 20) BUTTON "Akce 1" ID Tlac1 AT (CENTER@80 PREVBOTTOM+20 AUTO AUTO) BUTTON "Akce 2" ID Tlac2 AT (CENTER@80 PREVBOTTOM+20 AUTO AUTO) END
78
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Tento formulář obsahuje čtyři prvky: titulek (TITLE) s indexem 0, statický text (LABEL), jehož identifikační číslo nás nezajímá (AUTOID) s indexem 1 a dvě tlačítka (BUTTON), která jsou jednoznačně identifikována konstantami Tlac1 a Tlac2 na pozicích 2 a 3. Pro práci s těmito prvky ve funkci formuláře můžeme použít: index = FrmGetObjectIndex(FrmGetActiveForm(), Tlac1); // index je rovno 2
Funkce FrmGetObjectPtr zjistí ukazatel na datovou strukturu popisující příslušný prvek formuláře (u tlačítek je to ControlPtr); tento ukazatel budeme používat u většiny funkcí, které budou s tlačítky používat. Pokud to shrneme, tak pro práci s prvky formuláře se musíme orientovat mezi: • Identifikačním číslem prvku (konstanta za ID); je-li program pilrc spuštěn s parametrem –H, tak vytvoří hlavičkový soubor s definicemi všech těchto konstant. V opačném případě musíme konstanty definovat sami v hlavičkovém souboru, který příkazem #include vložíme do souboru prostředků aplikace i do zdrojového textu. Práce s těmito konstantami je názorná, pro volání většiny funkcí je však musíme převést na index prvku nebo na ukazatel na jeho data. • Pořadovým číslem (indexem) prvku ve formuláři. Většina funkcí, které pracují obecně s prvky dialogů a formulářů bude vyžadovat právě toto pořadové číslo. Pořadové číslo prvku zjistíme z jeho identifikačního čísla voláním funkce FrmGetObjectIndex. • Ukazatel na data prvku, se kterým pracují specializované funkce. Tento ukazatel (datový typ ControlPtr pro tlačítka, FieldPtr pro políčka textu a podobně) získáme pomocí funkce FrmGetObjectPtr, které předáme pořadové číslo prvku. V řadě našich programů se nám bude hodit funkce, která přímo převádí identifikační číslo prvku na ukazatel na jeho data, podobně jako v následujícím příkladu: MemPtr Objekt(UInt16 prvek) { FormPtr formular = FrmGetActiveForm(); UInt16 index = FrmGetObjectIndex(formular, prvek); return FrmGetObjectPtr(formular, index); }
Manažer formulářů v sobě obsahuje řadu užitečných funkcí, které pracují s prvky formulářů obecně. Kromě již uvedených funkcí se nám bude hodit například funkce FrmSetObjectPosition, která nastaví umístění prvku na displeji a funkce FrmShowObject a FrmHideObject, které umí zobrazit a skrýt prvek formuláře. Všechny tyto funkce pracují s indexy prvků formuláře. Typ prvku Všechna tlačítka, políčka k zaškrtnutí a přepínače Seznam Políčka pro úpravu textu Posuvník Tabulka
79
Datový typ, na který musíme přetypovat hodnotu vrácenou funkcí Objekt. ControlPtr ListPtr FieldPtr ScrollBarPtr TablePtr
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Statický text Statický text definujeme za klíčovým slovem LABEL. Pro zobrazení výsledků je jednodušší použít políčka textu; statické texty používáme pouze jako popisky. Při definici pozice textu na displeji uvádíme pouze souřadnice levého horního rohu, vše ostatní dopočítá program pilrc automaticky. LABEL "Text:" AUTOID AT (x y) [ FONT písmo ] [ NONUSABLE ]
Tlačítka V definici dialogu používáme pro definici tlačítek klíčové slovo BUTTON. Kromě obecných vlastností, které jsme si uvedli dříve v této kapitole můžeme u tlačítek definovat šířku rámečku (NOFRAME, FRAME a BOLDFRAME). Pokud šířku rámečku nedefinujeme, je tlačítko normálně orámováno. BUTTON "Text" ID Tlacitko1 AT (x y) [ FONT písmo ] [ NONUSABLE ] [ DISABLED ] [ NOFRAME ] [ FRAME ] [BOLDFRAME ]
„Stisknutí tlačítka“ – tj. dotek a zvednutí pera v tlačítku – generuje systémovou událost ctlSelectEvent, která je zaslána naší aplikaci a předána funkci formuláře. V naší aplikaci pak můžeme vyhodnotit parametr data.ctlSelect.controlID, který obsahuje identifikační číslo stisknutého tlačítka. Boolean FunkceHlavnihoFormulare(EventPtr udalost) { ... switch(udalost->eType) { ... case ctlSelectEvent: if(udalost->data.ctlSelect.controlID == TlacitkoPrvni) { // Stisknuto první tlačítko } else if(udalost->data.ctlSelect.controlID == TlacitkoDruhe) { // Stisknuto druhé tlačítko } ... }
return true; } return false;
Políčka k zaškrtnutí a přepínače K definici políček k zaškrtnutí v souboru prostředků aplikace slouží klíčové slovo CHECKBOX, přepínače definujeme pomocí PUSHBUTTON. Důležitou vlastností přepínačů a tlačítek je vymezení skupiny (GROUP číslo): z prvků, které mají stejnou skupinu, může být vybrán pouze jeden. Pokud číslo skupiny neuvedeme, nebo pokud zadáme GROUP 0 tak je přepínač nebo políčko k zaškrtnutí nezávislý na ostatních prvcích formuláře.
80
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
U políček k zaškrtnutí můžeme uvést vlastnost CHECKED. Uvedení této vlastnosti způsobí, že při zobrazení formuláře nebo dialogu bude toto políčko zaškrtnuto. Vlastnost CHECKED není možné uvádět u přepínačů; tam musíme nastavit stav přepínače při zobrazení formuláře nebo dialogu programově. PUSHBUTTON "Text" ID PrepinacText AT (x y šířka výška) [ GROUP číslo_skupiny ] [ FONT číslo ] [ NONUSABLE ] [ DISABLED ] [ LEFTANCHOR nebo RIGHTANCHOR ] CHECKBOX "Text" ID ZaskrtniText AT (x y šířka výška) [ GROUP číslo_skupiny ] [ CHECKED ] [ FONT číslo ] [ NONUSABLE ] [ DISABLED ] [ LEFTANCHOR nebo RIGHTANCHOR ]
Také přepínače a políčka k zaškrtnutí zasílají naší aplikaci systémovou událost ctlSelectEvent, poté co uživatel změní jejich stav. Většinou však nepotřebujeme reagovat na změnu stavu přepínačů hned – stačí načíst jejich hodnoty při inicializaci formuláře nebo dialogu a uložit je při jeho opuštění. V naší aplikaci můžeme číst a nastavovat stav těchto prvků pomocí několika funkcí PalmOS. Prohlédněte si příklad 1, který ilustruje základy práce s těmito prvky: K jednoduchému nastavení hodnoty přepínačů a políček k zaškrtnutí slouží funkce CtlGetValue a CtlSetValue. Obě tyto funkce vyžadují jako svůj první parametr ukazatel na data prvku formuláře (v tomto případě datový typ ControlPtr). Jednoduchý způsob použití ve funkci formuláře je v následujícím příkladu. Nejvhodnější místo pro inicializaci prvků formuláře je při zpracování systémové události frmOpenEvent. Podobně uložení stavu prvků formuláře můžeme provést při zpracování frmCloseEvent. V příkladu používáme funkci Objekt, kterou jsme si definovali dříve a která vrátí ukazatel na data prvku formuláře. static Boolean FunkceHlavnihoFormulare(EventPtr udalost) { ... switch(udalost->eType) { case frmOpenEvent: tlacitko = (ControlPtr)Objekt(PrepinacHlavni); CtlSetValue(tlacitko, globalni & 0x0010); FrmDrawForm(FrmGetActiveForm()); zpracovano = true; break; ... case frmCloseEvent: globalni&= 0xFF00; tlacitko = (ControlPtr)Objekt(PrepinacHlavni); if(CtlGetValue(tlacitko)) globalni |= 0x0010; break; ... } }
return zpracovano;
81
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Už víme jak zobrazit dialog; nastavení ovládacích prvků v dialogu provedeme obdobným způsobem ve funkci, ve které dialog inicializujeme. K nastavení hodnot přepínačů a políček k zaškrtnutí opět použijeme funkci CtlSetValue a CtlGetValue. void ZobrazDialog() { FormPtr dialog = FrmInitForm(Dialog); ControlPtr tlacitkoA, tlacitkoB; tlacitkoA = FrmGetObjectPtr(dialog, FrmGetObjectIndex(dialog, PrepinacAAA)); tlacitkoB = FrmGetObjectPtr(dialog, FrmGetObjectIndex(dialog, PrepinacBBB)); CtlSetValue(tlacitkoA, globalni&0x0100); CtlSetValue(tlacitkoB, globalni&0x0200); if(FrmDoDialog(dialog) == TlacitkoUloz) { globalni &= 0xF0FF; if(CtlGetValue(tlacitkoA)) globalni |= 0x0100; if(CtlGetValue(tlacitkoB)) globalni |= 0x0200; } }
Druhý způsob nastavení a čtení hodnoty přepínačů a políček k zaškrtnutí je použít funkce FrmGetControlValue ke čtení a FrmSetControlValue k nastavování hodnoty. Tyto funkce vyžadují index přepínače nebo políčka k zaškrtnutí ve formuláři nebo dialogu. Jejich volání je jinak stejné jako volání funkcí CtlGetValue a CtlSetValue. Při práci se skupinami přepínačů nebo políček k zaškrtnutí (vlastnost GROUP číslo) můžeme použít jiné dvě funkce PalmOS a to FrmGetControlGroupSelection a FrmSetControlGroupSelection. Obě dvě funkce vyžadují jako parametr číslo skupiny. Funkce FrmSetControlGroupSelection nastaví ve skupině právě jedno stisknuté tlačítko, jehož index jsme jí předali: UInt16 tlacitka[3] = { ZaskrtniPrvni, ZaskrtniDruhy, ZaskrtniTreti }; UInt16 gCislo = 0; ... formular = FrmGetActiveForm(); prvek = tlacitka[gCislo]; FrmSetControlGroupSelection(formular, 1, prvek);
Pomocí funkce FrmGetControlGroupSelection zjistíme identifikátor přepínače nebo políčka k zaškrtnutí, které je ve skupině vybráno (v proměnné gCislo je uloženo pořadové číslo políčka k zaškrtnutí od nuly do dvou). indexPrvku = FrmGetControlGroupSelection(formular, 1); // index ve formuláři prvekID = FrmGetObjectId(formular, indexPrvku); for(i = 0; i < 3; i++) { if(prvekID == tlacitka[i]) { gCislo = i; break; } }
82
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Opakující tlačítka Rozdíl mezi obyčejnými a opakovacími tlačítky je zejména v jejich chování, když na nich držíme stylus. Držíme-li stisknuté opakující tlačítko, tak operační systém zasílá naší aplikaci opakovaně každou polovinu sekundy systémovou událost ctlRepeatEvent. Uživatel tak (například ke změně číslice při nastavení času) nemusí opakovaně mačkat tlačítko; stačí, když jej nechá stisknuté a PalmOS se sám stará o opakování. K definici opakujícího tlačítka slouží klíčové slovo REPEATBUTTON; vlastnosti opakujícího tlačítka jsou stejné jako vlastnosti normálních tlačítek. Použití opakujících tlačítek si můžete prohlédnout v příkladu 2. REPEATBUTTON "Text" ID Tlacitko1 AT (x y šířka výška) [ FONT písmo ] [ NONUSABLE ] [ DISABLED ] [ NOFRAME ] [ FRAME ] [BOLDFRAME ]
V nejčastějším případu používáme opakující tlačítka s šipkou nahoru a dolů; tato tlačítka definujeme v souboru prostředků aplikace. Pro šipky používáme symboly z písma číslo 4 a 5. FORM ID HlavniFormular AT (0 0 160 160) MENUID HlavniMenu BEGIN TITLE "Priloha" LABEL "Prvni:" AUTOID AT (20 50) REPEATBUTTON "\002" ID TlacitkoZpet1 AT (PREVRIGHT+2 PREVTOP AUTO AUTO) FONT 4 NOFRAME PUSHBUTTON "000" ID Hodnota1 AT (PREVRIGHT+1 PREVTOP 50 AUTO) DISABLED REPEATBUTTON "\003" ID TlacitkoVpred1 AT (PREVRIGHT+1 PREVTOP AUTO AUTO) FONT 4 NOFRAME LABEL "Druhe:" AUTOID AT (20 90) PUSHBUTTON "000" ID Hodnota2 AT (PREVRIGHT+2 PREVTOP 50 AUTO) DISABLED REPEATBUTTON "\001" ID TlacitkoNahoru2 AT (PREVRIGHT+1 PREVTOP-4 13 AUTO) FONT 5 NOFRAME REPEATBUTTON "\002" ID TlacitkoDolu2 AT (PREVLEFT PREVBOTTOM+1 PREVWIDTH AUTO) FONT 5 NOFRAME END
Ve funkci formuláře našeho programu pak můžeme zpracovat událost ctlRepeatEvent; dokud budeme tlačítko s šipkou držet, bude PalmOS tuto zprávu naší aplikaci zasílat. Při zpracování této události nesmí funkce formuláře vrátit hodnotu true: jinak PalmOS nepřekreslí správně tlačítko (bude si myslet, že jsme tuto událost korektně zpracovali a tlačítko překreslili sami). static Boolean FunkceHlavnihoFormulare(EventPtr udalost) { Boolean zpracovano = false; ... case ctlRepeatEvent: if(udalost->data.ctlRepeat.controlID == TlacitkoVpred1) { ZmenCislo1(1); } else if(udalost->data.ctlRepeat.controlID == TlacitkoZpet1) { ZmenCislo1(-1); } else if(udalost->data.ctlRepeat.controlID == TlacitkoNahoru2) {
83
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
ZmenCislo2(1); } else if(udalost->data.ctlRepeat.controlID == TlacitkoDolu2) { ZmenCislo2(-1); } break;
}
... return zpracovano;
Změna textu v tlačítku V předchozím příkladu jsme k zobrazení výsledků použili přepínač (s vlastností DISABLED), který nereagoval na akce uživatele. Pokud potřebujeme změnit text tlačítka nebo přepínače, použijeme funkci CtlSetLabel, které předáme adresu textu. Použití funkce CtlSetLabel má dvě nevýhody: jednak se funkce nepostará o překreslení tlačítka a jednak vyžaduje, aby byla proměnná obsahující text po celou dobu života formuláře definována. První nevýhodu řešíme tak, že tlačítko nejprve skryjeme funkcí CtlHideControl, poté změníme jeho text a znovu jej vykreslíme funkcí CtlShowControl. Řešením druhé nevýhody je umístění textu tlačítka do globální proměnné, samozřejmě pro každé tlačítko zvlášť. Char textTlacitka1[64]; // globální proměnná, ve které je text tlačítka void ZmenCisloVTlacitku1(Int16 cislo) { FormPtr formular = FrmGetActiveForm(); UInt16 indexTlacitka = FrmGetObjectIndex(formular, PrepinacHodnota2); ControlPtr tlacitko = FrmGetObjectPtr(formular, indexTlacitka); CtlHideControl(tlacitko); // skryjeme StrIToA(textTlacitka1, cislo); CtlSetLabel(tlacitko, textTlacitka1); // nastavíme text CtlShowControl(tlacitko); // a zobrazíme }
Pro zobrazení textu je vždy lepší použít textová políčka (FIELD), která definujeme s vlastností DISABLED, aby je uživatel nemohl měnit. V některých případech, například při použití tlačítka volby textu, však budeme muset text v tlačítku nastavovat sami.
Tlačítko volby textu Z hlediska obsluhy ve vaší aplikaci je tlačítko volby textu prostě jen další tlačítko, které při svém stisknutí zasílá aplikaci systémovou událost ctlSelectEvent, a jehož text můžeme měnit funkcí CtlSetLabel. V souboru prostředků aplikace je ke vložení tlačítka volby textu do formuláře určeno klíčové slovo SELECTORTRIGGER. Tlačítko volby textu mění svoji velikost podle textu, který je v tlačítku zobrazen. Při definici tlačítka volby textu v souboru prostředků aplikace proto nesmíme zapomenout na vlastnost LEFTANCHOR nebo RIGHTANCHOR. Tato vlastnost určí, zda při změně textu bude ukotvena pozice pravé nebo levé hrany tlačítka.
84
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
SELECTORTRIGGER "Text" ID Tlacitko1 AT (x y šířka výška) [ FONT písmo ] [ NONUSABLE ] [ DISABLED ] [ LEFTANCHOR ] [ RIGHTANCHOR ]
I pro tlačítko volby textu platí, že chceme-li text v něm měnit, musíme mít definovánu globální řetězcovou proměnnou, do které budeme text ukládat. Pro změnu textu v tlačítku musíme tlačítko skrýt, nastavit nový text (tím se změní i rozměry tlačítka) a zobrazit. // Globální proměnná pro uložení textu tlačítka Char textTlacitka[40]; // Funkce pro překreslení void PrekresliTlacitko(UInt16 id, Char* text) { FormPtr formular = FrmGetActiveForm(); UInt16 indexTlacitka = FrmGetObjectIndex(formular, id); ControlPtr tlacitko = FrmGetObjectPtr(formular, indexTlacitka); CtlHideControl(tlacitko); // skryjeme CtlSetLabel(tlacitko, text); // nastavíme text CtlShowControl(tlacitko); // a zobrazíme } // Použití: StrCopy(textTlacitka, “kratky“); PrekresliTlacitko(PrvniVyber, textTlacitka);
Pokud nechcete text v tlačítku volby textu měnit, nemusíte se s použitím pomocných proměnných a s nastavováním textu zdržovat; chová se jako obyčejné tlačítko. Chování všech typů tlačítek ilustruje příklad 3.
Seznam (List) Chceme-li uživatele nechat vybrat jednu z několika možností, můžeme použít seznamy. Použití seznamů je velmi jednoduché, protože většinu práce, jako třeba posun prvků nahoru a dolů nebo zobrazení prvků seznamu, za nás udělá sám operační systém PalmOS. Jako všechny prvky uživatelského rozhraní PalmOS se i seznamy definují v souboru prostředků aplikace: LIST “A“ “B“ ... “Z“ ID SeznamPismen AT (x y šířka výška) VISIBLEITEMS počet [ FONT písmo ] [ NONUSABLE ] [DISABLED ]
Za parametrem VISIBLEITEMS je uváděn maximální počet řádků seznamu, které budou na displeji zobrazeny. Výsledná výška seznamu na displeji je počítána z počtu zobrazených řádků seznamu a z použitého písma. Pokud bude mít seznam větší počet prvků, než je maximální počet řádků (hodnota za VISIBLEITEMS), bude vykreslen jen tento počet řádků a do seznamu budou doplněny šipky pro stránkování. Prvky seznamu můžeme buď uvést přímo za klíčovým slovem LIST, nebo je můžeme nastavit dynamicky v našem programu. Nejjednodušší způsob je použití seznamu s pevně danými prvky, které definujeme přímo v souboru prostředků aplikace.
85
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Prvky seznamu jsou číslované od nuly. V seznamu může být vybrán (a vykreslen inverzně) nejvýše jeden prvek. Výběr prvku seznamu provádí uživatel dotekem pera na příslušném řádku seznamu, nebo programátor pomocí funkce LstSetSelection. Funkci LstSetSelection předáme číslo prvku, který chceme vybrat nebo hodnotu –1 pro zrušení výběru. Operační systém PalmOS nastaví nový vybraný prvek; pokud je seznam dlouhý, musíme ještě zavolat funkci LstMakeItemVisible, která zajistí, že vybraný prvek bude na stránce seznamu zobrazen. Nastavit vybraný prvek seznamu můžeme například při zpracování události frmOpenEvent ve funkci formuláře: ListPtr seznam; case frmOpenEvent: formular = FrmGetActiveForm(); seznam = (ListPtr)FrmGetObjectPtr(formular, FrmGetObjectIndex(formular, SeznamPismen)); if(prvekSeznamuVybran) { LstSetSelection(seznam, cislo); LstMakeItemVisible(seznam, cislo); } else { LstSetSelection(seznam, -1); } FrmDrawForm(formular); return true;
Zjistit, který prvek seznamu je vybrán, můžeme pomocí funkce LstGetSelection a text vybraného prvku můžeme vyzvednout funkcí LstGetSelectionText. Pokud není vybrán žádný prvek seznamu, vrací funkce LstGetSelection hodnotu noListSelection. Vybere-li uživatel prvek seznamu, je naší aplikaci zaslána událost lstSelectEvent a ve struktuře popisující událost (v prvku data.lstSelect.selection) je uvedeno číslo vybraného prvku seznamu. V dalších prvcích struktury je pak ukazatel na data seznamu a identifikační číslo seznamu. case lstSelectEvent: if(udalost->data.lstSelect.listID == SeznamPismen) { ListPtr seznam = udalost->data.lstSelect.pList; Int16 cisloPrvku = LstGetSelection(seznam); if(cisloPrvku != noListSelection) { Char* text = LstGetSelectionText(seznam, cisloPrvku); }
} return true;
86
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Nesmíme zapomenout uložit hodnotu vrácenou funkcí LstGetSelection do proměnné se znaménkem (Int16). Prvky seznamu jsou číslovány od nuly a není-li vybrán žádný prvek vrací tato funkce záporné číslo. V příkladu 4 si ukážeme několik možných použití seznamů: normální seznam, seznam s proměnným obsahem, uživatelsky kreslený seznam a vyskakovací seznam (popup list), který se zobrazí v místě doteku pera na displeji. Uživatelsky kreslený seznam, ve kterém jsou liché prvky přeškrtnuté
Standardní seznam
Seznam, jehož obsah se mění v závislosti na výběru ze seznamu nad ním
Vyskakovací seznam, který se zobrazí po doteku perem
Změna obsahu seznamu V naší aplikaci můžeme použít funkci LstSetListChoices, která nastaví počet prvků seznamu a texty, které odpovídají jednotlivým položkám seznamu. Funkci předáváme počet prvků seznamu a pole řetězců, které bude v seznamu zobrazeno. Poté, co změníme obsah seznamu musíme zavolat funkci LstEraseList, která smaže původní seznam z displeje a funkci LstDrawList, která vykreslí seznam s novými daty. Seznam si i při nastavení nových prvků seznamu stále pamatuje číslo původně vybraného prvku. Funkcí LstSetSelection nastavíme nový vybraný prvek nebo výběr zrušíme (předáme-li jako parametr hodnotu –1). Char* prvky[4] = {“prvni“, “druhy“, “treti“, “ctvrty“}; // Změna prvků v seznamu LstSetListChoices(seznam, prvky, 4); LstSetSelection(seznam, -1); LstEraseList(seznam); LstDrawList(seznam);
Prvky seznamu můžeme nastavit i dynamicky při vytvoření formuláře. Při zpracování události frmOpenEvent vytvoříme v nepřemístitelném bloku paměti pole, do kterého uložíme řetězce a odkaz na toto pole spolu s počtem prvků předáme funkci LstSetListChoices. Pole zrušíme při ukončení zobrazení formuláře: při zpracování události frmCloseEvent. Poslední možnost, jak měnit obsah seznamu spočívá ve využití uživatelem kresleného seznamu.
87
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Vyskakovací seznam (Popup list) Operační systém PalmOS nabízí i možnost, jak na libovolném místě displeje zobrazit seznam a nechat z něj uživatele jednu položku vybrat, podobně jako když ve Windows stisknete pravé tlačítko myši. K tomuto výběru slouží funkce LstPopupList, která se sama postará o zobrazení seznamu, výběr uživatele a vymazání seznamu. Pokud chceme vyskakovací seznam použít, musíme nejprve v souboru prostředků aplikace definovat seznam s vlastností NONUSABLE. Na umístění seznamu na displeji nezáleží, protože uživatel tento seznam za normálních okolností neuvidí. Přejeme-li si vyskakovací seznam zobrazit (například po doteku na displej), zavoláme funkci LstSetPosition, pomocí které nastavíme pozici seznamu na displeji a poté funkci LstPopupList. Použití této funkce si můžete prohlédnout v příkladu 4: case penDownEvent: FormPtr formular = FrmGetActiveForm(); ListPtr seznam = (ListPtr)FrmGetObjectPtr(formular, FrmGetObjectIndex(formular, SeznamVyskakovaci)); LstSetPosition(seznam, udalost->screenX, udalost->screenY); LstSetSelection(seznam, -1); vybranyPrvek = LstPopupList(seznam); return false;
Uživatelsky kreslený seznam Pokud vám nestačí, že máte v seznamu zobrazen jednoduchý text, máte možnost doplnit seznam o uživatelské vykreslování prvků. Jako většina věcí v PalmOS i toto je jednoduché. Stačí definovat ve zdrojovém textu naší aplikace funkci, kterou PalmOS zavolá když chce vykreslit jeden prvek seznamu. Seznamu pak přiřadíme adresu této funkce voláním LstSetDrawFunction. // Funkce pro vykreslení prvku seznamu void KresliPrvekSeznamu(Int16 cislo, RectangleType *hranice, Char **textyPrvku) { Char text[50]; StrPrintF(text, " Prvek %d", cislo); if(cislo % 2) { WinDrawGrayLine(hranice->topLeft.x, hranice->topLeft.y + 5, hranice->topLeft.x + hranice->extent.x, hranice->topLeft.y + 5); } }
WinDrawChars(text, StrLen(text), hranice->topLeft.x, hranice->topLeft.y);
88
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Použití ListPtr seznam = (ListPtr)FrmGetObjectPtr(formular, FrmGetObjectIndex(formular, SeznamKresleny)); LstSetDrawFunction(seznam, KresliPrvekSeznamu);
Využití uživatelsky kreslených seznamů je také nejjednodušší možností jak měnit obsah seznamu. Adresa pole řetězců, kterou předáváme funkci LstSetListChoices, je v uživatelsky kresleném seznamu pouze předávána funkci, která kreslí prvek seznamu. Pokud používáme uživatelsky kreslený seznam, můžeme předat funkci LstSetListChoices počet prvků seznamu a hodnotu NULL a o uložení prvků seznamu v paměti se postarat sami. Následující příklad ukazuje, jak je možné vytvořit seznam čísel od jedné do deseti bez použití pole řetězců: // Funkce pro vykreslení prvku seznamu void KresliPrvekSeznamu(Int16 cislo, RectangleType *hranice, Char **textyPrvku) { Char text[50];
}
StrPrintF(text, "%d", cislo + 1); WinDrawChars(text, StrLen(text), hranice->topLeft.x, hranice->topLeft.y);
// Vytvoření seznamu ... ListPtr seznam = (ListPtr)FrmGetObjectPtr(formular, FrmGetObjectIndex(formular, SeznamKresleny)); LstSetDrawFunction(seznam, KresliPrvekSeznamu); LstSetListChoices(seznam, NULL, 10);
Tlačítko volby ze seznamu Tlačítko volby ze seznamu použijeme vždy, chceme-li aby uživatel vybral jednu možnost ze seznamu a musíme-li šetřit místem na displeji. Tento druh tlačítka poznáme podle trojúhelníku se šipkou dolů, který je zobrazen vlevo od textu. Dotekem na trojúhelníku nebo na textu tlačítka zobrazíme seznam; text položky, kterou vybereme ze seznamu se zkopíruje do tlačítka.
89
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
V souboru prostředků aplikace tentokrát musíme definovat tlačítko (POPUPTRIGGER), skrytý seznam (LIST) a jejich propojení (POPUPLIST). Seznam by měl být umístěn tak, aby se jeho levý horní roh kryl s levým horním rohem tlačítka a aby tlačítko zcela překryl. V souboru prostředků aplikace můžeme tlačítko pro výběr ze seznamu definovat například takto: LABEL "Vyber: " AUTOID AT (10 50) POPUPTRIGGER "-nic-" ID Tlacitko1 AT (PREVRIGHT+2 PREVTOP 50 AUTO) LEFTANCHOR LIST "jedna" "dva" "tri" ID Seznam1 AT (PREVLEFT PREVTOP PREVWIDTH AUTO) VISIBLEITEMS 3 NONUSABLE POPUPLIST ID Tlacitko1 Seznam1
Při definici tlačítka pro volbu ze seznamu musíme zvolit vlastnost LEFTANCHOR nebo RIGHTANCHOR. Toto tlačítko totiž mění svoji velikost podle zobrazeného textu, podobně jako tlačítko volby textu, o kterém jsme psali dříve. Vlastnost LEFTANCHOR nebo RIGHTANCHOR specifikuje, který okraj tlačítka bude pevný a který okraj se bude měnit podle délky textu. V příkladu 5 jsou uvedené oba příklady pro srovnání. Definujeme-li tlačítko volby ze seznamu správně (POPUPTRIGGER, LIST, POPUPLIST), postará se o většinu obslužných úkolů operační systém PalmOS. Stiskneme-li tlačítko, zobrazí se seznam voleb. Po úspěšném výběru ze seznamu se vybraný text zobrazí v tlačítku a PalmOS zašle naší aplikaci událost popSelectEvent. case popSelectEvent: if(udalost->data.popSelect.controlID == TlacitkoVyberu1) { Int16 prvekSeznamu = udalost->data.popSelect.selection; // ... } return false;
Událost popSelectEvent využívá i operační systém PalmOS pro překreslení tlačítka. Nesmíme proto zapomenout, že funkce formuláře musí při zpracování této události vrátit logickou hodnotu false. Při prvním vykreslení formuláře je nicméně tlačítko pro výběr ze seznamu vykresleno s textem, který následuje za POPUPTRIGGER. Abychom v tlačítku zobrazili správný prvek seznamu, musíme volat funkce LstGetSelectionText a CtlSetLabel, podobně jako v následujícím příkladu: void NastavVyberSeznam(ListPtr seznam, ControlPtr tlacitko, Int16 vyber) { if(vyber >= 0 && vyber < LstGetNumberOfItems(seznam)) { CtlSetLabel(tlacitko, LstGetSelectionText(seznam, vyber)); } }
Políčka pro vstup textu Políčka pro editaci textu použijeme všude, kde nám nestačí zadávání hodnot pomocí tlačítek, políček k zaškrtnutí nebo výběrem ze seznamu. Grafické uživatelské rozhraní operačního systému PalmOS umožňuje velmi pohodlnou práci s políčky pro editaci textu. V souboru prostředků aplikace definujeme políčko pomocí klíčového slova FIELD.
90
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
FIELD ID PolickoEditace AT (x y w h) [ NONUSABLE ] [ DISABLED ] [ FONT pismo ] další vlastnosti
Přesnější představu o možnostech políček pro vstup textu si můžeme udělat z jednotlivých vlastností, které mohou políčka mít: Vlastnost LEFTALIGN nebo RIGHTALIGN EDITABLE nebo NONEDITABLE SINGLELINE nebo MULTIPLELINES MAXCHARS počet UNDERLINED AUTOSHIFT NUMERIC HASSCROLLBAR
Popis Určuje, zda bude text v políčku zarovnán doleva nebo doprava. Do políček s vlastností EDITABLE může uživatel zapisovat text, políčka s vlastností NONEDITABLE slouží pouze k zobrazování dat. Pomocí SINGLELINE nebo MULTIPLELINES určujeme, zda bude mít políčko jeden nebo více řádků. Je-li políčko definováno s vlastností MULTIPLELINES tak je počet řádků dán velikostí plochy na displeji, kterou políčko zabírá, a výškou použitého písma. Udává kolik nejvíce znaků může uživatel zapsat do políčka. Pokud text v políčku nastavujeme z programu tak nás tato hodnota neomezuje. Určuje zda budou řádky v políčku zvýrazněny podtržením. Nastavuje automaticky velké písmeno na začátku políčka a na začátcích vět zapsaných do políčka. Pokud nastavíme tuto vlastnost, bude do políčka možné zapisovat pouze číslice 0-9. Tuto vlastnost používáme u víceřádkových políček, která budou spřažena s posuvníkem.
Vlastnosti z jednotlivých řádků tabulky můžeme libovolně kombinovat tak, abychom vytvářeli políčka, která se budou chovat podle našich požadavků. V pravém dolním rohu každého formuláře, ve kterém jsme definovali políčko pro vstup textu, bychom měli zobrazit ukazatel stavu graffiti (GRAFFITISTATEINDICATOR). O jeho další obsluhu se nemusíme starat; operační systém PalmOS sám mění zobrazený symbol podle aktuálního stavu graffiti. GRAFFITISTATEINDICATOR AT (x y)
Pro přístup k políčkům používáme ukazatel na data políčka (datový typ FieldPtr). Vykreslit políčko na displeji a vymazat jej z displeje můžeme pomocí funkcí FldDrawField a FldEraseField. Chceme-li mít jistotu, že se políčko správně překreslí, musíme jej nejprve vymazat a poté vykreslit s novým obsahem. V datové struktuře políčka je uložen ovladač přemístitelného bloku paměti, ve kterém je uložen text políčka. Pokud je políčko prázdné, není k němu přiřazen žádný blok paměti. Vepíšeme-li do políčka první znak, vytvoří operační systém nový přemístitelný blok paměti, který bude obsahovat editovaný text a jeho ovladač uloží v datové struktuře políčka. Funkcemi FldGetTextHandle a FldSetTextHandle můžeme přečíst nebo nastavit ovladač bloku paměti, ve kterém je text políčka uložen. Text, který je uložen v políčku, můžeme zkopírovat do řetězcové proměnné například následující funkcí:
91
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void KopirujTextPolicka(FieldPtr policko, Char* kam) { MemHandle ovladacTextu = FldGetTextHandle(policko); if(ovladacTextu) { // Uzamkneme přemístitelný blok paměti, zkopírujeme text a odemkneme Char* textPolicka = (Char*)MemHandleLock(ovladacTextu); StrCopy(kam, textPolicka); MemHandleUnlock(ovladacTextu);
} else { // Ma-li ovladacTextu hodnotu NULL, je policko prazdne
}
}
StrCopy(kam, "");
Délku textu v políčku můžeme zjistit funkcí FldGetTextLength. Pokud je text v políčku vybrán, můžeme začátek a konec výběru zjistit voláním funkce FldGetSelection. Při nastavování textu v políčku musíme nahradit starý blok paměti, ve kterém byl uložen původní text políčka blokem, ve kterém je uložen text nový. Funkce, která to zajistí je například následující: void NovyOvladacTextuPolicka(FieldPtr policko, MemHandle novyOvladac) { MemHandle staryOvladac; // Zjistíme starý ovladač a nastavíme ovladač nový staryOvladac = FldGetTextHandle(policko); FldSetTextHandle(policko, novyOvladac); // Pokud v políčku byl text, zruš blok paměti, ve kterém byl uložen if(staryOvladac) { MemHandleFree(staryOvladac); } // Na závěr musíme políčko překreslit FldDrawField(policko); }
S takto definovanou funkcí už bude jednoduché nastavit nový text v políčku podle zadaného řetězce. Pokud bychom chtěli text v políčku vymazat, nastavíme jako nový ovladač textu políčka hodnotu NULL.
92
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void SmazTextPolicka(FieldPtr policko) { NovyOvladacTextuPolicka(policko, NULL); } void NastavTextPolicka(FieldPtr policko, Char* text) { MemHandle ovladac = MemHandleNew(StrLen(text) + 1); StrCopy((Char*)MemHandleLock(ovladac), text); MemHandleUnlock(ovladac); }
NovyOvladacTextuPolicka(policko, ovladac);
U každého políčka, které se nachází ve formuláři, je dále uložen údaj o tom, zda jsou data v políčku čistá nebo špinavá. V terminologii PalmOS jsou čistá ta data, která uživatel nezměnil a špinavá jsou data, která byla při práci s formulářem uživatelem změněna. Pokud uložíme do políčka nějaký text funkcí FldSetTextHandle tak je políčko označené jako čisté; změní-li uživatel text v políčku, tak je nastaven příznak špinavé. Stav políčka zjistíme voláním funkce FldDirty. Jedno políčko ve formuláři může obsahovat blikající kursor (aktivní políčko). Do tohoto políčka je vkládán nový text. Pomocí funkce FrmSetFocus můžete vybrat, ve kterém políčku bude kursor umístěn; index prvku formuláře (nejen políčka), ve kterém je kursor získáme funkcí FrmGetFocus.
Stránkování pomocí opakovacích tlačítek V prvních verzích operačního systému PalmOS se vyskytoval jen jediný způsob posouvání textu ve víceřádkovém políčku nahoru a dolů. Bylo jím použití opakovacích tlačítek (REPEATBUTTON) s trojúhelníčky směřujícími nahoru a dolů. Pokud pohyb textu daným směrem nebyl možný, byla tlačítka zobrazena v šedé barvě (vytečkována). Stiskne-li uživatel tlačítko, posune se text v políčku o stránku nahoru nebo dolů. Pro posuv textu v políčku slouží funkce FldScrollField, které předáváme parametr určující směr posunu (winUp nebo winDown). Počet řádků, o které máme políčko posunout můžeme zjistit například voláním funkce FldGetVisibleLines. void PosunTextOStranku(FieldPtr policko, WinDirectionType smer) { UInt16 radky = FldGetVisibleLines(policko); }
FldScrollField(policko, radky, smer);
Funkci pro posuv textu o stránku pak voláme při zpracování dvou událostí: jednak při stisknutí příslušného opakovacího tlačítka (ctlRepeatEvent), jednak při stisknutí hardwarové klávesy pro pohyb nahoru nebo dolů (keyDownEvent). switch(udalost->eType) { ...
93
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
case keyDownEvent: // Hardwarové klávesy if(udalost->data.keyDown.chr == vchrPageUp) { PosunTextOStranku(PoleTextVstupni, winUp); return true; } else if(udalost->data.keyDown.chr == vchrPageDown) { PosunTextOStranku(PoleTextVstupni, winDown); return true; } break; case ctlRepeatEvent: // Strankovani nahoru a dolu pomoci tlacitek
}
...
if(udalost->data.ctlRepeat.controlID == OpakujTextNahoru) { PosunTextOStranku(PoleTextVstupni, winUp); return false; } else if(udalost->data.ctlRepeat.controlID == OpakujTextDolu) { PosunTextOStranku(PoleTextVstupni, winDown); return false; } break;
Po každé změně textu v políčku je potřeba upravit zobrazení opakovacích tlačítek tak, aby byla zvýrazněná, je-li možné text v políčku posouvat. Operační systém PalmOS umožňuje upravit zobrazení opakovacích tlačítek velmi jednoduše pomocí funkce FrmUpdateScrollers, která automaticky změní vlastnosti opakovacích tlačítek v závislosti na tom, zda je možný posuv nahoru nebo dolů. Volání této funkce je následující: void UpravTlacitkaStranky(UInt16 idPolicka, UInt16 idNahoru, UInt16 idDolu) { FormPtr formular = FrmGetActiveForm(); UInt16 index = FrmGetObjectIndex(formular, idPolicka); FieldPtr policko = FrmGetObjectPtr(formular, index); FrmUpdateScrollers(formular, FrmGetObjectIndex(formular, idNahoru), FrmGetObjectIndex(formular, idDolu), FldScrollable(policko, winUp), FldScrollable(policko, winDown)); }
94
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Uvedenou funkci pak voláte vždy, když se text v políčku změní – po stisknutí klávesy, vložení textu, nebo například při každém průchodu funkcí formuláře. Zpracování formuláře s políčky pro vstup textu a stránkováním pomocí opakovacích tlačítek si můžete prohlédnout v příkladu 6.
Posuvníky Posuvníky se objevují v PalmOS 2.0 a slouží k elegantnějšímu posunu textu v políčkách a tabulkách. Posuvník bývá obvykle umístěn podél pravé strany políčka a většinou je stejně vysoký jako políčko, ke kterému patří. Šířka posuvníku musí být 7 obrazových bodů; kvůli chybě v programu pilrc ji vždy musíme zadávat sami (nefunguje použití AUTO). Posun o jeden řádek nahoru Posun o stránku nahoru „Vozík“ slouží k plynulému posuvu přetažením nahoru nebo dolů.
Posun o stránku dolů Posun o jeden řádek dolů
V souboru prostředků aplikace definujeme posuvník pomocí klíčového slova SCROLLBAR. Při umisťování posuvníku do formuláře můžeme výhodně použít konstanty PREVRIGHT, PREVTOP a PREVHEIGHT. S jejich pomocí můžeme umístit posuvník vedle příslušného políčka: FORM ID FormularVystupni AT (0 0 160 160) BEGIN ... FIELD ID PolickoText AT (5 18 145 121) HASSCROLLBAR ... SCROLLBAR ID PosuvText AT (PREVRIGHT PREVTOP 7 PREVHEIGHT) VALUE 10 MIN 0 MAX 100 PAGESIZE 10 ... END
Vlastnosti MIN, MAX, PAGESIZE a VALUE slouží k nastavení prvního zobrazení posuvníku na displeji a v naší aplikaci je budeme programově měnit. Políčka, která si přejeme posouvat pomocí posuvníku, musíme definovat s atributem HASSCROLLBAR. Tento atribut říká operačnímu systému, aby zaslal naší aplikaci zprávu fldChangedEvent kdykoliv dojde ke změně celkové výšky nebo pozice textu v políčku. Naše aplikace pak má možnost při zpracování zprávy fldChangedEvent aktualizovat zobrazení posuvníku na displeji. Na rozdíl od posouvání textu po stránkách pomocí opakovacích tlačítek nám použití posuvníku nabízí mnoho výhod. Text můžeme posouvat více způsoby. Dotekem pera na šipce nahoru nebo dolů můžeme posunout text o řádek nahoru nebo dolů. Dotekem pera na šedě vybarvenou plochu posuvníku posuneme text o stránku. Konečně tažením vozíku můžeme posouvat text plynule. Když se uživatel dotkne perem displeje kdekoliv na posuvníku, operační systém uloží do fronty zpráv zprávu sclEnterEvent. Tuto zprávu naše aplikace nepotřebuje zpracovávat.
95
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Dokud uživatel posuvníkem pohybuje tak operační systém zasílá naší aplikaci v pravidelných intervalech zprávu sclRepeatEvent a na konci pohybu zprávu sclExitEvent. V datové struktuře popisující událost je kromě identifikačního čísla posuvníku uložena i hodnota na začátku pohybu a na konci pohybu posuvníku. Z rozdílu těchto dvou hodnot můžeme spočítat počet řádků, o které políčko musíme v tomto kroku posunout abychom udrželi krok s posuvníkem. V naší aplikaci si musíme vybrat, zda budeme zpracovávat událost sclRepeatEvent nebo sclExitEvent. Jejich zpracování je zcela stejné, rozdíly jsou v následující tabulce. Při zpracování těchto událostí nesmí funkce formuláře vrátit logickou hodnotu true, neboť musí být dále zpracovávány operačním systémem. Zpracování události sclRepeatEvent • Tato událost je aplikaci zasílána opakovaně dokud uživatel pohybuje s posuvníkem. • Vyhodnocujeme-li tuto událost tak se při pohybu posuvníkem plynule pohybuje i text v políčku. • U velmi dlouhých políček s textem je odezva aplikace pomalejší.
Zpracování události sclExitEvent • Tato událost je aplikaci zaslána po skončení pohybu posuvníku. • Vyhodnocujeme-li tuto událost, tak se text v políčku skokem změní až po skončení manipulace s posuvníkem. • Tento způsob je velmi rychlý a je vhodný pro velmi dlouhá políčka s textem.
Chceme-li naopak nastavit zobrazení posuvníku podle políčka, můžeme použít dvojici funkcí FldGetScrollValues a SclSetScrollBar. Funkce FldGetScrollValues přečte z datové struktury políčka hodnoty, které slouží k nastavení pozice posuvníku: první zobrazený řádek, celkový počet řádků a výšku políčka v řádcích. Z těchto hodnot spočítáme výsku vozíku a jeho minimální a maximální pozici a předáme je funkci SclSetScrollBar, která změní zobrazení posuvníku. void UpravPosuvnikDlePolicka(ScrollBarPtr posuvnik, FieldPtr policko) { UInt16 poziceVoziku, vyskaTextu, vyskaPolicka; Int16 maximum, delkaStranky; FldGetScrollValues(policko, &poziceVoziku, &vyskaTextu, &vyskaPolicka); if(vyskaTextu > vyskaPolicka) { maximum = vyskaTextu - vyskaPolicka; } else if(poziceVoziku) { maximum = poziceVoziku; } else { maximum = 0; }
96
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
delkaStranky = vyskaPolicka - 1; SclSetScrollBar(posuvnik, poziceVoziku, 0, maximum, delkaStranky); }
Stránkování pomocí posuvníků Chceme-li propojit políčko pro vstup textu s posuvníkem, musíme jej definovat s atributem HASSCROLLBAR. Tento atribut říká operačnímu systému, aby zaslal naší aplikaci zprávu fldChangedEvent kdykoliv dojde ke změně celkové výšky nebo pozice textu v políčku. V naší aplikaci potom budeme zpracovávat následující události: Událost frmOpenEvent sclRepeatEvent nebo sclExitEvent keyDownEvent
fldChangedEvent
Zpracování Po nastavení textu políčka upravíme zobrazení posuvníku voláním funkce UpravPosuvnikDlePolicka. Spočteme počet řádků o který musíme políčko posunout a posuneme políčko voláním funkce FldScrollField. Podle stisknuté klávesy zavoláme funkci PosunPolickoOStranku (tu jsme definovali dříve) pro odstránkování políčka. Poté upravíme zobrazení posuvníku funkcí UpravPosuvnikDlePolicka. Upravíme zobrazení posuvníku voláním funkce UpravPosuvnikDlePolicka.
Zpracování události sclRepeatEvent nebo sclExitEvent je následující: void PosunTextORozdil(FieldPtr policko, Int16 rozdil) { WinDirectionType smer = winDown; if(rozdil < 0) { smer = winUp; rozdil = -rozdil; } // Pokud bude možné text posunout, posuneme jej
}
if(FldScrollable(policko, smer)) { FldScrollField(policko, rozdil, smer); }
Boolean FunkceHlavnihoFormulare(EventPtr udalost) { Boolean zpracovano = false; Int16 rozdil; switch(udalost->eType) { ...
97
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
case sclRepeatEvent: rozdil
= udalost->data.sclRepeat.newValue - udalost->data.sclRepeat.value;
if(udalost->data.sclRepeat.scrollBarID == PosuvnikText) { PosunTextORozdil(Objekt(PoleText), rozdil); } // Nenastavime priznak zpracovani break; } }
...
return zpracovano;
Spolupráce se schránkou Jak jsme již uvedli, tak v každém formuláři, ve kterém může uživatel editovat text, by měla být v menu přítomna karta Editace. Na této kartě jsou uvedeny příkazy pro práci se schránkou, která slouží k přenosu textu mezi aplikacemi a k ovládání políček. Na kartě Editace bývají obvykle následující příkazy menu: Vrácení předchozí operace v políčku zpět. Kopírování označeného textu do schránky. Vyříznutí označeného textu a jeho vložení do schránky. Vložení textu ze schránky na místo kursoru. Označení celého textu v políčku Zapnutí klávesnice. Zobrazení nápovědy ke Graffiti. Definice této karty v souboru prostředků aplikace je následující: MENU ID MenuFormulare BEGIN ... PULLDOWN "Editace" BEGIN MENUITEM "Zpet" ID PolozkaMenuZpet "U" MENUITEM "Vyrizni" ID PolozkaMenuVyrizni "X" MENUITEM "Kopiruj" ID PolozkaMenuKopiruj "C" MENUITEM "Vloz" ID PolozkaMenuVloz "P" MENUITEM "Vyber vse" ID PolozkaMenuVyberVse "S" MENUITEM SEPARATOR MENUITEM "Klavesnice" ID PolozkaMenuKlavesnice "K" MENUITEM "Graffiti" ID PolozkaMenuGraffiti "G" END END
98
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Operační systém PalmOS obsahuje funkce FldUndo, FldCut, FldCopy a FldPaste, které slouží k práci se schránkou. K výběru celého textu políčka slouží funkce FldSetSelection, která nastaví počátek a konec označeného textu v políčku. Všechny tyto funkce vyžadují ukazatel na data aktivního políčka – políčka, do kterého právě uživatel zapisuje text. Aktivní objekt formuláře získáme voláním funkce FrmGetFocus; to však nemusí být právě políčko pro vstup textu. Proto musíme zkontrolovat typ aktivního objektu pomocí funkce FrmGetObjectType. Pokud funkce FrmGetObjectType vrátí hodnotu frmFieldObj, je aktivní objekt políčko a můžeme použít funkce pro práci se schránkou. Následující funkce vrátí ukazatel na data políčka, do kterého uživatel zapisuje text. Pokud není žádné políčko pro vstup textu aktivní, vrátí funkce hodnotu NULL. FieldPtr ZjistiEditovanePole() { FormPtr formular = FrmGetActiveForm(); UInt16 zaostreni = FrmGetFocus(formular); FormObjectKind typObjektu; if(zaostreni == noFocus) { return NULL; } typObjektu = FrmGetObjectType(formular, zaostreni);
}
if(typObjektu == frmFieldObj) { return FrmGetObjectPtr(formular, zaostreni); } else { return NULL; }
Zobrazení klávesnice a nápovědy ke Graffiti zajistíme voláním funkcí SysKeyboardDialog a SysGraffitiReferenceDialog. Kompletní zdrojový text programu, který využívá kartu Editace je v příkladu 7. Boolean FunkceMenuKartyEditace(UInt16 prvekMenu) { FieldPtr policko; switch(prvekMenu) { case PolozkaMenuZpet: if((policko = ZjistiEditovanePole()) != NULL) { FldUndo(policko); } return true;
99
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
case PolozkaMenuKopiruj: if((policko = ZjistiEditovanePole()) != NULL) { FldCopy(policko); } return true; case PolozkaMenuVyrizni: if((policko = ZjistiEditovanePole()) != NULL) { FldCut(policko); } return true; case PolozkaMenuVloz: if((policko = ZjistiEditovanePole()) != NULL) { FldPaste(policko); } return true; case PolozkaMenuVyberVse: if((policko = ZjistiEditovanePole()) != NULL) { FldSetSelection(policko, 0, FldGetTextLength(policko)); } return true; case PolozkaMenuKlavesnice: SysKeyboardDialog(kbdDefault); return true; case PolozkaMenuGraffiti: SysGraffitiReferenceDialog(referenceDefault); return true;
} }
default: break;
return false;
100
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Tabulky Tabulky jsou jedním z nejsilnějších nástrojů uživatelského rozhraní Palm Pilota. Umožňují přehledně zobrazit textová i grafická data, editovat je na místě, spolupracovat s posuvníkem a mnoho dalšího. Zvládnout zacházení s tabulkami patří k mistrovským úkolům programátora počítačů s operačním systémem PalmOS. Na obrázku si můžeme prohlédnout, jak vypadají tabulky v několika vestavěných aplikacích počítačů Palm Pilot a kompatibilních.
Definice v souboru prostředků aplikace Tabulka je definována jako prvek formuláře pomocí klíčového slova TABLE, které je následováno jednoznačnou identifikací tabulky (za ID) a umístěním tabulky na displeji (za AT). Za těmito klíčovými slovy následuje počet řádků tabulky (ROWS počet), počet sloupečků tabulky (COLUMNS počet) a šířky jednotlivých sloupečků za klíčovým slovem COLUMNWIDTHS. Pokud je celkový součet šířek sloupců za COLUMNWIDTHS menší než šířka tabulky, jsou od sebe sloupce odděleny prázdným místem. TABLE ID TabulkaHlavni AT (2 20 144 110) ROWS 10 COLUMNS 5 COLUMNWIDTHS 20 20 20 30 50
Při výpočtu výšky tabulky je výhodné vycházet z velikosti písma, které chceme pro tabulku použít; u běžného a tučného písma (FONT 0 a FONT 1) je to 11 bodů. Šířka tabulky musí být rovna šířce sloupců a mezeře 1 bod mezi každými dvěma sloupci. Častokrát definujeme vpravo od tabulky posuvník, který slouží k stránkování tabulky. Počet řádků a sloupečků tabulky určujeme při její definici v souboru prostředků aplikace; poté můžeme řádky a sloupečky skrývat a odkrývat, ale ne přidávat. Jejich šířku a výšku můžeme poté v naší aplikaci upravovat programově.
Základ použití tabulek Pro manipulaci s tabulkou používáme ukazatel na její data TablePtr, který předáváme specializovaným funkcím manažeru tabulek (table manager). Každý sloupeček tabulky může být určen pro zobrazení jiného datového typu, který můžeme v naší aplikaci nastavit, řádky tabulky jsou věnované jednotlivým záznamům. K nastavování vlastností řádků, sloupců a jednotlivých buněk slouží funkce manažeru tabulek. Řádky tabulky slouží ke zobrazení jednotlivých záznamů databáze; k nastavování a zjišťování vlastností řádků slouží funkce v následující tabulce. Tučně jsou uvedeny funkce pro nastavování vlastností řádků.
101
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Vlastnost řádku Výška
Popis Výška řádku je na počátku určena vydělením výšky tabulky počtem řádků. V průběhu aplikace můžeme výšku jednotlivých řádků měnit nezávisle na sobě. Identifikace záznamu Každý řádek tabulky může obsahovat jednu 16bitovou uživatelem nastavitelnou hodnotu, která se používá pro uložení čísla záznamu databáze, která je v tabulce zobrazena. Data Každý řádek tabulky může obsahovat také jednu 32bitovou uživatelem nastavitelnou hodnotu. Použitelnost Řádky, které jsou označené jako nepoužitelné, jsou skryté a nereagují na vstup uživatele. Pokud se některé řádky tabulky dostanou mimo displej, jsou automaticky označeny jako nepoužitelné. Neproměnlivá výška Pokud je v řádku políčko pro editaci textu, tak se v některých případech může jeho výška při zadávání a mazání textu změnit. Pokud je tato vlastnost nastavena, nebude se výška řádku při změně textu v políčku měnit.
Funkce manažeru tabulek TblSetRowHeight TblGetRowHeight
TblSetRowID TblGetRowID TblFindRowID TblSetRowData TblGetRowData TblFindRowData TblSetRowUsable TblRowUsable
TblSetRowStaticHeight
Sloupečky tabulky slouží k zobrazení jednotlivých datových typů. Vlastnosti sloupečků nastavujeme v našem programu většinou pouze při inicializaci formuláře nebo dialogu, který tabulku obsahuje. Seznam vlastností sloupečků a funkce, které je nastavují jsou uvedeny v následující tabulce. Vlastnost sloupečku Šířka sloupce
Popis Šířka sloupce je na počátku určena při definici tabulky v souboru prostředků aplikace; později ji můžeme měnit programově. Použitelnost Sloupce, které jsou označené jako nepoužitelné, jsou skryté a nereagují na vstup uživatele. Mezera mezi sloupci Mezera mezi tímto a následujícím sloupcem.
102
Funkce manažeru tabulek TblSetColumnWidth
TblSetColumnUsable TblSetColumnSpacing
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
U univerzálního datového typu customTableItem je nutné definovat funkci, která se stará o vykreslení buňky ve sloupečku na displeji. Tuto funkci můžeme definovat i u typu narrowTextTableItem k vykreslení detailu vpravo od textu. Obsahuje-li sloupec editovatelné Vlastní funkce pro textové políčko, tak musíme předat čtení dat textového políčka ve sloupečku manažeru tabulek funkci, která nastaví text v políčku podle databáze. Obsahuje-li sloupec textové políčko, Vlastní funkce pro tak můžeme předat manažeru tabulek nastavení dat textového políčka ve funkci, která uloží text v políčku zpět do databáze. sloupečku Je-li tato vlastnost nastavená, tak je-li Zvýraznění při v řádku tabulky editovatelné políčko, editaci textu na tak bude políčko v tomto sloupci řádku invertováno. Vlastní funkce pro vykreslení buňky ve sloupečku
TblSetCustomDrawProcedure
TblSetLoadDataProcedure
TblSetSaveDataProcedure
TblSetColumnEditIndicator
Vlastnosti řádků a sloupců slouží k manipulaci s celou tabulkou. Jednotlivé buňky tabulky také obsahují informace, které jsou důležité pro zobrazení konkrétního políčka. Záznam databáze, ke kterému políčko patří, je dán řádkem tabulky; položka záznamu, která bude v políčku zobrazena závisí na sloupečku. V každé buňce jsou uloženy čtyři základní informace, důležité pro jeho zobrazení: Vlastnost buňky Typ dat buňky Písmo buňky Číslo Ukazatel
Popis Obsah buňky tabulky (políčko k zaškrtnutí, statický text, políčko pro editaci textu, seznam a podobně). Číslo písma, které je použito k vykreslení buňky. Numerická 16bitová hodnota, jejíž význam je závislý na typu dat buňky. Ukazatel na data specifická pro buňku tabulky.
Funkce manažeru tabulek TblSetItemStyle TblSetItemFont TblSetItemInt TblGetItemInt TblSetItemPtr
Typy dat buňky Typy dat, které jsou zobrazeny v buňce tabulky můžeme rozdělit na typy statické, které slouží pouze pro zobrazení dat, a typy editovatelné, které můžeme měnit.
103
Úvod do programování PalmOS
Statický typ buňky labelTableItem
numericTableItem
dateTableItem
customTableItem
MUDr. Petr Lesný, 2003
Význam Text, ukončený dvojtečkou; používá se často před políčkem pro editaci textu. Pokud nám dvojtečka vadí, musíme použít customTableItem. Celé číslo se znaménkem.
Data buňky (ukazatel a číslo) Ukazatel obsahuje adresu textu, který bude vykreslen. Standardně je použito základní písmo pro vykreslení formulářů. Numerická hodnota v parametru číslo bude standardně vykreslena tučným písmem. Krátké datum (den/měsíc) nebo Numerická hodnota obsahuje pomlčka, pokud nění datum přetypované číslo DataType, definováno. Je-li datum ve kterém je uloženo datum v minulosti, je za ním v interním formátu PalmOS. nakreslen vykřičník. Nemají význam. Uživatel se stará sám o vykreslení políčka. Toto je nejelegantnější varianta pro vykreslování obsahu políček.
Manažer tabulek také umožňuje editovat na místě logickou hodnotu (jako políčko k zaškrtnutí) a číslo nebo hodnotu výběrem ze seznamu. Typ buňky Význam Číslo a ukazatel políčka checkboxTableItem Číslo asociované s buňkou Ve sloupečku je zobrazeno tabulky obsahuje logickou políčko k zaškrtnutí, které hodnotu, která odpovídá stavu může uživatel měnit. políčka k zaškrtnutí. popupTriggerTableItem Výběr ze seznamu; v políčku je Ukazatel, asociovaný s buňkou ukazuje na data seznamu, který zobrazena šipka dolů a jedna hodnota seznamu, dotekem na musí být definován; numerická hodnota obsahuje číslo políčku zobrazíme seznam a můžeme novou hodnotu vybrat zobrazeného prvku seznamu. z něj. Pro použití buňky s výběrem ze seznamu (popupTriggerTableItem) musíme ve formuláři definovat kromě tabulky i seznam, který je skrytý (vlastnost NONUSABLE). V příkladu 1 si můžeme prohlédnout tabulku, která obsahuje seznamy ve dvou sloupečcích. V souboru prostředků aplikace je formulář, který obsahuje tabulku s buňkami s výběrem ze seznamu definován takto: FORM ID HlavniFormular AT (0 0 160 160) BEGIN TITLE "Priloha" LIST "A" "B" "C" "D" ID Seznam1 AT (1 1 30 AUTO) VISIBLEITEMS 4 NONUSABLE LIST "1" "2" "3" "4" ID Seznam3 AT (1 1 30 AUTO) VISIBLEITEMS 4 NONUSABLE TABLE ID TabulkaHlavni AT (2 20 144 110) ROWS 10 COLUMNS 4 COLUMNWIDTHS 40 30 30 40 END
104
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
V buňkách tabulky se mohou nacházet i tři typy políček pro editaci textu: klasické políčko (textTableItem), text s ikonou poznámky vpravo (textWithNoteTableItem) a text, vedle kterého je vpravo volné místo pro vykreslení (narrowTextTableItem). U řádku můžeme nastavit funkcí TblSetRowStaticHeight, zda bude políčko dynamicky měnit výšku při zadávání textu nebo ne. U každé editovatelné buňky můžeme nastavit vlastní písmo. Editovatelný typ textTableItem textWithNoteTableItem narrowTextTableItem
Význam Obyčejný editovatelný text. Text, vedle kterého je vpravo ikonka poznámky. Text, vedle kterého je vpravo vynechané volné místo; toto místo je možné vykreslit uživatelsky definovanou funkcí.
Číslo a ukazatel políčka
Numerická hodnota obsahuje počet bodů, které vynecháme od pravého okraje políčka.
Při práci s buňkami, které obsahují políčka pro editaci textu, musíme definovat dvě vlastní funkce. První z funkcí, kterou nastavujeme pomocí funkce TblSetLoadDataProcedure, bude zavolána když se uživatel rozhodne políčko editovat a má za úkol předat manažeru tabulek ovladač bloku paměti, který obsahuje editovaný text. Druhá funkce, kterou nastavujeme pomocí funkce TblSetSaveDataProcedure, má za úkol uložit po skončení editace text zpátky do databáze.
Obecné základy V této kapitole si probereme postup, který použijeme při úvahách o začlenění tabulek do našich aplikací a ukážeme si, že použití tabulek není ani trochu složité. Práci s tabulkami si rozdělíme na několik kapitol: • Inicializaci tabulky při zobrazení formuláře • Aktualizaci dat tabulky, například při překreslení nebo stránkování tabulky • Spolupráci tabulky s posuvníkem • Použití hardwarových kláves pro stránkování nahoru a dolů • Obsluhu událostí tabulky • Práci s datovými typy určenými pouze k zobrazení • Políčko k zaškrtnutí a výběr ze seznamu • Práci s políčky pro editaci textu v tabulce • Vlastní vykreslování buněk
Inicializace tabulky Bezprostředně po inicializaci formuláře je potřeba nastavit vlastnosti jednotlivých řádků a sloupečků tabulky. Toto nastavení je nejčastěji ošetřeno při zpracování události frmOpenEvent ve funkci formuláře. Nastavení se týká zejména následujících bodů • Pro každou buňku tabulky je třeba povinně nastavit její typ (TblSetItemStyle) a pokud chceme i písmo (TblSetItemFont).
105
Úvod do programování PalmOS •
MUDr. Petr Lesný, 2003
Je zapotřebí vybrat použitelné sloupce tabulky (TblSetColumnUsable) a pokud chceme tak i vybrat sloupečky, které budou invertovány při editaci textu v políčku buňky (TblSetColumnEditIndicator). Tam kde to vyžadujeme můžeme nastavit neměnnou výšku řádku (TblSetRowStaticHeight). Pokud to neuděláme a buňka tabulky bude obsahovat editovatelné políčko, může toto políčko měnit svůj počet řádků při zadávání dlouhého textu. Tím se mění také počet řádků tabulky. V této kapitole budeme používat jenom tabulky s neměnnou výškou řádku. U sloupečků, kde je to třeba musíme předat manažeru tabulek naše vlastní funkce pro vykreslování, vyzvedávání a ukládání dat (funkce TblSetCustomDrawProcedure, TblSetLoadDataProcedure a TblSetSaveDataProcedure).
•
•
Na pravé straně vidíme tabulku z příkladu 2, která má první sloupeček pouze číselný, ve druhém sloupečku je políčko k zaškrtnutí, pak text „Cislo:“ a políčko pro editaci. Příklad zjednodušené funkce pro inicializaci této tabulky je:
void InicializujTabulku(TablePtr tabulka) { UInt16 pocetRadku = TblGetNumberOfRows(tabulka); UInt16 r, s; // Vlastnosti buněk tabulky a řádků for(r = 0; r < pocetRadku; r++) { TblSetItemStyle(tabulka, r, TblSetItemStyle(tabulka, r, TblSetItemStyle(tabulka, r, TblSetItemStyle(tabulka, r, TblSetItemStyle(tabulka, r,
0, 1, 2, 3, 4,
numericTableItem); checkboxTableItem); customTableItem); labelTableItem); textTableItem);
TblSetRowStaticHeight(tabulka, r, true); } // Nastavení sloupečků tabulky for(s = 0; s < 5; s++) { TblSetColumnUsable(tabulka, s, true); TblSetColumnEditIndicator(tabulka, s, false); }
106
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Text ve třetím sloupci bude invertován při změně textu v buňce TblSetColumnEditIndicator(tabulka, 3, true); // Funkce pro vlastní vykreslení buňky tabulky a pro vyzvedávání // a ukládání dat TblSetCustomDrawProcedure(tabulka, 2, VykresleniPolicka2); TblSetLoadDataProcedure(tabulka, 4, VyzvedniCislo4); TblSetSaveDataProcedure(tabulka, 4, UlozCislo4); }
Aktualizace dat tabulky Zatímco inicializaci tabulky provádíme pouze jednou, tak aktualizaci dat v tabulce musíme dělat opakovaně – při prvním zobrazení tabulky, kdykoliv data v tabulce pomocí posuvníku nebo kláves posuneme a při změně dat v tabulce. Tabulka, kterou jsme definovali s deseti řádky, bude mít vždy nejvýše 10 řádků; pokud ji používáme pro zobrazení většího souboru dat, musíme si pamatovat číslo záznamu, které odpovídá nejvyššímu řádku tabulky. Toto číslo budeme mít uloženo v globální proměnné. Výhodné je tuto proměnnou ukládat do databáze uživatelského nastavení (preferences); v našem druhém příkladu ji pouze inicializujeme. Int16 prvniRadek = 0;
Základem aktualizace dat tabulky je přiřazení čísla odpovídajícího záznamu každému řádku tabulky (funkce TblSetRowID). Číslo záznamu se bude hodit při vykreslování vlastních políček i při vyzvedávání a ukládání dat z políček pro editaci textu. Pokud má tabulka více řádků, než je počet záznamů databáze, označíme řádky tabulky, které jsou přebytečné (TblSetRowUsable). Konečně u těch buněk tabulky, které obsahují statické položky, políčko k zaškrtnutí nebo výběr položky ze seznamu nastavujeme aktuální numerickou hodnotu a ukazatel asociované s buňkou tabulky (TblSetItemInt, TblSetItemPtr), které odvodíme z čísla příslušného záznamu. Příklad funkce pro aktualizaci dat tabulky z příkladu 2 je: void NaplnTabulku(TablePtr tabulka) { UInt16 pocetRadku = TblGetNumberOfRows(tabulka); UInt16 polozka, r; for(r = 0; r < pocetRadku; r++) { polozka = prvniRadek + r; // Převedeme číslo řádku na číslo záznamu if(polozka < POCET_HODNOT) { TblSetRowUsable(tabulka, r, true); TblSetRowID(tabulka, r, polozka); TblSetItemInt(tabulka, r, 0, polozka); TblSetItemInt(tabulka, r, 1, zaskrtnuto[polozka]); TblSetItemPtr(tabulka, r, 3, "Cislo"); } else { TblSetRowUsable(tabulka, r, false);
107
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
} TblMarkRowInvalid(tabulka, r); } TblRedrawTable(tabulka); }
Aktualizaci dat tabulky ve většině případů ukončíme funkcí TblRedrawTable, která překreslí ty řádky tabulky, které jsme předtím označili funkcí TblMarkRowInvalid.
Spolupráce tabulky s posuvníkem Propojit správně tabulku s posuvníkem vyžaduje dva jednoduché kroky: aktualizovat pozici jezdce na posuvníku při každé změně dat v tabulce a zpracovat systémové události, které posuvník zasílá naší aplikaci. K aktualizaci zobrazení posuvníku, v závislosti na obsahu tabulky, slouží jediná funkce: SclSetScrollBar. Tato funkce spočítá ze zadaných parametrů pozici a délku jezdce posuvníku a postará se o zobrazení posuvníku na displeji. Funkce vyžaduje čtyři číselné parametry: aktuální číslo prvního řádku tabulky, minimální a maximální možné číslo prvního řádku tabulky a počet řádků tabulky: UInt16 pocetRadku = TblGetNumberOfRows(tabulka); ... posledniHorni = (POCET_HODNOT > pocetRadku) ? (POCET_HODNOT - pocetRadku) : 0; SclSetScrollBar(posuvnik, prvniRadek, 0, posledniHorni, pocetRadku - 1);
Funkci SclSetScrollBar většinou voláme při každé aktualizaci tabulky, na konci funkce, kterou jsme pojmenovali NaplnTabulku. Tím zajistíme správné zobrazení posuvníku při každé změně dat v tabulce. Druhý krok, který musíme udělat, umožní použít posuvník k listování obsahem tabulky. I to je jednoduché: stačí zpracovat systémovou událost sclRepeatEvent nebo sclExitEvent. Událost sclRepeatEvent je v pravidelných intervalech zasílána naší aplikaci dokud uživatel posuvníkem pohybuje; tuto událost zpracováváme chceme-li, aby se obsah tabulky měnil při pohybu posuvníku. Dokončí-li uživatel pohyb posuvníkem, je naší aplikaci zaslána systémová událost sclExitEvent; pokud budeme reagovat až na tuto událost, bude tabulka překreslena až po skončení pohybu posuvníku. Tato varianta je uživatelsky méně přívětivá, ale rychlejší. Při zpracování události posuvníku pak jednoduše spočteme a nastavíme pozici nového prvního prvku tabulky, jehož index máme uložený v globální proměnné. Výpočet provádíme z rozdílu nové a původní hodnoty posuvníku. Poté znovu aktualizujeme data v tabulce a překreslíme ji. Boolean FunkceHlavnihoFormulare(EventPtr udalost) { ... switch(udalost->eType) {
108
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
case sclRepeatEvent: //nebo case sclExitEvent: if(udalost->data.sclRepeat.scrollBarID == PosuvnikTabulky)//data.sclExit... { rozdil = udalost->data.sclRepeat.newValue - udalost->data.sclRepeat.value; prvniRadek += rozdil; NaplnTabulku(true); } return false; ... } }
Stránkování tabulky pomocí hardwarových kláves Máme-li ve formuláři tabulku tak uživatel očekává, že bude moci stránkovat tabulkou pomocí hardwarových kláves pro pohyb nahoru a dolů. Stiskne-li uživatel nějakou klávesu, zašle operační systém PalmOS naší aplikaci zprávu keyDownEvent. V položce data.keyDown.chr je pak uložen kód klávesy: vchrPageUp pro horní a vchrPageDown pro spodní stránkovací klávesu. Při zpracování události keyDownEvent pak musíme změnit číslo záznamu v prvním řádku tabulky, které máme uloženo v globální proměnné, naplnit tabulku novými daty a překreslit ji: case keyDownEvent: if(udalost->data.keyDown.chr == vchrPageUp) { PosunTabulkuOStranku(TabulkaHlavni, -1); NaplnTabulku(); PrekresliTabulku(); return true; } else if(udalost->data.keyDown.chr == vchrPageDown) { PosunTabulkuOStranku(TabulkaHlavni, 1); NaplnTabulku(); PrekresliTabulku(); return true; } break; // Funkce sloužící k posunutí prvního řádku tabulky o stránku nahoru // nebo dolů void PosunTabulkuOStranku(UInt16 tabulkaID, Int16 znamenko) { FormPtr formular = FrmGetActiveForm(); UInt16 indexTabulky = FrmGetObjectIndex(formular, TabulkaID); TablePtr tabulka = (TablePtr)FrmGetObjectPtr(formular, indexTabulky); UInt16 pocetRadku = TblGetNumberOfRows(tabulka); // velikost stránky UInt16 posledniHorni; prvniRadek -= znamenko * pocetRadku;
109
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Upravíme pozici prvního řádku tak, abychom nepřekročili hranice // tabulky. Poslední možný horní řádek je zvolen tak, aby i při // odstránkování na konec měla tabulka všechny řádky vyplněné. if(prvniRadek < 0) prvniRadek = 0;
}
posledniHorni = (POCET_HODNOT>pocetRadku)?(POCET_HODNOT-pocetRadku):0; if(prvniRadek > posledniHorni) prvniRadek = posledniHorni;
Práce se statickými buňkami pro zobrazení čísla, data a textu Do každé buňky tabulky může uživatel vložit jednu celočíselnou hodnotu pomocí funkce TblSetItemInt a jeden ukazatel, k jehož vložení slouží funkce TblSetItemPtr. Statické buňky využívají tyto hodnoty k zobrazení čísla, textu nebo data. Buňka zobrazující číslo (numericTableItem) Buňka zobrazující datum (dateTableItem)
Buňka zobrazující text ukončený dvojtečkou (labelTableItem)
Celočíselná hodnota Ukazatel Číslo, které bude zobrazeno v buňce tabulky. Číslo je vždy zobrazeno tučným písmem. Datum ve tvaru DateType (16bitová hodnota, popsaná ve 4. kapitole). Datum je zobrazeno standardním písmem. Pokud je datum v minulosti, je za ním napsán vykřičník. Můžeme nastavit hodnotu –1, která znamená, že místo data bude vykreslena pomlčka. Ukazatel na text, který bude zobrazen v buňce.
Pokud chceme, aby sloupeček tabulky obsahoval nějaký text, který je ve všech řádcích shodný, můžeme jej nastavit přímo při inicializaci tabulky. Char* textSloupecku = “Datum“; void InicializujTabulku(TablePtr tabulka) { ... for(r = 0; r < pocetRadku; r++) { ... TblSetItemStyle(tabulka, r, 3, labelTableItem); TblSetItemPtr(tabulka, r, 3, textSloupecku); } ... }
110
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Pokud není hodnota v tabulce v celém sloupečku stejná, musíme ji nastavovat při aktualizaci dat tabulky podle řádku, ke kterému buňka patří. Nesmíme zapomenout tabulku na konci překreslit, aby se změny hodnot projevily i na displeji. void NaplnTabulku(TablePtr tabulka) { ... DateType datum; for(r = 0; r < pocetRadku; r++) { polozka = prvniRadek + r; ...
// Nastavení celočíselné hodnoty TblSetItemInt(tabulka, r, 0, cislo[polozka]); // Nastavení data
... } }
DateSecondsToDate(cas[polozka], &datum); TblSetItemInt(tabulka, r, 1, (Int16)datum);
TblRedrawTable(tabulka);
Chceme-li, aby buňka tabulky obsahovala text bez dvojtečky, datum v jiném formátu nebo číslo s desetinnou čárkou, musíme použít uživatelem vykreslované buňky tabulky.
Práce s uživatelsky kreslenými buňkami Uživatelsky kreslené buňky použijeme vždy, když potřebujeme v políčku tabulky zobrazit obsah, který neodpovídá některému z předdefinovaných typů políček. Používáme-li uživatelsky kreslené buňky v naší aplikaci, musíme sami napsat funkci, která vykreslí obsah jedné buňky tabulky podle následujícího vzoru: void VykresliPolicko(void *tabulka, Int16 radek, Int16 sloupek, RectangleType *hranice) { UInt16 zaznam = TblGetRowID(tabulka, radek); }
// Příkazy pro kreslení políčka
Při inicializaci tabulky nastavíme pomocí funkce TblSetItemStyle v celém sloupečku tabulky typ buněk, které si budeme přát vykreslovat jako customTableItem. Na konci inicializace zavoláme funkci TblSetCustomDrawProcedure, které předáme adresu naší funkce pro kreslení buněk a číslo sloupečku.
111
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void InicializujTabulku(TablePtr tabulka) { ... for(r = 0; r < pocetRadku; r++) { ... TblSetItemStyle(tabulka, r, 4, customTableItem); } ... TblSetCustomDrawProcedure(tabulka, 4, VykresliPolicko); }
O volání funkce pro uživatelské kreslení tabulky se správnými parametry se postará operační systém. Funkci je předáno číslo řádku a sloupečku, ve kterém se buňka nachází a výřez, udávající pozici buňky na displeji a její velikost. Z čísla řádku můžeme pomocí funkce TblGetRowID zjistit 16bitové číslo, které jsme nastavili funkcí TblSetRowID při aktualizaci dat tabulky. Například takto můžeme ke každému řádku tabulky při aktualizaci tabulky přiřadit číslo záznamu databáze, který je na něm zobrazen. Z uživatelsky definované funkce pro kreslení tabulky můžeme volat i další funkce, například TblGetRowData pro zjištění 32bitové datové hodnoty, kterou jsme při aktualizaci dat tabulky nastavili funkcí TblSetRowData. Tato datová hodnota může například obsahovat ukazatel na data v paměti, která se k příslušnému řádku vztahují. Opět nesmíme zapomenout nastavit správnou datovou hodnotu při aktualizaci dat tabulky. Pro podrobný popis funkcí PalmOS pro kreslení se podívejte do následující kapitoly; nyní si uvedeme jednoduchou funkci, která zobrazí v buňce tabulky text „Ano“ nebo „Ne“. Abychom mohli tuto funkci pro kreslení použít ve více sloupečcích tabulky, budeme používat funkce TblSetItemInt a TblGetItemInt pro uložení logické hodnoty pro každou buňku zvlášť. void VykresleniPolicka3(void *tabulka, Int16 radek, Int16 sloupec, RectangleType *ohraniceni) { Boolean vybrano = TblGetItemInt((TablePtr)tabulka, radek, sloupec); Char text[20]; StrCopy(text, vybrano ? "ANO" : "ne"); // Vlastní kreslení
}
WinSetClip(ohraniceni); // Opatření, abychom nepřekročili hranice FntSetFont(stdFont); // Normální písmo WinDrawChars(text, StrLen(text), ohraniceni->topLeft.x, ohraniceni->topLeft.y); WinResetClip();
Funkce pro kreslení dat tabulky může být stejná pro více sloupečků. Pokud obsahuje naše tabulka více uživatelsky kreslených sloupečků, rozlišíme ten, který je potřeba vykreslit podle čísla sloupečku, které je předáno funkci pro uživatelské kreslení. Příklad 3 shrnuje použití statických prvků a uživatelsky kreslených buněk v tabulce, spolu se stránkováním pomocí hardwarových kláves a posuvníkem.
112
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Práce s buňkami obsahujícími políčka k zaškrtnutí a výběr ze seznamu V buňce tabulky se může nacházet fungující políčko k zaškrtnutí nebo tlačítko pro výběr ze seznamu. Operační systém PalmOS ošetřuje zaškrtnutí políček nebo výběr ze seznamu sám. Celočíselná hodnota uložená v buňce tabulky (funkcí TblSetItemInt) pak udává stav políčka k zaškrtnutí nebo vybraný prvek seznamu. Celočíselná hodnota Ukazatel Logická hodnota, udávající Buňka s políčkem k zaškrtnutí zda je políčko zaškrtnuto nebo (checkboxTableItem) ne. Pořadí prvku seznamu, který Ukazatel na data seznamu Buňka se seznamem (datový typ ListPtr). (popupTriggerTableItem) je vybrán Při inicializaci tabulky je potřeba nastavit typ buněk. U buněk obsahujících seznam musíme nejprve seznam definovat ve formuláři s vlastností NONUSABLE. Na jeho umístění nezáleží, manažer tabulek jej zobrazí vždy u buňky tabulky, kterou měníme. FORM ID HlavniFormular AT (0 0 160 160) BEGIN LIST "A" "B" "C" "D" ID Seznam1 AT (1 1 30 AUTO) VISIBLEITEMS 4 NONUSABLE TABLE ID TabulkaHlavni AT (2 20 144 110) ROWS 10 COLUMNS 4 COLUMNWIDTHS 40 30 30 40 END
Funkce pro inicializaci tabulky obsahuje následující kód, kterým přiřadíme každé buňce ukazatel na příslušný seznam: static void InicializujTabulku() { ... UInt16 indexSeznamuCisel = FrmGetObjectIndex(formular, Seznam3); ListPtr seznamCisel = FrmGetObjectPtr(formular, indexSeznamuCisel); UInt16 indexSeznamuPismen = FrmGetObjectIndex(formular, Seznam1); ListPtr seznamPismen = FrmGetObjectPtr(formular, indexSeznamuPismen);
113
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
for(r = 0; r < pocetRadku; r++) { TblSetItemStyle(tabulka, r, 0, checkboxTableItem); TblSetItemStyle(tabulka, r, 1, popupTriggerTableItem); TblSetItemPtr(tabulka, r, 1, seznamCisel); TblSetItemStyle(tabulka, r, 2, popupTriggerTableItem); TblSetItemPtr(tabulka, r, 2, seznamPismen); } }
...
Při aktualizaci dat tabulky pak jenom nastavením příslušné hodnoty funkcí TblSetItemInt měníme stav zaškrtnutí nebo pořadí vybraného prvku seznamu. Ve funkci formuláře musíme zpracovávat událost tblSelectEvent, kterou zašle operační systém naší aplikaci vždy, když uživatel změní stav políčka k zaškrtnutí nebo seznamu voleb. Při zpracování této události musíme změněnou hodnotu uložit. Podrobněji si můžete práci s buňkami, které obsahují volbu ze seznamu, prohlédnout v příkladu 1 a práci s políčky k zaškrtnutí v příkladu 2.
Práce s buňkami pro editaci textu Buňky tabulky, které obsahují políčka pro editaci textu jsou nejhůře ovladatelné a mohou při špatném použití způsobovat pády operačního systému. Jejich použití si můžete prohlédnout v příkladu 2. Při inicializaci buněk, které budou sloužit k zadávání textu musíte v programu definovat dvě funkce, které bude operační systém PalmOS volat pro uložení a vyzvednutí textu z buňky tabulky. Adresy těchto funkcí pak předáte správci tabulek PalmOS voláním TblSetLoadDataProcedure a TblSetLoadDataProcedure: void InicializujTabulku() { ... for(r = 0; r < pocetRadku; r++) { ... TblSetItemStyle(tabulka, r, 4, textTableItem); TblSetRowStaticHeight(tabulka, r, true); } // Nastaveni sloupecku tabulky for(s = 0; s < 5; s++) { TblSetColumnUsable(tabulka, s, true); TblSetColumnEditIndicator(tabulka, s, false); }
114
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
TblSetColumnEditIndicator(tabulka, 3, true); TblSetLoadDataProcedure(tabulka, 4, VyzvedniCislo4); TblSetSaveDataProcedure(tabulka, 4, UlozCislo4); }
Při definici tabulky, která bude obsahovat políčka pro editaci textu můžeme také definovat, zda se může výška řádku při psaní textu do buňky měnit (funkce TblSetRowStaticHeight) a které buňky budou zvýrazněné, když budeme zapisovat text do políčka (funkce TblSetColumnEditIndicator). O aktualizaci dat v políčkách se musíme postarat v námi definovaných funkcích pro vyzvedávání a ukládání textu z buňky. Pomocí funkce TblSetLoadDataProcedure předáváme správci tabulek adresu funkce, která mu poskytne ovladač přemístitelného bloku v paměti, který obsahuje text políčka. Funkce je definována takto: Err VyzvedniCislo4(void *tabulka, Int16 radek, Int16 sloupec, Boolean editovat, MemHandle *data, Int16 *dataOffset, Int16 *dataVelikost, FieldPtr policko) { UInt16 polozka = TblGetRowID((TablePtr)tabulka, radek); *data = ovladač přemístitelného bloku paměti, ve kterém jsou data buňky; *dataOffset = 0; // kde v tomto bloku paměti začíná text *dataVelikost = MemHandleSize(*data); }
return 0;
Tato funkce je volána ve dvou případech: jednak při vykreslování tabulky (parametr editovat má hodnotu false) a v okamžiku, kdy uživatel zvolí buňku s políčkem pro vstup textu (parametr editovat má hodnotu true). Tímto krokem se přepne tabulka do režimu změny textu, kdy je aktivním prvkem příslušné políčko. Poslední parametr funkce obsahuje ukazatel na data políčka, který můžeme využít například ke změně vlastností políčka před editací a podobně. Po skončení úprav textu v buňce (když uživatel zvolí jinou buňku nebo jiný ovládací prvek formuláře) opustí tabulka režim změny textu a správce tabulek volá druhou funkci, která slouží k uložení textu z políčka. Adresu této funkce předáváme správci tabulek voláním TblSetSaveDataProcedure. Tuto funkci nemusíme implementovat, pokud nám stačí, že změněný text bude uložen v příslušném bloku paměti, jehož adresu vrátila předchozí funkce. Tato funkce vrací logickou hodnotu true pokud je potřeba překreslit tabulku. Pokud tuto funkci implementujeme, může být definována například následujícím způsobem:
115
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Boolean UlozCislo4(void *tabulka, Int16 radek, Int16 sloupec) { UInt16 polozka = TblGetRowID((TablePtr)tabulka, radek); FieldPtr policko = TblGetCurrentField((TablePtr)tabulka); MemHandle ovladac; if(!policko) { return false; } if(!FldDirty(policko)) { return false; } ovladac = FldGetTextHandle(policko); if(ovladac) { // dělej něco s textem v políčku }
}
TblMarkRowInvalid((TablePtr)tabulka, radek); return true;
Políčka pro změnu textu v tabulce mohou mít také proměnlivou velikost (pokud při inicializaci voláme funkci TblSetRowStaticHeight s parametrem false. Práce s těmito tabulkami je však o to komplikovanější, že se mění počet řádků tabulky v závislosti na výškách jednotlivých řádků. Operační systém v takovém případě zasílá naší aplikaci událost fldHeightChangedEvent vždy, je-li potřeba tabulku přepočítat.
116
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Základy grafiky První modely Palm Pilota měly pouze černobílý LCD displej a obsahovaly jednoduchou sadu funkcí pro černobílé kreslení. Postupně, od verze PalmOS 3.5, se objevovala možnost zobrazit na displeji odstíny šedi. Počítače s novějšími verzemi PalmOS již obsahovaly podporu kreslení v barvách a dvojnásobného rozlišení displeje. V této kapitole se naučíme používat základní funkce pro černobílé kreslení. Většina těchto funkcí je obsažena už v první verzi PalmOS; programy, které používají ke grafickému výstupu funkce z této kapitoly budou fungovat na většině modelů počítačů Palm Pilot a kompatibilních.
Začínáme kreslit Nejjednodušší způsob pro kreslení na displeji Palm Pilota je přímé volání kreslících funkcí, bez zdlouhavých úvah o kreslících oknech a uloženém grafickém stavu. V dalších odstavcích se naučíme chování těchto funkcí upravit tak, aby bylo jejich použití elegantnější. Pro začátek ale stačí, když vytvoříme prázdný formulář a do funkce formuláře uvedeme následující řádky (příklad 1): static Boolean FunkceHlavnihoFormulare(EventPtr udalost) { ... switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); WinDrawLine(30, 30, 130, 30); WinDrawLine(30, 130, 130, 130); WinDrawGrayLine(30, 30, 30, 130); WinDrawGrayLine(130, 30, 130, 130); WinDrawLine(40, 40, 120, 120); WinDrawLine(40, 120, 120, 40); WinDrawChars("Priklad", 7, 50, 50);
... }
zpracovano = true; break;
Na displeji se při spuštění aplikace vykreslí jednoduchý obrázek sestávající z čar a jednoduchého textu. Základní funkce pro kreslení čar jsou WinDrawLine, WinEraseLine, WinDrawGrayLine a WinInvertLine. Uvedené funkce kreslí čáru z bodu o souřadnicích (x1, y1) do bodu o souřadnicích (x2, y2). Čára může být černá (WinDrawLine), v barvě pozadí (WinEraseLine), inverzní (WinInvertLine) nebo tečkovaná (WinDrawGrayLine). V našem příkladu je pro kreslení použita celá plocha displeje a počátek souřadnic je v levém horním rohu displeje. Výsledek si můžeme prohlédnout na obrázku:
117
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Vykreslení textu Pro vykreslení textu na displeji v černé barvě (na barevných modelech v nastavené barvě popředí) a v barvě pozadí slouží obdobně pojmenované funkce (WinDrawChars, WinEraseChars). Pro vykreslení bílých znaků na černém pozadí slouží funkce WinDrawInvertedChars a WinInvertChars. První z jmenovaných funkcí vykreslí černý rámeček, obsahující bílý text; druhá pouze nahradí bílé obrazové body černými a černé bílými. V prvním parametru předáváme funkcím adresu řetězce a ve druhém parametru počet znaků, které si přejeme vykreslit (nejčastěji délku řetězce). Pro vyzkoušení invertovaného textu doplníme příklad 1 o následující řádky, ilustrující použití funkcí pro vykreslení textu na displeji při zpracování události doteku pera na displeji (penDownEvent): Char* gTexty[] = {"Tuky tuk", "jeste tuk", "uz to bude", "to je ono!!!", NULL }; Char* gText = "Ahoj!!!"; UInt16 gIndex = 0; static Boolean FunkceHlavnihoFormulare(EventPtr udalost) { ... case penDownEvent: if(gTexty[gIndex]) { WinDrawInvertedChars(gTexty[gIndex], StrLen(gTexty[gIndex++]), 50, 122); } WinInvertChars(gText, StrLen(gText), 50, 25); }
...
Rozdíl mezi textem, který vykresluje funkce WinDrawInvertedChars (spodní text) a textem zobrazeným funkcí WinInvertChars je na obrázku. Všimněte si, že když zavoláte funkci WinInvertChars dvakrát po sobě se stejnými parametry, jsou původně invertované obrazové body invertovány podruhé a text zmizí.
118
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Text vykreslený funkcí WinInvertChars Text vykreslený funkcí WinDrawChars Text vykreslený funkcí WinDrawInvertedChars
Změna písma Paměť ROM počítačů Palm Pilot a kompatibilních obsahuje 8 typů písma (font), které můžeme zobrazit pomocí funkce WinDrawChars a podobných. V české lokalizaci PalmOS obsahují tato písma české znaky. Výběr písma ke zobrazení se provádí funkcí FntSetFont. Parametrem funkce FntSetFont je konstanta typu FontID udávající typ písma. Tato konstanta může označovat jedno ze znakových písem v následující tabulce: Konstanta stdFont boldFont largeFont largeBoldFont ledFont
Popis Příklad Standardní písmo, použité k vykreslování většiny formulářů atd. Tučné písmo – je stejně vysoké jako standardní písmo, znaky jsou silnější. Vysoké písmo. Velké a tučné písmo, které se objevuje v PalmOS 3.0. Číslice 0-9 a znak mínus, které jsou využity při zobrazení výsledku v kalkulačce.
Také můžeme použít jedno z písem, obsahujících symboly. Tato písma jsou tři a přehled symbolů, které obsahují je v následující tabulce. Nahoře je vždy uvedena konstanta v osmičkové soustavě, kterou můžete použít při zápisu znaku v jazyce C++ - například ‘\001‘.
119
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Operační systém si pamatuje naposledy použité písmo; toto písmo můžete zjistit voláním funkce FntGetFont. Dobrým zvykem je nastavit po ukončení kreslení písmo, které bylo původně vybráno podobně jako v následujícím příkladu: FontID starePismo = FntGetFont(); FntSetFont(largeFont); ... FntSetFont(starePismo);
Výšku vybraného písma zjistíme voláním funkce FntCharHeight, doporučenou výšku řádku psaného tímto písmem vrací funkce FntLineHeight. Délku textu v obrazových bodech zjistíme funkcí FntCharsWidth. Příklad 2 vykreslí ve formuláři seznam standardních písem: FontID starePismo = FntGetFont(); for(i = 0, y = 20; i < POCET_RADKU; i++) { x = 20; FntSetFont(gTexty[i].pismo); WinDrawChars(gTexty[i].text, StrLen(gTexty[i].text), x, y); x += FntCharsWidth(gTexty[i].text, StrLen(gTexty[i].text)) + 10; FntSetFont(stdFont); WinDrawInvertedChars(gTexty[i].typ, StrLen(gTexty[i].typ), x, y); // Posuneme o doporučenou výšku řádku a něco navíc FntSetFont(gTexty[i].pismo); y += FntLineHeight() + 3; } FntSetFont(starePismo);
Výsledek si můžete prohlédnout na obrázku vlevo. Obrázek vpravo zobrazuje standardní dialog pro výběr písma. Pokud chceme v naší aplikaci nechat uživatele vybrat písmo, použijeme funkci FontSelect, jejíž definice je pod obrázkem.
FontID FontSelect();
120
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Výřezy (Rectangles) Pro řadu grafických operací se nám hodí datový typ, který obsahuje definici obdélníkového výřezu displeje. Operační systém PalmOS takový typ definuje a nabízí několik funkcí, které mohou s výřezy komfortně pracovat. Definice datového typu RectangleType typu pro uložení výřezu je následující: typedef struct PointType { Coord x; Coord y; } PointType; typedef struct RectangleType { PointType topLeft; // Souřadnice x a y levého horního rohu PointType extent; // Šířka x a výška y výřezu } RectangleType; typedef RectangleType *RectanglePtr;
extent.x
topLeft.x topLeft.y
extent.y S výřezy pracujeme prostřednictvím funkcí, kterým předáváme jejich adresu. Funkce RctSetRectangle slouží k jednoduché definici výřezu; pomocí funkce RctCopyRectangle můžeme parametry výřezu kopírovat z jedné struktury do druhé. Chceme-li zjistit, zda se bod o souřadnicích x, y nachází uvnitř výřezu, voláme funkci RctPtInRectangle. Výřezy je možné zmenšovat a zvětšovat (funkce RctInsetRectangle) a posouvat po displeji (funkcí RctOffsetRectangle). Známe-li dva výřezy, můžeme funkcí RctGetIntersection zjistit jejich průnik. Pro kreslení vyplněných výřezů můžeme použít – podobně jako při kreslení čar a písma – tři základní funkce: WinDrawRectangle pro vyplnění černou barvou, WinEraseRectangle pro vyplnění bílou barvou a WinInvertRectangle pro převrácení barev. Všem těmto funkcím předáváme ukazatel na datovou strukturu výřezu a celé číslo, které udává zaoblení rohů (0 znamená pravoúhlý výřez). Pomocí funkcí WinDrawRectangleFrame, WinEraseRectangleFrame, WinInvertRectangleFrame a WinDrawGrayRectangleFrame můžeme vykreslit rámeček kolem výřezu. Jejich první parametr označuje tvar rámečku. Možné hodnoty jsou například simpleFrame (jednoduchý rámeček), roundFrame (zaoblené rohy) nebo například boldRoundFrame pro rámeček široký dva body se zaoblenými rohy. 121
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Definované výrazy jsou použity v příkladu 3, ve kterém pohybujeme nakresleným výřezem po displeji podle příkazů v menu. Při zpracování události menuEvent nejprve vymažeme plochu okna a posuneme static RectangleType pohyblivy, staly, vyrez; // zpracování události menuEvent: ... RctSetRectangle(&vyrez, 0, 18, 160, 142); WinEraseRectangle(&vyrez, 0); // Pohneme výřezem if(udalost->data.menu.itemID == MenuPohybVpravo) { RctOffsetRectangle(&pohyblivy, 5, 0); // Pohyb o 5 bodů na ose X } ... else if(udalost->data.menu.itemID == MenuZmensi) { RctInsetRectangle(&pohyblivy, 5); // Zmenšení } WinDrawRectangleFrame(roundFrame, &pohyblivy); WinDrawGrayRectangleFrame(roundFrame, &staly); RctGetIntersection(&pohyblivy, &staly, &vyrez); if(vyrez.extent.x > 0 && vyrez.extent.y > 0) { // Pokud je výřez definován, jsou obě dvě tyto hodnoty větší než 0 WinDrawRectangle(&vyrez, 0); }
Na displeji vždy vykreslíme dva výřezy: tečkovaný, který zůstává na jednom místě, a černý, kterým můžeme pohybovat pomocí příkazů v menu. Pokud se tyto výřezy protínají, je jejich průsečík vyplněn černou barvou, podobně jako na následujícím obrázku:
Ořezávání (clipping) Někdy potřebujeme omezit kreslení jen na určitou plochu na displeji – například na jeden řádek seznamu nebo na políčko tabulky. K zajištění toho, že při našem kreslení ani omylem nepřekročíme hranice definovaného výřezu slouží funkce pro nastavení ořezávání 122
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
WinSetClip. Po zavolání této funkce bude možné kreslit jen uvnitř zadaného výřezu – pokud bude část textu přesahovat výřez, tak jednoduše nebude vykreslena. Funkci WinSetClip můžeme použít například ve funkci pro uživatelské vykreslení řádku seznamu. V následujícím příkladu (příklad 4) může být text, který kreslíme na řádku seznamu libovolně dlouhý i vysoký: pokud text přesáhne hranice nastaveného výřezu, bude na displeji zobrazena jen ta část textu, která leží uvnitř. Nastavené ořezávání odstraníme voláním funkce WinResetClip. void KresliRadekSeznamu(Int16 cislo, RectangleType *vyrez, Char **texty) { Coord x = vyrez->topLeft.x; Coord y = vyrez->topLeft.y; WinSetClip(bounds); // při kreslení nemůžeme poté ani omylem překročit hranice výřezu WinDrawChars(gTexty[cislo].text, StrLen(gTexty[cislo].text), x, y); WinResetClip(); }
Okna (windows) Mnohem elegantnější a lépe využitelná metoda kreslení na displeji Palm Pilota využívá okna (windows). Pomocí funkce WinCreateWindow vytvoříme na displeji jedno nebo více oken, do kterých můžeme kreslit. Okna mají vlastní souřadnice číslované od nuly; jejich souřadnice jsou nezávislé na umístění okna na displeji. 0, 0 Displej Palm Pilota
0, 0 Okno
Okna, která jsou vytvářena funkcí WinCreateWindow mohou být orámována. Funkce WinCreateWindow sice okno vytvoří, ale na displeji pouze rezervuje místo pro rámeček. Typ rámečku, který je stejný jako pro funkci WinDrawRectangleFrame, je uložen v paměti a později je použit při mazání okna. Funkci WinCreateWindow předáváme dva logické parametry, které určují chování okna při vstupu znaků Graffitti; obě hodnoty budou mít v našich aplikacích hodnotu false. Chceme-li vykreslit rámeček kolem okna, použijeme funkci WinDrawRectangleFrame.
123
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Seznam oken je uložen v paměti; abychom mohli s okny manipulovat, používáme ovladače okna (window handles). Pomocí funkce WinSetDrawWindow, můžeme určit, ve kterém okně budeme kreslit; přejeme-li si kreslit po celé ploše displeje, můžeme zjistit ovladač okna celého displeje pomocí funkce WinGetDisplayWindow. Od okamžiku, kdy zavoláme funkci WinSetDrawWindow můžeme kreslit jen v okně, jehož ovladač jsme funkci předali. Chceme-li vytvořit okno s rámečkem, musíme po vytvoření okna sami nakreslit rámeček. Protože rámeček bude vně okna, musíme před jeho vykreslením zajistit, že bude kreslen v okně, které zabírá celou plochu displeje; ovladač získáme voláním funkce WinGetDisplayWindow. Pro vytvoření okna s rámečkem může sloužit například tato funkce: WinHandle VytvorOknoSRameckem(RectanglePtr vyrez, FrameType ram) { WinHandle okno; UInt16 chyba; okno = WinCreateWindow(vyrez, ram, false, false, &chyba); if(okno) { WinHandle puvodniOknoProKresleni = WinGetDrawWindow(); // Budeme kreslit po celé ploše displeje WinSetDrawWindow(WinGetDisplayWindow()); WinDrawRectangleFrame(ram, vyrez); // Obnovíme původní okno pro kreslení WinSetDrawWindow(puvodniOknoProKresleni); } }
return okno;
Souřadnice levého horního rohu každého okna jsou 0,0 a rozměry okna, ve kterém kreslíme, zjistíme pomocí funkce WinGetWindowExtent. Při kreslení v okně je automaticky nastavené ořezávání tak, abychom nemohli kreslit mimo hranice okna. void NakresliNecoVOkne(WinHandle okno) { Coord sirka, vyska; // Vybereme pro kreslení okno, jehož ovladač jsme funkci předali // a zjistíme jeho rozměry WinHandle puvodniOknoProKresleni = WinGetDrawWindow(); WinSetDrawWindow(okno); WinGetWindowExtent(&sirka, &vyska); // Nakreslíme v okně čáry WinDrawLine(0, 0, sirka-1, vyska-1); WinDrawLine(0, vyska-1, sirka-1, 0);
124
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
WinDrawGrayLine(0, 0, sirka-1, 0); WinDrawGrayLine(0, 0, 0, vyska-1); WinDrawGrayLine(sirka-1, 0, sirka-1, vyska-1); WinDrawGrayLine(0, vyska-1, sirka-1, vyska-1); // Obnovíme původní okno pro kreslení }
WinSetDrawWindow(puvodniOknoProKresleni);
K odstranění okna z paměti (a chceme-li i k jeho vymazání z displeje) slouží funkce WinDeleteWindow. Logická hodnota, kterou předáváme této funkci určuje, zda si přejeme okno i vymazat. V některých případech, například víme-li, že budeme za chvíli překreslovat celý displej nebo před zavřením formuláře, nemusíme jednotlivá okna mazat. Okno je vymazáno i s rámečkem, jehož typ jsme nastavili při vytvoření okna.
Rámeček, nakreslený funkcí WinDrawRectangleFrame 0, 0 okno vytvořené funkcí WinCreateWindow
Oblast, vymazaná funkcemi WinEraseWindow a WinDeleteWindow
Pokud v našem formuláři používáme okna, je nejvhodnější vytvořit je při zpracování události frmOpenEvent a uložit jejich ovladače do globálních proměnných. Poté je můžeme vymazat z paměti při zpracování události frmCloseEvent ve funkci formuláře (příklad 5). case frmOpenEvent: RctSetRectangle(&vyrez, ......); gOkno = WinCreateWindow(&vyrez, noFrame, false, false, &chyba); return true; ... case frmCloseEvent: WinDeleteWindow(gOkno, false); return false;
Souřadnice doteku pera na displeji Dotkneme-li se perem displeje, zařadí operační systém PalmOS do fronty událostí událost penDownEvent a při zvednutí pera událost penUpEvent. Pokud perem pohybujeme po displeji, je opakovaně zasílána událost penMoveEvent. Za normálních okolností zpracuje všechny tyto události sám operační systém, který se na jejich základě rozhoduje, zda jsme stiskli tlačítko, pohnuli posuvníkem a podobně. Někdy však potřebujeme na pohyb pera po displeji reagovat v našem programu, například abychom umožnili uživateli na displeji kreslit.
125
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Struktura EventType, která popisuje událost, obsahuje prvky screenX a screenY. V nich je uložena souřadnice doteku pera na displeji. Pokud bychom chtěli, aby se na displeji vykreslovaly tečky v místech pohybu pera, stačí zpracovat všechny tyto události ve funkci formuláře: case penDownEvent: case penMoveEvent: case penUpEvent: if(udalost->screenY < 160) { WinDrawLine(udalost->screenX, udalost->screenY, udalost->screenX, udalost->screenY); zpracovano = true; } break;
Popsaný příklad (příklad 6) není ideální: dovoluje kreslit i po titulku formuláře a pohybujeme-li perem příliš rychle, čára se nám rozpadá do jednotlivých teček, jak PalmOS nestíhá sledovat pohyb pera. Pokud bychom ve formuláři měli tlačítko, nebude jej možné stisknout, protože naše aplikace sama zpracuje všechny pohyby pera po displeji. V praxi používáme pro kreslení okna, která vytváříme ve funkci formuláře. Proto potřebujeme funkce pro převod souřadnic na displeji na souřadnice uvnitř okna. Funkce WinDisplayToWindowPt slouží k převodu souřadnic na displeji na souřadnice uvnitř okna, ve kterém kreslíme. Obrácený převod je možný funkcí WinWindowToDisplayPt. // Globální proměnné RectangleType gVyrezOkna; WinHandle gOkno; Coord stareX, stareY; ... case penMoveEvent: if(RctPtInRectangle(udalost->screenX, udalost->screenY, &gVyrezOkna)) { // Souřadnice x a y relativně k displeji Coord x = udalost->screenX; Coord y = udalost->screenY; WinSetDrawWindow(gOkno); // Souřadnice x a y relativně k oknu, do kterého kreslíme WinDisplayToWindowPt(&x, &y);
126
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Spojujeme s předchozím bodem WinDrawLine(stareX, stareY, x, y); WinSetDrawWindow(WinGetDisplayWindow()); stareX = x; stareY = y; zpracovano = true; } break;
Prohlédněte si příklad 7, ve kterém perem kreslíme na displeji čáry, které začínají plným a končí dutým čtverečkem. Při otevření formuláře (frmOpenForm) vytvoříme výřez, obsahující souřadnice okna a vlastní okno. Okno zrušíme při zavření formuláře (frmCloseForm). Zpracujeme všechny tři události pohybu pera: při penDownEvent nakreslíme plný čtvereček a uložíme souřadnice, při penMoveEvent nakreslíme čáru od předchozích souřadnic a při penUpEvent nakreslíme prázdný čtvereček.
Při zpracování událostí pohybu pera využíváme funkci RctPtInRectangle, která pomůže zjistit, zda se událost týká okna, ve kterém kreslíme. Pokud ano, nastavíme naše okno jako nové okno pro kreslení funkcí WinSetDrawWindow a převedeme souřadnice doteku pera na displeji na relativní souřadnice v okně. Nesmíme zapomenout vrátit zpět původní okno pro kreslení (zavoláme WinSetDrawWindow s parametrem ovladače okna celého displeje.
Neviditelná okna (offscreen windows) Okna pro kreslení můžeme vytvářet nejen na displeji, ale i v paměti. Okno, které vytvoříme v paměti, může mít libovolnou velikost a můžeme v něm kreslit úplně stejně, jako v oknech na displeji. Okno v paměti vytvoříme funkcí WinCreateOffscreenWindow, které předáme požadované rozměry okna. Vytvořené okno zrušíme pomocí WinDeleteWindow. Zvolíme-li okno v paměti pro kreslení pomocí funkce WinSetDrawWindow, můžeme v něm kreslit stejně jako v oknech na displeji. UInt16 chyba; WinHandle gOkno = WinCreateOffscreenWindow(100, 60, screenFormat, &chyba); WinSetDrawWindow(gOkno); ...
127
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// v okně můžeme kreslit pomocí již uvedených funkcí pro čb kreslení WinDrawLine(0, 0, 99, 59); WinDeleteWindow(gOkno, false);
Neviditelná okna jsou uložena v paměti a jejich velikost a počet je omezen pouze dostupnou pamětí. Na konci programu nesmíme zapomenout všechna neviditelná okna, která jsme vytvořili, zrušit.
Okno displeje, jehož ovladač získáme funkcí WinGetDisplayWindow Okno, které jsme na displeji vytvořili funkcí WinCreateWindow
Okna, která vytváříme v paměti funkcí WinCreateOffscreenWindow
Při použití neviditelných oken je nejdůležitější funkce WinCopyRectangle, která umožňuje zkopírovat výřez z kteréhokoliv okna (na displeji i v paměti) do kteréhokoliv okna (na displeji i v paměti). Prohlédněte si příklady 8 a 9. V prvním z nich je na displeji opakovaně vykreslován obrázek pohybujících se čar: animace je pomalá a neobratná. // Příklad 8 WinHandle gOkno; RectangleType& gVyrezOkna; static Boolean FunkceHlavnihoFormulare(EventPtr udalost) { Boolean zpracovano = false; UInt16 chyba; switch(udalost->eType) { case frmOpenEvent: FrmDrawForm(FrmGetActiveForm()); RctSetRectangle(&gVyrezOkna, 10, 30, 140, 120); gOkno = WinCreateWindow(&gVyrezOkna, noFrame, false, false, &chyba); KresliCary(gOkno, SIRKA_PASU, 20, gPozice++); zpracovano = true; break;
128
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
case nilEvent: KresliCary(gOkno, SIRKA_PASU, 20, gPozice++); break; case frmCloseEvent: WinDeleteWindow(gOkno, false); break;
} }
default: break;
return zpracovano;
Ve druhém příkladu (příklad 9) je nejprve vytvořeno okno v paměti a v každém kroku je obrázek vykreslen nejprve do okna v paměti. Toto vykreslování uživatel nevidí. Poté je celý obsah neviditelného okna, do kterého jsme kreslili, najednou zkopírován na displej. Výsledkem je plynulejší animace. case nilEvent: // Nakreslíme v neviditelném okně KresliCary(gNeviditelneOkno, SIRKA_PASU, 20, gPozice++); // Zkpírujeme do okna na displeji RctSetRectangle(&vyrez, 0, 0, gVyrezOkna.extent.x, gVyrezOkna.extent.y); WinCopyRectangle(gNeviditelneOkno, gOkno, &vyrez, 0, 0, winPaint); break;
Neviditelná okna můžeme použít i k uložení obrázků, které svými rozměry přesahují velikost displeje.
Rastrové obrázky (bitmaps) Chceme-li v naší aplikaci používat obrázky, musíme je nejprve definovat v souboru prostředků aplikace. Tyto obrázky budou po definici uloženy v souboru aplikace (*.prc). K definici obrázků slouží klíčová slova BITMAP (BITMAPGREY, BITMAPGREY16, BITMAPCOLOR) a BITMAPFAMILY. Obrázek v jednom barevném rozlišení definujeme v souboru prostředků aplikace podle následujícího příkladu: BITMAP ID IdentifikaceObrazku “soubor.bmp“
129
...vlastnosti...
Úvod do programování PalmOS
Klíčové slovo BITMAP BITMAPGREY BITMAPGREY16 BITMAPCOLOR
MUDr. Petr Lesný, 2003
Popis Černobílý obrázek. Obrázek používající černou barvu, bílou barvu a dva odstíny šedé. Obrázek v odstínech šedé. Barevný obrázek s 8 bity na jeden obrazový bod (nejvýše 256 barev).
Možné vlastnosti COMPRESS NOCOMPRESS FORCECOMPRESS COMPRESS NOCOMPRESS FORCECOMPRESS COLORTABLE NOCOLORTABLE TRANSPARENT r g b TRANSPARENTINDEX i
Obrázky musí být uloženy v souborech s příponou *.bmp, program pilrc se je v případě potřeby pokusí zkonvertovat do správného barevného rozlišení. U černobílých a šedých obrázků si můžete vybrat, zda bude obrázek uložen do souboru aplikace (*.prc) v úsporné podobě (FORCECOMPRESS), nebo tak, aby k němu měl operační systém rychlejší přístup (NOCOMPRESS). Při použití vlastnosti COMPRESS rozhodne program pilrc o formátu uloženého obrázku sám. Barevné obrázky mohou být uloženy s nejvýše 256 barvami. Aby i přes toto omezení bylo možné zobrazovat jiné než předdefinované barvy, může obrázek obsahovat vlastní „paletu barev“ (definujeme-li vlastnost COLORTABLE). Pokud naopak použijeme vlastnost NOCOLORTABLE, budou pro vykreslení obrázku použity standardní barvy operačního systému. To povede k výrazně rychlejší práci s obrázkem; může však dojít k trochu nepřesnému vykreslení barev. Pro barevné obrázky můžete navíc definovat „průhlednou“ barvu: buď podle barevných složek (TRANSPARENT r g b) nebo podle jejího indexu v barevné paletě (TRANSPARENTINDEX). Vlastnost TRANSPARENT 255 255 255 například způsobí, že při vykreslení obrázku bude všude kde je v obrázku bílá barva ponechána barva pozadí. BITMAP ID ObrazekCernobily "obr_cb.bmp" COMPRESS BITMAPGREY ID ObrazekSedy "obr_sedy.bmp" NOCOMPRESS BITMAPGREY16 ID ObrazekSedy2 "obr_sedy16.bmp" COMPRESS BITMAPCOLOR ID ObrazekBarevny "obr_barevny.bmp" COMPRESS COLORTABLE TRANSPARENT 255 255 255
Druhým způsobem, jak definovat v souboru prostředků aplikace je použití klíčového slova BITMAPFAMILY. Tím definujete sadu obrázků v různých barevných rozlišeních, ze kterých operační systém při vykreslování sám vždy vybere ten nejvhodnější. BITMAPFAMILY ID Obrazek “obr_cb.bmp“ “obr_sedy.bmp“ “obr_16.bmp“ “obr_barva.bmp“ ... [ COLORTABLE | NOCOLORTABLE ] [COMPRESS | NOCOMPRESS | FORCECOMPRESS ] [TRANSPARENT r g b ] [TRANSPARENTINDEX i ]
Při definici sady obrázků pomocí BITMAPFAMILY můžete některá rozlišení i vynechat; pokud například chcete v aplikaci použít pouze černobílou a barevnou variantu obrázku, můžete jej definovat jako:
130
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
BITMAPFAMILY ID Obrazek “obr_cb.bmp“ ““ ““ “obr_barva.bmp“ NOCOLORTABLE COMPRESS
Rastrové obrázky ve formuláři Pokud chcete umístit rastrový obrázek do formuláře nebo do dialogu, je to velmi jednoduché. Stačí v definici dialogu nebo formuláře uvést klíčové slovo FORMBITMAP, za kterým následuje jednoznačná identifikace rastrového obrázku, který jste vložil na jiném místě souboru prostředků aplikace. BITMAP ID ObrazekFormulare1 “obrazek_1.bmp“ NOCOMPRESS FORM ID Formular1 AT (0 0 160 160) BEGIN ... FORMBITMAP AT (10 100) BITMAP ObrazekFormulare1 ... END
Kreslení rastrových obrázků Pro vykreslení obrázku, který jsme uvedli v souboru prostředků aplikace na displej slouží funkce WinDrawBitmap. Kreslíme-li obrázek, který byl definován pomocí klíčového slova BITMAPFAMILY, bude vždy vykreslen v rozlišení displeje. Jinak se podaří obrázek vykreslit jen tehdy, bude-li barevné rozlišení displeje stejné nebo lepší, než je barevné rozlišení obrázku. static void KresliObrazek(UInt16 obrID, Coord x, Coord y) { MemHandle ovladac = DmGetResource(bitmapRsc, obrID); BitmapType* obrazek = (BitmapType*)MemHandleLock(ovladac); WinDrawBitmap(obrazek, x, y);
}
MemHandleUnlock(ovladac); DmReleaseResource(ovladac);
Funkce DmGetResource a DmReleaseResource slouží k vyzvednutí ukazatele na data ze souboru aplikace *.prc. Oba dva způsoby vykreslování rastrových obrázků si můžete prohlédnout v příkladu 10.
131
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Databáze Největší odlišnost počítačů s operačním systémem PalmOS od kapesních počítačů s jinými operačními systémy (GEOS, EPOC, Windows CE a nástupci) je to, že základ operačního systému PalmOS není tvořen systémem souborů. Místo toho používá PalmOS takzvané databáze. V databázích je uloženo doslova všechno – součásti operačního systému, knihovny, aplikace i jejich data. Základní odlišnosti databází od souborů jsou: • Databáze nejsou hierarchicky organizovány do „adresářů“ jako v běžném systému souborů; existuje pouze jedna základní úroveň. • V paměti základní dva typy databází: databáze záznamů, které slouží pro uložení dat a databáze prostředků (resource databases), ve kterých jsou uloženy aplikace, knihovny a součásti systému. • Každá databáze je označena nejenom jménem, ale i identifikací aplikace, která ji vytvořila. Po smazání aplikace jsou vymazány i všechny databáze, které aplikace vytvořila. • Kromě jména a identifikace aplikace obsahuje databáze také 32bitové (čtyřpísmenné) označení typu dat (které si může aplikace libovolně definovat a využívat při správě svých databází). • Databáze z paměti RAM mohou být označeny příznakem pro zálohování. Zálohované databáze jsou ukládány na stolním počítači v příslušném adresáři (C:\Palm\jméno\BACKUP). V dalším popisu databází se budeme věnovat pouze databázím záznamů, které se používají pro uložení dat. Databáze se skládá z hlavičky (header), jednotlivých záznamů (records) a nepovinných speciálních bloků, obsahujících například informace o kategoriích, třídění databáze a podobně. Důležité součásti hlavičky databáze jsou následující: Prvek Jméno databáze
Typ dat řetězec maximální délky 31 znaků (32 s ukončujícím znakem ‘\0‘)
Typ databáze
32bitové číslo, často vyjadřované jako 4písmenná konstanta
Identifikace aplikace
132
Popis Každá databáze musí mít jiné jméno; toto jméno je použito při vyhledávání databází a při jejich zálohování do souborů. Vlastní identifikace databáze; později je možné procházet a vyhledávat databáze stejného typu. Jednoznačná identifikace aplikace, která databázi vytvořila a používá.
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Vlastnosti (attributes) databáze bitové pole Datum a čas vytvoření Datum a čas posledních úprav Datum poslední zálohy
32bitové číslo, ve kterém je časový údaj vyjádřen jako počet vteřin od 1.1.1904
Důležité vlastnosti databáze jsou popsány v následující tabulce Viz funkce data a času ve čtvrté kapitole.
Všechny tyto informace můžeme vyzvednout nebo nastavit později pomocí funkcí DmDatabaseInfo a DmSetDatabaseInfo. Celkový seznam vlastností databáze, které jsou uložené v hlavičce, by zabral několik stránek; nejdůležitější vlastnosti jsou následující: Vlastnost databáze zálohovaná
Bitová konstanta dmHdrAttrBackup
zabráněno kopírování
dmHdrAttrCopyPrevention
pouze pro čtení
dmHdrAttrReadOnly
Popis Pokud je tato vlastnost nastavena (příslušný bit má hodnotu 1) tak bude databáze při každé synchronizaci zálohována. Databáze s touto vlastností nemohou být kopírovány a vysílány infračerveným rozhraním (beaming). Do databáze není možné zapisovat, data je možné pouze číst.
Záznamy databáze nemají žádný pevný formát; data každého záznamu databáze jsou uložena ve svém vlastním přemístitelném bloku paměti. Tyto bloky můžeme uzamknout a číst data bez omezení; před ukončením aplikace nesmíme zapomenout zamčené bloky odemknout. Zapisovat data do záznamů databáze je však složitější.
Ochrana databází Návrháři operačního systému PalmOS kladli velký důraz na bezpečnost dat, uložených v databázích. Aby se zmenšilo riziko, že aplikace přepíše nedopatřením databázi, která patří jiné aplikaci, je paměť RAM, ve které jsou uloženy databáze chráněna hardwarovou pojistkou. Pokusí-li se aplikace zapisovat do části paměti RAM vyhrazené pro databáze bez odblokování hardwarové pojistky (například při přetečení zásobníku), je přerušen chod programu a na displeji zobrazena zpráva o systémové chybě. Jediná možnost pak je restartovat Palm Pilota; nicméně k přemazání některé databáze nedojde. Čtení dat z databází je jednoduché a není nijak omezeno. Pokud tedy chceme zapisovat do záznamů databáze, musíme používat funkce DmSet, DmWrite a DmStrCopy. Všem těmto funkcím předáváme adresu bloku paměti, který obsahuje data záznamu (a který je tedy umístěn v části paměti určené pro databáze) a index prvního zapisovaného byte v bloku (parametr offset). Funkce DmSet vyplní část bloku paměti konstantní hodnotou, DmWrite zkopíruje data do záznamu v databázi a DmStrCopy zkopíruje nulou ukončený řetězec. Výhodné je použití makra OffsetOf, které vrátí index prvního byte určeného prvku struktury. Pokud je každý záznam databáze definován takto:
133
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
typedef struct { UInt16 cislo; UInt32 velkecislo; Char text[40]; } ZaznamDatabaze;
Tak můžeme v naší aplikaci použít například následující příkazy (v příkladu jsou uvedeny i příkazy chybné, které vyvolají chybu): // vyzvedneme záznam z databáze pro zápis a uzamkneme jej v paměti MemHandle ovladac = DmGetRecord(databaze, cislozaznamu); ZaznamDatabaze* zaznam = MemHandleLock(ovladac); zaznam->cislo = 1; // chyba !!! StrCopy(zaznam->text, “pokus“); // chyba !!! // správné je: UInt16 novecislo = 1; DmWrite(zaznam, OffsetOf(ZaznamDatabaze, cislo), &novecislo, sizeof(UInt16); DmStrCopy(zaznam, OffsetOf(ZaznamDatabaze, text), “pokus“); // odemkneme blok paměti a uvolníme záznam databáze MemHandleUnlock(ovladac); DmReleaseRecord(databaze, cislozaznamu, true);
Vidíme, že použití záznamů databáze se od použití přemístitelných bloků paměti popsaných v kapitole 4 liší jen speciálními funkcemi, které musíme použít pro zápis.
Číslo vnitřní paměťové karty Už jsme zmínili, že původní koncept počítačů Palm Pilot obsahoval možnost použití vnitřních paměťových karet, jejichž obsah by se stal součástí paměti RAM nebo ROM (nejedná se o výměnné SD/MMC karty ani moduly Springboard). Vzhledem k tomuto uspořádání (které zatím nebylo využito) musí být hlavička databáze, záznamy i speciální bloky uloženy na stejné vnitřní paměťové kartě. Řada funkcí, které pracují s databázemi, bude proto požadovat číslo vnitřní karty, na které je databáze uložena; v našich programech můžeme bezpečně používat číslo karty 0 (nula). S původním plánovaným použitím vnitřních karet slouží i datový typ LocalID, který je určen k identifikaci přemístitelných bloků paměti patřících k databázi. Všechny bloky databáze musí být umístěny na stejné vnitřní kartě jako její hlavička. Při případné výměně nebo přemístění vnitřní paměťové karty se fyzická adresa bloku paměti změní, ale hodnota LocalID na příslušné vnitřní kartě zůstane stejná. Pokud označujeme blok paměti pomocí LocalID, musíme funkcím sdělit i číslo vnitřní karty, na které se blok nachází. Manažer paměti operačního systému PalmOS obsahuje řadu funkcí, které převádějí mezi různými metodami přístupu k paměti (ukazatel, ovladač a LocalID). Funkce MemHandleToLocalID převede ovladač přemístitelného bloku paměti na datový typ 134
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
LocalID; funkce MemLocalIDToLockedPtr zjistí z hodnoty LocalID adresu bloku paměti a tento blok paměti uzamkne. Pomocí typu LocalID můžeme odkazovat na databázi i na jednotlivé záznamy.
Chyby při práci s databázemi Většina funkcí, které pracují s databázemi vrací chybovou hodnotu Err; je-li vrácená hodnota nenulová, skončila funkce s chybou. U ostatních funkcí (například DmGetRecord) můžeme zjistit číslo chyby, ke které došlo, voláním funkce DmGetLastErr. Chceme-li zobrazit uživatelsky přívětivé hlášení o chybě, můžeme volat funkci SysErrString, například takto: Char text[40]; ... ErrDisplay(SysErrString(DmGetLastErr(), text, 40));
Vytvoření databáze K vytvoření databáze slouží funkce DmCreateDatabase. Při vytváření databáze je potřeba uvést několik parametrů (uvedeny v pořadí, ve kterém jsou předávány funkci DmCreateDatabase): • Číslo vnitřní karty, na které se databáze nachází; na místě tohoto parametru je bezpečné uvést číslo 0, protože zatím žádný model Palm Pilota nevyužívá více vnitřních paměťových karet. • Jméno databáze. Při vytváření jmen databáze je vhodné, aby na začátku jména byly čtyři znaky, udávající jednoznačnou identifikací aplikace, pomlčka a vlastní jméno (například „NECO-Jmeno databaze“. Tato konvence zajistí, že každá databáze bude mít jiné jméno. • Jednoznačnou identifikaci aplikace, která databázi vytváří. Pokud aplikaci smažeme, budou automaticky smazány i všechny databáze, které aplikace vytvořila. • Typ databáze (32bitová hodnota, vyjadřovaná jako 4písmenná konstanta), který může naše aplikace libovolně zvolit. • Logickou hodnotu, která definuje zda se jedná o databázi prostředků (true) nebo databázi záznamů (false). V našich programech budeme zatím používat pouze databáze záznamů. Vytvořenou databázi je před použitím potřeba otevřít, k čemuž slouží funkce uvedené v následující kapitole. #define ID_APLIKACE #define TYP_DATABAZE #define JMENO_DATABAZE
‘NECO‘ ‘data‘ “NECO-Seznam prvků“
if(DmCreateDatabase(0, JMENO_DATABAZE, ID_APLIKACE, TYP_DATABAZE, false) != 0) { ErrDisplay(“Nemohu vytvořit databázi“); }
135
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Otevření a zavření databáze K otevření databáze slouží dvě funkce: první z nich je funkce DmOpenDatabase, která otevře databázi na základě parametru LocalID. Poslední parametr funkce je způsob otevření databáze, pomocí kterého můžeme upřesnit zda je databáze otevřena jen pro čtení (dmModeReadOnly) nebo pro čtení i pro zápis (dmModeReadWrite), případně zda mají být zobrazeny i skryté záznamy (dmModeShowSecret). Hodnotu LocalID databáze, kterou chceme otevřít, můžeme například získat voláním funkce DmFindDatabase. Pro práci s otevřenou databází (čtení a zápis záznamů, třídění a podobně) slouží odkaz na databázi: datový typ DmOpenRef. Otevřenou databázi můžeme zavřít pomocí funkce DmCloseDatabase, které předáme odkaz na zavíranou databázi. Ve většině případů nepoužívá naše aplikace víc než jednu nebo dvě databáze, ve kterých ukládá svá data. K jednoduchému otevření databáze na základě jejího typu a jednoznačného identifikátoru aplikace, která ji vytvořila slouží funkce DmOpenDatabaseByTypeCreator. Nejběžnější případ použití této funkce je následující: DmOpenRef gDatabaze = NULL; DmOpenRef OtevriNeboVytvor(UInt32 typDatabaze, UInt32 idAplikace, Char* jmeno) { DmOpenRef db = NULL; db = DmOpenDatabaseByTypeCreator(typDatabaze, idAplikace, dmModeReadWrite); if(!db) { if(DmCreateDatabase(0, jmeno, idAplikace, typDatabaze, false) == 0) { db = DmOpenDatabaseByTypeCreator(typDatabaze, idAplikace, dmModeReadWrite); } } return db; } Err ZacatekProgramu() { gDatabaze = OtevriNeboVytvor(TYP_DATABAZE, ID_APLIKACE, JMENO_DATABAZE); if(!gDatabaze) return DmGetLastErr(); FrmGotoForm(HlavniFormular); return 0; } static void KonecProgramu() { FrmCloseAllForms(); DmCloseDatabase(gDb); }
Předchozí příklad zajistí, že v naší aplikaci bude přístupná otevřená databáze, kterou používáme pomocí odkazu na databázi gDatabaze. Při spuštění aplikace je databáze automaticky otevřena (jedná-li se o první spuštění aplikace tak i vytvořena) a před koncem aplikace databázi uzavřeme.
136
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Pokud potřebujeme procházet databáze postupně, můžeme využít funkce DmGetNextDatabaseByTypeCreator, která postupně vyhledává v paměti Palm Pilota databáze, které mají uvedenou jednoznačnou identifikaci aplikace, která je vytvořila a daný typ databáze.
Záznamy databáze Z hlediska uživatele je databáze uspořádaným souborem záznamů. Záznam databáze je blok paměti libovolné délky mezi 2 a 65000 byte, který je uložen na stejné paměťové kartě jako databáze. Záznamy jedné databáze nemusí mít stejnou délku. Každý záznam je určen svým pořadím v databázi (index); pořadí záznamu se však může měnit při vkládání záznamů jinam než na konec databáze. Proto operační systém PalmOS přiřazuje automaticky každému záznamu databáze unikátní 32bitové identifikační číslo, které se používá při synchronizaci se stolním počítačem. Hlavička databáze (jméno, typ, počet záznamů, vlastnosti atd.) Záznam 1 (vlastnosti, kategorie, unikátní číslo, odkaz na data)
Data záznamu 1
Záznam 2 (vlastnosti, kategorie, unikátní číslo, odkaz na data)
Data záznamu 2
Záznam 3 (vlastnosti, kategorie, unikátní číslo, odkaz na data)
Data záznamu 3
Databáze obsahuje jednak seznam záznamů a jednak jejich data. Pro každý záznam jsou v databázi uloženy jeho vlastnosti, číslo kategorie (0-15), do které záznam patří, identifikační číslo záznamu a odkaz na data v paměti (ve tvaru LocalID). Vlastnosti záznamů jsou uvedeny v následující tabulce (vlastnosti záznamů využívá zejména operační systém PalmOS a v této kapitole se jim nebudeme dále věnovat).
137
Úvod do programování PalmOS
Vlastnost dmRecAttrSecret
dmRecAttrDirty dmRecAttrDelete dmRecAttrBusy
MUDr. Petr Lesný, 2003
Význam Utajený záznam. Záznamy, které mají nastavenou tuto vlastnost „vidíme“ v databázi pouze tehdy, je-li otevřena s parametrem dmModeShowSecret. Záznam, který byl od poslední synchronizace změněn. Příznak záznamu, který byl na Palm Pilotovi smazán funkcí DmDeleteRecord. Při synchronizaci jsou záznamy s tímto příznakem vymazány z databáze. Záznam, se kterým nějaká aplikace pracuje a který můžeme jenom číst.
Pokud by nás zajímaly vlastnosti záznamu, jeho identifikační číslo a odkaz na jeho umístění v paměti, můžeme použít funkci operačního systému PalmOS DmRecordInfo. Podobně jako u vlastností databáze, můžeme vlastnosti záznamu nastavit funkcí DmSetRecordInfo. DmOpenRef gDatabaze; UInt16 vlastnosti; UInt16 identCislo; DmRecordInfo(gDatabaze, cisloZaznamu, &vlastnosti, &identCislo, NULL); UInt16 kategorie = vlastnosti & dmRecAttrCategoryMask; // 0-15 Boolean zmeneny = vlastnosti & DmRecAttrDirty;
K záznamům můžeme přistupovat jedním z následujících způsobů: 1. Na základě jejich pořadí v databázi. Toto je nejjednodušší způsob, který umožňuje přes funkce DmGetRecord a DmQueryRecord přímo přístup k datům záznamu. Celkový počet záznamů zjistíme voláním funkce DmNumRecords. 2. Na základě jejich 32bitového identifikačního čísla, které je unikátní pro každý záznam v databázi a nemění se při vkládání dalších záznamů do databáze. Funkce PalmOS DmFindRecordByID vrátí pořadí záznamu, jehož identifikační číslo jí předáme, v databázi. 3. Můžeme postupně procházet záznamy, které patří do jedné kategorie. K tomu slouží funkce DmQueryNextInCategory. Aby byla práce s kategoriemi co nejkomfortnější, obsahuje PalmOS řadu dalších funkcí, jako například DmNumRecordsInCategory.
Vytvoření nového záznamu K vytvoření nového záznamu databáze slouží funkce DmNewRecord. Tato funkce jako své parametry vyžaduje odkaz na otevřenou databázi, pozici na kterou bude nový záznam vložen a velikost záznamu. Po vytvoření je záznam „uzamčen“ abychom do něj mohli zapisovat (je nastaven příznak dmRecAttrBusy). Co nejdříve po ukončení zápisu do databáze musíme záznam „uvolnit“ funkcí DmReleaseRecord. UInt16 pozice = dmMaxRecordIndex; // vložit na konec MemHandle ovladac = DmNewRecord(gDatabaze, &pozice, sizeof(ZaznamDatabaze));
138
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// proměnná pozice nyní obsahuje skutečný index záznamu ... DmReleaseRecord(gDatabaze, pozice, true);
Funkce DmNewRecord zapíše do hlavičky databáze údaj o novém záznamu, vytvoří nové 32bitové unikátní identifikační číslo záznamu a vrátí přímo ovladač bloku paměti, ve kterém je uložen záznam. S blokem paměti, ve kterém je uložen záznam pracujeme způsobem, který už známe. Jediný rozdíl je, chceme-li do něj zapisovat. Funkce DmNewRecord vyžaduje jako parametr ukazatel na celočíselnou proměnnou, do které na počátku uložíme požadované číslo záznamu. Pokud funkci DmNewRecord předáme číslo existujícího záznamu databáze, bude nový záznam vložen před něj; je-li předaná hodnota dmMaxRecordIndex, bude nový záznam přidán na konec databáze. Po úspěšném volání funkce DmNewRecord je v této proměnné uloženo skutečné číslo přidaného záznamu. Paměť, ve které jsou uloženy databáze, je z důvodu zabezpečení dat chráněna proti neoprávněnému zápisu. Jediný způsob, jak je možné do této paměti zapisovat je pomocí funkcí DmWrite a DmStrCopy. Při jakémkoliv jiném pokusu o zápis do bloku paměti, který je součástí databáze, vyvoláme restart operačního systému.
Úsporné uložení záznamů Už jsme si uvedli, že záznam databáze je vlastně blok paměti libovolné délky, jehož obsahem mohou být libovolná data. V nejjednodušším případě mohou mít všechny záznamy databáze stejnou velikost a mohou být popsány jednoduchou strukturou: typedef struct { UInt16 typZaznamu; DateType datumNarozeni; Char jmeno[50]; Char prijmeni[50]; } ZaznamDatabaze; // Připravíme záznam ZaznamDatabaze Zaznam; Zaznam.typZaznamu = 0; StrCopy(Zaznam.jmeno, “Petr“); ... // Zapíšeme záznam do databáze UInt16 pozice = 0; MemHandle ovladac = DmNewRecord(gDatabaze, &pozice, sizeof(ZaznamDatabaze)); ZaznamDatabaze *Z = (ZaznamDatabaze *)MemHandleLock(ovladac); DmWrite(Z, 0, &Zaznam, sizeof(ZaznamDatabaze)); MemHandleUnlock(ovladac); DmReleaseRecord(gDatabaze, pozice, true);
Tento způsob uložení záznamů však (zejména pro uložení textu) není příliš úsporný. Proto se využívá toho, že záznamy databáze mohou mít různou délku, a texty se připojují na konec
139
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
záznamu. Hlavička záznamu obsahuje data s pevnou délkou, za ní jsou uložena jednotlivá řetězcová pole. Hlavička
Oblast pro řetězce ‘\0‘ ‘Příjmení‘ ‘\0‘
UInt16 typZaznamu; ‘Jméno‘ DateType datumNarozeni;
Tento způsob uložení záznamů je maximálně úsporný a používají jej všechny vestavěné aplikace v PalmOS. Záznam často používáme ve dvou tvarech: „rozbalený záznam“, který obsahuje řetězcová pole s pevnou délkou, a „sbalený záznam“, který je určen k uložení v úsporném tvaru. Příklad uložení záznamu v aplikaci ve „sbaleném tvaru“ je: typedef struct { UInt16 typZaznamu; DateType datumNarozeni; } HlavickaZaznamu; typedef struct { HlavickaZaznamu hlavicka; Char jmeno[50]; Char prijmeni[50]; } RozbalenyZaznamDatabaze; // Připravíme záznam RozbalenyZaznamDatabaze Zaznam; Zaznam.hlavicka.typZaznamu = 0; StrCopy(Zaznam.jmeno, “Petr“); // Zapíšeme záznam do databáze UInt16 pozice = 0; UInt16 delka = sizeof(HlavickaZaznamu) + StrLen(Zaznam.jmeno) + 1 + StrLen(Zaznam.prijmeni) + 1; MemHandle ovladac = DmNewRecord(gDatabaze, &pozice, delka); HlavickaZaznamu *H = (HlavickaZaznamu *)MemHandleLock(ovladac); // Zapíšeme hlavičku DmWrite(H, 0, &Zaznam, sizeof(HlavickaZaznamu)); // Zapíšeme oba řetězce za hlavičku DmStrCopy(H, sizeof(HlavickaZaznamu), Zaznam.jmeno); DmStrCopy(H, sizeof(HlavickaZaznamu) + StrLen(Zaznam.jmeno) + 1, Zaznam.prijmeni); MemHandleUnlock(ovladac);
DmReleaseRecord(gDatabaze, pozice, true);
Dekódování záznamu z úsporné podoby do rozbaleného tvaru naprogramujeme obdobně. Všude jinde v našem programu, kde budeme pracovat s daty záznamu, budeme používat rozbalený tvar záznamu; před uložením do databáze jej sbalíme a ve vlastní funkci pro vyzvednutí záznamu jej rozbalíme.
140
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Čtení a zapisování do záznamů databáze Pomocí funkce DmGetRecord získáme ovladač bloku paměti, ve kterém je záznam databáze uložen. Od okamžiku volání funkce DmGetRecord je záznam „uzamčen“: můžeme jej číst nebo zapisovat do něj jenom v naší aplikaci. Jakmile práci se záznamem skončíme, „odemkneme“ jej voláním funkce DmReleaseRecord. MemHandle ovladac = DmGetRecord(gDatabaze, cislo); // Tady standardně pracujeme s ovladačem bloku paměti; k záznamu databáze nemá // přístup žádná jiná aplikace if(ovladac) { MojeData* data = MemHandleLock(ovladac); // ... MemHandleUnlock(ovladac); }
DmReleaseRecord(gDatabaze, pozice, true);
Pokud voláme funkci DmGetRecord s číslem neexistujícího záznamu, nebo pokud je záznam uzamčen jinou aplikací, může tato funkce vrátit hodnotu NULL. Vrátí-li funkce ovladač bloku paměti, můžeme s ním pracovat jako s kterýmkoliv jiným blokem paměti. Jediný rozdíl je v tom, že data nemůžete zapisovat přímo: k zápisu do tohoto bloku paměti musíte použít funkce DmWrite nebo DmStrCopy. Pokud si přejete data záznamu jenom číst, můžete použít také funkci DmQueryRecord. Tato funkce také vrací ovladač bloku paměti, ve kterém se nachází data záznamu; záznam však „neuzamkne“. Data z bloku paměti je možné pouze číst; takto však může k jednomu bloku paměti přistupovat víc aplikací najednou. Samozřejmě není nutné po skončení práce se záznamem volat funkci DmReleaseRecord. MemHandle ovladac = DmQueryRecord(gDatabaze, cislo); // Tady standardně pracujeme s ovladačem bloku paměti if(ovladac) { MojeData* data = MemHandleLock(ovladac); // ... MemHandleUnlock(ovladac); }
Smazání záznamu a databáze K mazání záznamů slouží v PalmOS dvě funkce: DmRemoveRecord a DmDeleteRecord. Funkce DmRemoveRecord úplně odstraní z databáze záznam, jehož index jí předáme. Oproti tomu funkce DmDeleteRecord smaže pouze data záznamu. Odkaz na záznam v databázi zůstane; operační systém jej však zařadí jako poslední záznam a nastaví u něj vlastnost dmRecAttrDelete. Představíme si databázi s pěti záznamy (A až E), jako na následujícím obrázku: 141
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Hlavička databáze
DmDeleteRecord [0]
Záznam A
Data záznamu A
[1]
Záznam B
Data záznamu B
[2]
Záznam C
Data záznamu C
[3]
Záznam D
Data záznamu D
[4]
Záznam E
Data záznamu E
Po smazání druhého záznamu v pořadí (záznam B) funkcí DmDeleteRecord bude databáze vypadat takto: Hlavička databáze [0]
Záznam A
Data záznamu A
[1]
Záznam C
Data záznamu C
[2]
Záznam D
Data záznamu D
[3]
Záznam E
Data záznamu E
[4]
Záznam B; má však vlastnost
dmRecAttrDelete
Při následující synchronizaci je informace o smazaných záznamech využita k odstranění příslušných záznamů i v databázi na stolním počítači, se kterou synchronizujeme data. Teprve poté jsou záznamy, které jsme smazali funkcí DmDeleteRecord úplně odstraněny. Chceme-li smazat všechny záznamy databáze, musíme je buď mazat od konce, nebo opakovaně mazat záznam na začátku databáze (na pozici 0). Po každém vymazání záznamu se totiž změní počet záznamů databáze i jejich čísla. pocet = DmNumRecords(gDatabaze); for(i = pocet - 1; i >= 0; i--) { DmRemoveRecord(gDatabaze, i); }
142
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Seřazení databáze Operační systém PalmOS obsahuje jednoduchý způsob, jak setřídit záznamy databáze. K setřídění můžeme použít buď funkci DmInsertionSort nebo DmQuickSort. První z těchto funkcí je vhodné použít, je-li databáze částečně setříděna; druhá z nich je určena spíše pro setřídění databází, které nebyly uspořádány. Protože však PalmOS neví, jaký je obsah našich záznamů, musíme v naší aplikaci definovat vlastní funkci pro porovnání dvou záznamů databáze. Adresu této funkce pak předáme funkci pro třídění. Funkce pro porovnání záznamů musí vrátit hodnotu –1, 1 nebo 0 podle toho, zda je větší první záznam, druhý záznam nebo jsou-li oba záznamy stejné (podobně jako funkce StrCompare). Porovnávací funkce může být definována následujícím způsobem: typedef struct { Int32 pocet; Char text[1]; } ZaznamSbaleny; Int16 PorovnejZaznamy(void *rec1, void *rec2, Int16 other, SortRecordInfoPtr rec1SortInfo, SortRecordInfoPtr rec2SortInfo, MemHandle appInfoH) { ZaznamSbaleny* z1 = (ZaznamSbaleny*)rec1; ZaznamSbaleny* z2 = (ZaznamSbaleny*)rec2;
}
if(other == TRIDENI_JMENO) { return StrCompare(z1->text, z2->text); } else { if(z1->pocet < z2->pocet) { return -1; } else if(z1->pocet > z2->pocet) { return 1; } else { return 0; } }
První dva parametry (rec1 a rec2) obsahují ukazatel na data záznamů; třetí parametr (other) obsahuje uživatelem definovanou konstantu, kterou jsme předali jako parametr funkci DmQuickSort nebo DmInsertionSort.
143
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
// Volání funkce pro třídění DmQuickSort(gDatabaze, PorovnejZaznamy, TRIDENI_JMENO);
Vkládání záznamů do databáze Porovnávací funkci, kterou jsme definovali v předchozí podkapitole, můžeme také využít k nalezení vhodného místa pro vložení záznamu do databáze. Program, který využívá setříděnou databázi najdete v příkladu 3. K nalezení vhodné pozice záznamu v databázi nám slouží funkce DmFindSortPosition, které předáme ukazatel na data nového záznamu a adresu porovnávací funkce. Funkce DmFindSortPosition vrátí pozici, na kterou je třeba záznam do databáze vložit. Blok paměti, obsahující data záznamu v takovém případě nevytváříme funkcí DmNewRecord, ale funkcí DmNewHandle. Touto funkcí vytvoříte blok paměti, který je umístěn na stejné paměťové kartě jako databáze; do tohoto bloku zkopírujete data záznamu a do databáze jej začleníte funkcí DmAttachRecord. // Vytvoříme blok paměti, který může být vložen do databáze velikost = sizeof(ZaznamSbaleny) + StrLen(R.text); ovladac = DmNewHandle(gDatabaze, velikost); if(ovladac) { // Zkopírujeme data do záznamu ZaznamSbaleny* Z = MemHandleLock(ovladac); DmWrite(Z, 0, &R, velikost); // Nalezení vhodné pozice k zatřídění pozice = DmFindSortPosition(gDatabaze, Z, NULL, PorovnejZaznamy, typTrideni); MemHandleUnlock(ovladac); // Vložení záznamu do databáze na pozici pozice
}
if(DmAttachRecord(gDatabaze, &pozice, ovladac, NULL) != errNone) { MemHandleFree(ovladac); }
Pokud funkce DmAttachRecord vrátí kód chyby, musíme sami zrušit blok paměti, který jsme vytvořili voláním funkce DmNewHandle. Tento blok paměti není součástí žádné databáze a aplikace by k němu neměly přístup; nemohly by jej dokonce ani zrušit.
Propojení databáze s tabulkou Mnoho vestavěných aplikací na počítačích Palm Pilot využívá jednoduchou databázi, která využívá tabulku pro zobrazení dat. Propojení tabulky s databází je snadné. Nejprve musíme ve funkci, která aktualizuje tabulku, každému řádku přiřadit odpovídající číslo záznamu tabulky
144
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
funkcí TblSetRowID. Hodnoty políček k zaškrtnutí DmQueryRecord a nastavujeme v této funkci.
a
seznamů
zjistíme
voláním
void NaplnTabulku(TablePtr tabulka, ScrollBarPtr posuvnik) { UInt16 pocetRadku = TblGetNumberOfRows(tabulka); UInt16 pocetPrvku = DmNumRecords(gDatabaze); UInt16 zaznam, posledniHorni, r; MemHandle ovladac; ... for(r = 0; r < pocetRadku; r++) { zaznam = gPrvniPrvek + r; if(zaznam >= 0 && zaznam < pocetPrvku) { TblSetRowID(tabulka, r, zaznam); ovladac = DmQueryRecord(gDatabaze, zaznam); if(ovladac) { zaznam = (ZaznamDatabaze*)MemHandleLock(ovladac); TblSetItemInt(tabulka, r, 0, zaznam->vybran); MemHandleUnlock(ovladac); } TblSetRowUsable(tabulka, r, true); } else { TblSetRowUsable(tabulka, r, false); }
}
} ...
TblMarkRowInvalid(tabulka, r);
Hodnoty políček k zaškrtnutí a seznamů ukládáme do databáze hned po jejich volbě při zpracování události tblSelectEvent. Při práci s políčky pro vstup textu využijeme možnosti editovat záznamy databáze na místě. Definujeme si funkci pro vyzvednutí textu do políčka (TblSetLoadDataProcedure) i pro uložení textu do databáze (TblSetSaveDataProcedure). Ve funkci, která vyzvedává text z databáze do políčka zajistíme ovladač záznamu: pokud bude správce tabulek záznam měnit, použijeme funkci DmGetRecord; pokud má být záznam pouze zobrazen, použijeme DmQueryRecord. Na závěr funkce předáme správci tabulek ovladač záznamu, počátek textu v záznamu a délku textu.
145
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err VyzvedniText1(void *tabulka, Int16 radek, Int16 sloupec, Boolean editovat, MemHandle *data, Int16 *dataOffset, Int16 *dataVelikost, FieldPtr policko) { UInt16 zaznam = TblGetRowID((TablePtr)tabulka, radek); if(editovat) { *data = DmGetRecord(gDatabaze, zaznam); } else { *data = DmQueryRecord(gDatabaze, zaznam); } *dataOffset = OffsetOf(ZaznamDatabaze, text); *dataVelikost = MemHandleSize(*data) - sizeof(ZaznamDatabaze); }
return 0;
Funkce pro uložení textu do databáze je volána vždy, když uživatel ukončí změnu textu v políčku. Musíme zde odemknout záznam, který jsme uzamkli funkcí DmGetRecord ve funkci pro vyzvednutí textu z databáze. Boolean UlozText1(void *tabulka, Int16 radek, Int16 sloupec) { UInt16 pozice = TblGetRowID((TablePtr)tabulka, radek); DmReleaseRecord(gDatabaze, pozice, true); TblMarkTableInvalid(tabulka); }
return true;
Kompletní příklad tabulky propojené s databází si můžete prostudovat v příkladu 2. V následující tabulce uvedeme seznam bodů, které bylo při sestavování příkladu 2 nutno vyřešit:
146
Úvod do programování PalmOS
Kde začátek programu konec programu aktualizace dat tabulky
zpracování události tblSelectEvent vytvoření nového záznamu funkce pro vyzvednutí textu z databáze funkce pro uložení textu do databáze
MUDr. Petr Lesný, 2003
Co • • • • • • • •
•
vytvoření nebo otevření databáze uzavření databáze každému řádku musíme přiřadit číslo záznamu nastavíme stav logických ovládacích prvků (políček k zaškrtnutí a seznamů) zapíšeme do databáze změněnou hodnotu logických ovládacích prvků (políček k zaškrtnutí a seznamů) přidáme do tabulky prázdný záznam nastavíme kursor na políčko tabulky (viz příklad 2) vrátíme správci tabulek ovladač příslušného záznamu databáze (voláním DmQueryRecord nebo DmGetRecord podle hodnoty parametru editovat) „uvolnění“ záznamu pomocí DmReleaseRecord
147
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Závěr Cílem této publikace je poskytnout čtenářům úvodní informace o programování operačního systému PalmOS, které pak mohou sami studiem literatury rozvíjet a obohacovat. Operační systém PalmOS se neustále vyvíjí, je doplňován o další a další vlastnosti; přesto jsem přesvědčen že kniha, která popisuje úplné základy jeho programování, platné pro všechny verze operačního systému, má své místo. Jsem si vědom, že jsem v knize popsal pouze úplné základy; bude-li to možné, bude její druhé vydání (nebo druhý díl) obsahovat nejen popis synchronizace, ale i další témata, kterým jsem se v této knize vyhýbal. Laskavé čtenáře, kteří již nyní touží po rozšiřování svých znalostí o PalmOS odkazuji na originální velmi kvalitní dokumentaci, kterou obsahoval PalmOS SDK. Dalším vhodným zdrojem je internet; zadáte-li klíčové slovo PalmOS do vyhledávače, odhalíte jak mnoho stránek, věnovaných programování počítačů Palm Pilot a kompatibilních, tak tisíce aplikací, jejichž zdrojový kód je dostupný a ze kterých se lze mnoho přiučit.
148
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Příloha A: Instalace nástrojů pro vývoj Vývojové prostředí Cygwin a balík prc-tools Pro vývoj vašich vlastních aplikací na stolním počítači pod operačním systémem Microsoft Windows budete potřebovat vývojové prostředí Cygwin od společností Cygnus Solutions (http://www.cygwin.com). Toto vývojové prostředí je možné instalovat přímo z internetu; při minimální velikosti instalace musíte stáhnout zhruba 18MB dat. Otevřete stranu http://www.cygwin.com a klikněte na ikonku instalace:
Spusťte instalační program a nastavte adresář C:\cygwin jako základní adresář pro instalaci, podobně jako na následujícím obrázku:
149
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Poté zvolte nějaký vhodný dočasný adresář pro instalaci (například C:\temp\cygwin). Do tohoto adresáře budou kopírována instalační data z internetu.
150
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Na další obrazovce nastavte parametry připojení – pro většinu domácích počítačů vyhovuje buď první volba (přímé připojení na internet) nebo druhá (použij nastavení Microsoft Internet Exploreru). Po přesunu na další obrazovku napište do okénka označeného šipkou text
http://prc-tools.sourceforge.net/install a stiskněte tlačítko Add (přidej). Tím přidáte do seznamu adres, ze kterých můžete stahovat instalační balíčky i adresu, na které se nachází vývojové prostředí prc-tools.
V seznamu míst pro stahování označte internetové adresy, ze kterých budete stahovat instalační balíčky. Při označování musíte držet stisknuté tlačítko Control, aby se vybralo více adres. Adresa http://prc-tools.sourceforge.net/install, kterou jsme přidali v předchozím kroku musí být jednou z vybraných. Jedna z vybraných adres může být i na některém serveru v ČR. Instalační program stáhne z vybraných adres seznamy balíčků a nyní bude na vás, abyste označili ty správné součásti vývojového prostředí, které si přejete instalovat. Automaticky jsou vybrány součásti pro minimální instalaci. My musíme sami zaškrtnout pouze balíčky make, prctools a pilrc ve skupině Devel.
151
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Poté začne instalační program stahovat balíčky z internetu a instalovat je. Pokud se některé balíčky nepodaří stáhnout, musíte v seznamu adres pro stahování vybrat jiná místa.
152
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Po skončení instalace nabídne instalační program možnost umístění ikony na desktop a skončí. Není třeba restartovat počítač a můžete přejít k druhému kroku instalace: stažení SDK (Software Development Kit) pro PalmOS 5.0 ze stránek společnosti Palm, Inc.
PalmOS SDK Přejděte na stránku http://www.palmos.com/cgi-bin/sdk50.cgi a úplně dole stiskněte tlačítko s nápisem I Agree. Tím se dostanete na stránku, ze které můžete stáhnout jednotlivé součásti SDK pro PalmOS. Potřebujete dva soubory, které jsou na obrázku označené šipkou:
Ten větší z nich obsahuje hlavičkové soubory, manuály, PalmOS Simulátor, Debugger a další užitečné utility; druhý z nich doplňuje knihovny, které jsou potřeba pro správný překlad aplikací. Po stažení souboru Palm_OS_5_SDK_68K_R2.exe spusťte automatickou instalaci a instalujte data do standardního adresáře C:\Palm OS 5 SDK (68K) R2.
153
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Dokončení instalace 1. V adresáři C:\cygwin vytvořte podadresář jménem PalmDev. Jméno tohoto adresáře bude tedy c:\cygwin\PalmDev. 2. V adresáři c:\cygwin\PalmDev vytvořte podadresář jménem sdk-5 a v něm další podadresáře jménem include a lib.
3. Zkopírujte celý obsah adresáře C:\Palm OS 5 SDK (68K) R2\Palm OS Support\Incs do adresáře C:\cygwin\PalmDev\sdk-5\include. 4. Zkontrolujte, zda existuje soubor C:\cygwin\PalmDev\sdk-5\include\PalmOS.h
154
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
5. Zkopírujte dokumentaci PalmOS (podadresář Palm Documentation) a simulátor (podadresář Palm Tools\Palm OS Simulator) do adresáře C:\cygwin\PalmDev nebo kamkoliv jinam, kde k nim budete mít dobrý přístup. 6. Můžete umístit na plochu nebo do hlavní nabídky zkratky (shortcuts) k dokumentaci PalmOS a k simulátoru, aby byly po ruce. 7. Zkopírujte ze souboru palmos-sdk-5.0-1.zip celý podadresář m68k-palmos-coff do adresáře C:\cygwin\PalmDev\sdk-5\lib. 8. Zkontrolujte, zda existuje soubor C:\cygwin\PalmDev\sdk-5\lib\m68k-palmos-coff\libPalmOSGlue.a
9. Můžete smazat adresář C:\Palm OS 5 SDK (68K) R2. 10. Doplňte na konec souboru AUTOEXEC.BAT následující řádek:
PATH=%PATH%;C:\cygwin\bin 11. Restartujte počítač a spusťte soubor CYGWIN.BAT, který se nachází v adresáři C:\cygwin:
155
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
12. V okně, které se objeví po kliknutí na ikonu zadejte příkaz palmdev-prep, kterým nastavíte použití SDK pro PalmOS 5.0
156
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
13. Zkontrolujte, zda je možné spustit programy make, pilrc a m68k-palmos-gcc.
Při instalaci se může mnoho věcí pokazit; jejich seznam přesahuje rozsah této přílohy. Pokud se vám něco nepodaří, zkuste zopakovat postup instalace a zkontrolovat: • Připojení k internetu. • Zda máte právo zapisovat do příslušných adresářů (Windows 2000 a NT). • Zda je správně uveden adresář v AUTOEXEC.BAT. Pokud vše dopadlo správně, můžete používat freeware vývojové prostředí pro PalmOS, o kterém budeme psát v této knize. Hodně štěstí.
157
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Příloha B: Vybrané funkce PalmOS V této příloze je seznam funkcí, o kterých jsme v knize psali; u každé jsou uvedeny kapitoly, ve kterých byla funkce nějak významně použita, první verze operačního systému, ve kterém je možné ji použít (pokud není uvedena, vyskytuje se funkce ve všech verzích PalmOS) a stručný popis parametrů a vrácených hodnot. Pro úplný a podrobnější seznam funkcí si prostudujte originální dokumentaci PalmOS. Funkce jsou v přibližném abecedním pořadí (toto pořadí se docela dobře kryje s funkčními skupinami); pokud jsou některé z nich příbuzné, jsou uvedeny blíže k sobě než nepříbuzné funkce.
Funkce pro práci s tlačítky Int16 CtlGetValue (const ControlType *tlacitko) Vrátí hodnotu (zapnuto/vypnuto) tlačítka nebo políčka k zaškrtnutí. Parametry • tlacitko – ukazatel na datovou strukturu tlačítka Vrácená hodnota • 1 – zaškrtnuto nebo vybráno • 0 – nezaškrtnuto nebo nevybráno
Kap. 6
void CtlSetValue (ControlType *tlacitko, Int16 hodnota) Nastaví hodnotu (zapnuto/vypnuto) tlačítka nebo políčka k zaškrtnutí Kap. 6 Parametry • tlacitko – ukazatel na datovou strukturu tlačítka • hodnota – nový stav (1 zapnuto, 0 vypnuto) přepínače nebo políčka k zaškrtnutí void CtlHideControl (ControlType *tlacitko) Vymaže tlačítko z displeje. Parametry • tlacitko – ukazatel na datovou strukturu tlačítka
Kap. 6
void CtlShowControl (ControlType *tlacitko) Vykreslí tlačítko na displeji. Parametry • tlacitko – ukazatel na datovou strukturu tlačítka
Kap. 6
void CtlSetLabel (ControlType *tlacitko, const Char *text) Nastaví nový text tlačítka, přepínače nebo políčka k zaškrtnutí. Kap. 6 Parametry • tlacitko – ukazatel na datovou strukturu tlačítka • text – adresa globální proměnné, ve které je nový text tlačítka uložen
Funkce data void DateSecondsToDate (UInt32 seconds, DateType *datum) Převede čas vyjádřený jako počet vteřin od 1.1:1904 na strukturu DateType: Kap. 4 typedef struct{ UInt16 year :7; UInt16 month :4; UInt16 day :5; } DateType; Parametry • seconds – počet vteřin od 1.1:1904 • datum – ukazatel na strukturu DateType, do které bude uložen výsledek
158
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void DateToAscii (UInt8 mesice, UInt8 dny, UInt16 roky, DateFormatType format, Char *text) Převede datum na čas. Kap. 4 Parametry • mesice, dny, roky – datum • format – formát data ( • text – adresa proměnné, do které bude uložen výsledný text typedef enum { dfMDYWithSlashes, dfDMYWithSlashes, dfDMYWithDots, dfDMYWithDashes, dfYMDWithSlashes, dfYMDWithDots, dfYMDWithDashes, dfMDYLongWithComma, dfDMYLong, dfDMYLongWithDot, dfDMYLongNoDay, dfDMYLongWithComma, dfYMDLongWithDot, dfYMDLongWithSpace, dfMYMed, dfMYMedNoPost, dfMDYWithDashes } DateFormatType; UInt16 DateToInt (DateTime datum) Kap. 4 Makro, které převede typ DateTime na celé číslo bez znaménka. Parametry • datum – datum ve formátu DateTime Vrácená hodnota • celočíselná 16bitová hodnota, která datu odpovídá
Databázové funkce Err DmAttachRecord (DmOpenRef databaze, UInt16 *kam, MemHandle novy, MemHandle *stary) Zařadí záznam, jehož ovladač funkci předáváme, na určenou pozici databáze. Kap. 9 Parametry • databaze - ovladač otevřené databáze • kam – ukazatel na proměnnou, ve které je číslo záznamu • novy – ovladač bloku databáze, vytvořeného pomocí DmNewHandle. • stary – pokud má tento parametr hodnotu NULL, je záznam do databáze vložen. Pokud tento parametr obsahuje ukazatel na proměnnou, je záznam na určené pozici databáze nahrazen a v této proměnné je po návratu ovladač původního záznamu. Vrácená hodnota • číslo chyby nebo noError Err DmCloseDatabase (DmOpenRef databaze) Zavře otevřenou databázi. Parametry • databaze - ovladač otevřené databáze Vrácená hodnota • číslo chyby nebo noError
159
Kap. 9
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmCreateDatabase (UInt16 karta, const Char *jmeno, UInt32 idTvurce, UInt32 typ, Boolean resource) Vytvoří novou databázi. Kap. 9 Parametry • karta – číslo paměťové karty (obvykle 0), na které je databáze vytvořena • jmeno – jméno nové databáze • idTvurce – jednoznačná identifikace aplikace, která databázi vytváří • typ – typ databáze • resource – má-li parametr hodnotu true, jedná se o databázi prostředků Vrácená hodnota • číslo chyby nebo noError Err DmDatabaseInfo (UInt16 karta, LocalID dbID, Char *jmeno, UInt16 *vlastnosti, UInt16 *verze, UInt32 *datumVytvoreni, UInt32 *datumUpravy, UInt32 *datumZalohy, UInt32 *cisloUpravy, LocalID *appInfoIDP, LocalID *sortInfoIDP, UInt32 *typ, UInt32 *tvurce) Zjistí informace z hlavičky databáze. Kap. 9 Parametry • karta – číslo paměťové karty (obvykle 0), na které je databáze vytvořena • dbID – hodnota LocalID, která označuje databázi • jmeno – proměnná, do které bude uloženo jméno databáze. Pokud nepotřebujete, předejte hodnotu NULL. • vlastnosti – proměnná, do které budou uloženy vlastnosti databáze. Pokud nepotřebujete, předejte hodnotu NULL. • verze – proměnná, do které bude uložena verze databáze. Pokud nepotřebujete, předejte hodnotu NULL. • datumVytvoreni – proměnná, do které bude uloženo datum a čas vytvoření databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nepotřebujete, předejte hodnotu NULL. • datumUpravy – proměnná, do které bude uloženo datum a čas poslední změny databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nepotřebujete, předejte hodnotu NULL. • datumZalohy – proměnná, do které bude uloženo datum a čas poslední zálohy databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nepotřebujete, předejte hodnotu NULL. • cisloUpravy – proměnná, do které bude uloženo pořadové číslo změny databáze od poslední synchronizace. Pokud nepotřebujete, předejte hodnotu NULL. • appInfoIDP – proměnná, do které bude uložena hodnota LocalID bloku uživatelských informací o databázi (appInfo). Pokud nepotřebujete, předejte hodnotu NULL. • sortInfoIDP – proměnná, do které budou uložena hodnota LocalID bloku informací o třídění databáze (sortInfo). Pokud nepotřebujete, předejte hodnotu NULL. • typ – proměnná, do které bude uložen typ databáze. Pokud nepotřebujete, předejte hodnotu NULL. • tvurce - proměnná, do které bude uložena jednoznačná identifikace aplikace, která databázi vytvořila. Pokud nepotřebujete, předejte hodnotu NULL. Vrácená hodnota • číslo chyby nebo noError
160
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmDeleteRecord (DmOpenRef databaze, UInt16 index) Vymaže data, která patří k záznamu databáze, ale ponechá v hlavičce informaci Kap. 9 o smazaném záznamu pro účely synchronizace. Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu Vrácená hodnota • číslo chyby nebo noError Err DmRemoveRecord (DmOpenRef databaze, UInt16 index) Kap. 9 Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu Vrácená hodnota • číslo chyby nebo noError LocalID DmFindDatabase (UInt16 karta, const Char *jmeno) Vyhledá na kartě databázi s odpovídajícím jménem. Kap. 9 Parametry • karta – číslo paměťové karty • jmeno – jméno databáze Vrácená hodnota • hodnota LocalID, která odpovídá databázi Err DmFindRecordByID (DmOpenRef databaze, UInt32 id, UInt16 *index) Najde záznam databáze, který má určitý jednoznačný identifikátor. Kap. 9 Parametry • databaze – ovladač otevřené databáze • id – identifikátor záznamu • index – proměnná, do které bude uloženo číslo záznamu Vrácená hodnota • vrací noError, pokud byl záznam nalezen, jinak číslo chyby UInt16 DmFindSortPosition (DmOpenRef databaze, void *novyZaznam, SortRecordInfoPtr noveInfo, DmComparF *porovnej, Int16 vlastni) Najde pořadí v databázi, na které by měl být záznam vložen. Kap. 9 PalmOS 2.0 Parametry • databaze – ovladač otevřené databáze • novyZaznam – ukazatel na data nového záznamu • noveInfo – informace o zatřídění záznamu nebo NULL • porovnej – funkce pro porovnání záznamů typu DmComparF • vlastni – uživatelem definovaná hodnota, která bude předávána funkci pro porovnání záznamů
Vrácená hodnota
typedef Int16 DmComparF(void *rec1, void *rec2, Int16 vlastni, SortRecordInfoPtr rec1SortInfo, SortRecordInfoPtr rec2SortInfo, MemHandle appInfo) • pořadí v databázi, na které by měl být záznam vložen
Err DmGetLastErr (void) Vrátí číslo poslední chyby, ke které došlo při práci s databázemi. Vrácená hodnota • číslo chyby
161
Kap. 9
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmGetNextDatabaseByTypeCreator (Boolean novy, DmSearchStatePtr stavoveInfo, UInt32 typ, UInt32 idTvurce, Boolean jenNove, UInt16 *karta, LocalID *databaze) Slouží k prohledávání všech databází určité aplikace, které mají daný typ. Kap. 9 Parametry • novy – true, pokud začínáte nové hledání • stavoveInfo – ukazatel na datovou strukturu DmSearchState, do které funkce ukládá informace pro opakované volání • typ – typ databáze, který hledáme nebo 0L pro všechny typy • idTvurce – jednoznačná identifikace aplikace, která databázi vytvořila nebo 0L pro všechny aplikace • jenNove – pokud má hodnotu true, vrátí nejnovější databázi z hledaných • karta – do této proměnné bude uloženo číslo paměťové karty, na které je nalezená databáze • databaze – do této proměnné bude uložena hodnota LocalID nalezené databáze Vrácená hodnota • číslo chyby nebo noError MemHandle DmGetRecord (DmOpenRef databaze, UInt16 index) Vrátí ovladač bloku paměti, ve kterém jsou data příslušného záznamu a Kap. 9 uzamkne záznam tak, aby k němu nemohly přistupovat jiné aplikace. Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu Vrácená hodnota • ovladač bloku paměti nebo NULL došlo-li k chybě MemHandle DmGetResource (DmResType typ, DmResID id) Vrátí ovladač bloku paměti, ve kterém je daný zdrojový prostředek a uzamkne Kap. 8 blok tak, aby k němu nemohly přistupovat jiné aplikace. Parametry • typ – typ prostředku (například strRsc, strListRscType, bitmapRsc nebo fontRscType) • id – číslo prostředku tak jak je uvedeno v souboru prostředků aplikace Vrácená hodnota • ovladač bloku paměti nebo NULL došlo-li k chybě Err DmInsertionSort (DmOpenRef databaze, DmComparF *porovnani, Int16 vlastni) Setřídí databázi. Optimální pro částečně setříděné databáze. Kap. 9 Parametry • databaze - ovladač otevřené databáze • porovnani – funkce pro porovnání záznamů typu DmComparF • vlastni – uživatelem definovaná hodnota, která bude předávána funkci pro porovnání záznamů
Vrácená hodnota
typedef Int16 DmComparF(void *rec1, void *rec2, Int16 vlastni, SortRecordInfoPtr rec1SortInfo, SortRecordInfoPtr rec2SortInfo, MemHandle appInfo) • číslo chyby nebo noError
162
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmQuickSort (DmOpenRef databaze, DmComparF *porovnani, Int16 vlastni) Setřídí databázi metodou QuickSort. Optimální pro nijak nesetříděné databáze. Kap. 9 Parametry • databaze - ovladač otevřené databáze • porovnani – funkce pro porovnání záznamů typu DmComparF • vlastni – uživatelem definovaná hodnota, která bude předávána funkci pro porovnání záznamů
Vrácená hodnota
typedef Int16 DmComparF(void *rec1, void *rec2, Int16 vlastni, SortRecordInfoPtr rec1SortInfo, SortRecordInfoPtr rec2SortInfo, MemHandle appInfo) • číslo chyby nebo noError
MemHandle DmNewHandle (DmOpenRef databaze, UInt32 velikost) Vytvoří blok paměti, který bude možné vložit do příslušné databáze funkcí Kap. 9 DmAttachRecord Parametry • databaze - ovladač otevřené databáze • velikost – velikost požadovaného bloku paměti v byte Vrácená hodnota • ovladač bloku paměti nebo NULL v případě chyby MemHandle DmNewRecord (DmOpenRef databaze, UInt16* pozice, UInt32 velikost) Vloží do databáze nový záznam a uzamkne záznam tak, aby k němu nemohly Kap. 9 přistupovat jiné aplikace. Parametry • databaze - ovladač otevřené databáze • pozice – proměnná, do které bude uloženo pořadové číslo (index) záznamu • velikost – velikost požadovaného bloku paměti v byte Vrácená hodnota • ovladač bloku paměti nebo NULL v případě chyby UInt16 DmNumRecords (DmOpenRef databaze) Zjistí počet záznamů databáze. Parametry • databaze - ovladač otevřené databáze Vrácená hodnota • počet záznamů
Kap. 9
UInt16 DmNumRecordsInCategory (DmOpenRef databaze, UInt16 category) Zjistí počet záznamů databáze, které spadají do dané kategorie. Kap. 9 Parametry • databaze - ovladač otevřené databáze • category – číslo kategorie Vrácená hodnota • počet záznamů DmOpenRef DmOpenDatabase (UInt16 karta, LocalID dbID, UInt16 jak) Kap. 9 Otevře databázi na základě její hodnoty LocalID. Parametry • karta – číslo paměťové karty • dbID – hodnota LocalID databáze na této kartě • jak – konstanta udávající jak bude databáze otevřena (například dmModeReadWrite, dmModeReadOnly nebo dmModeExclusive) Vrácená hodnota • ovladač otevřené databáze nebo NULL v případě chyby
163
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
DmOpenRef DmOpenDatabaseByTypeCreator (UInt32 typ, UInt32 idTvurce, UInt16 mode) Otevře databázi na základě jednoznačné identifikace aplikace a typu databáze. Kap. 9 Parametry • typ – typ databáze • idTvurce – jednoznačná identifikace aplikace, která databázi vytvořila • jak – konstanta udávající jak bude databáze otevřena (například dmModeReadWrite, dmModeReadOnly nebo dmModeExclusive) Vrácená hodnota • ovladač otevřené databáze nebo NULL v případě chyby MemHandle DmQueryNextInCategory (DmOpenRef databaze, UInt16 *pozice, UInt16 category) Vrátí index následujícího záznamu databáze, který patří do uvedené kategorie. Kap. 9 Parametry • databaze - ovladač otevřené databáze • pozice – proměnná, do které bude uloženo pořadové číslo (index) záznamu • category – číslo kategorie Vrácená hodnota • ovladač bloku paměti záznamu nebo NULL v případě chyby MemHandle DmQueryRecord (DmOpenRef databaze, UInt16 index) Vrátí ovladač bloku paměti, ve kterém jsou data příslušného záznamu pouze Kap. 9 pro čtení. Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu Vrácená hodnota • ovladač bloku paměti nebo NULL došlo-li k chybě Err DmRecordInfo (DmOpenRef databaze, UInt16 index, UInt16 *vlastnosti, UInt32 *idZaznamu, LocalID *locID) Zjistí vlastnosti záznamu. Kap. 9 Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu • vlastnosti – proměnná, do které budou uloženy vlastnosti záznamu. Pokud nepotřebujete, předejte hodnotu NULL. • idZaznamu - proměnná, do které bude uložena jednoznačná identifikace záznamu. Pokud nepotřebujete, předejte hodnotu NULL. • locID - proměnná, do které bude uložena hodnota LocalID odpovídající bloku dat záznamu. Pokud nepotřebujete, předejte hodnotu NULL. Vrácená hodnota • číslo chyby nebo noError Err DmReleaseRecord (DmOpenRef databaze, UInt16 index, Boolean spinavy) Kap. 9 Odblokuje záznam, zamčený funkcí DmGetRecord nebo DmNewRecord. Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu • spinavy – zda byl záznam změněn od poslední synchronizace Vrácená hodnota • číslo chyby nebo noError Err DmReleaseResource (MemHandle ovladac) Kap. 8 Odblokuje prostředek aplikace, zamčený funkcí DmGetResource Parametry • ovladac – ovladač bloku paměti, který obsahuje prostředek aplikace Vrácená hodnota • číslo chyby nebo noError
164
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmSetDatabaseInfo (UInt16 karta, LocalID dbID, Char *jmeno, UInt16 *vlastnosti, UInt16 *verze, UInt32 *datumVytvoreni, UInt32 *datumUpravy, UInt32 *datumZalohy, UInt32 *cisloUpravy, LocalID *appInfoIDP, LocalID *sortInfoIDP, UInt32 *typ, UInt32 *tvurce) Nastaví informace v hlavičce databáze. Kap. 9 Parametry • karta – číslo paměťové karty (obvykle 0), na které je databáze vytvořena • dbID – hodnota LocalID, která označuje databázi • jmeno – jméno databáze. Pokud nechcete nastavit, předejte hodnotu NULL. • vlastnosti – vlastnosti databáze. Pokud nechcete nastavit, předejte hodnotu NULL. • verze – verze databáze. Pokud nechcete nastavit, předejte hodnotu NULL. • datumVytvoreni – datum a čas vytvoření databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nechcete nastavit, předejte hodnotu NULL. • datumUpravy – datum a čas poslední změny databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nechcete nastavit, předejte hodnotu NULL. • datumZalohy – datum a čas poslední zálohy databáze (jako počet vteřin od půlnoci 1.1.1904). Pokud nechcete nastavit, předejte hodnotu NULL. • cisloUpravy – pořadové číslo změny databáze od poslední synchronizace. Pokud nechcete nastavit, předejte hodnotu NULL. • appInfoIDP – hodnota LocalID bloku uživatelských informací o databázi (appInfo). Pokud nechcete nastavit, předejte hodnotu NULL. • sortInfoIDP – hodnota LocalID bloku informací o třídění databáze (sortInfo). Pokud nechcete nastavit, předejte hodnotu NULL. • typ – typ databáze. Pokud nepotřebujete, předejte hodnotu NULL. • tvurce - jednoznačná identifikace aplikace, která databázi vytvořila. Pokud nechcete nastavit, předejte hodnotu NULL. Vrácená hodnota • číslo chyby nebo noError Err DmSetRecordInfo (DmOpenRef databaze, UInt16 index, UInt16 *vlastnosti, UInt32 *idZaznamu, LocalID *locID) Nastaví vlastnosti záznamu databáze. Kap. 9 Parametry • databaze – ovladač otevřené databáze • index – číslo záznamu • vlastnosti – vlastnosti záznamu. Pokud nechcete nastavit, předejte hodnotu NULL. • idZaznamu - jednoznačná identifikace záznamu. Pokud nechcete nastavit, předejte hodnotu NULL. • locID - hodnota LocalID odpovídající bloku dat záznamu. Pokud nechcete nastavit, předejte hodnotu NULL. Vrácená hodnota • číslo chyby nebo noError Err DmSet (void *zaznam, UInt32 offset, UInt32 delka, UInt8 hodnota) Vyplní část paměti v záznamu databáze danou hodnotou. Kap. 9 Parametry • zaznam – ukazatel na počátek záznamu • offset – počet přeskočených byte od počátku záznamu • delka – počet zapsaných byte • hodnota – touto hodnotou bude oblast paměti vyplněna Vrácená hodnota • číslo chyby nebo noError
165
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Err DmStrCopy (void *zaznam, UInt32 offset, const Char *text) Zkopíruje řetězec do záznamu databáze. Kap. 9 Parametry • zaznam – ukazatel na počátek záznamu • offset – počet přeskočených byte od počátku záznamu • text – řetězec, který bude zkopírován Vrácená hodnota • číslo chyby nebo noError Err DmWrite (void *zaznam, UInt32 offset, const void *blok, UInt32 delka) Kopíruje data do bloku paměti obsahujícího záznam databáze. Kap. 9 Parametry • zaznam – ukazatel na počátek záznamu • offset – počet přeskočených byte od počátku záznamu • blok – adresa odkud budou data kopírována • delka – počet zkopírovaných byte Vrácená hodnota • číslo chyby nebo noError
Funkce pro zpracování chyb void ErrDisplay (Char* zprava) void ErrNonFatalDisplay (Char* zprava) void ErrNonFatalDisplayIf (Boolean podminka, Char* zprava) Makra, která zobrazí zprávu o chybě. Kap. 2,3,4,9 Parametry • zprava – text, který bude zobrazen • podminka – chybové hlášení bude vypsáno bude-li tato podmínka splněna void ErrFatalDisplay (Char* zprava) void ErrFatalDisplayIf (Boolean podminka, Char* zprava) Makra, která zobrazí zprávu o chybě a restartují Palm Pilota. Kap. 4 Parametry • zprava – text, který bude zobrazen • podminka – chybové hlášení bude vypsáno bude-li tato podmínka splněna
Funkce fronty systémových událostí void EvtAddEventToQueue (const EventType *udalost) Vloží do fronty událostí novou událost Kap. 2 Parametry • udalost – datová struktura popisující zasílanou událost void EvtGetEvent (EventType *udalost, Int32 timeout) Vyzvedne z fronty událostí následující událost. Kap. 2,3,5 Parametry • udalost – datová struktura do které bude zkopírována zpráva o události • timeout – čas v setinách sekundy, který bude funkce na událost čekat (po uplynutí této doby vrátí událost nilEvent) nebo evtWaitForever.
Funkce políček Boolean FldDirty (const FieldType *policko) Zjistí, zda bylo políčko po nastavení textu uživatelem měněno. Parametry • policko – ukazatel na data políčka Vrácená hodnota • true pokud uživatel políčko editoval void FldDrawField (FieldType *policko) Vykreslí políčko na displeji. Parametry • policko – ukazatel na data políčka
166
Kap. 6,7
Kap. 6
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void FldEraseField (FieldType *policko) Smaže políčko z displeje. Parametry • policko – ukazatel na data políčka
Kap. 6
void FldGetScrollValues (const FieldType *policko, UInt16 *horni, UInt16 *vyskaTextu, UInt16 *vyskaPole) Zjistí pozici dlouhého textu v políčku pro nastavení posuvníku. Kap. 6 PalmOS 2.0 Parametry • policko – ukazatel na data políčka • horni – proměnná, do které bude uloženo číslo prvního řádku textu zobrazeného v políčku • vyskaTextu - proměnná, do které bude uložen počet řádků textu v políčku • vyskaTextu - proměnná, do které bude uložena výška políčka v řádcích void FldGetSelection (const FieldType *policko, UInt16 *pocatek, UInt16 *konec) Zjistí počátek a konec vybraného textu v políčku. Kap. 6 Parametry • policko – ukazatel na data políčka • pocatek – proměnná, do které bude uložena pozice prvního vybraného písmena textu • konec – proměnná, do které bude uložena pozice prvního písmena textu za výběrem void FldSetSelection (const FieldType *policko, UInt16 *pocatek, UInt16 *konec) Vybere text v políčku. Kap. 6 Parametry • policko – ukazatel na data políčka • pocatek –pozice prvního vybraného písmena textu • konec –pozice prvního písmena textu za výběrem (pro zrušení výběru předejte hodnotu pocatek větší než konec) MemHandle FldGetTextHandle (const FieldType *policko) Vrátí ovladač bloku paměti, ve kterém je uložen text políčka. Kap. 6 Parametry • policko – ukazatel na data políčka Vrácená hodnota • ovladač bloku paměti, nebo NULL je-li políčko prázdné void FldGetTextHandle (const FieldType *policko, MemHandle ovladac) Nastaví nový ovladač bloku paměti, ve kterém je uložen text políčka. Kap. 6 Parametry • policko – ukazatel na data políčka • ovladac –ovladač bloku paměti, který obsahuje nový text políčka UInt16 FldGetTextLength (const FieldType *policko) Zjistí délku textu v políčku. Kap. 6 Parametry • policko – ukazatel na data políčka Vrácená hodnota • délka textu v políčku UInt16 FldGetVisibleLines (const FieldType *policko) Vrátí počet řádků políčka, které jsou zobrazeny na displeji. Kap. 6 Parametry • policko – ukazatel na data políčka Vrácená hodnota • počet řádků políčka na displeji
167
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Boolean FldScrollable (const FieldType *policko, WinDirectionType smer) Zjistí, zda je možné text v políčku rolovat nahoru nebo dolů. Kap. 6 Parametry • policko – ukazatel na data políčka • smer – konstanta winUp nebo winDown, která označuje směr posunu Vrácená hodnota • logická hodnota, udávající zda je možné text posunout daným směrem void FldScrollField (FieldType *policko, UInt16 pocetRadku, WinDirectionType smer) Posune text v políčku zadaným směrem. Kap. 6 Parametry • policko – ukazatel na data políčka • pocetRadku – o kolik řádků text posuneme • smer – konstanta winUp nebo winDown, která označuje směr posunu void FldUndo (FieldType *policko) void FldCut (FieldType *policko) void FldCopy (FieldType *policko) void FldPaste (FieldType *policko) Funkce pro práci se schránkou. Kap. 6 Parametry • policko – ukazatel na data políčka, kterého se operace týká.
Funkce pracující s čísly v pohyblivé desetinné čárce void FlpBufferAToF (FlpDouble *vysledek, const Char *s) Převede text na číslo v pohyblivé desetinné čárce. Kap. 4 Parametry • vysledek - proměnná, do které bude uložen výsledek • s – řetězec obsahující číslo
PalmOS 2.0
void FlpBufferCorrectedAdd (FlpDouble *vysledek, FlpDouble levy, FlpDouble pravy, Int16 presnost) void FlpBufferCorrectedSub (FlpDouble *vysledek, FlpDouble levy, FlpDouble pravy, Int16 presnost) Sečte (Add) nebo odečte (Sub) dvě čísla v pohyblivé desetinné čárce a opraví Kap. 4 PalmOS 2.0 výsledek dle zvolené přesnosti. Parametry • vysledek - proměnná, do které bude uložen výsledek • levy, pravy – operandy • presnost – nejmenší rozdíl v exponentech, který nezpůsobí nastavení výsledku na nulu Err FlpFToA (FlpDouble a, Char *s) Převede číslo v pohyblivé desetinné čárce na text. Kap. 4 PalmOS 2.0 Parametry • a – číslo v pohyblivé desetinné čárce • s – proměnná, do které bude uložena textová podoba čísla v exponenciálním tvaru (případně texty „+INF“, „-INF“ nebo „NaN“) Vrácená hodnota • číslo chyby nebo noError
Funkce pracující s písmy FontID FntGetFont (void) Zjistí číslo právě používaného písma. Vrácená hodnota • číslo právě používaného (aktuálního) písma
168
Kap. 8
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
FontID FntSetFont (FontID pismo) Nastaví nové písmo. Parametry • pismo – číslo písma, které bude použito Vrácená hodnota • číslo písma, které bylo používáno předtím
Kap. 7,8
Int16 FntCharHeight (void) Zjistí výšku aktuálního písma. Kap. 8 Vrácená hodnota • celková výška aktuálního písma v obrazových bodech (pixels) Int16 FntCharsWidth (Char const *text, Int16 delka) Spočte šířku textu v obrazových bodech. Kap. 8 Parametry • text – proměnná obsahující řeětzec znaků • delka – počet znaků proměnné text Vrácená hodnota • šířka v obrazových bodech, kterou by text zabíral na displeji, kdyby by byl vykreslen aktuálním písmem Int16 FntLineHeight (void) Zjistí výšku řádku textu. Kap. 8 Vrácená hodnota • výška jednoho řádku textu psaného aktuálním písmem (včetně mezery mezi řádky) v obrazových bodech FontID FontSelect (FontID pismo) Zobrazí dialog pro výběr písma. Parametry • pismo – číslo vybraného písma Vrácená hodnota • číslo písma, které uživatel zvolil
Kap. 8
PalmOS 3.0
Funkce pro práci s formuláři UInt16 FrmAlert (UInt16 id) Zobrazí výzvu definovanou v souboru prostředků aplikace. Kap. 5 Parametry • id- číslo prostředku výzvy (ALERT) Vrácená hodnota • číslo tlačítka, které uživatel stisknul (tlačítka jsou číslována zleva) UInt16 FrmCustomAlert (UInt16 id, Char *s1, Char *s2, Char *s3) Zobrazí výzvu definovanou v souboru prostředků aplikace a nahradí znaky ^1 Kap. 5 až ^3 definovanými texty. Parametry • id- číslo prostředku výzvy (ALERT) • s1 – text, kterým bude nahrazena kombinace znaků ^1 nebo NULL, pokud se v textu výzvy tato kombinace nevyskytuje • s2 – text, kterým bude nahrazena kombinace znaků ^2 nebo NULL, pokud se v textu výzvy tato kombinace nevyskytuje • s3 – text, kterým bude nahrazena kombinace znaků ^3 nebo NULL, pokud se v textu výzvy tato kombinace nevyskytuje Vrácená hodnota • číslo tlačítka, které uživatel stisknul (tlačítka jsou číslována zleva) void FrmCloseAllForms (void) Zašle všem otevřeným formulářům událost frmCloseEvent.
169
Kap. 2,5
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void FrmDeleteForm (FormType *formular) Zruší datové struktury formuláře. Parametry • formular – ukazatel na data formuláře
Kap. 5
Boolean FrmDispatchEvent (EventType *udalost) Předá událost funkci aktivního formuláře. Kap. 2,5 Parametry • udalost – ukazatel na datovou strukturu, ve které jsou informace o události Vrácená hodnota • true pokud funkce formuláře událost zpracovala UInt16 FrmDoDialog (FormType *formular) Zobrazí na displeji dialog. Kap. 5,6 Parametry • formular – ukazatel na data dialogu, který byl inicializován funkcí FrmInitForm Vrácená hodnota • jednoznačná identifikace tlačítka, které uživatel stisknul void FrmDrawForm (FormType *formular) Vykreslí formulář na displeji. Parametry • formular – ukazatel na data formuláře
Kap. 5
FormType *FrmGetActiveForm (void) Vrátí ukazatel na data právě aktivního formuláře. Vrácená hodnota • ukazatel na data aktivního formuláře
Kap. 5,6,7
void FrmSetActiveForm (FormType *formular) Nastaví nový aktivní formulář (formulář, který komunikuje s uživatelem) Parametry • formular – ukazatel na data formuláře
Kap. 5
UInt16 FrmGetControlGroupSelection (const FormType *formular, UInt8 skupina) Vrátí pořadové číslo přepínače nebo políčka k zaškrtnutí, který je vybrán Kap. 6 v rámci skupiny (GROUP n). Parametry • formular – ukazatel na data formuláře • skupina – číslo skupiny Vrácená hodnota • index prvku, který je vybrán void FrmSetControlGroupSelection (const FormType *formular, UInt8 skupina, UInt16 id) Nastaví ve skupině vybraný prvek (políčko k zaškrtnutí nebo přepínač). Kap. 6 Parametry • formular – ukazatel na data formuláře • skupina – číslo skupiny • id – jednoznačná identifikace políčka k zaškrtnutí nebo přepínače, které má být ve skupině vybráno Int16 FrmGetControlValue (const FormType *formular, UInt16 index) Zjistí stav přepínače nebo políčka k zaškrtnutí Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo tlačítka, jehož hodnotu zjišťujeme Vrácená hodnota • hodnota 0 (nevybráno) nebo 1 (vybráno, zaškrtnuto)
170
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void FrmSetControlValue (const FormType *formular, UInt16 index, Int16 novaHodnota) Nastaví stav přepínače nebo políčka k zaškrtnutí Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo tlačítka, jehož hodnotu nastavujeme • novaHodnota – zda je tlačítko vybráno nebo zaškrtnuto (1) nebo ne (0) UInt16 FrmGetFocus (const FormType *formular) Zjistí prvek formuláře, který je aktivní (do kterého uživatel zapisuje data) Kap. 6 Parametry • formular – ukazatel na data formuláře Vrácená hodnota • index prvku formuláře (většinou políčka), do kterého uživatel zapisuje data void FrmSetFocus (FormType *formular, UInt16 indexPolicka) Zobrazí kursor v políčku. Kap. 6 Parametry • formular – ukazatel na data formuláře • indexPolicka – pořadové číslo políčka, ve kterém zobrazujeme kursor UInt16 FrmGetObjectId (const FormType *formular, UInt16 index) Převede index prvku formuláře na jeho jednoznačnou identifikaci. Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři Vrácená hodnota • identifikační číslo (ID) prvku formuláře nebo konstanta frmInvalidObjectId UInt16 FrmGetObjectIndex (const FormType *formular, UInt16 id) Na základě jednoznačné identifikace prvku formuláře zjistí jeho index. Kap. 6,7 Parametry • formular – ukazatel na data formuláře • id – identifikační číslo (ID) prvku formuláře Vrácená hodnota • pořadové číslo (index) prvku ve formuláři nebo konstanta frmInvalidObjectId void *FrmGetObjectPtr (const FormType *formular, UInt16 index) Vrátí ukazatel na data prvku formuláře. Kap. 6,7 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři Vrácená hodnota • ukazatel na datovou strukturu prvku formuláře (nutno přetypovat například na ControlPtr, ListPtr nebo FieldPtr podle typu prvku) nebo NULL
171
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
FormObjectKind FrmGetObjectType (const FormType *formular, UInt16 index) Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři Vrácená hodnota • konstanta označující typ prvku enum FormObjectKind { frmFieldObj, frmControlObj, frmListObj, frmTableObj, frmBitmapObj, frmLineObj, frmFrameObj, frmRectangleObj, frmLabelObj, frmTitleObj, frmPopupObj, frmGraffitiStateObj, frmGadgetObj, frmScrollbarObj, }; void FrmGotoForm (UInt16 idFormulare) Zařadí do fronty systémových událostí frmCloseEvent, frmLoadEvent a Kap. 2,5 frmOpenEvent. Výsledkem je zrušení současného formuláře a nahrání formuláře nového. Parametry • idFormulare – jednoznačná identifikace formuláře v souboru prostředků aplikace void FrmHelp (UInt16 idTextu) Zobrazí nápovědu Kap. 4,5 Parametry • idTextu - jednoznačná identifikace textu, který bude na displeji zobrazen void FrmHideObject (FormType *formular, UInt16 index) Vymaže objekt formuláře z displeje. Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři void FrmShowObject (FormType *formular, UInt16 index) Zobrazí objekt formuláře na displeji. Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři FormType *FrmInitForm (UInt16 idFormulare) Inicializuje datové struktury formuláře. Kap. 5 Parametry • idFormulare – jednoznačná identifikace formuláře v souboru prostředků aplikace Vrácená hodnota • ukazatel na data inicializovaného formuláře
172
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void FrmSetEventHandler (FormType *formular, FormEventHandlerType *funkce) Nastaví funkci formuláře (funkci, která bude zpracovávat události v aktivním Kap. 5 formuláři) Parametry • formular – ukazatel na data formuláře • funkce – funkce formuláře typu FormEventHandlerType Boolean FormEventHandlerType (EventType *udalost) void FrmSetObjectPosition (FormType *formular, UInt16 index, Coord x, Coord y) Nastaví pozici prvku formuláře, nevykreslí jej na displeji. Kap. 6 Parametry • formular – ukazatel na data formuláře • index – pořadové číslo prvku ve formuláři • x, y – nové souřadnice prvku na displeji; void FrmUpdateScrollers (FormType *formular, UInt16 indexNahoru, UInt16 indexDolu, Boolean lzeNahoru, Boolean lzeDolu) Překreslí opakovací tlačítka pro stránkování nahoru a dolů. Kap. 6 Parametry • formular – ukazatel na data formuláře • indexNahoru – pořadové číslo tlačítka pro posun o stránku nahoru ve formuláři • indexDolu – pořadové číslo tlačítka pro posun o stránku dolů ve formuláři • lzeNahoru – true pokud je možný posun o stránku nahoru • lzeDolu – true pokud je možný posun o stránku dolů
Funkce pro vlastnosti (features) Err FtrGet (UInt32 idTvurce, UInt16 cisloVlastnosti, UInt32 *vysledek) Zjistí příslušnou vlastnost (32bitové číslo). Kap. 4 Parametry • idTvurce – jednoznačná identifikace aplikace, která vlastnost přidala do tabulky vlastností • cisloVlastnosti – uživatelem zvolené číslo vlastnosti • vysledek – proměnná, do které bude vlastnost uložena Vrácená hodnota • noError v případě úspěchu, číslo chyby pokud vlastnost není definována Err FtrSet (UInt32 idTvurce, UInt16 cisloVlastnosti, UInt32 hodnota) Nastaví příslušnou vlastnost (32bitové číslo) v tabulce vlastností. Kap. 4 Parametry • idTvurce – jednoznačná identifikace aplikace • cisloVlastnosti – uživatelem zvolené číslo vlastnosti • hodnota – 32bitová hodnota vlastnosti Vrácená hodnota • číslo chyby nebo noError
Funkce pro práci se seznamy void LstDrawList (ListType *seznam) Vykreslí seznam na displeji. Parametry • seznam – ukazatel na data seznamu
Kap. 6
void LstEraseList (ListType *seznam) Vymaže seznam z displeje. Parametry • seznam – ukazatel na data seznamu
Kap. 6
173
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Int16 LstGetSelection (const ListType *seznam) Zjistí, který prvek seznamu je vybrán. Kap. 6 Parametry • seznam – ukazatel na data seznamu Vrácená hodnota • pořadové číslo vybraného prvku seznamu (od nuly) nebo noListSelection, není-li žádný prvek seznamu vybrán Char *LstGetSelectionText (const ListType *seznam, Int16 cisloPrvku) Zjistí text vybraného prvku seznamu. Kap. 6 Parametry • seznam – ukazatel na data seznamu • cisloPrvku - pořadové číslo prvku seznamu (od nuly) Vrácená hodnota • ukazatel na text daného prvku seznamu nebo NULL void LstMakeItemVisible (ListType *seznam, Int16 cisloPrvku) Nastaví seznam tak,aby byl daný prvek zobrazen. Nepřekresluje seznam na Kap. 6 displeji. Parametry • seznam – ukazatel na data seznamu • cisloPrvku - pořadové číslo prvku seznamu (od nuly) Int16 LstPopupList (ListType *seznam) Zobrazí na displeji seznam, ze kterého může uživatel vybrat jednu hodnotu; Kap. 6 poté seznam zmizí. Parametry • seznam – ukazatel na data seznamu Vrácená hodnota • pořadové číslo vybraného prvku seznamu (od nuly) nebo noListSelection, nebyl-li žádný prvek seznamu vybrán void LstSetDrawFunction (ListType *seznam, ListDrawDataFuncPtr funkce) Nastaví funkci, která se bude starat o vykreslování prvků seznamu. Kap. 6 Parametry • seznam – ukazatel na data seznamu • funkce – funkce, která bude vykreslovat prvky seznamu typu ListDrawDataFuncType void ListDrawDataFuncType(Int16 itemNum, RectangleType *bounds, Char **itemsText) void LstSetListChoices (ListType *seznam, Char **texty, Int16 pocet) Nastaví počet - případně i texty - prvků seznamu. Kap. 6 Parametry • seznam – ukazatel na data seznamu • texty – pole ukazatelů na texty, které budou v seznamu zobrazeny nebo NULL, pokud zajišťujeme zobrazování textů uživatelsky kreslenou funkcí • pocet – počet prvků seznamu void LstSetPosition (ListType *seznam, Coord x, Coord y) Nastaví pozici, na které bude seznam vykreslen na displeji. Kap. 6 Parametry • seznam – ukazatel na data seznamu • x, y – nové souřadnice
174
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void LstSetSelection (ListType *listP, Int16 cisloPrvku) Vybere zvolený prvek seznamu. Kap. 6 Parametry • seznam – ukazatel na data seznamu • cisloPrvku - pořadové číslo prvku seznamu (od nuly)
Funkce pro správu paměti Err MemHandleFree (MemHandle h) Vrátí operačnímu systému přemístitelný blok paměti, získaný funkcí MemHandleNew. Parametry • h – ovladač přemístitelného bloku paměti Vrácená hodnota • číslo chyby nebo noError
Kap. 4,6
MemPtr MemHandleLock (MemHandle h) Uzamkne přemístitelný blok paměti na místě a vrátí jeho adresu. Kap. 4,6,8,9 Parametry • h – ovladač přemístitelného bloku paměti Vrácená hodnota • adresa v paměti, na které se nachází data přemístitelného bloku paměti. Tato adresa je platná až do volání funkce MemHandleFree MemHandle MemHandleNew (UInt32 velikost) Vytvoří nový přemístitelný blok paměti. Kap. 4 Parametry • velikost – velikost v byte (2-65000) požadovaného bloku paměti Vrácená hodnota • ovladač bloku paměti nebo NULL pokud není možné paměť získat Err MemHandleResize (MemHandle h, UInt32 novaVelikost) Změní velikost přemístitelného bloku paměti Kap. 4 Parametry • h – ovladač přemístitelného bloku paměti • novaVelikost – nová velikost bloku paměti Vrácená hodnota • číslo chyby nebo noError UInt32 MemHandleSize (MemHandle h) Zjistí velikost přemístitelného bloku paměti. Parametry • h – ovladač přemístitelného bloku paměti Vrácená hodnota • velikost bloku paměti v byte Err MemHandleUnlock (MemHandle h) Odemkne přemístitelný blok paměti, který byl uzamčen na místě funkcí MemHandleLock, tak aby jej mohl operační systém v případě potřeby přesunout. Parametry • h – ovladač přemístitelného bloku paměti Vrácená hodnota • číslo chyby nebo noError
Kap. 4,9
Kap. 4,6,8,9
LocalID MemHandleToLocalID (MemHandle h) Vrátí hodnotu LocalID, která odpovídá danému bloku paměti (tato hodnota je Kap. 9 relativní vzhledem k paměťové kartě a slouží pro práci s databázemi) Parametry • h – ovladač přemístitelného bloku paměti Vrácená hodnota • hodnota LocalID, která odpovídá danému bloku paměti nebo NULL
175
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
MemPtr MemLocalIDToLockedPtr (LocalID localID, UInt16 karta) Převede kombinaci hodnoty LocalID a čísla karty, na které je blok umístěn na Kap. 9 uzamčený ukazatel na počátek bloku paměti. Tento blok paměti je třeba po použití odemknout pomocí funkce MemPtrUnlock. Parametry • localID – hodnota LocalID • karta – číslo paměťové karty Vrácená hodnota • adresa počátku uzamčeného bloku paměti nebo NULL v případě neúspěchu Err MemPtrFree (MemPtr p) Vrátí operačnímu systému blok paměti získaný MemPtrNew. Parametry • p – adresa počátku bloku paměti Vrácená hodnota • číslo chyby nebo noError
Kap. 4
MemPtr MemPtrNew (UInt32 velikost) Vytvoří nový nepřemístitelný blok paměti. Kap. 4 Parametry • velikost – velikost požadovaného bloku paměti Vrácená hodnota • adresa počátku bloku paměti nebo NULL není-li možné takto velký blok získat Err MemPtrUnlock (MemHandle h) Odemkne přemístitelný blok paměti, který byl uzamčen na místě funkcí MemHandleLock, tak aby jej mohl operační systém v případě potřeby přesunout. Parametry • p – adresa počátku bloku paměti Vrácená hodnota • číslo chyby nebo noError
Kap. 4
Err MemMove (void* cil, const void* zdroj, Int32 kolik) Rychle zkopíruje data v paměti z jedné adresy do druhé. Pracuje korektně i Kap. 4 pokud se zdrojová a cílová oblast překrývají. Parametry • cil – adresa, kam budou data kopírována • zdroj – odkud budou data kopírována • kolik – počet byte, které budou kopírovány ze zdrojové na cílovou adresu v paměti Vrácená hodnota • noError Err MemSet (void* cil, Int32 kolik, UInt8 hodnota) Vyplní oblast paměti udanou hodnotou. Kap. 2,4 Parametry • cil – adresa, od které bude paměť vyplněna • kolik – délka vyplněné oblasti v byte • hodnota – byte, kterým bude oblast v paměti vyplněna Vrácená hodnota • noError
Funkce pro práci s menu Boolean MenuHandleEvent (MenuBarType *menu, EventType *udalost, UInt16 *chyba) Zpracuje události menu. Kap. 2,5 Parametry • menu – ukazatel na datové struktury menu nebo NULL pro použití menu formuláře, které bylo definováno v souboru prostředků aplikace • udalost – ukazatel na data události • chyba – proměnná, do které bude uloženo číslo případné chyby Vrácená hodnota • true pokud funkce událost zpracovala
176
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce pro práci s uživatelským nastavením (preferences) Int16 PrefGetAppPreferences (UInt32 idTvurce, UInt16 cislo, void *data, UInt16 *velikost, Boolean ulozene) Pokusí se z vyzvednout uložené uživatelské nastavení. Kap. 4 PalmOS 2.0 Parametry • idTvurce – jednoznačná identifikace naší aplikace • cislo – uživatelem definovaná konstanta, rozlišující různá uživatelská nastavení v rámci jedné aplikace • data – ukazatel na datovou strukturu, do které bude uživatelské nastavení nahráno nebo NULL pokud jenom zjišťujeme velikost uložených dat • velikost – ukazatel na proměnnou, do které je před voláním funkce uložena velikost datové struktury, do které má být uživatelské nastavení nahráno. Po úspěšném volání funkce obsahuje proměnná skutečnou velikost dat. • ulozene – konstanta udávající, zda bude uživatelské nastavení uloženo ve skupině, která je zálohována při synchronizaci nebo nikoliv Vrácená hodnota • číslo verze vyzvednutého uživatelského nastavení nebo konstanta noPreferenceFound nebylo-li žádné vhodné nastavení nalezeno void PrefSetAppPreferences (UInt32 idTvurce, UInt16 cislo, Int16 verze, const void *data, UInt16 velikost, Boolean ulozene) Uloží uživatelské nastavení. Kap. 4 PalmOS 2.0 Parametry • idTvurce – jednoznačná identifikace naší aplikace • cislo – uživatelem definovaná konstanta, rozlišující různá uživatelská nastavení v rámci jedné aplikace • verze – označení verze uživatelského nastavení pro odlišení datových struktur, které uložily různé verze naší aplikace a která mohou mít jiný obsah • data – ukazatel na strukturu obsahující uživatelské nastavení • velikost – velikost uživatelského nastavení v byte • ulozene – konstanta udávající, zda bude uživatelské nastavení uloženo ve skupině, která je zálohována při synchronizaci nebo nikoliv
Funkce pracující s výřezy void RctCopyRectangle (const RectangleType* zdroj, RectangleType* cil) Kopíruje souřadnice výřezu z jedné datové struktury do druhé. Kap. 8 Parametry • zdroj – ukazatel na výřez, který bude kopírován • cíl – ukazatel na datovou strukturu, do které bude výřez kopírován void RctGetIntersection (const RectangleType* r1, const RectangleType* r2, RectangleType* r3) Vrátí výřez, který se nachází v průsečíku dvou jiných výřezů. Kap. 8 Parametry • r1, r2 – výřezy, jejichž průsečík nás zajímá • r3 – datová struktura, do které bude uložen výsledný průsečík; pokud výřezy průsečík nemají tak je alespoň jeden z rozměrů výřezu nulový void RctInsetRectangle (RectangleType* r, Coord kolik) Symetricky zmenší nebo zvětší výřez. Kap. 8 Parametry • r – výřez, se kterým manipulujeme • kolik – udává, o kolik bodů budou okraje výřezu posunuty dovnitř (je-li kladné) nebo směrem ven (je-li záporné)
177
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void RctOffsetRectangle (RectangleType* r, Coord dX, Coord dY) Posune výřez. Kap. 8 Parametry • r – výřez, se kterým manipulujeme • dX – o kolik bodů bude výřez posunut na ose X (kladná hodnota znamená posunutí doprava) • dY – o kolik bodů bude výřez posunut na ose Y (kladná hodnota znamená posunutí dolů) Boolean RctPtInRectangle (Coord x, Coord y, const RectangleType* r) Zjistí, zda se daný bod nachází ve výřezu. Kap. 8 Parametry • x, y – souřadnice testovaného bodu • r – výřez, ve kterém zjišťujeme přítomnost bodu Vrácená hodnota • true pokud se bod nachází uvnitř výřezu void RctSetRectangle (RectangleType* r, Coord x, Coord y, Coord w, Coord h) Naplní datovou strukturu výřezu Kap. 8 Parametry • r – datová struktura, do které jsou hodnoty uloženy • x, y – souřadnice levého horního rohu výřezu • w, h – šířka a výška výřezu
Funkce pro práci s posuvníkem void SclSetScrollBar (ScrollBarType *posuvnik, Int16 hodnota, Int16 min, Int16 max, Int16 stranka) Aktualizuje zobrazení posuvníku a překreslí jej. Kap. PalmOS 2.0 Parametry • posuvnik – ukazatel datovou strukturu posuvníku • hodnota – aktuální pozice, např. řádek • min – nejmenší možná pozice • max – nejvyšší možná pozice (počet řádků – velikost stránky) • stranka – počet řádků na stránku
Funkce pro práci s řetězci Int16 StrCompare (const Char *s1, const Char *s2) Int16 StrNCompare (const Char *s1, const Char *s2, Int32 n) Int16 StrCaselessCompare (const Char *s1, const Char *s2) Int16 StrNCaselessCompare (const Char *s1, const Char *s2, Int32 n) Kap. 4,9 PalmOS 2.0 Funkce pro ASCII porovnání dvou řetězců: funkce StrNCompare a StrNCaselessCompare porovnávají pouze prvních n znaků; funkce StrCaselessCompare porovnává řetězce bez ohledu na malá a valká písmena. Parametry • s1, s2 – porovnávané řetězce • n – největší počet znaků, které jsou porovnávány Vrácená hodnota • -1 když s1 < s2 +1 když s1 > s2 0 když s1 = s2 (platí pro prvních n znaků)
178
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Char *StrCat (Char *kam, const Char *co) Char *StrNCat (Char *kam, const Char *co, Int16 n) Připojí jeden řetězec na konec druhého. Kap. 4 PalmOS 2.0 Parametry • kam – řetězec, ke kterému je text připojován • co – text, který je připojován na konec řetězce kam • n – největší možná délka řetězce kam (včetně ukončovacího znaku \0 Vrácená hodnota • je vrácena hodnota kam Char *StrCopy (Char *kam, const Char *co) Char *StrNCopy (Char *kam, const Char *co, Int16 n) Zkopíruje řetězec. Kap. 4 PalmOS 2.0 Parametry • kam – řetězec, do kterého je text kopírován • co – text, který je kopírován • n – největší možná délka řetězce kam (včetně ukončovacího znaku \0 Vrácená hodnota • je vrácena hodnota kam Char *StrChr (const Char *kde, WChar znak) Nalezne první pozici znaku v řetězci. Kap. 4 Parametry • kde – řetězec, ve kterém znak vyhledáváme • znak – znak, který hledáme Vrácená hodnota • ukazatel na první pozici znaku v řetězci nebo NULL, nebyl-li v řetězci znak nalezen Int32 StrAToI (const Char *text) Pokusí se převést řetězec na číslo. Kap. 4 Parametry • text – řetězec, který obsahuje číslo k převedení Vrácená hodnota • číslo, které bylo v řetězci nebo 0 pokud se převod nepodařil Char *StrIToA (Char *s, Int32 i) Převede číslo na řetězec. Kap. 4 Parametry • s – řetězcová proměnná minimální délky maxStrIToALen, do které bude uložen výsledek • i – číslo k převedení Vrácená hodnota • vrací hodnotu s UInt16 StrLen (const Char *text) Spočte délku řetězce ve znacích. Parametry • text – řetězec, jehož délku zjišťujeme Vrácená hodnota • délka řetězce ve znacích
Kap. 4
Int16 StrPrintF (Char *s, const Char *format, ...) Funkce pro formátování textu a jeho uložení do proměnné. Kap. PalmOS 2.0 Parametry • s – řetězcová proměnná, do které bude uložen výsledek • format – řetězec, ve kterém jsou formátovací znaky pro výstup čísel (%d, %u, %x, %ld, %lu, %lx), textu (%s), znaků (%c). Rozeznává také prefixy +, -, *. Neumí pracovat s čísly v pohyblivé desetinné čárce. Vrácená hodnota • počet znaků zapsaných do proměnné s nebo záporné číslo v případě chyby
179
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Char *StrStr (const Char *text, const Char *co) Hledá řetězec v jiném řetězci. Kap. 4 PalmOS 2.0 Parametry • text – text, ve kterém hledáme výskyt textu v proměnné co • co – hledaný řetězec Vrácená hodnota • ukazatel na začátek nalezeného textu nebo NULL pokud text nebyl nalezen
Systémové funkce void SysCopyStringResource (Char *kam, Int16 idTextu) Zkopíruje text, definovaný v souboru prostředků aplikace (STRING) do Kap. 4 proměnné. Parametry • kam – proměnná, do které bude text kopírován • idTextu – jednoznačná identifikace textu, který bude kopírován Char *SysErrString (Err chyba, Char *kam, UInt16 maxDelka) Uloží do proměnné textový popis chyby. Kap. 2,9 PalmOS 2.0 Parametry • chyba – číslo chyby • kam – proměnná, do které bude textová zpráva o chybě uložena • maxDelka – maximální počet znaků (včetně ukončujícího \0), který bude uložen do proměnné kam Vrácená hodnota • vrací hodnotu proměnné kam void SysGraffitiReferenceDialog (ReferenceType typ) Zobrazí nápovědu ke Graffiti nebo Graffiti 2 Kap. 4,6 Parametry • typ – typ nápovědy (zatím může mít pouze hodnotu referenceDefault) Boolean SysHandleEvent (EventPtr udalost) Zpracování události operačním systémem PalmOS. Kap. 2,3,5 Parametry • udalost – ukazatel na strukturu, ve které je uložen popis události Vrácená hodnota • true pokud byla událost systémem zpracována void SysKeyboardDialog (KeyboardType kbd) Zobrazí na displeji klávesnici. Parametry • kbd – typ klávesnice
Kap. 4,6
PalmOS 2.0
typedef enum { kbdAlpha, kbdNumbersAndPunc, kbdAccent, kbdDefault } KeyboardType; Int16 SysRandom (Int32 inicializace) Pseudonáhodné číslo. Kap. 4 PalmOS 2.0 Parametry • inicializace – pokud je tato hodnota nanulová, použije se k inicializaci generátoru náhodných čísel; pokud je 0, je generováno pseudonáhodné číslo Vrácená hodnota • pseudonáhodné číslo mezi 0 a sysRandomMax void SysReset (void) Restart operačního systému (podobně jako stisk tlačítka reset)
180
Kap. 4
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce pro práci s tabulkami Boolean TblFindRowData (const TableType *tabulka, UInt32 data, Int16 *radek) Pokusí se najít řádek, který obsahuje příslušnou 32bitovou datovou hodnotu Kap. 7 (nastavenou pomocí TblSetRowData) Parametry • tabulka – ukazatel na data tabulky • data – hledaná hodnota • radek – proměnná, do které bude uloženo číslo nalezeného řádku Vrácená hodnota • true pokud byl řádek nalezen Boolean TblFindRowID (const TableType *tabulka, UInt16 id, Int16 *radek) Pokusí se najít řádek, který obsahuje příslušnou 16bitovou ID hodnotu Kap. 7 (nastavenou pomocí TblSetRowID) Parametry • tabulka – ukazatel na data tabulky • id– hledaná hodnota • radek – proměnná, do které bude uloženo číslo nalezeného řádku Vrácená hodnota • true pokud byl řádek nalezen FieldPtr TblGetCurrentField (const TableType *tabulka) Je-li tabulka v režimu změny textu, zjistí tato hodnota políčko, které uživatel Kap. 7 edituje. Parametry • tabulka – ukazatel na data tabulky Vrácená hodnota • ukazatel na data políčka nebo NULL, pokud tabulka není v režimu změny textu Int16 TblGetItemInt (const TableType *tabulka, Int16 radek, Int16 sloupec) Vrátí celočíselnou hodnotu uloženou v buňce tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky • sloupec – sloupek tabulky Vrácená hodnota • funkce vrací celočíselnou hodnotu uloženou v buňce tabulky Int16 TblGetNumberOfRows (const TableType *tabulka) Zjistí počet řádků tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky Vrácená hodnota • počet řádků, které tabulka na displeji zabírá UInt32 TblGetRowData (const TableType *tabulka, Int16 radek) Vrátí 32bitovou datovou hodnotu, která je uložena v řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky Vrácená hodnota • 32bitová datová hodnota, uložená v řádku tabulky Coord TblGetRowHeight (const TableType *tabulka, Int16 radek) Vrátí výšku řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky Vrácená hodnota • výška řádku tabulky v obrazových bodech
181
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Coord TblGetRowID (const TableType *tabulka, Int16 radek) Vrátí 16bitovou hodnotu ID, která je uložena v řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky Vrácená hodnota • 16bitová hodnota ID, která je uložena v řádku tabulky (často například číslo záznamu databáze, který je v řádku tabulky) void TblMarkRowInvalid (TableType *tabulka, Int16 radek) Označí řádek jako neplatný, aby byl při příštím vykreslování tabulky Kap. 7 překreslen. Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky void TblMarkTableInvalid (TableType *tabulka) Označí celou tabulku (všechny řádky) jako neplatnou tak, aby byla při příštím vykreslování tabulky celá překreslena. Parametry • tabulka – ukazatel na data tabulky
Kap. 7
void TblRedrawTable (TableType *tabulka) Překreslí tabulku (pouze ty řádky, které byly označeny jako neplatné). Parametry • tabulka – ukazatel na data tabulky
Kap. 7
Boolean TblRowUsable (const TableType *tabulka, Int16 radek) Zjistí, zda je řádek tabulky použitelný (zda je zobrazen a může reagovat na akce Kap. 7 uživatele). Parametry • tabulka – ukazatel na data tabulky • radek – řádek tabulky Vrácená hodnota • true pokud je řádek použitelný void TblSetColumnSpacing (TableType *tabulka, Int16 sloupec, Coord mezera) Nastaví šířku prázdného místa vedle sloupečku. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • mezera – šířka bílého místa mezi tímto a dalším sloupcem void TblSetColumnUsable (TableType *tabulka, Int16 sloupec, Boolean pouzitelny) Nastaví použitelnost sloupečku tabulky (zda jsou buňky v něm vykreslovány a Kap. 7 zda reagují na akce uživatele) Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • pouzitelny – zda je tento sloupeček vykreslován a zda buňky v něm reagují na akce uživatele
182
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void TblSetRowUsable (TableType *tabulka, Int16 radek, Boolean pouzitelny) Nastaví použitelnost řádku tabulky (zda jsou buňky v něm vykreslovány a zda Kap. 7 reagují na akce uživatele) Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku tabulky (také řádky jsou číslovány od nuly) • pouzitelny – zda je tento sloupeček vykreslován a zda buňky v něm reagují na akce uživatele void TblSetColumnEditIndicator (TableType *tabulka, Int16 sloupec, Boolean jeZvyraznovan) Zvolí, zda jsou buňky v daném sloupci zvýrazňovány, upravuje-li uživatel text Kap. 7 na řádku. Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • jeZvyraznovan – zda jsou buňky v tomto sloupci zvýrazňovány (inverzí), editujeli uživatel text v některém políčku na řádku void TblSetColumnWidth (TableType *tabulka, Int16 sloupec, Coord sirka) Nastavuje šířku sloupečku tabulky Kap. 7 Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • sirka – šířka sloupce v obrazových bodech void TblSetCustomDrawProcedure (TableType *tabulka, Int16 sloupec, TableDrawItemFuncPtr funkce) Nastaví uživatelem definovanou funkci pro vykreslování buněk v sloupečku, Kap. 7 který byl definován s typem customTableItem. Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • funkce – adresa funkce typu TableDrawItemFuncType, která je použita k vykreslování buněk void TableDrawItemFuncType (void *tableP, Int16 row, Int16 column, RectangleType *bounds) void TblSetLoadDataProcedure (TableType *tabulka, Int16 sloupec, TableLoadDataFuncPtr funkce) Nastaví uživatelem definovanou funkci pro vyzvednutí dat (například Kap. 7 z databáze) do textového políčka tabulky. Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku (od nuly) • funkce – adresa funkce typu TableLoadDataFuncType, která je volána vždy při zobrazení políčka a před začátkem změny textu v políčku Err TableLoadDataFuncType (void *tableP, Int16 row, Int16 column, Boolean editable, MemHandle *dataH, Int16 *dataOffset, Int16 *dataSize, FieldPtr fld)
183
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void TblSetSaveDataProcedure (TableType *tabulka, Int16 sloupec, TableSaveDataFuncPtr funkce) Nastaví uživatelem definovanou funkci pro uložení dat – případně jejich Kap. 7 kontrolu – po skončení úprav textu v buňce. Parametry • tabulka – ukazatel na data tabulky • sloupec – číslo sloupečku • funkce – adresa funkce typu TableSaveDataFuncType, která je volána vždy po ukončení změn textu v políčku Boolean TableSaveDataFuncType (void *tableP, Int16 row, Int16 column) void TblSetItemFont (TableType *tabulka, Int16 radek, Int16 sloupec, FontID pismo) Nastaví písmo, které bude použito k vykreslení políčka pro úpravu textu Kap. 7 PalmOS 3.0 v buňce. Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • sloupec – číslo sloupečku • pismo – číslo písma void TblSetItemInt (TableType *tabulka, Int16 radek, Int16 sloupec, Int16 hodnota) Nastaví celočíselnou informaci, která je uložena v buňce tabulky (například Kap. 7 stav políčka k zaškrtnutí nebo vybraný prvek seznamu). Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • sloupec – číslo sloupečku • hodnota – číslo, které bude uloženo do buňky tabulky void TblSetItemPtr (TableType *tabulka, Int16 radek, Int16 sloupec, void *hodnota) Nastaví ukazatel, který je uložen v buňce tabulky (například ukazatel na data Kap. 7 seznamu nebo ukazatel na text v buňce). Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • sloupec – číslo sloupečku • hodnota – ukazatel, který bude uložen do buňky tabulky
184
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void TblSetItemStyle (TableType *tabulka, Int16 radek, Int16 sloupec, TableItemStyleType typ) Nastaví typ buňky tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • sloupec – číslo sloupečku • typ – typ buňky tabulky dle následující struktury enum tableItemStyleType { checkboxTableItem, customTableItem, dateTableItem, labelTableItem, numericTableItem, popupTriggerTableItem, textTableItem, textWithNoteTableItem, timeTableItem, narrowTextTableItem, tallCustomTableItem }; void TblSetRowData (TableType *tabulka, Int16 radek, UInt32 data) Nastaví 32bitovou datovou hodnotu, která je uložena v řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • data – 32bitová hodnota void TblSetRowHeight (TableType *tabulka, Int16 radek, Coord vyska) Nastaví výšku řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • vyska – výška řádku tabulky v obrazových bodech void TblSetRowID (TableType *tabulka, Int16 radek, UInt16 id) Nastaví 16bitovou hodnotu ID, která je uložena v řádku tabulky. Kap. 7 Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • id – 16bitová hodnota ID (často například číslo záznamu databáze, který je vykreslen v řádku) void TblSetRowStaticHeight (TableType *tabulka, Int16 radek, Boolean pevnaVyska) Určí, zda se může výška řádku měnit při přidávání textu do políčka v něm Kap. 7 obsaženého nebo ne. Parametry • tabulka – ukazatel na data tabulky • radek – číslo řádku • pevnaVyska – pokud je true, je výška řádku pevně daná a není možné ji měnit například při zadávání textu do políčka v řádku obsaženém
185
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce pro práci s časem UInt32 TimDateTimeToSeconds (const DateTimeType *datumACas) Převede datum a čas na počet vteřin od půlnoci 1.1.1904. Kap. 4 Parametry • datumACas – ukazatel na strukturu, obsahující datum a čas Vrácená hodnota • počet vteřin od půlnoci 1.1.1904, který odpovídá předanému časovému údaji UInt32 TimGetSeconds (void) Aktuální datum a čas. Kap. 4 Vrácená hodnota • Vrátí hodnotu aktuálního data a času jako počet vteřin od půlnoci 1.1.1904 void TimSecondsToDateTime (UInt32 vteriny, DateTimeType *datumACas) Převede číslo odpovídající počtu vteřin od půlnoci 1.1.1904 na strukturu Kap. 4 obsahující datum a čas. Parametry • vteriny - počet vteřin od půlnoci 1.1.1904 • datumACas – ukazatel na strukturu, do které bude uloženo datum a čas void TimeToAscii (UInt8 hodiny, UInt8 minuty, TimeFormatType format, Char *kam) Převede čas na text v jednom z předdefinovaných formátů. Kap. 4 Parametry • hodiny, minuty – časový údaj • format – formát času TimeFormatType • kam – řetězcová proměnná, do které bude výsledek uložen typedef enum { tfColon, tfColonAMPM, tfColon24h, tfDot, tfDotAMPM, tfDot24h, tfHoursAMPM, tfHours24h, tfComma24h, } TimeFormatType;
186
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Funkce správce oken void WinCopyRectangle (WinHandle zdrojoveOkno, WinHandle ciloveOkno, const RectangleType *zdrojVyrez, Coord x, Coord y, WinDrawOperation mod) Zkopíruje výřez obrázku z jednoho okna do druhého nebo v rámci toho samého Kap. 8 okna. Parametry • zdrojoveOkno – ovladač okna, ze kterého je výřez kopírován nebo NULL pro použití aktuálního okna • ciloveOkno - ovladač okna, do kterého je výřez kopírován nebo NULL pro použití aktuálního okna • zdrojVyrez – výřez, který udává souřadnice kopírované oblasti ve zdrojovém okně • x, y – souřadnice levého horního rohu výřezu v cílovém okně • mod – jeden z režimů kopírování typedef enum { winPaint, winErase, winMask, winInvert, winOverlay, winPaintInverse, winSwap } WinDrawOperation; WinHandle WinCreateOffscreenWindow (Coord sirka, Coord vyska, WindowFormatType format, UInt16 *chyba) Vytvoří skryté okno. Kap. 8 Parametry • sirka, vyska – šířka a výška okna v obrazových bodech • format – typ souřadnic a barevné rozlišení okna; použijte konstantu screenFormat • chyba – proměnná, do které bude uloženo číslo případné chyby Vrácená hodnota • ovladač nově vytvořeného okna nebo NULL v případě neúspěchu WinHandle WinCreateWindow (const RectangleType *hranice, FrameType ramecek, Boolean modalni, Boolean aktivni, UInt16 *chyba) Vytvoří nové okno na displeji. Kap. 8 Parametry • hranice – výřez, udávající pozici okna na displeji a jeho velikost • ramecek – typ rámečku, pro který bude rezervováno místo kolem okna (noFrame, simpleFrame, roundFrame, boldRoundFrame, popupFrame, dialogFrame) • modalni – true je-li okno dialog (v popředí) • aktivni – true může-li být okno aktivní (jako například políčka) • chyba – proměnná, do které bude uloženo číslo případné chyby Vrácená hodnota • ovladač nově vytvořeného okna nebo NULL v případě neúspěchu void WinDeleteWindow (WinHandle okno, Boolean smazat) Kap. 8 Vymaže okno, které jsme vytvořili funkcí WinCreateWindow nebo WinCreateOffscreenWindow Parametry • okno – ovladač okna, které rušíme • smazat – true pokud si přejeme smazat okno a rámeček kolem něj void WinDisplayToWindowPt (Coord *x, Coord *y) Převede souřadnice na displeji na souřadnice v rámci aktuálního okna Parametry • x, y – převáděné souřadnice
187
Kap. 8
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
void WinWindowToDisplayPt (Coord *x, Coord *y) Převede souřadnice v rámci aktuálního okna na absolutní souřadnice (na displeji) Parametry • x, y – převáděné souřadnice
Kap. 8
void WinDrawBitmap (BitmapPtr obrazek, Coord x, Coord y) Vykreslí na displeji rastrový obrázek. Kap. 8 Parametry • obrazek – ukazatel na datovou strukturu obrázku • x, y – souřadnice levého horního rohu void WinDrawChars (const Char *text, Int16 delka, Coord x, Coord y) void WinEraseChars (const Char * text, Int16 delka, Coord x, Coord y) void WinInvertChars (const Char * text, Int16 delka, Coord x, Coord y) void WinDrawInvertedChars(const Char * text, Int16 delka, Coord x, Coord y) Vykreslí v aktivním okně text černou barvou (WinDrawChars), bílou barvou Kap. 6,7,8 (WinEraseChars), bílý na černém pozadí (WinDrawInvertedChars) nebo invertuje obsah displeje (WinInvertChars). Parametry • text – řetězec, jehož obsah bude vykreslován • delka – počet znaků • x, y – souřadnice levého horního rohu textu void WinDrawLine (Coord x1, Coord y1, Coord x2, Coord y2) void WinDrawGrayLine (Coord x1, Coord y1, Coord x2, Coord y2) void WinEraseLine (Coord x1, Coord y1, Coord x2, Coord y2) void WinInvertLine (Coord x1, Coord y1, Coord x2, Coord y2) Kap. 8 Nakreslí v aktivním okně černou čáru (WinDrawLine), bílou čáru (WinEraseLine), tečkovanou čáru (WinDrawGrayLine) nebo invertuje obsah displeje (WinInvertLine) Parametry • x1, y1 – souřadnice počátku čáry • x2, y2 – souřadnice konce čáry void WinDrawRectangle (const RectangleType *r, UInt16 rohy) void WinEraseRectangle (const RectangleType *r, UInt16 rohy) void WinInvertRectangle (const RectangleType *r, UInt16 rohy) Kap. 8 Nakreslí v aktivním okně černý plný obdélník (WinDrawRectangle), bílý plný obdélník (WinEraseRectangle) nebo invertuje výřez displeje (WinInvertRectangle). Parametry • r – výřez, který bude vykreslen • rohy – poloměr zaoblení rohů (0 pro hrany) void WinDrawRectangleFrame (FrameType ram, const RectangleType *r) void WinDrawGrayRectangleFrame (FrameType ram, const RectangleType *r) void WinEraseRectangleFrame (FrameType ram, const RectangleType *r) void WinInvertRectangleFrame (FrameType ram, const RectangleType *r) Kap. 8 Nakreslí rámeček okolo výřezu; rámeček bude černý (WinDrawRectangleFrame), bílý (WinEraseRectangleFrame), tečkovaný (WinDrawGrayRectangleFrame) nebo inverzní (WinInvertRectangleFrame). Parametry • ram- typ rámečku (noFrame, simpleFrame, roundFrame, boldRoundFrame, popupFrame, dialogFrame) • r – výřez, který bude orámován
188
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
WinHandle WinGetDisplayWindow (void) Zjistí ovladač okna celého displeje. Kap. 8 Vrácená hodnota • ovladač základního okna, které zabírá celý displej WinHandle WinGetDrawWindow (void) Zjistí ovladač aktivního okna (okna ve kterém kreslíme) Vrácená hodnota • ovladač aktivního okna
Kap. 8
void WinGetWindowExtent (Coord *sirka, Coord *vyska) Zjistí rozměry aktivního okna. Kap. 8 Parametry • sirka – proměnná, do které bude uložena šířka aktivního okna v obrazových bodech • sirka – proměnná, do které bude uložena výška aktivního okna v obrazových bodech void WinResetClip (void) Zruší ořezávání.
Kap. 7,8
void WinSetClip (const RectangleType *vyrez) Nastaví ořezávání (nebude možné kreslit mimo oblast daného výřezu) Parametry • vyrez – výřez, ve kterém bude možné kreslit WinHandle WinSetDrawWindow (WinHandle noveOkno) Nastaví nové aktivní okno (okno ve kterém budeme kreslit). Parametry • noveOkno- ovladač okna, které bude aktivní Vrácená hodnota • ovladač okna, které bylo aktivní dotéď
189
Kap. 7,8
Kap. 8
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Příloha C: Příklady Tato kniha je doprovázena mnoha příklady jednoduchých aplikací; příklady si můžete stáhnout z internetu. Kompletní seznam příkladů, které jsou v knize použity, je uveden v následující tabulce: Adesář uvodsystem/1
Kapitola Soubor Popis příkladu kap_2.zip 2 Nejjednodušší aplikace pro PalmOS s odlišnou ikonou pro každé barevné rozlišení. kap_3.zip prvniaplikace 3 Nejjednodušší aplikace pro PalmOS, na které si vyzkoušíme překlad a ladění aplikací. kap_4.zip skupiny/1 4 Jednoduchá kontrola verze operačního systému. kap_4.zip Seznam systémových vlastností (features). skupiny/2 4 kap_4.zip Práce s čísly v pohyblivé desetinné čárce. skupiny/3 4 kap_4.zip Uložení stavu aplikace do databáze a jeho skupiny/4 4 načtení při opětovném spuštění aplikace kap_5.zip zakladui/1 5 Jednoduchý příklad definice složitého formuláře v souboru prostředků aplikace. kap_5.zip zakladui/2 5 Příklad přepínání mezi dvěma formuláři dotekem na displeji. kap_5.zip zakladui/3 5 Jednoduché volání dialogu. kap_6.zip Základy použití tlačítek, políček k zaškrtnutí a prvky/1 6 přepínačů ve formuláři a dialogu. kap_6.zip Opakovací tlačítka pro nastavení číselné prvky/2 6 hodnoty. kap_6.zip Tlačítka pro výběr textu a změna textu, který je prvky/3 6 v nich zobrazen. kap_6.zip Různé seznamy a práce s nimi. prvky/4 6 kap_6.zip Tlačítka pro výběr ze seznamu. prvky/5 6 kap_6.zip Vstup textu a použití opakovacích tlačítek ke prvky/6 6 stránkování. kap_6.zip Podobně jako předchozí, ale ke stránkování prvky/7 6 používáme posuvník. kap_7.zip Jednostránková tabulka s buňkami umožňujícími tabulky/1 7 výběr ze seznamu a se zobrazením data. kap_7.zip tabulky/2 7 20řádková tabulka s políčkem k zaškrtnutí, buňkami pro úpravu textu a uživatelsky kreslenými buňkami. kap_7.zip tabulky/3 7 Tabulka s posuvníkem a statickými políčky pro zobrazení textu a čísla. kap_8.zip cbgrafika/1 8 Nejjednodušší vykreslení černobílých čar a textu na displeji. kap_8.zip cbgrafika/2 8 Demonstrace různých písem, které je možné použít pro kreslení na displeji.
190
Úvod do programování PalmOS
cbgrafika/3
MUDr. Petr Lesný, 2003
8
kap_8.zip Výřezy, jejich posouvání, zvětšování a
8
kap_8.zip Příklad na ořezávání (clipping) a na seznam
zmenšování.
cbgrafika/4 cbgrafika/5
8
kap_8.zip
cbgrafika/6 cbgrafika/7
8 8
kap_8.zip kap_8.zip
cbgrafika/8
8
kap_8.zip
cbgrafika/9
8
kap_8.zip
cbgrafika/10
8
kap_8.zip
databaze/1
9
kap_9.zip
databaze/2
9
kap_9.zip
databaze/3
9
kap_9.zip
s uživatelsky vykreslovanými řádky, který jej používá. Dvě okna vykreslená na displeji, každé s jným orámováním. Nejjednodušší možné kreslení na displeji. Kreslení v okně a se zachováním plynulosti vykreslované čáry. Příklad pomalé animace s opakovaným vykreslováním vzoru. Předchozí příklad, kdy je pomocí skrytého okna dosaženo plynulé animace. Programové vykreslování rastrových obrázků na displeji a jejich vkládání do formuláře. Jednoduchá databáze, ve které je možné přidávat a mazat záznamy. Setříděná databáze propojená s tabulkou – umožňuje editaci záznamů na místě. Příklad databáze, která může být setříděná podle jednoho ze dvou kritérií.
191
Úvod do programování PalmOS
MUDr. Petr Lesný, 2003
Příloha D: Seznam prvků formuláře V této příloze (na následující straně) si můžete prohlédnout a případně i vytisknout referenční kartičky se seznamem definic prvků formuláře a výzvy. Vlastnosti v hranatých závorkách jsou nepovinné; kurzívou jsou uvedeny číselné hodnoty nebo identifikátory. Více se můžete dozvědět v dokumentaci k programu pilrc.
192
Úvod do programování PalmOS
FORM ID čísloProstředku AT ( x y w h ) [FRAME] [NOFRAME] [MODAL] [SAVEBEHIND] [NOSAVEBEHIND] [USABLE] [HELPID čísloProstředkuNápovědy] [DEFAULTBTNID identifikátorTlačítka] [MENUID čísloProstředkuMenu] BEGIN seznam objektů END
MUDr. Petr Lesný, 2003
ALERT ID [HELPID čísloProstředkuNápovědy] [DEFAULTBUTTON čísloTlačítka] [INFORMATION] [CONFIRMATION] [WARNING] [ERROR] BEGIN TITLE “Titulek“ MESSAGE “Zpráva ...“ BUTTONS “OK“ “Zruš“ ... END
TITLE
“Titulek“
BUTTON
“Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FRAME] [NOFRAME] [BOLDFRAME] [FONT cisloPisma]
PUSHBUTTON “Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FRAME] [NOFRAME] [BOLDFRAME] [FONT cisloPisma] CHECKBOX “Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FONT cisloPisma] [GROUP skupina] [CHECKED] POPUPTRIGGER “Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FONT cisloPisma] SELECTORTRIGGER “Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FONT cisloPisma] REPEATBUTTON „Text“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTANCHOR] [RIGHTANCHOR] [FRAME] [NOFRAME] [BOLDFRAME] [FONT cisloPisma] LABEL
„Text“ ID identifikace AT ( x y ) [USABLE] [NONUSABLE] [FONT cisloPisma]
FIELD
ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [LEFTALIGN] [RIGHTALIGN] [FONT cisloPisma] [EDITABLE] [NONEDITABLE] [UNDERLINED] [SINGLELINE] [MULTIPLELINES] [MAXCHARS počet] [AUTOSHIFT] [NUMERIC] [HASSCROLLBAR]
POPUPLIST LIST
ID identifikaceTlačítka identifikaceSeznamu
“Prvek 1“ “Prvek 2“ “Prvek 3“ ... “Prvek N“ ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [DISABLED] [VISIBLEITEMS počet] [FONT cisloPisma]
FORMBITMAP AT ( x y ) BITMAP identifikaceObrázku [USABLE] [NONUSABLE] TABLE
ID identifikace AT ( x y w h ) [ROWS početŘádků] [COLUMNS početSloupců] [COLUMNWIDTHS šířka1 šířka2 ... šířkaN ]
SCROLLBAR ID identifikace AT ( x y w h ) [USABLE] [NONUSABLE] [VALUE ] [MIN <MinValue.n>] [MAX <MaxValue.n>] [PAGESIZE <PageSize.n>] GRAFFITISTATEINDICATOR
AT ( x y )
193