Win32 API - 5. díl - GDI
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama

Win32 API - 5. díl - GDIWin32 API - 5. díl - GDI

 

Win32 API - 5. díl - GDI

Google       Google       30. 8. 2006       25 542×

A je to tady, po dlouhé době jsem zpět a se mnou prichází code ;-). Dnes se podíváme na funkci TextOut a blíže si vysvětlíme GDI.

Reklama
Reklama

Děkuji za trpělivost i za žádosti o pokračování ;-).
Jak jsem slíbil v posledním dílu, chtěl bych nakousnout GDI; co to vlastně je a k čemu ho potřebujeme, v návaznosti na to doladit psaní textu do okna funkcí TextOut(…) a povědět něco o základech kreslení.

TextOut(…);

Když jsme v minulém díle mluvili o výpisu textu do okna, použili jsme funkci DrawText, která používá tzv. kontext zařízení (DC). Kontext zařízení je velmi důležitá součást GDI (o tom za chvíli). Daleko používanější funkcí je ale funkce TextOut(…);. Syntaxe funkce je:

TextOut(hdc, x, y, psText, iLength);

Prvním parametrem je handle kontextu zařízení, stejně tak jako u f-ce DrawText(…).

Atributy kontextu zařízení určují způsob zobrazení textu. Jedny z nich jsou například barva textu a barva pozadí textu. Barva textu je defaultně černá, díky čemuž nemusíme jeho barvy nutně měnit, pokud nechceme nějakou jinou než černou. Barva pozadí textu nemusí odpovídat s barvou pozadí definovanou ve třídě okna. Barva pozadí textu je prostor obklopující každý vypisovaný znak a nazývá se „obdélníček znaku“; defaultně je bílá.

Parametry x a y jsou souřadnice umístění textu v okně. Hodnota x je vodorovné umístění a y je umístění svislé. Levý horní roh prvního znaku je umístění hodnot x a y. Ve standardním kontextu zařízení je počátek souřadnic – tedy místo, kde x a y jsou nulové – levý horní roh klientské oblasti okna. Tedy když zadáme x=0 a y=0, tak se text začne vykreslovat v levém horním rohu. Takže x určuje vzdálenost od levé strany okna a y určuje vzdálenost od horní části okna.

Orientaci souřadnic GDI si vysvětlíme v části o GDI za chvíli.

Parametr psText je ukazatel na řetězec znaků a iLength je počet znaků v řetězci. Pokud psText ukazuje na řetězec UNICODE, tak počet bajtů v řetězci se rovná dvojnásobku hodnoty v iLength. Řetězec by neměl obsahovat žádné řídící znaky ASCII. Windows zobrazují tyto znaky jako rámečky nebo obdélníky. F-ce TextOut(…) neumí rozpoznat konec řetězce (nulový bajt), pro zjištění délky řetězce používá parametr iLength. Tato funkce je používanější nežli DrawText.

GDI

Už minule jsme nakousli základní objekt GDI, a to Kontext zařízení. GDI neboli Graphics Device Interface – Rozhranní grafického zařízení. Ve Windows je grafika spravována především většinou funkcemi, které jsou volány z dynamické knihovny GDI32.DLL. Knihovna volá rutiny v ovladačích grafiky popř. tiskáren. Základním cílem GDI je tzv. podpora grafiky nezávislé na zařízení. Z toho důvodu by Windows měly být schopné bez problému fungovat na jakémkoliv grafickém adaptéru, který podporují Windows.

Grafiky se rozdělují na tzv. rastrové a vektorové. Většina výstupních zařízení pro PC se řadí mezi rastrová zařízení. To znamená, že obraz zobrazují pomocí obdélníků z teček. Sem spadají grafické karty, jehličkové tiskárny a také laserové tiskárny. Vektorová zařízení vykreslují pomocí čar, ale to je záležitost plotteru a podobných zařízení a tím se opravdu zabývat nebudeme.

Nezávislost na zařízení GDI nám tedy umožňuje používat grafické funkce pro vykreslování, aniž bychom věděli, jaký grafický adaptér bude na cílovém PC, znali jeho hardware a věděli, jak s ním máme pracovat, o to se stará právě Windows prostřednictvím GDI a ovladačů grafiky, což byl v dřívějších dobách v DOSu problém z důvodu vysoké závislosti na grafickém zařízení.

Funkce GDI lze rozdělit do těchto částí:

Funkce pro nastavení a získání atributů kontextu zařízení
Např. pro nastavení barvy textu, bodu, čáry nebo výplně obdélníku. A také pro získání aktuálních informací. Z pravidla všechny funkce, které něco nastavují, začínají slovem „Set“ a k nim exituje ekvivalent „Get“ pro získání hodnoty kontextu.

