# 22 2D-Grafik Langsam nähern wir uns dem Ende des WPF-Teils dieses Buches. In diesem letzten Kapitel zur WPF möchte ich Ihnen einen kurzen Einblick in die grafischen Fähigkeiten der WPF geben. Mehr noch als in den anderen Kapiteln zuvor gilt hier, dass wir uns nur auf einen oberflächlichen Streifzug durch die 2D-Grafik begeben. Auf die Betrachtung der 3D-Fähigkeiten und auch auf das Erzeugen von Animationen müssen wir leider aus Platzgründen verzichten. Eigentlich schade, denn insbesondere diese Themen bieten viele reizvolle Effekte. Allerdings wären für diese Themen bei intensiver Behandlung auch ein paar hundert Seiten mehr erforderlich. So beschränken wir uns in diesem Buch auf die Grundzüge der 2D-Grafik, was immerhin erahnen lässt, welche Fähigkeiten, jetzt rein aus grafischer Sicht, in WPF stecken. ## 22.1 Shapes ### 22.1.1 Allgemeine Beschreibung Die einfach zu verwendenden Shapes stellen grafische Elemente dar, die sich auf der Oberfläche platzieren lassen. Allen gemeinsam ist die Basisklasse Shape, von der es sechs Ableitungen gibt. Sie haben also eine gemeinsame Grundfunktionalität. Shape selbst leitet sich aus UIElement ab, so wie auch beispielsweise der Button oder die TextBox. Somit können Sie Shapes genauso wie diese Steuerelemente behandeln: Sie zeichnen sich selbst und reagieren sogar auf Maus- und Tastatureingaben. Eine Besonderheit sollte nicht unerwähnt bleiben. Shapes können keine anderen Elemente aufnehmen, wie es üblicherweise bei den Steuerelementen der Fall ist. Shapes eignen sich, um durch die Kombination mehrerer Shapes komplexere grafische Gebilde zu schaffen. Dazu sollten Sie einen Canvas-Container benutzen, da sich UI-Elemente darin beliebig positionieren lassen. Als Basisklasse stellt Shape einige spezifische Eigenschaften bereit. Dazu gehört beispielsweise die Eigenschaft Fill, mit der ein Füllmuster angegeben werden kann. Füllmuster werden durch die Klasse Brush beschrieben, der wir uns später ebenfalls noch zuwenden werden. Zur Anpassung an den Umgebungsbereich dient die Eigenschaft Stretch. Zudem werden mit mehreren StrokeXxx-Eigenschaften Möglichkeiten zur Definition von Rahmen, Linien und Linienzügen angeboten. Die von Shape abgeleiteten Klassen können Sie Tabelle 22.1 entnehmen.

Tabelle 22.1 Die von Shape abgeleiteten Klassen

Klasse | Beschreibung
Ellipse | Beschreibt Ellipsen und Kreise.
Line | Beschreibt eine durch Koordinaten definierte Linie.
Path | Beschreibt eine komplexe Struktur, die aus Linien, Bögen und Rechtecken besteht.
Polygon | Beschreibt eine Reihe von Koordinatenpunkten. Der letzte Koordinatenpunkt wird mit dem ersten verbunden, sodass eine geschlossene Fläche entsteht.
Polyline | Beschreibt eine geometrische Struktur, bei der der letzte Punkt nicht mit dem ersten verbunden wird, wie das bei Polygon der Fall ist.
Rectangle | Beschreibt ein Rechteck.
### 22.1.2 Line-Elemente Linien werden über zwei Punkte definiert. Dafür dienen die Eigenschaften X1, Y1 und X2, Y2. X1 und Y1 beschreiben den Startpunkt der Linie, wobei als Ursprungspunkt der linke obere Eckpunkt des Containers dient. Die Farbe der Linie wird durch Stroke beschrieben, die Zeichenbreite durch StrokeThickness. Setzen Sie zum Zeichnen die Klasse Pen ein, können Sie die Charakteristik der Linien auch frei gestalten. Beispielsweise ließen sich damit gestrichelte Linien darstellen, oder Sie könnten das Linienende abrunden:
    <Canvas>
       <Line X1="10" X2="100" Y1="110" Y2="40"
             Stroke="Blue" StrokeThickness="4" />
       <Line X1="0" X2="120" Y1="0" Y2="100"
             Stroke="Red" StrokeThickness="2" />
    </Canvas>
Hier klicken, um das Bild zu vergrößern Abbildung 22.1 Liniendarstellung ### 22.1.3 Ellipse- und Rectangle-Elemente Im XAML-Code sind sich Rectangle und Ellipse sehr ähnlich. Über Height und Width wird die Ausdehnung der beiden grafischen Elemente beschrieben. Auch hier ist der Bezugsstartpunkt der linke obere Eckpunkt des umgebenden Containers. Eine Besonderheit hat Rectangle zu bieten. Mit RadiusX und RadiusY können Sie abgerundete Ecken erzeugen. Im Gegensatz zu Line macht die Eigenschaft Fill hier Sinn, da es sich um flächenbeschreibende grafische Figuren handelt.
    <Canvas>
      <Rectangle Width="120" Height="40" Stroke="Blue"
                 StrokeThickness="2" Fill="AntiqueWhite"
                 RadiusX="10" RadiusY="30" />
      <Ellipse Width="100" Height="100" Stroke="Black" StrokeThickness="2" />
    </Canvas>
Hier klicken, um das Bild zu vergrößern Abbildung 22.2 Rechteck und Ellipe ### 22.1.4 Polygon- und Polyline-Elemente Zum Zeichnen eines Polygon- oder Polyline-Objekts werden die einzelnen Punkte durch den Typ Point beschrieben und einer PointCollection übergeben. Diese wird mit der Eigenschaft Points angesprochen. Bei einem Polygon werden der erste und der letzte Punkt automatisch miteinander verbunden, sodass daraus eine geschlossene Fläche resultiert. In XAML werden die Punkte als Wertepaare angegeben. Jedes Wertepaar kann durch ein Komma getrennt werden, aber das ist optional. Somit sind die beiden folgenden XAML-Ausdrücke identisch:
    <Polyline Points="0 0 20 30 40 70 60 30" Stroke="Black" />
    <Polyline Points="0,0 20,30 40,70 60,30" Stroke="Black" />
### 22.1.5 Darstellung der Linien Eine Vielzahl von Eigenschaften ermöglicht es, die Darstellung der Linien von Shape-Objekten zu beeinflussen. Stroke und StrokeThickness haben wir bereits benutzt. In Tabelle 22.2 sind einige der beeinflussenden Eigenschaften aufgeführt.

Tabelle 22.2 Eigenschaften zur Darstellung der Linien

Eigenschaft | Beschreibung
Stroke | Gibt das Füllmuster an. Die Eigenschaft erwartet ein Brush-Objekt. Im einfachsten Fall geben Sie hier nur die Farbe an.
StrokeDashArray | Gibt das Strichmuster der Linie an.
StrokeDashCap | Definiert die Form der Linienenden innerhalb der Linie bei Verwendung von Mustern. Diese Eigenschaft ist vom Typ der Enumeration PenLineCap.
StrokeDashOffset | Beschreibt den Versatz, der beim Zeichnen einer Strich-Punkt-Linie verwendet wird.
StrokeEndLineCap | Definiert die Form des Linienendes und ist vom Typ der Aufzählung PenLineCap.
StrokeLineJoin | Definiert, wie zwei Linienenden miteinander verbunden werden. Die Eigenschaft ist vom Typ der Enumeration PenLineJoin.
StrokeMiterLimit | Legt fest, wie zwei Linienenden beim Aufeinandertreffen ineinander übergehen.
StrokeStartLineCap | Definiert die Form des Linienanfangs und ist vom Typ der Aufzählung PenLineCap.
StrokeThickness | Legt die Zeichenbreite fest.
Linienenden werden durch einen Wert der Enumeration PenLineCap beschrieben. Diese Aufzählung beschreibt die Werte Flat, Round, Square und Triangle. Das dürfte keiner weiteren Erläuterung bedürfen. Erklärungsbedürftig sind aber auf jeden Fall die beiden Eigenschaften StrokeDashArray und StrokeDashOffset. Beide gestatten die freie Definition der Linie mit Double-Werten. Die Double-Werte werden in einer Collection gelistet. Es wird immer ein Pärchen gebildet, bei dem die erste Zahl die Länge der Teillinie beschreibt und die zweite die Lücke zwischen zwei Linien. Dabei ist eine Besonderheit zu beachten: Die Werte werden immer mit der Linienbreite StrokeThickness multipliziert. In Abbildung 22.3 sind drei Linien dargestellt, die einige der aufgeführten Eigenschaften nutzen. Die Ausgabe basiert auf dem folgenden XAML-Code:
    <Canvas>
      <Line X1="10" X2="400" Y1="10" Y2="10" Stroke="Black"
            StrokeThickness="10"
            StrokeDashArray="2 3 2 3 2 3" StrokeStartLineCap="Square"
            StrokeDashOffset="2"
            StrokeDashCap="Round" />
      <Line X1="10" X2="400" Y1="30" Y2="30" Stroke="Blue" StrokeThickness="10"
            StrokeDashArray="1 2 4 2"
            StrokeDashCap="Triangle"/>
      <Line X1="10" X2="400" Y1="50" Y2="50" Stroke="Red" StrokeThickness="10"
            StrokeDashArray="1 0.5 5 0.5"/>
    </Canvas>
Hier klicken, um das Bild zu vergrößern