Clase para generar efectos de transición entre imágenes con GDI+
Fecha: 13/Dic/2004 (12/Dic/04)
|
Programa en Ejecución
Este proyecto muestra como realizar 55 diferentes efectos de transición (movimiento) entre imágenes con GDI+.
Para eso vamos a crear una clase de nombre "EfectosTrans" la cual recibirá en su constructor un control que será
donde se dibujarán los efectos, y una propiedad de tipo "Image" de dicho control donde pondremos una imagen vacía sobre la cual se va a dibujar una imagen mediante un efecto que también hay que pasarle a la clase.
A continuación pongo el código completo de la clase EfectosTrans y del código de ejemplo (también pueden descargar la clase junto al proyecto de ejemplo siguiendo el link que está al final de la página).
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.ComponentModel
Friend Class EfectosTrans
Implements IDisposable
'Evento EffectEnded: se dispara al finalizar un efecto
Public Event EffectEnded As EventHandler
#Region " Enumeraciones "
'Enumeración de Efectos
Public Enum Efectos
Abanico_Derecha = 0
Abanico_Izquierda
Aparecer
Barras_Horizontales
Barras_Verticales
Barrido_Horizontal
Barrido_Vertical
Circulos_Dentro
Circulos_Fuera
Desplegar_Centro
Desplegar_ID
Desplegar_II
Desplegar_SD
Desplegar_SI
Diagonal
DivisiónH_Entrante
DivisiónH_Saliente
DivisiónV_Entrante
DivisiónV_Saliente
Empuja_División_Lados
Empuja_División_Topes
Empujar_Abajo
Empujar_Arriba
Empujar_Derecha
Empujar_Diagonal_ID
Empujar_Diagonal_II
Empujar_Diagonal_SD
Empujar_Diagonal_SI
Empujar_Izquierda
Estirar_Centro
Estirar_ID
Estirar_II
Estirar_SD
Estirar_SI
Girar_Centro
Girar_Espiral_Abajo
Girar_Espiral_Arriba
PersianasH_Abajo
PersianasH_Arriba
PersianasV_Derecha
PersianasV_Izquierda
Reloj
Reloj_AntiHorario
Rodar_DAbajo
Rodar_DArriba
Rodar_IAbajo
Rodar_IArriba
Rueda_2Ejes
Rueda_3Ejes
Rueda_4Ejes
Rueda_8Ejes
Simetrico_Adentro
Simetrico_Afuera
Simetrico_Derecha
Simetrico_Izquierda
End Enum
#End Region
#Region " Miembros Privados "
'Velocidad a la que se dibujará el efecto
Private _Velocidad As Integer = 20
'Contiene el efecto actual
Private _Efecto As Efectos = Efectos.Abanico_Derecha
'Control donde se mostrarán los efectos
Private _Contenedor As Control
'Propiedad de _Contenedor donde se colocará una imagen para realizar los efectos
Private _Propiedad As Reflection.PropertyInfo
'Color que se usará para rellenar el fondo de la imagen
Private _Color As Color = Color.Transparent
'Control Timer que controlará la ejecución de los efectos
Private _Tiempo As Timer
'Cuenta las veces que se debe ejecutar el evento Tick para cada efecto
Private _Contador As Integer = 0
'Contiene una copia de la imagén pasada a uno de los constructores para realizar los efectos
Private _bmpTextura As Image
'Contiene una copia vacia de _bmpTextura donde se dibujará el efecto
Private _bmpDibujar As Image
'Creamos un objeto _Graphics para dibujar en _bmpDibujar
Private _Gr As Graphics
'Creamos un TextureBrush con la textura de la imágen _bmpTextura
Private _Brocha As TextureBrush
'Contienen el Ancho y Alto de _bmpTextura respectivamente
Private _AnchoImagen, _AltoImagen As Single
'Indica si actualmente hay un efecto ejecutandose
Private blnEfectoEjecutandose As Boolean = False
Private disposed As Boolean = False
#Region " Variables especificas de algunos efectos "
'Ángulo de giro
Private _AnguloGiro As Single
'Cantidad en que se aumentan las transformaciones de ejes.
Private _xAumentaPos, _yAumentaPos As Single
'_Aumento progresivo de los dibujos
Private _Aumento As Single
#End Region
#End Region
#Region " Métodos Publicos "
'Constructor
Public Sub New(ByVal RutaImagen As String, ByVal Contenedor As Control, ByVal strPropiedad As String, Optional ByVal intVelocidad As Integer = 20)
Try
_bmpTextura = Image.FromFile(RutaImagen)
Iniciar(Contenedor, intVelocidad, strPropiedad)
Catch ex As Exception When Not IO.Directory.Exists(RutaImagen)
MessageBox.Show("La ruta de la imagen no es válida")
Catch ex As Exception When _bmpTextura Is Nothing
MessageBox.Show("La imagen no puede ser nula.")
End Try
End Sub
'Constructor
Public Sub New(ByVal Imagen As Image, ByVal Contenedor As Control, ByVal strPropiedad As String, Optional ByVal intVelocidad As Integer = 20)
Try
_bmpTextura = Imagen
Iniciar(Contenedor, intVelocidad, strPropiedad)
Catch ex As Exception When _bmpTextura Is Nothing
MessageBox.Show("La imagen no puede ser nula.")
End Try
End Sub
'Ejecuta el efecto en la propiedad "EfectosTrans.EfectoActual"
Public Overloads Sub Start()
If Not disposed Then
'Iniciamos los objetos de dibujo y el Timer
EstableceObjetos()
Else
Throw New ObjectDisposedException("", "Esta instancia de la clase EfectosTrans ha sido desechada previamente y por lo tanto, ya no es accesible.")
End If
End Sub
'Ejecuta el efecto pasado en eEfecto
Public Overloads Sub Start(ByVal eEfecto As Efectos)
If Not disposed Then
_Efecto = eEfecto
'Iniciamos los objetos de dibujo y el Timer
EstableceObjetos()
Else
Throw New ObjectDisposedException("", "Esta instancia de la clase EfectosTrans ha sido desechada previamente y por lo tanto, ya no es accesible.")
End If
End Sub
#End Region
#Region " Propiedades "
'EfectoActual
<DefaultValue(GetType(Efectos), "Abanico_Derecha"), _
Category("Comportamiento"), _
Description("Establece el efecto actual para este objeto.")> _
Public Property EfectoActual() As Efectos
Get
Return _Efecto
End Get
Set(ByVal Value As Efectos)
'Si no se esta ejecutando un efecto en este momento cambiamos el efecto
If Not Me.blnEfectoEjecutandose Then
_Efecto = Value
End If
End Set
End Property
'VelocidadEfecto
<DefaultValue(GetType(Integer), "20"), _
Category("Comportamiento"), _
Description("Establece la velocidad de dibujado para este objeto.")> _
Public Property VelocidadEfecto() As Integer
Get
Return _Velocidad
End Get
Set(ByVal Value As Integer)
_Velocidad = ValidaVelocidad(Value)
End Set
End Property
'ColorTrans
<DefaultValue(GetType(Color), "Transparent"), _
Category("Apariencia"), _
Description("Establece el color de relleno para este objeto.")> _
Public Property ColorTrans() As Color
Get
Return _Color
End Get
Set(ByVal Value As Color)
_Color = Value
End Set
End Property
'Image
<Category("Apariencia"), _
Description("Establece la imagen que se usará para realizar el efecto seleccionado.")> _
Public Property Image() As Image
Get
Return _bmpTextura
End Get
Set(ByVal Value As Image)
Try
_bmpTextura = Value
_AnchoImagen = _bmpTextura.Width
_AltoImagen = _bmpTextura.Height
'Hay imagenes que tienen un formato de pixel
'que no permite crear un objeto Graphics para dibujar sobre
'ellas, por eso creamos una copia de la imagen, del mismo tamaño
'y con un formato de pixel que no de problemas
_bmpDibujar = New Bitmap(CInt(_AnchoImagen), CInt(_AltoImagen), PixelFormat.Format32bppArgb)
Catch ex As Exception When Value Is Nothing
Throw New NullReferenceException("La imagen no puede ser nula.")
End Try
End Set
End Property
#End Region
#Region " Destructores "
Public Overloads Sub Dispose() Implements System.IDisposable.Dispose
Dispose(True)
End Sub
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposed Then
If disposing Then
'Acá, limpiamos recursos administrados de esta clase
'En este caso no hay ningúno (que no haya sido descargado)
End If
'Acá, limpiamos recursos no administrados de esta clase
If Not _bmpTextura Is Nothing Then
_bmpTextura.Dispose()
End If
_bmpDibujar.Dispose()
Me.disposed = True
End If
End Sub
' Este metodo Finalize se ejecutará (automaticamente) solamente
' si el metodo Dispose no es usado por el usuario.
Protected Overrides Sub Finalize()
'Limpiamos solamente los recursos no manejados pasando False
Dispose(False)
End Sub
#End Region
#Region " Métodos Privados "
'Establecemos las variables de nivel de modulo
Private Sub Iniciar(ByVal Contenedor As Control, ByVal intVelocidad As Integer, _
ByVal strPropiedad As String)
_Contenedor = Contenedor
_Velocidad = ValidaVelocidad(intVelocidad)
_AnchoImagen = _bmpTextura.Width
_AltoImagen = _bmpTextura.Height
'Hay imagenes que tienen un formato de pixel
'que no permite crear un objeto Graphics para dibujar sobre
'ellas, por eso creamos una copia de la imagen, del mismo tamaño
'y con un formato de pixel que no de problemas
_bmpDibujar = New Bitmap(CInt(_AnchoImagen), CInt(_AltoImagen), PixelFormat.Format32bppArgb)
'Obtenemos y utilizamos la propiedad de tipo Image a partir de strPropiedad
ObtenerPropiedad(strPropiedad)
_Tiempo = New Timer
_Tiempo.Interval = 70
'Controlador del evento Tick del objeto Timer
AddHandler _Tiempo.Tick, AddressOf TiempoTick
End Sub
'El siguiente código me fue proporcionado por Eduardo A. Morcillo [MS MVP VB]
Private Sub ObtenerPropiedad(ByVal strPropiedad As String)
' Obtengo el tipo de control
Dim t As Type = _Contenedor.GetType
' Obtengo la propiedad
_Propiedad = t.GetProperty(strPropiedad)
' Verifico que se devolvio la propiedad
If _Propiedad Is Nothing Then
Throw New ArgumentException("El control no posee la propiedad")
End If
' Verifico que la propiedad devuelva
' el tipo Image o una subclase de el
If Not GetType(Drawing.Image).IsAssignableFrom(_Propiedad.PropertyType) Then
Throw New ArgumentException("La propiedad no es de tipo Image")
End If
End Sub
'(Re)Establece objetos y variables globales a su estado original antes de ejecutar un efecto
Private Sub EstableceObjetos()
Try
'Si el efecto anterior todabia no terminó de ejecutarse salimos
If blnEfectoEjecutandose Then Exit Sub
'Iniciamos el objeto Graphics
_Gr = Graphics.FromImage(_bmpDibujar)
Select Case _Efecto
Case Efectos.Aparecer, Efectos.Estirar_Centro To Efectos.Girar_Espiral_Arriba, Efectos.Rodar_DAbajo, Efectos.Rodar_DArriba
'Para estos efectos no se necesita el objeto _Brocha (se usa DrawImage)
'En el caso de 'Rodar_DArriba' y 'Rodar_DAbajo',
'el código de estos efectos inicializa el objeto
Case Else
'Iniciamos el objeto TextureBrush
IniTextureBrush()
End Select
'******* Aquí se modifica el contenedor de la imagen *******
'Asignamos _bmpDibujar a la propiedad del Contenedor de la imagen
_Propiedad.SetValue(_Contenedor, _bmpDibujar, Nothing)
'******* Aquí se modifica el contenedor de la imagen *******
'Limpiamos el contenido de _bmpDibujar
_Gr.Clear(_Color)
'Reiniciamos variables
_Contador = 0
_Aumento = 0
_AnguloGiro = 0
_xAumentaPos = 0
_yAumentaPos = 0
'True paar indicar que el efecto se va a iniciar
blnEfectoEjecutandose = True
'Iniciamos el objeto Timer
_Tiempo.Start()
Catch ex As Exception When _bmpDibujar Is Nothing
Throw New NullReferenceException("No se ha establecido la imagen donde se dibujará el efecto")
End Try
End Sub
'Inicializa el objeto TextureBrush
Private Sub IniTextureBrush()
_Brocha = New TextureBrush(_bmpTextura)
End Sub
'Controlador del evento Tick del control _Timer
Private Sub TiempoTick(ByVal sender As System.Object, ByVal e As System.EventArgs)
Try
'Ejecutamos cada 80 milesimas de segundo, el efecto selecionado
Select Case _Efecto
Case Efectos.Abanico_Derecha, Efectos.Abanico_Izquierda
Abanico(_Efecto)
Case Efectos.Aparecer
Aparecer()
Case Efectos.Barras_Horizontales, Efectos.Barras_Verticales
Barras(_Efecto)
Case Efectos.Barrido_Horizontal, Efectos.Barrido_Vertical
Barrido(_Efecto)
Case Efectos.Circulos_Fuera
Circulos_Fuera()
Case Efectos.Circulos_Dentro
Circulos_Dentro()
Case Efectos.Desplegar_Centro To Efectos.Desplegar_SI, Efectos.Estirar_Centro To Efectos.Estirar_SI
Desplegar_Estirar(_Efecto)
Case Efectos.Diagonal
Diagonal()
Case Efectos.DivisiónH_Entrante, Efectos.DivisiónH_Saliente
DivisionH(_Efecto)
Case Efectos.DivisiónV_Entrante, Efectos.DivisiónV_Saliente
DivisionV(_Efecto)
Case Efectos.Empujar_Abajo To Efectos.Empujar_Izquierda
Empujar(_Efecto)
Case Efectos.Girar_Centro To Efectos.Girar_Espiral_Arriba
Girar(_Efecto)
Case Efectos.PersianasH_Abajo, Efectos.PersianasH_Arriba
PersianasH(_Efecto)
Case Efectos.PersianasV_Derecha, Efectos.PersianasV_Izquierda
PersianasV(_Efecto)
Case Efectos.Reloj, Efectos.Reloj_AntiHorario
Reloj(_Efecto)
Case Efectos.Simetrico_Adentro To Efectos.Simetrico_Izquierda
Simetrico(_Efecto)
Case Efectos.Rueda_2Ejes To Efectos.Rueda_8Ejes
RuedaMultiple(_Efecto)
Case Efectos.Empuja_División_Lados, Efectos.Empuja_División_Topes
EmpujaDivision(_Efecto)
Case Efectos.Rodar_DAbajo To Efectos.Rodar_IArriba
Rodar(_Efecto)
End Select
Catch ex As System.Exception
Throw New System.Exception(ex.ToString)
End Try
End Sub
'Descarga objetos y detiene el Timer
Private Sub DescargaObjetos()
_Gr.Dispose()
If Not (_Brocha Is Nothing) Then
_Brocha.Dispose()
End If
_Tiempo.Stop()
'False para indicar que el efecto acaba de terminar
blnEfectoEjecutandose = False
'El efecto terminó, disparamos un evento para indicarlo
RaiseEvent EffectEnded(Me, New EventArgs)
End Sub
'Valida la propiedad VelocidadEfecto
Private Function ValidaVelocidad(ByVal intValor As Integer) As Integer
If intValor <= 0 Then
Return _Velocidad ' Valor por defecto (20)
ElseIf intValor > 100 Then
Return 100
Else : Return intValor
End If
End Function
#Region " Efectos de Transición "
'Genera los efecto de abanico
Private Sub Abanico(ByVal Efecto As Efectos)
'Calculamos por Pitagoras el radio de la circunferencia con centro en (_AnchoImagen / 2, _AltoImagen)
'que dibujará la imagen.
Dim Radio As Single = CSng(Math.Pow(((_AnchoImagen / 2) ^ 2) + (_AltoImagen ^ 2), 1 / 2))
'Negativo: dirección del efecto
Dim AnguloInicio, Negativo As Integer
'iniciamos variables según el efecto
If Efecto = Efectos.Abanico_Derecha Then
AnguloInicio = 180
Negativo = 1
ElseIf Efecto = Efectos.Abanico_Izquierda Then
AnguloInicio = 0
Negativo = -1
End If
'Llenamos media torta con centro en (_AnchoImagen / 2, _AltoImagen),
'con la textura de la imágen original,
'agregandole trozos de _AnguloGiro
Dim Rec As New Rectangle(CInt(-(Radio - (_AnchoImagen / 2))), CInt(-(Radio - _AltoImagen)), CInt(Radio * 2), CInt(Radio * 2))
'Mostramos el trozo actual de la imagen
_Gr.FillPie(_Brocha, Rec, AnguloInicio, Negativo * _AnguloGiro)
'Aumentamos el angulo de giro
_AnguloGiro += CSng(180 / _Velocidad)
'Mostramos los trozos actuales
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera el efecto de desvanecimiento de la imagen
Private Sub Aparecer()
'Opacidad contiene el valor de opacidad actual con que se va a dibujar de la imagen
Static Opacidad As Single = 0.0F
Dim CopiaVelocidad As Single = 0.0F
'Cm representa una matriz de 5X5 que servirá para modificar la opacidad de la imagen
Dim Cm As ColorMatrix = New ColorMatrix
'Con Ia establecemos la matriz de color Cm para luego usar Ia al dibujar la imagen mediante DrawImage
Dim Ia As ImageAttributes = New ImageAttributes
'100 es el valor maximo de la propiedad VelocidadEfecto
'Para calcular la velocidad en función de esta propiedad calculamos CSng(101 - _Velocidad) / 1000
CopiaVelocidad = CSng(101 - _Velocidad) / 1000
'Aumentamos el valor de Opacidad
Opacidad += CopiaVelocidad
'El valor de Opacidad debe estar entre 0.0 y 1.0
If Opacidad > 1.0F Then
Opacidad = 1.0F
ElseIf Opacidad < 0.01F Then
Opacidad = 0.01F
CopiaVelocidad = 0.01F
End If
'Limpiamos la imagen
_Gr.Clear(_Color)
'Cambiando el valor de la columna 3, fila 3 de la matriz de color se logra modificar la opacidad de la imagen
Cm.Matrix33 = Opacidad
'Establecemos a Cm como la matriz de color de el objeto de atributos de imagen Ia
Ia.SetColorMatrix(Cm)
'Dibujamos la imagen usando el objeto de atributos de imagen que preparamos previamente
_Gr.DrawImage(_bmpTextura, New Rectangle(0, 0, CInt(_AnchoImagen), CInt(_AltoImagen)), 0, 0, _AnchoImagen, _AltoImagen, GraphicsUnit.Pixel, Ia)
'Refrescamos el contenedor de la imagen
_Contenedor.Refresh()
'Cuando la imagen sea totalmente opaca terminamos el efecto
If Opacidad >= 1.0F Then
Opacidad = 0
Ia.Dispose()
DescargaObjetos()
End If
End Sub
'Genera los efectos con Barras
Private Sub Barras(ByVal Efecto As Efectos)
Dim i, j, MedidaImagen, X, Y, Ancho, Alto As Integer
Dim Iteraciones As Integer
Dim _CopiaVelocidad As Integer
'Establecemos variables según el efecto
If Efecto = Efectos.Barras_Horizontales Then
Ancho = CInt(_AnchoImagen)
Alto = 2
MedidaImagen = CInt(_AltoImagen)
ElseIf Efecto = Efectos.Barras_Verticales Then
Ancho = 2
Alto = CInt(_AltoImagen)
MedidaImagen = CInt(_AnchoImagen)
End If
'Calculamos en Iteraciones, la cantidad de barras que se van a dibujar
'teniendo en cuenta que la medida de cada barra es de 2 y
'cuidando que todo quede en función de _Velocidad.
'Aproximamos a el entero más grande en el caso de que la
'Medida de la imagen no sea divisible entre _Velocidad * 2
Iteraciones = CInt(Math.Ceiling(MedidaImagen / (_Velocidad * 2)))
_CopiaVelocidad = CInt(Math.Ceiling(MedidaImagen / (Iteraciones * 2)))
_Tiempo.Stop()
'Cada vez que se ejecuta este método dibujamos Iteraciones barras
For i = 0 To Iteraciones - 1
'Hallamos las coordenadas de cada barra que se necesita dibujar (sin repetir)
'llamando a DameParUnico.
j = DameParUnico(CInt(MedidaImagen - 2), CInt(MedidaImagen / 2) - 1)
'Cuando j = -1 ya se dibujaron todas las barras (toda la imagen)
If j = -1 Then Exit For
If Efecto = Efectos.Barras_Horizontales Then
X = 0 : Y = j
ElseIf Efecto = Efectos.Barras_Verticales Then
X = j : Y = 0
End If
'Dibujamos la barra actual
_Gr.FillRectangle(_Brocha, New Rectangle(X, Y, Ancho, Alto))
Next
_Tiempo.Start()
'Refrescamos el contenedor de la imagen
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _CopiaVelocidad veses terminamos el efecto
If _Contador = _CopiaVelocidad Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Barrido
Private Sub Barrido(ByVal Efecto As Efectos)
'Creamos un segundo objeto Graphics para dibujar en _bmpDibujar
Static Gr2 As Graphics
Dim Persiana As Single
Dim xEsquinaPersiana, yEsquinaPersiana As Single
Dim AnchoPersiana, AltoPersiana As Single
If Efecto = Efectos.Barrido_Horizontal Then
_xAumentaPos = _AnchoImagen
_yAumentaPos = 0
xEsquinaPersiana = 0
yEsquinaPersiana = _AltoImagen / 20
AnchoPersiana = _AnchoImagen
AltoPersiana = _AltoImagen / 20
ElseIf Efecto = Efectos.Barrido_Vertical Then
_xAumentaPos = 0
_yAumentaPos = _AltoImagen
xEsquinaPersiana = _AnchoImagen / 20
yEsquinaPersiana = 0
AnchoPersiana = _AnchoImagen / 20
AltoPersiana = _AltoImagen
End If
If _Contador = 0 Then
Gr2 = Graphics.FromImage(_bmpDibujar)
'Movemos el centro del eje de coordenadas la primera vez
'que se ejecuta el evento, para que la imagen se dibuje pero no se vea
_Gr.TranslateTransform(_xAumentaPos, _yAumentaPos)
Gr2.TranslateTransform(-_xAumentaPos, -_yAumentaPos)
End If
'***** Esto solo es necesario para imagenes con fondo transparente *****
'_Gr.Clear(_Color)
'***********************************************************************
For Persiana = 0 To 20 'Nº de Persianas (20)
'Las persianas pares las dibujamos con _Gr,
'y las impares con Gr2
Dim SupIzquierda As New PointF(Persiana * xEsquinaPersiana, Persiana * yEsquinaPersiana)
Dim TamañoPersiana As New SizeF(AnchoPersiana, AltoPersiana)
If Persiana Mod 2 = 0 Then
Dim RecBarridoPar As New RectangleF(SupIzquierda, TamañoPersiana)
_Gr.FillRectangle(_Brocha, RecBarridoPar)
Else
Dim RecBarridoImpar As New RectangleF(SupIzquierda, TamañoPersiana)
Gr2.FillRectangle(_Brocha, RecBarridoImpar)
End If
Next
'Transladamos los ejes progresivamente
_Gr.TranslateTransform(-_xAumentaPos / _Velocidad, -_yAumentaPos / _Velocidad) 'Velocidad
Gr2.TranslateTransform(_xAumentaPos / _Velocidad, _yAumentaPos / _Velocidad)
'Contamos las veces que movimos la imágen
_Contador += 1
'Refrescamos el Control
_Contenedor.Refresh()
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
Gr2.Dispose()
xEsquinaPersiana = 0 : yEsquinaPersiana = 0
AnchoPersiana = 0 : AltoPersiana = 0
DescargaObjetos()
End If
End Sub
'Genera el efecto con Circulos hacia Adentro
Private Sub Circulos_Dentro()
'El diametro de los circulos
Dim Diametro As Single
'Contiene los cuadrados pares
Static RecAnterior As RectangleF
'La diagonal de la imágen va a ser el diametro máximo.
'La calculamos por Pitagoras.
Dim Diagonal As Single = CSng(Math.Pow((_AltoImagen ^ 2) + (_AnchoImagen ^ 2), 1 / 2))
'Aumentamos el diametro
Diametro = Diagonal - (_Contador * Diagonal / _Velocidad)
'Definimos las coordenadas del punto superior
'izquierdo del rectángulo a partir del cual
'se dibujará un circulo circunscripto en él, de modo que
'el centro de el circulo coincida con el centro del Control
Dim xEsquina As Single = (_AnchoImagen / 2) - (Diametro / 2)
Dim yEsquina As Single = (_AltoImagen / 2) - (Diametro / 2)
Dim MiPunto As New PointF(xEsquina, yEsquina)
'Tamaño del rectángulo donde se dibujará el circulo
Dim Tamaño As SizeF = New SizeF(Diametro, Diametro)
Dim Rectángulo As New RectangleF(MiPunto, Tamaño)
If _Contador > 0 Then
Dim Trayecto1 As New GraphicsPath
'Usamos el rectángulo anterior para que no queden zonas sin dibujar
Trayecto1.AddEllipse(RecAnterior)
Dim Trayecto2 As New GraphicsPath
Trayecto2.AddEllipse(Rectángulo)
'Creamos un objeto region
'compuesto por la elipse encapsuladas en Trayecto1
'Al añadir el GraphicsPth Trayecto2
'indicamos que vamos a combinar el contenido
'del nuevo GraphicsPath Trayecto2 con Trayecto1 usando el método Xor
Dim Región As New Region(Trayecto2)
Región.Xor(Trayecto1)
'Dibujamos la región
If _Contador > 0 Then _Gr.FillRegion(_Brocha, Región)
'Mostramos el circulo actual
_Contenedor.Refresh()
End If
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Recordamos el último rectangulo que se uso para dibujar el último circulo
RecAnterior = Rectángulo
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
RecAnterior = Nothing
DescargaObjetos()
End If
End Sub
'Genera el efecto con Circulos hacia Afuera
Private Sub Circulos_Fuera()
'El diametro de los circulos
Static Diametro As Single
'La diagonal de la imágen va a ser el diametro máximo.
'La calculamos por Pitagoras.
Dim Diagonal As Single = CSng(Math.Pow((_AltoImagen ^ 2) + (_AnchoImagen ^ 2), 1 / 2))
'Definimos las coordenadas del punto superior
'izquierdo del rectángulo a partir del cual
'se dibujará un circulo circunscripto en él, de modo que
'el centro de el circulo coincida con el centro del Control
Dim xEsquina As Single = (_AnchoImagen / 2) - (Diametro / 2)
Dim yEsquina As Single = (_AltoImagen / 2) - (Diametro / 2)
Dim MiPunto As New PointF(xEsquina, yEsquina)
'Tamaño del rectángulo donde se dibujará el circulo
Dim Tamaño As SizeF = New SizeF(Diametro, Diametro)
Dim Rectángulo As New RectangleF(MiPunto, Tamaño)
_Gr.FillEllipse(_Brocha, Rectángulo)
'Mostramos el circulo actual
_Contenedor.Refresh()
'Aumentamos el diametro
Diametro += Diagonal / _Velocidad
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
Diametro = 0
DescargaObjetos()
End If
End Sub
'Genera los efectos de despliegue y estiramiento
Private Sub Desplegar_Estirar(ByVal Efecto As Efectos)
Dim X, Y, Ancho, Alto As Single
_Aumento += CSng(1 / _Velocidad)
'Iniciamos variables según el efecto.
'Notar que el código para los efectos "Desplegar" y "Estirar" son identicos
'excepto por el método usado para dibujar la imagen (FillRectangle o DrawImage)
Select Case Efecto
Case Efectos.Desplegar_Centro, Efectos.Estirar_Centro
X = (_AnchoImagen / 2) - ((_AnchoImagen / 2) * _Aumento)
Y = (_AltoImagen / 2) - ((_AltoImagen / 2) * _Aumento)
Case Efectos.Desplegar_ID, Efectos.Estirar_ID
X = _AnchoImagen - (_AnchoImagen * _Aumento)
Y = _AltoImagen - (_AltoImagen * _Aumento)
Case Efectos.Desplegar_II, Efectos.Estirar_II
X = 0
Y = _AltoImagen - (_AltoImagen * _Aumento)
Case Efectos.Desplegar_SD, Efectos.Estirar_SD
X = _AnchoImagen - (_AnchoImagen * _Aumento)
Y = 0
Case Efectos.Desplegar_SI, Efectos.Estirar_SI
X = 0
Y = 0
End Select
Ancho = _AnchoImagen * _Aumento
Alto = _AltoImagen * _Aumento
Dim Rec As New RectangleF(X, Y, Ancho, Alto)
_Gr.Clear(_Color)
Select Case Efecto
Case Efectos.Desplegar_Centro To Efectos.Desplegar_SI
_Gr.FillRectangle(_Brocha, Rec)
Case Efectos.Estirar_Centro To Efectos.Estirar_SI
_Gr.DrawImage(_bmpTextura, Rec)
End Select
'Refrescamos el contenedor de la imagen
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad veses terminamos el efecto
If _Contador = _Velocidad Then
DescargaObjetos()
End If
End Sub
'Genera el efecto en Diagonal desde el angúlo superior izquierdo
Private Sub Diagonal()
'Aumentamos los lados del triángulo
_xAumentaPos += _AnchoImagen / _Velocidad
_yAumentaPos += _AltoImagen / _Velocidad
'Dibujanos el triángulo actual
_Gr.FillPolygon(_Brocha, New PointF() {New PointF(0, 0), New PointF(_xAumentaPos, 0), New PointF(0, _yAumentaPos)})
'Actualizamos el dibujo
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad * 2
'veses terminamos el efecto
If _Contador = _Velocidad * 2 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Divición Horizontal
Private Sub DivisionH(ByVal Efecto As Efectos)
Dim Velocidad As Single = _AnchoImagen / _Velocidad
'Si es la primera vez que se llega aquí, establecemos algunas variables
If _Contador = 0 Then
If Efecto = Efectos.DivisiónH_Entrante Then
_Aumento = 0
ElseIf Efecto = Efectos.DivisiónH_Saliente Then
_Aumento = _AnchoImagen / 2
End If
End If
Dim RecDivision As New RectangleF(_Aumento, 0, Velocidad, _AltoImagen)
Dim RecDivision2 As New RectangleF(_AnchoImagen - _Aumento, 0, Velocidad, _AltoImagen)
'Dibujamos los rectangulos de división
_Gr.FillRectangle(_Brocha, RecDivision)
_Gr.FillRectangle(_Brocha, RecDivision2)
_Contenedor.Refresh()
'Aumentamos el tamaño de los rectangulos
_Aumento += Velocidad
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado la mitad de la cantidad de
'diviciones del Ancho + 1 veses terminamos el efecto
If _Contador = ((_Velocidad + 1) \ 2) + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Divición Vertical
Private Sub DivisionV(ByVal Efecto As Efectos)
Dim Velocidad As Single = _AltoImagen / _Velocidad
'Si es la primera vez que se llega aquí, establecemos algunas variables
If _Contador = 0 Then
If Efecto = Efectos.DivisiónV_Entrante Then
_Aumento = 0
ElseIf Efecto = Efectos.DivisiónV_Saliente Then
_Aumento = _AltoImagen / 2
End If
End If
Dim RecDivision As New RectangleF(0, _Aumento, _AnchoImagen, Velocidad)
Dim RecDivision2 As New RectangleF(0, _AltoImagen - _Aumento, _AnchoImagen, Velocidad)
'Dibujamos los rectangulos de división
_Gr.FillRectangle(_Brocha, RecDivision)
_Gr.FillRectangle(_Brocha, RecDivision2)
_Contenedor.Refresh()
'Aumentamos el tamaño de los rectangulos
_Aumento += Velocidad
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado la mitad de la cantidad de
'diviciones del Alto + 1 veses terminamos el efecto
If _Contador = ((_Velocidad + 1) \ 2) + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Empuje
Private Sub Empujar(ByVal eEfecto As Efectos)
'Si es la primera vez que se llega aquí,
'Establecemos las transformaciónes iniciales
'según la variante de efecto de Empuje
If _Contador = 0 Then
If eEfecto = Efectos.Empujar_Abajo Then
_Gr.TranslateTransform(0, -_AltoImagen)
_xAumentaPos = 0 : _yAumentaPos = _AltoImagen / _Velocidad
ElseIf eEfecto = Efectos.Empujar_Arriba Then
_Gr.TranslateTransform(0, _AltoImagen)
_xAumentaPos = 0 : _yAumentaPos = -_AltoImagen / _Velocidad
ElseIf eEfecto = Efectos.Empujar_Derecha Then
_Gr.TranslateTransform(-_AnchoImagen, 0)
_xAumentaPos = _AnchoImagen / _Velocidad : _yAumentaPos = 0
ElseIf eEfecto = Efectos.Empujar_Izquierda Then
_Gr.TranslateTransform(_AnchoImagen, 0)
_xAumentaPos = -_AnchoImagen / _Velocidad : _yAumentaPos = 0
ElseIf eEfecto = Efectos.Empujar_Diagonal_SI Then
_Gr.TranslateTransform(-_AnchoImagen, -_AltoImagen)
_xAumentaPos = _AnchoImagen / _Velocidad : _yAumentaPos = _AltoImagen / _Velocidad
ElseIf eEfecto = Efectos.Empujar_Diagonal_SD Then
_Gr.TranslateTransform(_AnchoImagen, -_AltoImagen)
_xAumentaPos = -_AnchoImagen / _Velocidad : _yAumentaPos = _AltoImagen / _Velocidad
ElseIf eEfecto = Efectos.Empujar_Diagonal_II Then
_Gr.TranslateTransform(-_AnchoImagen, _AltoImagen)
_xAumentaPos = _AnchoImagen / _Velocidad : _yAumentaPos = -_AltoImagen / _Velocidad
ElseIf eEfecto = Efectos.Empujar_Diagonal_ID Then
_Gr.TranslateTransform(_AnchoImagen, _AltoImagen)
_xAumentaPos = -_AnchoImagen / _Velocidad : _yAumentaPos = -_AltoImagen / _Velocidad
End If
End If
'***** Esto solo es necesario para imagenes con fondo transparente *****
'_Gr.Clear(_Color)
'***********************************************************************
'Dibujamos la imagen con las transformaciónes de ejes.
Dim RecEmpuja As New RectangleF(0, 0, _AnchoImagen, _AltoImagen)
_Gr.FillRectangle(_Brocha, RecEmpuja)
_Gr.TranslateTransform(_xAumentaPos, _yAumentaPos)
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1 veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Empuje con División
Private Sub EmpujaDivision(ByVal Efecto As Efectos)
'Creamos el segundo objeto Graphics para dibujar en _bmpDibujar
Static Gr2 As Graphics
Dim Ancho, Alto, xEsquina, yEsquina As Single
If Efecto = Efectos.Empuja_División_Lados Then
_xAumentaPos = _AnchoImagen / (2 * _Velocidad)
_yAumentaPos = 0
Ancho = _AnchoImagen / 2
Alto = _AltoImagen
xEsquina = Ancho
yEsquina = 0
ElseIf Efecto = Efectos.Empuja_División_Topes Then
_xAumentaPos = 0
_yAumentaPos = _AltoImagen / (2 * _Velocidad)
Ancho = _AnchoImagen
Alto = _AltoImagen / 2
xEsquina = 0
yEsquina = Alto
End If
'Si es la primera vez que se llega aquí,
'Establecemos las transformaciónes iniciales
'según la variante de efecto de Empuje y División
If _Contador = 0 Then
Gr2 = Graphics.FromImage(_bmpDibujar)
If Efecto = Efectos.Empuja_División_Lados Then
_Gr.TranslateTransform(-Ancho, 0)
Gr2.TranslateTransform(Ancho, 0)
ElseIf Efecto = Efectos.Empuja_División_Topes Then
_Gr.TranslateTransform(0, -Alto)
Gr2.TranslateTransform(0, Alto)
End If
End If
Dim RecEmpujaLado As New RectangleF(0, 0, Ancho, Alto)
Dim RecEmpujaOpuesto As New RectangleF(xEsquina, yEsquina, Ancho, Alto)
'***** Esto solo es necesario para imagenes con fondo transparente *****
'_Gr.Clear(_Color)
'***********************************************************************
'Dibujamos los rectangulos y los lenamos con la imagen
_Gr.FillRectangle(_Brocha, RecEmpujaLado)
Gr2.FillRectangle(_Brocha, RecEmpujaOpuesto)
'Movemos los ejes de coordenadas
_Gr.TranslateTransform(_xAumentaPos, _yAumentaPos)
Gr2.TranslateTransform(-_xAumentaPos, -_yAumentaPos)
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1 veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
Gr2.Dispose()
DescargaObjetos()
End If
End Sub
'm: Matriz que vamos a usar para establecer tranformaciones en algunos efectos
Private m As Matrix
'Genera los efectos de giro de la imagen con movimiento en espiral
Private Sub Girar(ByVal Efecto As Efectos)
Dim X, Y, Ancho, Alto As Single
If _Contador = 0 Then
'La primera vez que se ejecuta el procedimiento, iniciamos la martix
'y establecemos el ángulo de giro
m = New Matrix
_AnguloGiro = CInt(360 / _Velocidad)
End If
_Aumento += CSng(1 / _Velocidad)
Ancho = _AnchoImagen * _Aumento
Alto = _AltoImagen * _Aumento
If Efecto = Efectos.Girar_Centro Then
X = (_AnchoImagen / 2) - ((_AnchoImagen / 2) * _Aumento)
Y = (_AltoImagen / 2) - ((_AltoImagen / 2) * _Aumento)
ElseIf Efecto = Efectos.Girar_Espiral_Abajo Then
X = 0
Y = _AltoImagen - _AltoImagen * _Aumento
ElseIf Efecto = Efectos.Girar_Espiral_Arriba Then
X = _AnchoImagen - _AnchoImagen * _Aumento
Y = 0
End If
'Rectangulo donde se dibujará la imagen
Dim Rec As New RectangleF(X, Y, Ancho, Alto)
_Gr.Clear(_Color)
'Dibujamos la imagen completa
_Gr.DrawImage(_bmpTextura, Rec)
'"Preparamos" una rotación con centro en el centro de la imagen en la matriz m
'por medio del metodo RotateAt y estableciendo la transformación en nuestro objeto Graphics _Gr
'para ser usada en la proxima ejecución del procedimiento
m.RotateAt(_AnguloGiro, New PointF(_AnchoImagen / 2, _AltoImagen / 2))
_Gr.Transform = m
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Para asegurarnos de que la imagen de 1 vuelta entera terminamos el efecto cuando _Contador = 360,
'o sea ...
If _Contador = CInt(360 / _AnguloGiro) Then
'***** Esto solo es necesario para imagenes con fondo transparente *****
'_Gr.Clear(_Color)
'***********************************************************************
'Rotamos la imagen a su posición original y la dibujamos antes de descargar todo
m.RotateAt(-CSng(_AnguloGiro * _Contador), New PointF(_AnchoImagen / 2, _AltoImagen / 2))
_Gr.Transform = m
_Gr.DrawImage(_bmpTextura, _bmpDibujar.GetBounds(GraphicsUnit.Pixel))
_Contenedor.Refresh()
m.Dispose()
DescargaObjetos()
End If
End Sub
'Genera los efectos con Persianas Horizontales
Private Sub PersianasH(ByVal Efecto As Efectos)
Dim Persiana As Integer
'Total de Persianas
Dim TotalPersianas As Integer = 15
Dim Velocidad As Integer = TotalPersianas * _Velocidad
'Si es la primera vez que se llega aquí, establecemos algunas variables
If _Contador = 0 Then
If Efecto = Efectos.PersianasH_Abajo Then
_Aumento = 0
ElseIf Efecto = Efectos.PersianasH_Arriba Then
_Aumento = _AltoImagen / TotalPersianas
End If
End If
For Persiana = 0 To TotalPersianas - 1
'Dibuja un trozo de cada una de las persianas por cada ejecución del evento
Dim SupIzquierda As New PointF(0, _Aumento + (Persiana * (_AltoImagen / TotalPersianas)))
Dim TamañoPersiana As New SizeF(_AnchoImagen, _AltoImagen / Velocidad)
Dim RecPersiana As New RectangleF(SupIzquierda, TamañoPersiana)
_Gr.FillRectangle(_Brocha, RecPersiana)
Next
_Contenedor.Refresh()
'Aumentamos el tamaño de cada persiana para la próxima vez que se dibujen
If Efecto = Efectos.PersianasH_Abajo Then
_Aumento += _AltoImagen / Velocidad
ElseIf Efecto = Efectos.PersianasH_Arriba Then
_Aumento -= _AltoImagen / Velocidad
End If
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1 veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos con Persianas Verticales
Private Sub PersianasV(ByVal Efecto As Efectos)
Dim Persiana As Integer
Dim TotalPersianas As Integer = 15
Dim Velocidad As Integer = TotalPersianas * _Velocidad
'Si es la primera vez que se llega aquí, establecemos algunas variables
If _Contador = 0 Then
If Efecto = Efectos.PersianasV_Izquierda Then
_Aumento = 0
ElseIf Efecto = Efectos.PersianasV_Derecha Then
_Aumento = _AnchoImagen / TotalPersianas
End If
End If
For Persiana = 0 To TotalPersianas - 1
'Dibuja un trozo de cada una de las persianas por cada ejecución del evento
Dim SupIzquierda As New PointF(_Aumento + (Persiana * (_AnchoImagen / TotalPersianas)), 0)
Dim TamañoPersiana As New SizeF(_AnchoImagen / Velocidad, _AltoImagen)
Dim RecPersiana As New RectangleF(SupIzquierda, TamañoPersiana)
_Gr.FillRectangle(_Brocha, RecPersiana)
Next
_Contenedor.Refresh()
'Aumentamos el tamaño de cada persiana para la próxima vez que se dibujen
If Efecto = Efectos.PersianasV_Izquierda Then
_Aumento += _AnchoImagen / Velocidad
ElseIf Efecto = Efectos.PersianasV_Derecha Then
_Aumento -= _AnchoImagen / Velocidad
End If
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1 veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera el efecto de Reloj
Private Sub Reloj(ByVal Efecto As Efectos)
'La diagonal de la imágen va a ser el diametro.
'La calculamos por Pitagoras.
Dim Diagonal As Single = CSng(Math.Pow((_AltoImagen ^ 2) + (_AnchoImagen ^ 2), 1 / 2))
'Negativo: indica la dirección del giro
Dim Negativo As Integer
If Efecto = Efectos.Reloj Then
Negativo = 1
ElseIf Efecto = Efectos.Reloj_AntiHorario Then
Negativo = -1
End If
'Llenamos una torta con centro en el centro del Control,
'con la textura de la imágen original,
'agregandole trozos de _AnguloGiro
_Gr.FillPie(_Brocha, CSng(-(Diagonal - _AnchoImagen) / 2), CSng(-(Diagonal - _AltoImagen) / 2), Diagonal, Diagonal, -90, Negativo * _AnguloGiro)
'Mostramos el trozo actual
_Contenedor.Refresh()
_AnguloGiro += CSng(360 / _Velocidad)
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Rodar
Private Sub Rodar(ByVal Efecto As Efectos)
'intAngulo: angulo de giro progresivo
Dim intAngulo As Single = CSng(90 / _Velocidad)
If _Contador = 0 Then
'Si es la primera vez que se llega aquí iniciamos variables dependiendo
'de el tipo de efecto
If Efecto = Efectos.Rodar_IAbajo Then
_AnguloGiro = 90.0F
_Aumento = -1
_xAumentaPos = 0
_yAumentaPos = 0
ElseIf Efecto = Efectos.Rodar_IArriba Then
_AnguloGiro = -90.0F
_Aumento = 1
_xAumentaPos = 0
_yAumentaPos = 0
ElseIf Efecto = Efectos.Rodar_DArriba Then
_bmpTextura.RotateFlip(RotateFlipType.RotateNoneFlipXY)
IniTextureBrush()
_AnguloGiro = 270
_Aumento = -1
_xAumentaPos = _AnchoImagen
_yAumentaPos = _AltoImagen
ElseIf Efecto = Efectos.Rodar_DAbajo Then
_bmpTextura.RotateFlip(RotateFlipType.RotateNoneFlipXY)
IniTextureBrush()
_AnguloGiro = -270.0F
_Aumento = 1
_xAumentaPos = _AnchoImagen
_yAumentaPos = _AltoImagen
End If
'Movemos el centro del eje de coordenadas la primera vez
'que se ejecuta el evento, para que la imagen se dibuje pero no se vea
_Gr.TranslateTransform(_xAumentaPos, _yAumentaPos)
'Tambien aplicamos la rotación adecuada al objeto _Gr
_Gr.RotateTransform(_AnguloGiro)
End If
'Dibujamos la imagen con las transformaciónes de ejes.
Dim RecEmpuja As New RectangleF(0, 0, _AnchoImagen, _AltoImagen)
_Gr.Clear(_Color)
_Gr.FillRectangle(_Brocha, RecEmpuja)
'Refrescamos el contenedor de la imagen
_Contenedor.Refresh()
'Rotamos la imagen progresivamente
_Gr.RotateTransform(_Aumento * intAngulo)
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Para asegurarnos de que la imagen de 1/2 vuelta, terminamos el efecto cuando _Contador = 90
'o sea ...
If _Contador = CInt(90 / intAngulo) + 1 Then
'Restablecemos la imagen a su estado original antes de descargar objetos
If (Efecto = Efectos.Rodar_DAbajo) OrElse (Efecto = Efectos.Rodar_DArriba) _
Then _bmpTextura.RotateFlip(RotateFlipType.RotateNoneFlipXY)
DescargaObjetos()
End If
End Sub
'Genera los efecto con múltiples Ejes
Private Sub RuedaMultiple(ByVal Efecto As Efectos)
Dim AnguloInicio, Paso, Ejes As Integer
'Establecemos variables según la variante del efecto seleccionados
Select Case Efecto
Case Efectos.Rueda_2Ejes
AnguloInicio = -90 : Paso = 180 : Ejes = 2
Case Efectos.Rueda_3Ejes
AnguloInicio = -90 : Paso = 120 : Ejes = 3
Case Efectos.Rueda_4Ejes
AnguloInicio = 0 : Paso = 90 : Ejes = 4
Case Efectos.Rueda_8Ejes
AnguloInicio = 0 : Paso = 45 : Ejes = 8
End Select
'La diagonal de la imágen va a ser el diametro.
'La calculamos por Pitagoras.
Dim Diagonal As Single = CSng(Math.Pow((_AltoImagen ^ 2) + (_AnchoImagen ^ 2), 1 / 2))
Dim i As Integer
'Llenamos una torta con centro en el centro del Control,
'con la textura de la imágen original,
'agregandole trozos de _AnguloGiro
Dim Rec As New Rectangle(CInt(-(Diagonal - _AnchoImagen) / 2), CInt(-(Diagonal - _AltoImagen) / 2), CInt(Diagonal), CInt(Diagonal))
For i = 1 To Ejes
_Gr.FillPie(_Brocha, Rec, AnguloInicio, _AnguloGiro)
AnguloInicio += Paso
Next
_AnguloGiro += CSng(Paso / _Velocidad)
'Mostramos los trozos actuales
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Genera los efectos de Simetría
Private Sub Simetrico(ByVal Efecto As Efectos)
'La diagonal de la imágen va a ser el diametro.
'La calculamos por Pitagoras.
Dim Diagonal As Single = CSng(Math.Pow((_AltoImagen ^ 2) + (_AnchoImagen ^ 2), 1 / 2))
Dim AnguloInicio As Integer
'Iniciamos variables según el efecto seleccionado
If Efecto = Efectos.Simetrico_Adentro Then
AnguloInicio = -90
ElseIf Efecto = Efectos.Simetrico_Afuera Then
AnguloInicio = 90
ElseIf Efecto = Efectos.Simetrico_Izquierda Then
AnguloInicio = 180
ElseIf Efecto = Efectos.Simetrico_Derecha Then
AnguloInicio = 0
End If
'Llenamos una torta con centro en el centro de _bmpDibujar,
'con la textura de la imágen original,
'agregandole trozos de _AnguloGiro
Dim rec As New Rectangle(CInt(-(Diagonal - _AnchoImagen) / 2), CInt(-(Diagonal - _AltoImagen) / 2), CInt(Diagonal), CInt(Diagonal))
_Gr.FillPie(_Brocha, rec, AnguloInicio, _AnguloGiro)
_Gr.FillPie(_Brocha, rec, AnguloInicio, -_AnguloGiro)
_AnguloGiro += CSng(180 / _Velocidad)
'Mostramos los trozos actuales
_Contenedor.Refresh()
'Contamos las veces que se ejecutó este evento
_Contador += 1
'Cuando el evento se halla ejecutado _Velocidad + 1
'veses terminamos el efecto
If _Contador = _Velocidad + 1 Then
DescargaObjetos()
End If
End Sub
'Arreglo que se va a usar para contar los enteros pares generados por DameParUnico
Private Rango() As Integer = {}
'Genera y devuelve 'TotalCoordBarras' enteros positivos pares (de a uno)
'entre 0 y intMaximo (incluido el cero) de forma aleatoria y sin repetir
Private Function DameParUnico(ByVal intMaximo As Integer, ByVal TotalCoordBarras As Integer) As Integer
'r: para generar los números de forma aleatoria
Dim r As New Random
'i: contiene cada número que se genera
Dim i As Integer
Static j As Integer = 0
'Para saber si ya salio el cero
Static CeroYaSalio As Boolean = False
If j = 0 Then
'La primera vez redimensionamos el arreglo 'Rango' que contendrá los enteros
ReDim Rango(TotalCoordBarras)
ElseIf j = TotalCoordBarras Then
'Cuando se llene el arreglo, reiniciamos variables y lo indicamos devolviendo -1
j = 0
CeroYaSalio = False
Return -1
End If
Do
i = r.Next(intMaximo)
If i > 0 Then
'Si i es par...
If i Mod 2 = 0 Then
'... y no esta en el arreglo...
If Rango.IndexOf(Rango, i) = -1 Then
'... lo agregamos en Rango y lo devolvemos
j += 1
Rango.SetValue(i, j - 1)
Return Rango(j - 1)
End If
End If
ElseIf Not CeroYaSalio Then
'Agregamos el cero en el arreglo y lo devolvemos
j += 1
Rango.SetValue(i, j - 1)
CeroYaSalio = True
Return Rango(j - 1)
End If
Loop Until j = TotalCoordBarras
End Function
#End Region
#End Region
End Class
El Proyecto de ejemplo...
En un formulario escribir el siguiente código:
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Public Class frmEfectos
Inherits System.Windows.Forms.Form
#Region " Código generado por el Diseñador de Windows Forms "
Public Sub New()
MyBase.New()
'El Diseñador de Windows Forms requiere esta llamada.
InitializeComponent()
'Agregar cualquier inicialización después de la llamada a InitializeComponent()
End Sub
'Form reemplaza a Dispose para limpiar la lista de componentes.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Requerido por el Diseñador de Windows Forms
Private components As System.ComponentModel.IContainer
Friend WithEvents pic As System.Windows.Forms.PictureBox
Friend WithEvents btnReproducir As System.Windows.Forms.Button
'NOTA: el Diseñador de Windows Forms requiere el siguiente procedimiento
'Puede modificarse utilizando el Diseñador de Windows Forms.
'No lo modifique con el editor de código.
Friend WithEvents PropertyGrid1 As System.Windows.Forms.PropertyGrid
Friend WithEvents lblEstado As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(frmEfectos))
Me.pic = New System.Windows.Forms.PictureBox
Me.btnReproducir = New System.Windows.Forms.Button
Me.PropertyGrid1 = New System.Windows.Forms.PropertyGrid
Me.lblEstado = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.CheckBox1 = New System.Windows.Forms.CheckBox
Me.SuspendLayout()
'
'pic
'
Me.pic.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.pic.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.pic.Image = CType(resources.GetObject("pic.Image"), System.Drawing.Image)
Me.pic.Location = New System.Drawing.Point(215, 61)
Me.pic.Name = "pic"
Me.pic.Size = New System.Drawing.Size(800, 600)
Me.pic.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize
Me.pic.TabIndex = 0
Me.pic.TabStop = False
'
'btnReproducir
'
Me.btnReproducir.Location = New System.Drawing.Point(15, 466)
Me.btnReproducir.Name = "btnReproducir"
Me.btnReproducir.Size = New System.Drawing.Size(153, 29)
Me.btnReproducir.TabIndex = 1
Me.btnReproducir.Text = "Reproducir"
'
'PropertyGrid1
'
Me.PropertyGrid1.CommandsVisibleIfAvailable = True
Me.PropertyGrid1.LargeButtons = False
Me.PropertyGrid1.LineColor = System.Drawing.SystemColors.ScrollBar
Me.PropertyGrid1.Location = New System.Drawing.Point(12, 60)
Me.PropertyGrid1.Name = "PropertyGrid1"
Me.PropertyGrid1.Size = New System.Drawing.Size(198, 390)
Me.PropertyGrid1.TabIndex = 8
Me.PropertyGrid1.Text = "PropertyGrid1"
Me.PropertyGrid1.ViewBackColor = System.Drawing.SystemColors.Window
Me.PropertyGrid1.ViewForeColor = System.Drawing.SystemColors.WindowText
'
'lblEstado
'
Me.lblEstado.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.lblEstado.Location = New System.Drawing.Point(266, 34)
Me.lblEstado.Name = "lblEstado"
Me.lblEstado.Size = New System.Drawing.Size(327, 22)
Me.lblEstado.TabIndex = 9
Me.lblEstado.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'Label2
'
Me.Label2.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Label2.Location = New System.Drawing.Point(160, 34)
Me.Label2.Name = "Label2"
Me.Label2.TabIndex = 10
Me.Label2.Text = "Estado:"
Me.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
'
'CheckBox1
'
Me.CheckBox1.Location = New System.Drawing.Point(15, 516)
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox1.Size = New System.Drawing.Size(179, 32)
Me.CheckBox1.TabIndex = 12
Me.CheckBox1.Text = "Establecer imagen de fondo"
'
'frmEfectos
'
Me.AcceptButton = Me.btnReproducir
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.AutoScroll = True
Me.ClientSize = New System.Drawing.Size(770, 509)
Me.Controls.Add(Me.CheckBox1)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.lblEstado)
Me.Controls.Add(Me.PropertyGrid1)
Me.Controls.Add(Me.btnReproducir)
Me.Controls.Add(Me.pic)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
Me.MinimumSize = New System.Drawing.Size(700, 550)
Me.Name = "frmEfectos"
Me.Text = "Efectos"
Me.WindowState = System.Windows.Forms.FormWindowState.Maximized
Me.ResumeLayout(False)
End Sub
#End Region
'Definimos un objeto de tipo EfectosTrans
Private WithEvents et As EfectosTrans
'Seleccionamos el primer elemento del ListBox y los ComboBox para que todo quede listo para usar.
Private Sub frmEfectos_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
et = New EfectosTrans("..\Dibujo1.jpg", pic, "Image")
PropertyGrid1.SelectedObject = et
CheckBox1.Checked = True
End Sub
'Reproduce el Efecto seleccionado en el ListBox
Private Sub btnReproducir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReproducir.Click
et.Start()
lblEstado.Text = "Efecto Iniciado..."
End Sub
'Controla el evento EffectEnded que se dispara al terminar de ejecutarce un efecto
Private Sub et_EffectEnded(ByVal sender As Object, ByVal e As System.EventArgs) Handles et.EffectEnded
lblEstado.Text = "Efecto Terminado"
End Sub
'Al establecer una imagen de fondo en el contenedor, y establecer el color de relleno en "Transparente"
'Se logra una transición entre dos imagenes.
Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
Try
pic.BackgroundImage = Image.FromFile("..\Dibujo2.jpg")
et.ColorTrans = Color.Transparent
PropertyGrid1.Refresh()
Catch ex As Exception
End Try
Else
pic.BackgroundImage = Nothing
End If
End Sub
End Class
Fichero con el código de ejemplo anibal_et_clase.zip - 82.8 KB