Entwickler-Ecke

Delphi Tutorials - GDI+ - Teil 1


Anonymous - Mi 30.07.03 22:57
Titel: GDI+ - Teil 1
GDI+

1. Was ist überhaupt das "GDI"?

Das GDI ist seit der ersten Version von Windows die Schnittstelle für Grafikausgaben aller Art. Seit Windows XP hat Microsoft eine neue, überarbeitete Version in Windows eingeführt. Beim GDI+ sind verschiedene neue Funktionen hinzugekommen, das Problem dabei ist jedoch, dass nur bei Windows XP Standardmäßig eine Unterstützung dafür vorhanden ist. Allerdings läßt sich alles nach inklusive Windows 98 Aufrüsten (Siehe Link am Ende)
Folgende neue Funktionen sind hinzugekommen:


2. Möglichkeiten

Es gibt mehrere Möglichkeiten das neue GDI zu nutzen. Entweder man nutzt eine Headerdatei,
wie ich sie z.B. hier [http://odown.de.vu/GdiPlus.zip] hochgeladen habe. Man kann auch Komponenten nutzen, wobei man sich dann in der Regel nicht mehr um die Header zu kümmern braucht. (hier [http://www.delphi-forum.de/viewtopic.php?t=14447] habe meine vorgestellt). Ich werde hier nur auf die Verwendung der Header eingehen, dabei sollte es auch möglich sein, andere Übersetzungen zu nutzen.

3. Grundgerüst

Das Grundgerüst jeder GDI+ Zeichenoperation sieht folgendermaßen aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
 graphic: GGraphics;
begin
 graphic := GGraphics.Create(DeviceContext);
 try
  // Zeichenoperationen
 finally
  graphic.free;
 end;
end;


Alternativ kann man natürlich auch auf die Variable verzichten indem man das ganze in einen with-try-finally Block einbaut.

4. Zusatzmethoden

Ich nutze folgende Zusatzmethoden, die einige Tipparbeit ersparen können (auch wenn hier nicht alle gebraucht werden):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
function RGBToColor(r,g,b: byte): color;
begin
 result.New(r,g,b);
end;

function ARGBToColor(a, r,g,b: byte): color; overload;
begin
 result.New(a,r,g,b);
end;

function ARGBToColor(argb: cardinal): color; overload;
begin
 result.New(argb);
end;

function MakePoint(x,y: integer): point;
begin
 result.New(x,y);
end;

function MakePointF(x,y: single): pointf;
begin
 result.New(x,y);
end;


5. Zeichnen von Bildern und Transformationen

Die einfachste Bild-Zeichen-Methode sieht folgendermaßen aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var
 graphic: GGraphics;
 img: Image;
begin
 graphic := GGraphics.Create(Canvas.Handle);
 try
  // Bild öffnen
  img := Image.Create('knorkwarz1.bmp');
  try
   // Bild zeichnen
   graphic.DrawImage(img, 1010);
  finally
   // Bild freigeben
   img.Free; 
  end;
 finally
  graphic.free;
 end;
end;


Hier wird zuerst das Bild geöffnet, an Position 10,10 gezeichnet und wieder freigegeben.
Ein Hinweis zu FromFile: Die Funktion ist eine Klassenmethode, also muss man Image.FromFile('...') schreiben. Die Rückgabe ist zwar eine neue Instanz vom Typ Image, die man auch wieder Ordungsgemäß freigeben sollte. Richtig ist also img := image.FromFile('dateiname')

Jetzt wollen wir unser Bild noch Drehen, danach verschieben und zuletzt wieder in der Ursprünglichen Form zeichnen.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
var
 graphic: GGraphics;
 img: Image;
begin
 graphic := GGraphics.Create(Canvas.Handle);
 try
  // Bild öffnen
  img := Image.Create('Bild.bmp');
  try
   // Komplette Leinwand um 20° drehen
   graphic.RotateTransform(20);
   // Bild zeichnen
   graphic.DrawImage(img, 1010);
   // Um 20 Pixel jeweils nach unten und nach rechts Verschieben
   graphic.TranslateTransform(2020);
   // Bild zeichnen
   graphic.DrawImage(img, 1010);
   // Ursprünglichen Zustand wiederherstellen (für eventuelle weitere Zeichenoperationen)
   graphic.ResetTransform;
   // Bild freigeben
  finally
   img.Free;
  end;
 finally
  graphic.free;
 end;
end;


Je nach Größe des Bildes kann es sein, dass sich die Bilder überlappen. Am besten ist es, jede Zeile einmal auszuklammern und die Werte zu ändern, damit man sieht, was passiert.

Man sieht, dass Transformationen nicht nur eine Zeichenoperation erhalten bleiben, sondern so lange, bis entweder mit SetTransform(matrix) eine Transformationsmatrix geladen wird, oder mit Resettransform wieder der Ursprüngliche Zustand hergestellt wird.

6. Textausgabe

Wenn man zum Text kommt, wird das Ganze schon etwas umständlicher.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
procedure TForm1.Button2Click(Sender: TObject);
var
 graphic: GGraphics;
 brush: SolidBrush;
 font: GFont;
 col: GpColor;
 pt: Gppointf;
begin
 graphic := GGraphics.Create(Canvas.Handle);
 try
  // Mit weiß füllen
  col.new(255,255,255);
  graphic.Clear(col);
  // Ist später die Farbe des Textes
  col.new(255,0,0);
  brush := SolidBrush.Create(col);
  try
   // Die Schrift erstellen. Achtung: das G vor dem hinteren
   // Font nicht vergessen.
   // Der vordere Parameter ist die Schriftart, der hintere
   // die Größe
   font := GFont.Create('times'30);
   try
    // Die Position des Textes
    pt.new(10,10);
    // Text ausgeben
    graphic.DrawString('Test', -1, font, pt, brush);
    // Schrift und brush freigeben
   finally
    font.free;
   end;
  finally
   brush.Free;
  end;
 finally
  graphic.free;
 end;
end;


Bei GFont.Create(...) lassen sich auch mehr als 2 Parameter angeben. Beispiel:

font := GFont.Create('times', 10, FontStyleBold or FontStyleUnderline, UnitMillimeter);

für fetten, unterstrichenen, 10 Millimeter hohen Text.
Für FontStyle... lassen sich folgende Werte eintragen (Die auch mit or verknüpft werden können):


Quelltext
1:
2:
3:
4:
5:
6:
FontStyleRegular ......Normal (Standard)
FontStyleBold .........Fett
FontStyleItalic .......Kursiv
FontStyleBoldItalic ...Fett + Kursiv (FontStyleBold or FontStyleItlic)
FontStyleUnderline ....Unterstrichen
FontStyleStrikeout ....Durchgestrichen

Für Unit... sind folgende Werte interessant:

Quelltext
1:
2:
3:
4:
5:
UnitPixel .............Jede Einheit ist ein Pixel   
UnitPoint .............Jede Einheit ist ein Punkt eines Druckers oder 1/72 Inch
UnitInch ..............Jede Einheit ist ein Inch
UnitDocument ..........Jede Einheit ist 1 / 300 Inch
UnitMillimeter ........Jede Einheit ist ein Millimeter


Selbstverständlich sind Transformationen auch für Text.

7. Cardinal SPlines und Linien

Wenn man sich die Deklaration von DrawCurve ansieht,

Delphi-Quelltext
1:
function Graphics.DrawCurve(const pen: Pen; points: PointF; count: integer): Status;                    

Fällt auf dass weder ein Array noch ein Pointer vorhanden ist. Allerdings funktioniert es wenn man das erste Element eines Arrays übergibt.

Hier jetzt noch ein Beispiel zur Verwendung:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
var
 graphic: GGraphics;
 pen: GPen;
 col: gpcolor;
 i: integer;
 pts: array[0..3of point;
begin
 graphic := GGraphics.Create(Canvas.Handle);
 try
  // Mit weiß füllen
  col.new(255,255,255);
  graphic.Clear(col);
  // Pen in rot mit Dicke 1.5 erstellen
  pen := GPen.Create(255001.5);
  // alles um 100 Pixel nach unten und rechts verschieben
  Graphic.TranslateTransform(100,100);
  // Kurven mit unterschiedlicher Spannung zeichnen
  pts[0] := MakePoint(0,0);
  pts[1] := MakePoint(40,70);
  pts[2] := MakePoint(150,90);
  pts[3] := MakePoint(200,30);
  for i := 0 to 8 do
   graphic.DrawCurve(pen, pts[0], 4, i/2);
  // Nach eine schöne Linie:
  graphic.ResetTransform;
  Graphic.TranslateTransform(0,30);
  graphic.DrawLine(pen, 10250400,300);
  // Und ein Rechteck
  graphic.DrawRectangle(pen, 40,60,310,170);
  // Und einen Kreis
  graphic.DrawEllipse(pen, 370,0,100,100);
 finally
  graphic.free;
 end;
end;


Die Funktionen für das Füllen von Rechtecken und Ellipsen heißen FillRectangle und FillEllipse.

So, ich habe jetzt genug für Heute, morgen mache ich vielleicht den 2. Teil. Dort werden dann mit Muster gefüllte Polygone, normale Polygone, Bézierkurven, Kuchen und weitere Funktionen beim Bilder-Zeichnen drankommen.

http://www.microsoft.com/downloads/details.aspx?... [http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=BFC0B436-9015-43E2-81A3-54938B6F4614]

Moderiert von user profile icontommie-lie: Link korrigiert

//Edit: Den einen oder anderen inhaltlichen Fehler korrigiert und den Headerlink aktualisiert
//Edit2: try-finally-Blocks eingebaut


mimi - So 08.08.04 10:00

der ertelink geht nicht... kennst du noch einen andrenlink ?


raziel - So 08.08.04 11:13

Meinst Du den hier [http://pages.infinit.net/smarth/gdiplus.html]?
Da gäbs hier [http://www.progdigy.com/headers/] ne Alternative für...

raziel


Anonymous - So 08.08.04 11:29

Ich lad den Header den ich benutze einfach nochmal bei mir hoch.


mimi - So 08.08.04 13:31

danke !!!


jdv - Mo 04.04.05 15:47

Ich habe versucht das Sample runtergeladen jedoch scheint dir URL nicht mehr zu stimmen.


raziel - Mo 04.04.05 17:12

Was meinst Du? Alle Links die ich im obigen Beitrag finden konnte funktionierten.


GTA-Place - Mo 04.04.05 17:44

Das meint er:

Microsoft hat folgendes geschrieben:

The download you requested is unavailable. If you continue to see this message when trying to access this download, you might try the "Search for a Download" area on the Download Center home page.


Und:

http://pages.infinit.net/smarth/gdiplus.html und http://www.progdigy.com/headers/ hat folgendes geschrieben:
Die Seite wurde nicht gefunden.


raziel - Mo 04.04.05 20:07

user profile iconGTA-Place hat folgendes geschrieben:
Das meint er:

Microsoft hat folgendes geschrieben:

The download you requested is unavailable. If you continue to see this message when trying to access this download, you might try the "Search for a Download" area on the Download Center home page.

Sucht ihr das hier?
http://www.microsoft.com/downloads/results.aspx?productID=&freetext=gdi%2B&DisplayLang=en

user profile iconGTA-Place hat folgendes geschrieben:
Und:

http://pages.infinit.net/smarth/gdiplus.html und http://www.progdigy.com/headers/ hat folgendes geschrieben:
Die Seite wurde nicht gefunden.

Aber er hat das doch noch auf seinen eigenen Space hochgeladen:
http://odown.de.vu/GdiPlus.zip