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

Dieses Thema gibt eine Übersicht über das Zeichnen mit Shape-Objekten. Ein Shape-Objekt ist ein UIElement-Typ und ermöglicht Ihnen das Zeichnen von Formen auf dem Bildschirm. Da es sich hierbei um Benutzeroberflächenelemente handelt, können Shape-Objekte innerhalb von Panel-Elementen und den meisten Steuerelementen verwendet werden.

Windows Presentation Foundation (WPF) bietet mehrere Ebenen für den Zugriff auf Grafiken und Renderingdienste. Auf der obersten Ebene stehen die benutzerfreundlichen Shape-Objekte mit einer Vielzahl von nützlichen Features zur Verfügung, z. B. Layout und Teilnahme am Windows Presentation Foundation (WPF)-Ereignissystem.

Dieses Thema enthält folgende Abschnitte.

  • Shape-Objekte
  • Verwenden von Pfaden und Geometrien
  • Zeichnen von Formen
  • Gestreckte Formen
  • Transformieren von Formen
  • Verwandte Abschnitte

Shape-Objekte

WPF stellt eine Reihe von vorgefertigten Shape-Objekten zur Verfügung. Alle Shape-Objekte erben von der Shape-Klasse. Zu den verfügbaren Shape-Objekten gehören Ellipse, Line, Path, Polygon, Polyline und Rectangle. Shape-Objekte besitzen alle die folgenden allgemeinen Eigenschaften.

  • Stroke: Beschreibt, wie der Rand der Form gezeichnet wird.

  • StrokeThickness: Beschreibt die Randstärke der Form.

  • Fill: Beschreibt, wie das Innere der Form gezeichnet wird.

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

Da sie sich vom UIElement herleiten, können Shape-Objekte in Bereichen und den meisten Steuerelementen verwendet werden. Der Canvas-Bereich eignet sich besonders gut zur Erstellung komplexer Zeichnungen, da er die absolute Positionierung von untergeordneten Objekten unterstützt.

Die Line-Klasse ermöglicht es Ihnen, eine Linie zwischen zwei Punkten zu zeichnen. Im folgenden Beispiel werden mehrere Möglichkeiten veranschaulicht, Linienkoordinaten und Stricheigenschaften anzugeben.

<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
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)

// 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
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);

Die folgende Abbildung zeigt die gerenderte Line.

Liniendarstellung

Obwohl die Line-Klasse die Fill-Eigenschaft bereitstellt, wirkt sich die Einstellung dieser Eigenschaft nicht aus, da eine Line über keinen Bereich verfügt.

Eine weitere allgemeine Form ist die Ellipse. Sie erstellen eine Ellipse, indem Sie die Formeigenschaften Width und Height definieren. Um einen Kreis zu zeichnen, geben Sie eine Ellipse an, deren Werte für Width und Height gleich sind.

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


Imports Microsoft.VisualBasic
Imports System
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
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;
        }

    }
}

Die folgende Abbildung zeigt ein Beispiel einer gerenderten Ellipse.

Ellipsendarstellung

Verwenden von Pfaden und Geometrien

Die Path-Klasse ermöglicht es Ihnen, Kurven und komplexe Formen zu zeichnen. Diese Kurven und Formen werden mithilfe der Geometry-Objekte beschrieben. Zur Verwendung von Path erstellen Sie ein Geometry-Objekt und nutzen es, um die Data-Eigenschaft des Path-Objekts festzulegen.

Sie können aus einer Vielzahl von Geometry-Objekten auswählen. Die Klassen LineGeometry, RectangleGeometry und EllipseGeometry beschreiben relativ einfache Formen. Um komplexere Formen oder Kurven zu erstellen, verwenden Sie ein PathGeometry-Objekt.

PathGeometry und PathSegments

PathGeometry-Objekte setzen sich aus einem oder mehreren PathFigure-Objekten zusammen, wobei jedes PathFigure-Objekt eine andere "Abbildung" oder Form darstellt. Jedes PathFigure-Objekt setzt sich wiederum aus einem oder mehreren PathSegment-Objekten zusammen, die jeweils einen verknüpften Bereich der Abbildung oder Form darstellen. Zu den Segmenttypen gehören 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 über PathGeometry und die anderen Geometry-Klassen finden Sie unter Übersicht über die Geometrie.

Abgekürzte Syntax in XAML

In Extensible Application Markup Language (XAML) können Sie einen Path auch mit einer besonderen abgekürzten Syntax beschreiben. Im folgenden Beispiel wird eine 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.

Pfaddarstellung

Die Data-Attributzeichenfolge beginnt mit dem Verschiebebefehl, angegeben durch ein "M", der im Koordinatensystem von Canvas einen Startpunkt für den Pfad festlegt. Bei Path-Datenparametern wird die Groß-/Kleinschreibung beachtet. Der großgeschriebene Buchstabe M gibt eine absolute Position für den neuen aktuellen Punkt an. Ein kleingeschriebenes m gibt relative Koordinaten an. Das erste Segment ist eine kubische Bézierkurve, die an der Position (100,200) beginnt, an der Position (400,175) endet und mit den beiden Kontrollpunkten (100,25) und (400,350) gezeichnet wird. Dieses Segment wird durch den C-Befehl in der Data-Attributzeichenfolge angegeben. Auch hier gibt der großgeschriebene Buchstabe C einen absoluten Pfad an. Ein kleingeschriebenes c würde einen relativen Pfad angeben.

Das zweite Segment beginnt mit dem absoluten horizontalen LineTo-Befehl "H", der eine Linie angibt, die vom Endpunkt (400,175) des vorherigen untergeordneten Pfads bis zu einem neuen Endpunkt (280,175) gezeichnet wird. Da es sich um einen horizontalen Linienbefehl handelt, ist der angegebene Wert eine x-Koordinate.

Die vollständige Pfadsyntax finden Sie in der Referenz für Data und unter Gewusst wie: Erstellen einer Form mithilfe von PathGeometry.

Zeichnen von Formen

Brush-Objekte werden zum Zeichnen von Stroke und Fill für eine Form verwendet. Im folgenden Beispiel werden der Strich und der Füllbereich einer Ellipse angegeben. Beachten Sie, dass Pinseleigenschaften entweder über ein Schlüsselwort oder anhand eines hexadezimalen Farbwerts eingegeben werden können. Weitere Informationen über verfügbare Farbschlüsselwörter finden Sie in 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 dazu 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 den Strich oder Füllbereich einer Form auch mit Farbverläufen, Bildern, Mustern usw. 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 die Stretch-Eigenschaft. Diese Eigenschaft legt fest, wie der Inhalt (die zu zeichnende Form) eines Shape-Objekts gestreckt wird, um den Layoutbereich im Shape-Objekt auszufüllen. Der Layoutbereich eines Shape-Objekts ist die Bereichsgröße, die dem Shape-Objekt vom Layoutsystem zugeordnet wird, und zwar entweder durch die explizite Einstellung von Width und Height oder aufgrund seiner Einstellungen für HorizontalAlignment und VerticalAlignment. Weitere Informationen über das Layout in Windows Presentation Foundation finden Sie in der Übersicht Layoutsystem.

Die Stretch-Eigenschaft nimmt einen der folgenden Werte an:

  • None: Der Inhalt des Shape-Objekts wird nicht gestreckt.

  • Fill: Der Inhalt des Shape-Objekts wird gestreckt, um dessen Layoutbereich auszufüllen. Das Seitenverhältnis wird nicht beibehalten.

  • Uniform: Der Inhalt des Shape-Objekts wird so weit wie möglich gestreckt, um unter Beibehaltung des ursprünglichen Seitenverhältnisses den Layoutbereich auszufüllen.

  • UniformToFill: Der Inhalt des Shape-Objekts wird gestreckt, um unter Beibehaltung des ursprünglichen Seitenverhältnisses den Layoutbereich komplett auszufüllen.

Beachten Sie, dass beim Strecken des Inhalts eines Shape-Objekts der Rand des Shape-Objekts 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 sind für das Polygon-Objekt auf 100 festgelegt; die Stretch-Eigenschaft ist auf Fill festgelegt. Das Ergebnis ist, dass der Inhalt (das Dreieck) des Polygon-Objekts gestreckt wird, 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 stellt die Mittel bereit, Formen in einer zweidimensionalen Ebene zu transformieren. Zu den unterschiedlichen Transformationstypen gehören die Drehung (RotateTransform), die Skalierung (ScaleTransform), die Neigung (SkewTransform) und die Verschiebung (TranslateTransform).

Eine allgemeine, für Formen angewandte Transformation ist die Drehung. Um eine Form zu drehen, erstellen Sie einen RotateTransform-Typ und geben seinen Angle-Wert an. Wenn Sie für Angle den Wert 45 angeben, wird das Element im Uhrzeigersinn um 45 Grad gedreht; ein Winkel von 90 dreht das Element um 90 Grad im Uhrzeigersinn usw. Legen Sie die CenterX-Eigenschaft und die CenterY-Eigenschaft fest, wenn Sie steuern möchten, um welchen Punkt das Element gedreht werden soll. Diese Eigenschaftswerte werden im Koordinatenraum des Elements ausgedrückt, das transformiert wird. CenterX und CenterY sind standardmäßig auf den Wert 0 (null) gesetzt. Wenden Sie abschließend RotateTransform auf das Element an. Wenn sich die Transformation nicht auf das Layout auswirken soll, legen Sie die RenderTransform-Eigenschaft der Form fest.

Im folgenden Beispiel wird RotateTransform verwendet, um eine Form um 45 Grad um ihre obere linke 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 wird eine weitere Form um 45 Grad gedreht; diesmal jedoch um den Punkt (25,50).

<!-- 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 nach der Anwendung der beiden Transformationen angezeigt.

45-Grad-Drehungen mit unterschiedlichen Mittelpunkten

In den vorherigen Beispielen wurde eine einzelne Transformation auf jedes Shape-Objekt angewendet. Um mehrere Transformationen auf eine Form (oder auf ein beliebig anderes Benutzeroberflächenelement) anzuwenden, verwenden Sie eine TransformGroup.

Siehe auch

Konzepte

Optimieren der Leistung: 2D-Grafiken und Bildverarbeitung

Übersicht über das Zeichnen mit Volltonfarben und Farbverläufen

Übersicht über die Geometrie

Exemplarische Vorgehensweise: Erste Schritte mit WPF

Übersicht über Animationen