[X] Die Windows GDI+
-
Soweit liest es sich gut und macht Lust auf mehr.
keine kryptischen Variablennamen aus ungarischer Notation
Gegen die Wertung muss ich aber protestieren. Ich finde das nämlich nicht kryptisch sondern nützlich.
Vielleicht sollte man das, um einen Flamewar zu verhindern, etwas entschärfen.
-
Das mit der ungarische Notation werde ich in der nächsten Fassung raus nehmen. Kein Problem.
SideWindwer! Welche pers. Wertungen meinst du? Auch die estartu_de meint?
-
Meine Vermutung geht dahin, das dies durch die anspruchsvollere WinXP-GUI Luna hervorgekommen ist. Also eine leistungsfähigere Grafik-Bibliothek entwicklt aus reinem Selbstzweck.
Ich dachte du bist immer gegen wage Mutmaßungen was Microsoft angeht?
Die Entwickler von Microsoft haben mit der GDI+ nach vielen Jahren endlich mal eine Bibliothek entworfen die einem C++ Programmierer nicht peinlich sein muß.
Könnte man eventuell auch weniger negativ sagen.
Aber dein Artikel - wenn du auf rege Diskussionen im Nachhinein stehst
MfG SideWinder
-
Hihi, wegen den Mutmassungen meinst du wegen "MS lässt C++ fallen" u.ä.? Naja, bei mir ist es anders: ich bringe _positive_ Mutmassungen bezogen auf C++.
Ich werde das ganze tatsächlich mal entschärfen. Aber ich darf noch positiv über die GDI+ schreiben?
-
Positiv kannst du die GDI+ verherrlichen wie du willst, aber positiv über etwas schreiben heißt nicht negativ über alles andere zu schreiben
Der Knackpunkt liegt eindeutig bei:
...nach vielen Jahren endlich mal eine...
MfG SideWinder
-
@Artchi
Da ich selbst eine Niete in Sachen Rechtschreibung bin sollte ich eigentlich besser ruhig sein aber "Mutmassungen" sind glaube ich immer noch "Mutmaßungen"
-
Die Windows GDI Plus (GDI+)
In diesem C++ Artikel geht es um die relativ neue Grafik Bibliothek GDI+ von Microsoft für Windows.
1. Einleitung
2. Technische Voraussetzungen
3. Sauberes C++ von Microsoft
4. Was kann die GDI+?
5. Hello World!
6. Mächtige Graphics
7. Bilder laden und zeichnen1. Einleitung
Wer bisher in seinen Windows-Anwendungen Grafikfunktionen benötigt hat, hat meistens die alte GDI API benutzt. Immerhin erfüllt sie ihren Zweck und ist seit eh und je in Windows vorhanden. Für C++ Programmierer ist sie jedoch leider eine API die nicht auf einer OO-Sprache basiert, obwohl sie einen objektorientieren Ansatz verfolgt. Doch könnte es für einen C++ Programmierer viel komfortabler sein komplexere Grafiken zu erstellen als dies mit der GDI der Fall ist. Um zu ansprechenderen Ergebnissen in kürzerer Zeit zu gelangen, muß man sich mit der GDI aktuelle Effekte selbst entwickeln oder kombinieren.Mit Erscheinen von Windows XP hat Microsoft jedoch die Zeichen der Zeit erkannt eine leistungsfähigere API eingeführt. Und schon sind wir bei der neuen GDI+ Bibliothek angelangt.
2. Technische Voraussetzungen
Die GDI+ ist in jedem Windows XP serienmäßig dabei, ist jedoch nicht auf Windows XP beschränkt. Es kann auch auf Windows 2000, Windows NT 4.0 SP6 und Windows 98/ME mit einer zusätzlichen DLL ohne Installation eingesetzt werden. Die kostenlose GDI+ für Endbenutzer ist auf der GDI+ Homepage als Download verfügbar.3. Sauberes C++ von Microsoft
Die Entwickler von Microsoft haben mit der GDI+ eine Bibliothek entworfen die einem C++ Programmierer nicht peinlich sein muß. Keine Makros, keine Prefixe sondern Namespaces und klare Parameternamen. Die Freigabe von Resourcen, wie sie in der alten GDI nötig war, entfällt durch die Fähigkeiten der C++-Stackobjekte ebenfalls. Alles das hätten wir uns von Microsoft viel früher gewünscht. Aber lieber spät als nie.Vom Programmierer werden Kenntnisse in C++ und der Objekt Orientierung verlangt, wobei diese auf einer einfachen Ebene stattfinden ("weil einfach einfach einfach ist!"). Templates o.ä. muß man nicht kennen, was die GDI+ auf jeden Fall auch für C++ Einsteiger sehr interessant macht. Besonders diese können schnell und einfach in die Grafikprogrammierung einsteigen ohne in die Gefahr der Speicherlecks o.ä. zu laufen.
4. Was kann die GDI+?
Wem die oben genannten Argumente immer noch nicht überzeugt haben, wird dies ganz bestimmt durch die Features der GDI+. Prinzipiell deckt die GDI+ alle Bereiche der 2D-Grafik ab, so lange man kein Actionspiel programmieren will. Aber 2D-Vectorgrafik mit Transformationnen und Translationen in Kombination mit Spezialeffekten sind für jeden intuitiv umsetzbar. Weiterhin unterstützt werden das codieren und decodieren von wichtigen Grafikformaten, dazu gehören z.B. JPEGs, PNGs, TIFFs u.a. Diese Bitmaps kann man ebenfalls wie die Vectorfunktionen mit Effekten versehen und transformieren (z.B. skallieren). Wie das alles sehr einfach, schnell und intuitiv umsetzbar ist, werde ich jetzt endlich zeigen.5. Hello World!
Ich gehe in diesem Tutorial nicht auf die Windows-Programmierung ein. Deshalb werde ich nur auf die relevanten Teile für die GDI+ eingehen. Um die GDI+ nutzen zu können, muß die gdiplus.lib dem Linker mitgeteilt werden und bei Nicht-WinXP-Systemen die gdiplus.dll in den Arbeitspfad gelegt werden. Wer mit dem VisualC++ ein Win32-Projekt anlegt muß unbedingt das Makro WIN32_LEAN_AND_MEAN entfernen (wird im stdafx.h definiert), da man sonst Compilierungs-Fehler bekommt. Schon steht dem Programmieren nichts mehr im Weg.Für ein erstes einfaches Beispiel werden wir die GDI+ initialisieren und eine Linie zeichnen.
#include <gdiplus.h> using namespace Gdiplus; // 01 INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) { // ... GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 02 // ... paint(hdc); // ... GdiplusShutdown(gdiplusToken); // 03 } void paint(HDC hdc) { Graphics graphics(hdc); // 04 Pen pen(Color(255, 0, 0, 255)); // 05 graphics.DrawLine(&pen, 0, 0, 200, 100); // 06 }
Erklärungen zu den einzelnen Zeilen:
01: Um nicht vor jeder Klasse oder Funktion ein "Gdiplus::" zu schreiben, benutzen wir implizit den Namespace.
02: Im Startpunkt unserer Anwendung (hier die WinMain-Funktion) sollten wir die GDI+ initialisieren. Da die GDI+ eine komplexere Initialisierung durchführt, ist dieser Aufruf nur einmalig zu empfehlen und nicht vor jedem Zeichenvorgang. Das gdiplusTocken (ein Pointer) darf nicht verloren gehen, damit man die GDI+ wieder deinitialisieren kann. Das ist der einzige Pointer der unfreiwillig bei der GDI+ Nutzung entsteht.
03: Die GdiplusShutdown()-Funktion will den gültigen gdiplusToken-Pointer haben um die GDI+ zu beenden. Dieser Aufruf kann und sollte erst kurz vor Beenden der Anwendung aufgerufen werden.
04: Hier geht es endlich zur Sache. Gdiplus::Graphics ist die wichtigste Klasse die uns begegnet. Sie stellt sozusagen die Zeichenfläche da auf der sich das Geschehen abspielt. In dem Beispiel beziehen wir die Zeichenfläche auf ein HDC-Device (z.B. ein Fenster). Wir hätten auch eine Bitmap übergeben können, welche sich nicht auf dem Bildschirm befindet. So könnte man Bitmaps im Hintergrund manipulieren.
05: Zum Zeichnen benötigt man auch ein Werkzeug, wir instanzieren hier einen Stift und übergeben dem Konstruktor gleich eine Wunschfarbe. Gdiplus::Color ist eine Farbenklasse die auch einen Alphachannel unterstützt, somit sind auch transluzente Farben kein Problem.
06: Auf unserer Zeichfläche (graphics) können wir Aktionen ausführen, z.B. mit DrawLine eine Linie ziehen. Als Parameter erwartet diese Methode einmal das Werkzeug (unseren blauen Stift) und die X/Y-Koordinaten jeweils für den Start- und Endpunkt unserer Linie. Das Beispiel zeichnet eine blaue Linie von oben links diagonal nach rechts unten.
Wie man an unserer paint() Funktion sieht, können wir alle Objekte auf dem Stack anlegen brauchen diese deshalb nicht wieder mit einem delete oder ominösen release()-Funktion freigeben.
6. Mächtige Graphics
Das Graphics-Objekt legt man wahlweise vor jeder Zeichensequenz neu an oder einmalig und löscht sie jedesmal mit der Clear() Methode. ...
-
Die GDI Plus (Teil 1)
In diesem C++ Artikel geht es um die relativ neue Grafik Bibliothek GDI+ für Windows.
1. Einleitung
2. Technische Voraussetzungen
3. Sauberes C++ von Microsoft
4. Was kann die GDI+?
5. Hello World!
6. Mächtige Graphics
7. Ausblick
A. Links1. Einleitung
Wer bisher in seinen Windows-Anwendungen Grafikfunktionen benötigt hat, hat meistens die alte GDI API benutzt. Immerhin erfüllt sie ihren Zweck und ist seit eh und je in Windows vorhanden. Für C++ Programmierer ist sie jedoch leider eine API die nicht auf einer OO-Sprache basiert, obwohl sie einen objektorientieren Ansatz verfolgt. Doch könnte es für einen C++ Programmierer viel komfortabler sein komplexere Grafiken zu erstellen als dies mit der GDI der Fall ist. Um zu ansprechenderen Ergebnissen in kürzerer Zeit zu gelangen, muß man sich mit der GDI aktuelle Effekte selbst entwickeln oder kombinieren.Mit Erscheinen von Windows XP hat Microsoft jedoch die Zeichen der Zeit erkannt eine leistungsfähigere API eingeführt. Und schon sind wir bei der neuen GDI+ Bibliothek angelangt.
2. Technische Voraussetzungen
Die GDI+ ist in jedem Windows XP serienmäßig dabei, ist jedoch nicht auf Windows XP beschränkt. Es kann auch auf Windows 2000, Windows NT 4.0 SP6 und Windows 98/ME mit einer zusätzlichen DLL ohne Installation eingesetzt werden. Die kostenlose GDI+ für Endbenutzer ist auf der GDI+ Homepage als Download verfügbar.3. Sauberes C++ von Microsoft
Die Entwickler von Microsoft haben mit der GDI+ eine Bibliothek entworfen die einem C++ Programmierer nicht peinlich sein muß. Keine Makros, keine Prefixe sondern Namespaces und klare Parameternamen. Die Freigabe von Resourcen, wie sie in der alten GDI nötig war, entfällt durch die Fähigkeiten der C++-Stackobjekte ebenfalls. Alles das hätten wir uns von Microsoft viel früher gewünscht. Aber lieber spät als nie.Vom Programmierer werden Kenntnisse in C++ und der Objekt Orientierung verlangt, wobei diese auf einer einfachen Ebene stattfinden ("weil einfach einfach einfach ist!"). Templates o.ä. muß man nicht kennen, was die GDI+ auf jeden Fall auch für C++ Einsteiger sehr interessant macht. Besonders diese können schnell und einfach in die Grafikprogrammierung einsteigen ohne in die Gefahr der Speicherlecks o.ä. zu laufen.
4. Was kann die GDI+?
Wem die oben genannten Argumente immer noch nicht überzeugt haben, wird dies ganz bestimmt durch die Features der GDI+. Prinzipiell deckt die GDI+ alle Bereiche der 2D-Grafik ab, so lange man kein Actionspiel programmieren will. Aber 2D-Vectorgrafik mit Transformationnen und Translationen in Kombination mit Spezialeffekten sind für jeden intuitiv umsetzbar. Weiterhin unterstützt werden das codieren und decodieren von wichtigen Grafikformaten, dazu gehören z.B. JPEGs, PNGs, TIFFs u.a. Diese Bitmaps kann man ebenfalls wie die Vectorfunktionen mit Effekten versehen und transformieren (z.B. skallieren). Wie das alles sehr einfach, schnell und intuitiv umsetzbar ist, werde ich jetzt endlich zeigen.5. Hello World!
Ich gehe in diesem Tutorial nicht auf die Windows-Programmierung ein. Deshalb werde ich nur auf die relevanten Teile für die GDI+ eingehen. Um die GDI+ nutzen zu können, muß die gdiplus.lib dem Linker mitgeteilt werden und bei Nicht-WinXP-Systemen die gdiplus.dll in den Arbeitspfad gelegt werden. Wer mit dem VisualC++ ein Win32-Projekt anlegt muß unbedingt das Makro WIN32_LEAN_AND_MEAN entfernen (wird im stdafx.h definiert), da man sonst Compilierungs-Fehler bekommt. Schon steht dem Programmieren nichts mehr im Weg.Für ein erstes einfaches Beispiel werden wir die GDI+ initialisieren und eine Linie zeichnen.
#include <gdiplus.h> using namespace Gdiplus; // 01 INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) { // ... GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 02 // ... paint(hdc); // ... GdiplusShutdown(gdiplusToken); // 03 } void paint(HDC hdc) { Graphics graphics(hdc); // 04 Pen pen(Color(255, 0, 0, 255)); // 05 graphics.DrawLine(&pen, 0, 0, 200, 100); // 06 }
Erklärungen zu den einzelnen Zeilen:
01: Um nicht vor jeder Klasse oder Funktion ein "Gdiplus::" zu schreiben, benutzen wir implizit den Namespace.
02: Im Startpunkt unserer Anwendung (hier die WinMain-Funktion) sollten wir die GDI+ initialisieren. Da die GDI+ eine komplexere Initialisierung durchführt, ist dieser Aufruf nur einmalig zu empfehlen und nicht vor jedem Zeichenvorgang. Das gdiplusTocken (ein Pointer) darf nicht verloren gehen, damit man die GDI+ wieder deinitialisieren kann. Das ist der einzige Pointer der unfreiwillig bei der GDI+ Nutzung entsteht.
03: Die GdiplusShutdown()-Funktion will den gültigen gdiplusToken-Pointer haben um die GDI+ zu beenden. Dieser Aufruf kann und sollte erst kurz vor Beenden der Anwendung aufgerufen werden.
04: Hier geht es endlich zur Sache. Gdiplus::Graphics ist die wichtigste Klasse die uns begegnet. Sie stellt sozusagen die Zeichenfläche da auf der sich das Geschehen abspielt. In dem Beispiel beziehen wir die Zeichenfläche auf ein HDC-Device (z.B. ein Fenster). Wir hätten auch eine Bitmap übergeben können, welche sich nicht auf dem Bildschirm befindet. So könnte man Bitmaps im Hintergrund manipulieren.
05: Zum Zeichnen benötigt man auch ein Werkzeug, wir instanzieren hier einen Stift und übergeben dem Konstruktor gleich eine Wunschfarbe. Gdiplus::Color ist eine Farbenklasse die auch einen Alphachannel unterstützt, somit sind auch transluzente Farben kein Problem.
06: Auf unserer Zeichfläche (graphics) können wir Aktionen ausführen, z.B. mit DrawLine eine Linie ziehen. Als Parameter erwartet diese Methode einmal das Werkzeug (unseren blauen Stift) und die X/Y-Koordinaten jeweils für den Start- und Endpunkt unserer Linie. Das Beispiel zeichnet eine blaue Linie von oben links diagonal nach rechts unten.
Wie man an unserer paint() Funktion sieht, können wir alle Objekte auf dem Stack anlegen brauchen diese deshalb nicht wieder mit einem delete oder ominösen release()-Funktion freigeben.
6. Mächtige Graphics
Das Graphics-Objekt legt man wahlweise vor jeder Zeichensequenz neu an oder einmalig und löscht sie jedesmal mit der Clear() Methode. Hat man das gemacht, kann man allerhand damit anstellen, denn sie verfügt über 188 Methoden.Sehr leicht kann man z.B. eine Figur (Rechteck, Ellipse, Pfade usw.) rotieren, verschieben und skallieren lassen. Diese aktionen benötigen dabei jeweils nur eine einzige Zeile Programmcode. Das folgende Beispiel zeichnet erst ein Rechteck und verschiebt dann ein zweites Rechteck nach unten links und dreht es dann um 28°.
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); Pen pen(Color::Blue, 1); // 01 graphics.DrawRectangle(&pen, rect); pen.SetColor(Color::Red); graphics.TranslateTransform(100,100); // 02 graphics.RotateTransform(28.0f); // 03 graphics.DrawRectangle(&pen, rect); // 04
01: Unser Stift bekommt die Farbe blau, da die Klasse Color uns schon Enumerationen für viele Farben bereitstellt. Selbst Farben die uns Männern nichts sagen, aber wohl den Damen, sind vordefiniert.
02: Nachdem wir das erste Rechteck gezeichnet haben, bewegen wir unseren Grafikkontext um 100/100 (X/Y) Pixel.
03: Jetzt rotieren wir den Grafikkontext um 28°.
04: Auf Grund der vorherigen Aktionen wird unser Rechteck an einer ganz anderen Stelle gezeichnet. Das Rechteck selbst braucht man nicht verändern, es soll sich einfach nur zeichnen. Das hat den Vorteil, das sich die Transformationen auf alle möglichen Figuren auswirken. Und somit die Figuren selbst keine Transformations-Methoden bieten müssen. Kann man ganz gut mit dem STL-Konzept vergleichen, wo die Container auch keine Algorithmen a la Sortieren oder Suchen haben.
Wer will kann auch mit der Methode ScaleTransform() seine Figuren skallieren, d.h. in der Größe ändern.
Hier noch ein Beispiel das eindrucksvoll zeigt, wie man mit einer zusätzlichen Zeile Code (in dem Fall eine for-Schleife) etwas spektakuläres zaubern kann:
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); Pen pen(Color::Red, 1); graphics.TranslateTransform(100,100); for(int i =0; i < 360; i=i+10) { // for-Schleife neu graphics.RotateTransform(i); // dynamische Rotation mehrmals durchlaufen graphics.DrawRectangle(&pen, rect); }
7. Ausblick
Das war jetzt der erste Teil in dem ich euch die GDI+ hoffent schmackhaft machen konnte. Sicherlich waren die die Ergebnisse auf dem Bildschirm nicht sehr spektakulär, doch an den Beispiel-Codes kann man sehen, das man mit sehr wenig Programmieraufwand spektakulärere Ergebnisse zaubern kann. Im nächsten Teil werde ich etwas tiefer in die Möglichkeiten der GDI+ Figuren eingehen. Auf Bitmaps aus Dateien werde ich auch noch eingehen.
A. Links
GDI+ Homepage
Neueste SDK-Distribution
GDI+ Reference
-
Danke.
-
Uhh, das schaut cool aus, hat MS mal was richtig geiles auf die Beine gestellt (auch wenn's mich stark an Java erinnert ), vllt. werd ich doch noch Windows installieren...
-
Das wird mit WPF noch viel geiler!
-
Natürlich ist das super. Deshalb poche ich z.B. auch darauf, endlich mal von den ollen Libs und ollen C++ Compilern weg zu kommen. Ich habe erst vor ein oder zwei Tagen im MFC-Forum empfohlen die GDI+ anstatt die GDI zu benutzen. Weil einem Fragesteller als Antwort GDI-Code gepostet wurde. Habe von dem GDI-Antworter als antwort erhalten, das der Fragesteller nur einfache Sachen machen will, und da reicht die GDI. Aber darum geht es doch garnicht?!
C++ würde einen viel besseren Ruf haben, wenn man endlich neue Techniken fördert. Ihr glaubt garnicht was für einen schlechten Ruf C++ hier in meinem Berufsumfeld hat. Ca. 3000 Java-Programmierer arbeiten für unseren Kunden die nur Halbwissen über C++ haben und dieses gerne erzählen, wenn das Thema mal aufkommt. Dabei kann C++ ziemlich Idiotensicher sein, wie die GDI+ Beispiele aufzeigen.
-
So, jetzt habe ich es auch geschafft, deinen Artikel zu lesen.
Er ist soweit gut verständlich und macht Lust auf mehr - so solls sein.
-
Die GDI Plus (Teil 1)
In diesem C++ Artikel geht es um die relativ neue Grafik Bibliothek GDI+ für Windows.
1. Einleitung
2. Technische Voraussetzungen
3. Sauberes C++ von Microsoft
4. Was kann die GDI+?
5. Hello World!
6. Mächtige Graphics
7. Ausblick
A. Links1. Einleitung
Wer bisher in seinen Windows-Anwendungen Grafikfunktionen benötigt hat, hat meistens die alte GDI API benutzt. Immerhin erfüllt sie ihren Zweck und ist seit eh und je in Windows vorhanden. Für C++ Programmierer ist sie jedoch leider eine API die nicht auf einer OO-Sprache basiert, obwohl sie einen objektorientieren Ansatz verfolgt. Doch könnte es für einen C++ Programmierer viel komfortabler sein komplexere Grafiken zu erstellen als dies mit der GDI der Fall ist. Um zu ansprechenderen Ergebnissen in kürzerer Zeit zu gelangen, muß man sich mit der GDI aktuelle Effekte selbst entwickeln oder kombinieren.Mit Erscheinen von Windows XP hat Microsoft jedoch die Zeichen der Zeit erkannt und eine leistungsfähigere API eingeführt. Und schon sind wir bei der neuen GDI+ Bibliothek angelangt.
2. Technische Voraussetzungen
Die GDI+ ist in jedem Windows XP serienmäßig dabei, ist jedoch nicht auf Windows XP beschränkt. Es kann auch auf Windows 2000, Windows NT 4.0 SP6 und Windows 98/ME mit einer zusätzlichen DLL ohne Installation eingesetzt werden. Die kostenlose GDI+ für Endbenutzer ist auf der GDI+ Homepage als Download verfügbar.3. Sauberes C++ von Microsoft
Die Entwickler von Microsoft haben mit der GDI+ eine Bibliothek entworfen die einem C++ Programmierer nicht peinlich sein muß. Keine Makros, keine Prefixe sondern Namespaces und klare Parameternamen. Die Freigabe von Resourcen, wie sie in der alten GDI nötig war, entfällt durch die Fähigkeiten der C++-Stackobjekte ebenfalls. Alles das hätten wir uns von Microsoft viel früher gewünscht. Aber lieber spät als nie.Vom Programmierer werden Kenntnisse in C++ und der Objekt Orientierung verlangt, wobei diese auf einer einfachen Ebene stattfinden ("weil einfach einfach einfach ist!"). Templates o.ä. muß man nicht kennen, was die GDI+ auf jeden Fall auch für C++ Einsteiger sehr interessant macht. Besonders diese können schnell und einfach in die Grafikprogrammierung einsteigen ohne in die Gefahr der Speicherlecks o.ä. zu laufen.
4. Was kann die GDI+?
Wem die oben genannten Argumente immer noch nicht überzeugt haben, wird dies ganz bestimmt durch die Features der GDI+. Prinzipiell deckt die GDI+ alle Bereiche der 2D-Grafik ab, so lange man kein Actionspiel programmieren will. Aber 2D-Vectorgrafik mit Transformationen und Translationen in Kombination mit Spezialeffekten sind für jeden intuitiv umsetzbar. Weiterhin unterstützt werden das Codieren und Decodieren von wichtigen Grafikformaten, dazu gehören z.B. JPEG, PNG, TIFF u.a. Diese Bitmaps kann man ebenfalls, wie die Vectorfunktionen, mit Effekten versehen und transformieren (z.B. skallieren). Wie das alles sehr einfach, schnell und intuitiv umsetzbar ist, werde ich jetzt endlich zeigen.5. Hello World!
Ich gehe in diesem Tutorial nicht auf die Windows-Programmierung ein. Deshalb werde ich nur auf die relevanten Teile für die GDI+ eingehen. Um die GDI+ nutzen zu können, muß die gdiplus.lib dem Linker mitgeteilt werden und bei Nicht-WinXP-Systemen die gdiplus.dll in den Arbeitspfad gelegt werden. Wer mit dem VisualC++ ein Win32-Projekt anlegt muß unbedingt das Makro WIN32_LEAN_AND_MEAN entfernen (wird im stdafx.h definiert), da man sonst Compilierungs-Fehler bekommt. Schon steht dem Programmieren nichts mehr im Weg.Für ein erstes einfaches Beispiel werden wir die GDI+ initialisieren und eine Linie zeichnen.
#include <gdiplus.h> using namespace Gdiplus; // 01 INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 02 // ... paint(hdc); // ... GdiplusShutdown(gdiplusToken); // 03 } void paint(HDC hdc) { Graphics graphics(hdc); // 04 Pen pen(Color(255, 0, 0, 255)); // 05 graphics.DrawLine(&pen, 0, 0, 200, 100); // 06 }
Erklärungen zu den einzelnen Zeilen:
01: Um nicht vor jeder Klasse oder Funktion ein "Gdiplus::" zu schreiben, benutzen wir implizit den Namespace.
02: Im Startpunkt unserer Anwendung (hier die WinMain-Funktion) sollten wir die GDI+ initialisieren. Da die GDI+ eine komplexere Initialisierung durchführt, ist dieser Aufruf nur einmalig zu empfehlen und nicht vor jedem Zeichenvorgang. Das gdiplusTocken (ein Pointer) darf nicht verloren gehen, damit man die GDI+ wieder deinitialisieren kann.
03: Die GdiplusShutdown()-Funktion will den gültigen gdiplusToken-Pointer haben um die GDI+ zu beenden. Dieser Aufruf kann und sollte erst kurz vor Beenden der Anwendung aufgerufen werden.
04: Hier geht es endlich zur Sache. Gdiplus::Graphics ist die wichtigste Klasse die uns begegnet. Sie stellt sozusagen die Zeichenfläche da auf der sich das Geschehen abspielt. In dem Beispiel beziehen wir die Zeichenfläche auf ein HDC-Device (z.B. ein Fenster). Wir hätten auch eine Bitmap übergeben können, welche sich nicht auf dem Bildschirm befindet. So könnte man Bitmaps im Hintergrund manipulieren.
05: Zum Zeichnen benötigt man auch ein Werkzeug, wir instanzieren hier einen Stift und übergeben dem Konstruktor gleich eine Wunschfarbe. Gdiplus::Color ist eine Farbenklasse die auch einen Alphachannel unterstützt, somit sind auch transluzente Farben kein Problem.
06: Auf unserer Zeichenfläche (graphics) können wir Aktionen ausführen, z.B. mit DrawLine eine Linie ziehen. Als Parameter erwartet diese Methode einmal das Werkzeug (unseren blauen Stift) und die X/Y-Koordinaten jeweils für den Start- und Endpunkt unserer Linie. Das Beispiel zeichnet eine blaue Linie von oben links diagonal nach unten rechts.
Wie man an unserer paint()-Funktion sieht, können wir alle Objekte auf dem Stack anlegen. Brauchen diese deshalb nicht wieder mit einem delete oder einer ominösen release()-Funktion freigeben.
6. Mächtige Graphics
Das Graphics-Objekt legt man wahlweise vor jeder Zeichensequenz neu an oder einmalig und löscht sie jedesmal mit der Clear() Methode. Hat man das gemacht, kann man allerhand damit anstellen, denn sie verfügt über 188 Methoden.Sehr leicht kann man z.B. eine Figur (Rechteck, Ellipse, Pfade usw.) rotieren, verschieben und skallieren lassen. Diese aktionen benötigen dabei jeweils nur eine einzige Zeile Programmcode. Das folgende Beispiel zeichnet erst ein Rechteck und verschiebt dann ein zweites Rechteck nach unten links und dreht es dann um 28°.
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); // 01 Pen pen(Color::Blue, 1); // 02 graphics.DrawRectangle(&pen, rect); pen.SetColor(Color::Red); graphics.TranslateTransform(100,100); // 03 graphics.RotateTransform(28.0f); // 04 graphics.DrawRectangle(&pen, rect); // 05
01: Wir wollen ein Rechteck, hier wird es mit der Größe 50x50 Pixel instanziert.
02: Unser Stift bekommt die Farbe blau, da die Klasse Color uns schon Enumerationen für viele Farben bereitstellt. Selbst Farben die uns Männern nichts sagen, aber wohl den Damen, sind vordefiniert.
03: Nachdem wir das erste Rechteck gezeichnet haben, bewegen wir unseren Grafikkontext um 100/100 (X/Y) Pixel.
04: Jetzt rotieren wir den Grafikkontext um 28°.
05: Auf Grund der vorherigen Aktionen wird unser Rechteck an einer ganz anderen Stelle gezeichnet. Das Rechteck selbst braucht man nicht verändern, es soll sich einfach nur zeichnen. Das hat den Vorteil, das sich die Transformationen auf alle möglichen Figuren auswirken. Und somit die Figuren selbst keine Transformations-Methoden bieten müssen. Kann man ganz gut mit dem STL-Konzept vergleichen, wo die Container auch keine Algorithmen a la Sortieren oder Suchen haben.
Wer will kann auch mit der Methode ScaleTransform() seine Figuren skallieren, d.h. in der Größe ändern.
Hier noch ein Beispiel das eindrucksvoll zeigt, wie man mit nur einer zusätzlichen Zeile Code (in dem Fall eine for-Schleife) etwas spektakuläres zaubern kann:
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); Pen pen(Color::Red, 1); graphics.TranslateTransform(100,100); for(int i =0; i < 360; i=i+10) { // 360° in 10° Schritten graphics.RotateTransform(i); // dynamische Rotation mehrmals durchlaufen graphics.DrawRectangle(&pen, rect); }
7. Ausblick
Das war jetzt der erste Teil in dem ich euch die GDI+ hoffentlich schmackhaft machen konnte. Sicherlich waren die Ergebnisse auf dem Bildschirm nicht wahnsinnig spektakulär, doch an den Beispiel-Codes kann man sehen, das man mit sehr wenig Programmieraufwand spektakulärere Ergebnisse zaubern kann. Im nächsten Teil werde ich etwas tiefer in die Möglichkeiten der GDI+ Figuren eingehen.
A. Links
GDI+ Homepage
Neueste SDK-Distribution
GDI+ Reference
-
Da anscheinend keine technischen Verbesserungen nötig sind, wäre es super wenn ihr noch mal Rechschreibung und Grammatik überpüfen könntet. Würde den Artikel endlich in die freie Wildbahn los lassen.
-
BTW: Als Beispiel für Rotation ist eine analoge Uhr imemr ganz praktisch. Wir haben in C# letztens die GDI+ benützt und ebenfalls mit RotateTransform eine analoge Uhr in gut 10 Minuten erstellt
MfG SideWinder
-
OK Sidewinder, hab ne Analoguhr programmiert. Ist ne gute Idee, ist mir so garnicht in den Sinn gekommen. Hab den Artikel entsprechend erweitert. Aber heute abend geht der endlich offiziell raus. Kanns nicht leiden wenn alles immer ewig dauert.
-
Die GDI Plus (Teil 1)
In diesem C++ Artikel geht es um die relativ neue Grafik Bibliothek GDI+ für Windows.
1. Einleitung
2. Technische Voraussetzungen
3. Sauberes C++ von Microsoft
4. Was kann die GDI+?
5. Hello World!
6. Mächtige Graphics
7. Ausblick
A. Links1. Einleitung
Wer bisher in seinen Windows-Anwendungen Grafikfunktionen benötigt hat, hat meistens die alte GDI API benutzt. Immerhin erfüllt sie ihren Zweck und ist seit eh und je in Windows vorhanden. Für C++ Programmierer ist sie jedoch leider eine API die nicht auf einer OO-Sprache basiert, obwohl sie einen objektorientieren Ansatz verfolgt. Doch könnte es für einen C++ Programmierer viel komfortabler sein komplexere Grafiken zu erstellen als dies mit der GDI der Fall ist. Um zu ansprechenderen Ergebnissen in kürzerer Zeit zu gelangen, muß man sich mit der GDI aktuelle Effekte selbst entwickeln oder kombinieren.Mit Erscheinen von Windows XP hat Microsoft jedoch die Zeichen der Zeit erkannt und eine leistungsfähigere API eingeführt. Und schon sind wir bei der neuen GDI+ Bibliothek angelangt.
2. Technische Voraussetzungen
Die GDI+ ist in jedem Windows XP serienmäßig dabei, ist jedoch nicht auf Windows XP beschränkt. Es kann auch auf Windows 2000, Windows NT 4.0 SP6 und Windows 98/ME mit einer zusätzlichen DLL ohne Installation eingesetzt werden. Die kostenlose GDI+ für Endbenutzer ist auf der GDI+ Homepage als Download verfügbar.3. Sauberes C++ von Microsoft
Die Entwickler von Microsoft haben mit der GDI+ eine Bibliothek entworfen die einem C++ Programmierer nicht peinlich sein muß. Keine Makros, keine Prefixe sondern Namespaces und klare Parameternamen. Die Freigabe von Resourcen, wie sie in der alten GDI nötig war, entfällt durch die Fähigkeiten der C++-Stackobjekte ebenfalls. Alles das hätten wir uns von Microsoft viel früher gewünscht. Aber lieber spät als nie.Vom Programmierer werden Kenntnisse in C++ und der Objekt Orientierung verlangt, wobei diese auf einer einfachen Ebene stattfinden ("weil einfach einfach einfach ist!"). Templates o.ä. muß man nicht kennen, was die GDI+ auf jeden Fall auch für C++ Einsteiger sehr interessant macht. Besonders diese können schnell und einfach in die Grafikprogrammierung einsteigen ohne in die Gefahr der Speicherlecks o.ä. zu laufen.
4. Was kann die GDI+?
Wem die oben genannten Argumente immer noch nicht überzeugt haben, wird dies ganz bestimmt durch die Features der GDI+. Prinzipiell deckt die GDI+ alle Bereiche der 2D-Grafik ab, so lange man kein Actionspiel programmieren will. Aber 2D-Vectorgrafik mit Transformationen und Translationen in Kombination mit Spezialeffekten sind für jeden intuitiv umsetzbar. Weiterhin unterstützt werden das Codieren und Decodieren von wichtigen Grafikformaten, dazu gehören z.B. JPEG, PNG, TIFF u.a. Diese Bitmaps kann man ebenfalls, wie die Vectorfunktionen, mit Effekten versehen und transformieren (z.B. skallieren). Wie das alles sehr einfach, schnell und intuitiv umsetzbar ist, werde ich jetzt endlich zeigen.5. Hello World!
Ich gehe in diesem Tutorial nicht auf die Windows-Programmierung ein. Deshalb werde ich nur auf die relevanten Teile für die GDI+ eingehen. Um die GDI+ nutzen zu können, muß die gdiplus.lib dem Linker mitgeteilt werden und bei Nicht-WinXP-Systemen die gdiplus.dll in den Arbeitspfad gelegt werden. Wer mit dem VisualC++ ein Win32-Projekt anlegt muß unbedingt das Makro WIN32_LEAN_AND_MEAN entfernen (wird im stdafx.h definiert), da man sonst Compilierungs-Fehler bekommt. Schon steht dem Programmieren nichts mehr im Weg.Für ein erstes einfaches Beispiel werden wir die GDI+ initialisieren und eine Linie zeichnen.
#include <gdiplus.h> using namespace Gdiplus; // 01 INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 02 // ... paint(hdc); // ... GdiplusShutdown(gdiplusToken); // 03 } void paint(HDC hdc) { Graphics graphics(hdc); // 04 Pen pen(Color(255, 0, 0, 255)); // 05 graphics.DrawLine(&pen, 0, 0, 200, 100); // 06 }
Erklärungen zu den einzelnen Zeilen:
01: Um nicht vor jeder Klasse oder Funktion ein "Gdiplus::" zu schreiben, benutzen wir implizit den Namespace.
02: Im Startpunkt unserer Anwendung (hier die WinMain-Funktion) sollten wir die GDI+ initialisieren. Da die GDI+ eine komplexere Initialisierung durchführt, ist dieser Aufruf nur einmalig zu empfehlen und nicht vor jedem Zeichenvorgang. Das gdiplusTocken (ein Pointer) darf nicht verloren gehen, damit man die GDI+ wieder deinitialisieren kann.
03: Die GdiplusShutdown()-Funktion will den gültigen gdiplusToken-Pointer haben um die GDI+ zu beenden. Dieser Aufruf kann und sollte erst kurz vor Beenden der Anwendung aufgerufen werden.
04: Hier geht es endlich zur Sache. Gdiplus::Graphics ist die wichtigste Klasse die uns begegnet. Sie stellt sozusagen die Zeichenfläche da auf der sich das Geschehen abspielt. In dem Beispiel beziehen wir die Zeichenfläche auf ein HDC-Device (z.B. ein Fenster). Wir hätten auch eine Bitmap übergeben können, welche sich nicht auf dem Bildschirm befindet. So könnte man Bitmaps im Hintergrund manipulieren.
05: Zum Zeichnen benötigt man auch ein Werkzeug, wir instanzieren hier einen Stift und übergeben dem Konstruktor gleich eine Wunschfarbe. Gdiplus::Color ist eine Farbenklasse die auch einen Alphachannel unterstützt, somit sind auch transluzente Farben kein Problem.
06: Auf unserer Zeichenfläche (graphics) können wir Aktionen ausführen, z.B. mit DrawLine eine Linie ziehen. Als Parameter erwartet diese Methode einmal das Werkzeug (unseren blauen Stift) und die X/Y-Koordinaten jeweils für den Start- und Endpunkt unserer Linie. Das Beispiel zeichnet eine blaue Linie von oben links diagonal nach unten rechts.
Wie man an unserer paint()-Funktion sieht, können wir alle Objekte auf dem Stack anlegen. Brauchen diese deshalb nicht wieder mit einem delete oder einer ominösen release()-Funktion freigeben.
6. Mächtige Graphics
Das Graphics-Objekt legt man wahlweise vor jeder Zeichensequenz neu an oder einmalig und löscht sie jedesmal mit der Clear() Methode. Hat man das gemacht, kann man allerhand damit anstellen, denn sie verfügt über 188 Methoden.Sehr leicht kann man z.B. eine Figur (Rechteck, Ellipse, Pfade usw.) rotieren, verschieben und skallieren lassen. Diese aktionen benötigen dabei jeweils nur eine einzige Zeile Programmcode. Das folgende Beispiel zeichnet erst ein Rechteck und verschiebt dann ein zweites Rechteck nach unten links und dreht es dann um 28°.
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); // 01 Pen pen(Color::Blue, 1); // 02 graphics.DrawRectangle(&pen, rect); pen.SetColor(Color::Red); graphics.TranslateTransform(100,100); // 03 graphics.RotateTransform(28.0f); // 04 graphics.DrawRectangle(&pen, rect); // 05
01: Wir wollen ein Rechteck, hier wird es mit der Größe 50x50 Pixel instanziert.
02: Unser Stift bekommt die Farbe blau, da die Klasse Color uns schon Enumerationen für viele Farben bereitstellt. Selbst Farben die uns Männern nichts sagen, aber wohl den Damen, sind vordefiniert.
03: Nachdem wir das erste Rechteck gezeichnet haben, bewegen wir unseren Grafikkontext um 100/100 (X/Y) Pixel.
04: Jetzt rotieren wir den Grafikkontext um 28°.
05: Auf Grund der vorherigen Aktionen wird unser Rechteck an einer ganz anderen Stelle gezeichnet. Das Rechteck selbst braucht man nicht verändern, es soll sich einfach nur zeichnen. Das hat den Vorteil, das sich die Transformationen auf alle möglichen Figuren auswirken. Und somit die Figuren selbst keine Transformations-Methoden bieten müssen. Kann man ganz gut mit dem STL-Konzept vergleichen, wo die Container auch keine Algorithmen a la Sortieren oder Suchen haben.
Wer will kann auch mit der Methode ScaleTransform() seine Figuren skallieren, d.h. in der Größe ändern.
Hier noch ein Beispiel das eindrucksvoll zeigt, wie man mit nur einer zusätzlichen Zeile Code (in dem Fall eine for-Schleife) etwas spektakuläres zaubern kann:
Graphics graphics(hdc); Rect rect(0, 0, 50, 50); Pen pen(Color::Red, 1); graphics.TranslateTransform(100,100); for(int i =0; i < 360; i=i+10) { // 360° in 10° Schritten graphics.RotateTransform(i); // dynamische Rotation mehrmals durchlaufen graphics.DrawRectangle(&pen, rect); }
Mit diesem Wissen können wir jetzt auch etwas praktisches mit der GDI+ umsetzen. Eine analoge Uhr ist dazu gerade ideal.
Ist euch in dem obigen Screenshot das Anti-Aliasing (Kantenglättung) aufgefallen? Dies kann man mit der Graphics-Methode SetSmoothingMode() ein- und ausschalten. Wie man eine solche Uhr zeichnet, zeigt die Klasse kharchi::clock, welche ich hier im Quellcode bereit gestellt habe. Die Klasse unterliegt der BSD Lizenz, Ihr könnt sie also ändern, erweitern und in eigenen Projekten benutzen. Anwenden kann man sie wie folgt:
using namespace Gdiplus; Graphics graphics(hdc); kharchi::clock c; c.set_time(16, 55, 00); // 16:55 Uhr c.paint(graphics);
7. Ausblick
Das war jetzt der erste Teil in dem ich euch die GDI+ hoffentlich schmackhaft machen konnte. Sicherlich waren die Ergebnisse auf dem Bildschirm nicht wahnsinnig spektakulär, doch an den Beispiel-Codes kann man sehen, das man mit sehr wenig Programmieraufwand spektakulärere Ergebnisse zaubern kann. Im nächsten Teil werde ich etwas tiefer in die Möglichkeiten der GDI+ Figuren eingehen.
A. Links
GDI+ Homepage
Neueste SDK-Distribution
GDI+ Reference
-
-
Artchi schrieb:
Erstmal muss den Artikel irgendjemand Korrekturlesen
MfG SideWinder