Como usar arreglos de controles para el objeto bitclip

Fecha: 21/Sep/2004 (17/09/2004)
Autor: Victor Hugo Cordon  victor.cordon@integra.com.sv


Para todos aquellos que extrañan los arreglos de controles en VB6 e escrito el siguiente articulo. A medida que iba escribiendo me di cuenta que ya no existía el control bitclip en .net por lo que hice una pequeña implementación. Finalmente le puse un toque personal desarrollando un pequeño juego de puzzles.

En esta oportunidad deseo compartir con ustedes algunas experiencias con respecto al trabajo con imágenes y grupos de controles. Empezare describiendo a grandes rasgos la presente experiencia.

Crear el escenario de trabajo

El escenario de trabajo consiste en un objeto openfiledialog, un objeto picturebox y un objetos button . Primero declararemos los objetos y luego los agregaremos a la colección de controles del formulario. Para que el botón sea funcional debemos programar el evento click.

Dim picboxSource As New PictureBox() 
Dim bitmapSource As Bitmap Dim butonInicio As New Button() 

Dim openFile As New OpenFileDialog() 
Private Sub form_Load(ByVal sender As System.Object, ByVal e  As System.EventArgs) Handles MyBase.Load 
crearEscenario() 
End 

Sub Private Sub crearEscenario() 
With picboxSource 
.Width = 200 : .Height = 200 
.Left = 350 : .Top = 50 
.BorderStyle = BorderStyle.Fixed3D 
.SizeMode = PictureBoxSizeMode.StretchImage 
End With 
Me.Controls.Add(picboxSource) 
With butonInicio 
.Top = 260 : .Left = 350 
.Text = "Inicio" 
End With 
Me.Controls.Add(butonInicio) 
AddHandler butonInicio.Click, AddressOf butonInicio_click 
End Sub 

Private Sub butonInicio_click(ByVal sender As Object, ByVal e  As EventArgs) 
inicio() 
End Sub

Nótese que es a partir de este evento inicio que se desarrollara nuestra aplicación Abrir una imagen desde un archivo No podemos asignar directamente una imagen a un picturebox. Para ello es necesario crear primero un objeto bitmap desde un archivo

Private Sub asignarImagen() 
openFile.DefaultExt = "bmp;jepg;gif" 
If openFile.ShowDialog = DialogResult.OK Then 
Dim bmp As New Bitmap(openFile.FileName) 
picboxSource.Image = bmp 
End If 
End Sub

Creando el grupo de controles De igual forma como hicimos en el escenario crearemos un objeto picturebox con su respectivo evento. Usaremos dos ciclos for anidados para controlar la ubicación de los objetos en una construcción matricial de 3 filas por 3 columnas. Añadiremos a la sección de declaraciones generales una nueva variable de tipo arreglo de picturebox. El objetivo es crear un arreglo paralelo de 9 posiciones y lo igualaremos a cada uno de los controles dentro del grupo. La idea es que esta igualdad entre objetos hará que ambos compartan una misma puntero de memoria de tal manera que al hacer un cambio en un elemento del arreglo se vea reflejado en el respectivo control correspondiente. Para poder hacer esta equivalencia agregaremos la propiedad tag de los controles para asignar un índice a cada uno de los controles.

Dim picboxSource As New PictureBox() 
Dim bitmapSource As Bitmap 
Dim butonInicio As New Button() 
Dim openFile As New OpenFileDialog() 
Dim picboxArray(8) As PictureBox

Para asignar a cada control una porción de la imagen original primero definiremos un control rectangle que defina una región dentro de la imagen original y luego utilizaremos el método clone del objeto bitmap para recuperar la región como una imagen. Observe que utilizamos las variables xR,yR para controlar la ubicación del rectángulo que define el área de la imagen original.

Private Sub createGrupo() 
Dim n, i, j, x, y, xR, yR As Short 
Dim alto, ancho As Integer ancho = Int(bitmapSource.Width / 3) 
alto = Int(bitmapSource.Height / 3) 
For i = 0 To 2 
For j = 0 To 2 
Dim objPicBox As New PictureBox() 
Dim rect As New Rectangle(xR, yR, ancho, alto) 
With objPicBox 
.Width = 100 : .Height = 100 
.Left = x : .Top = y 
.SizeMode = PictureBoxSizeMode.StretchImage 
.BorderStyle = BorderStyle.Fixed3D 
.BackColor = Color.Black 
.Tag = n 
End With 
Me.Controls.Add(objPicBox) 
AddHandler objPicBox.Click, AddressOf  groupPicBox_Click 
objPicBox.Image = bitmapSource.Clone(rect, bitmapSource.PixelFormat) 
picboxArray(n) = objPicBox 
x += 100 
xR += ancho 
n += 1 
Next 
y += 100 
x = 0 
yR += alto 
xR = 0 
Next 
End Sub 

Private Sub groupPicBox_Click(ByVal sender As Object, ByVal e  As EventArgs) 
End Sub

Hemos creado un arreglo de controles en memoria que esta sincronizado con los controles del grupo así si hacemos que la imagen del elemento 8 del arreglo sea nothing obtendremos la siguiente vista.

Private Sub inicio() asignarImagen() 
createGrupo() picboxArray(8).Image = Nothing 
End Sub

 

Si recuerdas visual basic 6 , aquí tienes una forma de emular el antiguo control bitclip. Como te lo puedes haber imaginado esto se parece a un rompecabezas de esos que vas intercambiando las imágenes hasta llegar a la imagen original. Pues bien trabajemos en el evento clic de estos controles. El procedimiento consiste en intercambiar la imagen de un control con el control vecino siempre y cuando la imagen de este sea nothing. Para ello haremos un procedimiento llamado swap en la que le indicaremos a cada cuadro quienes son sus vecinos. El problema es saber cual de los cuadros es sobre el cual hemos hecho clic. El truco esta en convertir el argumento sender a un objeto picturebox y luego extraer, en este caso la propiedad tag.

Private Sub groupPicBox_Click(ByVal sender As Object, ByVal e  As EventArgs) 
Dim index As Short 
Dim objPicBox As New PictureBox() 
objPicBox = CType(sender, PictureBox) 
index = CType(objPicBox.Tag, Short) 
swap(index) 
End Sub

 Ahora utilizaremos la variable strVecino para indicar al control index cuales son sus vecinos. Seguidamente haremos el swap de imágenes siempre y cuando uno de los vecinos de index tenga una imagen nothing. De esta manera cada vez que hacemos clic sobre un control se dispara el evento correspondiente y si es posible se intercambian las imágenes.

Private Sub swap(ByVal index As Short) 
Dim strVecino As String 
Select Case index 
Case 0 
strVecino = "13" 
Case 1 
strVecino = "042" 
Case 2 
strVecino = "15" 
Case 3 
strVecino = "046" 
Case 4 
strVecino = "3175" 
Case 5 
strVecino = "248" 
Case 6 
strVecino = "37" 
Case 7 
strVecino = "648" 
Case 8 
strVecino = "75" 

End Select 
Dim i As Short 
For i = 0 To strVecino.Length - 1 
Dim pos As Short pos = CType(strVecino.Chars(i).ToString, Short) 
If IsNothing(picboxArray(pos).Image) Then 
Dim tempPicBox As New PictureBox() 
tempPicBox.Image = picboxArray(index).Image 
picboxArray(index).Image = picboxArray(pos).Image 
picboxArray(pos).Image = tempPicBox.Image 
Exit For 
End If 
Next 
End Sub
Ahora agregaremos al procedimiento Inicio el procedimiento revolver, el cual generara un numero aleatorio entre 0 y 8 e intentara un swap. Este proceso se repite cíclicamente
Private Sub Revolver() 
Dim azar, i As Integer 
For i = 0 To 10000 
Randomize() 
azar = Int(Rnd() * 9) 
swap(azar) 
Next 
End Sub

Por ultimo solo queda determinar cuando el rompecabezas esta armado correctamente comenzaremos agregando la propiedad text a cada uno de los controles del grupo en el procedimiento donde fueron creados y haciendo swap de estas propiedades en el momento que se intercambian las imágenes. Declararemos una variable booleana de control de nombre revuelto para determinar en que momento esta revuelto el rompecabezas

Dim revuelto As Boolean 
Private Sub createGrupo() 
Dim n, i, j, x, y, xR, yR As Short 
Dim alto, ancho As Integer 
ancho = Int(bitmapSource.Width / 3) 
alto = Int(bitmapSource.Height / 3) 
For i = 0 To 2 
For j = 0 To 2 
Dim objPicBox As New PictureBox() 
Dim rect As New Rectangle(xR, yR, ancho, alto) 
With objPicBox 
.Width = 100 : .Height = 100 
.Left = x : .Top = y 
.SizeMode = PictureBoxSizeMode.StretchImage 
.BorderStyle = BorderStyle.Fixed3D 
.BackColor = Color.Black 
.Tag = n 
.Text = n 
End With 
Me.Controls.Add(objPicBox) 
AddHandler objPicBox.Click, AddressOf  groupPicBox_Click 
objPicBox.Image = bitmapSource.Clone(rect, bitmapSource.PixelFormat) 
picboxArray(n) = objPicBox 
x += 100 
xR += ancho 
n += 1 
Next 
y += 100 
x = 0 
yR += alto 
xR = 0 
Next 
End Sub

Crearemos una función que se va llamar cada vez que se realice un swap de imágenes siempre y cuando la imagen ya haya sido revuelta y va formar una cadena de caracteres igual a la suma de las propiedades text de los controles del grupo. Cuando esta cadena sea “1234567” significa que el rompecabezas ha sido armado.

Private Sub swap(ByVal index As Short) 
Dim strVecino As String 
Select Case index 
Case 0 
strVecino = "13" 
Case 1 
strVecino = "042" 
Case 2 
strVecino = "15" 
Case 3 
strVecino = "046" 
Case 4 
strVecino = "3175" 
Case 5 
strVecino = "248" 
Case 6 
strVecino = "37" 
Case 7 
strVecino = "648" 
Case 8 
strVecino = "75" 

End Select 
Dim i As Short 
For i = 0 To strVecino.Length - 1 
Dim pos As Short 
pos = CType(strVecino.Chars(i).ToString, Short) 
If IsNothing(picboxArray(pos).Image) Then 
Dim tempPicBox As New PictureBox() 
tempPicBox.Image = picboxArray(index).Image 
picboxArray(index).Image = picboxArray(pos).Image 
picboxArray(pos).Image = tempPicBox.Image 
Dim tempTexto As String = picboxArray(index).Text 
picboxArray(index).Text = picboxArray(pos).Text 
picboxArray(pos).Text = tempTexto 
If revuelto Then 
VerificaArmado() 
End If 
Exit For 
End If 
Next 
End Sub 

Private Sub VerificaArmado()  
Static intentos As Integer 
Dim i As Integer 
Dim cadena As String 
For i = 0 To 7 
cadena &= picboxArray(i).Text 
Next 
If cadena = "01234567" Then 
MsgBox("Felicidades lo armo en " & intentos & " intentos") 
intentos = 0 Controls.Clear() 
crearEscenario() 
revuelto = False i 
nicio() 
Else 
intentos += 1 
End If 
End Sub

Hasta la próxima


ir al índice