Kurz1 - Kapitola6

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

2.7 Zpracování zprávy WM_PAINT

Posledním krokem, který v našem zjednodušeném zkoumání programu vytvořeném AppWizardem uděláme, bude "zrychlený rozbor" obsluhy zprávy WM_PAINT. Tato zpráva patří k nejdůležitějším zprávám programu pro Windows CE. Téměř každý program, který něco zobrazuje na displeji počítače s operačním systémem Windows, obsluhuje zprávu WM_PAINT. Operační systém ji programu předává vždy, když je potřeba překreslit klientskou část okna.
Mohlo by se zdát, že nakreslit něco na obrazovku by nemělo být tak velký problém. Skutečně není, musíme si však dát pozor na pravidla pro používání grafického rozhraní Windows.
Názorně si okno programu můžeme představit jako malířský stojan. Windows jsou víceúlohový systém, takže v počítači to vypadá jako v malířské třídě :-). I jiné programy mají své "stojany", na které si kreslí svoje obrázky. Zvláštním stojanem je pak např. tiskárna, o níž se musí podělit více žáků.
Podobně jako v malířské třídě by při nekontrolovaném provozu vznikl chaos, musí se i v programování pro Windows dodržovat jistá pravidla. Stojan, ke kterému se chceme dostat, se nazývá "kontext zařízení" (device context) a popisuje vlastnosti daného zařízení. Pokud zařízení chceme používat, musíme k němu získat právo přístupu, v našem případě už zmiňovaný handle. Po skončení malování pak toto právo musíme vrátit, aby si jej mohl vyžádat někdo jiný.
Kontext zařízení obsahuje řadu vlastností (atributů) popisujících aktuální stav a vlastnosti daného zařízení. Podobně jako u malířského stojanu můžeme mít připravený namočený štětec a pero, tak ve vlastnostech okna jsou nastaveny odpovídající atributy pro kreslení. Budeme-li chtít něco jiného (jinou barvu štětce), musíme si to připravit a změnit v kontextu zařízení. Slušností nebo zvykem je provedené změny po sobě uklízet (zvláště v rozsáhlejších programových projektech) a všechny vytvořené objekty, které zabírají paměť, zrušit.
Proto, abychom na displeji přístroje nakreslili objekt na správné místo, musíme kreslící funkci předat souřadnice požadovaného místa. Pro náš zjednodušený přehled můžeme plochu klientské oblasti považovat za obdélník s počátečním bodem v levém horním rohu a max. souřadnice je v pravém dolním rohu. Součástí klientské oblasti je i případný nabídkový pruh (CommandBar).

obr. 13 Souřadnice klientské oblasti

