Spotkania grupy - Windows Presentation Foundation

W tym tygodniu odbędą się dwa spotkania:

Zapraszam na spotkania :)

Zwracam uwagę, że spotkania są przesuniętę o półgodziny w stosunku do tego co było wcześniej (na Waszą prośbę :) ).

Tagi: , ,

70-536: Starting Multiple Threads

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Zaczynamy rozdział nr 7 w naszym Training Kicie, który będzie dotyczył wątków. Od tej pory przejdziemy z tematów łatwiejszych do nieco trudniejszych:) Dziś wpis bardzo krótki, wprowadzający tylko do wątków.

Po co nam wątki? Dzięki wątkom możemy np. uruchomić jakiś kod w tle, nie blokując w międzyczasie innych czynności naszego programu. Jednak używanie wielowątkowości jest dosyć skomplikowane i w pewnych określonych sytuacjach zamiast zwiększać wydajność, zmniejsza ją. No ale oczywiście więcej mamy plusów korzystając z wątków niż minusów:)

Używanie klasy ThreadPool

Aby uruchomić metodę w tle, używamy klasy System.Threading.ThreadPool. Poniższy kod pokazuje jak używać statycznej metody ThreadPool.QueueUserWorkItem (która zawiera się w przestrzeni System.Threading), do odpalenia własnej metody w nowym wątku.

   1: static void Main(string[] args)
   2:  {
   3:   //Kolejka zadań
   4:    ThreadPool.QueueUserWorkItem(ThreadProc);
   5:    Console.WriteLine("Główny wątek coś robi a następnie zostaje uśpiony.");
   6:    Thread.Sleep(1000);
   7:    Console.WriteLine("Koniec głównego wątku.");
   8:    Console.ReadLine();
   9:  }
  10:  static void ThreadProc(Object stateInfo)
  11:   {
  12:        Console.WriteLine("Pula wątków.");
  13:   }

Za pomocą przeciążonej QueueUserWokItem możemy również przekazać obiekt do metody. Poniższy kod jest rozszerzeniem poprzedniego. Różni się tym, że do metody ThreadProc dostarczymy obiekt stringa:

   1: static void Main(string[] args)
   2:   {
   3:      string state = "Hello, world!";
   4:      //Kolejka zadań
   5:      ThreadPool.QueueUserWorkItem(ThreadProc,state);
   6:      Console.WriteLine("Główny wątek coś robi a następnie zostaje uśpiony.");
   7:      Thread.Sleep(1000);
   8:      Console.WriteLine("Koniec głównego wątku.");
   9:      Console.ReadLine();
  10:   }
  11: static void ThreadProc(Object stateInfo)
  12:  {
  13:     //musimy rzutować na stringa parametr
  14:     string state = (string)stateInfo;
  15:     Console.WriteLine("Pula wątków."+ state);
  16:  }

Metodę ThreadPool.QueueUserWorkItem możemy wywołać wiele razy, nawet jeśli wątki mają wykonać się jednocześnie. Możemy więc zamienić ostatni kod na taki:

   1: static void Main(string[] args)
   2:  {
   3:    ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 1");
   4:    ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 2");
   5:    ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 3");
   6:    ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 4");
   7:    ThreadPool.QueueUserWorkItem(ThreadProc,"Thread 5");
   8:    
   9:  Console.WriteLine("Główny wątek coś robi a następnie zostaje uśpiony.");
  10:  Thread.Sleep(1000);
  11:    
  12:  Console.WriteLine("Koniec głównego wątku.");
  13:          
  14:  }
  15: static void ThreadProc(Object stateInfo)
  16: {
  17:    //musimy rzutować na stringa parametr
  18:     string state = (string)stateInfo;
  19:     Console.WriteLine("Pula wątków."+ state);
  20: }

 

Wątki główne i w tle

