|
Curso básico
de programación en Visual Basic
Lección
25
Otros
evemtos
|
Realizamos
programas para la gestión de empresas. Empresas medianas y
pequeñas. Programas de contabilidad, cartera de pedidos
clientes proveedores, facturación control de albaranes,
tesorería cartera de cobros y pagos y estadísticas.
Nuestro
agradecimiento a todos los que por unas causas o por otras
visitan nuestra web. Gestión de empresas PYMES. Curso de
programación de Visual Basic.
|
Si esto de los
números de las entregas fuese como los años de un matrimonio, con
esta cumpliríamos las bodas de plata, pero esto no es ningún
matrimonio ni nada que se le parezca... o casi, ya que es casi como
un compromiso entre tú, el lector, y yo, el profe, así que vamos a
ver si seguimos llevándonos bien para no tener que divorciarnos ni
nada por el estilo.
La mejor forma de llevarnos bien es que cada uno haga lo que tiene
que hacer, tú estudiar y practicar y yo dedicarme a seguir
cumpliendo entregas... que por otro lado son menos pesadas que
cumplir años...
Hoy vamos a
continuar con los eventos, esta será la última de la serie, que ya
está bien.
En la próxima entrega haremos un pequeño repaso a cómo se deben
declarar las variables y algunos otros consejos que espero que sigas
a pies juntillas, o al menos los tenga casi siempre presentes... ya
verás a que me refiero, pero ahora vamos a ver esos cuantos eventos
que en algunos casos es conveniente saber utilizar.
Otros eventos.
Ya habrás
comprobado que eventos hay para casi cualquier cosa, muchos de ellos
no se suelen usar de forma habitual, y siquiera los habituales. La
razón es porque no siempre es necesario interceptar todos los
avisos que nos envían los controles. Según el tipo de control y en
ciertas de estancias se usan unos u otros pero aún no he visto
ninguna aplicación que necesitara manipular todo, qué digo todo,
ni siquiera la mitad de ellos. Creo que sería una locura.
Hay que saber que
algunos eventos son procesados por los controles o formularios
cuando ese control o formulario está activo o recibe el foco,
mientras esto no ocurra, el susodicho control estará en standby.
Evento GotFocus.
Cuando un control
se convierte en activo y recibe el foco, produce el evento GotFocus,
es decir que tiene el foco de atención del usuario; de igual forma,
cuando deja de ser el control activo, hace sonar la alarma mediante
el evento LostFocus.
El control en el que suele usarse estos eventos, de forma más
habitual, es el TextBox.
Normalmente en el evento de GotFocus se suele seleccionar todo el
texto que contenga, para hacerlo, como ya vimos con
"profusión" en la entrega
anterior, se suele usar un código como este:
Private Sub Text1_GotFocus()
With Text1
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub
Aunque ya deberías
saberlo, te vuelvo a repetir lo que hacen esas líneas de código:
| .SelStart
= 0 |
Le indica al control que la posición
de inicio del texto seleccionado empiece por la posición
cero, es decir la primera letra. |
| .SelLength
= Len(.Text) |
SelLength es la longitud del texto
seleccionado y el valor que se le asigna es la longitud
total del texto que haya en el control. |
Por tanto lo que se
hace es seleccionar todo el contenido del TextBox, las propiedades
SelStart y SelLength también se podrían usar para saber cuál es
el texto que hay seleccionado y poderlo usar en los casos de
búsqueda y sustitución de palabras. Pero hay otra forma más
rápida de saberlo, mediante la propiedad SelText
del TextBox, con esta propiedad nos indica que texto es el que está
seleccionado en ese momento.
Para almacenar en una variable el texto que actualmente está
seleccionado, haremos esto:
'Guardar en sBuscar el texto seleccionado en Text1
sBuscar = Text1.SelText
Evento LostFocus.
En el evento
LostFocus se suele comprobar si el contenido es el que se espera que
haya. Realmente es un pequeño problema el tener que validar los
datos en este evento, ya que cuando se producen, inmediatamente hay
otro control que recibe el foco y si resulta que los datos
contenidos en ese control no son los que esperábamos se intente
volver a darle el foco a este control, con lo cual se produciría un
evento LostFocus en el control que recibió el foco cuando el
primero lo perdió y si en ese segundo control también hay una
comprobación de datos y éstos son erróneos, tendremos tal cacao
que el pobre Visual Basic se terminará quejándose.
Aunque el que se habrá quejado
habrá sido tú, ya que me imagino que no te has enterado de
lo que acabo de decir, pero no te voy a dar un ejemplo para
que lo entiendas, en vez de eso, te voy a poner un ejercicio y así
de camino practicas un poco.
Crea un proyecto
nuevo, en el Form inserta dos TextBox y CommandButton, el botón se
usará para salir del programa, en cada uno de los TextBox se
comprobará que el contenido no esté vacio y no se permitirá salir
del TextBox en cuestión si el contenido no es el que esperamos que
sea, por ejemplo, podrías hacer que el primero sólo admita
números y el segundo sólo letras. Aunque esto se podría hacer de
otra forma, prefiero que lo hagas en el LostFocus, para que
practiques.
Pero como te digo, si lo prefieres, puedes validar cualquier otra
cosa, por ejemplo que tenga algo escrito o cualquier otra cosa que
se te ocurra... yo no suelo validar casi nada en esos eventos ya que
normalmente suelen dar más quebraderos de cabeza que ventajas. Pero
de lo que se trata es que seas tú el que decida
que es lo mejor o peor para tus programas, esto es
extensible a cualquier otra cosa que yo u otra persona pueda
decirte: evalúalo primero y después decide si es lo que realmente
te hace falta.
Para que realmente
funcionen esas comprobaciones, asignales una cadena vacia nada más
cargarse el formulario y añade también código al botón de salir
para que descargue el formulario, así podrás comprobar que hasta
que no se cumplan las condiciones especificadas, no dejará de
"pitarte" para que escribas lo que debes escribir.
Por supuesto, estas comprobaciones se harán en los eventos
LostFocus de cada control y si el contenido no cumple las
condiciones que esperamos, habrá que volver a darle el foco, usando
el método SetFocus, además de un Beep
para que sepamos que los datos contenidos no son válidos.
El código a usar sería algo como
esto:
Private Sub Text1_LostFocus()
'...
'Si el contenido del control no es válido entonces
Beep
Text1.SetFocus 'Volvemos a darle el foco
End Sub
Pruébalo y verás
cómo ahora entenderás lo que digo, y si no lo entiendes al menos
habrás visto cómo el Visual Basic se queja.
Bueno, vale, te
pongo el código que no permitirá que los TextBoxes estén vacios y
si está al cambiar de control, se quedará en ese, pero como te he
dicho, esto volverá loco al VB.
'----------------------------------------------------
'Pruebas para la entrega veinticinco del curso básico
'----------------------------------------------------
Option Explicit
Private Sub Form_Load()
'Borramos el contenido de los TextBox
Text1 = ""
Text2 = ""
'Hacemos que el Text1 sea el primero en recibir el foco
Text1.TabIndex = 0
End Sub
Private Sub cmdSalir_Click()
Unload Me
End Sub
Private Sub Text1_LostFocus()
'No permitir que el TextBox esté vacio
If Len(Trim$(Text1)) = 0 Then
Beep
Text1.SetFocus
End If
End Sub
Private Sub Text2_LostFocus()
'No permitir que el TextBox esté vacio
If Len(Trim$(Text2)) = 0 Then
Beep
Text2.SetFocus
End If
End Sub
Ejecuta el
programa, el foco lo tendrá el primer cuadro de texto, sin escribir
nada, pulsa la tecla TAB para cambiar al otro control, verá cómo
el VB se vuelve turuta... Tendrás que pulsar
Control+Break (Cttl+Inter) para pararlo...
En la versión 6
del VB se incluye un nuevo evento: Validate que
será el que se use para "validar" el contenido de un
TextBox, en lugar de hacerlo en el evento LostFocus. Sobre este
evento ya veremos algo más adelante (en unas cuantas celebraciones
más), aunque dentro de poco lo podrás ver en la sección sobre el
VB6 que tengo en mis páginas, las cuales seguramente se sumarán en
su momento a este curso... cuando les toque el turno.
Evento Change.
Otro evento
relacionado con los controles que permiten introducir información
es: Change. Este evento se disparará siempre que
el contenido del control cambie, por tanto en un TextBox se
producirá si lo que hay en la propiedad Text cambia.
Esto ya lo vimos en las primeras entregas, además de cómo no usar
este evento, para que no diese un error de desbordamiento de la
pila.
Arrastrar y Soltar
controles y otros "objetos".
Pero no creas que
esto terminar aquí ya que te voy a explicar algo sobre cómo
arrastrar y soltar, ya que ésta es una de las peculiaridades del
entorno Windows y es una de las cosillas que deberías de tener
siempre en tus aplicaciones. Aunque el ejemplo y la explicación que
te voy a dar es para el Visual Basic 5, si quieres ver cómo se hace
con la versión anterior te recomiendo que te leas los trucos de mis
páginas.
También te voy a dar un ejemplo de cómo hacer que se puedan mover
los controles de tamaño y o posición dentro del formulario, en
tiempo de ejecución, claro. No es perfecto, pero medio funciona, el
problema que tiene es que hay que codificar en muchos eventos, pero
para ello he creado unos procedimientos para hacer menos tedioso el
tema...
La "versión" que tenía antes de esta
"utilidad", no permitía que se soltara un control encima
de otro, sólo permitía que se soltasen en el formulario, osea, si
en la nueva posición había otro control, no se dejaba en ese
sitio...
Pero como te digo, ahora va mucho mejor... después de el evento
OLEDragDrop veremos el código y un poco de explicación.
Evento OLEDragDrop.
Veamos primero
cómo hacer que nuestra aplicación permita que se suelte un fichero
y cuando se haga se muestre en un TextBox, por tanto no pruebes con
ficheros que no sean de texto.
Para poder hacer esto, hay que asignar las siguientes propiedades
del Form y del TextBox que mostrará el texto:
OLEDropMode = 1 ' Manual
El TextBox debería ser Multiline para que se muestre bien el
fichero soltado.
Para asignar a un TextBox el primer
fichero de los que se sueltan en un formulario o cualquier control
que tenga la propiedad OLEDropMode igual a uno, vamos a usar un
procedimiento genérico, se supone que será para ficheros de texto,
incluso documentos RTF si el control en cuestión es un
RecichTextBox.
Private Sub AsignarFichero(unTextBox As Control)
'Asignar al TextBox indicado el contenido del fichero soltado
Dim sFic As String
Dim nFic As Long
Dim sText As String
'Asignar sólo el primer fichero
sFic = Data.Files(1)
'Abrirlo y leer el contenido
nFic = FreeFile
Open sFic For Input As nFic
sText = Input$(LOF(nFic), nFic)
Close nFic
'Asignarlo al control indicado
unTextBox = sText
End Sub
Para usar este
procedimiento, lo llamaremos desde el evento OLEDragDrop
del formulario y del control en cuestión:
Private Sub Form_OLEDragDrop(Data As DataObject, Effect As Long, _
Button As Integer, Shift As Integer, X As Single, Y As Single)
AsignarFichero Text3
End Sub
Private Sub Text3_OLEDragDrop(Data As DataObject, Effect As Long, _
Button As Integer, Shift As Integer, X As Single, Y As Single)
AsignarFichero Text3
End Sub
Ahora ya puedes
"soltar" un fichero de texto en el formulario o el TextBox
y se mostrará el contenido en ese TextBox.
Evento DragDrop y propiedad
Drag
Ejemplo
de cómo redimensionar y mover controles en tiempo de ejecución.
Ahora vamos a ver
cómo mover controles por el formulario y soltarlos en la posición
deseada. También vamos a ver cómo, mediante el uso de una llamada
al API de Windows, podemos hacer que un control sea
"redimensionable", la única pega para hacer que sea
redimensionable, o si lo prefieres, la única condición, es que el
control sea una "ventana", no te confundas, los controles
en Visual Basic son controles, pero el Windows trata a algunos de
ellos como si fuesen ventanas, por ejemplo el control TextBox es
para Windows una ventana, sin embargo el control Label no lo es.
Normalmente se puede saber si un control es "ventanero" si
tiene la propiedad hWnd, ya que los que no son
realmente una ventana, no tienen esa propiedad.
Veamos el código y
las declaraciones para hacer que todo esto pueda funcionar.
Primero te explico
que en cada control hay que hacer lo siguiente en los eventos
MouseDown y DragDrop, salvo en el Form, como veremos después, ya
que en el Form sólo se detectará la acción de soltar el control:
Private Sub NombreDelControl_DragDrop(Source As Control, X As Single, _
Y As Single)
EndDragDrop NombreDelControl, Source, X, Y
End Sub
Private Sub NombreDelControl_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag NombreDelControl, Button, X, Y
End Sub
En los controles que no
queramos permitir que se suelte, hay que "cancelar" la operación de
Drag & Drop, por ejemplo, si tenemos un botón y no queremos que se suelte
encima, habría que hacer algo como esto:
Private Sub cmdSalir_DragDrop(Source As Control, X As Single, Y As Single)
'Cancelar la acción de soltado
CancelarDrag Source
End Sub
El procedimiento de calcular
la nueva posición se encarga de hacer las comprobaciones pertinente para
posicionar adecuadamente el control soltado; si el control que se mueve, está
contenido a su vez en otro control, no se permite que se mueva fuera de su
contenedor. Esta forma de actuar puedes cambiarla si quieres, aunque deberías
tener en cuenta que el contenedor debe ser el control de destino o el
formulario en caso de que se suelte sobre el form, también podrías hacer que
al soltarse un control en otro, el que recibe el control fuese el contenedor...
todo es cuestión de que hagas pruebas y lo adecues a tus gustos.
Una cosa que debes tener en
cuenta si quieres mover los TextBox, es que no te permitirá seleccionar el
texto usando el ratón, ya que al pulsarse con el ratón se llama al
procedimiento que "avisa" que se está haciendo el Drag&Drop y al
dejarlo "invisible", pierde el foco, aunque esto se soluciona en el
procedimiento que calcula la nueva posición, podrías querer que no se pueda
mover, ese es el caso del Text4 del ejemplo que pongo a continuación.
Ahora veamos el código de
este ejemplo,
el código lo puedes conseguir pulsando en este
link: codigo25.zip (6.62 KB)
'----------------------------------
'Prueba para redimensionar Pictures
' y mover controles
'
'©Guillermo 'guille' Som,
'----------------------------------------
Option Explicit
Dim frmName As String
Dim DY As Single
Dim DX As Single
Dim NumColumnas As Integer
Dim NumFilas As Integer
Dim bIniciando As Boolean
'Declaraciones del API para 32 bits
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32" _
(ByVal hWnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cX As Long, ByVal cY As Long, _
ByVal wFlags As Long) As Long
Const GWL_STYLE = (-16)
Const WS_THICKFRAME = &H40000
'
Const SWP_DRAWFRAME = &H20
Const SWP_NOMOVE = &H2
Const SWP_NOSIZE = &H1
Const SWP_NOZORDER = &H4
Private Sub CmdSalir_Click()
Unload Me
End Sub
Private Sub cmdSalir_DragDrop(Source As Control, X As Single, Y As Single)
'Cancelar la acción de soltado
CancelarDrag Source
End Sub
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single)
'Cuando se suelta en el form, no especificar el destino
EndDragDrop Source, X, Y
End Sub
Private Sub Form_Load()
bIniciando = True
'Asignamos el nombre del formulario, ya que lo necesitaremos
'para saber si se mueve encima del form o de otro control
frmName = Me.Name
'Hacer estos controles redimensionables,
'usando el API
CambiarEstilo PicColum(0)
CambiarEstilo Text2
CambiarEstilo Picture1
CambiarEstilo Frame1
CambiarEstilo Picture3
CambiarEstilo Picture4
CambiarEstilo Text4
Text3 = "Left= " & Text3.Left & ", Top= " & Text3.Top
'Para crear filas/columnas en un Control
NumFilas = 2
Label1(0) = "Cabecera de la colunma"
Load Text1(1)
With Text1(1)
Set .Container = PicColum(0)
.Visible = True
.Top = Text1(0).Top + Text1(0).Height
End With
Load Label2(1)
With Label2(1)
.Visible = True
.Top = Label2(0).Top + Label2(0).Height
.Caption = "Fila 2"
End With
NumColumnas = 1
bIniciando = False
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Text2.Text = "X= " & Str$(X) & ", Y= " & Str$(Y)
End Sub
Private Sub Frame1_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Frame1
End Sub
Private Sub Frame1_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Frame1, Button, X, Y
End Sub
Private Sub Label1_DragDrop(Index As Integer, Source As Control, _
X As Single, Y As Single)
EndDragDrop Source, X, Y, Label1(Index)
End Sub
Private Sub Label2_DragDrop(Index As Integer, Source As Control, _
X As Single, Y As Single)
EndDragDrop Source, X, Y, Label2(Index)
End Sub
Private Sub PicColum_DragDrop(Index As Integer, Source As Control, _
X As Single, Y As Single)
EndDragDrop Source, X, Y, PicColum(Index)
End Sub
Private Sub PicColum_Resize(Index As Integer)
Dim k As Integer
Dim i As Integer
If bIniciando Then Exit Sub
'ajustar el ancho del Label y los texts
Label1(Index).Width = PicColum(Index).Width
For i = 0 To NumFilas - 1
k = i * NumColumnas + Index
Text1(k).Width = PicColum(Index).Width
Next
PicColum(0).Left = Label2(0).Width
For i = 0 To NumColumnas - 1
If i > 0 Then
PicColum(i).Left = PicColum(i - 1).Left + PicColum(i - 1).Width
End If
PicColum(i).Top = 0
Next
End Sub
Private Sub Picture1_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Picture1
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Picture1, Button, X, Y
End Sub
Private Sub Picture2_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Picture2
End Sub
Private Sub Picture2_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Picture2, Button, X, Y
End Sub
Private Sub Picture3_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Picture3
End Sub
Private Sub Picture3_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Picture3, Button, X, Y
End Sub
Private Sub Picture4_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Picture4
End Sub
Private Sub Picture4_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
IniciarDrag Picture4, Button, X, Y
End Sub
Private Sub Text1_DragDrop(Index As Integer, Source As _
Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Text1(Index)
End Sub
Private Sub Text2_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Text2
End Sub
Private Sub Text2_DragOver(Source As Control, X As Single, _
Y As Single, State As Integer)
'Si no se quiere que pase por encima otro control
'CancelarDrag Source
End Sub
Private Sub Text2_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Text2, Button, X, Y
End Sub
Private Sub Text3_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Text3
End Sub
Private Sub Text3_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
IniciarDrag Text3, Button, X, Y
End Sub
Private Sub Text4_DragDrop(Source As Control, X As Single, Y As Single)
EndDragDrop Source, X, Y, Text4
End Sub
Private Sub Text4_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
'Si se quiere poder seleccionar con el ratón
'quitar la siguiente llamada, aunque entonces no se permitirá
'mover el control
'IniciarDrag Text4, Button, X, Y
End Sub
Private Sub CambiarEstilo(queControl As Control)
Dim Style As Long
On Local Error Resume Next
Style = GetWindowLong(queControl.hwnd, GWL_STYLE)
If Err Then
Err = 0
MsgBox "El control " & queControl.Name & " no permite que se redimensione", vbInformation
Exit Sub
End If
Style = Style Or WS_THICKFRAME
Style = SetWindowLong(queControl.hwnd, GWL_STYLE, Style)
Style = SetWindowPos(queControl.hwnd, _
Me.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME)
End Sub
Private Sub CancelarDrag(Source As Control)
Source.Visible = True
Source.Drag vbCancel
End Sub
Private Sub EndDragDrop(Source As Control, X As Single, Y _
As Single, Optional Dest As Object)
Dim posX As Long
Dim posY As Long
If Dest Is Nothing Then
'Si no se especifica el control de origen,
'por ejemplo cuando se suelta en el formulario
posX = -30
posY = -30
'Si el nombre del contenedor del Source no es el nombre
'del destino, no moverlo.
'Esto ocurrirá cuando se mueve un control contenido en otro
'y el destino no es el control que lo contiene
If Source.Container.Name <> frmName Then
CancelarDrag Source
Exit Sub
End If
Else
'Si el control destino es el mismo que el contenedor del Source
'Esto ocurrirá cuando el control que se mueve se suelta
'en el control en que está contenido
If Dest.Name = Source.Container.Name Then
posX = -60
posY = -60
Else
'Si el nombre del contenedor del Source no es el nombre
'del destino, no moverlo.
'Esto ocurrirá cuando se mueve un control contenido en otro
'y el destino no es el control que lo contiene
If Source.Container.Name <> frmName Then
CancelarDrag Source
Exit Sub
End If
With Dest
'El nombre del formulario se asignará
'a la variable frmName
If .Container.Name = frmName Then
'Esto ocurrirá cuando se suelte un control
'en otro que esté contenido en el formulario,
'no contenido en otro control
posX = .Left
posY = .Top
Else
'Esto ocurrirá cuando se suelte en un control
'que está contenido en otro control
posX = .Container.Left + .Left + 60
posY = .Container.Top + .Top + 60
End If
End With
End If
End If
'Posicionar el control soltado
With Source
.Visible = True
.Move posX + X - DX, posY + Y - DY
.Drag vbEndDrag
.ZOrder
End With
'Si el Source es un textbox, darle el foco
If TypeOf Source Is TextBox Then
Source.SetFocus
End If
'Si se van a usar RichTextBox, hacer la comparación correspondiente
End Sub
Private Sub IniciarDrag(Source As Control, Button As Integer, X As Single, Y As Single)
If Button = vbLeftButton Then
DX = X
DY = Y
Source.Drag vbBeginDrag
'Cambiar a no visible, ya que si no,
'el form no detectaría que se ha soltado,
'si el puntero del ratón no sale del control.
Source.Visible = False
Source.Drag
End If
End Sub
Hasta aquí ha
llegado esta "entrega de plata", si quieres hacer un
comentario, guárdatelo para otra ocasión... je, je.
Parte de esta
entrega la tenía escrita desde el 15 de julio de 1998, en total un
folio manuscrito por las dos caras y pasado al Word usando el
ViaVoice de IBM que aunque no me entiende, (seguramente porque yo no
"dicto" bien), algo es algo y en cuanto le enseñe a
entenderme seguramente las entregas llegarán con mayor rapidez.
Aunque es algo "lentillo" y la verdad es que el código no
hay forma de hacérselo entender, pero seguiré probando a ver si
logro que algún día sepa de que le estoy hablando... al menos me
rio un poco de lo que escribe cuando no me entiende...
Hasta la próxima que será...
imagínatelo...
Nos vemos.
|