Foro de elhacker.net

Programación => Programación Visual Basic => Mensaje iniciado por: WHK en 10 Octubre 2009, 09:15 am



Título: coo saber si existe una variante?
Publicado por: WHK en 10 Octubre 2009, 09:15 am
Hola, tengo un array de datos que varía por lo tanto lo hize variante.
Mas abajo en el código hize un loop para obtener cada variante y procesar los datos pero cuando la variante está vacia marcaría error por lo tanto le puse el siguiente código para verificar si realmente hay variante o no antes de procesar:

Código
  1. If UBound(Imagenes) = 0 Then
  2.  Estado_1.Caption = "No se han localizado imagenes"
  3.  Exit Function
  4. End If

Pero resulta que UBound solo procesa variantes o arrays existentes, por eso me da error cuando esta vacio, por o tanto esa verificación no me sirve.

Como lo puedo hacer?

Y aprovechando el mismo tema... como puedo saber si un control está cargado? por ejemplo image(6).picture como index de 6 sin tener que hacer un for each en cada verificación.

Supongo que habrá alguna función o algo que verifique si alguno de esos dos casos existe, en casoc ontrario tendría que hacer una funcion con un foreach y comenzar a verificar el index contra el valor del index a comprobar  :-\


Título: Re: coo saber si existe una variante?
Publicado por: BlackZeroX en 10 Octubre 2009, 11:10 am
No se me ocurre nada mas, pero para eso puedes llevar registros y evitar usar on error pero si no deseas eso aquí esta con on error

Código
  1. on error goto ErrOut
  2. If UBound(Imagenes) = 0 Then
  3.  Estado_1.Caption = "No se han localizado imagenes"
  4.  Exit Function
  5. End If
  6. Exit function' Exit sub
  7. ErrOut:
  8. msgbox "Error Array Nulo"
  9. err.clear' Solo por si las moscas
  10.  

y lo de objetos argados similar:

Código
  1. Private Sub Form_Load()
  2.    MsgBox cargado(Picture1(4))
  3. End Sub
  4.  
  5. Public Function Cargado(Objeto As Object) As Boolean
  6. On Error GoTo ErrOut
  7.    If Objeto.Index >= 0 Then
  8.        cargado = True
  9.    End If
  10.    Exit Function
  11. ErrOut:
  12.    cargado = False
  13. End Function
  14.  

Dulces Lunas!¡.


Título: Re: coo saber si existe una variante?
Publicado por: seba123neo en 10 Octubre 2009, 18:54 pm
Hola, para saber si un array esta inicializado hay varias formas, te dejo algunas, probalas si te sirven:

Código
  1. Private Sub Form_Load()
  2.    Dim ArrayPrueba() As String
  3.    Dim CadenaPrueba As String
  4.  
  5.    CadenaPrueba = "hola,como,va"
  6.  
  7.    If ((Not ArrayPrueba) = -1) Then
  8.        MsgBox "No esta Inicializado"
  9.    Else
  10.        MsgBox "Si esta Inicializado"
  11.    End If
  12.  
  13.    ArrayPrueba = Split(CadenaPrueba, ",")
  14.  
  15.    If ((Not ArrayPrueba) = -1) Then
  16.        MsgBox "No esta Inicializado"
  17.    Else
  18.        MsgBox "Si esta Inicializado"
  19.    End If
  20. End Sub

otra con la api CopyMemory...