AppWizard pro obsluhu zprávy WM_PAINT vytvořil následující kód.
case WM_PAINT:
RECT rt;
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rt);
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
DrawText(hdc, szHello, _tcslen(szHello), &rt,
DT_SINGLELINE | DT_VCENTER | DT_CENTER);
EndPaint(hWnd, &ps);
break;
Vytvořená proměnná rt je typu RECT - obdélník. Je to struktura 4 čísel obsahujících hraniční souřadnice trojúhelníku (horní, dolní, levá a pravá). Voláním první funkce BeginPaint získáme handle kontextu zařízení hdc a tím i právo toto zařízení používat. Handle hdc je vyžadováno ve většině kreslících funkcí. Po skončení kreslení vrátíme kontext zařízení voláním funkce EndPaint. Pokud bychom to neudělali, obvykle to způsobí "zamrzání" programu.
Funkcí GetClientRect získáme do proměnné rt rozměry klientské části okna. Poznamenejme, že ve Windows CE klientská část zahrnuje i nabídkový pruh. Následující funkce LoadString přenese do řetězcové proměnné szHello textový řetězec z resources. K resources a jeho použití se dostaneme v některém z dalších dílů.
Vlastní vykreslení textu na displej zajišťuje funkce DrawText se svými parametry:
1. parametr - hdc - handle kontextu zařízení, na které budeme kreslit
2. parametr - szHello - vypisovaný text
3. parametr - počet znaků určených k vypsání (v našem případě je AppWizard nechal spočítat funkcí _tcslen()
4. parametr - &rt - obdélník, v jehož rámci se bude text vypisovat
5. parametr - způsob, jak zadaný text vykreslit (viz Help)

2.8 Úpravy programu

Úpravy programu zahájíme tím, že změníme vypisovaný pozdrav na české "Nazdar". Druhý parametr ve funkci DrawText nahradíme řetězcem TEXT("Nazdar") a třetí parametr změníme na hodnotu -1. Tato hodnota přikazuje funkci DrawText, aby si délku řetězce spočítala sama - jde o řetězec zakončený 0. Protože nebudeme řetězec natahovat do proměnné szHello z "resources", můžeme řádek s funkcí LoadString vymazat nebo uložit do komentáře.
Pokusíte-li se nyní přeložit upravený program, překladač vás patrně bude varovat, že proměnná szHello je nepoužitá (unreferenced local variable). Chyba to sice není, ale pro klid při překladu (přece si nenecháme nadávat :-)) je vhodné proměnnou szHello vymazat nebo vložit do komentáře. Po překladu a testu by se vám nápis na displeji měl změnit na český pozdrav.
Naším cílem bude na displeji zobrazit následující obrázek.

obr. 14 Cílová verze programu "Nazdar"
Další úpravy v programu můžeme zahájit tím, že v proceduře okna si doplníme nové proměnné potřebné k vykreslení ukázek kreslení grafiky. Doplníme dvakrát handle štětce a dvakrát handle pera. Také připojíme pole dvou bodů (POINT).
   HDC hdc;
int wmId, wmEvent;
PAINTSTRUCT ps;
// TCHAR szHello[MAX_LOADSTRING];
HBRUSH hbrOld, hbrMy;
HPEN hpenOld, hpenMy;
POINT pts[2];
Postupně tedy změníme zpracování zprávy WM_PAINT na následující zdrojový kód. Jako podklad je použit velký šedý obdélník menší na každé straně klientské oblasti o 15 bodů. Pro vykreslení použijeme štětec, který si vytvoříme pomocí funkce CreateSolidBrush. Štětec pak vložíme do kontextu zařízení prostřednictvím SelectObject a po použití funkcí Rectangle vrátíme starý štětec a námi vytvořený štětec, který již nebudeme potřebovat, zrušíme.
   RECT rt1, rt2;
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rt1);
// Velky sedy obdelnik na pozadi
rt1.top+=(CommandBar_Height(hwndCB)+15);
rt1.bottom-=15;
rt1.left+=15;
rt1.right-=15;
hbrMy = CreateSolidBrush(0x00808080);
hbrOld = (HBRUSH)SelectObject(hdc, hbrMy);
Rectangle(hdc, rt1.left, rt1.top, rt1.right, rt1.bottom);
SelectObject(hdc,hbrOld);
DeleteObject(hbrMy);
Máme připravené dvě proměnné typu RECT na rozdělení plochy displeje na dvě poloviny.
// Rozdeleni velkeho obdelniku na dva male - horni a dolni
rt2=rt1;
rt1.bottom=(rt1.bottom+rt1.top)/2;
rt2.top=rt1.bottom;
Uprostřed plochy je červená úsečka. Pro její nakreslení můžeme použít pero červené barvy o síle 4 body. Ve Windows 9x nebo Windows NT bychom pro úsečku pravděpodobně použili funkce MoveToEx a LineTo. Bohužel, Windows CE je nepodporují a tak použijeme funkci Polyline, která vyžaduje pole bodů, mezi nimiž má nakreslit úsečky a počet spojovaných bodů. V námi dříve vytvořeném poli musíme ovšem nejdříve nastavit souřadnice bodů. Po nakreslení přímky uklidíme vytvořené pero.
// Delici cara uprostred
hpenMy = CreatePen(PS_SOLID,4,0x000000FF);
hpenOld = (HPEN)SelectObject(hdc, hpenMy);
pts[0].x = rt1.left;
pts[0].y = rt1.bottom;
pts[1].x = rt1.right;
pts[1].y = rt1.bottom;
Polyline (hdc, pts, 2);
SelectObject(hdc,hpenOld);
DeleteObject(hpenMy);
Na závěr nám zbývá do dvou obdélníků rt1 a rt2 vypsat požadovaný text. Je použita výše uvedená funkce DrawText. Před vlastním výpisem textu jsou vždy v kontextu zařízení změněny atributy pro vykreslení textu (viz Help):
SetTextColor - mění barvu vykreslovaného textu
SetBkColor - mění barvu pozadí
SetBkMode - určuje režim kreslení textu.
// Vypis textu upravime podle potreby
SetBkColor(hdc,0x00FFFF00);
DrawText(hdc, TEXT("Nazdar"), -1, &rt1,
DT_SINGLELINE | DT_VCENTER | DT_CENTER);
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,0x0000FF00);
DrawText(hdc, TEXT("Windows CE!"), -1, &rt2,
DT_SINGLELINE | DT_VCENTER | DT_CENTER);
Zpracování zprávy WM_PAINT musí samozřejmě končit standardně.
   EndPaint(hWnd, &ps);