Nasz główny wątek aplikacji jest uważany jako foreground thread, czyli ten wątek “na wierzchu”, głowny.Dopóki wątek ten jest aktywny, nasza aplikacja działa. Wszystkie wątki, które działają w tle zostają automatycznie anulowane, w momencie zakończenia głównego wątku. Aby sprawdzić, czy bieżący wątek jest wątkiem w tle czy tym foreground  możemy użyć bool’owskiej właściwości Thread.CurrentThread.IsBackground. Poniższy kod prezentuje wywołanie metody ThreadProc jako wątek background lub foreground. Aby wywołać metodę jako wątek foreground, wywołujemy ją normalnie. Żeby stworzyć wątek w tle, wywołujemy ThreadPool.QueueUserWorkItem:

   1: static void Main(string[] args)
   2:  {
   3:     //wątki, które będą traktowane jako background
   4:     ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 1");
   5:     ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 2");
   6:     
   7:     //wątek wywołany normalnie, potraktowany będzie jako foreground
   8:      ThreadProc("Thread 3"); // Called as part of the foreground thread
   9:     
  10:     //kolejny jako background      
  11:     ThreadPool.QueueUserWorkItem(ThreadProc, "Thread 4");
  12:            
  13:     Console.WriteLine("Main thread does some work, then sleeps.");
  14:     Thread.Sleep(1000);
  15:     Console.WriteLine("Main thread exits.");
  16:     
  17:     Console.ReadLine();
  18:   }
  19:  
  20: static void ThreadProc(Object stateInfo)
  21: {
  22:     //musimy rzutować na stringa parametr
  23:     string state = (string)stateInfo;
  24:     
  25:     //sprawdzamy czy bieżący wątek jest traktowany jako background
  26:     if (Thread.CurrentThread.IsBackground)
  27:                Console.WriteLine("Hello from backgroud thread: " + state);
  28:            else
  29:                Console.WriteLine("Hello from foreground thread: " + state);
  30:  }

To by było na tyle dzisiaj :) W środę Dawid opisze zarządzanie wątkami.

Kolejny artykuł z serii to 70-536 Managing Threads

Tagi: , ,

SQLite i ADO .NET

Chciałbym przedstawić wykorzystanie SQLite w połączeniu z ADO.NET przy wykorzystaniu C#.

[slideshare id=2595661&doc=sqliteiado-net-091127052918-phpapp02]

Wymaga to jednak pewnego uzupełnienia.

SQLite

SQLite jest biblioteką napisaną w języku C, która implementuje silnik relacyjnej bazy danych. Jak głosi główne hasło projektu jest ona “prosta, szybka, niezawodna”. Cała baza znajduje się w pojedynczym pliku, a w przeciwieństwie do innych systemów baz danych, nie występuje tu żaden demon nią zarządzający.

Inne cechy warte wymienienia:

  • Mały rozmiar biblioteki (ok. 0.5MB),
  • ACID
  • Nie wymaga żadnej konfiguracji,
  • Obsługa baz do 2TB.

Kody źródłowe udostępnione są jako domena publiczna (ang. public domain), przez co dostępne dla wszystkich i do dowolnych zastosować – także komercyjnych. Ze względu na brak ograniczeń wykorzystują ją m.in.: Mozilla, Google, Adobe, Apple, Symbian. Wbudowana jest także w interpretery języków PHP i Python.

Jeśli chcemy rozpocząć przygodę najłatwiej jest pobrać konsolowy program sqlite3 (np. sqlite-3_6_17.zip), a następnie dodać go do systemowej zmiennej PATH.

image Wygodniejszym rozwiązaniem może okazać się skorzystanie z któregoś z dostępnych menedżerów:

Dzięki prostemu, łatwemu do wykorzystania API powstało wiele nakładek, które pozwalają na dostęp do danych z innych języków programowania, niż standardowy C.

SQLite ADO.NET 2.0/3.5 Provider

System.Data.SQLite jest silnikiem relacyjnej bazy danych SQLite wraz z dostawcą danych (Data Provider) dla ADO.NET. Wszystko udostępniane jest jako pojedynczy. Wszystko udostępniane jest jako pojedyncze assembly. To, co wyróżnia podaną bibliotekę, to:

  • Dostępność na zasadach public domain,
  • Całkowita implementacja ADO.NET 2.0,
  • Wsparcie dla wersji Full i Compact .NET Framework,
  • Wsparcie dla C/C++,
  • Wsparcie dla Mono,
  • ADO.NET 3.5 Entity Framework,
  • Integracja z Visual Studio 2005/2008.

Po zainstalowaniu biblioteki tworzymy konsolowy projekt (File > New > Project… > Console Application). Następnie dodajemy referencję do System.Data.SQLite (Add Reference… > Zakładka .NET), oraz odpowiednią dyrektywę using, do naszego kodu:

   1: using System.Data.SQLite;

