Compartilhar via


Formas e Desenho Básico no WPF: uma Visão Geral

Este tópico fornece uma visão geral de como desenhar com Shape objetos. Um Shape é um tipo de UIElement que permite que você desenhe uma forma na tela. Como são elementos da interface do usuário, objetos Shape podem ser usados dentro de elementos Panel e na maioria dos controles.

O Windows Presentation Foundation (WPF) oferece várias camadas de acesso a elementos gráficos e serviços de renderização. Na camada superior, Shape os objetos são fáceis de usar e fornecem muitos recursos úteis, como layout e participação no sistema de eventos WPF (Windows Presentation Foundation).

Os tipos relacionados à forma estão no Windows.Shapes namespace. Tipos relacionados à geometria estão no System.Windows.Media namespace.

Objetos de Forma

O WPF fornece vários objetos prontos para uso Shape . Todos os objetos de forma herdam da Shape classe. Os objetos de forma disponíveis incluem Ellipse, Line, Path, , Polygon, Polylinee Rectangle. Shape os objetos compartilham as propriedades comuns a seguir.

  • Stroke: descreve como o contorno da forma é pintado.

  • StrokeThickness: Descreve a espessura do contorno da forma.

  • Fill: descreve como o interior da forma é pintado.

  • Propriedades de dados para especificar coordenadas e vértices, medidas em pixels independentes do dispositivo.

Como os objetos de forma derivam de UIElement, eles podem ser usados dentro de painéis e na maioria dos controles. O Canvas painel é uma opção particularmente boa para criar desenhos complexos porque dá suporte ao posicionamento absoluto de seus objetos filho.

A Line classe permite que você desenhe uma linha entre dois pontos. O exemplo a seguir mostra várias maneiras de especificar coordenadas de linha e propriedades de traço.

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

A imagem a seguir mostra o elemento renderizado Line.

Ilustração de linha

Embora a classe Line forneça uma propriedade Fill, defini-la não tem efeito porque um Line não possui área.

Outra forma comum é a Ellipse. Crie um Ellipse definindo as propriedades Width e Height da forma. Para desenhar um círculo, especifique um Ellipse cujo Width e Height os valores são iguais.

<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

A imagem abaixo mostra um exemplo de renderização de Ellipse.

Ilustração de elipse

Usando caminhos e geometrias

A Path classe permite desenhar curvas e formas complexas. Essas curvas e formas são descritas usando Geometry objetos. Para usar um Path, crie um Geometry e use-o para definir a Path propriedade do Data objeto.

Há uma variedade de Geometry objetos para escolher. As classes LineGeometry, RectangleGeometry e EllipseGeometry descrevem formas relativamente simples. Para criar formas mais complexas ou criar curvas, use um PathGeometry.

Geometria de Caminho e Segmentos de Caminho

PathGeometry os objetos são compostos por um ou mais PathFigure objetos; cada PathFigure um representa uma "figura" ou forma diferente. Cada PathFigure é composto por um ou mais objetos do tipo PathSegment, cada um representando uma parte conectada da figura ou forma. Os tipos de segmento incluem o seguinte: LineSegment, BezierSegmente ArcSegment.

No exemplo a seguir, um Path é usado para desenhar uma curva quadrática de Bezier.

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

A imagem a seguir mostra a forma renderizada.

Ilustração de caminho

Para obter mais informações sobre PathGeometry e as outras Geometry classes, consulte a Visão Geral de Geometria.

Sintaxe abreviada de XAML

Em XAML (Extensible Application Markup Language), você também pode usar uma sintaxe abreviada especial para descrever um Path. No exemplo a seguir, a sintaxe abreviada é usada para desenhar uma forma complexa.

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

A imagem a seguir mostra uma imagem renderizada Path.

Uma segunda ilustração de caminho.

A Data cadeia de caracteres de atributo começa com o comando "moveto", indicado por M, que estabelece um ponto inicial para o caminho no sistema de coordenadas do Canvas. Path os parâmetros de dados são sensíveis a maiúsculas e minúsculas. O M maiúsculo indica uma posição absoluta para o novo ponto. Um m minúsculo indicaria coordenadas relativas. O primeiro segmento é uma curva de Bezier cúbica começando em (100.200) e terminando em (400.175), desenhada usando os dois pontos de controle (100,25) e (400.350). Esse segmento é indicado pelo comando C na cadeia de caracteres do atributo Data. Novamente, o C maiúscula indica um caminho absoluto; o c minúsculo indicaria um caminho relativo.

O segundo segmento começa com um comando "lineto" horizontal absoluto H, que especifica uma linha desenhada do ponto de extremidade do subcaminho anterior (400.175) para um novo ponto de extremidade (280.175). Como é um comando "lineto" horizontal, o valor especificado é uma coordenada x.

Para obter a sintaxe completa do caminho, consulte a Data referência e Crie uma Forma usando um PathGeometry.

Pintando formas

Brush os objetos são usados para pintar uma forma Stroke e Fill. No exemplo a seguir, o traço e o preenchimento de um Ellipse são especificados. Observe que a entrada válida para propriedades de pincel pode ser uma palavra-chave ou um valor de cor hexadecimal. Para obter mais informações sobre palavras-chave de cores disponíveis, consulte as Colors propriedades da classe no 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>

A imagem a seguir mostra o elemento renderizado Ellipse.

elipseUma

Como alternativa, você pode usar a sintaxe do elemento de propriedade para criar explicitamente um SolidColorBrush objeto para pintar a forma com uma cor sólida.

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

A ilustração a seguir mostra a forma renderizada.

Ilustração do SolidColorBrush

Você também pode pintar o contorno ou o preenchimento de uma forma com gradientes, imagens, padrões e muito mais. Para obter mais informações, consulte a Visão geral da Pintura com Cores Sólidas e Gradientes.

Formas elásticas

As Line, Path, Polygon, Polyline e Rectangle classes todas têm uma propriedade Stretch. Essa propriedade determina como o conteúdo de um Shape objeto (a forma a ser desenhada) é estendido para preencher o Shape espaço de layout do objeto. O espaço de layout de um objeto Shape é a quantidade de espaço Shape alocada pelo sistema de layout, devido a uma configuração Width e Height explícitas ou por causa das configurações HorizontalAlignment e VerticalAlignment. Para obter informações adicionais sobre o layout no Windows Presentation Foundation, consulte a visão geral do Layout .

A propriedade Stretch usa um dos seguintes valores:

  • None: O conteúdo do objeto Shape não está expandido.

  • Fill: o Shape conteúdo do objeto é estendido para preencher seu espaço de layout. A proporção não é preservada.

  • Uniform: O conteúdo do objeto Shape é estendido o máximo possível para preencher seu espaço de layout, preservando sua proporção original.

  • UniformToFill: o conteúdo do Shape objeto é estendido para preencher completamente seu espaço de layout, preservando sua proporção original.

Observe que, quando o conteúdo de um Shape objeto é estendido, o contorno do Shape objeto é pintado após o estiramento.

No exemplo a seguir, um Polygon é usado para desenhar um triângulo muito pequeno de (0,0) para (0,1) para (1,1). O Polygon objeto Width e Height são definidos como 100, e sua propriedade stretch é definida como Fill. Como resultado, o Polygon conteúdo do objeto (o triângulo) é estendido para preencher o espaço maior.

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

Transformando formas

A Transform classe fornece os meios para transformar formas em um plano bidimensional. Os diferentes tipos de transformação incluem rotação (RotateTransform), escala (ScaleTransform), distorção (SkewTransform) e tradução (TranslateTransform).

Uma transformação comum a ser aplicada a uma forma é uma rotação. Para girar uma forma, crie um RotateTransform e especifique o seu Angle. Um Angle de 45 gira o elemento 45 graus no sentido horário; um ângulo de 90 gira o elemento 90 graus no sentido horário; e assim por diante. Defina as CenterX propriedades e CenterY se você quiser controlar o ponto sobre o qual o elemento é girado. Esses valores de propriedade são expressos no espaço de coordenadas do elemento que está sendo transformado. CenterX e CenterY ter valores padrão de zero. Por fim, aplique o RotateTransform ao elemento. Se você não quiser que a transformação afete o layout, defina a propriedade da RenderTransform forma.

No exemplo a seguir, um RotateTransform é usado para girar uma forma de 45 graus sobre o canto superior esquerdo da 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>

No exemplo seguinte, outra forma é girada 45 graus, mas desta vez é girada em torno do ponto (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>

A ilustração a seguir mostra os resultados da aplicação das duas transformações.

Rotações de 45 graus com diferentes pontos centrais

Nos exemplos anteriores, uma única transformação foi aplicada a cada objeto de forma. Para aplicar várias transformações a uma forma (ou a qualquer outro elemento de interface do usuário), use um TransformGroup.

Consulte também