Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.
Wraz z dzisiejszym artykułem, w naszym training kicie rozpoczyna się rozdział nr 6, który skupia się na grafice.
Na dobry początek dostajemy 3-stronnicową tabelkę opisującą najczęściej używane klasy, które pomagają nam w .NET’owym rysowaniu. Nie będę ich opisywał, ale przynajmniej wymienię. Klasy, które zawarte są w przestrzeni System.Drawing to m.in:
Bitmap. Brush, Brushes, ColorConverter, ColorTranslator, Font, FontConverter, FontFamily, Graphics, Icon, IconConverter, Image, ImageAnimator, ImageConverter, ImageFormatConverter, Pen, Pens, PointConverter, RectangleConverter, Region, SizeConverter, SolidBrush, StringFormat, SystemBrushes, SystemColors, SystemFonts, SystemIcons, SystemPens, TextureBrush, ToolboxBitmapAttribute.
Uff.. jest tego trochę :)
Określanie koloru kontrolek
Dzięki klasom zawartym w System.Drawing możemy w bardzo prosty sposób określić kolor naszych kontrolek. W poniższym przykładzie, zmienimy sobie kolor tła oraz napisu kontrolki Button (zakładając, że nazywa się ona button1) :
1: button1.ForeColor = Color.Red;
2: button1.BackColor = Color.Black;
Oczywiście oprócz wbudowanych kolorów, możemy określić własne, w taki sposób:
1: button1.ForeColor = Color.FromArgb(10, 200, 200);
2: button1.BackColor = Color.FromArgb(200, 5, 5);
W parametrze FromArgb wpisujemy odpowiednie składowe RGB.
Rysowanie linii i kształtów
Aby rozpocząć rysowanie, musimy utworzyć obiekt Graphics znajdujący się w przestrzeni nazw System.Drawing. Kiedy mamy już ten obiekt, dostajemy wiele metod, dzięki którym możemy rysować sobie linie, kształty itp. Oto niektóre z nich:
- Clear – czyści powierzchnię po której rysujemy i wypełnia określonym kolorem
- DrawEllipse – rysuje elipse lub okrąg
- DrawIcon and DrawIconUnstretched – rysuje obraz reprezentowany przez określoną ikonę o określonych współrzędnych
- DrawImage, DrawImageUnscaled, and DrawImageUnscaledAndClipped – rysuje obraz z określonej lokalizacji z lub bez skalowania i przycinania
- DrawLine – rysuje linię łączącą dwa punkty
- DrawLines – rysuje serię odcinków
- DrawPath – rysuje serie linii i krzywych
- DrawPolygon – jak sama nazwa wskazuje rysuje wielokąt określony przez tablicę struktur typu Point
- DrawRectangle - rysuje prostokąt lub kwadrat określony przez parę współrzędnych
- DrawString – rysuje tekst w określonym miejscu na ekranie z określonymi właściwościami (np. czcionka itp,)
Aby używać tych metod musimy dostarczyć instancję klasy Pen. W konstruktorze tej klasy określamy kolor oraz szerokość w pikselach. Czas na przykłady :) W poniższym, narysujemy 7-pikselową linie, która ma swój początek w lewym górnym rogu:
1: // Tworzenie obiektu graphics
2: Graphics g = this.CreateGraphics();
3: // Tworzenie obiektu pen i ustawienie w konstruktorze koloru i szerokości
4: Pen p = new Pen(Color.Red, 7);
5: // Rysowanie linii
6: g.DrawLine(p, 1, 1, 100, 100);
Metody Graphics.DrawLines, Graphics.DrawPolygon, i Graphics.DrawRectangles przyjmują tablicę (ze współrzędnymi) jako parametry, pozwalając na tworzenie bardziej skomplikowanych kształtów :)
Poniższy kod wyświetli nam figurę taką jak na obrazku w kolorze fioletowym.