break;
Uvedené změny v programu vytvořeném pomocí AppWizardu by měly přinést stejný výsledek, jako je na obrázku č. 13.

2.8.1 Úprava pro Pocket PC

Pokud jste však zadali při zahájení projektu jako cílový program aplikaci pro PocketPC, pravděpodobně vám uvedené změny a úpravy programu nemusí fungovat. V programu připraveném pomocí AppWizardu po PocketPC je nabídkový pruh vytvořen jiným způsobem - pomocí funkce SHCreateMenuBar. Důsledkem je, že funkce CommandBar_Height nepracuje tak, jak bychom potřebovali. Funkci CommandBar_Height můžete sice zavolat, ale nevrátí se očekávaná výška "CommandBaru".
Nabídkový pruh je navíc umístěn na spodní části okna. Proto je nutné počítat s jeho výškou u položky .bottom obdélníku. Budete-li chtít vytvořit program speciálně pro PocketPC je zde uvedena jednoduchá úprava pro získání rozměrů šedého obdélníku. Je možné např. do proměnné rt2 získat pomocí funkce GetWindowRect souřadnice, na kterých se nachází CommandBar. Jeho šířku pak odečteme i s 15 body od spodní souřadnice klientské oblasti. Část výše uvedeného kódu je nutné nahradit následujícím:
// Velky sedy obdelnik na pozadi
GetWindowRect(hwndCB,&rt2);
rt1.top+=15;
rt1.bottom-=(rt2.bottom-rt2.top+15);
rt1.left+=15;
rt1.right-=15;
Takto upravený program pak pro Pocket PC přináší následující výsledek:

obr. 15 Verze programu "Nazdar" pro Pocket PC
Nyní již byste měli být schopni vytvořit jednoduchý standardní program pro Windows CE a měnit typ zpráv používaných programem a jejich zpracování. V příštím díle se začneme věnovat cílovému programu - hexadecimálnímu prohlížeči souborů.

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

  • Zpráva WM_PAINT je volána při požadavku vykreslení klientské oblasti okna.
  • Pro kreslení musíme získat kontext zařízení.
  • Změna kreslících parametrů se dosahuje změnou atributů kontextu zařízení.
  • Souřadnicová síť začíná v levém horním rohu bodem [0,0].
  • Po ukončení kreslení je nutné kontext zařízení opět uvolnit.
 

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.