× Aktuálně z oboru

Programátoři po celém světě dnes slaví Den programátorů [ clanek/2018091300-programatori-po-celem-svete-dnes-slavi-den-programatoru/ ]
Celá zprávička [ clanek/2018091300-programatori-po-celem-svete-dnes-slavi-den-programatoru/ ]

Win32 API - Díl 6. GDI - Pokračování

[ http://programujte.com/profil/20356-kamil-skala/ ]Google [ ?rel=author ]       [ http://programujte.com/profil/2331-linda-erlichova/ ]Google [ ?rel=author ]       30. 1. 2007       28 446×

A jedeme dál. Minule jsme se začali trochu zajímat o GDI a kreslení čar, dnes si probereme křivky.

Tak se opět vracím k našemu seriálu o WinApi.
Minule jsme začali kapitolu o kreslení čar, dnes v ní chci pokračovat a naučit vás, jak kreslit i jiné čáry.

Když jsme minule chtěli nakreslit přímou čáru, použili jsme na to dvě funkce. Funkci MoveToEx , která nám vyznačila počáteční bod, od kterého se čára kreslí, a funkci LineTo, která zase označuje konečný bod, kde kreslení čáry končí.

Když bysme chtěli například nakreslit obdélník, museli bychom použít několik volání LineTo a upravit souřadnice tak, aby výsledný efekt splňoval naše požadavky. Jednodušším způsobem je použití funkce Polyline. Máme-li pole bodů, které chceme propojit, je ideálním řešením použití Polyline a pospojovat tak body čarami. Takto velice jednoduše nakreslíme zmíněný obdélník. Je samozřejmostí, že pomocí této funkce lze kreslit i jiné obrazce skládající se z čar a to daleko složitější. Tato funkce nepoužívá a ani nemění aktuální polohu. Funkce PolylineTo je trochu jiná. Používá aktuální pozici pro výchozí bod a nastavuje aktuální polohu na polohu koncového bodu poslední vykreslené čáry. Polyline i PolylineTo lze použít pro vykreslování několika čar, jejich opravdová síla tkví v kreslení opravdu složitých křivek. Mám na mysli stovky či tisíce velmi malých čárek. Jsou-li tyto čárky dostatečně krátké a je jich dost, budou dohromady vypadat jako křivka.


Polyline(hdc, apt, count);
PolylineTo(hdc, apt, count);

První parametr již dobře známe, nebudu ho popisovat. Druhý parametr je pole struktur na strukturu POINT. Třetí parametr je počet bodů. Tahle hodnota se dá i vypočítat podle jednoduchého vzorce:

sizeof(apt)/sizeof(POINT).

Příklad: Jedná se o známý příklad pro kreslení sinusoidy:


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static int cxClient, cyClient;     
        HDC hDC;
        int i;
        PAINTSTRUCT ps;
        POINT apt[NUM];

        switch(message)
        {
          case WM_SIZE:
               cxClient = LOWORD(lParam);
               cyClient = HIWORD(lParam);
               return 0;

           case WM_PAINT:
                hDC=BeginPaint(hWnd, &ps);
                MoveToEx(hDC, 0, cyClient/2, NULL);
                LineTo(hDC, cxClient, cyClient/2);

             for(i=0;i<1000;i++)
             {
                 apt[i].x = i*cxClient/NUM;
                 apt[i].y = (int) (cyClient/2*(1-sin(TWOPI * i/NUM)));
             }
             Polyline(hDC, apt, NUM);      
             EndPaint(hWnd, &ps);
             return 0;      
         case WM_DESTROY:
           PostQuitMessage(0);
           return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}	

Za include dejte do define tyto definice konstant:
#define NUM 1000
#define TWOPI 2*3.14159)

Zde vyvstává skutečná výhoda Polyline oproti LineTo. Polyline je implementována na úrovni ovladače zařízení, tudíž je rychlejší, což má při tak značném volání v cyklu svůj význam. Muselo by se 1000x volat LineTo!

Rectangle

Rectangle, Ellipse, RoundRect, Chord a Pie, všechny tyto funkce spojuje to, že jsou postaveny na obdélníkovém „ohraničujícím“ rámu. Definujeme souřadnice rámu, který objekt obklopuje a Windows objekt vykreslí uvnitř rámu. Také vyplní vzniklou uzavřenou oblast barvou.

Nejjednodušší z těchto funkcí je obdélník:
Rectangle(hdc, xLeft, yTop, xRight, yBottom);

xLeft, yTop je levý horní roh obdélníku a xRight, yBottom je pravý dolní roh obdélníku. Strany obdélníku sou vždy rovnoběžné s vertikální a horizontální stranou displeje. Abyste se dobře vyznali v souřadnicích a v tom, jak Windows kreslí tyto a jiné složitější tvary, je dobré na display pohlížet jako na mřížku, kde každý bod je v buňce mřížky. Do mřížky se nakreslí pomyslný ohraničující rám a do něj se potom nakreslí obdélník. Oblast oddělující obdélník je od horní a levé strany klientské oblasti 1 bod široká. Takto kreslí Windows.

Rectangle vyplňuje také uzavřenou oblast vybranou barvou. Jelikož je standardní štětec bílé barvy, není výplň vidět a ani není zřejmé, že se vůbec oblast vyplňuje.

Ellipse

Funkce Ellipse má shodné parametry jako funkce Rectangle.

Ellipse(hdc, xLeft, yTop, xRight, yBottom);
Platí zde to samé co pro obdélník.

RoundRect

Jedná se o funkci pro kreslení obdélníků se zaoblenými rohy. Využívá stejný ohraničující rám jako Rectangle nebo Ellipse, ale očekává další dva parametry:

RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse);

