Übersicht über Formen und die grundlegenden Funktionen zum Zeichnen in WPF

Dieses Thema bietet eine Übersicht über das Zeichnen mit Shape-Objekten. Eine Shape ist ein Typ von UIElement, mit der Sie eine Form auf dem Bildschirm zeichnen können. Da sie Benutzeroberflächenelemente sind, können Shape-Objekte in Panel-Elementen und den meisten Steuerelementen verwendet werden.

WPF (Windows Presentation Foundation) bietet mehrere Ebenen für den Zugriff auf Grafiken und Renderingdienste. Auf der obersten Ebene sind Shape-Objekte einfach zu verwenden und bieten viele nützliche Funktionen, z. B. Layout und Teilnahme am WPF-Ereignissystem.

Formbezogene Typen befinden sich im Windows.Shapes-Namespace. Geometriebezogene Typen befinden sich im System.Windows.Media-Namespace.

Shape-Objekte

WPF stellt eine Reihe von einsatzbereiten Shape-Objekten zur Verfügung. Alle shape-Objekte erben von der Shape-Klasse. Verfügbare Shape-Objekte sind Ellipse, Line, Path, Polygon, Polyline und Rectangle. Shape-Objekte geben die folgenden allgemeinen Eigenschaften frei.

  • Stroke beschreibt, wie die Kontur der Form gezeichnet wird.

  • StrokeThickness beschreibt die Dicke der Kontur der Form.

  • Fill beschreibt, wie das Innere der Form gezeichnet wird.

  • Dateneigenschaften zum Angeben von Koordinaten und Eckpunkten, gemessen in geräteunabhängigen Pixeln.

Da sie von UIElement abgeleitet sind können shape-Objekte in Panels und den meisten Steuerelementen verwendet werden. Das Canvas-Panel ist eine besonders gute Wahl für das Erstellen von komplexen Zeichnungen, da es die absolute Positionierung der untergeordneten Objekte unterstützt.

Die Line-Klasse ermöglicht Ihnen, eine Linie zwischen zwei Punkten zu zeichnen. Das folgende Beispiel zeigt verschiedene Arten, wie Zeilenkoordinaten und Stricheigenschaften angegeben werden können.

<Canvas Height="300" Width="300">

  <!-- Draws a diagonal line from (10,10) to (50,50). -->
  <Line
    X1="10" Y1="10"
    X2="50" Y2="50"
    Stroke="Black"
    StrokeThickness="4" />

  <!-- Draws a diagonal line from (10,10) to (50,50)
       and moves it 100 pixels to the right. -->
  <Line
    X1="10" Y1="10"
    X2="50" Y2="50"
    StrokeThickness="4"
    Canvas.Left="100">
    <Line.Stroke>
      <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
        <RadialGradientBrush.GradientStops>
          <GradientStop Color="Red" Offset="0" />
          <GradientStop Color="Blue" Offset="0.25" />
        </RadialGradientBrush.GradientStops>
      </RadialGradientBrush>
    </Line.Stroke>
  </Line>

  <!-- Draws a horizontal line from (10,60) to (150,60). -->
  <Line
     X1="10" Y1="60"
     X2="150" Y2="60"
     Stroke="Black"
     StrokeThickness="4"/>

</Canvas>

// Add a Line Element
myLine = gcnew Line();
myLine->Stroke = Brushes::LightSteelBlue;
myLine->X1 = 1;
myLine->X2 = 50;
myLine->Y1 = 1;
myLine->Y2 = 50;
myLine->HorizontalAlignment = HorizontalAlignment::Left;
myLine->VerticalAlignment = VerticalAlignment::Center;
myLine->StrokeThickness = 2;
myGrid->Children->Add(myLine);

// Add a Line Element
myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);

' Add a Line Element
Dim myLine As New Line()
myLine.Stroke = Brushes.LightSteelBlue
myLine.X1 = 1
myLine.X2 = 50
myLine.Y1 = 1
myLine.Y2 = 50
myLine.HorizontalAlignment = HorizontalAlignment.Left
myLine.VerticalAlignment = VerticalAlignment.Center
myLine.StrokeThickness = 2
myGrid.Children.Add(myLine)

Die folgende Abbildung zeigt die gerenderte Line.

Liniendarstellung

Obwohl die Line-Klasse eine Fill-Eigenschaft bietet, hat das Festlegen derselben keine Auswirkung, da eine Line keine Fläche hat.

Eine weitere allgemeine Form ist die Ellipse. Sie erstellen eine Ellipse durch Definieren der Eigenschaften Width und Height der Form. Um einen Kreis zu zeichnen, geben Sie eine Ellipse an, bei der die Werte Width und Height gleich sind.

