.NET-Klassen in C++ Windows Forms-Anwendungen

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.

Grafiken auf einer PictureBox zeichnen

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 Koordi­naten 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=Clip­Bounds.Width, y=ClipBounds.Height) auf die als Argument übergebene Zeichenfläche g.

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 Zeichen­funktion wie DrawLine mit der Zeichenfläche e->Graphics auf, wird die Figur auf dieser Zeichenfläche gezeichnet:

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:

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,

Apfelmännchen

Schneeflockenkurven,

Schneeflockenkurven

mathematische Funktionen usw.

mathematische Funktion

Collection-Klassen

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

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:

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:

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 Argu­ment übergebenen Wert.

verschiedene Sort-Methoden zum Sortieren der Liste

Textdateien

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:

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