Funkce, které pracují s objekty GDI
Mezi tyto objekty se řadí pera, štětce atd.

Typ grafiky, kterou chceme zobrazovat ať už na obrazovce, nebo na tiskárně, se dá rozdělit do těchto kategorií, které tvoří tzv. „stavební kameny“:

Čáry a křivky
Čáry jsou základem každého vektorového kreslícího systému. GDI podporuje přímé čáry, obdélníky, elipsy (a také podmnožiny elips, což jsou kružnice), oblouky, což jsou části křivek na obvodu elipsy a Bézierovy křivky.

Vyplněné oblasti
Když několik čar nebo křivek uzavře oblast, můžeme tuto oblast vyplnit barvou podle aktuálního štětce. Tento štětec může mít plnou barvu, vzorek nebo bitmapu.

Bitmapa
Což je obdélníkové pole bitů, které odpovídá bodům zobrazovacího zařízení. Bitmapa je základ pro rastrovou grafiku. Ta se obvykle používá k zobrazení složitých obrázků. Používají se také k zobrazení malých obrázků, které se mají velice rychle vykreslovat, jako např. ikona, kurzor nebo tlačítka panelu nástrojů. GDI zná 2 bitmapy. Starý, ale stále velice používaný, typ „na zařízení závislou bitmapu“ a novější „na zařízení nezávislou bitmapu“ – DIB, kterou lze ukládat na disk viz později.

Text
Typy písma atd. Prozatím se nebudeme blíže zabývat.

GDI lze dále dělit na další části:

Mapovací režimy a převody
Standardně se kreslí v bodových jednotkách, ale to neznamená, že tím to začíná a končí. Můžeme si nastavit jiný mapovací režim a kreslit třeba v palcích, milimetrech nebo jiných rozměrech. Novější Windows podporují i tzv. „Světovou transformaci“, která je vyjádřena maticí 3×3. Ta slouží ke skosení a natáčení grafických objektů. Kdo pracuje s DirectX nebo OpenGL, jistě ví, o co jde.

Metasoubory
Je sada příkazů GDI uložených v binární formě. Používají se hlavně pro přenos vektorových grafických obrazů prostřednictvím schránky.

Oblasti
Neboli Regiony jsou složité oblasti libovolného tvaru, které jsou definovány složitou booleovskou kombinací jednodušších oblastí. Používají se pro ohraničení, ořezávání a vyplňování.

Cesty
Také Paths. Je skupina přímých čar a křivek, které jsou interně uloženy v GDI. Používají se ke kreslení, vyplňování a ořezávání. Lze je také převádět na oblasti.

Ořezávání
Clipping slouží k vyhraničení určité části klientské oblasti. Může mít obdelníkový nebo jiný tvar.

Palety
Uživatelská paleta je obecně omezena na zobrazení 256 barev. Windows pro systémové využití používají z těchto barev pouze 20. Zbylých 236 barev můžete upravit pro zobrazování obrázků reálného světa, které jsou uloženy v bitmapách.

Tisk
Většina funkcionality pro kreslení na obrazovku se používá i pro výpis na tiskárnu. Tím se zatím moc zabývat nebudeme.

Tím bychom měli za sebou takový hrubý základ teorie GDI. Takže teď se můžeme pustit dál. Z teoretického pohledu lze postup kreslení popsat třemi jednoduchými kroky:

  1. získání handle kontextu zařízení
  2. kreslící funkce
  3. uvolnění kontextu

Tedy než začneme něco kreslit, musíme získat handle kontextu zařízení – DC.

Kontext zařízení si lze představit jako plátno, na které se kreslí. Analogicky, když chce malíř namalovat obraz, natáhne si nové plátno; když je s kresbou hotov, plátno sundá a popřípadě dá do rámu a má obraz. Stejně tak, když my chceme něco kreslit, musíme si vytvořit kontext, kreslíme a když jsme s prací hotovi, kontext uvolníme.

POZOR! Každý kontext, který vytvoříme, bychom měli zrušit!

DC nám určuje, kde si přejeme kreslit, můžeme vytvořit kontext na klientskou oblast, ale taky mimo ni.

Získání handle kontextu zařízení

Když získáme handle kontextu zařízení během zpracování nějaké zprávy, měli bychom před opuštěním procedury okna handle vrátit – kontext uvolnit. Poté, co jej uvolníme, přestane být handle platný, již není kontext přístupný.