Código
  1. Option Explicit
  2.  
  3. Private Const VT_BYREF = &H4000
  4. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes As Long)
  5.  
  6. Private Sub Form_Load()
  7.    Dim ArrayPrueba() As String
  8.    Dim CadenaPrueba As String
  9.  
  10.    CadenaPrueba = "hola,como,va"
  11.    MsgBox ArrayEstaDimensionado(ArrayPrueba)
  12.  
  13.    ArrayPrueba = Split(CadenaPrueba, ",")
  14.    MsgBox ArrayEstaDimensionado(ArrayPrueba)
  15. End Sub
  16.  
  17. Private Function ArrayEstaDimensionado(ByVal pArray As Variant) As Boolean
  18.    Dim lp As Long, VType As Integer
  19.    If Not IsArray(pArray) Then Exit Function
  20.    Dim nDims As Integer
  21.    CopyMemory ByVal VarPtr(VType), ByVal VarPtr(pArray), 2
  22.    CopyMemory ByVal VarPtr(lp), ByVal (VarPtr(pArray) + 8), 4
  23.    If lp = 0 Then Exit Function
  24.    If (VType And VT_BYREF) <> 0 Then
  25.        CopyMemory ByVal VarPtr(lp), ByVal lp, 4
  26.    End If
  27.    If lp = 0 Then Exit Function
  28.    CopyMemory nDims, ByVal lp, 2
  29.    ArrayEstaDimensionado = CBool(nDims)
  30. End Function

y con la misma api + ArrPtr...

Código
  1. Option Explicit
  2.  
  3. Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long
  4. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
  5.  
  6. Private Sub Form_Load()
  7.    Dim ArrayPrueba() As String
  8.    Dim CadenaPrueba As String
  9.  
  10.    CadenaPrueba = "hola,como,va"
  11.    MsgBox ArrayEstaDimensionado(ArrayPrueba)
  12.  
  13.    ArrayPrueba = Split(CadenaPrueba, ",")
  14.    MsgBox ArrayEstaDimensionado(ArrayPrueba)
  15. End Sub
  16.  
  17. Private Function ArrayEstaDimensionado(pArray) As Boolean
  18.  Dim vValorMemoria As Long
  19.  CopyMemory vValorMemoria, ByVal VarPtr(pArray) + 8, ByVal 4
  20.  CopyMemory vValorMemoria, ByVal vValorMemoria, ByVal 4
  21.  ArrayEstaDimensionado = (vValorMemoria <> 0)
  22. End Function

saludos.



Título: Re: coo saber si existe una variante?
Publicado por: WHK en 11 Octubre 2009, 00:24 am
Hola,
estaba haciendo este proyecto y me puse de metano usar control de errores ya que quiero que mi programa pueda estar preparado ante cualquier defecto y aprender mas, asi que no quisiera tomar por opción forzar un error para saber si el array existe o no asi que tomé la segunda opción que fue como dijo seba123neo:

form:
Código
  1. If Not Es_Array(Imagenes) Then
  2.  Estado_1.Caption = "No se han localizado imagenes"
  3.  Exit Function
  4. End If

Strings.bas:
Código
  1. Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long
  2. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
  3.  
  4. ' .........
  5.  
  6. Public Function Es_Array(Array_data) As Boolean
  7. Dim vValorMemoria As Long
  8. CopyMemory vValorMemoria, ByVal VarPtr(Array_data) + 8, ByVal 4
  9. CopyMemory vValorMemoria, ByVal vValorMemoria, ByVal 4
  10. Es_Array = (vValorMemoria <> 0)
  11. End Function
  12.  
  13. ' ..........

