Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 190. – GDI grafika

Jan Šindelář 22.6.2005

I když při programování běžných aplikací na kreslení příliš nenarazíme, určitě neuškodí povědět si pár základních věcí o tom, jak nakreslit jednoduché tvary s využitím GDI (resp. Delphi). Tento díl tedy bude opět určen spíše začátečníkům, kteří si o podobné téma píší.

Nejprve si musíme ujasnit, o jaké kreslení se bude jednat, protože není kreslení jako kreslení. Jednak je třeba říci, že se budeme pohybovat čistě v 2D oblasti. Druhé důležité upozornění se týká samotné metody kreslení. Už v titulku jste si mohli přečíst o GDI (Graphics Device Interface), což je standardní rozhraní, které využívá systém pro kreslení a můžeme ho použít i my. Kromě kreslení na obrazovku slouží i k výstupu na tiskárnu. Proč vlastně existuje? Aplikace nemohou pod Windows přistupovat ke grafickému hardware přímo a proto se musí využít toto rozhraní.

Naneštěstí je GDI snad nejpomalejší metodou pro kreslení vůbec a proto není v žádném případě vhodné použít toto rozhraní pro tvorbu her (nemluvě dokonce o 3D). Použijeme ho pouze pro jednoduché kreslení nenáročné grafiky a pro komplikovanější grafické hrátky je třeba použít např. OpenGL či DirectX (případně knihovny Delphi, které je využívají jako třeba DelphiX). Jejich popisem se však zabývat nebudeme, jelikož tato oblast by vydala spíše na samostatný seriál.

Než se pustíme do uměleckých výtvorů v podobě jednoduchým čar a obrazců, musíme mít nejprve prostor, kam kreslit a dále nástroj, kterým budeme kreslení provádět. Stejně jako v reálném světě i zde tedy budeme používat plátno a štětec (pero). Plátnem bude v našem případě objekt TCanvas, jež je součástí většiny běžných grafických komponent či tříd v Delphi, formulářem počínaje.

Kreslícím nástrojem bude jednak pero v podobě vlastnosti Pen daného plátna a nastavením jeho parametrů určujeme vzhled používaných čar u linek či orámování. Mezi nejběžnější vlastnosti patří zejména tloušťka, barva a styl čáry (tečkovaná, čárkovaná atd..). Dalším z nástrojů je pak Brush (štětec), s pomocí kterého lze nastavit vlastnosti pozadí či výplně grafických objektů. Za zmínku stojí i vlastnost Font, která určuje parametry vykreslovaných textů. S dalšími pojmy se případně seznámíme dále v textu.

Nyní už se vrhneme na samotné kreslení a začneme od jednoduchých čar. Zřejmě zbytečně (předpokládám, že i začínající programátor nejen v Delphi tuto skutečnost bude vědět), ale přesto pro jistotu připomínám, že souřadnice bodů jsou počítány od levého horního rohu obrazovky (plátna) směrem dolů vpravo, takže pro tentokrát zapomeňte na matematiku základní školy.

Pro samotné kreslení použijeme dvě funkce - MoveTo a LineTo. Pomyslné pero má počáteční pozici v bodě [0, 0], tedy v levém horním rohu. Funkcí MoveTo můžeme přesunout aktuální pozici "kurzoru" na zadané souřadnice. LineTo pak nakreslí čáru z aktuální pozice (zadané předem např. funkcí MoveTo a nebo prostě z místa, kde jsme naposledy skončili kreslení) do zadaných souřadnic. Tímto způsobem lze tedy kreslit jednoduché čáry, jejichž vlastnosti lze ovlivnit již zmiňovaným parametrem Pen.

Následující zdrojový kód nakreslí přímo na plochu formuláře tisíc čar, jejichž souřadnice a barva jsou generovány náhodně.

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
  Randomize;
  for i := 0 to 1000 do
  begin
    Canvas.Pen.Color := RGB(Random(256), Random(256), Random(256));
    Canvas.LineTo(Random(ClientWidth), Random(ClientHeight));
  end;
end;

Od jednoduchých čar přejděme ke složitějším útvarům - eliptické útvary, obdélníky či obdélníky se zakulacenými rohy. Zajímat nás tedy budou funkce Ellipse, FillRect, FloodFill, Rectangle či RoundRect. Na podrobný popis doporučuji nápovědu Delphi, ale z názvů funkcí lze tušit co umí. Za pozornost stojí rovněž funkce TextOut, která slouží pro vykreslení textu požadovaných vlastností na zadané souřadnice. Pro ukázku opět několik náhodných obdélníků vyplněných náhodnou barvou.

procedure TForm1.Button2Click(Sender: TObject);
var i, ShapeL, ShapeT: Integer;
begin
  for i := 0 to 10000 do
  begin
    Canvas.Brush.Color := RGB(Random(256), Random(256), Random(256));
    ShapeL := Random(ClientWidth);
    ShapeT := Random(ClientHeight);
    Canvas.Rectangle(ShapeL, ShapeT, ShapeL + Random(50), ShapeT + Random(50));
  end;
end;

Než se pustíme do dalšího kreslení v některém z příštích dílů, zbývá nám vyřešit jeden problém, který nemusel být na první pohled patrný. Pokud vykreslíme výše uvedeným způsobem nějaký objekt a okno aplikace poté překryjeme jiným oknem, přesuneme částečně mimo pracovní plochu a vrátíme zpět a nebo minimalizujeme a opět obnovíme, celý vykreslený objekt (a nebo jeho překrytá část) zmizí.

Proč tomu tak je? K pochopení celé věci si musíme vysvětlit rozdíl mezi "kreslením" (Drawing) a "malováním" (Painting). Doposud jsme pouze kreslili. V daný okamžik jsme na plátno formuláře nakreslili objekt. Ten vydržel pouze do té doby, dokud nebylo okno překryto (resp. překresleno). Jedná se o jakési dočasné kreslení. Pokud však chceme objekt zachovat, musíme přejít k "malování", což znamená, že kdykoliv je potřeba, objekt musí být znovu překreslen. Kdy tento okamžik nastane řeknou naší aplikaci přímo Windows prostřednictvím příslušné zprávy. To vyvolá následně událost OnPaint. A právě zde je místo, kde se postaráme o opětovné překreslení objektu.

Pokud tedy chceme kupříkladu "udržovat" uprostřed formuláře velký zelený obdélník, stačí do události OnPaint přidat tento kód:

procedure TForm1.FormPaint(Sender: TObject);
begin
  Canvas.Brush.Color := clLime;
  Canvas.Rectangle(10, 10, ClientWidth - 10, ClientHeight - 10);
end;

Tím dojde k překreslení objektu kdykoliv je potřeba. Problém by pochopitelně nastal, pokud bychom chtěli překreslovat naše náhodně vygenerované objekty z předchozích pokusů. V tom případě lze použít jednoduchou fintu prostřednictvím komponenty Image. Umístíme jí na formulář, nastavíme příslušné rozměry a barvu a náhodné objekty poté kreslíme na Canvas právě této komponenty zcela identickým postupem jako při kreslení na formulář. Komponenta Image se pak o překreslování postará sama.

A to je pro dnešek vše. O některých dalších možnostech kreslení si povíme zase někdy příště a jednoduchý ukázkový projekt si můžete opět stáhnout zde.