Nejčastěji se získává a uvolňuje handle DC voláním funkcí BeginPaint a EndPaint při zpracování zprávy WM_PAINT.

Jejich hlavička:

BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);

EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint);

Funkce BeginPaint vrací platný handle kontextu zařízení. Parametr hWnd je již známý handle okna, pomocí kterého určujeme, kterého okna se bude kreslení týkat. lpPaint je struktura typu PAINTSTRUCT. Struktura PAINSTRUCT také obsahuje strukturu RECT (rectangle – obdélník) pojmenovanou rcPaint, která definuje obdélník ohraničující neplatnou oblast klientské oblasti okna. Pomocí hDC můžete tedy kreslit pouze uvnitř této oblasti. BeginPaint tuto oblast označí jako platnou.

HDC hDC;
PAINTSTRUCT &ps;

hDC = BeginPaint(habr, &ps);
//kreslení
EndPaint(hWnd,&ps);

Můžeme také získat handle DC při zpracování jiných zpráv než je WM_PAINT. Pak tedy použijeme funkci GetDC, ke které se volá ReleaseDC pro uvolnění kontextu.

GetDC(HWND hWnd);

ReleaseDC(HWND hWnd, HDC hDC);

Rozdíl těchto ekvivalentů spočívá v tom, že tyto funkce umožňuje kreslit do celé klientské oblasti okna. Ale zase neoznačí případnou neplatnou oblast v klientské oblasti za platnou.

hDC = GetDC(hWnd);
//code
ReleaseDC(hWnd, hDC);

Lze také získat hadle, který nám umožní kreslit po celém okně a ne jen v klientské oblasti, a to voláním funkce GetWindowDC:

GetWindowDC(HWND hWnd);

hDC = GetWindowDC(hWnd);
//code
ReleaseDC(hWnd, hDC);

Tento kontext umí pracovat s pruhem záhlaví okna, nabídkami, posuvníky a rámem vedle klientské oblasti. Používá se ale jen málokdy. Pokud budeme chtít takto pracovat, měli bychom ošetřit i zpracování zprávy WM_NCPAINT(noclient paint). To je zpráva, kterou Windows používají pro kreslení mimo klientskou oblast.

Tyto tři funkce pro získání kontextu DC získávají kontext spojený s konkrétním oknem na obrazovce. Existuje ještě speciální kontext, který umožňuje kreslit i mimo okno – po celém displeji. Jeho handle získáme voláním funkce CreateDC.

CreateDC(LPCTSTR pszDriver, LPCTSTR pszDevice, LPCTSTR pszOutput, CONST  DEVMODE*);

hDC = CreateDC(TEXT(“DISPLAY“),NULL,NULL,NULL);

Toto volání nám vrátí handle celého displeje.

Takový malý fígl: voláním funkce GetDC s parametrem NULL lze také získat handle cele obrazovky ;-). Lze také získat paměťový kontext zařízení, např. při práci s bitmapami voláním:

CreateCompatibleDC(HDC hDC);

A zrušíme ho voláním:

DeleteDC(HDC hDC);

A taky lze získat kontext metasouboru pro práci s metasoubory:

CreateMetaFile(LPCTSTR pszFileName);

I ten musíme zrušit voláním:

CloseMetaFile(HDC hDC);

To by bylo pro dnešek ohledně kontextu DC vše, ještě se koukneme, jak se kreslí body a čáry.

Když už umíme vytvořit ten správný DC, tak aby nám to k něčemu bylo, ukážeme si ty nejzákladnější grafické funkce. Budou to funkce SetPixel – GetPixel a MovetoEx – LineTo.

Body

Teoreticky všechny grafické výstupní zařízení potřebují pro kreslení funkce SetPixel a GetPixel. Například kreslení čáry se v podstatě realizuje voláním SetPixel několikrát za sebou s vhodně upravenými souřadnicemi x-y. Ale v praxi by funkce, která volá SetPixel mnohokrát za sebou, byla dost pomalá, proto se provádí kreslení složitějších grafických operací na úrovni ovladače, který už může navíc pro tyto účely mít své optimalizované kódy.

I když se funkce SetPixel a GetPixel obecně moc nepoužívají, měkdy můžou být užitečné.

Funkce SetPixel nastaví bod na pozici x-y na určitou barvu:

SetPixel(HDC hDC, int x, int y, COLORREF crColor);

První 3 parametry již určitě nemusím popisovat, za povšimnutí stoji akorát poslední parametr, což je typ COLORREF, který určuje barvu bodu. Pokud nemůže být barva nastavena, Windows nastaví barvu na nejbližší čistou barvu a tuto hodnotu vrátí. Barvu můžeme určit pomocí makra RGB(r,g,b);, kde jako jednotlivé parametry předáme celočíselné hodny 0-255, což je určení hodnoty barvy dané složky.

