Entrega Treinta y una: 30/Jun/99
por Guillermo "guille" Som
Si quieres linkar con las otras entregas, desde el índice lo puedes hacer
Menús (el resto) y los diálogos comunes
Nos quedamos pendientes de codificar las opciones del menú de ficheros.
Las opciones que tenemos son:
Nuevo
---
Abrir...
Guardar
Guardar como...
---
Imprimir...
Seleccionar impresora...
Imprimir
---
Salir
Pero vamos a añadir otra: Mezclar
Esta opción insértala entre abrir y guardar, el nombre del menú es mnuFicMezclar y la letra M es la que debe estar subrayada (escribe &Mezclar en el caption)
¿Para que sirve mezclar?
Para intercalar otro fichero en el texto actual; ahora vamos a ver qué necesitamos para escribir el código de estas opciones.
Cuando se pulsa Abrir…, (o en cualquiera de las opciones en las que se necesite el nombre de un fichero), lo que el usuario espera es que se le pregunte el fichero a editar. Se puede hacer de forma simple, usando el InputBox o un formulario de nuestra cosecha que simplemente pregunte un nombre de fichero, pero… eso no es lo que estamos acostumbrados a ver… lo que necesitamos es poder mostrar un:Es decir, un cuadro de diálogo, (no se porqué lo llaman de diálogo, ya que no habla…), con el que poder seleccionar un fichero de cualquier directorio o unidad de disco. El VB incluye un control para hacer esto. Pero para poder usarlo, primero tiene que estar disponible.
Para ello, en el menú proyecto, selecciona componentes… y te mostrará un cuadro de diálogo con los controles que tenemos registrados en el sistema, selecciona: Microsoft Common Dialog Control (ComDlg32.ocx, control de diálogos comunes) y pulsa aceptar.En la barra de herramientas, (la que está a la izquierda), verás que hay un icono como este:
Muestra el formulario y haz doble clic en ese icono, y se insertará en el formulario, desde este momento ya está disponible, el nombre por defecto de este control es: CommonDialog1, por tanto para acceder a las propiedades y métodos tendremos que usar, como es costumbre en todos los controles, ese nombre seguido de un punto y después la propiedad o método.Por ejemplo para abrir:
With CommonDialog1 .DialogTitle = "Seleccionar un fichero para abrirlo" .ShowOpen NombreFichero = .FileName End WithAhora que "sabemos" cómo se usa este control, vamos a usarlo "correctamente" y no es porque lo otra forma no sea correcta, que lo es, me refiero a que nos sea "útil" en nuestro proyecto.
Bien, estamos dispuestos a entrar de lleno en lo que es la codificación del programa; ya hemos visto otros "listados", pero este es algo más complicado... aunque no tiene porqué serlo...
Revisemos lo que tenemos y, sobre todo, que utilidad tendrá todo este tinglado, sé que después de dos entregas ya se tendría que saber pero...
-La intención es crear un formulario con una serie de menús, una caja de texto en la que poder escribir y poder manipular el texto escrito, pudiendo guardarlo en el fichero de texto y permitirnos asignar el texto contenido en cualquier otro fichero, además de realizar ciertas tareas de "edición" en el texto contenido en esa caja de texto.
Pero nos falta un pequeño detalle: cómo saber el nombre del fichero con el que queremos "nombrar" lo que hemos escrito o como saber el nombre del fichero que usamos para asignarlo al textbox, es decir necesitamos una variable para guardar un nombre de fichero.
Ahora hay otro pequeño detalle: ¿dónde necesitamos usarla?
Me explico: ¿necesitamos una variable local a un solo procedimiento? o ¿ necesitamos una variable que pueda ser "vista" en todos los procedimientos?
¿Recuerdas lo dicho en la entrega 26?
Creo que nuestra variable para almacenar el nombre del fichero debe tener una "cobertura" a nivel de módulo, ya que se usará tanto en los procedimientos de abrir como en los de guardar. Por tanto declárala en la sección general del formulario:
Private NombreFichero As StringY ahora te tendría que seguir mostrando código, pero, creo que parte de lo que hay que hacer ya lo hemos hecho... voy a comprobarlo y te lo digo... ¡vuelvo enseguida!
Si se ha hecho, en la entrega quince para más señas, así que solo te diré "lo nuevo", pero el resto tendrás que hacerlo por tu cuenta, aunque te diré que es lo que debes hacer y dónde; de esta forma tendrás ejercicios obligatorios... si no los resuelves, no tienes programa, je, je.
Antes de ver el código de este mini-editor, vamos a ver un nuevo sistema de nombrar constantes:
Nota: esto sólo existe en la versión 5 o superior.
La enumeración se usa para constantes de forma correlativa, aunque eso puede cambiarse.
Por ejemplo:
Enum eEdicion Deshacer Sep1 Cortar Copiar End EnumSegún esto, Deshacer vale 0, Sep1=1, Cortar=2, etc.
Osea el primer nombre de constante valdrá cero y las demás irán incrementando el valor de uno en uno.
Si no queremos que se comporte de esta forma, es decir que empiece con cero, podemos asignar el valor que queramos:
Enum ePrueba Primero = -1 Segundo Tercero End EnumAhora los valores son: Primero= -1, Segundo= 0, Tercero= 1
También podemos asignar los que queramos:
Enum ePrueba2 Uno = 1 Dos '2 Tres '3 Nulo = 0 Cuatro = 4 Cinco '5 End EnumFíjate que al indicarle Uno=1, se empieza por uno y el siguiente valor será dos, etc., hasta que volvamos a asignar un nuevo valor, en este caso Nulo=0, Cuatro vale 4 y los siguientes, si no se le indica lo contrario, van aumentando de uno en uno.
Otra cosa que se suele hacer con esto de las enumeraciones, siempre que los valores asignados sean correlativos, es indicar cual es el valor menor y cual el mayor; así se pueden usar en ciertos bucles y para ciertas comprobaciones en las que necesitemos que un valor determinado esté entre los dos valores indicados:
Enum eEdicion edPrimero edDeshacer = edPrimero edSep1 edCortar edCopiar edPegar edSep2 edSeleccionarTodo edSep3 edBuscar edBuscarSig edReemplazar edUltimo = edReemplazar End EnumEn este caso, se asignan dos constantes: edPrimero y edUltimo para indicar los valores mínimo y máximo del rango de las constantes. Recuerda que cada vez que se asigna un valor a una constante de una enumeración, si en la siguiente no se le indica explícitamente un valor, se incrementa el valor anterior en uno. Por tanto, edPrimero y edDeshacer valdrán cero, edSep1 vale 1, edCortar vale dos y así sucesivamente.
Otra cosa a saber sobre las enumeraciones, es que los valores siempre son numéricos del tipo long.
Cuando creamos una enumeración, estamos creando un nuevo tipo de variable... o casi, lo importante es que podemos crear variables de la enumeración:
Dim miVarEnum As ePruebaAl asignar un valor a una variable declarada de esta forma, el Visual Basic nos indicará los nombres (o valores posibles)
Por ejemplo:
es decir, nos muestra una lista despegable con los valores posibles.
También podemos usar esos nombres de forma independiente, sin necesidad de crear una variable especial:
Dim x As Long x = PrimeroEs decir, se asignará a la variable x lo que vale la constante Primero (-1)
Un dato importante: no deberías usar el mismo nombre de constante en diferentes enumeraciones, ya que el Visual Basic podría confundirse... aunque te avisará de que hay un "conflicto".
Si tenemos estas dos enumeraciones:
Enum ePrueba Primero = -1 Segundo Tercero End Enum Enum ePrueba1 Primero = -1 Otro = Primero Siguiente Ultimo = Siguiente End EnumY asignamos x = Primero, nuestro querido Visual Basic nos dirá que se ha detectado un nombre ambiguo, tal como nos muestra este mensaje:
Para solucionarlo podemos hacer dos cosas:
---Usar nombres diferentes en las constantes enumeradas, (lo más recomendable).
---Indicar el nombre de la enumeración: x = ePrueba1.PrimeroPara terminar esto, decirte que puedes usar nombres de constantes con espacios, aunque esto es algo que está bien cuando creamos "controles", para que los nombres de las constantes de las propiedades sean descriptivas:
Enum ePrueba3 [Fecha Actual] [Fecha Anterior] End EnumFíjate en el uso de corchetes.
Cuando se usan estos valores, el propio Visual Basic se encarga de asignarlo con los corchetes:unaFecha = [Fecha Actual]Y si los asignamos nosotros directamente, hay que poner el nombre de la "constante" dentro de los corchetes, sino el Visual Basic entenderá que son dos nombres diferentes sin ningún tipo de operación de por medio... lo cual se convertirá en un "bonito" error...
El único "defectillo" que tienen las constantes de las enumeraciones, es que los nombres usados no mantienen el estado de mayúsculas / minúsculas, es decir que si declaramos Primero en un Enum y después escribimos ese nombre en minúsculas se cambiará la declaración a minúsculas:
x = primeroPero aún así, si tenemos Option Explicit podemos detectar valores no "creados"; aunque para mi gusto, se debería "respetar" el estado de mayúsculas/minúsculas de la declaración.
Un último comentario y ya termino..., al igual que ocurre con los procedimientos en los que no se indica "explícitamente" que es privado, serán públicos por defecto. Así que, si no tienes intención de hacer públicas las enumeraciones, decláralas como Private.
Ahora veamos parte del código nuevo, el resto será el que se mostró en la entrega anterior.
Los valores de las constantes para el menú de edición las vamos a tener en una enumeración. Por tanto si la versión que estás usando es anterior a la 5, tendrás que declararlas como constantes normales, (tal y como se mostró en la entrega 30).
En la parte de las declaraciones del formulario:
' Constantes para el menú de Edición. ' Los valores se corresponden con el índice de mnuEditor Private Enum eEdicion cedPrimero cedDeshacer = cedPrimero cedSep1 cedCortar cedCopiar cedPegar cedSep2 cedSeleccionarTodo cedSep3 cedBuscar cedBuscarSig cedReemplazar cedUltimo = cedReemplazar End Enum Private NombreFichero As String ' Nombre del fichero Private Modificado As Boolean ' Para indicar si se ha cambiado el textoAl iniciarse el formulario asignaremos los filtros para la selección del tipo de ficheros en el cuadro de diálogo.
El filtro se asigna a la propiedad Filter del CommonDialog y el formato a usar será: descripción del tipo, el tipo, descripción, tipo, etc. cada uno de estos "datos" estará separado por el signo | (ALT+124) o Alt Gr y 1.Private Sub Form_Load() ' Asignar el filtro para el diálogo común CommonDialog1.Filter = "Textos (*.txt)|*.txt|Todos (*.*)|*.*" End SubCada vez que escribamos algo en el textbox habrá que indicarle a nuestro programa de que se ha cambiado, por tanto asignaremos True a la variable Modificado:
Private Sub txtEditor_Change() Modificado = True End SubAhora veremos el código de algunas de las opciones del menú de ficheros, el resto lo veremos en la siguiente entrega, junto con todo el código...
Private Sub mnuFicAbrir_Click() ' Comprobar si el texto se ha modificado ' si es así, guardarlo o no, según la respuesta del usuario ' ***ejercicio*** With CommonDialog1 .DialogTitle = "Seleccionar un fichero para abrilo" .FileName = NombreFichero .ShowOpen If Len(.FileName) Then NombreFichero = .FileName ' Abrir el fichero y asignarlo al textbox ' ***ejercicio*** Modificado = False End If End With End Sub Private Sub mnuFicGuardar_Click() ' Si no se ha asignado el nombre al fichero, preguntar por él If Len(NombreFichero) = 0 Then mnuFicGuardarComo_Click Else GuardarFichero End If End Sub Private Sub mnuFicGuardarComo_Click() ' Preguntar el nombre del fichero y guardarlo With CommonDialog1 .DialogTitle = "Guardar el fichero" .FileName = NombreFichero .ShowSave If Len(.FileName) Then NombreFichero = .FileName GuardarFichero End If End With End Sub Private Sub mnuFicMezclar_Click() ' Preguntar el nombre del fichero a mezclar With CommonDialog1 .DialogTitle = "Fichero a mezclar" .ShowOpen If Len(.FileName) Then ' Leer el fichero y guardarlo en una variable Dim nFic As Long Dim sMerge As String Dim sTmp1 As String, sTmp2 As String nFic = FreeFile Open .FileName For Input As nFic sMerge = input$(LOF(nFic), nFic) Close nFic ' Tomar lo que hay hasta la posición del cursor With txtEditor sTmp1 = Left$(.Text, .SelStart) sTmp2 = Mid$(.Text, .SelStart + 1) .Text = sTmp1 & sMerge & vbCrLf & sTmp2 End With End If End With End Sub Private Sub mnuFicNuevo_Click() ' Comprobar si se ha modificado el fichero actual ' ***ejercicio*** txtEditor = "" Modificado = False End Sub Private Sub GuardarFichero() ' Guardar el contenido del textbox en NombreFichero ' ***ejercicio*** Modificado = False End SubComo te imaginarás donde pone ***ejercicio*** es lo que tienes que hacer, ya sabes que en la entrega quince se hizo algo parecido.
Por lo demás, nos queda la parte de: seleccionar impresora, imprimir, buscar y reemplazar, pero eso lo dejaremos para otra ocasión... aunque si no quieres esperar, pásate por la sección "Mis Utilidades" y busca la entrada que dice "Un procedimiento genérico para imprimir"
En la próxima entrega también veremos algo sobre el control de errores... cosa que será necesaria "controlar" para los casos en que se pulse "Cancelar" en el cuadro de diálogo de selección del nombre del fichero.
Así que, paciencia... y a esperar... si puedes... y si no puedes... pues eso...
Hasta la próxima
Nos vemos
Guillermo