Introduktion til GDI+

Tags:    .net
Skrevet af Bruger #3491 @ 06.05.2005
Introduktion
GDI bruges til at tegne med under Microsoft Windows. GDI+ er en forbedret udgave af GDI (Graphical Device Interface) og er en del af .NET’s klasse bibliotek.
GDI+ klasserne kan findes i følgende namespaces:

- System.Drawing
- System.Drawing2D
- System.Text
- System.Printing
- System.Internal
- System.Imaging
- System.Design

I denne artikel vil jeg forklare noget om de klasser som du skal kende for at kunne bruge GDI+ til at tegne med. Du vil derfor senere kunne bruge artiklen som reference hvis du ikke kan huske hvordan du bruger en af klasserne.

Det er primært klasserne som ligger i System.Drawing der er vigtige at kende. Her findes bl.a klasserne:
Image, Brush, Pen, Font og Graphics.

Men først vil jeg fortælle om de vigtigste strukturer som du skal kende.

Strukturer (structs)
Der er nogle vigtige strukturer det er vigtigt at kende funktionen af. De fleste af de vigtige findes i System.Drawing og er:
Color, Point, Size og Rectangle.

Color strukturen
Repræsentere en RGB farve med en alpha kanal.
Strukturen har en mængde statiske properties der repræsentere hver sin farve.
F.eks. er Color.Green en Color struktur der repræsentere en grøn farve.

Point strukturen
Angiver et punkt I et 2 dimenionelt koordinatsystem. X og Y værdierne er her integers, men der findes også en PointF struktur hvor de istedet er angivet med floats.

Size strukturen
Angiver en størrelse med en bredde og en højde. Har derfor de to properties Width og Height.
Der findes ligesom med Point strukturen en udgave hvor der benyttes floats. Denne hedder SizeF.

Rectangle strukturen
Angiver et rektangel med en position. Man kan nærmest sige at det er sammensmeltning af Size og Point strukturerne. Den har ligeledes en anden udgave hvor der benyttes floats, RectangleF.

Klasserne
I det følgende vil jeg forklare om de vigtigste klasser I GDI+.
Graphics klassen
Graphics klassen er vigtig da den repræsentere en GDI+ overflade som vi vha. forskellige metoder kan tegne på. Et Graphics objekt kan f.eks. repræsentere et billede, en control eller en form.
Hvis vil tegne på en f.eks. en form bliver vi nød til at få en reference til formens Graphics objekt. Det kan gøres på forskellige måder. Enten abonnerer vi på formens Paint event.

Fold kodeboks ind/udKode 

Ellers overrider vi formens OnPaint metode:
Fold kodeboks ind/udKode 


I begge tilfælde finder vi Graphics objektet i PaintEventArgs objektet.
Graphics klassen indeholder en masse forskellige metoder til at tegne med, her er nogen af dem jeg bruger oftest med forklaring.



For en fuld liste så kig på Graphics objektet på msdn, hvor du også kan se parametrene til de forskellige metoder.

Som det kan ses af listen skal der bruges forskellige andre objekter for at tegne kunne noget. Det drejer sig om Brush, Pen og Font objekterne.
Der er en ting der gælder alle disse 3 typer objekter og som er vigtigt at have i tankerne når du skriver kode der gør brug af dem. C# har en garbage collector som burde frigøre objekter fra hukommelsen når du er færdig de ikke bruges mere. Men disse objekter kan på en måde bruge ressourcer hurtigere end garbage collectoren kan frigøre dem. Derfor bør du selv frigører ressourcerne ved at bruge objekternes Dispose() metode når du er færdige med dem.

Fold kodeboks ind/udKode 


Brush klassen
Bruges til definere hvordan former skal udfyldes med farver eller mønstre.
Du kan ikke lave objekter ud fra selve Brush klassen da det er en abstrakt klasse som andre skal nedarve fra. Der findes forskellige af disse i frameworket

I System.Drawing findes følgende Brush implementeringer:
- SolidBrush, udfylder med en enkelt farve.
- TextureBrush, udfylder med et billede.

I System.Drawing.Drawing2D findes følgende Brush implementeringer:
- HatchBrush, udfylder med en valgt HatchStyle, forgrundsfarve og baggrundsfarve. De forskellige HatchStyle’s der kan vælges i mellem findes i enum’en HatchStyle.
- LinearGradientBrush, udfylder med en farveovergang mellem 2 farver eller flere.
- PathGradientBrush, udfylder en GraphicsPath struktur med en farveovergang mellem 2 farver eller flere.

