Stifte und Linien

In dieser und der nächsten Lektion lernen Sie Anweisungen zum Zeichnen von Grafiken kennen. Anfangen werden wir mit den Linengrafiken.

Liniengrafiken, und später auch die Umrandungen von Flächen, werden mit sogenannten Stiften (Pens) gezeichnet. Dazu stellt WINDOWS zunächst einen Satz von vordefinierten Stiften zur Verfügung. Diese Stifte müssen nicht, wie die nachher vorgestellten anwenderdefinierten Stifte, explizit erstellt werden, sondern können direkt für die nachfolgende Zeichenoperation verwendet werden. Wenn Sie sich noch an die vorherige Lektion erinnern, müssen Zeichenobjekte, und um ein solches handelt es sich bei einem Stift, vor der eigentlichen Zeichenoperation ausgewählt werden. Bei den von WINDOWS vorgegebenen Stiften erfolgt dies mittels der CGdiObject Methode SelectStockObject(...). Als Parameter erhält die Methode eine der der Konstanten BLACK_PEN, WHITE_PEN oder NULL_PEN, je nach dem, ob ein schwarzer, weißer oder nicht sichtbarer Stift für die nachfolgende Zeichenoperation verwendet werden soll. Für den Fall dass Sie sich jetzt über den Stift NULL_PEN wundern, hier auch gleich eines seiner Einsatzgebiete. Der NULL_PEN wird u.a. immer dann verwendet, wenn eine Fläche ohne Umrandung gezeichnet werden soll.

Der nachfolgende Auszug aus einem Listing wählt zuerst einen schwarzen Stift und dann einen weißen Stift für die jeweils nächsten Zeichenoperationen aus:

void CMyView::OnDraw (CDC *pDC)
{
    pDC->SelectStockObject (BLACK_PEN);
    ....   
// Hier wird mit dem schwarzen Stift gemalt
    pDC->SelectStockObject (WHITE_PEN);
    ....   
// und hier mit dem weissem Stift
}

Da das Leben aber nicht nur aus schwarz und weiß besteht, können auch eigene Stifte erstellt werden. Für diese anwenderdefinierten Stifte stellt die MFC die Klasse CPen zur Verfügung. Ein Stift dieser Klasse kann auf zwei Weisen erstellt werden. Im ersten Fall wird ein MFC-Objekt vom Typ CPen (Aufruf des Konstruktor ohne Parameter) erstellt und anschließend dessen Methode CreatePen(...) aufgerufen. Über Parameter der CreatePen(...) Methode wird dann das Aussehen des Stifts festgelegt. Alternativ kann aber auch schon bei der Erstellung des CPen-Objekts (Konstruktor mit Parameter) dessen Aussehen mit angegeben werden. Sehen wir uns auch hierzu wieder einen Auszug aus einem Listing an. Die Parameter beim Festlegen des Stiftstils werden im Anschluss gleich behandelt.

void CMyView::OnDraw (CDC *pDC)
{
    // 1. Fall: Stiftstil mittels Create(...) Methode festlegen
    // Stiftobjekt zunächst erstellen

    CPen CMyPen;
    // Stiftstil festlegen
    CMyPen.CreatePen(PS_SOLID,1,0x00000000);
    // 2. Fall: Stiftstil beim Erstellen des Stifts festlegen
    CPen CFirstPen(PS_SOLID,1,0x00000000);
    ....
}

Sowohl die Methode CreatePen(...) wie auch der Konstruktor im zweiten Fall legen über den ersten Parameter den Stiftstil fest. Hierzu stehen Ihnen folgende Konstanten zur Verfügung:

Stil

Aussehen

Stiftstile