1: Graphics g = this.CreateGraphics();
2: Pen p = new Pen(Color.MediumPurple, 2);
3: // Tworzymy tablicę punktów typu Point
4: Point[] points = new Point[]
5: new Point(10, 10),
6: new Point(10, 100),
7: new Point(50, 65),
8: new Point(100, 100),
9: new Point(85, 40)};
10: // Rysowanie figury określonej przez tablicę
11: g.DrawPolygon(p, points);
Dostosowywanie obiektu Pen
Oprócz kontrolowania koloru oraz rozmiaru Pen’a, możemy dostosować wzór oraz końcówkę. Dzięki końcówce możemy zrobić sobie z linii strzałkę i inne bajery :) Domyślnie linia jest ciągła. Aby zrobić z niej linię przerywaną, należy stworzyć obiekt Pen a następnie ustawić właściwość Pen.DashStyle na jedną z wartości: DashStyle.Dash, Dash-Style.DashDot, DashStyle.DashDotDot, DashStyle.Dot, or DashStyle.Solid. Poniższy kod pokazuje poszczególne style ustawiane na obiekt Pen. Aby kod zadziałał musimy dodać przestrzeń nazw System.Drawing.Drawing2D:
1: Graphics g = this.CreateGraphics();
2: Pen p = new Pen(Color.Red, 7);
3: p.DashStyle = DashStyle.D
4: g.DrawLine(p, 50, 25, 400, 25);
5:
6: p.DashStyle = DashStyle.Dash;
7: g.DrawLine(p, 50, 50, 400, 50);
8:
9: p.DashStyle = DashStyle.DashDot;
10: g.DrawLine(p, 50, 75, 400, 75);
11:
12: p.DashStyle = DashStyle.DashDotDot;
13: g.DrawLine(p, 50, 100, 400, 100);
14:
15: p.DashStyle = DashStyle.Solid;
16: g.DrawLine(p, 50, 125, 400, 125);
Po uruchomieniu kodu otrzymamy taki obraz:

Aby zmodyfikować końcówkę linii musimy do właściwości Pen.StartCap i Pen.EndCap przypisać jakieś pole z enumeracji LineCap.
1: Graphics g = this.CreateGraphics();
2: Pen p = new Pen(Color.Red, 7);
3:
4: p.StartCap = LineCap.ArrowAnchor;
5: p.EndCap = LineCap.DiamondAnchor;
6: g.DrawLine(p, 50, 25, 400, 25);
7:
8: p.StartCap = LineCap.SquareAnchor;
9: p.EndCap = LineCap.Triangle;
10: g.DrawLine(p, 50, 50, 400, 50);
11:
12: p.StartCap = LineCap.Flat;
13: p.EndCap = LineCap.Round;
14: g.DrawLine(p, 50, 75, 400, 75);
15:
16: p.StartCap = LineCap.RoundAnchor;
17: p.EndCap = LineCap.Square;
18: g.DrawLine(p, 50, 100, 400, 100);
Po uruchomieniu otrzymamy taki oto obraz :)

Wypełnianie kształtów
Klasa Graphic posiada metody, które wypełniają różne kształty kolorem bądź gradientem. Metody działają tak samo jak te rysujące z tą różnicą, że do wypełniania potrzebna jest klasa Brush a nie tak jak poprzednio Pen. Klasa Brush jest abstrakcyjna więc musimy używać klasy dziedziczących po niej:
- System.Drawing.Drawing2D.LinearGradientBrush – zwykły liniowy gradient
- System.Drawing.Drawing2D.PathGradientBrush – gradient, w którym możemy ustawiać bardziej skomplikowane przenikanie
- System.Drawing.SolidBrush – wypełnianie pojedynczym kolorem
- System.Drawing.TextureBrush – wypełnianie obrazkiem
Na sam koniec jeszcze dwa przykłady wypełniania. Pierwszy wypełnia pojedynczym kolorem a drugi liniowym gradientem:
1: Graphics g = this.CreateGraphics();
2: //obiekt brush ustawiamy na wypełnienie pojedynczym kolorem
3: Brush b = new SolidBrush(Color.Maroon);
4:
5: Point[] points = new Point[]
6: new Point(10, 10),
7: new Point(10, 100),
8: new Point(50, 65),
9: new Point(100, 100),
10: new Point(85, 40)};
11:
12: g.FillPolygon(b, points);

1: Graphics g = this.CreateGraphics();
2: Pen p = new Pen(Color.Maroon, 2);
3: Brush b = new LinearGradientBrush(new Point(1, 1), new Point(100, 100),
4: Color.White, Color.Red);
5:
6: Point[] points = new Point[]
7: new Point(10, 10),
8: new Point(10, 100),
9: new Point(50, 65),
10: new Point(100, 100),
11: new Point(85, 40)};
12:
13: g.FillPolygon(b, points);
14: g.DrawPolygon(p, points);

To tyle na dzisiaj. Mój następny artykuł i rozdział zarazem będzie dotyczył wątków. A już teraz zapraszam na kolejny wpis, który jak zwykle pojawi się w środę, dotyczący pracy z obrazami :)
Kolejny artykuł z serii to 70-536 Working with Images