Pen klassen
Et Pen objekt bruges til at tegne linjer med en valgt tykkelse og udfyldningsmetode. Udfyldningsmetoden kan enten være en Brush eller en Color og angives i contructoren.
Der findes således 4 forskellige contructors:
Fold kodeboks ind/udKode 


Pen klassen har en DashStyle property som angiver hvilken DashStyle der skal bruges når der tegnes stiplede linjer. De forskellige DashStyle’s findes i enum’en DashStyle:



Som nævnt i ovenstående tabel kan du definere din egen DashStyle i DashPattern propertyen.
Når du sætter DashPattern propertyen bliver DashStyle propertyen automatiskt sat til DashStyle.Custom.
For at definere dit eget DashPattern laver du et array af floats. Hver anden værdi angiver længden af en streg og hver anden angiver længen af et mellemrum.

For at illustrere det har jeg lavet en lille applikation hvor jeg abonnere på en forms Paint event:
Fold kodeboks ind/udKode 


Den kommer så til at se således ud:


Font klassen
Font klassen definere hvilket format noget tekst skal skrives med. F.eks. skrifttype, størrelse, om teksten skal være normal, fed, kursiv, understreget eller gennemstreget.

Font klassen har over 10 forskellige contructors alt efter hvor meget information du har behov for at give. Når du instantiere et Font objekt finder GDI ud fra parametrene ud af hvilken font du har valgt. Hvis du f.eks. vil have skrifttypen ”Verdana” i størrelse 10, så finder GDI ud af hvilken font der skal bruges. Hvis vi kigger i mappen C:\\Windows\\Fonts kan vi se at der er 4 forskellige ud gaver af Verdana skrifttypen:

verdana.ttf – Normal Verdana
verdanab.ttf – Fed Verdana
verdanai.ttf – Kursiv Verdana
verdanaz.ttf – Fed & Kursiv Verdana

Vores Font objekt peger således på verdana.ttf, hvis vi så vil gøre skrifttypen kursiv kan det ikke gøres ved blot at ændre på Font objektet da det peger på en enkelt fil og ikke gruppen af Verdana filer. Vi bliver i stedet nød til at oprette et nyt Font objekt som så peger på den nye fil.
En af contructorsne tager et Font objekt som parameter og kan ud fra det Font objekt og de resterende parametre finde den ændrede version af skrifttypen.

Her er et eksempel hvor jeg først opretter et Font objekt og derefter modificere det ved at instantiere det igen med en anden constructor.

Fold kodeboks ind/udKode 


Resultat bliver så følgende:


Se evt. mere om Font klassen på msdn, hvor du også kan læse om alle de forskellige constructors.

Afslutning
Jeg håber du kunne bruge artiklen til noget og måske har fået lyst til at læse mere om GDI+, for der er meget mere at lære om emnet.
Jeg var lidt i tvivl om hvornår jeg burde bruge det engelsk og hvornår jeg burde bruge det danske ord til f.eks. strukturer/structs og konstruktører/constructors, så jeg vil meget gerne have kritik af mine valg i den sammenhæng :).

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (3)

User
Bruger #2730 @ 06.05.05 11:02
Dejligt at se en artikel om GDI+. Lige et par ting:

Du skriver at for at få fat i Graphics skal man enten tage fat i det i form_paint eventhandleren eller override OnPaint(). Hvad med at gøre dette: Graphics g = form1.CreateGraphics(); Dette kan gøres alle steder i din kode, så er du fri for at være afhængig af dine events.

I dit eksempel laver du dette trick: Graphics g = e.Graphics; Hvorfor? du har jo allerede e.Graphics, hvorfor lave et nyt objekt nøjagtigt magen til (det er faktisk det samme)? i stedet for bare at bruge e.Graphics.DrawString(.....);

P.S. Garbage Collectoren kører altid med lav priority, det betyder at den ikke vil køre, hvis dit program hele tiden tegner (men hvis du hele tiden laver det trick med at lave et nyt Graphics objekt i din paint metode, så har den på et tidspunkt brugt for meget hukommelse og bliver nødt til at sætte prioriteten op på garbage collectorens tråd) :-)
User
Bruger #2730 @ 06.05.05 11:41
Sry: du allokerer jo ikke hukommelse når du laver dit "Graphics g" trick, som jeg var så hurtig til at skrive....
User
Bruger #5910 @ 19.08.05 19:51
Rart med en artikel om 2D!
Du skal være logget ind for at skrive en kommentar.
t