Información general sobre formas y dibujo básico en WPF

Este tema proporciona información general sobre cómo dibujar con objetos Shape. Un Shape es un tipo de UIElement que le permite dibujar una forma en la pantalla. Como se trata de elementos de la interfaz de usuario, los objetos Shape se pueden usar dentro de los elementos Panel y la mayoría de los controles.

Windows Presentation Foundation (WPF) ofrece varias capas de acceso a gráficos y servicios de representación. En la capa superior los objetos Shape son fáciles de usar y proporcionan varias características útiles, como el diseño y la participación en el sistema de eventos de Windows Presentation Foundation (WPF).

Objetos Shape

WPF proporciona un número de objetos Shape listos para usar. Todos los objetos de forma heredan de la clase Shape. Los objetos de forma disponibles incluyen Ellipse, Line, Path, Polygon, Polyline y Rectangle. Los objetos Shape comparten las siguientes propiedades comunes.

  • Stroke: describe cómo se pinta el contorno de la forma.

  • StrokeThickness: describe el espesor del contorno de la forma.

  • Fill: describe cómo se pinta el interior de la forma.

  • Propiedades de datos para especificar coordenadas y vértices, medidos en píxeles independientes del dispositivo.

Dado que derivan de UIElement, los objetos de forma pueden utilizarse en los paneles y en la mayoría de los controles. El panel Canvas es una opción particularmente apropiada para crear dibujos complejos, porque admite la posición absoluta de sus objetos secundarios.

La clase Line le permite dibujar una línea entre dos puntos. En el ejemplo siguiente se muestran varias maneras de especificar coordenadas de línea y propiedades de trazo.

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

La siguiente imagen muestra el Line representado.

Ilustración de línea

Aunque la clase Line proporciona una propiedad Fill, configurarla no produce ningún efecto, porque un Line no tiene área.

Otra forma frecuente es el Ellipse. Cree un Ellipse mediante la definición de las propiedades de la forma Width y Height. Para dibujar un círculo, especifique un Ellipse cuyos valores Width y Height sean iguales.

<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

En la imagen siguiente se muestra un ejemplo de un Ellipse representado.

Ilustración de elipse

Utilizar trazados y geometrías

La clase Path le permite dibujar curvas y formas complejas. Estas curvas y formas se describen mediante los objetos Geometry. Para usar un Path, cree un Geometry y úselo para establecer la propiedad Path del objeto Data.

Hay una variedad de objetos Geometry entre los que puede elegir. Las clases LineGeometry, RectangleGeometry y EllipseGeometry describen formas relativamente sencillas. Para crear formas más complejas o crear curvas, use un PathGeometry.

PathGeometry y PathSegments

Los objetos PathGeometry constan de uno o más objetos PathFigure; cada PathFigure representa una «figura» o forma diferente. Cada PathFigure consta, él mismo, de uno o más objetos PathSegment, cada uno de los cuales representa una porción conectada de la figura o forma. En los tipos de segmentos se incluyen los siguientes: LineSegment, BezierSegment y ArcSegment.

En el ejemplo siguiente se usa un Path para dibujar una curva de Bézier cuadrática.

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

La siguiente imagen muestra la forma representada.

Ilustración de trazado

Para más información sobre PathGeometry y otras clases Geometry, consulte Información general sobre geometría.

Sintaxis abreviada de XAML

En lenguaje XAML también se puede usar una sintaxis abreviada especial para describir un Path. En el ejemplo siguiente, se utiliza la sintaxis abreviada para dibujar una forma compleja.

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

La siguiente imagen muestra un Path representado.

Ilustración de segundo trazado

La cadena de atributo Data empieza con el comando «MoveTo», indicado por M, que establece un punto de inicio para la trayectoria en el sistema de coordenadas del Canvas. Los parámetros de datos Path distinguen entre mayúsculas y minúsculas. La letra M mayúscula indica una ubicación absoluta para el nuevo punto activo. Una m minúscula indica coordenadas relativas. El primer segmento es una curva de Bézier cúbica que comienza en (100,200) y termina en (400,175), trazado con los dos puntos de control (100,25) y (400,350). Este segmento se indica con el comando C de la cadena de atributo Data. De nuevo, la C mayúscula indica una ruta de acceso absoluta; la c minúscula indicaría una ruta de acceso relativa.

El segundo segmento comienza con un comando H "lineto" horizontal absoluto, que especifica una línea trazada desde el punto de conexión del subtrazado anterior (400,175) hasta un nuevo punto de conexión (280,175). Dado que es un comando «LineTo» horizontal, el valor especificado es una coordenada x.