Poniższy kod ilustruje podstawowe operacje na bazie:

   1: // Utworzenie połączenia z bazą. Jeżeli nie istnieje - utworzona zostanie nowa.
   2: var conn = new SQLiteConnection("Data Source = test.db;");
   3: conn.Open();
   4:  
   5: // Utworzenie tabeli
   6: using(var command = conn.CreateCommand()){
   7:     command.CommandText = "CREATE TABLE tbl (id integer primary key, col1 int, col2 string)";
   8:     command.ExecuteNonQuery();
   9: }
  10:  
  11: // Wstawienie danych
  12: using(var command = conn.CreateCommand()){
  13:     command.CommandText = "INSERT INTO tbl (col1, col2) Values('1', 'eastgroup.pl')";
  14:     command.ExecuteNonQuery();
  15: }
  16:  
  17: int col1;
  18: string col2;
  19:  
  20: // Odczyt danych
  21: using(var command = conn.CreateCommand()){
  22:     command.CommandText = "SELECT * FROM tbl";
  23:  
  24:     var reader = command.ExecuteReader();
  25:     reader.Read();
  26:  
  27:     col1 = (int)reader["col1"];            // 1
  28:     col2 = (string)reader["col2"];      // eastgroup.pl
  29: }
  30:  
  31: // Zamykamy połączenie
  32: conn.Close();
  33:  
  34: Console.WriteLine("{0} to nr {1}!", col2, col1);
  35: Console.ReadKey();

Nie jest to jedyna metoda dostępu. Kolejne przykłady będą wymagały jednak bazy northwindEF.db, która znajduje się w plikach źródłowych naszego providera. Aby ją zdobyć należy przejść na stronę System.Data.SQLite na sourceforge i pobrać plik SQLite-*-source.zip (np. SQLite-1.0.65.0-source.zip). Baza znajduje się w katalogu testlinq. Warto otworzyć plik solucji i przejrzeć jej projekty – znajduje się tu sporo ciekawego kodu.

W pliku SQLite_Eastgroup.pl.zip (126,45 kb) zamieściłem dwa przykłady – jeden pokazuje jak korzystać z LINQ, drugi wyświetla dane jednej z tabel za pomocą kontrolki DataGridView. Oba projekty szukają pliku bazy danych w “D:\northwindEF.db”. Jeżeli chcemy to zmienić musimy wyedytować plik App.Config.

image

Podsumowanie

SQLite jest wspaniałym narzędziem. System.Data.SQLite ułatwia wykorzystanie bazy danych z wykorzystaniem .NET Framework. Oto kilka sytuacji, kiedy SQLite sprawdza się najlepiej:

  • Gotowy standard zapisu, format plików dla aplikacji,
  • Urządzenia i aplikacje wbudowane,
  • Strony internetowe (do ok. 100K odwiedzin dziennie),
  • Wewnętrzne lub tymczasowe bazy,
  • Analiza z wiersza poleceń,
  • Dema i testowanie,
  • Edukacja,
  • Nauka pisania rozszerzeń.

A jakie są Wasze doświadczenia z SQLite?

Tagi: ,

70-536: Formatting Text

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Często w pracy z grafiką pojawia się potrzeba dodania tekstu. Może to być np. opis, czy nota autorska. Jeżeli chcemy dodać sformatowany tekst do obrazka należy wykonać kilka kroków.

Utworzenie obiektu Graphics

W tym celu w aplikacji Windows Forms wywołujemy metodę this.CreateGraphics(). Możemy też utworzyć wspomniany obiekt z bitmapy za pomocą metody Graphics.FromImage(bitmap).

   1: Graphics g = this.CreateGraphics();

Utworzyć obiekt Font. Klasa Font oferuje 13 różnych konstruktorów wywołania. Najprostszą metodą, aby utworzyć obiekt Font jest podanie nazwy czcionki, rozmiaru i stylu.

   1: Font f = new Font("Consolas", 12, FontStyle.Bold);

Inną metodą jest np. wykorzystanie FontFamily:

   1: FontFamily ff = new FontFamily("Consolas");
   2: Font f = new Font(ff, 40, FontStyle.Underline);

Utworzenie obiektu Brush

Krok opcjonalny. Najprostszą metodą jest wykorzystanie wyliczenia Brushes, które oferuje pędzle dla wszystkich standardowych kolorów, np.:

   1: Brush b = Brushes.DarkRed;

