6.1.2002
Minulé pokračování jsme ukončili tím, že jsme si tím nejjednodušším způsobem vypsali do okna text tak, aby zůstal na svém místě po celou dobu běhu programu. V té souvislosti jsme si řekli obecně jak funguje překreslování okna v reakci na zprávu WM_PAINT. V tomto pokračování se naučíme o trochu více o funkcích GDI, tedy kreslení do okna, přičemž jak jsem již uvedl kreslením budu mít nadále na mysli také výstup textu. Nejdříve si řekneme o další funkci pro výpis textu, kterou je DrawText:int DrawText( HDC hDC, // handle kontextu zařízení LPCTSTR lpString, // text int nCount, // délka textu LPRECT lpRect, // obdélník UINT uFormat // volby );Tato funkce se liší od funkce TextOut především tím, že cílové souřadnice nejsou určeny souřadnicemi počátku textu, ale obdélníkem (struktura RECT), do kterého je text formátován způsobem určeným parametrem uFormat. Navíc je zde drobná výhoda v tom, že tato funkce akceptuje jako parametr nCount (délka textu) hodnotu -1, při které si sama spočítá celkovou délku zadaného textu a správně jej vypíše. Řekněme si o některých běžně používaných hodnotách, ze kterých se skládá parametr uFormat:
void centerText(HDC hdc) { RECT rect; GetClientRect(g_hwndMain, &rect); DrawText(hdc, "Text uprostřed okna", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }Tuto funkci si zavoláme z handleru zprávy WM_PAINT, který jsme si vytvořili již minule:
void OnWM_PAINT() { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(g_hwndMain, &ps); centerText(hdc); EndPaint(g_hwndMain, &ps); }Když nyní program spustíme, text bude uprostřed okna. Když budeme okno roztahovat za okraj, text se bude automaticky překreslovat tak aby byl stále uprostřed. Ale pozor! Automatické překreslování textu, resp. celé klientské oblasti okna je závislé na nastavení stylu třídy okna. Když se podíváte do funkce InitApp, kde jsme registrovali třídu, najdete tam tento řádek:
wc.style = CS_HREDRAW | CS_VREDRAW;Tyto vlastnosti ve stylu třídy určují, jak jejich název napovídá, zda se při horizontální či vertikální změně velikosti okna má překreslit celá klientská oblast. Když si zkusíte hodnotu wc.style nastavit na 0, zjistíte, že při roztažení okna zůstane text stále na místě do té doby, než bude jeho překreslení vyvoláno "standardním" způsobem, tedy například, skrytím a znovuodkrytím okna. Nyní provedeme změnu v nastavení pozadí okna. Nastavíme jeho barvu tak, aby odpovídala systémové barvě prostorových prvků. Změníme proto jeden řádek ve funkci InitApp takto:
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);Po spuštění programu zjistíme, že již to není to pravé ořechové. Bílý podklad textu nepůsobí příliš esteticky. Bývá zvykem, že texty se vypisují jako průhledné s podkladem odpovídajícím barvě, nebo i vzorku okna. Musíme se tedy naučit nastavovat barevné parametry textového výstupu. Je důležité vědět, že následující funkce, kterými se budeme zabývat, nastaví příslušnou vlastnost kontextu zařízení a nikoli textu nebo jen některé funkci. Znamená to, že po nastavení některé z vlastností bude tato vlastnost aplikována na všechny následné volání funkcí pro výstup textu (zatím používáme 2 - TextOut a DrawText). Na druhou stranu toto nastavení se "ztratí", jakmile ukončíme kreslení funkcí EndPaint. Nyní již ke třem základním funkcím, nastavujícím barvy textového výstupu. Nastavení barvy písma:
COLORREF SetTextColor( HDC hdc, // handle kontextu zařízení COLORREF crColor // barva textu );Nastavení barvy pozadí textu:
COLORREF SetBkColor( HDC hdc, // handle kontextu zařízení COLORREF crColor // barva pozadí );Nastavení průhlednosti textu:
COLORREF SetBkMode( HDC hdc, // handle kontextu zařízení int iBkMode // průhlednost );Hodnota crColor použitá u prvních 2 funkcí je 32-bitové číslo, v jehož nejnižší BYTE obsahuje hodnotu červené složky barvy, následující zelené a modré. Nejvyšší BYTE musí být 0. V tomto seriálu se postupně dostaneme k funkcím, resp. makrům, umožňujícím pohodlnější práci s typem COLORREF. Běžně se požívá hexadecimální zápis ve tvaru 0x00BBGGRR, kde BB, GG a RR jsou ony barevné složky v rozsahu 0x00 - 0xFF. Parametr iBkMode ve funkci SetBkMode může nabývat 2 předdefinovaných hodnot:
void pozadiTextu(HDC hdc) { TCHAR chText[100]; lstrcpy(chText, TEXT("Modrá barva písma...")); SetTextColor(hdc, 0x00FF0000); // modrý text TextOut(hdc, 10, 10, chText, lstrlen(chText)); SetBkColor(hdc, 0x0000FFFF); // žluté pozadí lstrcpy(chText, TEXT("Změníme pozadí, písmo zůstává...")); TextOut(hdc, 10, 40, chText, lstrlen(chText)); lstrcpy(chText, TEXT("Konečně máme průhledný text !!!")); SetBkMode(hdc, TRANSPARENT); // průhlednost textu TextOut(hdc, 10, 70, chText, lstrlen(chText)); lstrcpy(chText, TEXT("Pokračování příště ...")); SetTextColor(hdc, 0x000000FF); // modrý text TextOut(hdc, 10, 110, chText, lstrlen(chText)); }Doprovodný projekt (Visual C++ 6) je ke stažení zde: win_api_6.zip
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články