Cuando lo hecho a correr me funciona bién la comprobación cuando si hay valor en el array pero cuando no hay valor el IDE de visual basic se cae lanzando el drwin y cerrandome la ventana.
(http://i.elhacker.net/i?i=4TevuDC-BgEzxS8-hghrq2Vo)

Probaré la otra opción con copymemory


Código
  1. Private Sub Form_Load()
  2.    Dim ArrayPrueba() As String
  3.    Dim CadenaPrueba As String
  4.  
  5.    CadenaPrueba = "hola,como,va"
  6.  
  7.    If ((Not ArrayPrueba) = -1) Then
  8.        MsgBox "No esta Inicializado"
  9.    Else
  10.        MsgBox "Si esta Inicializado"
  11.    End If
  12.  
  13.    ArrayPrueba = Split(CadenaPrueba, ",")
  14.  
  15.    If ((Not ArrayPrueba) = -1) Then
  16.        MsgBox "No esta Inicializado"
  17.    Else
  18.        MsgBox "Si esta Inicializado"
  19.    End If
  20. End Sub

Acá me dice que no coinciden los tipos pero es raro porque si le estoy enviando la variante

form:
Código
  1. Imagenes = Obtiene_imagenes(Text1.Text)
  2.  
  3. If Not Es_Array(Imagenes) Then
  4.  Estado_1.Caption = "No se han localizado imagenes"
  5.  Exit Function
  6. End If

Archivos.bas:
Código
  1. Public Function Obtiene_archivos(Ruta_expreg As String) As String
  2. Dim Archivo As String, temp As String
  3. Archivo = Dir(Ruta_expreg)
  4. While Archivo <> ""
  5.  Archivo = Dir
  6.  If Es_String(Archivo) Then
  7.   Obtiene_archivos = Obtiene_archivos & Archivo & ","
  8.  End If
  9. Wend
  10. End Function
  11.  
  12. Public Function Obtiene_imagenes(Ruta As String) As Variant
  13. Dim Archivos As String, Imagenes As Variant, Cuenta As Integer, Buffer As String
  14.  
  15. ' Obtiene el listado de imagenes con posibles extensiones
  16. Archivos = _
  17.  Obtiene_archivos(Ruta & "*.jpg") & _
  18.  Obtiene_archivos(Ruta & "*.jpeg") & _
  19.  Obtiene_archivos(Ruta & "*.png") & _
  20.  Obtiene_archivos(Ruta & "*.gif")
  21.  
  22. ' Separa en array
  23. Imagenes = Split(Archivos, ",")
  24.  
  25. ' Procesa una por una
  26. For Cuenta = 0 To UBound(Imagenes) - 1
  27.  ' Filtra imagenes de hasta 1.5 MB solamente
  28.  If FileLen(Ruta & Imagenes(Cuenta)) < 1500000 Then
  29.   Buffer = Buffer & Imagenes(Cuenta) & ","
  30.  End If
  31. Next Cuenta
  32.  
  33. ' Retorna solamente si hay imagenes válidas
  34. If Es_String(Buffer) Then
  35.  Obtiene_imagenes = Split(Buffer, ",")
  36. End If
  37. End Function
  38.  
  39.  

Algo pasa que me está dando conflictos en los tipos


Título: Re: coo saber si existe una variante?
Publicado por: seba123neo en 11 Octubre 2009, 00:34 am
si, ese codigo esta malo, a mi me paso lo mismo una vez, proba este por lo que veo es el mejor con api's, te dice si un array ha sido inicilizado o no, y es muy corto el codigo:

CopyMemory: Determining Array Initialization State and Dimensions (http://vbnet.mvps.org/index.html?code/helpers/getarraydims.htm)

saludos.


Título: Re: coo saber si existe una variante?
Publicado por: WHK en 11 Octubre 2009, 00:54 am
ahora veo porque no funcionaba, tu le pasas arrays y yo variantes  :P

edito:
bueno me aburrí, traté de pasar de variantes a array como una variable temporal antes de procesar pero tenia el mismo problema si la variante estaba vacia, decia que los tipos no coincidian porque se considera la variante como un string nulo y tampoco puedo devolver arrays desde una función porque tendria que declararlo como string y hacerle redim a la función con string_r() as string y eso no se puede asi que me resigné y voy a tener que utilizar errores forzados para hacer las comprobaciones como decia blackzero.
talves por eso todo lo de windows funciona a base de errores xD

Código
  1. Public Function Es_Array(Array_data) As Boolean
  2. On Error GoTo Error
  3. If UBound(Array_data) > 0 Then
  4.  Es_Array = True
  5.  Exit Function
  6. End If
  7. Error:
  8. Es_Array = False
  9. End Function

Gracias por el tiempo.