Kurz1 - Kapitola7

17. června 2007 v 16:10 | http://www.sweb.cz/kurz_evt/ |  Programování pro WinCE

3. Hexadecimální prohlížeč

V několika následujících dílech si při postupném vytváření hexadecimálního prohlížeče souborů ukážeme některé odlišnosti specifické pro operační systém Windows CE. Vlastní program a jeho tvorba se velmi podobá verzi, kterou bychom tvořili pro Windows 95 a vyšší. Jsou zde však odchylky charakteristické pro systém kapesních počítačů. Těmito odchylkami se budeme zabývat podrobněji.

3.1 Kostra programu

V dnešním dílu si připravíme základ programu, který budeme dále zdokonalovat. Na úvod necháme AppWizard, aby za nás udělal "špinavou práci", - tj. vytvořil standardní tělo programu. Vytvořte nový projekt typu "WCE Application" pojmenovaný "HexaView". Jako typ zvolte opět "Hello World!" aplikaci.
Celý příklad programu bude ukazován na starší verzi (pro Windows CE 2.11). Snahou je, aby si mohli postup vyzkoušet i majitelé starších počítačů. Starší verze funguje i na Pocket PC, naopak to však neplatí. Případný zájemce si může tvořit program založený na Pocket PC aplikaci. V místech, kde se verze operačního systému odlišují, bude upozornění.
Pokud se vám podařilo aplikaci úspěšně vygenerovat a případně i přeložit a vyzkoušet, můžeme přikročit k jejím úpravám. Otevřete si soubor HexaView.cpp, většina úprav se bude odehrávat zde.
Vzhledem k tomu, že nebudeme vytvářet rozsáhlý projekt, všechny obecně potřebné hodnoty uložíme do globálních proměnných programu, případné lokální proměnné bude obsahovat pouze funkce WndProc.
Úpravy zahájíme přidáním globálních proměnných na místo v úvodu souboru, kde si již AppWizard vložil své globální proměnné:
#define    BUFSIZE 1024
PBYTE pBuffer = NULL; // Ukazatel na zacatek bufferu
INT nZobrByte = 0, // Ukazatel (index) odkud zobrazuju
nMaxPocet = 0, // Pocet Bytu v souboru nebo bufferu
nSloupce = 4, // Pocet zobrazovanych sloupcu na radku
nLinek = 15, // Pocet radku na obrazovce
nVyskaRadku = 16; // Vyska radku v obrazovych bodech
BOOL bSTextem = TRUE; // Zobrazovat s pridavnym textem?
RECT rctKlient; // Velikost klientske oblasti okna
Abychom mohli nějaká data zobrazovat, vytvoříme si zatím buffer o velikosti 1 kB. K tomu využijeme ukazatel pBuffer a máme připravenou konstantu velikosti BUFSIZE. Proměnné nMaxPocet a nZobrByte uschovávají velikost bufferu, resp. místo, odkud zobrazuji data. Následující 3 proměnné slouží k uchování hodnot pro zobrazování na displeji. Pro začátek jsou inicializovány na zkusmo odhadnuté hodnoty. Postupně budou při úpravě programu nahrazeny vypočítanými přesnými čísly. Logická proměnná bSTextem určuje, zda se zobrazují pouze holá hexadecimální čísla nebo je doplněn i obraz znaku odpovídajícího příslušné hodnotě. V poslední proměnné rctKlient budeme mít souřadnice klientské oblasti okna.
Nyní si doplníme několik lokálních proměnných na začátek funkce WndProc:
// Pro vykreslovani
int nByteLin, nZacRadku, i, j, y;
TCHAR cZnak, szOut[100], szTmp[100];
PBYTE pPomUkaz1,pPomUkaz2;
BYTE bZnak;
Jejich význam bude zřejmý při zpracování zpráv ve funkci WndProc. V tomto díle se dotkneme pouze tří zpráv: WM_CREATE, WM_PAINT a WM_DESTROY.
Jako první začneme se zprávou WM_CREATE. Při vytváření okna, je vhodná doba pro vytvoření bufferu s daty a inicializaci některých proměnných. Tato část programu je provizorní a při dalších úpravách ji budeme postupně rušit. Na konec zpracování zprávy WM_CREATE vložte:
   // Vytvorime si buffer pro zobrazovani
pBuffer = (BYTE*)LocalAlloc(LMEM_FIXED, BUFSIZE);
if (!pBuffer) {
MessageBox(NULL, TEXT("Nedostatek pameti!"),
TEXT("Chyba!"), MB_OK);
return 0;
}
// A zatim si ho naplnime hodnotami 0 az 255
for(i=0; i < BUFSIZE; i++)
*(pBuffer + i) = (BYTE)(i % 256);

// Zobrazovat zacneme od prvniho Byte
nZobrByte = 0;
nMaxPocet = BUFSIZE;
// Pro prvni pokus si nastavime horni cast klientske oblasti odhadem
rctKlient.top = 28;
Nejprve si v paměti alokujeme místo pro buffer se zobrazovanými daty a potom si tento buffer několikrát naplníme postupně vzrůstající posloupností čísel od 0 do 255.
Na závěr jsou nastaveny hodnoty některých proměnných. Globální proměnné jsou inicializovány již při své deklaraci, zde je nastavení přidáno pouze jako imitace otevření souboru a zpracování zprávy WM_PAINT, které doplníme později. Doporučuji po závěrečném přeložení a spuštění vyzkoušet změnu nZobrByte a rctKlient.top např. na 50 a porovnat zobrazená data.
Největší změnu zaznamená zpracování zprávy WM_PAINT. Její kód nahradíme následujícím kouskem programu.
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);

// Nastavime ukazatele, odkud zaciname zobrazovat
pPomUkaz1 = pPomUkaz2 = pBuffer + nZobrByte;
y = rctKlient.top;
// Zobrazime jednotlive radky na obrazovce
for (j=0; j < nLinek; j++) {
nZacRadku = (((nZobrByte + j*nSloupce) > nMaxPocet) ? nMaxPocet : (nZobrByte + j*nSloupce));
// Kolik Byte bude zobrazeno na tomto radku
nByteLin = (((nMaxPocet - nZacRadku) > nSloupce) ? nSloupce : (nMaxPocet - nZacRadku));
// Zobraz adresu prvniho Byte radku
wsprintf (szOut, TEXT ("%08X| "), nZacRadku);
// Zobraz jednotlive Byte
for (i = 0; i < nByteLin; i++) {
wsprintf (szTmp, TEXT ("%02X"), *pPomUkaz1++);
lstrcat (szOut, szTmp);
if ((i == 7) && (nByteLin>8))
lstrcat (szOut, TEXT ("."));
else
lstrcat (szOut, TEXT (" "));
}
// Doplnek mezer na radku, ktery neni uplny
if (nByteLin<nSloupce)
for (i = 0; i < nSloupce-nByteLin; i++) {
wsprintf (szTmp, TEXT (" "));
lstrcat (szOut, szTmp);
}
// Zde je pridano zobrazovani textu v prave polovine obrazovky
if (nByteLin) lstrcat (szOut, TEXT ("|"));
if (bSTextem)
for (i = 0; i < nByteLin; i++) {
bZnak=*pPomUkaz2++;
cZnak = bZnak>31 ? bZnak : 46;
wsprintf (szTmp, TEXT ("%c\0"), cZnak);
lstrcat (szOut, szTmp);
}
// ... a zbyva radek zobrazit
if (nByteLin) ExtTextOut(hdc, 0, y, 0, NULL, szOut, lstrlen(szOut), NULL);
y += nVyskaRadku;
}
EndPaint(hWnd, &ps);
break;
V programu jsou doplněny komentáře, není jej tedy asi nutné příliš rozebírat. Proměnné pPomUkaz slouží jako ukazatele na právě zobrazovaný Byte. První je pro číselné hodnoty, druhá pro textovou část. V proměnné y je uložena souřadnice, kde na obrazovce vykreslujeme řádek. K vlastnímu zobrazení dat použijeme funkci ExtTextOut, která je vhodná pro vypsání jednořádkového textu.
Na závěr ještě vložíme na začátek zpracovaní zprávy WM_DESTROY likvidaci námi vytvořeného bufferu:
   // Je slusne po sobe uklidit, takze zrusime pouzite prostredky
if (pBuffer) LocalFree(pBuffer);
A aby nás překladač zbytečně nevaroval, že lokální proměnná szHello není použita, můžeme ji zrušit.
Máte-li vše upraveno, můžete zkusit program přeložit a spustit. Po spuštění by se na obrazovce počítače mělo objevit něco podobného:

obr. 16 První verze programu "HexaView"
V rámci testu vytvořeného programu je možné postupně zkusit změnit hodnoty proměnných nSloupce (např. na 8), nLinek (10), bSTextem (FALSE), nVyskaRadku (20). Kdo si v AppWizardu založil aplikaci jako Pocket PC, nepotřebuje "přeskakovat" nahoře v okně nabídkový pruh a může snížit hodnotu rctKlient.top na 0. Pro kontrolu při dalších dílech doporučuji proměnné vrátit na původní hodnoty.

Co bychom si měli z této lekce zapamatovat?

  • Úpravou AppWizardem vytvořeného kódu získáme rychle základ programu.
  • Pro výpis jednořádkových textů je vhodná funkce ExtTextOut.
  • Při ukončení programu uvolníme použitou paměť.
 

Buď první, kdo ohodnotí tento článek.

Nový komentář

Přihlásit se
  Ještě nemáte vlastní web? Můžete si jej zdarma založit na Blog.cz.