17.1.2002
Zatím jsme se zabývali pouze takříkajíc čárovými grafickými objekty. V tomto pokračování se seznámíme s tím, jak kreslit plošné objekty a definovat vlastnosti jejich výplně pomocí štětců.
Geometrické útvary, které budeme dnes kreslit, budou mít definovány 2 typy "vlastností". Čáry tvořící jejich okraj, budou mít vlastnosti definované nám již známými pery a výplně štětci (brush), se kterými se seznámíme dnes. Princip použití štětců je stejný jako per. Nejdříve si jednou z příslušných funkcí vytvoříme objekt typu štětec (handle HBRUSH), ten pak vybereme pomocí funkce SelectObject do kontextu zařízení (HDC) a poté budou mít nakreslené grafické objekty výplň tvořenou aktuálně vybraným štětcem.
Nejjednodušším tvarem je obyčejný obdélník. Pokud chceme nakreslit obdélník, jehož okraj je kreslený aktuálně vybraným perem a výplň je tvořená aktuálně vybraným štětcem, použijeme funkci Rectangle:
BOOL Rectangle( HDC hdc, // handle kontextu zařízení int nLeftRect, // x-souřadnice levého horního rohu int nTopRect, // y-souřadnice levého horního rohu int nRightRect, // x-souřadnice pravého dolního rohu int nBottomRect // y-souřadnice pravého dolního rohu );
Dalším základním tvarem je elipsa nebo kružnice jako zvláštní případ elipsy, kterou kreslíme pomocí funkce Ellipse:
BOOL Ellipse( HDC hdc, // handle kontextu zařízení int nLeftRect, // x-souřadnice levého horního rohu opsaného obdélníka int nTopRect, // y-souřadnice int nRightRect, // x-souřadnice pravého dolního rohu opsaného obdélníka int nBottomRect // y-souřadnice );
Uveďme si zde ještě jeden plošný útvar kterým je obdélník (čtverec) se zaoblenými rohy, kreslený funkcí RoundRect:
BOOL RoundRect( HDC hdc, // handle kontextu zařízení int nLeftRect, // x-souřadnice levého horního rohu opsaného obdélníka int nTopRect, // y-souřadnice int nRightRect, // x-souřadnice pravého dolního rohu opsaného obdélníka int nBottomRect, // y-souřadnice int nWidth, // šířka elipsy tvořící zaoblené rohy int nHeight // výška elipsy tvořící zaoblené rohy );
Další plošné geometrické objekty, resp. funkce pro jejich kreslení jsou samozřejmě popsány v dokumentaci. Pro nás je nyní důležité seznámit se se štětci tvořícími výplň plošných objektů. Nejjednodušším případem je štětec tvořený jednou barvou, který vytvoříme funkcí CreateSolidBrush:
HBRUSH CreateSolidBrush( COLORREF crColor // definice barvy );
Handle typu HBRUSH vrácený touto funkcí pak vybereme již známou funkcí SelectObject do kontextu zařízení (HDC) a všechny další kreslené plošné objekty pak budou mít výplň tvořenou tímto štětcem. Ukážeme si příklad, ve kterém se současně ještě vrátíme k perům, přesněji řečeno k demonstraci stylu pera PS_INSIDEFRAME. Tento styl pera určuje, že pokud je kreslen obrazec, který definujeme opsaným obdélníkem (jako výše zmíněná elipsa/kružnice) a pero má šířku větší než 1 pixel, je obrazec nakreslen tak že se celý vejde dovnitř tohoto obdélníka. Bez tohoto stylu k okrajům obdélníka přiléhá střed čáry a tedy polovina šířky čáry pera je mimo tyto hranice. Podívejme se na příklad, který toto demonstruje:
V obou případech (jak uvidíte z výpisu kódu) je kružnice (kreslená funkcí Ellipse) definována stejným (rozměrově) opsaným obdélníkem. Rozdíl je ve vybraném peru. Pero použité pro levý obrázek má ve stylu příznak PS_INSIDEFRAME, tj je vytvořené takto:
hPen = CreatePen(PS_SOLID | PS_INSIDEFRAME, 20, 0x00FF8080);
Současně je ukázán příklad obdélníka kresleného systémovým černým perem a vyplněného systémovým bílým štětcem. Je to ukázka použítí funkce GetStockObject:
HGDIOBJ GetStockObject( int fnObject // typ objektu );
Touto funkcí můžeme získat již existující handle na některý ze systémových objektů. Jejich úplný seznam naleznete v dokumentaci této funkce. Zbytek kódu pak ukazuje vytvoření spojitého pera, a jeho použití jako výplň kružnice. Zde je tedy opis kódu, volaného z handleru zprávy WM_PAINT, realizujícího výše uvedený obrázek:
void InsideFrameDemo(HDC hdc) { HPEN hPen; HBRUSH hBrush; hPen = CreatePen(PS_SOLID | PS_INSIDEFRAME, 20, 0x00FF8080); hBrush = CreateSolidBrush(0x0080FFFF); SelectObject(hdc, GetStockObject(BLACK_PEN)); Rectangle(hdc, 15, 15, 115, 115); SelectObject(hdc, hPen); SelectObject(hdc, hBrush); Ellipse(hdc, 15, 15, 115, 115); SelectObject(hdc, GetStockObject(BLACK_PEN)); DeleteObject(hPen); SelectObject(hdc, GetStockObject(WHITE_BRUSH)); Rectangle(hdc, 140, 15, 240, 115); hPen = CreatePen(PS_SOLID, 20, 0x00FF8080); SelectObject(hdc, hPen); SelectObject(hdc, hBrush); Ellipse(hdc, 140, 15, 240, 115); SelectObject(hdc, GetStockObject(WHITE_PEN)); DeleteObject(hPen); DeleteObject(hBrush); }
Dále si ještě ukážeme příklad štětce, tvořeného mřížkou zvolené barvy a typu. K tomu nám slouží funkce CreateHatchBrush:
HBRUSH CreateHatchBrush( int fnStyle, // styl mřížky COLORREF clrref // barva čar mřížky );
Parametr fnStyle určuje typ mřízky, může mít jednu z hodnot, které jsou vypsány na následujícím obrázku, z něhož je nejlépe patrný jejich význam:
Kód toto realizující vypadá následovně:
void ShowBrush(HDC hdc, int Style, int x, int y, LPCTSTR lpText) { RECT rect; rect.left = x; rect.top = y; rect.right = rect.left + 140; rect.bottom = rect.top + 80; HBRUSH hb = CreateHatchBrush(Style, 0x00A00000); SelectObject(hdc, hb); FillRect(hdc, &rect, hb); DrawText(hdc, lpText, lstrlen(lpText), &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); DeleteObject(hb); } void OnPaint(HDC hdc) { ShowBrush(hdc, HS_BDIAGONAL, 10, 10, "HS_BDIAGONAL"); ShowBrush(hdc, HS_CROSS, 160, 10, "HS_CROSS"); ShowBrush(hdc, HS_DIAGCROSS, 310, 10, "HS_DIAGCROSS"); ShowBrush(hdc, HS_FDIAGONAL, 10, 100, "HS_FDIAGONAL"); ShowBrush(hdc, HS_HORIZONTAL, 160, 100, "HS_HORIZONTAL"); ShowBrush(hdc, HS_VERTICAL, 310, 100, "HS_VERTICAL"); }
Na závěr ještě ukázku použití funkce Rect a RoundRect, opět ve spojení s mřížkovaným štětcem a vlastním perem:
Kód tohoto kreslení:
void HatchBrush(HDC hdc) { HBRUSH hBrush, hbOld; HPEN hPen, hpOld; hBrush = CreateHatchBrush(HS_CROSS, 0x000000A0); hPen = CreatePen(PS_SOLID, 8, 0x00D00000); hbOld = (HBRUSH)SelectObject(hdc, hBrush); hpOld = (HPEN)SelectObject(hdc, hPen); Rectangle(hdc, 10,10, 180, 120); SelectObject(hdc, hbOld); DeleteObject(hBrush); hBrush = CreateHatchBrush(HS_DIAGCROSS, 0x0000A000); SelectObject(hdc, hBrush); RoundRect(hdc, 10,140, 180, 230, 50, 50); SelectObject(hdc, hpOld); DeleteObject(hPen); }
Doprovodný projekt je ke stažení zde: win_api_17.zip
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články