Außer den oben angegebenen Stilen gibt es noch die Stile PS_NULL und PS_INSIDEFRAME. Ein Stift mit dem Stil PS_NULL zeichnet überhaupt nichts und entspricht damit weitgehend dem Standard-Stift NULL_PEN. Wird der Stil PS_INSIDEFRAME verwendet und anschließend eine Zeichenoperation durchgeführt die ein umschließendes Rechteck für die Zeichenoperation verwendet (z.B. Rectangle(...) oder auch Pie(...)), so wird die darzustellende Figur soweit verkleinert, dass der Stift für die Umrandung der Figur innerhalb der angegebenen Grenzen bleibt: Das nachfolgende Bild demonstriert diesen Sachverhalt. Die Grenzen des dargestellten Rechtecks wird durch die dünne schwarze Linie dargestellt. Wird für die Umrandung z.B. ein Stift vom Typ PS_SOLID und der Stiftdicke 5 verwendet, so läuft die Umrandung über die Grenzen des Rechtecks hinaus. Anders dagegen beim Stifttyp PS_INSIDEFRAME. Hier bleibt die komplette Figur innerhalb der angegebenen Grenze.

Stiftstile für Umrandungen

Es gibt noch weitere Stiftstile wie z.B. PS_COSMETIC oder PS_ENDCAP_XXX. Diese Stiftstile sind unter WINDOWS 95/98 aber nur beim Zeichnen von Pfaden relevant. Was Pfade sind wird in einer späteren Lektion noch erläutert.

Kommen wir jetzt zum zweiten Parameter beim Einstellen des Stiftstils. Der zweite Parameter bestimmt die Stärke (Dicke) des Stifts in logischen Einheiten. Wie breit dann eine Linie mit dem Stift im Fenster tatsächlich gezeichnet wird, hängt vom nachher behandelten Mapping-Mode ab. Im Standard-Mapping-Mode entspricht eine logische Einheit auf dem Bildschirm einem Pixel (Punkt).

Linien mit einem Stil ungleich PS_SOLID müssen unter WINDOWS95/98 immer ein Pixel breit gezeichnet werden. WINDOWS NT/2000 lässt auch gemusterte Stifte mit einer Dicke größer 1 zu.

Soll (oder muss wie gerade erwähnt) die Linie unabhängig vom Mapping-Mode ein Pixel breit gezeichnet werden, so ist als Stiftstärke der Wert 0 anzugeben!

Als letzter, unter WINDOWS 95/98 gültiger Parameter folgt die Angabe der Stiftfarbe. Die Farbe kann auf zwei verschiedene Arten festgelegt werden: einmal über einen COLORREF Wert und zum anderen über eine Struktur vom Typ LOGBRUSH, die wir hier aber nicht weiter betrachten. Ein COLORREF Wert ist ein 32-Bit Wert der in 8-Bit breite einzelne RGB-Teile unterteilt wird. Das Low-Byte des COLORREF Werts enthält den Wert für den Rotanteil, das 2. Byte den Wert für den Grünanteil und das 3. Byte den Wert für den Blauanteil. Das High-Byte muss immer '0' sein! So ist z.B. für die Farbe 'gelb' der COLORREF-Wert 0x0000FFFF. Außer der direkten Angabe eines COLORREF-Wertes kann der Farbwert auch über das Makro RGB(...) ermittelt werden. Das Makro erhält drei Parameter für den jeweiligen Rot-, Grün- und Blauanteil und liefert als Ergebnis den entsprechenden COLORREF-Wert zurück. Für die Farbe 'gelb' würde das Makro wie folgt aufgerufen werden: RGB (255,255,0). Beachten Sie bitte, dass hier die RGB-Anteile in der umgekehrten Reihenfolge angegeben werden wie bei der direkten Angabe des COLORREF-Werts.

Um für eine bestimmte Farbe die RGB-Anteile zu ermitteln können Sie sich folgenden 'Trick' zunutze machen:
  1. Klicken Sie mit der rechten Maustaste auf den Desktop und öffnen Sie dessen Eigenschaften.
  2. Wählen Sie den Tabulator Darstellung aus.
  3. Klicken Sie das Dropdown-Menü Farbe und wählen dort den Eintrag Weitere... aus.
  4. Daraufhin wird folgender Farbdialog eingeblendet:

Farbauswahl-Dialog

Durch Ziehen des Kreuzes im Farbfeld stellen Sie die gesuchte Farbe ein und können dann rechts unten die RGB-Anteile der entsprechenden Farbe ablesen.

Im Zusammenhang mit gemusterten Stiften, und den in der nächsten Lektion aufgeführten gemusterten Pinsel, spielt noch eine weitere CDC Eigenschaft eine wichtige Rolle, der Hintergrund. Für Zeichenoperationen können zwei verschiedene Hintergrundmodi mittels der CDC-Methode SetBkMode(...) gesetzt werden. Die Methode erhält als Parameter eine der beiden Konstanten OPAQUE oder TRANSPARENT. Wird der Hintergrundmode OPAQUE eingestellt, so wird der Hintergrund bei Textausgaben bzw. der Zwischenraum bei gemusterten Stiften und Pinsel mit der aktuellen Hintergrundfarbe ausgefüllt. Dies ist übrigens die Standard-Einstellung des DC. Beim Hintergrundmode TRANSPARENT wird der Hintergrund bzw. Zwischenraum bei der Darstellung nicht gezeichnet. Um die Hintergrundfarbe zu setzen wird die CDC-Methode SetBkColor(...) aufgerufen, die als Parameter den COLORREF Wert für die Hintergrundfarbe erhält.

Wird ein anwenderdefinierter Stift nicht mehr benötigt, so sollte er mittels der Methode DeleteObject(...) gelöscht werden. Dieses Löschen kann entfallen, wenn das CPen-Objekt automatisch zerstört wird da der Destruktor von CPen diese Methode aufruft.

Aber gehen wir jetzt wieder zur Praxis über. Durch diese und den nachfolgenden beiden Lektionen zieht sich ein etwas größeres Beispiel, das an Hand der Darstellung einer Messkurve die verschiedensten GDI-Funktionen aufzeigt. Es ist deshalb wichtig, dass Sie die Lektionen dieses Kapitels der Reihe nach durcharbeiten.

Damit wir uns auf das Wesentlich konzentrieren können, kopieren Sie zunächst das Ausgangsprogramm für das Beispiel aus dem Verzeichnis 99Templates\GDIFunc in Ihr Arbeitsverzeichnis. Die Daten für die Messkurve werden im Beispiel im Konstruktor des Dokuments erzeugt und in einem CPoint-Feld abgelegt. In der Praxis würden Sie diese Daten z.B. in der Serialize(...) Methode des Dokuments aus einer Datei einlesen. Ebenso wurde der Dokumentenklasse bereits die Methode GetData(...) hinzugefügt, die die Anzahl der Messpunkte sowie die Messpunkte selbst an das Ansichtsobjekt liefert.

Übersetzen und starten Sie jetzt das Ausgangsprogramm. In der OnDraw(...) Methode des Ansichtobjekts werden die Messwerte bis jetzt mittels TRACE(...) Anweisung im Debuggerfenster ausgegeben.

Und damit können wir nun zur Übung übergehen. Erstellen Sie in der OnDraw(...) Methode des Ansichtobjekts zunächst die beiden Stifte CAxisPen und CLinePen. Der CAxisPen dient nachher zum Zeichnen der Achsen des Koordinatensystems und der CLinePen zum Zeichnen der Messkurve. Beide Stifte sollen eine Strichstärke von einem Pixel besitzen. Der CAxisPen ist als gestrichelter, blauer  Stift zu erstellen und der CLinePen als durchgezogener roter Stift.

Lösung zur Erstellung von Stiften

void CGDIFuncView::OnDraw(CDC* pDC)
{
    CGDIFuncDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen
    // Stift fuer das Koordinatensystem
    CPen     CAxisPen(PS_DASH,1,RGB(0,0,255));
    // Stift fuer die Kurve
    CPen    CLinePen;
    CLinePen.CreatePen(PS_SOLID,1,RGB(255,0,0));
}

In der hier vorgestellten Lösung wird das Aussehen des ersten Stifts CAxisPen gleich bei der Erstellung des CPen-Objektes angegeben während das Aussehen des zweiten Stifts CLinePen erst mittels der Methode CreatePen(...) festgelegt wird.

Das Löschen der Stifte mittels DeleteObjekt(...) kann hier entfallen, da beide CPen-Objekte als lokale Objekte definiert wurden die am Ende der Methode zerstört werden. Und der Destruktor von CPen löscht automatisch den Stift.

Ende der Lösung

Kommen wir jetzt zu den Methoden zum Zeichnen. Bei allen Methoden beachten Sie jedoch bitte unbedingt folgendes:

WINDOWS zeichnet nur in dem aktuell als ungültig markierten Bereich eines Fensters. Um einen Bereich eines Fensters als ungültig zu markieren kann unter anderem die CWnd-Methode Invalidate(...) bzw. InvalidateRect(...) eingesetzt werden

Die einfachste Methode um etwas in einem Fenster zu zeichnen ist die Methode SetPixel(...). Sie setzt einen Punkt im Fenster auf eine bestimmte Farbe. Die Koordinaten des Punktes sind in logischen Einheiten anzugeben.

Noch ein Hinweis zu den Koordinatenangaben. Koordinatenangaben in logischen Einheiten sind vom eingestellten Mapping-Mode abhängig, d.h. der Nullpunkt des Koordinatensystems liegt nicht unbedingt in der linken oberen Ecke und nächstliegende Koordinatenpunkt ist nicht immer auch der nächste physikalische Punkt auf dem Ausgabegerät (bei einem Bildschirm z.B. der nächste Bildpunkt). Koordinatenangaben in physikalischen Einheiten erfolgen unabhängig vom eingestellten Mapping-Mode, der Nullpunkt liegt stets in der linken oberen Ecke und der nächstliegende Koordinatenpunkt ist immer der nächste physikalische Punkt des Ausgabegeräts (beim Bildschirm der nächste Bildpunkt). Beim Standard-Mapping-Mode MM_TEXT, mehr dazu später noch,  ist das logische und das physikalische Koordinatensystem deckungsgleich. Der Nullpunkt liegt hier, wie bereits erwähnt, in der linken oberen Ecke und die Koordinatenwerte nehmen von links nach rechts und von oben nach unten zu. Dies mag Sie vielleicht im Augenblick etwas verwundern, aber bei der Ausgabe von Texten macht dies durch aus Sinn.

Sehen wir uns als nächstes an wie Linien gezeichnet werden. Wie Sie vorher schon erfahren haben, werden Linien mit dem aktuellen Stift gezeichnet. Um nun eine Linie vom Punkt A zum Punkt B und weiter zum Punkt C zu zeichnen, sind zwei verschiedene Methoden erforderlich. Vor dem Zeichnen einer Linie muss als erstes der sogenannte Grafikcursor mittels der CDC-Methode MoveTo(...) auf den Ausgangspunkt der Linie positioniert werden. Die an MoveTo(...) zu übergebenden Koordinaten beziehen sich auf logische Einheiten. Um dann anschließend eine Linie von der aktuellen Position des Grafikcursor aus zu zeichnen wird die CDC-Methode LineTo(...) aufgerufen. Die Parameter der Methode geben die Endkoordinate der Linie in logischen Einheiten an. Der Grafikcursor befindet sich nach der Ausführung der Methode auf dieser Endkoordinate. Mit aufeinanderfolgenden LineTo(...) Aufrufen kann somit ein Linienzug gezeichnet werden. Aber beachten Sie bitte folgendes:

Wird mit LineTo(...) eine Linie zum Punkt B gezeichnet, so endet die Linie eine Einheit vor diesem Punkt, d.h. der Endpunkt selbst wird nicht mehr mitgezeichnet.

Der nachfolgend dargestellte Linienzug wurde mit der unten stehenden OnDraw(...) Methode gezeichnet. Die strichpunktierte Linie endet auf dem Punkt (100,99) und der Grafikcursor befindet sich danach auf der Koordinate (100,100).

Linien zeichnen

void CGdiView::OnDraw(CDC* pDC)
{
    CGdiDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen
    try
    {
        CPen *pCOrgPen;
        CPen CRedPen(PS_SOLID,2,RGB(255,0,0));
        CPen CBluePen(PS_DASHDOT,1,RGB(0,0,255));

        // Grafikcursor auf Ausgangsposition setzen
        pDC->MoveTo(10,10);
        // Roten Stift fuer erste Linie auswaehlen
        pCOrgPen = pDC->SelectObject(&CRedPen);
        // Erste Linie zeichnen
        pDC->LineTo(100,10);
        // Strichpunktierten Stift fuer zweite Linie auswaehlen
        pDC->SelectObject(&CBluePen);
        // Hintergrund des strichpunktierten Stifts auf gruen setzen
        pDC->SetBkMode(OPAQUE);
        pDC->SetBkColor(RGB(0,255,0));
        // Zweite Linie zeichnen
        pDC->LineTo(100,100);
        // Original-Stift wieder auswaehlen
        pDC->SelectObject(pCOrgPen);
        // Hier werden die beiden Stifte wieder geloescht!!
    }
    // Hier Fehler beim Erstellen der Stifte abfangen
    catch (CResourceException& CEx)
    {
        char acErrText[128];
        CEx.GetErrorMessage( acErrText, sizeof(acErrText));
        MessageBox (acErrText,"FEHLER");
    }

}

Außer geraden Linien können auch Kreisbögen gezeichnet werden. Hierzu wird die CDC Methode Arc(...) aufgerufen. Sie zeichnet innerhalb eines umschließenden Rechtecks einen Kreisbogen von einem Startpunkt zum Endpunkt entgegen des Uhrzeigersinn. Der Start- und Endpunkt selbst muss dabei nicht auf dem Kreisbogen liegen. Auch hier erfolgt die Angabe der Koordinatenwerte wieder in logischen Einheiten.

Kreisbögen zeichnen

Unter WINDOWS NT/2000 und WINDOWS 98 kann die Zeichenrichtung des Bogen mit der Methode SetArcDirection(...) beeinflusst werden. Außerdem gibt es keine Methode um einen Kreis zu zeichnen. Sie müssen dazu die in der nächsten Lektion behandelte Methode Ellipse(...) verwenden.

Sollen Kurvenzüge gezeichnet werden, deren Daten in einem Feld abgelegt sind, so wird hierfür die CDC-Methode Polyline(...) verwendet. Die Koordinatenwerte, ebenfalls wieder in logischen Einheiten, müssen hierbei in einen CPoint- oder POINT-Feld abgelegt sein. Des weiteren steht zum Zeichnen von komplexen Kurvenzügen steht noch die Methode PolyPolyline(...) zur Verfügung. Sie zeichnet mehrere Kurvenzüge mit einem einzigen Aufruf.

Die letzte Methode die wir uns noch ansehen werden, ist die CDC-Methode PolyBezier(...). Diese Methode zeichnet einen oder mehrere Bézier Splines. Auch hier werden die Stützpunkte für die Kurve in einem CPoint- bzw. POINT-Feld übergeben. Sehen wir uns noch kurz den Begriff Bézier Spline an da er wahrscheinlich nicht so geläufig ist. Ein Bézier Spline wird durch 4 Stützpunkte definiert. Der erste Punkt ist der Startpunkt des Spline. Danach folgt der erste Stützpunkt. Dieser Stützpunkt bestimmt in welchem Winkel das Spline vom Startpunkt aus gezeichnet wird. Der nächste Punkt ist ebenfalls ein Stützpunkt und bestimmt den 'Eintrittswinkel' des Spline im Endpunkt. Der vierte und letzte Punkt ist dann der Endpunkt des Spline. Außer dem ersten Spline benötigen alle weiteren Splines nur noch 3 Punkte, da der Startpunkt mit dem Endpunkt des vorhergehenden Spline zusammenfällt. Das nachfolgende Bild zeigt diesen Zusammenhang nochmals auf. Das dazugehörige Programm folgt nach dem Bild.

Eine Bezierkurve

// Initialisierung der Bezier-Daten, irgendwo im Dokument
m_pPoints[0].x = 10;    // Startpunkt 0
m_pPoints[0].y = 100;
m_pPoints[1].x = 50;    // Stuetzpunkt 1
m_pPoints[1].y = 40;
m_pPoints[2].x = 75;   
// Stuetzpunkt 2
m_pPoints[2].y = 80;
m_pPoints[3].x = 100;  
// Endpunkt Kurve 1 und Startpunkt Kurve 2
m_pPoints[3].y = 25;
m_pPoints[4].x = 125;  
// Stuetzpunkt 1
m_pPoints[4].y = 75;
m_pPoints[5].x = 175;  
// Stuetzpunkt 2
m_pPoints[5].y = 25;
m_pPoints[6].x = 200;  
// Endpunkt Kurve 2
m_pPoints[6].y = 100;

void CGdiView::OnDraw(CDC* pDC)
{
    CGdiDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen
    POINT *pData;
    int nNoOfPoints;

    nNoOfPoints = pDoc->GetData(&pData);
    pDC->PolyBezier (pData, nNoOfPoints);
}

Werden die Stützpunkte 1 und 2 sowie die Stützpunkte 4 und 5 vertauscht, so ergibt sich folgendes Bild:

Bezier2.gif (4548 Byte)

 

So, jetzt sind Sie wieder dran. Erweitern Sie das Beispiel nun um die Darstellung der Messkurve. Alle hierfür notwendigen Methoden haben Sie nun kennen gelernt.

Für die Darstellung der Messkurve soll zunächst ein Achsenkreuz mit dem vorhin erstellten Stift CAxisPen gezeichnet werden. Da CAxisPen ein gestrichelter Stift ist, sollen die Zwischenräume zwischen den Strichen gelb ausgefüllt werden. Die für das Zeichnen des Achsenkreuzes notwendigen Werte XMin/XMax und YMin/YMax der Messkurve liegen bereits fertig berechnet in dem Membervariablen m_nXMin, m_nXMax, m_nYMin und m_nYMax des Ansichtsobjektes vor.

Die Messkurve selbst ist dem Stift CLinePen zu zeichnen.

Lösung zur Darstellung der Messkurve

void CGDIFuncView::OnDraw(CDC* pDC)
{
    CGDIFuncDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen
    // Stift fuer das Koordinatensystem
    CPen    CAxisPen(PS_DASH,1,RGB(0,0,255));
    // Stift fuer die Kurve
    CPen    CLinePen;
    CLinePen.CreatePen(PS_SOLID,1,RGB(255,0,0));

    // Hintergrund fuer gestrichelte Linie
    pDC->SetBkColor(RGB(255,255,0));
    pDC->SetBkMode(OPAQUE);

    // Koordinatenachsen zeichnen
    pDC->SelectObject(&CAxisPen);
    pDC->MoveTo(m_nXMin,0);
    pDC->LineTo(m_nXMax,0);
    pDC->MoveTo(0,m_nYMin);
    pDC->LineTo(0,m_nYMax);

    // Messkurve zeichnen
    pDC->SelectObject(&CLinePen);
    pDC->Polyline(m_pPts,m_nNoOfPts);
}

Zuerst wird der Hintergrund für den gestrichelten Stift gesetzt. Anschließend wird der Stift für das Achsenkreuz ausgewählt und dann die X-Achse und die Y-Achse gezeichnet. Zum Schluss wird der Stift für Darstellung der Messkurve ausgewählt und die Messkurve mittels Polyline(...) gezeichnet.

Die Stifte müssen hier nicht explizit gelöscht werden, da sie als lokale Objekte definiert wurden.

Ende der Lösung

Wenn Sie alles richtig eingegeben haben sollten Sie folgende Darstellung erhalten:

Messkurve, 1. Versuch

Für den Anfang doch nicht schlecht. Aber diese Darstellung hat noch einige 'kleine' Fehler. Zum einen widerspricht die Richtung der Y-Achse dem normalen mathematischen Denken. Die positiven Werte der Y-Achse gehen hier nach unten da die Fensterkoordinaten in Y-Richtung von oben nach unten zunehmen. Zweitens sehen Sie nur die positiven X- und Y-Werte da der Nullpunkt des Fensters sich links oben im Fenster befindet. Wenn Sie genau hinsehen, werden Sie das Achsenkreuz gerade noch so am Fensterrand erkennen können. Und drittens ist die Darstellung der Kurve relativ klein. All diese Ungereimtheiten werden wir in der übernächsten Lektion noch beseitigen.

Beenden wir damit die Einführung der Linienfunktionen und wenden uns in der nächsten Lektion den Flächenfunktionen zu.



Copyright © 2004

Senden Sie Emails mit Fragen oder Kommentaren zu dieser Website an: mailto:info@cpp-tutor.de
 Wolfgang Schröder, Lerchenweg 23, D-72805 Lichtenstein. Tel: +49 7129 6470