Veröffentlicht: Dezember 2009
Von Richard Kaiser und Alexander Kaiser
In einer C++ Windows Forms-Anwendung steht im Wesentlichen die gesamte .NET Bibliothek zur Verfügung. Im Folgenden wird an einigen einfachen Beispielen gezeigt, wie .NET-Klassen in C++ verwendet werden können.
Dieser Artikel ist ein kurzer Auszug aus dem Buch „C++ mit Microsoft Visual C++ 2008“ (ISBN 978-3540238690), das C++ mitsamt den Visual C++-Erweiterungen (C++/CLI) umfassend darstellt. Der Verfasser dieses Buches ist ein erfahrener C++- und C#-Trainer, der auch für Firmenschulungen zur Verfügung steht.
Die Klasse Graphics
aus dem Namensbereich System::Drawing stellt eine Zeichenfläche dar. Sie
enthält zahlreiche Elementfunktionen wie z.B.
void DrawLine(Pen^ pen, int x1, int
y1, int x2, int y2);
// Zeichnet eine Linie von
(x1,y1) nach (x2,y2).
mit denen man
Linien, Kreise, Rechtecke, Text usw. zeichnen kann. Alle Koordinaten sind in
Pixeln angegeben und beziehen sich auf die Zeichenfläche. Dabei ist der
Nullpunkt (0,0) links oben und nicht (wie in der Mathematik üblich) links
unten. Die Höhe und Breite der Zeichenfläche erhält man als float-Wert
über die Methoden Width und Height der Eigenschaft
property
RectangleF ClipBounds
Der Zeichenstift
wird durch ein Objekt der Klasse Pen dargestellt, das durch einen
Konstruktor wie
Pen(Color color, float
width)
mit einer Farbe
und einer Strichstärke initialisiert werden kann.
Beispiel: Die Funktion zeichneDiagonale zeichnet eine rote Diagonale
von links oben (Koordinaten x=0, y=0) nach rechts unten (Koordinaten x=ClipBounds.Width,
y=ClipBounds.Height) auf die als Argument übergebene Zeichenfläche
g.
C++
void zeichneDiagonale(Graphics^ g)
{
Pen^ pen=gcnew Pen(Color::Red, 1);
Point start(0,0);
Point end(g->ClipBounds.Width,
g->ClipBounds.Height);
g->DrawLine(pen, start,end);
delete pen; // nicht notwendig
}
Als Zeichenfläche
kann man die Zeichenfläche einer PictureBox verwenden, die man aus dem Register
„Allgemeine Steuerelemente“ der Toolbox auf ein Formular zieht. Die
Zeichenfläche der PictureBox wird im EventHandler für das Ereignis Paint
über den Parameter e übergeben. Dieser Eventhandler wird von Visual Studio nach
einem Doppelklick auf das Ereignis Paint im Eigenschaftenfenster
erzeugt. Ruft man in diesem Eventhandler eine Zeichenfunktion wie DrawLine
mit der Zeichenfläche e->Graphics auf, wird die Figur auf dieser
Zeichenfläche gezeichnet:
C++
private: System::Void
pictureBox1_Paint(
System::Object^ sender,
System::Windows::Forms::PaintEventArgs^
e)
{
e->Graphics->Clear(Color::White);
zeichneDiagonale(e->Graphics);
}
Dieses Ereignis
wird von Windows immer dann automatisch ausgelöst, wenn die PictureBox neu
gezeichnet werden muss (z.B. nachdem sie durch ein anderes Fenster verdeckt
war). Es kann aber auch vom Anwender durch einen Aufruf der Funktion Invalidate
ausgelöst werden:
C++
private:
System::Void button1_Click(System::Object^
sender,
System::EventArgs^ e)
{
this->pictureBox1->Invalidate();
}
Dieser Aufruf
bewirkt dann, dass die Funktion neu gezeichnet wird. Selbstverständlich kann
man auf diese Weise nicht nur einfache Diagonalen zeichnen. Mit etwas
aufwendigeren Anweisungen erhält man auch Apfelmännchen,

Schneeflockenkurven,

mathematische
Funktionen usw.

Die Namensbereiche
System::Collections und System::Collections::Generic
enthalten einige Collection-Klassen, mit denen man Daten speichern und
verwalten kann. Hier soll nur am Beispiel der generischen Collection-Klasse List, die nach
C++
using
namespace System::Collections::Generic;
zur Verfügung
steht, kurz gezeigt werden, wie das geht.
Bei der Definition
einer generischen List-Collection gibt man nach List in spitzen Klammern den
Datentyp der Elemente an, die gespeichert werden sollen. Mit der Methode Add können dann Elemente dieses Typs
eingefügt werden:
C++
List<String^>^ gl = gcnew
List<String^>;
gl->Add("one ");
gl->Add("two ");
gl->Add("three ");
Die Liste kann
dann mit einer for und einer for each-Anweisung durchlaufen werden:
C++
for each(String^ i in gl)
textBox1->AppendText(i);
for (int i=0; i<gl->Count;
i++)
textBox1->AppendText(gl[i]);
Für viele der
wichtigsten Operationen mit Listen stehen Elementfunktionen zur Verfügung:
bool Contains(T item) // gibt true zurück, wenn das Argument
in der Liste enthalten ist, und andernfalls false
int IndexOf(T item) // der Index des ersten Elements mit dem als
Argument übergebenen Wert.
verschiedene Sort-Methoden zum
Sortieren der Liste
Mit den Klassen StreamReader
und StreamWriter
aus dem Namensbereich System::IO kann man Textdateien lesen und
schreiben. Sie haben unter anderem die folgenden Konstruktoren
StreamReader(String^ path)
StreamWriter(String^ path)
die eine Datei mit
dem angegebenen Dateinamen öffnen und die Zeichen als Unicode Zeichen (UTF-8)
behandeln. Über weitere Konstruktoren können auch andere Zeichensätze verwendet
werden.
Ein StreamReader
hat unter anderem die folgenden Methoden, mit denen Daten aus der Datei gelesen
werden können:
virtual String^ ReadLine() override // liest die nächste Zeile
virtual int Read() override // liest das nächste Zeichen
virtual int Read(array<wchar_t>^ buffer, int index, int
count) override
Die Eigenschaft
property
bool EndOfStream
hat genau dann den
Wert true, wenn alle Zeichen gelesen wurden.
Beispiel: Die Funktion f1 liest alle Zeilen einer Textdatei und gibt sie in
einer TextBox aus:
C++
void
f1(TextBox^ tb, String^ path)
{
using namespace System::IO;
StreamReader^
r = gcnew StreamReader(path);
while
(!r->EndOfStream)
{
tb->AppendText(r->ReadLine()+"\r\n");
}
r->Close();
}
Zurück: C++/CLI-Erweiterungen | Weiter: Win32-DLLs und Win32-API Funktionen in Windows Forms-Anwendungen verwenden