Opcjonalnie możemy wykorzystać klasę SolidBrush, wyliczenie SystemBrushes,czy bardziej skomplikowany LinearGradientBrush.

Ustawienie opcji wyrównania i kierunku

Możemy kontrolować wyrównaniem (ang. alignment) i kierunkiem (ang. direction) tekstu wykorzystując StringFormat. Jest to oczywiście opcjonalny krok.

Jeżeli chcemy kontrolować wyrównanie napisu należy utworzyć instancję klasy StringFormat. Następnie ustawiamy jej właściwości. Przykładowo jeżeli chcemy wycentrować tekst w poziomie, oraz ustawić wyrównanie do dołu w pionie:

   1: StringFormat f1 = new StringFormat();            
   2: f1.LineAlignment = StringAlignment.Far;
   3: f1.Alignment = StringAlignment.Center;

 

Właściwości:

Rysowanie

Narysowanie tekstu sprowadza się do wywołania Graphics.DrawString wraz z określeniem pozycji dla tekstu. Zakładając, że wszystkie zmienne są zadeklarowane:

   1: g.DrawString("Eastgroup.pl", f, b, 10, 10);

W tym wypadku f to obiekt typu Font, b – typu Brush. Pierwsza wartość liczbowa to x, druga – y. 

 

Składamy przykłady

Pokazane zostały wszystkie elementy niezbędne, aby rozpocząć swoją przygodę z rysowaniem tekstów. Pora złożyć z nich działający przykład:

   1: Font f = new Font("Consolas", 40, FontStyle.Underline);
   2: Brush b = Brushes.DarkRed;
   3: Graphics g = this.CreateGraphics();
   4: g.DrawString("Eastgroup.pl", f, b, 10, 10);

Powyższy kod dodajemy do metody skojarzonej ze zdarzeniem Paint (np. Form1_Paint) w naszej formatce.

image

 

 

Kolejny przykład demonstruje wstawianie tekstu do prostokąta, oraz jego wyrównanie za pomocą StringFormat:

   1: FontFamily ff = new FontFamily("Consolas");
   2: Font f = new Font(ff, 12, FontStyle.Underline);
   3: Brush b = new SolidBrush(Color.Red);
   4:  
   5: StringFormat f1 = new StringFormat();            
   6: f1.LineAlignment = StringAlignment.Far;
   7: f1.Alignment = StringAlignment.Center;
   8:  
   9: Graphics g = this.CreateGraphics();
  10:  
  11: // Rysujemy prostokąt
  12: Rectangle r = new Rectangle(new Point(40, 40), new Size(200, 200));
  13: g.DrawRectangle(Pens.Black, r);
  14:  
  15: g.DrawString("Eastgroup.pl", f, b, (RectangleF)r, f1);

image

Artykuł ten zamyka temat grafiki. W następnym wpisie zapoznamy się z wątkami.

Kolejny artykuł z serii to 70-536: Starting Multiple Threads

Tagi: , , ,

70-536 Working with Images

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Dzisiaj wyjątkowo krótki wpis. Powiemy sobie o tym jak wyświetlić, stworzyć i zapisać rysunek. Żeby nie przedłużać wstępu od razu lecimy z tematem.

The Image and Bitmap Classes

System.Drawing.Image jest klasą abstrakcyjną która umożliwia nam tworzenie, ładowanie, modyfikacje oraz zapis obrazka do formatu .bmp, .jpg oraz .tif. Klasy tej można użyć do stworzenia rysunku, wykresu, zmiany rozmiaru obrazka czy też dodania np. znaku wodnego itd.

Klasa Image jest abstrakcyjna dlatego do stworzenia jej instancji musimy użyć metody Image.FromFile (która przyjmuje ścieżkę do pliku jako parametr) lub metody Image.FromStream (która przyjmuje obiekt System.IO.Stream jako parametr). Można również skorzystać z dwóch klas które dziedziczą po Image: System.Drawing.Bitmap dla obrazów statycznych oraz System.Drawing.Imaging.Metafile dla animacji.

Klasa Bitmap jest najczęściej używaną klasa do pracy na nowych lub istniejących już obrazach. Różne konstruktory pozwalają na utworzenie bitmapy z istniejących już obrazów, plików, strumieni plików czy też stworzenie pustej bitmapy o określonej wysokości i szerokości. Klasa Bitmap zawiera dwie szczególnie przydatne metody których nie zawiera klasa Image:

GetPixel – zwraca kolor obiektu opisującego szczegółowo dany piksel w obrazku. Pikselem jest pojedyncza kropka na rysunku opisana kolorami RGB.

SetPixel – ustawia piksel o określonym kolorze.

Do bardziej złożonej edycji obrazu należałoby użyć obiektu Graphics.

Jak wyświetlić rysunek

No nareszcie jakaś część praktyczna ;) Aby wyświetlić w Windows Forms rysunek należy użyć kontrolki PictureBox. Nic skomplikowanego, spójrzcie na przykład:

   1: // Pamiętajmy o zmianie ścieżki
   2: Image i = Image.FromFile(@"picture.bmp");
   3: // Kontrolka PictureBox nazywa się tutaj pictureBox1
   4: // sorrki ale wole wspomniec bo może ktoś jest po nieprzespanej nocy ;)
   5: pictureBox1.BackgroundImage = i;

Dla obiektu typu Bitmap nie ma żadnej różnicy…wystarczy zastąpić Image na Bitmap, reszta bez zmian.

Alternatywnie do stworzenie tła dla formularza można posłużyć się metodą Graphics.DrawImage, Metoda ta ma 30 przeciążeń także jest szeroki wybór do określenia lokalizacji i wymiarów obrazka. Poniższy przykład demonstruje ustawnie tła które jest niezależne od wymiarów formularza, spójrzmy:

   1: Bitmap bm = new Bitmap(@"picture.jpg");
   2: Graphics g = this.CreateGraphics();
   3: g.DrawImage(bm, 1, 1, this.Width, this.Height);

 

Jak stworzyć i zapisać rysunek?

Spójrzmy na przykład bo wszystko jest tutaj intuicyjne. Warto dodać, że kod poniżej można normalnie uruchomić w konsoli i wszystko pójdzie gdyż nie wyświetlamy grafiki tylko ją tworzymy i zapisujemy. Należy pamiętać również o dodaniu referencji do System.Drawing i dodaniu przestrzeni nazw System.Drawing.Drawing2D, System.Drawing.Imaging.

   1: Bitmap bm = new Bitmap(600, 600);
   2: Graphics g = Graphics.FromImage(bm);
   3: Brush b = new LinearGradientBrush(
   4: new Point(1, 1), new Point(600, 600),
   5: Color.White, Color.Red);
   6: Point[] points = new Point[]
   7: {new Point(10, 10),
   8: new Point(77, 500),
   9: new Point(590, 100),
  10: new Point(250, 590),
  11: new Point(300, 410)};
  12: g.FillPolygon(b, points);
  13: bm.Save("bm.jpg", ImageFormat.Jpeg);

 

Jak używać ikon?

Ikony w .Net Framework to przezroczyste bitmapy o określonych rozmiarach. Standartowo maja one rozmiar 40 x 40 i są zawarte w klasie SystemIcon. Aby dodać ikonę np. do formularza należy posłużyć się metodą Graphics.DrawIcon lub Graphics.DrawIconUnstretched. Przykład zastosowania poniżej:

   1: Graphics g = this.CreateGraphics();
   2: g.DrawIcon(SystemIcons.Question, 40, 40);

To tyle na dzisiaj. Tak jak obiecałem krótko i na temat. Następny artykuł będzie o formatowaniu tekstu a napisze nam go Kamil ;)

Dzięki za poświęcenie czasu.

Kolejny artykuł z serii to 70-536: Formatting Text

Tagi: , ,

70-536: Drawing graphics

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.

image

   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:

image

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 :)

image

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);

image

   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);

image

 

 

 

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

Tagi: , ,

Wstęp do asp.net

Dzięki za przybycie na moja prezentację o asp.net Zdaje sobie sprawę, że nie jestem profesjonalistą w prowadzeniu prezentacji ale mam nadzieje, że wynieśliście coś z niej:) W każdym bądź razie uwierzcie mi, że nie łatwo stać po tej drugiej stronie. Poniżej macie króciutką prezentację a pod spodem cały projekt który robiłem na prezentacji.

Materiały:

Test.rar (60,81 kb)

Tagi: ,

Eastgroup.pl na facebooku