Durante todos estos años que llevo "computerizado" me he topado con algún que otro fallo en los discos duros y disquetes, además de los que causan los programas cuando se "cuelgan"; todo esto acarrea pérdidas de datos...
Me imagino que esto no sólo me ha pasado a mi, por desgracia es algo que casi todos hemos experimentado.
¿A ti no? Pues, una de dos, o es que eres extremadamente precavido/a o es que llevas poco tiempo en esto... en cualquier caso serás una excepción.
Antes mis copias de seguridad las hacia en disquetes, algunas veces usando el típico programa de copia de seguridad, otras usando algún compresor, (el PKZIP ha sido siempre un asiduo de mis disquetes de utilidades), pero también he hecho "copias a pelo", es decir, simplemente copiando los ficheros de un sitio a otro.
Antes del Windows 95 y los nombres largos, usaba el Comandante Norton para MS-DOS, (otro programa habitual en mis discos de utilidades), este programa tiene una opción que sirve para comparar el contenido de dos directorios, "marcando" los ficheros que son diferentes.
Durante mucho tiempo he usado esta utilidad, pero los nombres largos son un "pequeño" inconveniente, ya que no entiende de nombres largos y estos se pierden. Ahora hay una para Windows95, pero la verdad es que es un poco engorrosa de usar y lo poco que he probado no me termina de convencer.
Hacer una aplicación que maneje nombres largos, realmente no es un inconveniente, sobre todo si la programamos con el Visual Basic de 32 bits. Otra cosa es hacerla para que funcione en MS-DOS, por ejemplo con el QuickBasic, aunque también me fabriqué una utilidad que me sirviera en MS-DOS con este lenguaje... realmente la tengo hecha con la versión 7 de este compilador para MS-DOS. Pero no te preocupes que la que vamos a realizar aquí es para Windows y con el Visual Basic 5, aunque con pequeños retoques, al menos en lo que a las clases usadas se refiere, podrás crearla con el VB4-32 bits.
El concepto de esta utilidad
Lo que vamos a hacer, o al menos lo que te voy a explicar, para conseguir el objetivo de esta utilidad es usar, básicamente, dos controles FileList, además de los correspondientes controles para manejar la unidad y directorios, ya que vamos a necesitar seleccionar los directorios que vamos a comparar, sino no sería una utilidad para comparar directorios...
En cada uno de estos controles estarán los ficheros que queremos comparar. Una vez que tengamos el contenido de los dos directorios que queremos comparar, lo que haremos será comparar cada uno de los ficheros con todos los que estén en el otro directorio, si encontramos uno con el mismo nombre, comprobaremos la fecha y "marcaremos" el que tenga la fecha más reciente. En caso de que el fichero no esté en el otro directorio, también quedará marcado.
De esta forma, una vez comprobados todos los ficheros, se quedarán seleccionados los ficheros que sean diferentes (más recientes y los que no estén).
Una vez comprobados los ficheros, podremos hacer varias cosas con los que estén seleccionados, copiarlos, moverlos y eliminarlos.
Como opciones extras, podremos invertir la selección realizada, seleccionar todos o quitar la selección.
Por supuesto que también permitirá la selección manual de ficheros.
Lo que no hará esta utilidad, será "Drag & Drop", así que no creo que Microsoft conceda el "logo" de compatibilidad Win95.
Pero esto será algo que en un futuro implementaré y te mostraré cómo hacerlo. Ya que prefiero empezar por algo fácil y comprensible y siempre habrá tiempo para mejorarla.
Las piezas de la utilidad
Para conseguir nuestro propósito, además de que así aprendas otros conceptos de programación, que es de lo que realmente se trata, vamos a usar una serie de clases y colecciones con las que manipularemos la información de los ficheros de cada directorio.
Las clases que usaremos serán tres:
- Una básica para almacenar cada uno de los ficheros.
- En otra guardaremos el nombre de cada directorio y todos los ficheros de ese directorio.
- La tercera contendrá los dos directorio que queremos comparar o manipular.
La clase básica, se llama cFichero y tiene estas propiedades:
Propiedades Descripción ID Clave única para almacenar en la colección. Nombre El nombre del fichero, sin la ruta. Tamaño Tamaño en bytes del fichero. FechaHora La fecha y hora de este fichero. Seleccionado Un valor Verdadero/Falso que indica si está seleccionado o no. El tamaño, en principio no lo vamos a usar para nada, para lo que si que puede servir es en el caso de que se quiera mostrar información extra o bien que se use un control ListView para mostrar la información de los ficheros. Pero en esta primera aproximación no se empleará.
La clase que contendrá la colección de los ficheros de un directorio se llama: cDirectorio y sus propiedades y métodos son:
Propiedades / Métodos Descripción ID Clave única para almacenar en la colección. Nombre El nombre del directorio o ruta del directorio. Ficheros Colección de los ficheros de este directorio. HaySeleccionados Nos indicará si hay algún fichero seleccionado. Eliminar Servirá para eliminar el contenido de la colección de ficheros.
Por último, la clase cUnidad será la que contenga los directorios usados. Aunque en principio sólo serán dos, puede contener todos los directorios que la memoria del sistema nos permita, pero nuestra aplicación sólo usará dos.
Propiedades / Métodos Descripción Directorios Colección de los directorios usados. CompararDirectorios Compará el contenido de los directorios indicados en los parámetros y seleccionará los que sean distintos o no estén en el otro.
Este tipo de utilidad es muy propia para el empleo de ventanas MDI, pero como sólo vamos a usar dos, no será necesario, aunque hay que hacerle ver al usuario con que directorio va a trabajar.
Habrá dos paneles, cada uno de ellos contendrá los controles necesarios para manipular los directorios a comparar y/o manipular.
Para contener estos controles, vamos a usar un frame.
Los controles empleados en cada uno de los frames serán: un control DriveListBox, un DirListBox, un FileListBox y unos cuantos Labels. Todos estos controles formará parte de un array, de esta forma será más fácil acceder a cada uno de ellos sin tener que hacer comprobaciones extras.
Las acciones que se ejecutarán, se harán sobre el panel activo, por tanto necesitaremos que se vea de forma clara cual es el que está activo en cada momento. Para ello usaremos un label que al estar activo mostrará los colores que tenga la barra de una ventana activa y cuando no esté activo, estos colores cambiarán al que estén definidos como inactivos. Siempre usando los colores que el usuario ha seleccionado en las propiedades del escritorio. Esta es una norma que deberíamos emplear siempre y que el VB5 facilita gracias al uso de unas constantes que hacen referencia a estos colores.
Además de este "caption" al estilo de las ventanas, también indicaremos cual es el activo o inactivo cambiando la propiedad Enabled de los controles de manejo de ficheros/directorios/unidad, aunque sólo será "más" visible en el control FileListBox.Estos efectos del caption se manipulan tanto al pulsar sobre cualquiera de los frames como en la etiqueta que simula el caption de la ventana, en el evento Click de estos controles se llama a un procedimiento que es el que se encarga de esta tarea, veamos el código usado para coseguirlo:
Private Sub Frame1_Click(Index As Integer) ActivarPanel Index End Sub Private Sub lblCaption_Click(Index As Integer) ActivarPanel Index End Sub Private Sub ActivarPanel(ByVal Index As Integer) 'Activar el panel activo y desactivar el otro Dim i% DirActivo = Index + 1 With lblCaption(Index) .ForeColor = vbTitleBarText .BackColor = vbActiveTitleBar End With File1(Index).Enabled = True Drive1(Index).Enabled = True Dir1(Index).Enabled = True 'El otro frame i = -1 * (Index = 0) With lblCaption(i) .ForeColor = vbInactiveCaptionText .BackColor = vbInactiveTitleBar End With File1(i).Enabled = False Drive1(i).Enabled = False Dir1(i).Enabled = False End SubEn este procedimiento también se asigna a la variable DirActivo cual es el directorio activo, esta variable se usará en otros procedimientos y eventos para saber la colección de ficheros a usar y que controles son de los que hay que tomar los datos.
De todas formas, para evitar cualquier tipo de descuido o metedura de pata, antes de efectuar una acción sobre los ficheros, se mostrará un cuadro de diálogo que pedirá confirmación de la acción a realizar.
Aunque no vendrá mal que prestemos atención a estos avisos, ya que un despiste puede causar que se borre accidentalmente el contenido de un directorio. Pero este tipo de utilidades tienen ese "inconveniente", ya que de lo que se trata es de manipular ficheros...Aunque también podríamos "curarnos en salud" y usar funciones del API que al borrar ficheros los mande a la papelera de reciclaje, pero eso será cuestión de cambiar el KILL que se usa para borrar y sustituirlo por la correspondiente llamanda a la función ShellDelete la cual puedes copiar de la página del API.
De todas formas hay que ser conscientes de que no estamos programando un juego, vamos a manipular ficheros y no es cuestión de juguetear y hacer las cosas con "conciencia".
Como yo soy un gran "despistado", he puesto, en los casos de Eliminar y Mover, el botón que ACEPTA la acción como botón no predeterminado, así habrá algo de más "mala cabeza" a la hora de meter la pata.El formulario no permite que se cambie de tamaño y siempre se muestra centrado en la pantalla, se podría mejorar permitiendo el cambio de tamaño y adaptar los controles al nuevo tamaño, pero como ya dije antes, la intención es hacer algo sencillo y que te sea fácil de seguir, para que no te pierdas en cosas extras que lo único que hacen es mejorar el look pero no la utilidad del programa. Todo esto puede que esté en una nueva versión de esta utilidad.
El aspecto del programa.
Este es el diseño que mostrará de cara al usuario:
Figura 1 - Aspecto del programa en ejecuciónLas distintas acciones a realizar están incluidas en el menú Archivo, cada una de ellas lleva asociada una tecla de acceso rápido, básicamente he usado las disponibles en el Comandante Norton, al menos para las operaciones de Copiar (F5), Mover (F6) y Eliminar (F8), aunque en este último caso podría ser más intuitivo el uso de la tecla Suprimir, pero esto es fácil de cambiar.
Además de estas tres "acciones", desde este menú podremos comparar los directorios, seleccionar todos los archivos, invertir la selección y también quitar la selección. Como extras, están las opciones clásicas Acerca de... y Salir.Este es el aspecto del Menú Archivo:
Figura 2 - Las opciones del menúFijate que hay una serie de opciones que están desabilitadas, estas opciones sólo estarán disponibles cuando haya ficheros seleccionados en el panel activo y en el caso de Copiar y Mover, también estarán inhabilitadas si los directorios de los dos paneles hacen referencia al mismo path.
Esto se consigue en el evento Click del menú de Archivo, ya que antes de mostrar el contenido de un menú se produce ese evento, ahí es un buen sitio para hacer las comprobaciones pertinentes.Private Sub mnuArchivo_Click() mnuCopiar.Enabled = m_Directorio(DirActivo).HaySeleccionados mnuEliminar.Enabled = mnuCopiar.Enabled mnuMover.Enabled = mnuCopiar.Enabled mnuQuitarSelec.Enabled = mnuCopiar.Enabled 'Si son el mismo directorio, no copiar ni mover If m_Directorio(1).Nombre = m_Directorio(2).Nombre Then mnuCopiar.Enabled = False mnuMover.Enabled = False mnuComparar.Enabled = False End If End SubPara saber si deben estar habilitados o no se usa el método HaySeleccionados, el cual devolverá un valor verdadero si alguno de los ficheros está seleccionado.
En el caso de que los dos directorios sean iguales, se deshabilitarán las opciones de Copiar, Mover y la de Comparar, ya que no tiene ninguna utilidad hacer estas operaciones con el mismo directorio.
Las interioridades del programa.
Ahora veamos algunas de las distintas operaciones a realizar con las opciones del menú.
Antes veremos la parte que se encarga de rellenar las colecciones de ficheros.
Para manipular las clases se declara a nivel de módulo una variable de tipo cUnidad:
Dim m_Directorio As cUnidadEn el evento Form_Load es cuando realmente se "carga" esta clase:
Set m_Directorio = New cUnidadAhora que sabemos que m_Directorio es la clase que contiene los directorios, veamos el contenido del menú Comparar:
Private Sub mnuComparar_Click() 'Comparar los archivos de los dos paneles Dim i& 'Asignar los ficheros a la colecciones For i = 0 To 1 CalculaTamaño i Next m_Directorio.CompararDirectorios 1, 2 bCalculando = True 'Mostrar los ficheros seleccionados de los dos directorios With File1(0) For i = 1 To m_Directorio(1).Ficheros.Count .Selected(i - 1) = m_Directorio(1).Ficheros(i).Seleccionado Next End With CalculaTamaño 0 With File1(1) For i = 1 To m_Directorio(2).Ficheros.Count .Selected(i - 1) = m_Directorio(2).Ficheros(i).Seleccionado Next End With CalculaTamaño 1 bCalculando = False End SubAntes de poder comparar los contenidos de los directorios, hay que llenar las colecciones, de ello se encarga el procedimiento del formulario: CalculaTamaño. En este procedimiento también se muestra información del número de ficheros seleccionados además de cuanto espacio ocupan dichos ficheros.
Private Sub CalculaTamaño(ByVal Index As Integer) '---------------------------------------------- ' Calcula el tamaño de los archivos seleccionados ' y rellena la colección correspondiente '---------------------------------------------- Dim i As Integer Dim nSelect As Integer Dim lngTotalSelec As Long Dim lngTotal As Long Dim sTmp As String Const cUnK = 1024& Const cUnMega = 1000& * cUnK Dim iSelected% Index = Index + 1 'Borrar el contenido de la colección m_Directorio(Index).Eliminar 'Asignar el nombre del directorio actual m_Directorio(Index).Nombre = File1(Index - 1).Path Label1(Index - 1) = " No hay archivos" Label1(Index + 1) = "" 'Sólo comprobar si hay archivos If File1(Index - 1).ListCount > 0 Then nSelect = 0 lngTotalSelec = 0 With File1(Index - 1) lblCaption(Index - 1) = " " & .Path sTmp = AddBSlash(.Path) For i = 0 To .ListCount - 1 m_Directorio(Index).Ficheros(i + 1).Nombre = .List(i) m_Directorio(Index).Ficheros(i + 1).Tamaño = FileLen(sTmp & .List(i)) lngTotal = lngTotal + m_Directorio(Index).Ficheros(i + 1).Tamaño m_Directorio(Index).Ficheros(i + 1).FechaHora = FileDateTime(sTmp & .List(i)) m_Directorio(Index).Ficheros(i + 1).Seleccionado = False If .Selected(i) Then iSelected = i m_Directorio(Index).Ficheros(i + 1).Seleccionado = True nSelect = nSelect + 1 lngTotalSelec = lngTotalSelec + m_Directorio(Index).Ficheros(i + 1).Tamaño End If Next ' If lngTotalSelec = 0 Then Label1(Index - 1) = " " & .ListCount & " ficheros " lngTotalSelec = lngTotal ElseIf nSelect = 1 Then Label1(Index - 1) = " " & .List(iSelected) lngTotalSelec = FileLen(sTmp & .List(iSelected)) Else Label1(Index - 1) = " " & nSelect & " ficheros seleccionados " End If If lngTotalSelec > cUnMega Then sTmp = Format(lngTotalSelec / cUnMega, "#,###.##") & " M " ElseIf lngTotalSelec > cUnK Then sTmp = Format(lngTotalSelec / cUnK, "#,###.##") & " K " Else sTmp = Format(lngTotalSelec, "#,### ") End If End With Label1(Index + 1) = sTmp End If End SubEste procedimiento recibe como parámetro el índice del array de controles que debe manipular. Como las colecciones empiezan la numeración por UNO en lugar de CERO, se tiene en cuenta este detalle y por eso se cambia el valor de la variable Index.
El método CompararDirectorio es el que se encarga de hacer las comparaciones pertinentes. Este método forma parte de la clase cUnidad.
Public Sub CompararDirectorios(ByVal dUno As Variant, ByVal dDos As Variant) 'Comparar los archivos de los dos directorios indicados Dim i&, j& Dim tFichero1 As cFichero Dim tFichero2 As cFichero Dim tDir1 As cDirectorio Dim tDir2 As cDirectorio On Local Error Resume Next i = Directorios(dUno).Ficheros.Count j = Directorios(dDos).Ficheros.Count 'El directorio UNO será el que tenga más archivos If i > j Then Set tDir1 = Directorios(dUno) Set tDir2 = Directorios(dDos) Else Set tDir1 = Directorios(dDos) Set tDir2 = Directorios(dUno) End If 'Hay que marcarlos como seleccionados para que se haga 'siempre la comprobación la primera vez que se repita el bucle For Each tFichero2 In tDir2.Ficheros tFichero2.Seleccionado = True Next 'Comparar todos los archivos del directorio 1 con el 2 For Each tFichero1 In tDir1.Ficheros tFichero1.Seleccionado = True For Each tFichero2 In tDir2.Ficheros 'Los NO seleccionados es que ya se sabe que 'son de fechas anteriores If tFichero2.Seleccionado Then If tFichero1.Nombre = tFichero2.Nombre Then 'Tienen el mísmo nombre... 'No seleccionar el más antiguo If tFichero1.FechaHora = tFichero2.FechaHora Then tFichero1.Seleccionado = False tFichero2.Seleccionado = False ElseIf tFichero1.FechaHora < tFichero2.FechaHora Then tFichero1.Seleccionado = False tFichero2.Seleccionado = True Else tFichero1.Seleccionado = True tFichero2.Seleccionado = False End If End If End If Next Next Err = 0 End SubLos parámetros que se usan en este método son los directorios a comparar, aunque en esta utilidad sólo se usan dos, no sería necesario, pero así estará preparada para que puedas, si lo crees conveniente, almacenar más directorios en esta colección.
Fijate que en lugar de usar las colecciones directamente uso unos "punteros" a esas colecciones, esto lo hago por la razón de que la colección que tenga menos ficheros será la segunda a usar, es decir se realizará una comprobación de una de las colecciones con el contenido de la otra, siendo ésta última la que tenga menos ficheros... no es que acelere el tema, pero de esta forma puedes ver mejor cómo manejar las clases y colecciones.Una vez que se han comparado los ficheros de los dos directorios, hay que mostrarlos en los controles correspondientes, de eso se encargan los bucles que asignan la propiedad Selected(xxx) del ListBox.
Las acciones a realizar.
Ahora vamos a ver el código usado para las distintas opciones del menú.
Empezaremos por las más simples, las de seleccionar todo, invertir la selección y quitar las selecciones.
Private Sub mnuSeleccionarTodo_Click() 'Seleccionar todos los del directorio activo Dim i& bCalculando = True With File1(DirActivo - 1) For i = 0 To .ListCount - 1 .Selected(i) = True Next End With CalculaTamaño DirActivo - 1 bCalculando = False End Sub Private Sub mnuQuitarSelec_Click() 'invertir la selección del directorio activo Dim i& bCalculando = True With File1(DirActivo - 1) For i = 0 To .ListCount - 1 .Selected(i) = False Next End With CalculaTamaño DirActivo - 1 bCalculando = False End Sub Private Sub mnuInvertir_Click() 'invertir la selección del directorio activo Dim i& bCalculando = True With File1(DirActivo - 1) For i = 0 To .ListCount - 1 .Selected(i) = Not .Selected(i) Next End With CalculaTamaño DirActivo - 1 bCalculando = False End SubFijate que en todas ellas se cambia el valor de la variable bCalculando, esta variable de tipo Boolean, se usa para que al producirse el evento File1_Click no se ejecute el código de ese evento. Esto se produce al cambiar el valor de .Selected(i) y para ser sinceros, me dió más de un quebradero de cabeza...
Este es el código de ese evento:Private Sub File1_Click(Index As Integer) 'Para evitar que se produzca un click cuando 'se cambia la propiedad Selected() ' If bCalculando Then Exit Sub 'Asignar los nombres a la colección CalculaTamaño Index End SubY todo es porque dentro de este evento se llama al procedimiento de calcular tamaño.
¿Por qué lo pongo en este evento?
Porque cuando se cambia de unidad o de directorio hago una llamada a este evento, además de que de esta forma se pueden seleccionar manualmente ficheros.A continuación tienes el código de los eventos Change de los controles Dir y Drive para que veas cómo va esto:
Private Sub Drive1_Change(Index As Integer) 'Cambiar la unidad de disco 'Si la unidad no está preparada, dará error On Local Error Resume Next Dir1(Index).Path = Drive1(Index).Drive If Err Then Drive1(Index).Drive = Dir1(Index).Path End If File1_Click Index Err = 0 End Sub Private Sub Dir1_Change(Index As Integer) 'Cambiar de directorio File1(Index).Path = Dir1(Index).Path Drive1(Index).Drive = Dir1(Index).Path File1_Click Index GuardarIni sFicIni, "Directorios", "Dir" & CStr(Index), Dir1(Index).Path End SubFijate que al cambiar de Directorio se actualiza un fichero de configuración, esto es para que se pueda mostrar, la próxima vez que se entre en el programa, el último directorio al que hemos accedido.
Por supuesto que al iniciar el programa hay que leer esa información, esto se hace en el Form_Load.
Y como debemos contar que la última unidad accedida puede que no esté disponible, bien porque sea un disquete o bien porque sea una unidad extraible o de red, tenemos que preverlo para que no nos suelte un error nada más entrar en el programa.
Para ello he usado la detección de errores, veamos el código:'Este código está en el evento Form_Load sFicIni = AddBSlash(App.Path) & "gsDirDif.ini" On Local Error Resume Next 'Usar el path de la última vez Dir1(0).Path = LeerIni(sFicIni, "Directorios", "Dir0", Dir1(0).Path) 'Si da error, usar el path actual If Err Then Dir1(0).Path = CurDir$ End If Err = 0 Dir1(1).Path = LeerIni(sFicIni, "Directorios", "Dir1", Dir1(1).Path) If Err Then Dir1(1).Path = CurDir$ End If Err = 0Las funciones LeerIni y GuardarIni, están en un módulo, ya publicado antes en mis páginas, y lo que hacen es escribir en ficheros INI, en lugar de usar el registro de Windows, para que de esta forma sea más fácil de localizar y modificar. Normalmente este tipo de ficheros los guardo en el mismo directorio en que se encuentra el ejecutable, para ello uso la propiedad .Path del objeto App.
Las opciones de Copiar, Mover y Eliminar.
Estas tres tareas están en un mismo procedimiento y según la acción indicada hará una cosa u otra o una mezcla de dos, como ocurre con Mover, ya que para mover un fichero, primero hay que copiarlo y después borrarlo del sitio en que estaba... siempre que no se haya producido un error, claro.
Private Sub mnuCopiar_Click() 'Copiar los ficheros seleccionados del directorio activo 'al otro Accion cCopiar End Sub Private Sub mnuEliminar_Click() 'Eliminar los ficheros seleccionados del directorio activo Accion cEliminar End Sub Private Sub mnuMover_Click() 'Mover los ficheros Accion cMover End Sub Private Sub Accion(ByVal queAccion As Integer) 'Acciones a realizar con los ficheros seleccionados Dim sTmp$ Dim DirDestino& Dim tFichero As cFichero Dim sDir1$, sDir2$ Dim i& Dim bAceptado As Boolean On Local Error Resume Next DirDestino = 1 If DirActivo = 1 Then DirDestino = 2 End If sDir1 = AddBSlash(File1(DirActivo - 1).Path) sDir2 = AddBSlash(File1(DirDestino - 1).Path) bAceptado = False Select Case queAccion Case cCopiar sTmp = "¿Quieres COPIAR los ficheros seleccionados" & vbCrLf & _ "de: " & sDir1 & vbCrLf & _ "a: " & sDir2 & "?" If MsgBox(sTmp, vbQuestion + vbYesNo, "Copiar ficheros") = vbYes Then bAceptado = True Label1(DirActivo - 1) = "Copiando..." End If Case cMover sTmp = "¿Quieres MOVER los ficheros seleccionados" & vbCrLf & _ "de: " & sDir1 & vbCrLf & _ "a: " & sDir2 & "?" If MsgBox(sTmp, vbQuestion + vbDefaultButton2 + vbYesNo, "Mover ficheros") = vbYes Then bAceptado = True Label1(DirActivo - 1) = "Moviendo..." End If Case cEliminar sTmp = "¿Quieres ELIMINAR los ficheros seleccionados" & vbCrLf & _ "de: " & sDir1 & "?" If MsgBox(sTmp, vbQuestion + vbDefaultButton2 + vbYesNo, "Eliminar ficheros") = vbYes Then bAceptado = True Label1(DirActivo - 1) = "Eliminando..." End If End Select If bAceptado Then CalculaTamaño DirActivo - 1 Screen.MousePointer = vbArrowHourglass For Each tFichero In m_Directorio(DirActivo).Ficheros If tFichero.Seleccionado Then DoEvents Err = 0 If queAccion = cCopiar Or queAccion = cMover Then FileCopy sDir1 & tFichero.Nombre, sDir2 & tFichero.Nombre End If If Err = 0 Then 'En el caso de Mover, 'no borrar si se ha producido un error If queAccion = cEliminar Or queAccion = cMover Then Kill sDir1 & tFichero.Nombre End If End If End If Next Screen.MousePointer = vbDefault bCalculando = True 'obligar a releer los ficheros File1(0).Path = ".." File1(0).Path = Dir1(0).Path ' File1(1).Path = ".." File1(1).Path = Dir1(1).Path CalculaTamaño 0 CalculaTamaño 1 bCalculando = False End If Err = 0 End SubPara finalizar veamos el código usado para Crear y Eliminar directorios. Estos son bastantes simples, simplemente se llama a las funciones incorporadas en el VB. Aunque hay que hacer, como es costumbre, las pertinentes comprobaciones de error y por supuesto, pedir la conformiadad de lo que se quiere hacer.
En el caso de la creación de directorio, para pedir el nombre del directorio a crear, he usado la función INPUTBOX. Si el nombre introducido es una cadena vacía, simplemente no se hace nada.En el caso de que queramos borrar un directorio, éste no será el que está actualmente "abierto", en su lugar se borrará el que esté seleccionado en el DirListBox.
Private Sub mnuMkDir_Click() 'Crear un directorio Dim sDir1$ Dim sTmp$ sDir1 = AddBSlash(File1(DirActivo - 1).Path) On Local Error Resume Next sTmp = InputBox("Nombre del directorio a crear en " & vbCrLf & sDir1, "Crear directorio", "") If Len(sTmp) Then sTmp = sDir1 & sTmp MkDir sTmp If Err Then MsgBox "Imposible crear el directorio:" & vbCrLf & sTmp, vbInformation, "Error al crear directorio" Else 'Releer el directorio sDir1 = File1(DirActivo - 1).Path Dir1(DirActivo - 1).Path = sTmp Dir1(DirActivo - 1).Path = sDir1 End If End If Err = 0 End Sub Private Sub mnuRmDir_Click() 'Eliminar el directorio seleccionado en el DirListBox Dim sDir1$ On Local Error Resume Next With Dir1(DirActivo - 1) sDir1 = AddBSlash(.List(.ListIndex)) End With If MsgBox("¿Quieres eliminar el directorio:" & vbCrLf & sDir1 & "?" & vbCrLf & "(Sólo se eliminará si está vacio)", vbQuestion + vbYesNo + vbDefaultButton2, "Eliminar directorio") = vbYes Then RmDir sDir1 If Err Then MsgBox "Imposible eliminar el directorio:" & vbCrLf & sDir1 & vbCrLf & "puede que no esté vacio o se haya denegado el acceso.", vbInformation, "Error al eliminar directorio" Else 'Releer el directorio sDir1 = File1(DirActivo - 1).Path Dir1(DirActivo - 1).Path = ".." Dir1(DirActivo - 1).Path = sDir1 End If End If Err = 0 End SubPara saber que directorio está seleccionado se usa el valor guardado en el .List(.ListIndex)
Esto mismo se usa en el evento Dir1_KeyPress, para que al pulsar Intro se cambie de directorio:Private Sub Dir1_KeyPress(Index As Integer, KeyAscii As Integer) 'Si se pulsa INTRO, cambiar de directorio On Local Error Resume Next If KeyAscii = 13 Then With Dir1(Index) .Path = .List(.ListIndex) End With End If Err = 0 End SubBueno, creo que habrá quedado bien claro cómo se ha "fabricado" esta utilidad y confio en que haya sido instructivo, ya que de eso es de lo que se trata.
Para bajarte los listados, recuerda que son para VB5, pulsa en este link. (gsDirDif_cod.zip 9.85 KB)
Este otro link es para que descargues el ejecutable, pequeñito pero matón. (gsDirDif.zip 11.9 KB)
Recuerda que está compilado con el Service Pack 2 (SP2), por tanto necesitarás el runtime correspondiente, que puedes bajar de esta otra dirección: http://www.chez.com/guille/ftp/Msvbvm50.zip
La versión usada es: 05.00.4319 (SP2)Espero que esta utilidad te sea tan útil como lo es para mi y, si lo crees conveniente, hazme un comentario sobre lo que te ha parecido.
Nos vemos.
Guillermo