Umíme to s Delphi, 16. díl – grafika v Delphi

Tento díl seriálu je zaměřen na popis aktivní práce s grafikou v Delphi, tedy jak kreslit na formulář. Než se podíváme na ryze grafické prvky a komponenty, řekneme si několik rozšiřujících informací o používání myši.
Tento díl seriálu je zaměřen na popis aktivní práce s grafikou v Delphi, tedy jak kreslit na formulář. Než se podíváme na ryze grafické prvky a komponenty, řekneme si několik rozšiřujících informací o používání myši.

Práce s myší – události OnMouseDown, OnMouseUp, OnMouseMove

Možná si říkáte, že k myši není co dodat; po přečtení této kapitoly však možná změníte názor, neboť uvidíte, že dosud jsme využili jen velmi malou část možností, které Delphi v souvislosti s myší nabízejí.

V pátém díle seriálu jsme popisovali nejčastější události. Zmínili jsme se také o událostech OnMouseDown, OnMouseUp a OnMouseMove. Jsou generovány v okamžiku, kdy uživatel stiskne či uvolní tlačítko myši, resp. pohne kurzorem myši. Parametry těchto tří událostí jsou podobné (jen události OnMouseMove z pochopitelných důvodů chybí parametr specifikující stisknuté tlačítko). Podívejme se, jaké rozšiřující možnosti tyto události přináší (demonstrujeme si to na události OnMouseDown):

procedure TForm.FormMouseDown(
  Sender: TObject;
  Button: TMouseButton;
  Shift: TShiftState;
  X, Y: Integer);

Parametr Sender má obvyklý význam (je to odesílatel). Další parametry jsou však velmi mocné.

Parametr Button

Parametr Button říká, které tlačítko bylo stisknuto (stiskem kterého tlačítka byla událost vyvolána). Možné hodnoty:

  • mbLeft – levé tlačítko myši,
  • mbRight – pravé tlačítko myši,
  • mbCenter – prostřední tlačítko myši,
Příklad: testujeme, vznikla-li událost stiskem pravého tlačítka myši:

if Button = mbRight then
  ShowMessage(`Pravé tlačítko`);

Parametr Shift

Parametr Shift udává stav některých kláves v okamžiku vzniku události. Kromě toho také indikuje stav vlastních tlačítek myši. Tento parametr je typu množina, protože může být zároveň platných více hodnot. Možné hodnoty:

  • ssShift – byla stisknuta klávesa Shift,
  • ssAlt – byla stisknuta klávesa Alt,
  • ssCtrl – byla stisknuta klávesa Ctrl,
  • ssLeft – bylo stisknuto levé tlačítko myši,
  • ssRight – bylo stisknuto pravé tlačítko myši,
  • ssMiddle – bylo stisknuto prostřední tlačítko myši,
  • ssDouble – došlo k dvojitému kliknutí myši.

Příklad: testujeme, vznikla-li událost dvojitým kliknutím za současného stisku klávesy Shift:

if (ssShift in Shift) and (ssDouble in Shift) then
  ShowMessage(`Shift + dvojklik`);

Parametry X, Y

Parametry X, Y indikují souřadnice kurzoru myši v klientské oblasti odesílatele (komponenty, z níž událost vzešla). Souřadnice jsou udávány v pixelech a vztahují se k levému hornímu rohu klientské oblasti odesílatele. Klientskou oblastí je myšlena „vnitřní oblast“ komponenty, tj. oblast bez hlavního menu, posuvných lišt, apod.

Příklad: vypíšeme souřadnice, na kterých uživatel klikl na formulář:

ShowMessage(Format(`Souřadnice X = %d, souřadnice Y = %d`, [X, Y]));

Kreslení v Delphi – základní informace

Delphi přináší základní objekt určený ke kreslení – plátno (třída TCanvas). Představte si okno (formulář) jako prázdnou plochu, plátno, Stejně jako malíři kreslí na plátna své nejrůznější výtvory, také my kreslíme na své plátno (tedy Canvas) všechny objekty v aplikaci – tlačítka, kurzory, editační pole… Každý z těchto objektů je pouhým shlukem různobarevných pixelů, které jsou vhodně poskládány vedle sebe.

Každý malíř potřebuje štětec, paletu a barvy. My budeme také potřebovat nějaké analogie těchto nástrojů. Ve Windows samozřejmě tyto nástroje existují a jsou dostupné prostřednictvím tzv. Graphic Device Interface (GDI, rozhraní grafických zařízení). Vše, co vidíte na své obrazovce při práci s Windows, je nakresleno pomocí GDI. Pokud byste chtěli, můžete sami přímo používat nástroje, funkce a metody GDI. Není to ovšem příliš jednoduché a zřejmě by trvalo určitou dobu, než byste se naučili programovat v GDI opravdu efektivně.

Naštěstí Delphi opět přináší nástroj, který práci s GDI výrazně zjednodušuje. Tímto nástrojem není nic jiného než právě třída TCanvas, který zapouzdřuje mnoho nástrojů a funkcí GDI.

Třída TCanvas – plátno

Objekt Canvas je vlastností mnoha grafických komponent v Delphi. Používá se jako (abstraktní) kreslicí plocha pro ty komponenty a objekty, které vykreslují svůj vzhled samy. Standardní komponenty jako např. editační okno nebo seznam nevyžadují použití Canvasu, neboť jsou kresleny přímo operačním systémem Windows.

Canvas má několik vlastností, které umožňují podrobné nastavení výsledného vzhledu. Popíšeme si je v následujících podkapitolách. Všechny příklady v následujícím textu budou pracovat s plátnem formuláře (budou tedy kreslit přímo na plochu formuláře). Plátno je ale dostupné i v dalších komponentách (např. Image) a třídách (např. TBitmap).

Vlastnost Handle

Nejprve se podíváme na vlastnost Handle objektu Canvas. Handle je manipulátor tzv. kontextu zařízení (Device Context, DC) Windows pro dané plátno. Handle si představte jako jednoznačný (číselný) identifikátor, tedy číselný údaj,který jednoznačně určuje, identifikuje daný objekt. Ve Windows má snad každý objekt, každé okno svůj handle. Delphi své vývojáře před používáním handle důsledně chrání. Tuto vlastnost tedy nebudete potřebovat při používání standardních funkcí Delphi pro kreslení na plátno, nicméně jakmile budete chtít rozšířit možnosti standardního plátna užitím některé funkce Windows GDI, budete se vám znalost handle hodit.

Naštěstí práce s vlastností handle je v Delphi mimořádně jednoduchá, protože se zpravidla omezuje jen na jeho předání do parametru funkci Windows GDI, kterou chcete použít.

Jako příklad uvedeme změnu transparentnosti šrafování. Pokud chceme vyšrafovat určitou plochu, používáme k tomu tzv. štětec, jeho styly a metodu Rectangle (je to jen jedna z možností). Standardně se toto šrafování provádí transparentně, tedy tak, že zůstávají viditelné objekty pod šrafováním. Chceme-li nastavit netransparentní šrafování, můžeme použít funkci Windows GDI SetBkMode, která ovšem vyžaduje handle kontextu zařízení. Celá akce bude provedena v rámci ošetření události OnClick tlačítka btnSrafy formuláře frmHlavni:

procedure TfrmHlavni.btnSrafyClick(Sender: TObject);
begin
  with frmHlavni.Canvas do begin
    Brush.Style := bsCross;
    Brush.Color := clRed;
    SetBkMode(Handle, OPAQUE);
    Rectangle(0, 0, 100, 100);
  end;
end;

Poznámka: funkce SetBkMode vyžaduje kromě handle kontextu zařízení už jen konstantu říkající, bude-li pozadí transparentní (TRANSPARENT) nebo neprůhledné (OPAQUE).

Vlastnost Brush

Vlastnost Brush (jejíž hodnota je typu TBrush) zapouzdřuje štětec Windows. Nastavením vlastnosti Brush měníte barvu a vzor pro vyplňování grafických tvarů a pozadí. Popíšeme si vlastnosti štětce:

Bitmap

Specifikuje (externí) soubor s bitmapou, která bude definovat vzor štětce. Následující příklad načte bitmapu ze souboru Mraky.bmp na disku a přiřadí ji do štětce plátna formuláře. Poté aktuálním štětcem (tedy touto bitmapou) vyplní celý formulář (obdélník o velikosti formuláře). Formulář se jmenuje frmHlavni a celá akce je programována jako ošetření události OnClick tlačítka btnNactiBMP. Výsledek ukazuje obrázek níže.

procedure TfrmHlavni.btnNactiBMPClick(Sender: TObject);
var
  Bitmap: TBitmap;

begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.LoadFromFile(`Mraky.bmp`);
    Canvas.Brush.Bitmap := Bitmap;
    Canvas.FillRect(Rect(0, 0, Width, Height));
  finally
    Canvas.Brush.Bitmap := nil;
    Bitmap.Free;
  end;

end;

Všimněte si, že před atributy formuláře (Canvas, Width…) není uvedeno jeho jméno (frmHlavni). Je to proto, že v metodě třídy není nutné uvádět jméno třídy při práci s jejími atributy. Zápisy Width a frmHlavni.Width jsou tak zcela ekvivalentní.

Color

Nastavuje barvu štětce. Poznámka: je-li hodnota vlastnost Style = bsClear, nemá nastavení vlastnosti Color žádný vliv.

Handle

Handle štětce používaný systémem Windows.

Style

Nastavení vzoru štětce, tedy šrafovacího stylu. Možné hodnoty ukazuje následující tabulka..

Styl Popis Ukázka
bsSolid Úplná výplň
blClear Prázdná (žádná) výplň
bsBDiagonal Šrafování zleva shora doprava dolů pod úhlem 45°
bsFDiagonal Šrafování zleva zdola doprava nahoru pod úhlem 45°
bsCross Horizontální a vertikální šrafování (mřížka)
bsDiagCross Mřížka pod úhlem 45°
BsHorizontal Horizontální šrafování
bsVertical Vertikální šrafování

Vlastnost Font

Vlastnost plátna Font je typu TFont, a proto informace uvedené v této kapitole můžete použít při nastavování libovolného fontu (např. fontu písma komponenty RichEdit, komponenty Memo, apod.). Třída TFont je zapouzdřena do mnoha komponent a objektů, a také do objektu Canvas. Ve spolupráci se standardním dialogem pro výběr fontu (FontDialog) je nastavování vlastností písma otázkou několika okamžiků.

V rámci dílu 12, ve kterém jsme popisovali dialog FontDialog, jsme si ukázali, jak přiřadit změnit font pomocí tohoto dialogu. Nyní si ukážeme některé podrobnosti a také způsob, jak měnit vlastnosti fontu „ručně“ a po částech.

Základní metodou pro napsání textu přímo na plátno je Canvas.TextOut.

Následující příklad vypíše nápis do levého horního roku formuláře (formulář se jmenuje frmHlavni):

frmHlavni.Canvas.TextOut(5, 5, `Toto je výstup metody TextOut.`); Barva fontu – vlastnost Font.Color

Nastavení vlastnosti Color se provádí stejně jako nastavování barvy jakéhokoliv jiného prvku v Delphi . Všimněte si pouze toho, že nastavení barvy fontu neříká nic o pozadí tohoto fontu, takže pokud nezměníte nastavení pozadí, bude nápis zobrazen neprůhledně, viz příklad a obrázek.

frmHlavni.Canvas.Font.Color := clBlue;
frmHlavni.Canvas.TextOut(10, 10, `Toto je nápis`);

Chcete-li nápis zobrazit průhledně, můžete opět použít funkci SetBkMode, která využívá handle plátna (viz příklad a obrázek):

SetBkMode(frmHlavni.Canvas.Handle, TRANSPARENT);
frmHlavni.Canvas.Font.Color := clBlue;
frmHlavni.Canvas.TextOut(10, 10, `Toto je nápis`);

Další vlastnosti fontu (velikost, styl, rozteč, znaková sada, …) jsou shodné jako v případě již popisovaného typu TTextAttributes (viz 13. díl seriálu).

Vlastnost Pen

Vlastnost Pen (která je typu TPen) specifikuje typ pera daného plátna, které řídí způsob kreslení čar a rámů (orámování) obrazců. Nastavením vlastnosti Pen udáváte barvu, styl, šířku a kreslicí mód pera.

Barva pera - vlastnost Pen.Color

Nastavování barvy pera se provádí již několikrát opakovaným způsobem, např.:

frmHlavni.Canvas.Pen.Color := clBlue;

Mód pera – vlastnost Pen.Mode

Mód pera říká, jakým způsobem bude pero vykreslovat čáry na plátno, lépe řečeno, jakým způsobem bude probíhat interakce barvy pera s barvami, které byly na formuláři. O tom, jak bude čára vykreslena na formulář, totiž rozhodují tři faktory: barva pera, barva povrchu a způsob, jakým jsou tyto dvě barvy kombinovány. Přesněji – Windows s těmito dvěma barvami provádějí bitovou operaci, která se nazývá rastrová operace (Raster Operation, ROP). Mód pera specifikuje ROP, která se má použít pro dané plátno. K dispozici je 16 předdefinovaných módů, některé ukazuje následující tabulka:

Mód pera Výsledná barva
PmBlack Vždy černá
pmWhite Vždy bílá
PmNop Nezměněná (výsledek je neviditelný)
PmNot Inverzní k barvě pozadí plátna (barvu pozadí plátna budeme dále označovat „barva obrazovky“)
PmCopy Určená vlastností Pen.Color
pmNotCopy Inverzní k barvě Pen.Color
pmMergePenNot Kombinace barvy pera a inverzní barvy obrazovky
pmMaskPenNot Kombinace barev společných peru a inverzní barvy obrazovky
pmMergeNotPen Kombinace barev obrazovky a inverzní barvy pera
pmMaskNotPen Kombinace barev společných obrazovce a inverzní barvy pera
pmMerge Kombinace barev pera a obrazovky
pmNotMerge Inverzní k pmMerge
PmMask Kombinace barev společných peru a obrazovce
pmNotMask Inverzní k pmMask
PmXor Kombinace barev buď pera nebo obrazovky (ale ne obou)
pmNotXor Inverzní k pmXor

Mód pera je implicitně pmCopy, tedy pero kreslí barvou specifikovanou v její vlastnosti Color.

Následující obrázek demonstruje čtyři možná nastavení vlastnosti Mode. Vodorovné čáry jsou vždy kresleny s módem pmCopy (tedy standardním), a jednotlivá nastavení módu pera pro svislé čáry jsou uvedena pod každým obrázkem.

Styl pera – vlastnost Pen.Style

Nastavením stylu pera říkáme, jaký styl bude mít výsledná čára. Možné styly shrnuje tabulka:

Styl Popis
PsSolid Plná čára
PsDash Čárkovaná čára
PsDot Tečkovaná čára
PsDashDot Čerchovaná čára
PsDashDotDot Čára typu čárka – tečka – tečka
PsClear Není kresleno nic
PsInsideFrame Čáry uvnitř rámce uzavřených tvarů, který určuje ohraničující obdélník – záleží na šířce čáry

Šířka čáry – vlastnost Pen.Width

Nastavením této vlastnosti určujete šířku vykreslované čáry. Uvádí se v pixelech.

Vlastnost PenPos

Vlastnost plátna PenPos uchovává aktuální pozici pera. Hodnota této vlastnosti není určena pouze ke čtení, proto můžete jejím nastavením pozici pera změnit. Níže si povíme o metodě MoveTo, která nastaví pero na danou pozici. Volání této metody je ekvivalentní nastavení vlastnosti PenPos.

Vlastnost Pixels

Vlastnost plátna Pixels určuje barvu pixelů. Hodnotu této vlastnosti je opět možné měnit, a kreslit tak „ručně“ na plátno.

Příklad (formulář se jmenuje frmHlavni a akce je provedena v event handleru události OnClick tlačítka btnPixely):

procedure TfrmHlavni.btnPixelyClick(Sender: TObject);
var
  W: Word;

begin
  for W := 10 to 200 do
    Canvas.Pixels[W, 10] := clRed;
end;

Metody třídy TCanvas

Plátno má celou řadu kreslicích metod. Nejdůležitější z nich ukazuje následující tabulka :

Metoda Popis
Arc Kreslí křivku (část elipsy definovanou zadaným čtyřúhelníkem).
Chord Kreslí uzavřený útvar reprezentovaný průsečíky přímky a elipsy (čára spojující dva body na obvody elipsy).
CopyRect Kopíruje (duplikuje) část plochy.
Draw Vykreslí grafiku (bitmapu, ikonu, metasoubor) specifikovaný parametrem.
Ellipse Kreslí elipsu (a používá se i ke kreslení kružnice) definovanou zadaným čtyřúhelníkem (elipsa je do něj „uzavřena“).
FillRect Vykreslí zadaný čtyřúhelník aktuálním štětcem.
LineTo Nakreslí úsečku z aktuální pozice pera (viz vlastnost plátna PenPos) na zadané souřadnice.
MoveTo Změní aktuální pozici pera (nastaví vlastnost PenPos).
Pie Vykreslí výseč.
PolyBezier Vykreslí Bezierovu křivku na základě zadaných bodů.
PolyBezierTo Vykreslí Bezierovu křivku na základě zadaných bodů a nastaví hodnotu PenPos.
Polygon Kreslí mnohoúhelník definovaný maticí bodů.
Rectangle Vykreslí obdélník nebo čtverec.
StretchDraw Vykreslí zadanou grafiku do zadaného čtyřúhelníku (jehož velikost nemusí odpovídat velikosti grafiky).
TextOut Vypíše řetězec na zadané souřadnice a nastaví vlastnost PenPos.

Poznámka ke kreslení v Delphi

Nejprve vytvoříme jednoduchý příklad, který nakreslí formulář malé kolečko nebo čtvereček. Tento útvar se nakreslí na místo, kam uživatel klikne myší a tvar se vybere podle toho, držel-li uživatel při kliknutí stisknutou klávesu Shift (kolečko) nebo ne (čtvereček). Na tomto příkladu následně demonstrujeme některé problémy spojené s kreslením v Delphi. Formulář se jmenuje frmHlavni a celá akce je naprogramována jako ošetření události OnMouseDown tohoto formuláře. Vytvořenou aplikaci s několik „naklikanými“ objekty ukazuje obrázek.

procedure TfrmHlavni.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ssShift in Shift then
    frmHlavni.Canvas.Ellipse(X - 10, Y - 10, X + 10, Y + 10)
  else
    frmHlavni.Canvas.Rectangle(X - 10, Y - 10, X + 10, Y + 10);
end;

Program je velmi jednoduchý a vypadá poměrně elegantně. Problém ovšem nastane v okamžiku, kdy okno s běžící aplikací (nebo jeho část) zakryjete jiným oknem. Pak zjistíte, že nakreslené obrazce z příslušné části plochy okna zmizely (viz další obrázek). Totéž se stane, pokud okno zmenšíte a následně pět zvětšíte na původní velikost.

Proč tento problém nastává a jak jej nejsnáze vyřešit? Nejprve si vysvětlíme několik podrobností souvisejících s obecným postupem při obsluze výstupu ve Windows.

Při kreslení do okna Windows výslednou bitmapu nikam neukládají. Stane-li se pak cokoliv, co část nakreslených objektů smaže, je obsah okna zpravidla ztracen. Ve Windows i v Delphi existují postupy, jak zajistit, aby se bitmapa ukládala a okno neztrácelo svůj obsah při každé operaci. Toho je možné dosáhnout buď programově (napsáním určitého programového kódu) nebo použitím těch správných komponent.

Překreslování okna – ručně

První přístup spočívá v metodě nazvané store and paint (ulož a namaluj). Jakmile uživatel provede nějakou akci (např. klikne myší), musíme uložit pozici a jiné elementy. Později tyto informace využijeme a znovu vykreslíme celou scénu (případně její část). Je zřejmé, že tento postup si vyžádá poměrně významnou programátorskou režii (a zajisté také dodatečné datové struktury, ve kterých uchováváme údaje o všech vykreslovaných objektech).

Vlastní překreslení se následně provede použitím některé z vhodných metod a událostí:

  • Metoda Invalidate informuje Windows, že by měl být překreslen povrch formuláře (nicméně nevynucuje vlastní překreslení). Není ovšem nutné volat ji pouze na formulář.
  • Metoda Update žádá Windows o překreslení formuláře. Překreslení je provedeno okamžitě, ale pouze na ty oblasti, které jsou neplatné, tedy např. na které byla zavolána metoda Invalidate.
  • Metoda Repaint překreslí formulář, a to tím způsobem, že zavolá Invalidate a vzápětí Update.
  • Metoda Refresh má stejné účinky jako metoda Repaint (přesněji řečeno – metoda Refresh volá metodu Repaint).

Při vytváření programu tímto způsobem tedy postupujete zhruba takto:

  • Vytvoříte vhodnou datovou strukturu pro ukládání všech nakreslených objektů.
  • Ošetříte událost OnPaint a to tak, že v těle event handleru vykreslíte na formulář všechny objekty právě uložené v datové struktuře.
  • Má-li se nakreslit nový objekt (např. když uživatel klikne na formulář), uložíte jej do datové struktury a zavoláte metodu Repaint.
Postup je popsán jen velmi rámcově, protože podrobný rozbor tohoto způsobu přesahuje rámec našeho seriálu, zvláště za předpokladu, že v následující kapitole si ukážeme způsob, jak celý tento kostrbatý postup obejít.

Překreslování okna – použitím komponenty Image

Ano, pouhým zvolením vhodné komponenty si můžete ušetřit starosti způsobené uchováváním a ručním překreslováním všech objektů V předchozích příkladech jsme vždy kreslili na plátno formuláře (frmHlavni.Canvas). Stačí použít místo formuláře komponentu Image a problém je vyřešen.

Komponenta Image (z palety Additional) slouží primárně k zobrazení obrázku. Je možné zobrazit obrázek rozpoznaný typem TImage, tedy bitmapu, ikonu, metasoubor nebo jiný grafický objekt zapouzdřovaný třídou TPicture.

Nejdůležitější vlastností komponenty Image je tedy Picture (obrázek), která udává jméno zobrazovaného obrázku. Načtení obrázku do komponenty Image je mimořádně jednoduché, např.:

Image.Picture.LoadFromFile(`C:\Bitmapa.bmp`);

Image má ovšem také plátno ke kreslení, podobně jako formulář. A tím se dostáváme k problémům s překreslováním plátna: místo kreslení na povrch okna kreslíme na bitmapu do paměti (ale v okně samozřejmě vždy vidíme její aktuální stav), a komponenta Image provádí veškerá překreslování zcela automaticky. Uvedeme tedy znovu příklad z předchozího textu, jen na formulář (nazvaný frmHlavni) umístíme komponentu Image (imgKresli) a místo plátna formuláře budeme používat plátno komponenty Image:

procedure TfrmHlavni.imgKresliMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ssShift in Shift then
    imgKresli.Canvas.Ellipse(X - 10, Y - 10, X + 10, Y + 10)
  else
    imgKresli.Canvas.Rectangle(X - 10, Y - 10, X + 10, Y + 10);
end;

Pokud tuto aplikaci přeložíme, bude překreslování probíhat skvěle; jediným problémem je, že barva bitmapy je zpočátku nastavena na bílou:

Tento problém vyřešíme velmi jednoduše – při startu aplikace vyplníme plátno komponenty Image barvou formuláře:

procedure TfrmHlavni.FormCreate(Sender: TObject);
begin
  with imgKresli.Canvas do begin
    Brush.Color := frmHlavni.color;
    Fillrect(Rect(0, 0, imgKresli.Picture.Width, imgKresli.Picture.Height));
    Brush.Color := clWhite;
  end;
end;

Výsledek je přesně takový, jaký jsme si přáli – tedy stejný vzhled jako u aplikace kreslící na plátno formuláře, nicméně automatické překreslování. Zkuste si přes běžící aplikaci přetáhnout jiné okno, případně okno zmenšit a zvětšit.

Závěrečný příklad

Na závěr vytvoříme trochu rozsáhlejší příklad pro demonstraci některých prvků popsaných v této kapitole.

Aplikace bude:

  • umožňovat kreslit čtverečky a kolečka (se stiskem klávesy Shift);
  • umožňovat změnu velikosti a barvy vykreslovaných útvarů;
  • zobrazovat v záhlaví okna informace o aktuálních souřadnicích kurzoru;
  • umožňovat zapnout / vypnout zobrazování rámečku okolo vykreslovaných objektů;
  • umět vyplňovat objekty buď úplně nebo šrafováním;
  • umožňovat vymazání plochy (se zapamatováním aktuálního nastavení výplně, barvy a ohraničení);
  • zajišťovat překreslování obsahu okna.

K vytvoření programu použijeme následující komponenty:

  • formulář (frmHlavni);
  • 2x Button (btnBarva a btnVymaz);
  • 2x CheckBox (cbOhraniceni a cbPlne);
  • 1x ColorDialog (dlgColor);
  • 1x Image (imgKresli);
  • 1x Label (lblVelikost);
  • 1x UpDown (udVelikost, místo ní lze případně použít i SpinButton).

Ukázka běžící aplikace je na následujícím obrázku.

Zdrojový kód celého modulu:

unit hlavni;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, ComCtrls;

type
  TfrmHlavni = class(TForm)
    imgKresli: TImage;
    btnBarva: TButton;
    dlgColor: TColorDialog;
    btnVymaz: TButton;
    udVelikost: TUpDown;
    lblVelikost: TLabel;
    cbPlne: TCheckBox;
    cbOhraniceni: TCheckBox;
    procedure imgKresliMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure imgKresliMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure btnBarvaClick(Sender: TObject);
    procedure udVelikostClick(Sender: TObject; Button: TUDBtnType);
    procedure btnVymazClick(Sender: TObject);
    procedure cbOhraniceniClick(Sender: TObject);
    procedure cbPlneClick(Sender: TObject);
  private
    Rozmer : Integer;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmHlavni: TfrmHlavni;

implementation

{$R *.DFM}

procedure TfrmHlavni.imgKresliMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ssShift in Shift then
    imgKresli.Canvas.Ellipse(X - Rozmer, Y - Rozmer, X + Rozmer, Y + Rozmer)
  else
    imgKresli.Canvas.Rectangle(X - Rozmer, Y - Rozmer, X + Rozmer, Y + Rozmer);
end;

procedure TfrmHlavni.FormCreate(Sender: TObject);
begin
  Rozmer := 10;
  udVelikost.Position := Rozmer;
  lblVelikost.Caption := `Velikost: ` + IntToStr(Rozmer);
  with imgKresli.Canvas do begin
    Brush.Color := clWhite;
    Fillrect(Rect(0, 0, imgKresli.Picture.Width, imgKresli.Picture.Height));
    Brush.Color := clBlack;
  end;
  cbOhraniceniClick(Sender);  // inicializuj Pen.Style
  cbPlneClick(Sender);        // inicializuj Brush.Style
end;

procedure TfrmHlavni.imgKresliMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  frmHlavni.Caption :=
    Format(`Souradnice: X = %d, Y = %d`, [X, Y]);
end;

procedure TfrmHlavni.btnBarvaClick(Sender: TObject);
begin
  if dlgColor.Execute then
    imgKresli.Canvas.brush.Color := dlgColor.Color;
end;

procedure TfrmHlavni.udVelikostClick(Sender: TObject; Button: TUDBtnType);
begin
  Rozmer := udVelikost.Position;
  lblVelikost.Caption := `Velikost: ` + IntToStr(Rozmer);
end;

procedure TfrmHlavni.btnVymazClick(Sender: TObject);
var
  BarvaZal : TColor;
  StylZal : TBrushStyle;

begin
  with imgKresli.Canvas do begin
    BarvaZal := Brush.Color;
    StylZal := Brush.Style;

    Brush.Color := clWhite;
    Brush.Style := bsSOlid;
    Fillrect(Rect(0, 0, imgKresli.Picture.Width, imgKresli.Picture.Height));

    Brush.Style := StylZal;
    Brush.Color := BarvaZal;
  end;
end;

procedure TfrmHlavni.cbOhraniceniClick(Sender: TObject);
begin
  if cbOhraniceni.Checked then
    imgKresli.Canvas.Pen.Style := psSolid
  else
    imgKresli.Canvas.Pen.Style := psClear;
end;

procedure TfrmHlavni.cbPlneClick(Sender: TObject);
begin
  if cbPlne.Checked then
    imgKresli.Canvas.Brush.Style := bsSolid
  else
    imgKresli.Canvas.Brush.Style := bsDiagCross;
end;

end.

Diskuze (1) Další článek: Apple mění přes půl milionu zdrojů

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , , ,