CAPÍTULO II: Creando objetos Graphics, Pen y Font, y manejando las estructuras Pens y Color.

(GDI+ CON VISUAL BASIC .NET)

 

Fecha: 03/Sep/2005 (28/08/2005)
Autor: Arbis Percy Reyes Paredes 
Email: [email protected]
http://percyreyes.blogspot.com 

 


Joven desarrollador de aplicaciones Web y Servicios Web XML en Visual Basic .NET y Visual C# .NET con bases de datos SQL Server 2000 - 2005.

¡ Los peruanos Sí podemos !

Dada la base introductoria acerca de GDI+(Vea CAPÍTULO I), donde habíamos estudiado conceptos importantes relacionados a GDI+, empezaré a partir de este artículo a profundizar cada uno de los componentes de GDI+ (la tecnología contenida en .NET Frameworks con la que se pueden generar salidas gráficas, textuales y trabajo con mapas de bits e imágenes). Una de las cosas que habíamos mencionado es que toda la funcionalidad de GDI+ está en encapsulada en el assembly System.Drawing.dll. Por otra parte, todas las clases GDI+ classes se encuentran dentro de los namespaces System.Drawing, System.Drawing2D, System.Text, System.Design, System.Imaging, System.PrintingSystem.Internal . Ahora sí, empezemos detallando la clase Graphics.

LA  CLASE GRAPHICS 

Cuando usted se propone a dibujar una línea o cualquier forma manualmente, pues necesitará de un espacio donde hacerlo, como por ejemplo: un trozo de papel, una región de pared, o cualquier superficie de dibujo que esté en condiciones como para representar nuestras imágenes o creaciones. Pues bien, estas ideas llevémoslo a la práctica, es decir, a la parte programática. A ese trozo de papel, región de pared ... se llama lienzo, y en .NET  este lienzo está representado mediante la clase Graphics. Entonces, la clase Graphics viene a ser el lienzo donde expresaremos nuestro arte.

La clase Graphics es la base de la funcionalidad de GDI+, en otras palabras, es la clase que realmente dibuja líneas, curvas, figuras, imágenes y texto. Estas Clases cooperan entre ellas, es decir trabajan en conjunto, pero siempre al mando de nuestra majestad... la clase Graphics. Algo a resaltar acerca del clase Graphics es que éste carece de constructor público, negándonos de esta manera la posibilidad de instanciar un objeto Graphics con la palabra clave New,¿Qué pena verdad? pues no os preucupéis, ya que todo tiene su porqué, como veremos más adelante. Sigamos... Podemos crear nuestro objeto Graphics de diversas maneras, como por ejemplo

'creamos un objeto Graphics en el formulario
Dim myLienzoForm As Graphics = Me.CreateGraphics

'creamos un objeto Graphics en un PictureBox
Dim myLienzoPictureBox As Graphics = PictureBox1.CreateGraphics

 'creamos un objeto Graphics en un control
Dim myLienzoControl As Graphics = Button1.CreateGraphics

Existe otra manera de crear un objeto Graphics, pero tiene que tener en cuenta algunos riesgos al hacerlo, ya que el repintado de la imagen puede verse afectado debido a la complejidad de esta.


Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
    Handles MyBase.Paint

    Dim myGraphics As Graphics = e.Graphics

End Sub

REFERENCIA Vea algo más acerca de la clase Graphics

NOTA: En algún momento deseaba que cuando se cargue el formulario se dibujara un gráfico, para la cual insertaba el código en el evento Load. Cuando corría la aplicación nunca observaba el gráfico dibujado, era claro que algo andaba mal, pues todo era incorrecto.  Ahora entiendo porque no era posible realizarlo. Pues me di cuenta que esto, era debido a que el evento Paint del formulario se levantaba después del evento Load, por eso no podía trabajar este código en este evento Load.  Es decir, el formulario se pintaba sin dibujar el gráfico. Para solucionar este problemilla, opté por escribir el código en el evento Paint del formulario, siempre que quisiese graficar cuando el formulario se cargue. Ejemplo:

Este código no mostrará resultado alguno.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load

    Me.CreateGraphics.DrawLines(New Pen(Color.Blue, 4), New Point() {New Point(34, 56), New Point(74, 93), New Point(56, 12)})

End Sub

Este código dibuja dos segmentos conectados por la matriz de puntos (34,56), (74,93) y (56,12)

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
    Handles MyBase.Paint

    Me.CreateGraphics.DrawLines(New Pen(Color.Blue, 4),    New  Point()
    {New Point(34, 56), New Point(74, 93), New Point(56, 12)})

End Sub

MÉTODOS DE LA CLASE GRAPHICS  Estos son algunos de los métodos de la clase Graphics, las cuales serán ejemplificados más adelante. Las propiedades de esta clase puede revisarlo en la ayuda MSDN Library online de Microsoft.

 DrawArc

Dibuja un archivo que representa una parte de una elipse especificada por un par de coordenadas, un valor de ancho y un valor de alto.

 DrawBezier

Dibuja una curva spline de Bézier definida por cuatro estructuras Point.

 DrawBeziers 

Dibuja una serie de curvas spline de Bézier a partir de una matriz de estructuras Point.

 DrawClosedCurve 

Dibuja una curva spline cardinal cerrada, definida por una matriz de estructuras Point.

 DrawCurve 

Dibuja una curva spline cardinal a través de una matriz especificada de estructuras Point.

 DrawEllipse 

Dibuja una elipse definida por un rectángulo delimitador especificado por un par de coordenadas, un valor de alto y un valor de ancho.

 DrawImage 

Dibuja el objeto Image especificado en la ubicación especificada y con el tamaño original.

 DrawLine 

Dibuja una línea que conecta los dos puntos especificados por los pares de coordenadas.

 DrawLine

Dibuja una serie de segmentos de línea que conectan una matriz de estructuras Point.

 DrawPath 

Dibuja un objeto GraphicsPath.

 DrawPie 

Dibuja una forma circular definida por una elipse y determinada por un par de coordenadas, unos valores de ancho y alto y dos líneas radiales.

 DrawPolygon 

Dibuja un polígono definido por una matriz de estructuras Point.

 DrawRectangle 

Dibuja un rectángulo especificado por un par de coordenadas, un valor de ancho y un valor de alto.

 DrawString 

Dibuja la cadena de texto especificada en la ubicación especificada y con los objetos Brush y Font especificados.

 FillEllipse 

Rellena el interior de una elipse definida por un rectángulo de delimitación especificado por un par de coordenadas, un valor de alto y un valor de ancho.

 FillPath 

Rellena el interior de un objeto GraphicsPath.

 FillPie 

Rellena el interior de una sección de gráfico circular definida por una elipse, determinada por un par de coordenadas, unos valores de ancho y alto y dos líneas radiales.

 FillPolygon 

Rellena el interior de un polígono definido por una matriz de puntos, especificados por estructuras Point.

 FillRectangle 

Rellena el interior de un rectángulo especificado por un par de coordenadas, un valor de ancho y un valor de alto.

 FillRectangles 

Rellena el interior de una serie de rectángulos especificados por estructuras Rectangle.

 FillRegion 

Rellena el interior de un objeto Region.

 MeasureString 

Mide la cadena especificada al dibujarla con el objeto Font especificado.

 MultiplyTransform

Multiplica la transformación universal del objeto Graphics y especificada en el objeto Matrix.

 RotateTransform

Aplica la rotación especificada a la matriz de transformación de este objeto Graphics.

 ScaleTransform

Aplica la operación de cambio de escala especificada a la matriz de transformación de este objeto Graphics, anteponiéndola a esta última.

 TransformPoints

Transforma una matriz de puntos de un espacio de coordenadas a otro utilizando las transformaciones universal y de página actuales de este objeto Graphics.

 TranslateClip

Convierte la región de recorte de este objeto Graphics usando las cantidades especificadas en las direcciones horizontal y vertical.

TranslateTransform

Antepone la conversión especificada a la matriz de transformación de este objeto Graphics.

Ahora, necesitamos saber acerca de la clase Pen, la cual usaremos para dibujar formas.

LA CLASE PEN

La clase Pen nos permite crear objetos para dibujar líneas y curvas, es decir, crear lapiceros para dibujar. A continuación mostraremos cómo crear algunos lapiceros:

' creamos un lapicero de color azul. Por defecto de grosor 1
Dim myLapicero1 As New Pen(Color.Blue)

' Lo anterior es lo mismo que...
Dim myLapicero1 As New Pen(Color.Blue, 1)

' creamos un lapicero de color azul y grosor 10
Dim myLapicero2 As New Pen(Color.Blue, 10)

Creo que explicar acerca de esta clase no tiene mucho sentido. Durante el desarrollo de este artículo se explicarán el uso de algunas propiedades. Mientras tanto, revise algunos métodos de esta clase, las cuales serán ejemplificados más adelante.

Clone

Crea una copia exacta de este objeto Pen.

MultiplyTransform

Multiplica la matriz de transformación de este objeto Pen por la Matrix especificada.

ResetTransform

Restablece la matriz de transformación geométrica de este objeto Pen en identidad.

RotateTransform

Gira la transformación geométrica local el ángulo especificado. Este método antepone la rotación a la transformación.

ScaleTransform

Cambia el tamaño de la transformación geométrica local en los factores especificados. Este método antepone la matriz de escala a la transformación.

SetLineCap

Establece los valores que determinan el estilo de cierre que se utiliza para finalizar las líneas dibujadas con este objeto Pen.

TranslateTransform

Convierte la transformación geométrica local en las dimensiones especificadas. Este método antepone la conversión a la transformación.

Una manera de crear un objeto lapicero sin instanciarlo de la clase Pen, es a través de la enumeración Pens.

Quedando un lapicero de color azul y de grosor 1, que nos servirá como parámetro para dibujar el segmento de línea. Es decir:

Me.CreateGraphics.DrawLine(Pens.Blue, New Point(20, 20), New Point(50, 50))

Lo prometido es deuda. Expliquemos el uso de algunas propiedades de un objeto Pen. Por favor observe detalladamente el estilo de las figuras.

' USO DE PROPIEDADES ' definiendo el estilo del lapicero.
Dim myLapicero2 As New Pen(Color.Blue, 5) 'de grosor 5
myLapicero2.StartCap = Drawing2D.LineCap.RoundAnchor 'extremo redondeado
myLapicero2.EndCap = Drawing2D.LineCap.ArrowAnchor 'extremo de forma flecha
myLapicero2.DashStyle = Drawing2D.DashStyle.DashDotDot 'línea-punto-punto
myLapicero2.DashOffset = 5 'distancia para empezar a dibujar desde el inicio

' dibuja una línea con este Pen myLapicero2
Me.CreateGraphics.DrawLine(myLapicero2, New Point(80, 100), New Point(100, 200))


            
' dibuja un rectángulo con este Pen myLapicero2
Me.CreateGraphics.DrawRectangle(myLapicero2, New Rectangle(New Point(50, 60), New Size(200, 200)))

También podemos crear objetos Pen personalizándolos de la siguiente manera

'definimos el estilo para nuestro lapicero
myLapicero.DashPattern = New Single() {6, 8, 4, 5, 17, 2, 9, 10}
'dibujamos una línea
Me.CreateGraphics.DrawLine(myLapicero, New Point(50, 50), New Point(300, 300))

Creo que la siguiente imagen explica claramente la funcionalidad de este estilo.

 

LA ESTRUCTURA COLOR

En la  escuela me enseñaron que los colores se componen de  rojo, verde y azul, pero no me indicaron que estos colores pueden tener grados de transparencia. Entonces un color está definido por cuatros parámetros, tres de estos definen el color  y el otro parámetro (opcional) define la transparencia (0 indica transparencia total  y 255 opacidad total). Todos estos parámetros varían en un rango de 0-255. Por ejemplo la combinación (255, 255, 255) es el color blanco, (0, 0, 255) es el color azul , mientras la combinación (0, 0, 0) define el color negro. Vayamos familiarizándonos con los métodos de este tipo.

Equals Comprueba si el objeto especificado es una estructura Color y si equivale a esta estructura Color.
FromArgb Crea una estructura Color a partir de los cuatro valores de los componentes ARGB de 8 bits (alfa, rojo, verde y azul).
FromKnownColor Crea una estructura Color a partir del color predefinido especificado.
FromName Crea una estructura Color a partir del nombre especificado de un color predefinido.
GetHashCode Devuelve un código hash para esta estructura Color.
GetHue Obtiene el valor de matiz HSB (brillo de saturación de matiz), en grados, de esta estructura Color.
ToArgb Obtiene el valor ARGB de 32 bits de esta estructura Color.
ToKnownColor Obtiene el valor KnownColor de esta estructura Color.

La manera de usarla se muestra a continuación, con este ejemplillo.

Pues quedando de la siguiente manera:

Me.CreateGraphics.DrawLines(New Pen(Color.FromArgb(100, 200, 0, 200)), New Point() _
{New Point(34, 56), New Point(74, 93), New Point(56, 12)})

A continuación ejemplifico la manera de usar algunos de los métodos mencionados anteriormente para este tipo.

' CREANDO UN LAPICERO DE DIVERSAS MANERAS
' =======================================

' creamos un lapicero de combinación:
' Rojo=83 ,Verde=29 ,Azul=2
' y con transparencia 200
Dim myLapicero As New Pen(Color.FromArgb(200, 83, 29, 2))
Me.CreateGraphics.DrawRectangle(myLapicero, New Rectangle(New Point(40, 50), New Size(200, 200)))

'creamos un lapicero de color Peru
Dim myLapicero1 As New Pen(Color.FromName("Peru"))
Me.CreateGraphics.DrawRectangle(myLapicero1, New Rectangle(New Point(50, 60), New Size(200, 200)))

'creamos un lapicero de un color predefinido por el sistema,
'en este caso el color es Coral.
Dim myLapicero2 As New Pen(Color.FromKnownColor(KnownColor.Coral))
Me.CreateGraphics.DrawRectangle(myLapicero2, New Rectangle(New Point(60, 70), New Size(200, 200)))

' creamos un lapicero definiendo el color de acuerdo al número asociado -65536 (número que define el color rojo)
Dim myLapicero3 As New Pen(Color.FromArgb(-65536))
' dibujamos un  línea de color rojo
Me.TextBox1.CreateGraphics.DrawLine(myLapicero3, New Point(70, 80), New Point(60, 90))

' AHORA RECUPERAMOS LOS NÚMEROS ASOCIADOS A UN COLOR
' ===================================================

' POR EJEMPLO:

' recuperamos el número ARGB de 32 bits asociado al color Red
' este número debe ser igual a -65536, usado más arriba..
Me.TextBox2.Text = Color.Red.ToArgb.ToString

' devuelve un número asociado al nivel de transparencia (parámetro alfha) para el color Green
Me.TextBox3.Text = Color.Green.A.ToString

' devuelve un número asociado al nivel de color azul (Blue) para el color Green
Me.TextBox4.Text = Color.Green.B.ToString



' EJEMPLIFICANDO EL USO DEL MÉTODO Equals()
Dim myColor AsColor = Color.Blue

' Comprueba si el objeto especificado es una estructura Color y si equivale a esta estructura Color.
If myColor.Equals(Color.Red) Then
    Me.TextBox5.Text = "el objeto es una estructura Color y es de color Rojo." 'no
Else
    Me.TextBox6.Text = "el objeto es una estructura Color pero no es de color Rojo." 'sí
End If

' devolviendo el código hash para este color.
Me .TextBox7.Text = myColor.GetHashCode.ToString

LA CLASE FONT

La clase Font define un formato particular para el texto, tanto como el nombre de la fuente, tamaño, y los atributos de estilo. La clase Font expone muchos constructores que nos permitirán instanciarla de diversas maneras, obteniendo así objetos Font con diferentes estilos. Diríjase a la Ayuda Online MSDN de Microsoft para consultar al respecto. Ahora revisemos cuestiones relacionadas a esta clase que serán útiles para definir nuestros estilos de fuente.

Empezando nos encontramos con la enumeración FontStyle cuyos miembros son:

Bold Texto en negrita.
Italic Texto en cursiva.
Regular Texto de forma normal.
Strikeout Texto con una línea horizontal de tachado.
Underline Texto subrayado.

Un ejemplo aclarará esto.

Dim myFont As New Font("Arial", 25, FontStyle.Underline)
Me.TextBox1.CreateGraphics.DrawString("Hola Clase Font", myFont, Brushes.Brown, 40, 40)

El siguiente cuadro muestra las propiedades más comunes de esta clase.

FontFamily Obtiene el objeto FontFamily asociado a este objeto Font.
Name Obtiene el nombre del tipo de letra de este objeto Font.
Height Obtiene el interlineado de esta fuente.
Bold Texto en negrita.
Italic Texto en cursiva.
Regular Texto de forma normal.
Strikeout Texto con una línea horizontal de tachado.
Underline Texto subrayado.
Style Obtiene la información de estilo de este objeto Font
Size Obtiene el tamaño de este objeto Font expresado en la unidad de este objeto Font.
SizeInPoints Obtiene el tamaño de este objeto Font, expresado en puntos.
Unit Obtiene la unidad de medida de este objeto Font.

Esta es otra manera de crear un objeto Font.

Quedando:

' observe los parámetros que manejamos para definir nuestra fuente.
Dim myFont As New Font("Verdana", 12, FontStyle.Italic, GraphicsUnit.Millimeter, 0)
Me.TextBox1.CreateGraphics.DrawString("Por ti sigo, por ti", myFont, Brushes.DarkOrange, 40, 40)

OTRO EJEMPLO El siguiente ejemplo ilustra el uso de FontFamiliy y la familia de colores del sistema, como también el uso de otros métodos explicados anteriormente.

Revise el código fuente.

Private Sub TrackBar1_ValueChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles track.ValueChanged

    Dim myFont As Font = New Font(myFontname, track.Value, FontStyle.Regular)
    Me.TxtMuestra.Font = myFont
    Me.LabelSize.Text = Me.track.Value
    Me.LabelSize.AutoSize = True

End Sub

Private Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load

    Me.track.Value = 10

    Dim myColor As System.Drawing.Color

    For Each myColor In System.ComponentModel.TypeDescriptor. _
        GetConverter(GetType(Color)).GetStandardValues()
            Me.lstFamilyColors.Items.Add(myColor.ToKnownColor)
        Next

        Dim myFontFamily As FontFamily

        For Each myFontFamily In FontFamily.Families
            Me.lstFamilyFonts.Items.Add(myFontFamily.Name.ToString)
        Next

    End Sub

    Public myColor As Color
    Public myFontname As String = "Arial"

    Private Sub lstFamilyColors_SelectedIndexChanged(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles lstFamilyColors.SelectedIndexChanged

        ' la propiedad ForeColor tan sólo admite colores definidos por el sistema.
        ' es debido a esto que usamos el método FromKnownColor para definir el color
        myColor = Color.FromKnownColor(Me.lstFamilyColors.SelectedItem)
        ' INCORRECTO: myColor = Color.FromName(Me.lstFamilyColors.SelectedItem)
        Me.TxtMuestra.ForeColor = myColor
    End Sub

    Private Sub lstFamilyFonts_SelectedIndexChanged(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles lstFamilyFonts.SelectedIndexChanged

        '  Me.Label1.Text = myFontFamily.GetName(10)
        Dim myFontName As String = Me.lstFamilyFonts.SelectedItem
        Me.TxtMuestra.Font = New Font(myFontName, track.Value, FontStyle.Regular, GraphicsUnit.Pixel)
    End Sub

End Class

Como se dará cuenta, tan sólo he detallado la manera de crear objetos Graphics, Pen y Font y manejar las estructuras Pens y Color. En los próximos capítulos haremos uso de estos objetos para dibujar objetos más complejos. 

Esto ha sido todo para este CAPITULO II. Nos vemos en el siguiente CAPÍTULO.

Por favor, califica este artículo en PanoramaBox, pues así me animarás a continuar colaborando contigo.

Web Developer Percy Reyes                ®Todos los Derechos Reservados

Saludos desde Trujillo - Perú.


ir al índice