Funkce GetPixel vrací barvu bodu na dané pozici.

Čáry

Můžeme kreslit různé čáry, Windows má funkce tyto funkce pro kreslení čar:

LineTo – kreslí přímou čáru.
Polyline a PolylineTo – kreslí posloupnost přímých čar(lomenou čáru).
PolyPolyline – více lomených čar.
Arc – eliptické čáry.
PolyBezier a PolyBezierTo – Bézierovy křivky.
ArcTo AngleArc – eliptické čáry ve Windows NT.
PolyDraw – posloupnost spojených přímých čar a Bézierových křivek ve Windows NT.

Windows mají i další funkce pro kreslení čar, které navíc i vyplní uzavřenou oblast:

Rectangle – obdélník.
Elipse – elipsa.
RoundRect – obdélník se zaoblenými rohy.
Pie – část elipsy jako část koláčového grafu.
Chord – část elipsy určená tětivou.

Vzhled čar ovlivňuje 5 atributů kontextu zařízení:

Aktuální poloha pera – pouze u LineTo, PolylineTo, PolyBezierTo, ArcTo.
Pero.
Režim pozadí.
Barva pozadí.
Režim kreslení.

Dnes se podíváme na funkcí LineTo pro nakreslení přímé čáry.

Když chceme nakreslit přímou čáru, musíme ve skutečnosti zavolat funkce 2. Ještě dříve, než budeme volat LineTo, musíme zavolat funkci MoveToEx.

Pokud má PC nakreslit čáru, potřebuje k tomu v podstatě 4 parametry. První dva jsou souřadnice x-y počátečního bodu (odkud se kreslí čára) a zbylé dva jsou souřadnice x-y koncového bodu (kde čára končí). K nastavení počátku slouží funkce MoveToEx a k nastavení konce LineTo:

MoveToEx(HDC hDC, int xBeg, int yBeg, LPPOINT lp);
LineTo(HDC hDC, int xEnd, int yEnd);

Malý příklad:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        HMENU hMenu;
        HDC hDC;
        PAINTSTRUCT ps;
        switch(message)
        {
          case WM_COMMAND:
          hMenu=GetMenu(hWnd);
          switch(LOWORD(wParam))
           {
              case IDM_ABOUT:
                   MessageBox(hWnd,TEXT("Jsem informační zpráva"),TEXT("Systém"),
                   MB_OK|MB_ICONINFORMATION);
                   return 0;
           }
           return 0;
           case WM_PAINT:
                hDC=BeginPaint(hWnd, &ps);
                MoveToEx(hDC, 10, 10, NULL);
                LineTo(hDC, 100, 100);
                EndPaint(hWnd, &ps);
           return 0;      
         case WM_DESTROY:
          PostQuitMessage(0);
          return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

A to je pro dnešek všechno. Kdyby byl někdo nedočkavý, může vyzkoušet i ostatní funkce. Zkuste si pomocí těchto funkcí kreslit a třeba i složitější tvary, paskvily atd. např. V cyklu. Je to docela sranda, ale bacha na zacyklení, to je taky docela sranda ;-).

Příště budeme pokračovat v kreslení.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
Autor programuje v jazycích C++ a Delphi, mezi další koníčky patří kvantová fyzika.

Nové články

Obrázek ke článku Hackerský kongres přiveze v září do Prahy špičky světové kryptoanarchie

Hackerský kongres přiveze v září do Prahy špičky světové kryptoanarchie

Hackerský kongres HCPP16 pořádá od 30. září do 2. října nezisková organizace Paralelní Polis již potřetí, a to ve stejnojmenném bitcoinovém prostoru v pražských Holešovicích. Letos přiveze na třídenní konferenci přes 40 většinou zahraničních speakerů – lídrů z oblastí technologií, decentralizované ekonomiky, politických umění a aktivismu. Náměty jejich přednášek budou také hacking, kryptoměny, věda, svoboda nebo kryptoanarchie.

Reklama
Reklama
Obrázek ke článku ICT PRO školení zaměřené nejenom na ICT

ICT PRO školení zaměřené nejenom na ICT

Dovolte, abychom se představili. Jsme zaměstnanci společnosti ICT Pro, profesionálové v oblasti poskytování komplexních ICT služeb. Neboli služeb spojených s informačními a komunikačními technologiemi, které dnes - ve 21. století - tvoří  nedílnou součást běžného provozu všech moderních firem.

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý