Kreslení v C# Obsah Vlastnosti třídy Form... 3 Třída Graphics... 4 Události a handlery událostí... 5 Pojem událost... 5 Handler události... 6 Metody, začínající On... 7 Kreslení vyplněných útvarů... 12 Delegát, přiřazený události... 15 Použití dialogu pro nastavení barvy... 17 Psaní textu do okna... 20 Kreslení rovných čar... 24 Speciální dialogy... 36 Úlohy... 40 Seznam obrázků... 40 Seznam programů... 41 Literatura... 41 Cílem kapitoly je ukázat možnosti kreslení čar, křivek a výplní ploch s využitém možností vektorové grafiky jak je implementovaná v MS Windows Forms a GDI+. Klíčové pojmy: Události, handlery, třída Graphics, pera, stětce, kreslení vyplněných a nevyplněných objektů. Dosud uváděné programy byly konzolové aplikace. Mezi konzolovou aplikací a aplikací pro Windows není jednoznačně definovaný rozdíl. Aplikace může začínat jako konzolová, pak se stát Windows aplikací a vrátit se zpět ke konzolové aplikaci. Windows aplikace může mít konzolový výstup a konzolová aplikace může zobrazit zprávu v okně Windows. Pro úspěšné spuštění uvedených programů je třeba založit nový projekt Visual C# typu Console Application, do něj zkopírovat uvedený zdrojový kód a nastavit reference na jmenný prostor System.Windows.Forms: 22.9.2011 Kreslení v C# 1/41
Obrázek 1 Aktivace dialogového okna Add Reference Obrázek 2 Nastavení referencí na jmenný prostor System.Windows.Forms Program 1 První aplikace pro Windows Následující program vytvoří prázdné okno objekt w třídy Win, která je odvozená od třídy Form. Aplikace je spuštěná metodou Run třídy Application. Metodě Run je objekt w předán jako parametr. Na závěr je na konzolu vypsán text "Konec". class Win:Form 22.9.2011 Kreslení v C# 2/41
Win w=new Win(); w.text = "Okno"; Application.Run(w); Uvedený program vytvořil prázdné okno, neboť prázdná byla i třída Win. Vlastnosti třídy Form Text nastaví text v titulkovém pruhu okna BackColor nastaví barvu pozadí okna Width nastaví šířku okna Height nastaví výšku okna FormBorderStyle nastaví styl rámečku okna MinimizeBox nastaví použitelnost minimalizačního tlačítka Cursor nastavuje vzhled kurzoru StartPosition nastavuje počáteční zobrazení formuláře Před spuštěním následujícího programu je třeba přidat referenci na jmenný prostor System.Drawing. Obrázek 3 Přidání reference na jmenný prostor System.Drawing Program 2 Nastavení vlastností formuláře class Win :Form 22.9.2011 Kreslení v C# 3/41
Win w=new Win(); w.text = "Okno"; w.backcolor = Color.Pink; w.width=400; w.height=200; w.formborderstyle=formborderstyle.fixed3d; w.minimizebox=false; w.cursor=cursors.waitcursor; w.startposition = FormStartPosition.CenterScreen; Application.Run(w); Pokud chceme do okna kreslit, musíme napsat potřebné metody do třídy, odvozené z třídy Form, z níž vytváříme objekt, který předáváme metodě Run při spuštění aplikace. Počítačovou grafiku dělíme na: vektorovou čáry, křivky, vyplněné plochy rastrovou bitmapy, obrázky Zde se budeme zabývat vektorovou grafikou jak je implementovaná v MS Windows Forms a GDI+. Třída Graphics Všechny kreslící funkce jsou metodami třídy Graphics a začínají prefixem Draw nebo Fill. Chceme-li použít třídu Graphics musíme připojit jmenný prostor System.Drawing. Vytvoření objektu třídy Graphics? Metody začínající Draw kreslí čáry a křivky. První parametr těchto metod je objekt typu Pen (pero). Vytvoření vlastního pera pro kreslení čar // Vytvoření pera. Pen p = new Pen(barva,tloušťka); Metody začínající Fill vyplňují plochy, jejichž obrysy jsou definovány pomocí čar a křivek. První parametr těchto metod je objekt typu Brush (štětec). Vytvoření vlastního štětce pro kreslení vyplněných oblastí SolidBrush b = new SolidBrush(Color.Coral); 22.9.2011 Kreslení v C# 4/41
Nakreslení obdélníku Pomocí metod DrawRectangle nebo FillRectangle: g.drawrectangle(new Pen(Color.Blue, 3), 10, 10, 100, 100); g.fillrectangle(new SolidBrush(Color.DarkGreen), 10, 10, 100, 100); Elipsu i obdélník kreslíme do obdélníkové oblasti, kterou můžeme zadat pomocí souřadnic, jak je uvedeno výše, nebo můžeme vytvořit objekt třídy Rectangle, a ten použít pro kreslení útvaru: Vytvoření obdélníkové oblasti pro kreslení // Vytvoření obdélníku pro elipsu. Rectangle rect = new Rectangle(0, 0, 100, 80); Rectangle r = new Rectangle(0,10,this.Width-10,this.Height/2); Pen pe = new Pen(Color.DarkGreen, 5); Rectangle r = new Rectangle(10, 10,150,100); g.drawrectangle(pe,r ); Události a handlery událostí Pojem událost Událost je obecný mechanismus, umožňující jedné třídě či objektu signalizovat nějakou věc jiné třídě či objektu, a to prostřednictvím volání určité metody. Příklady událostí MouseClick kliknutí myší Resize změna velikosti ovládacího prvku, nebo formuláře Paint požadavek na překreslení ovládacího prvku, nebo formuláře Událost MouseClick Událost MouseClick nastává kdykoli uživatel klepne tlačítkem myši na příslušný ovládací prvek, nebo do klientské oblasti formuláře. Událost Resize Událost Resize nastává při změně velikosti ovládacího prvku, nebo formuláře. Událost Paint Událost Paint oznamuje, že vizuální povrch příslušného ovládacího prvku, nebo formuláře vyžaduje překreslení. K první události Paint dojde při vytváření formuláře Následné události Paint se objevují, když je formulář minimalizován a poté obnoven, dojde-li ke změně jeho velikosti nebo jakmile jej zastíní jiný formulář a ten náš se potom vrátí do popředí. 22.9.2011 Kreslení v C# 5/41
Událost Paint zajišťuje opakované vytvoření veškerého textu a grafiky na formuláři. Handler události Handler události je metoda, která se v reakci na událost zavolá. Je to rutina zpracování události. Použité handlery musí mít předepsaný prototyp: protected override void NázevHandleru(parametry handleru) Následující program používá metodu OnPaint pro obsluhu události Paint. Program 3 Obsluha události Paint metodou OnPaint Program obsahuje metodu OnPaint pro obsluhu události Paint. Tato metoda je volaná automaticky, je-li zapotřebí překreslit okno. Chceme-li kreslit, musíme nejprve vytvořit objekt třídy Graphics metodou CreateGraphics(). Potom se vytvoří pero jako nový objekt třídy Pen pomocí konstruktoru, který má dva parametry: barva pera a tloušťka čáry. Dále je vytvořen objekt třídy Rectangle pomocí konstruktoru, jehož parametry jsou souřadnice levého horního rohu obdélníka, jeho šířka a výška. Vlastní vykreslení obdélníka je provedeno metodou DrawRectangle, jejímiž parametry jsou vytvořené pero a obdélník. Obdélník má vzhledem k oknu absolutní souřadnice jeho velikost a pozice se nemění při změně velikosti okna. this.text = "Obdélník"; Pen pe = new Pen(Color.DarkGreen, 5); Rectangle r = new Rectangle(10, 10,150,100); g.drawrectangle(pe,r ); 22.9.2011 Kreslení v C# 6/41
Metody, začínající On Metody, začínající On jsou zodpovědné za volání všech zavedených obsluh příslušných událostí: OnPaint za obsluhu události Paint OnResize za obsluhu události Resize OnMouseClick za obsluhu události MouseClick Obsluhovaných událostí i metod je daleko víc. Tyto metody nemusí přímo provádět obsluhu odpovídajících událostí, ale mohou volat jiné metody, které obsluhu událostí provedou. Program 4 Volání soukromé metody KresliObdelnik z metody OnPaint KresliObdelnik(); private void KresliObdelnik() this.text = "Obdélník"; Pen pe = new Pen(Color.DarkGreen, 5); Rectangle r = new Rectangle(10, 10, 150, 100); g.drawrectangle(pe, r); Doplnění metody OnMouseClick pro obsluhu události MouseClick. Program 5 Použití metody OnMouseClick pro obsluhu události MouseClick Následující program doplňuje metodu OnMouseClick do třídy Win. Tato metoda obsluhuje událost kliknutí myší. Dojde-li ke kliknutí myší v okně, aktivuje se metoda Show, která je přetížená metoda třídy MessageBox a zobrazuje okno se zprávou. Po aktivaci metody MessageBox.Show("Nazdar","Pozdrav")se zobrazí dialogové okno, v jehož záhlaví je druhý parametr metody a řetězec, který je prvním parametrem se vypisuje v zobrazovaném okně. 22.9.2011 Kreslení v C# 7/41
KresliObdelnik(); private void KresliObdelnik() this.text = "Obdélník"; Pen pe = new Pen(Color.DarkGreen, 5); Rectangle r = new Rectangle(10, 10, 150, 100); g.drawrectangle(pe, r); protected override void OnMouseClick(MouseEventArgs e) MessageBox.Show("Nazdar","Pozdrav"); Podle argumentů metod pro obsluhu události můžeme provést podrobnější rozbor události například u metody OnMouseClick(MouseEventArgs e) můžeme z vlastností parametru e určit, kterým tlačítkem bylo kliknuto a toto vypsat metodou Show, jak ukazuje následující program. Program 6 Využití parametru MouseEventArgs pro určení, kterým tlačítkem bylo kliknuto KresliObdelnik(); private void KresliObdelnik() this.text = "Obdélník"; Pen pe = new Pen(Color.DarkGreen, 5); Rectangle r = new Rectangle(10, 10, 150, 100); g.drawrectangle(pe, r); protected override void OnMouseClick(MouseEventArgs e) if(e.button==mousebuttons.left)messagebox.show("kliknuto levým"); 22.9.2011 Kreslení v C# 8/41
if (e.button == MouseButtons.Right) MessageBox.Show("Kliknuto pravým"); V následujícím programu je doplněna metoda OnResize pro obsluhu události Resize. Program 7 Obsluha události Resize metodou OnResize Tento program vykresluje obdélník relativní velikosti vzhledem k velikosti okna při změně velikosti okna se mění jeho velikost. Aby došlo k překreslení při změně velikosti okna, je zapotřebí do třídy Win doplnit metodu OnResize, která se automaticky spustí při změně velikosti okna a označí celou oblast okna za neplatnou voláním metody Invalidate(). Je-li oblast neplatná, je třeba ji překreslit. Dojde k automatickému volání metody OnPaint, která provede překreslení. Změnou velikosti okna se nyní mění i velikost nakresleného obdélníku, neboť rozměry obdélníku jsou odvozeny od výšky a šířky okna (proměnné cy a cx). this.text = "Obdélník"; int cx = this.width, cy = this.height; Pen pe = new Pen(Color.DarkGreen, 5); g.drawrectangle(pe, cx / 8, cy / 8, 3 * cx / 8, 3 * cy / 8); protected override void OnResize(EventArgs e) this.invalidate(); 22.9.2011 Kreslení v C# 9/41
Musíme dodržet počet a typ argumentů metod pro obsluhu událostí. Argumenty lze přejmenovat. Následující program ukazuje možnost využít pro kreslení přímo parametr pea metody OnPaint(PaintEventArgs pea). Program 8 Využití argumentu metody OnPaint pro kreslení pea.graphics.drawline(new Pen(Color.DarkGreen, 5),0,0, this.width, this.height-25); pea.graphics.drawline(new Pen(Color.DarkRed, 3),0,this.Height-35, this.width,-10); protected override void OnMouseClick(MouseEventArgs a) if(a.button==mousebuttons.left)messagebox.show("kliknuto levým"); if (a.button == MouseButtons.Right) MessageBox.Show("Kliknuto pravým"); protected override void OnResize(EventArgs e) this.invalidate(); Obrázek 4 Výstup programu Program 8 22.9.2011 Kreslení v C# 10/41
Argument metody OnPaint má vlastnost ClipRectangle která určuje obdélník kreslící oblasti. Následující metoda ukazuje použití této vlastnosti pro nakreslení barevného obdélníku kolem celého okna. pea.graphics.drawrectangle(new Pen(Color.DarkGreen, 20), pea.cliprectangle); Obrázek 5 Výstup výše uvedené metody OnPaint Nakreslení nevyplněné elipsy Program 9 Program pro nakreslení nevyplněné elipsy Následující program kreslí elipsu přes celé okno podle obrázku Obrázek 6 a její rozměry se přizpůsobují velikosti okna. Obrázek 6 Výstup programu Program 9 22.9.2011 Kreslení v C# 11/41
this.text = "Elipsa"; g.drawellipse(new Pen(Color.DarkRed,5), pea.cliprectangle); protected override void OnResize(EventArgs e) this.invalidate(); Kreslení vyplněných útvarů Metody pro kreslení vyplněných útvarů začínají Fill a místo pera mají jako první parametr štětec. Chceme-li plnou výplň, vytvoříme štětec jako objekt třídy SolidBrush. Následující program nakreslí obdélník, vyplněný zelenou barvou. Program 10 Kreslení vyplněného obdélníku Následující program kreslí vyplněný obdélník podle obrázku Obrázek 7. Obrázek 7 Vyplněný obdélník this.text = "Obdélník"; SolidBrush b = new SolidBrush(Color.DarkGreen); Rectangle r = new Rectangle(10, 10, 150, 100); 22.9.2011 Kreslení v C# 12/41
g.fillrectangle(b, r); Kreslení vyplněné elipsy Nejprve vytvoříme objekt třídy Graphics a potom pomocí tohoto objektu vyvoláme metodu FillEllipse, která má 2 parametry: barvu a oblast, v níž se má elipsa vykreslit. Následující program ukazuje možnost zadání vstupu do konzolového okna. V Mainu do veřejné a statické celočíselné proměnné co načteme, jaký útvar chceme kreslit a v metodě OnPaint testujeme tuto proměnnou a nakreslíme buď vyplněný obdélník, nebo elipsu. Program 11 Volba kresleného útvaru v konzolovém okně Obrázek 8 Volba kresleného útvaru static public int co; this.text = "Obdélník"; SolidBrush b = new SolidBrush(Color.DarkGreen); Rectangle r = new Rectangle(10, 10, 150, 100); if (co == 1) g.fillrectangle(b, r); else 22.9.2011 Kreslení v C# 13/41
this.text = "Elipsa"; g.fillellipse(brushes.aquamarine, pea.cliprectangle); protected override void OnResize(EventArgs e) this.invalidate(); Console.WriteLine("Zadej co chceš kreslit:\n1 obdélník \n2 elipsu"); Win.co = Convert.ToInt32(Console.ReadLine()); Lepším řešením je zajistit volbu kresleného útvaru i jeho smazání pomocí tlačítek, které se vytvoří v konstruktoru. Program 12 Použití tlačítek pro volbu kresleného útvaru Obrázek 9 Volba kresleného útvaru pomocí tlačítek public Win() this.text = "Volba kresleného útvaru"; Button b1 = new Button(); b1.parent = this; b1.location = new Point(10,10); b1.text = "Obdélník"; b1.click += new EventHandler(Click_b1); Button b2 = new Button(); b2.parent = this; b2.location = new Point(10,50); b2.text = "Elipsa"; b2.click += new EventHandler(Click_b2); Button b3 = new Button(); 22.9.2011 Kreslení v C# 14/41
b3.parent = this; b3.location = new Point(10,90); b3.text = "Smazání"; b3.click += new EventHandler(Click_b3); void Click_b1(object obj,eventargs e) g.drawrectangle(new Pen(Color.DarkGreen, 10),this.ClientRectangle); void Click_b2(object obj,eventargs e) g.drawellipse(new Pen(Color.DarkGreen, 10),this.ClientRectangle); void Click_b3(object obj,eventargs e) g.clear(systemcolors.control); protected override void OnResize(EventArgs e) this.invalidate(); V uvedeném programu jsou handlery tlačítek připojeny k události kliknutí na tlačítku operátorem: +=. b1.click += new EventHandler(Click_b1) b2.click += new EventHandler(Click_b2) b3.click += new EventHandler(Click_b3) Obecně: Událost += new konstruktor_handleru(jméno_handleru); Delegát, přiřazený události Delegát, přiřazený události je prototyp funkce, který stanovuje, jak musí být handler události definován. Název může mít libovolný. Musí mít stejnou návratovou hodnotu, jako příslušný delegát. Argumenty můžeme přejmenovat. Musíme dodržet počet a typ argumentů. V uvedeném příkladě jsou pro obsluhu tlačítek tři delegáti: void Click_b1(object obj,eventargs e) void Click_b2(object obj,eventargs e) 22.9.2011 Kreslení v C# 15/41
void Click_b3(object obj,eventargs e) Program 13 Kreslení vyplněných i nevyplněných útvarů - ovládání pomocí tlačítek Následující program obsahuje další tlačítka pro kreslení vyplněných útvarů: Obrázek 10 Kreslení vyplněných i nevyplněných útvarů public Win() this.text = "Volba kresleného útvaru"; Button b1 = new Button(); b1.parent = this; b1.location = new Point(10,10); b1.text = "Obdélník"; b1.click += new EventHandler(Click_b1); Button b2 = new Button(); b2.parent = this; b2.location = new Point(10,50); b2.text = "Elipsa"; b2.click += new EventHandler(Click_b2); Button b3 = new Button(); b3.parent = this; b3.location = new Point(10,90); b3.text = "Smazání"; b3.click += new EventHandler(Click_b3); Button b4 = new Button(); b4.parent = this; b4.location = new Point(100, 10); b4.text = "Vyplněný obdélník"; b4.click += new EventHandler(Click_b4); Button b5 = new Button(); b5.parent = this; b5.location = new Point(100, 50); b5.text = "Vyplněná elipsa"; b5.click += new EventHandler(Click_b5); void Click_b1(object obj,eventargs e) g.drawrectangle(new Pen(Color.DarkGreen, 10),this.ClientRectangle); void Click_b2(object obj,eventargs e) 22.9.2011 Kreslení v C# 16/41
g.drawellipse(new Pen(Color.DarkGreen, 10),this.ClientRectangle); void Click_b3(object obj,eventargs e) g.clear(systemcolors.control); void Click_b4(object obj, EventArgs e) g.fillrectangle(brushes.aquamarine, this.clientrectangle); void Click_b5(object obj, EventArgs e) g.fillellipse(brushes.aquamarine, this.clientrectangle); protected override void OnResize(EventArgs e) this.invalidate(); Použití dialogu pro nastavení barvy Pro nastavení barvy je možné použít dialog, používaný operačním systémem Windows. Program 14 Použití dialogu pro nastavení barvy 22.9.2011 Kreslení v C# 17/41
Obrázek 11 Výběr barvy Dialog pro nastavení barvy se otevře po kliknutí na tlačítko s textem: "Vyber barvu", Které je vytvořeno v konstruktoru třídy Win. Ukončíme-li po výběru barvy dialog tlačítkem OK, barva se použije, zvolíme-li Storno, barva se nepoužije. public static Color barva; public Win() Button b1 = new Button(); b1.parent = this; b1.location = new Point(10, 150); b1.text = "Vyber barvu"; b1.click += new EventHandler(Click_b1); void Click_b1(object obj, EventArgs e) ColorDialog cd = new ColorDialog(); cd.showdialog(); barva = cd.color; this.invalidate(); KresliObdelnik(); private void KresliObdelnik() this.text = "Obdélník"; Pen pe = new Pen(barva, 5); Rectangle r = new Rectangle(10, 10, 150, 100); g.drawrectangle(pe, r); 22.9.2011 Kreslení v C# 18/41
Štětcem, vytvořeným podle třídy SolidBrush vyplňuje útvar spojitě, bez šrafování. Konstruktor této třídy má jeden parametr barvu výplně. Kromě toho můžeme použít šrafovací štětce, které vyplní danou oblast malým, opakujícím se vzorkem. Pro vytvoření tohoto štětce použijeme třídu HatchBrush, jejíž konstruktor je přetížený a může mít dva, nebo tři parametry: HatchBrush() Chceme-li použít třídu, musíme připojit jmenný prostor: System.Drawing.Drawing2D Na následujícím příkladě si ukážeme použití šrafovacích štětců. Program 15 Použití šrafovacích štětců pro výplň útvarů using System.Drawing.Drawing2D; Rectangle r; HatchBrush b; this.text = "Různá šrafování"; HatchBrush b = new HatchBrush(HatchStyle.Cross,Color.DarkBlue,Color.LightBlue); r = new Rectangle(10, 10, 50, 50); g.fillrectangle(b, r); b = new HatchBrush(HatchStyle.DashedHorizontal, Color.DarkBlue, Color.LightBlue); r = new Rectangle(70, 10, 50, 50); g.fillrectangle(b, r); b = new HatchBrush(HatchStyle.DashedVertical,Color.DarkBlue,Color.LightBlue); r = new Rectangle(10, 70, 50, 50); g.fillrectangle(b, r); b = new HatchBrush(HatchStyle.DiagonalBrick,Color.DarkBlue,Color.LightBlue); r = new Rectangle(70, 70, 50, 50); g.fillrectangle(b, r); 22.9.2011 Kreslení v C# 19/41
Okno po spuštění programu: Obrázek 12 Použití třídy HatchBrush pro tvorbu štětce Psaní textu do okna Pro psaní do okna používáme metodu DrawString, kterou voláme pomocí objektu třídy Graphics. Metoda je přetížená v jedné verzi má čtyři parametry: Vypisovaný text Font Štětec Souřadnice bodu, od kterého bude text vypisovaný Point p = new Point(20,50); g.drawstring("dobrý den",font,sb,p); Namísto výchozího bodu lze uvést jako čtvrtý parametr obdélník, do něhož bude text vypisovaný. Rectangle r = new Rectangle(10, 10, 150, 100); g.drawstring("dobrý den",font,sb,r); Pokud jako druhý parametr použijeme Font, použije se implicitní nastavení. Program 16 Výpis textu zadané barvy na zadané místo v okně 22.9.2011 Kreslení v C# 20/41
Obrázek 13 Výpis textu do okna this.text = "Text v okně"; SolidBrush sb = new SolidBrush(Color.DarkGreen); Rectangle r = new Rectangle(10, 10, 150, 100); g.drawstring("dobrý den",font,sb,r); protected override void OnResize(EventArgs e) this.invalidate(); Vytvoření fontu pro určité písmo a velikost Pro vytvoření požadovaného fontu můžeme použít konstruktor třídy Font: Font f = new Font("Verdana", 19); Prvním parametrem je typ písma a druhým velikost. Použití třídy FontDialog Pro nastavení fontu je možné použít dialog, používaný operačním systémem Windows. Program 17 Využití dialogového okna Písmo pro nastavení fontu 22.9.2011 Kreslení v C# 21/41
Obrázek 14 Nastavení vlastností písma public Font f; public Win() FontDialog fd = new FontDialog(); fd.showdialog(); f = fd.font; this.text = "Text v okně"; SolidBrush sb = new SolidBrush(Color.Red); Rectangle r = new Rectangle(100, 50, 150, 100); g.drawstring("dobrý den", f, sb, r); protected override void OnResize(EventArgs e) this.invalidate(); Následující aplikace obsahuje 4 tlačítka a jedno textové pole (podle obrázku Obrázek 15). Uživatel může v textovém poli zadat text a po kliknutí na tlačítko Vypiš se text vypíše do okna nastavenou barvou a fontem. Text můžeme smazat kliknutím na tlačítko Smaž. 22.9.2011 Kreslení v C# 22/41
Obrázek 15 Výpis zadaného textu nastavenou barvou a fontem Program 18 Výpis zadaného textu nastavenou barvou a fontem Pro správnou funkci programu je třeba nejprve nastavit font a barvu textu, potom napsat vypisovaný text do textového pole a kliknout na tlačítko Vypiš. public static Font f; public static Color c; public static int x, y; public static Graphics g; public TextBox textbox1; public Win() this.text = "Výpis textu"; Button b1 = new Button(); b1.parent = this; b1.location = new Point(10, 150); b1.text = "Vypiš"; b1.click += new EventHandler(Click_b1); Button b2 = new Button(); b2.parent = this; b2.location = new Point(100, 150); b2.text = "Smaž"; b2.click += new EventHandler(Click_b2); Button b3 = new Button(); b3.parent = this; b3.location = new Point(190, 150); b3.width = 100; b3.text = "Nastavení fontu"; b3.click += new EventHandler(Click_b3); Button b4 = new Button(); b4.parent = this; b4.location = new Point(190, 180); 22.9.2011 Kreslení v C# 23/41
b4.width = 100; b4.text = "Nastavení barvy"; b4.click += new EventHandler(Click_b4); textbox1 = new TextBox(); textbox1.parent = this; textbox1.location = new Point(10,10); c = Color.Red; x = 100; y = 100; void Click_b1(object obj, EventArgs e) g = this.creategraphics(); SolidBrush b = new SolidBrush(c); Rectangle r = new Rectangle(10, 50, 200, 100); g.drawstring(textbox1.text, f, b, r); void Click_b2(object obj, EventArgs e) g = this.creategraphics(); g.clear(systemcolors.control); this.invalidate(); void Click_b3(object obj, EventArgs e) FontDialog fd = new FontDialog(); fd.showdialog(); f = fd.font; this.invalidate(); void Click_b4(object obj, EventArgs e) ColorDialog cd = new ColorDialog(); cd.showdialog(); c = cd.color; this.invalidate(); Kreslení rovných čar Pro kreslení rovných čar se používají následující metody třídy Graphics: DrawLine(Pen,Point,Point) kreslí čáru, spojující dva body Přetížené verze: DrawLine(Pen,Pointf,Pointf) DrawLine(Pen,Int32, Int32,Int32, Int32) 22.9.2011 Kreslení v C# 24/41
DrawLine(Pen,Single, Single, Single, Single) DrawLines(Pen,Point[]) kreslí posloupnost úseček, které spojují pole bodů Přetížená verze: DrawLines(Pen,PointF[]) Program 19Kreslení čar metodou DrawLine Následující program nakreslí dvě čáry podle obrázku Obrázek 16: Obrázek 16 Výstup programu pro kreslení dvou čar metodou DrawLine this.text = "Kreslení čar"; int cx = this.width, cy = this.height; Pen pe = new Pen(Color.DarkGreen, 5); g.drawline(pe, cx / 8, cy / 8, 3 * cx / 8, 3 * cy / 8); g.drawline(pe, cx / 8, 3 *cy / 8, 3 * cx / 8, cy / 8); protected override void OnResize(EventArgs e) this.invalidate(); 22.9.2011 Kreslení v C# 25/41
V tomto programu jsou souřadnice bodů počítány jako hodnoty celočíselných výrazů, odvozované z šířky a výšky okna (cx, cy). K určení souřadnic je též možné použít objekty struktury Point. Metoda OnPaint potom bude: Výstup programu bude stejný, jako na obrázku Obrázek 16. this.text = "Kreslení čar"; int cx = this.width, cy = this.height; Pen pe = new Pen(Color.DarkGreen, 5); Point b1 = new Point(cx / 8, cy / 8); Point b2 = new Point(3 * cx / 8, 3 * cy / 8); g.drawline(pe,b1,b2 ); Point b3 = new Point( cx / 8, 3 *cy / 8); Point b4 = new Point( 3 * cx / 8, cy / 8); g.drawline(pe,b3,b4); Sérii spojených čar bychom mohli nakreslit pomocí DrawLines, ale výhodnější je použít metodu DrawLines, jejímž druhým parametrem je pole bodů, které chceme spojit. Použití DrawLines neumožňuje měnit barvu jednotlivých úseček, vše se nakreslí jednou barvou štětce. 22.9.2011 Kreslení v C# 26/41
Program 20 Kreslení domečku s využitím metody DrawLines Následující program nakreslí domeček podle obrázku : Obrázek 17 Výstup programu pro kreslení domečku metodou DrawLines this.text = "Použití DrawLines"; Pen p = new Pen(Color.Blue, 3); int sirka = this.width; int vyska = this.height; int[] x = sirka / 4, 3 * sirka / 4, 3 * sirka / 4, sirka / 4, sirka / 4, sirka /2,3 * sirka / 4; int[] y = vyska / 3, vyska /3, 2 * vyska / 3, 2* vyska / 3, vyska / 3,vyska / 6,vyska / 3; Point[] dum = new Point[x.Length]; for(int i=0;i<x.length;i++) dum[i]=new Point(x[i], y[i]); ; g.drawlines(p, dum); protected override void OnResize(EventArgs e) this.invalidate(); 22.9.2011 Kreslení v C# 27/41
Souřadnice domečku jsou uvedeny v polích x, y, které jsou použity pro vytváření jednotlivých bodů objektu dům struktury Point, pomocí které je vykreslen obrázek. Metodu DrawLines lze využít prokreslení průběhů matematických funkcí. Pokud jsou úsečky mezi jednotlivými body krátké a použijeme jich hodně, můžeme s využitím metody DrawLines nakreslit libovolnou křivku. Program 21 Kreslení funkce sinus s využitím metody DrawLines Následující program kreslí funkci sinus. Výstup programu je uvedený na obrázku. Obrázek 18 Průběh funkce sinus, nakreslený s využitím metody DrawLines this.text = "Použití DrawLines pro kreslení funkce sinus"; Pen p = new Pen(Color.Blue, 3); int sirka = this.width; int vyska = 3*this.Height/4; int PocetBodu = sirka; PointF[] aptf = new PointF[PocetBodu]; g.clear(color.white); for (int i = 0; i < PocetBodu; i++) aptf[i].x = i; aptf[i].y = vyska / 2 * (1 - (float) Math.Sin(i * 2 * Math.PI / (sirka - 1)))+20; 22.9.2011 Kreslení v C# 28/41
g.drawlines(p, aptf); protected override void OnResize(EventArgs e) this.invalidate(); Program 22 Volba počtu period funkce sinus pomocí číselníku Následující program umožňuje nastavit počet period funkce sinus pomocí číselníku (prvku NumericUpDown). jak je vidět na obrázku. NumericUpDown nu; int PocetPeriod; public Win() this.text = "Volba počtu period funkce sinus"; nu = new NumericUpDown(); nu.parent = this; nu.location = new Point(10, 200); 22.9.2011 Kreslení v C# 29/41
nu.text = "Obdélník"; nu.click += new EventHandler(ZmenaHodnoty_nu); PocetPeriod = 1; nu.value = 1; private void ZmenaHodnoty_nu(object sender, EventArgs e) PocetPeriod = Convert.ToInt32(nu.Value); this.invalidate(); if (PocetPeriod > 0) Pen p = new Pen(Color.Blue, 3); int sirka = this.width; int vyska = 3 * this.height / 4; int PocetBodu = sirka * PocetPeriod; PointF[] aptf = new PointF[PocetBodu]; g.clear(color.white); for (int i = 0; i < PocetBodu; i++) aptf[i].x = i / PocetPeriod; aptf[i].y = vyska / 2 * (1 - (float) Math.Sin(i * 2 * Math.PI / (sirka - 1))) + 20; g.drawlines(p, aptf); else MessageBox.Show("Počet period musí být kladné číslo"); protected override void OnResize(EventArgs e) this.invalidate(); Program v konstruktoru vytváří číselník a nastavuje jeho hodnotu na 1 periodu. Uživatel může za běhu programu nastavit jinou hodnotu. Číselník je obsluhován handlerem ZmenaHodnoty_nu, v němž je nastavená hodnota uložena do proměnné PocetPeriod. Tato hodnota je použitá v metodě OnPaint pro nastavení počtu bodů a modifikace délky kroku souřadnice x. V programu je ošetřeno, aby bylo možné zadávat pouze kladné hodnoty počtu period. 22.9.2011 Kreslení v C# 30/41
Program 23 Kreslení do formuláře Následující program umožňuje kreslit do okna tak, že body, v nichž se klikne se propojí čarou výsledek je vidět na obrázku Obrázek 19: Obrázek 19 Ukázka kreslení do formuláře Graphics g; Pen p; Color c = Color.Blue; bool md = false; int x = 0, y = 0, xs, ys; public Win() this.text = "Kreslení do formuláře"; this.mouseclick += new MouseEventHandler(Form_MouseClick); g = this.creategraphics(); private void Form_MouseClick(object sender, MouseEventArgs e) if (x!= 0 && y!= 0) xs = x; ys = y; x = e.x; y = e.y; g = this.creategraphics(); p = new Pen(Color.Blue, 3); g.drawline(p, xs, ys, x, y); 22.9.2011 Kreslení v C# 31/41
x = e.x; y = e.y; Program 24 Vylepšené kreslení do formuláře Následující program je vylepšením předchozího programu kreslení do formuláře. Zajišťuje kreslení pouze za stisknutého levého tlačítka myši. To je zajištěno doplněním handlerů událostí MouseUp a MouseDown. Kreslení je zajištěno při obsluze události MouseMove. Graphics g; Pen p; Color c = Color.Blue; bool md = false; int x = 0, y = 0, xs, ys; public Win() 22.9.2011 Kreslení v C# 32/41
this.text = "Kreslení do formuláře"; this.mousemove += new MouseEventHandler(Form_MouseMove); this.mouseup += new MouseEventHandler(Form_MouseUp); this.mousedown += new MouseEventHandler(Form_MouseDown); g = this.creategraphics(); private void Form_MouseDown(object sender, MouseEventArgs e) md = true; private void Form_MouseUp(object sender, MouseEventArgs e) md = false; private void Form_MouseMove(object sender, MouseEventArgs e) if (x!= 0 && y!= 0 && md) xs = x; ys = y; x = e.x; y = e.y; g = this.creategraphics(); p = new Pen(Color.Blue, 3); g.drawline(p, xs, ys, x, y); x = e.x; y = e.y; Souřadnice bodů lze uložit do souboru, což umožní opětovné vykreslení kresby podle těchto souřadnic. Program 25 Uložení souřadnic bodů kresby do souboru using System.IO; Graphics g; Pen p; 22.9.2011 Kreslení v C# 33/41
Color c = Color.Blue; bool md = false; int x = 0, y = 0, xs, ys; StreamWriter sw; public Win() sw = new StreamWriter(@"..\..\souradnice.txt"); this.text = "Kreslení do formuláře"; this.mousemove += new MouseEventHandler(Form_MouseMove); this.mouseup += new MouseEventHandler(Form_MouseUp); this.mousedown += new MouseEventHandler(Form_MouseDown); g = this.creategraphics(); Button b1 = new Button(); b1.parent = this; b1.location = new Point(10, 150); b1.width = 150; b1.text = "Uložení do souboru"; b1.click += new EventHandler(Click_b1); private void Form_MouseDown(object sender, MouseEventArgs e) md = true; private void Form_MouseUp(object sender, MouseEventArgs e) md = false; private void Form_MouseMove(object sender, MouseEventArgs e) if (x!= 0 && y!= 0 && md) xs = x; ys = y; x = e.x; y = e.y; g = this.creategraphics(); p = new Pen(Color.Blue, 3); g.drawline(p, xs, ys, x, y); sw.writeline("0 1 2 3", xs, ys, x, y); x = e.x; y = e.y; void Click_b1(object obj, EventArgs e) sw.close(); 22.9.2011 Kreslení v C# 34/41
Program 26 Čtení souřadnic pro kreslení ze souboru Následující program po kliknutí na tlačítko vykreslí kresbu podle souřadnic, uložených v souboru. Obrázek 20 Výstup programu pro čtení souřadnic ze souboru using System.IO; Graphics g; Pen p; Color c = Color.Blue; int x = 0, y = 0, xs, ys; StreamReader sr; public Win() this.text = "Kreslení do formuláře"; g = this.creategraphics(); Button b1 = new Button(); b1.parent = this; b1.location = new Point(10, 10); b1.width = 150; b1.text = "Čtení ze souboru"; b1.click += new EventHandler(Click_b1); void Click_b1(object obj, EventArgs e) sr = new StreamReader(@"..\..\souradnice.txt"); g = this.creategraphics(); p = new Pen(Color.Blue, 3); while (!sr.endofstream) 22.9.2011 Kreslení v C# 35/41
string radek = sr.readline(); string[] sourad = radek.split(' '); xs = Convert.ToInt32(sourad[0]); ys = Convert.ToInt32(sourad[1]); x = Convert.ToInt32(sourad[2]); y = Convert.ToInt32(sourad[3]); g.drawline(p, xs, ys, x, y); sr.close(); Speciální dialogy Ukázali jsme si použití speciálních dialogů operačního systému Windows: ColorDialog dialog pro výběr barvy TextDialog dialog pro nastavení vlastností textu Nyní si ukážeme použití dalších speciálních dialogů operačního systému Windows: OpenFileDialog dialog pro otevření souboru SaveFileDialog - dialog pro otevření souboru Program 27 Výběr souboru pro čtení dat pomocí OpenFileDialogu Po spuštění program vytvoří okno s tlačítkem, kde po kliknutí se objeví dialog pro otevření souboru: Obrázek 21 Čtení dat ze souboru V tomto dialogu můžeme nalistovat textový soubor, v němž jsou uloženy souřadnice bodů, podle kterých program vykreslí obrázek v okně. 22.9.2011 Kreslení v C# 36/41
Souřadnice v souboru musí být uloženy ve tvaru x1 y1 x2 y2, kde [x1,y1] jsou souřadnice prvního a [x2,y2] jsou souřadnice druhého bodu, které jsou propojeny čarou. Obrázek 22 Příklad souřadnic bodů pro kreslení obrázku using System.IO; Graphics g; Pen p; Color c = Color.Blue; int x = 0, y = 0, xs, ys; StreamReader sr; public Win() this.text = "Kreslení do formuláře"; g = this.creategraphics(); Button b1 = new Button(); b1.parent = this; b1.location = new Point(10, 10); b1.width = 150; b1.text = "Čtení ze souboru"; b1.click += new EventHandler(Click_b1); void Click_b1(object obj, EventArgs e) OpenFileDialog o = new OpenFileDialog(); DialogResult r = o.showdialog(); if (r == DialogResult.OK) sr = new StreamReader(o.OpenFile()); g = this.creategraphics(); p = new Pen(Color.Blue, 3); while (!sr.endofstream) string radek = sr.readline(); string[] sourad = radek.split(' '); xs = Convert.ToInt32(sourad[0]); ys = Convert.ToInt32(sourad[1]); x = Convert.ToInt32(sourad[2]); y = Convert.ToInt32(sourad[3]); 22.9.2011 Kreslení v C# 37/41
g.drawline(p, xs, ys, x, y); sr.close(); Podobně lze použít SaveFileDialog pro nalistování složky, do které chceme soubor uložit a volbu jeho jména: Program 28 Program, umožňující uložit kresbu pomocí SaveFileDialogu using System.IO; Graphics g; Pen p; Color c = Color.Blue; bool md = false; int x = 0, y = 0, xs, ys; StreamWriter sw; public Win() SaveFileDialog s = new SaveFileDialog(); DialogResult r = s.showdialog(); sw = new StreamWriter(s.OpenFile()); this.text = "Zápis souřadnic do souboru"; this.mousemove += new MouseEventHandler(Form_MouseMove); this.mouseup += new MouseEventHandler(Form_MouseUp); this.mousedown += new MouseEventHandler(Form_MouseDown); g = this.creategraphics(); Button b1 = new Button(); b1.parent = this; b1.location = new Point(90, 230); b1.width = 100; b1.text = "Uložení"; b1.click += new EventHandler(Click_b1); private void Form_MouseDown(object sender, MouseEventArgs e) md = true; private void Form_MouseUp(object sender, MouseEventArgs e) md = false; 22.9.2011 Kreslení v C# 38/41
private void Form_MouseMove(object sender, MouseEventArgs e) if (x!= 0 && y!= 0 && md) xs = x; ys = y; x = e.x; y = e.y; g = this.creategraphics(); p = new Pen(Color.Blue, 3); g.drawline(p, xs, ys, x, y); sw.writeline("0 1 2 3", xs, ys, x, y); x = e.x; y = e.y; void Click_b1(object obj, EventArgs e) sw.close(); SaveFileDialog se otevře v konstruktoru, kde zvolíme složku a název souboru, pod kterým uložíme souřadnice bodů kresby. Obrázek 23 Dialog Uložit jako Kreslení a ukládání souřadnic bodů do souboru je zajištěno v handleru Form_MouseMove. Po kliknutí na tlačítko se zavře soubor, do nějž se souřadnice ukládají. 22.9.2011 Kreslení v C# 39/41
Uvedené programy máte k dispozici ve spustitelném tvaru v souboru EXE.ZIP. Úlohy Upravte program Program 24 Vylepšené kreslení do formuláře tak, aby obsluhoval: událost MouseClick a po kliknutí pravým tlačítkem aktivoval dialog pro výběr barvy, kterou kreslíme 1. Číselník, kterým by se nastavovala tloušťka čáry Do programu Program 27 Výběr souboru pro čtení dat pomocí OpenFileDialogu doplňte tlačítko pro smazání okna. Do programu Program 27 Výběr souboru pro čtení dat pomocí OpenFileDialogu doplňte tlačítko pro aktivování dialogu pro výběr barvy a zajistěte nakreslení kresby zvolenou barvou. Seznam obrázků Obrázek 1 Aktivace dialogového okna Add Reference... 2 Obrázek 2 Nastavení referencí na jmenný prostor System.Windows.Forms... 2 Obrázek 3 Přidání reference na jmenný prostor System.Drawing... 3 Obrázek 4 Výstup programu Program 8... 10 Obrázek 5 Výstup výše uvedené metody OnPaint... 11 Obrázek 6 Výstup programu Program 9... 11 Obrázek 7 Vyplněný obdélník... 12 Obrázek 8 Volba kresleného útvaru... 13 Obrázek 9 Volba kresleného útvaru pomocí tlačítek... 14 Obrázek 10 Kreslení vyplněných i nevyplněných útvarů... 16 Obrázek 11 Výběr barvy... 18 Obrázek 12 Použití třídy HatchBrush pro tvorbu štětce... 20 Obrázek 13 Výpis textu do okna... 21 Obrázek 14 Nastavení vlastností písma... 22 Obrázek 15 Výpis zadaného textu nastavenou barvou a fontem... 23 Obrázek 16 Výstup programu pro kreslení dvou čar metodou DrawLine... 25 Obrázek 17 Výstup programu pro kreslení domečku metodou DrawLines... 27 Obrázek 18 Průběh funkce sinus, nakreslený s využitím metody DrawLines... 28 Obrázek 19 Ukázka kreslení do formuláře... 31 Obrázek 20 Výstup programu pro čtení souřadnic ze souboru... 35 Obrázek 21 Čtení dat ze souboru... 36 Obrázek 22 Příklad souřadnic bodů pro kreslení obrázku... 37 Obrázek 23 Dialog Uložit jako... 39 22.9.2011 Kreslení v C# 40/41
Seznam programů Program 1 První aplikace pro Windows... 2 Program 2 Nastavení vlastností formuláře... 3 Program 3 Obsluha události Paint metodou OnPaint... 6 Program 4 Volání soukromé metody KresliObdelnik z metody OnPaint... 7 Program 5 Použití metody OnMouseClick pro obsluhu události MouseClick... 7 Program 6 Využití parametru MouseEventArgs pro určení, kterým tlačítkem bylo kliknuto.. 8 Program 7 Obsluha události Resize metodou OnResize... 9 Program 8 Využití argumentu metody OnPaint pro kreslení... 10 Program 9 Program pro nakreslení nevyplněné elipsy... 11 Program 10 Kreslení vyplněného obdélníku... 12 Program 11 Volba kresleného útvaru v konzolovém okně... 13 Program 12 Použití tlačítek pro volbu kresleného útvaru... 14 Program 13 Kreslení vyplněných i nevyplněných útvarů - ovládání pomocí tlačítek... 16 Program 14 Použití dialogu pro nastavení barvy... 17 Program 15 Použití šrafovacích štětců pro výplň útvarů... 19 Program 16 Výpis textu zadané barvy na zadané místo v okně... 20 Program 17 Využití dialogového okna Písmo pro nastavení fontu... 21 Program 18 Výpis zadaného textu nastavenou barvou a fontem... 23 Program 19Kreslení čar metodou DrawLine... 25 Program 20 Kreslení domečku s využitím metody DrawLines... 27 Program 21 Kreslení funkce sinus s využitím metody DrawLines... 28 Program 22 Volba počtu period funkce sinus pomocí číselníku... 29 Program 23 Kreslení do formuláře... 31 Program 24 Vylepšené kreslení do formuláře... 32 Program 25 Uložení souřadnic bodů kresby do souboru... 33 Program 26 Čtení souřadnic pro kreslení ze souboru... 35 Program 27 Výběr souboru pro čtení dat pomocí OpenFileDialogu... 36 Program 28 Program, umožňující uložit kresbu pomocí SaveFileDialogu... 38 Literatura [1] Charles Petzold: Programování Microsoft Windows v jazyce C#, SoftPress, 2003 22.9.2011 Kreslení v C# 41/41