Para conocer la sintaxis de trazado completa, consulte la referencia Data y Crear una forma mediante un PathGeometry.

Pintar formas

Los objetos Brush se usan para pintar las formas Stroke y Fill. En el ejemplo siguiente se especifican el trazo y el relleno de un Ellipse. Tenga en cuenta que una entrada válida para las propiedades del pincel puede ser una palabra clave o el valor de color en formato hexadecimal. Para obtener más información sobre las palabras clave disponibles para el color, consulte las propiedades de la clase Colors en el espacio de nombres System.Windows.Media.

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

La siguiente imagen muestra el Ellipse representado.

Una elipse

Como alternativa, puede utilizar la sintaxis del elemento de propiedad para crear explícitamente un objeto SolidColorBrush para pintar la forma con un color sólido.

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

En la ilustración siguiente se muestra la forma representada.

Ilustración de SolidColorBrush

También puede pintar el trazo o relleno de una forma con degradados, imágenes, patrones y mucho más. Para más información, consulte Información general sobre el dibujo con colores sólidos y degradados.

Formas extensibles

Las clases Line, Path, Polygon, Polyline y Rectangle tienen, todas, una propiedad Stretch. Esta propiedad determina cómo se estira el contenido de un objeto Shape (la forma que se va a dibujar), para rellenar el espacio de diseño del objeto Shape. El espacio de diseño de un objeto Shape es la cantidad de espacio que el sistema de diseño asigna a Shape, o bien por unos valores Width y Height explícitos, o bien por las configuraciones de HorizontalAlignment y VerticalAlignment. Para obtener información adicional sobre el diseño en Windows Presentation Foundation, consulte la información general sobre el Diseño.

La propiedad Stretch puede tener uno de los siguientes valores:

  • None: el contenido del objeto Shape no se estira.

  • Fill: el contenido del objeto Shape se estira para rellenar su espacio de diseño. No se mantiene la relación de aspecto.

  • Uniform: el contenido del objeto Shape se estira todo lo posible para rellenar el espacio de diseño al tiempo que conserva su relación de aspecto original.

  • UniformToFill: el contenido del objeto Shape se ajusta para rellenar totalmente el espacio de diseño al tiempo que conserva su relación de aspecto original.

Observe que cuando el contenido de un objeto Shape se estira, el contorno del objeto Shape se pinta después del estiramiento.

En el ejemplo siguiente, se usa un Polygon para dibujar un triángulo muy pequeño de (0,0) a (0,1) a (1,1). El Width y el Height del objeto Polygon se establecen en 100 y su propiedad de estiramiento se establece en Rellenar. Como resultado, el contenido del objeto Polygon (el triángulo) se estira para rellenar el espacio mayor.

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

Transformar formas

La clase Transform proporciona los medios para transformar formas en un plano bidimensional. Los diferentes tipos de transformación incluyen rotación (RotateTransform), escalado (ScaleTransform), sesgado (SkewTransform) y traslación (TranslateTransform).

Una transformación común para aplicar a una forma es la rotación. Para girar una forma, cree un RotateTransform y especifique su Angle. Un Angle de 45 gira el elemento 45 grados en el sentido de las agujas del reloj; un ángulo de 90 gira el elemento 90 grados en el sentido de las agujas del reloj; y así sucesivamente. Establezca las propiedades CenterX y CenterY si quiere controlar el punto alrededor del cual gira el elemento. Estos valores de propiedad se expresan en el espacio de coordenadas del elemento que se va a transformar. CenterX y CenterY tienen valores predeterminados de cero. Finalmente, aplique el RotateTransform al elemento. Si no quiere que la transformación afecte al diseño, establezca la propiedad RenderTransform de la forma.

En el ejemplo siguiente se utiliza un RotateTransform para girar una forma 45 grados alrededor de la esquina superior izquierda de la forma (0,0).

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

En el ejemplo siguiente, otra forma se gira 45 grados, pero esta vez se gira alrededor del punto (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>

En la ilustración siguiente se muestran los resultados de aplicar las dos transformaciones.

Rotaciones de 45 grados con diferentes puntos centrales

En los ejemplos anteriores, se aplicó una única transformación a cada objeto de forma. Para aplicar varias transformaciones a una forma (o cualquier otro elemento de la interfaz de usuario), utilice un TransformGroup.

Consulte también