<Ellipse
Fill="Yellow"
Height="100"
Width="200"
StrokeThickness="2"
Stroke="Black"/>

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SDKSample
{
    public partial class SetBackgroundColorOfShapeExample : Page
    {
        public SetBackgroundColorOfShapeExample()
        {
            // Create a StackPanel to contain the shape.
            StackPanel myStackPanel = new StackPanel();

            // Create a red Ellipse.
            Ellipse myEllipse = new Ellipse();

            // Create a SolidColorBrush with a red color to fill the
            // Ellipse with.
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();

            // Describes the brush's color using RGB values.
            // Each value has a range of 0-255.
            mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
            myEllipse.Fill = mySolidColorBrush;
            myEllipse.StrokeThickness = 2;
            myEllipse.Stroke = Brushes.Black;

            // Set the width and height of the Ellipse.
            myEllipse.Width = 200;
            myEllipse.Height = 100;

            // Add the Ellipse to the StackPanel.
            myStackPanel.Children.Add(myEllipse);

            this.Content = myStackPanel;
        }
    }
}

Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes

Namespace SDKSample
    Partial Public Class SetBackgroundColorOfShapeExample
        Inherits Page
        Public Sub New()
            ' Create a StackPanel to contain the shape.
            Dim myStackPanel As New StackPanel()

            ' Create a red Ellipse.
            Dim myEllipse As New Ellipse()

            ' Create a SolidColorBrush with a red color to fill the 
            ' Ellipse with.
            Dim mySolidColorBrush As New SolidColorBrush()

            ' Describes the brush's color using RGB values. 
            ' Each value has a range of 0-255.
            mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0)
            myEllipse.Fill = mySolidColorBrush
            myEllipse.StrokeThickness = 2
            myEllipse.Stroke = Brushes.Black

            ' Set the width and height of the Ellipse.
            myEllipse.Width = 200
            myEllipse.Height = 100

            ' Add the Ellipse to the StackPanel.
            myStackPanel.Children.Add(myEllipse)

            Me.Content = myStackPanel
        End Sub

    End Class
End Namespace

Die folgende Abbildung zeigt ein Beispiel für eine gerenderte Ellipse.

Ellipsendarstellung

Verwenden von Pfaden und Geometrien

Die Path-Klasse ermöglicht Ihnen, Kurven und komplexe Formen zu zeichnen. Diese Kurven und Formen werden mit Geometry-Objekte beschrieben. Zum Verwenden eines Path, erstellen Sie eine Geometry und verwenden diese, um die Data-Eigenschaft des Path-Objekts festzulegen.

Es gibt eine Vielzahl von Geometry-Objekten, aus denen Sie auswählen können. Die Klassen LineGeometry, RectangleGeometry und EllipseGeometry beschreiben relativ einfache Formen. Verwenden Sie eine PathGeometry, um komplexere Formen oder Kurven zu erstellen.

PathGeometry und PathSegments

PathGeometry-Objekte werden aus einem oder mehreren PathFigure-Objekten zusammengestellt, wobei jede PathFigure eine andere „Figur“ oder Form repräsentiert. Jede PathFigure ist selbst aus einem oder mehreren PathSegment-Objekten zusammengestellt, wobei jede einen Verbindungsanschluss der Figur oder Form repräsentiert. Folgende Segmenttypen stehen zur Verfügung: LineSegment, BezierSegment und ArcSegment.

Im folgenden Beispiel wird ein Path zum Zeichnen einer quadratischen Bézierkurve verwendet.

<Path Stroke="Black" StrokeThickness="1">
  <Path.Data>
    <PathGeometry>
      <PathGeometry.Figures>
        <PathFigureCollection>
          <PathFigure StartPoint="10,100">
            <PathFigure.Segments>
              <PathSegmentCollection>
                <QuadraticBezierSegment Point1="200,200" Point2="300,100" />
              </PathSegmentCollection>
            </PathFigure.Segments>
          </PathFigure>
        </PathFigureCollection>
      </PathGeometry.Figures>
    </PathGeometry>
  </Path.Data>
</Path>

Die folgende Abbildung zeigt die gerenderte Form.

Pfaddarstellung

Weitere Informationen zu PathGeometry und anderen Geometry-Klassen finden Sie unter Übersicht über Geometrien.

Abgekürzte Syntax in XAML

In XAML (Extensible Application Markup Language) können Sie auch eine spezielle abgekürzte Syntax verwenden, um einen Path zu beschreiben. Im folgenden Beispiel wird abgekürzte Syntax verwendet, um eine komplexe Form zu zeichnen.

      <Path Stroke="DarkGoldenRod" StrokeThickness="3"
Data="M 100,200 C 100,25 400,350 400,175 H 280" />  

Die folgende Abbildung zeigt einen gerenderten Path.

Weitere Pfaddarstellung

Die Zeichenfolge des Data-Attributs beginnt mit dem moveto-Befehl, angegeben durch „M“, der einen Startpunkt für den Pfad im Koordinatensystem der Canvas festlegt. Bei Path-Datenparametern wird die Groß-/Kleinschreibung beachtet. Der Großbuchstabe „M“ gibt eine absolute Position für den neuen aktuellen Punkt an. Ein kleingeschriebenes m würde relative Koordinaten angeben. Das erste Segment ist eine kubische Bézierkurve, die bei (100,200) beginnt und bei (400,175) endet. Sie wird mit zwei Kontrollpunkten bei (100,25) und (400,350) gezeichnet. Dieses Segment wird durch den „C“-Befehl in der Zeichenfolge des Data-Attributs angegeben. Ein großes C gibt erneut einen absoluten Pfad an. Ein kleingeschriebenes c würde einen relativen Pfad angeben.

Das zweite Segment beginnt mit einem absoluten horizontalen „Lineto“-Befehl H, der eine Linie vom vorherigen untergeordneten Endpunkt (400,175) zu einem neuen Endpunkt (280,175) zeichnet. Da es sich um einen horizontalen lineto-Befehl handelt, ist der angegebene Wert eine x-Koordinate.

Die vollständige Pfadsyntax finden Sie unter dem Data-Verweis und unter Erstellen einer Form mithilfe von PathGeometry.

Zeichnen von Formen

Brush-Objekte werden verwendet, um den Stroke und die Fill von Formen zu zeichnen. Im folgenden Beispiel werden Pinselstrich und Füllung einer Ellipse angegeben. Beachten Sie, dass Pinseleigenschaften entweder ein Schlüsselwort oder einen hexadezimalen Farbwert werden können. Weitere Informationen zu den verfügbaren Farbschlüsselwörtern finden Sie unter den Eigenschaften der Colors-Klasse im System.Windows.Media-Namespace.

<Canvas Background="LightGray">
   <Ellipse  
      Canvas.Top="50"  
      Canvas.Left="50"  
      Fill="#FFFFFF00"  
      Height="75"  
      Width="75"  
      StrokeThickness="5"  
      Stroke="#FF0000FF"/>  
</Canvas>  

Die folgende Abbildung zeigt die gerenderte Ellipse.

Eine Ellipse

Alternativ können Sie die Syntax eines Eigenschaftenelements verwenden, um explizit ein SolidColorBrush-Objekt zum Zeichnen der Form in einer Volltonfarbe zu erstellen.

<!-- This polygon shape uses pre-defined color values for its Stroke and  
     Fill properties.   
     The SolidColorBrush's Opacity property affects the fill color in   
     this case by making it slightly transparent (opacity of 0.4) so   
     that it blends with any underlying color. -->  
  
<Polygon  
    Points="300,200 400,125 400,275 300,200"  
    Stroke="Purple"
    StrokeThickness="2">  
    <Polygon.Fill>  
       <SolidColorBrush Color="Blue" Opacity="0.4"/>  
    </Polygon.Fill>  
</Polygon>  

Die folgende Abbildung zeigt die gerenderte Form.

SolidColorBrush-Darstellung

Sie können die Kontur oder Fläche einer Form auch mit Farbverläufen, Bildern, Mustern und mehr zeichnen. Weitere Informationen finden Sie unter Übersicht über das Zeichnen mit Volltonfarben und Farbverläufen.

Gestreckte Formen

Die Klassen Line, Path, Polygon, Polyline und Rectangle verfügen alle über eine Stretch-Eigenschaft. Diese Eigenschaft bestimmt, wie der Inhalt eines Shape-Objekts (die zu zeichnende Form) gestreckt wird, um den Layoutbereich des Shape-Objekts zu füllen. Der Layoutbereich eines Shape-Objekts ist der Platz, der vom Layoutsystem für Shape zugeordnet wird – entweder aufgrund einer expliziten Festlegung von Width und Height oder aufgrund seiner Einstellungen HorizontalAlignment und VerticalAlignment. Weitere Informationen zu Layouts in Windows Presentation Foundation finden Sie unter Übersicht über das Layout.

Die Stretch-Eigenschaft nimmt einen der folgenden Werte an:

  • None: Die Inhalte des Shape-Objekts wird nicht gestreckt.

  • Fill: Die Inhalte des Shape-Objekts wird gestreckt, um den Layoutbereich auszufüllen. Das Seitenverhältnis wird nicht beibehalten.

  • Uniform: Die Inhalte des Shape-Objekts werden so weit wie möglich gestreckt, um den Layoutbereich auszufüllen und gleichzeitig die ursprünglichen Seitenverhältnisse beizubehalten.

  • UniformToFill: Die Inhalte des Shape-Objekts werden gestreckt, um den Layoutbereich vollständig auszufüllen und gleichzeitig die ursprünglichen Seitenverhältnisse beizubehalten.

Beachten Sie, dass beim Strecken des Inhalts des Shape-Objekts der Rand des Shape-Objekts erst nach dem Strecken gezeichnet wird.

Im folgenden Beispiel wird mit einem Polygon ein sehr kleines Dreieck von (0,0) bis (0,1) bis (1,1) gezeichnet. Die Eigenschaften Width und Height des Polygon-Objekts werden auf 100 und die Streckungseigenschaft wird auf „Fill“ festgelegt. Daher wird der Inhalt des Polygon-Objekts (das Dreieck) gestreckt, um den größeren Bereich auszufüllen.

<Polygon  
  Points="0,0 0,1 1,1"  
  Fill="Blue"  
  Width="100"  
  Height="100"  
  Stretch="Fill"  
  Stroke="Black"  
  StrokeThickness="2" />  
PointCollection myPointCollection = new PointCollection();  
myPointCollection.Add(new Point(0,0));  
myPointCollection.Add(new Point(0,1));  
myPointCollection.Add(new Point(1,1));  
  
Polygon myPolygon = new Polygon();  
myPolygon.Points = myPointCollection;  
myPolygon.Fill = Brushes.Blue;  
myPolygon.Width = 100;  
myPolygon.Height = 100;  
myPolygon.Stretch = Stretch.Fill;  
myPolygon.Stroke = Brushes.Black;  
myPolygon.StrokeThickness = 2;  

Transformieren von Formen

Die Transform-Klasse bietet die Möglichkeit, Formen in einer zweidimensionalen Ebene zu transformieren. Zu den verschiedenen Transformationstypen gehören Drehung (RotateTransform), Skalierung (ScaleTransform), Scherung (SkewTransform) und Übersetzung (TranslateTransform).

Eine allgemeine Transformation einer Form ist die Drehung. Um eine Form zu drehen, erstellen Sie eine RotateTransform und geben deren Angle an. Wenn Sie für Angle den Wert 45 angeben, wird das Element um 45 Grad im Uhrzeigersinn gedreht. Ein Winkel von 90 dreht das Element um 90 Grad im Uhrzeigersinn usw. Legen Sie die CenterX- und CenterY-Eigenschaften fest, wenn Sie steuern möchten, um welchen Punkt das Element gedreht werden soll. Diese Eigenschaftswerte werden im Koordinatenraum des transformierten Elements ausgedrückt. CenterX und CenterY haben den Standardwerte null. Wenden Sie abschließend die RotateTransform auf das Element an. Wenn die Transformation sich nicht auf das Layout auswirken soll, legen Sie RenderTransform-Eigenschaft der Form fest.

Im folgenden Beispiel wird eine RotateTransform verwendet, um eine Form um 45 Grad zur linken oberen Ecke (0,0) zu drehen.

<!-- Rotates the Polyline 45 degrees about the point (0,0). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0" 
  Stroke="Blue" StrokeThickness="10"
  Canvas.Left="75" Canvas.Top="50">
  <Polyline.RenderTransform>
    <RotateTransform CenterX="0" CenterY="0" Angle="45" />
  </Polyline.RenderTransform>
</Polyline>

Im nächsten Beispiel eine andere Form um 45 Grad gedreht wird, aber dieses Mal wird sie über den Punkt (25,50) gedreht.

<!-- Rotates the Polyline 45 degrees about its center. -->
<Polyline 
  Points="25,25 0,50 25,75 50,50 25,25 25,0" 
  Stroke="Blue" StrokeThickness="10"
  Canvas.Left="75" Canvas.Top="50"
  RenderTransformOrigin="0.5,0.5">
  <Polyline.RenderTransform>
    <RotateTransform Angle="45" />
  </Polyline.RenderTransform>
</Polyline>

In der folgenden Abbildung werden die Ergebnisse der Anwendung der zwei Transformationen dargestellt.

45-Grad-Drehungen mit unterschiedlichen Mittelpunkten

In den vorherigen Beispielen wurde eine einzelne Transformation auf jedes Shape-Objekt angewendet. Verwenden Sie zum Anwenden mehrerer Transformationen auf eine Form (oder andere Elemente der Benutzeroberfläche) eine TransformGroup.

Weitere Informationen