Pro kreslení malých zaoblených rohů se používá malé elipsy. Šířka elipsy je xCornerEllipse a výška elipsy je yCornerEllipse. Zaoblení rohů je výraznější pro větší hodnoty xCornerEllipse a yCornerEllipse. Pokud se xCornerEllipse rovná rozdílu mezi xLeft a xRight a yCornerEllipse se rovná rozdílu mezi yTop a yBottom, pak funkce RoundRect nakreslí elipsu.

Funkce Arc, Chord a Pie mají shodné parametry:
Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
Chord(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);

Windows používají pomyslnou čáru pro spojení bodu (xStart, yStart) se středem elipsy. V místě, kde čára protíná elipsu, se začne kreslit oblouk po obvodu elipsy ve směru hodinových ručiček. Windows také používají pomyslnou čáru pro spojení bodu (xEnd, yEnd) se středem elipsy. V bodě, ve kterém čára protíná elipsu, Windows kreslení oblouku ukončí. U funkce Arc je oblouk eliptická čára a ne vyplněná oblast. U funkce Chord Windows spojí krajní body oblouku. U funkce Pie spojí každý krajní bod oblouku se středem elipsy. Vnitřní plochy tětivy a koláčového klínu budou vyplněny aktuálním štětcem.

Beziérovy křivky

Jednoduché beziérovy křivky jsou definovány 4mi body – 2 body koncové a 2 body řídící. Konce křivky jsou určeny 2mi koncovými body. Řídící body vystupují jako magnety pro přetahování křivky od přímé spojnice mezi dvěma koncovými body. V podstatě vezmete přímku, zatáhnete za ní a zkřivíte její tvar určitým směrem. Jedná se tedy o dnes již téměř povinnou výbavu každého modelovacího software. Pro nakreslení jedné nebo více spojených Beziérových křivek používáme funkce:

PolyBezier(hdc, apt, iCount);
PolyBezierTo(hdc, apt, iCount);

V obou případech je apt pole struktur POINT, ale to už známe. První 4 body určují(v tomto pořadí) počáteční bod, první řídící bod, druhý řídící bod a koncový bod Beziérovy křivky. Každá další Beziérova křivka vyžaduje pouze 3 body, protože počáteční bod druhé Beziérovy křivky je současně koncovým bodem předcházející Beziérovy křivky. Parametr iCount má vždy hodnotu 1+trojnásobek spojených křivek, které chceme kreslit.

Funkce PolyBezierTo používá aktuální polohu prvního počátečního bodu. A tedy první a každá další křivka potřebuje pouze 3 body. Když se funkce dokončí, bude aktuální poloha nastavena na poslední koncový bod.

Pozn.: Když kreslíte posloupnost Beziérových křivek, bude spojovací bod hladký pouze v případě, že druhý řídící bod první Beziérovy křivky, koncový bod první Beziérovy křivky(což je také počáteční bod následující Beziérovy křivky) a první řídící bod následující Beziérovy křivky budou kolineární; to znamená, že leží v jedné přímé čáře.

Příště: Pera a štětce.

Článek stažen z webu Programujte.com [ http://programujte.com/clanek/2006103101-win32-api-dil-6-gdi-pokracovani/ ].