|
Curso básico
de programación en Visual Basic
Lección
29
Menús,
submenús, PopupMenús
|
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 has notado que la entrega
anterior está "inacabada" estás en lo cierto... la
verdad es que gracias a uno de los "típicos" despistes
que me caracterizan, se me fue un poco la "olla" y creí
haberla acabado, pero... no fue así, por tanto, espero que no te
enfades mucho conmigo y tengas paciencia, que pronto estará
terminada... por ahora sigue con lo que hay que al ser un tema
diferente no te causará ningún trastorno cerebral... y si te lo
causa... ¡bienvenido al club!
Esta entrega también ha sido
"mecanografiada" por Encarnica... que ya tiene pasadas a
limpio hasta la entrega 32... aunque sólo la parte explicativa, ya
que el código me lo deja a mi... que ella aún no sabe programar...
así que si hay retrasos en la publicación, es sólo culpa mia...
También quiero daros las gracias,
en nombre de Encarni por los que la habéis felicitado por
"ofrecerse" a pasar a limpio mis notas
"ininteligibles". ¡Gracias
otra vez Encarni!
Menús, submenús,
popupmenús y ajuste de tamaños.
En la entrega de hoy vamos a ver cómo añadir menús a nuestros
programas. Para verlo "ejemplarizado" vamos a crear un
minieditor (¡por fin!) pero no te hagas ilusiones... será tan
simple que casi sólo vamos a utilizar un cuadro de texto y sus
posibilidades serán básicamente las que nos de el textbox...
bueno, realmente tendrá algunas más... ya veremos.
Para crear el programa, abre un proyecto nuevo, el el form que se
crea por defecto, añade un TextBox, asígnale estos valores a las
propiedades indicadas:
| Propiedad |
Valor |
| Multiline |
True |
| Scrollbars |
3-Both |
| Left |
0 |
| Top |
0 |
| Name |
txtEditor |
Multiline para que permita más de una línea de
texto; los dos Scrollbars para que podamos escribir
líneas de cualquier longitud y que sólo cambien al pulsar Intro; Left
y Top, para que se posicione en la esquina superior
izquierda del formulario.
Crear una barra de estado (StatusBar)
Vamos a añadirle al formulario un Picture para que nos sirva de
Statusbar, para ello añade un picture al proyecto, selecciónalo y
asígnale la propiedad Align a 2 - Align
Bottom para que se pegue a la parte inferior del
formulario. Asígnale un valor 315 a la propiedad Height,
en la propiedad BorderStyle, asígnale un 0 (sin
borde). Selecciona del toolbar una etiqueta haz doble click y se
insertará en el formulario. Selecciona la etiqueta y córtala
(menú edición / cortar). Selecciona el picture y pega la etiqueta
(menú edición / pegar). Asígnale estas valores a las propiedades
indicadas: Height = 285, Top = 15,
Left = 30, BorderStyle = 1 (con
borde).
Ahora vamos a darles nombre a los controles, al TextBox llámalo
txtEditor, el Picture será picStatus, el Label se llamará
lblStatus.
Posicionar los controles automáticamente en el
formulario
Antes de empezar a crear los menús, vamos a indicarle al Visual
Basic que "posicione" correctamente los controles cuando
el formulario cambie de tamaño. Para ello, abre la pantalla del
código, selecciona Form de la lista de la
izquierda y Resize en la lista de la derecha.
Cada vez que un formulario cambia de tamaño se ejecuta el evento
Form_Resize, por tanto este es el sitio en el que
tendremos que codificar para adaptar los controles al tamaño
adecuado. Lo que vamos a hacer es ajustar el tamaño de la etiqueta
al tamaño del Picture y el TexBox para que ocupe todo el tamaño
restante.
Pero sólo haremos los cálculos cuando el form no se minimice,
ya que si está minimizado, no se ve nada, así que para que vamos a
ajustar el tamaño de algo que no se ve; para indicarle al VB que
sólo ejecute el código cuando no vaya a minimizar la aplicación
usaremos la propiedad WindowState, si esta es
diferente de vbMinimized querrá decir que no se ha
minimizado, así pues, añade este código:
' Sólo cuando no esté minimizado el formulario
If WindowState <> vbMinimized Then
Y ahora empezaremos a ajustar los tamaños:
El label será igual de ancho que el PicStatus menos 60, para que
tenga un poco de "respiro" por los lados:
'
lblStatus.Width = picStatus.ScaleWidth - 60
esta es simple, ahora haremos lo mismo lo mismo con el txtEditor:
'
txtEditor.Width = ScaleWidth
el alto será el alto del form menos el alto del PicStatus:
'
txtEditor.Height = ScaleHeight - picStatus.Height
y ya está. Se supone que en tiempo de diseño asignaste 0 a las
propiedades Left y Top del txtEditor, aunque si quieres, puedes
hacerlo en este mismo evento:
'
txtEditor.Move 0, 0
eso es lo mismo que haber asignado 0 a las propiedades Left y Top…
es más rápido cambiar el tamaño de un control con Move que
asignando cada una de las propiedades por separado, ya que se usa un
sólo método en lugar de 4 asignaciones a propiedades, así pues,
podríamos haber cambiado el tamaño del txtEditor de esta otra
forma, aunque seguramente sería menos "instructivo":
'
txtEditor.Move 0, 0, ScaleWidth, ScaleHeight - picStatus.Height
Vamos a probarlo :
Pulsa F5 y cambia el tamaño de la ventana, verás como se
"adaptan" los controles… aunque el label no parece
enterarse ¿verdad?
Para que el label se ajuste al tamaño del picture, hay que
ajustar ese tamaño en el evento Resize del picStatus:
'
Private Sub picStatus_Resize()
' Sólo cuando no esté minimizado el formulario
If WindowState <> vbMinimized Then
' Aquí se ajustará el tamaño del label
' cuando cambie el del picStatus
lblStatus.Width = picStatus.ScaleWidth - 60
End If
End Sub
Algo sobre los tamaños de los controles: Diferencia
entre Height/Width y ScaleHeight/ScaleWidth
Como habrás notado, para ajustar el ancho y alto, se está
usando ScaleWidth y ScaleHeight,
aunque para calcular el alto del textbox también se usa picStatus.Height,
en cuanto te explique que significan estas propiedades, seguro que
lo entiendes.
ScaleWidth y ScaleHeight son
propiedades que nos informan del ancho y alto "interno"
del formulario o control, es decir lo que miden sin contar el borde.
Width y Height, por otro lado, nos
dicen que el ancho y alto "externo" del form o control.
Cuando se calcula el alto del txtEditor necesitamos saber el alto
interno del formulario (ScaleHeight) al que hay que restarle el alto
total de picStatus (picStatus.Height). Si hubiésemos usado Height
en el lugar de ScaleHeight, los cálculos no nos hubiesen salido
correctos, ya en el valor devuelto por esa propiedad nos indicaría el
alto total del form. Ahora mismo, tal como está el
programa habría poco diferencia, aunque aún así no se ajustaría
perfectamente, "desajuste" que quedaría demasiado
evidente en cuanto añadamos menús. (¿menús? No era de eso de lo
que iba a tratar esta entrega).
Otro detalle es que para referirnos al alto y ancho
"interno" del formulario, lo hemos usado sin indicar nada
más, esto siempre es así cuando hagamos referencia a una propiedad
de un objeto, (en este caso un formulario), y el código se ejecuta
"dentro" de ese formulario. Sin embargo cuando hacemos
referencia a las propiedades de otros controles, (incluso de otro
formulario), tendremos que anteponer el nombre de ese control
delante de la propiedad o método, para que el VB sepa a que control
nos estamos refiriendo.
Borra la línea que cambiaba el tamaño de la etiqueta en el
evento Form_Resize y vuelve a pulsar F5, cambia el tamaño del
formulario, esta vez si que se adapta bien el lblStatus dentro del
picture que la contiene.
Ya puedes detener el programa, pulsando en la "x" del
form. Haz que se muestre el fomulario ya que es necesario para poder
añadir menús a nuestro "mini-editor".
Añadir menús a un
formulario
Como habrás observado en todas las aplicaciones de Windows, los
menús se muestran en la parte superior de las aplicaciones, esto no
es ningún descubrimiento, excepcional pero… la cuestión es que
si se muestran en la parte superior ¿tendremos que hacer un nuevo
cálculo al cambiar el tamaño del formulario?
La respuesta es: no.
Al añadir menús a nuestro formulario, el tamaño de éste se
ajusta automáticamente y no tendremos que tener en cuenta el
espacio que ocupa para "ajustar" los controles que
tengamos en él. Es decir, que el código del Form_Resire sigue
siendo válido con o sin menús.
Una vez aclarado este punto, antes de empezar a añadir menús,
otro poco de teoría… pero no te asustes, no es demasiado la
teoría, sólo para aclarar "conceptos".
Cuando creamos menús tenemos varios "niveles",
normalmente son dos: el menú principal que siempre está visible en
la parte superior y los elementos que se muestran cuando hacemos click
(o pulsamos) en ese menú principal. Cada vez que pulsamos en un
elemento de la "lista" de menús principal se muestran los
que "cuelgan" de él. Habrás observado que muchos de los
elementos de los menús, tanto principales como secundarios, tienen
una letra subrayada, eso quiere decir que pulsando Alt más esa
letra, se despliega o selecciona esa opción del menú, es como si
pulsáramos con el ratón. Cuando empiece con la explicación verás
cómo podemos crear nuestras propias letras de acceso, incluso cómo
añadir "accesos rápidos" a algunas de las opciones de
los menús, todo esto lo veremos ahora mismo.
Cómo añadir
menús a nuestro formulario (ahora si)
Para poder "diseñar" los menús, tienes que tener
visible el formulario en el que mostraremos los menús, así que si
el formulario no está mostrado, haz que se muestre, (haciendo
dobleclick en la ventana del explorador de proyectos)
Para entrar en modo de diseño de menús, puedes hacerlo de dos
formas: seleccionando del menú Tools (Herramientas) la opción Menu
Editor… o pulsando el icono
de la barra de herramientas. Te mostrará un cuadro de diálogo como
el que sigue:

Las partes más importantes son:
Caption/Descripción que es el texto que se mostrará,
Name/Nombre del menú que será donde escribamos el código a
ejecutar cuando se seleccione ese menú.
Vamos a empezar por añadir un menú "Fichero", (o
archivo si así lo prefieres), en este menú tendremos las opciones
de Abrir, Guardar, Guardar como y Salir, después añadiremos otras,
según convenga. También tendremos otro menú principal llamado
Edición con las clásicas opciones de ese tipo de menú: Deshacer,
Cortar, Copiar, Pegar, etc.
Pero empecemos por el de fichero:
Escribe en el "Caption", &Ficheros,
el signo & le indicará al Visual Basic que muestre subrayada la
letra que sigue a ese signo, de esa forma se podrá acceder pulsando
Alt y la letra subrayada, es decir Alt+F
En el nombre del menú escribe: mnuFic y pulsa Intro o en el
botón Siguiente. Se "limpiarán" las
casillas de texto y estará listo para escribir las opciones de este
menú:
Escribe en Caption: &Abrir... y en nombre
mnuFicAbrir los tres puntos suspensivos es una norma
recomendable, que indica que se mostrará un cuadro de diálogo,
acostúmbrate a seguirla, de esta forma tus aplicaciones tendrán un
aspecto "standard windows" (realmente no es un estándar
de windows, sino una norma anterior anterior, pero…)
Después de la opción Abrir vamos a añadir Guardar, por tanto
en el caption del menú escribimos &Guardar y
en el nombre de esa opción: mnuFicGuardar, en este caso no
añadimos los tres puntos seguidos ya que lo habitual en las
opciones guardar, es guardar sin preguntar, salvo que aún no se le
haya dado nombre al fichero.
Como habrás observado cada vez que añades una opción se va
mostrando en la lista inferior. Antes de seguir vamos a ver cómo
quedan nuestros menús.
Pulsa el botón "aceptar" del cuadro de diálogo del
"diseñador de menús".
¡Sorpresa!
Como puedes observar, tenemos tres opciones "principales":
Ficheros, Abrir… y Guardar, pero esta no era la intención, ya que
Abrir y Guardar sólo se deberían mostrar al seleccionar el menú
Ficheros
¿Qué ha pasado?
Muy fácil, al menos cuando se sabe cómo trabaja esto de los
menús, que al no indicarle lo contrario… ¡todos los menús se
muestran en la barra principal! ¿cómo podemos crear los submenús
(o menús que se muestran al seleccionar un menú)?
Ahora lo veremos, antes de hacerlo, en tiempo de diseño, es
decir, sin pulsar F5, pulsa en el menú Fichero. Se mostrará la
ventana de código, el combo de en la parte izquierda se mostrará
mnuFic y en el de la derecha verás que es el evento click, por
tanto estaremos en el procedimiento mnuFic_Click.
Todo lo que escribas en este menú se ejecutará cuando selecciones
esta opción. No escribas nada, cierra la ventana de código para
volver a mostrar el formulario.
Vamos a hacer que los menús se muestren como deben: al
seleccionar Ficheros que se despliegue el menú con las opciones
Abrir, Guardar, etc.
Entra en el diseño de menús, (esto tendrás que hacerlo siempre
que quieras añadir nuevas opciones de menús o modificar las ya
existentes.)
Si te fijas en la lista inferior, verás que las tres opciones
que tenemos están alineadas a la izquierda.
Selecciona Abrir en la lista inferior, comprobarás que se
"rellenan" las casillas con la descripción y el nombre
del menú, eso nos indica que está seleccionada esa opción y que
cualquier cambio que hagamos, se hará en esa opción. Sé que todo
esto es evidente, pero… por si no lo habías captado… ahora
pulsa en la flecha que señala a la derecha, esto hará que la
opción seleccionada se desplace a la derecha, esto se muestra por
tres puntos delante de Abrir, no los confundas con los tres puntos
que nosotros le añadimos al final.
Haz lo mismo con "Guardar"
Cierra el cuadro de diálogo y veras que ahora sólo se muestra
el menú Ficheros. ¡Bien! ¡Ya tenemos lo que queríamos!
Selecciona ese menú y verás que se muestran las dos opciones que
hemos añadido; en esta ocasión no se muestra la ventana de
código, pero ya veremos que e evento "sigue operativo".
Pulsa en la opción "Abrir..." y en esta ocasión se
mostrará la ventana de código con el procedimiento:
"mnuFicAbrir_Click", para comprobar que funciona vamos a
añadir un mensaje que se mostrará cuando seleccionemos esta
opción:
'
Private Sub mnuFicAbrir_Click()
' Abrir
MsgBox "Esta es la opción Abrir..."
End Sub
Ahora para comprobarlo, pulsa F5 y selecciona el menú Ficheros,
se mostrarán las dos opciones que tenemos en este menú: Abrir y
guardar. Selecciona Abrir y verás que se muestra el mensaje, lo
cual quiere decir que todo está bien.
Cierra la aplicación y vuelve a mostrar el formulario para
añadir más opciones a los menús; así que haz que se muestre el
diseñador de menús.
Selecciona la última de las opciones de la lista y pulsa en el
botón Siguiente para que podamos añadir más opciones. Escribe G&uardar
como... en la descripción y mnuFicGuardarComo
en el nombre. Si esta nueva opción se muestra en la lista
totalmente a la izquierda, pulsa en la flecha de identación a la
derecha para que esté al mismo nivel que las otras dos, es decir
que tenga tres puntos delante del Caption que le hemos dado.
Pulsa de nuevo en el botón Siguiente, ahora tendrás que escribir
un guión, (signo menos), en la descripción del menú, en el nombre
del mismo escribe: mnuFicSep1, no sirve de nada, ya
que las líneas "divisorias" no se pueden seleccionar,
pero deben tener un nombre. Lo que debes "recordar" es que
si se indica un "-" en la descripción del menú, estamos
indicándole al VB que lo que queremos es que muestre una línea de
división. Pulsa en siguiente y escribe: &Salir
y mnuFicSalir (ya no es necesario que te diga
dónde debes escribirlo, ¿verdad?)
Ya tenemos las opciones del menú Ficheros, ahora vamos con el
menú de edición. Añade este menú a continuación de Salir,
escribe &Edición en el Caption y mnuEdit
en el nombre. Cuando lo hayas escrito verá que está debajo de
Salir y con los tres puntos delante, si lo dejamos así, no se
mostrará en la barra principal de menús, sino que será una
opción más del menú Ficheros, y eso no es lo que queremos, por
tanto, pulsa en la flecha que señala a la izquierda para que se
pegue totalmente a la izquierda, y desaparezcan los puntos
suspensivos que hay delante del Caption. Porque como ya vimos antes,
las opciones que se muestran en la lista y que están sin los puntos
suspensivos son las que se mostrarán en la barra de menús. Antes
de añadir opciones al menú de edición, vamos a modificar las
opciones que tenemos, insertaremos una nueva al principio, que
servirá para crear un nuevo fichero. El caption, como puedes
imaginar, será Nuevo y el nombre del menú será mnuFicNuevo.
Vamos a añadirla: asegúrate que estemos en modo de diseño de
menús.
La nueva opción la vamos a insertar al principio, es decir justo
antes de Abrir. Por tanto, selecciona Abrir de la lista inferior,
pulsa el botón insertar y podrás escribir la descripción: &Nuevo
y el nombre del menú: nmuFicNuevo.
Cada vez que quieras insertar una nueva opción puedes hacerlo de
esta forma o bien añadiendo la opción al final y después
"situarla" en el lugar correspondiente usando las flechas
arriba y abajo.
Cuando insertas una opción, usando el botón insertar, la opción
insertada tiene la misma "indentación" que la que estaba
seleccionada antes de pulsar en insertar. Ya sabes que puedes
modificar dicha identación, o desplazamiento, usando las flechas de
izquierda y derecha.
Si lo que quieres es borrar un elemento de menú, simplemente la
seleccionas y pulsa en "eliminar", aunque esto sólo
elimina la opción del menú, no el código que tuviese asociado, lo
mismo ocurre cuando eliminamos o cambiamos el nombre de un control:
si ya tenía código en algunos eventos, este código sigue estando,
pero no en el sitio que debiera… no voy a seguir con esto, ya que
lo veremos en otra ocasión, pero al menos cuando le llegue el turno
te "sonara"…
Como ya vimos en La entrega 26 se
suele seguir unas "normas" a la hora de nombrar a los
controles y variables, y si no se "suele" seguir, al menos
se recomienda. En este caso los menús se preceden con
"mnu" seguido del nombre de menú principal y por último
el nombre de la opción. Aunque, como todos los consejos, eres libre
de seguir estas normas o de crear las tuyas propias. En mi caso,
"intento" seguir éstas que te estoy indicando, aunque
algunas veces me las salto, normalmente con la opción
"Salir" que simplemente la llamo: mnuSalir, aunque es
mejor llamarlo mnuFicSalir para que sepamos que está
"incluida" en el menú fic-heros.
Pero en esto de los nombre de los menús, aparte de que los
puedes "nombrar" como quieras, existe otra forma de
hacerlo.
Ya vimos que se pueden crear "arrays" de controles y que
la ventaja era, sobre todo si estaban relacionados, que no
necesitamos escribir el mismo código para cada uno de los eventos
que queramos interceptar; simplemente usando el índice podríamos
distinguir un control de otro; pero siempre, y esa es la ventaja, en
un mismo procedimiento de evento. Pues esto mismo se puede hacer con
los menús: podemos crear un array.
La única diferencia es que se crea de forma un poco más manual
y se hace en la "ventana de diseño de menús".
Array de menús
Para ello, se usa el mismo nombre de menú, pero usando un
"índice" diferente para cada opción.
El único requisito "obligatorio" es que los elementos
de un array de menús han de estar correlativos. Habitualmente se
incluyen en ese array todos los elementos de un menú principal…
bueno, los que se muestran al seleccionar esa opción. Y esto es lo
que vamos a hacer nosotros: incluir en un array todos las opciones
del menú edición, que serán las siguientes: Deshacer,
separación, cortar, copiar, pegar, separación, seleccionar todo;
posteriormente añadiremos más opciones… aunque seguramente será
en otra entrega.
El nombre del array será: mnuEditor, el primer
elemento, de índice cero, será: Deshacer.
Vamos a añadirlo pasito a pasito, para que no tropieces y te
"descalabres".
Supongo que ya estarás en el diseñador de menús y que la
opción seleccionada es la última: Edición.
Pulsa en el botón Siguiente y escribe en el Caption: Des&hacer,
en el nombre del menú: mnuEditor, (sin acento o
tilde... como prefieras llamarlo), en Index escribe
0; pulsa el botón con la flecha a la derecha, para indicar que esta
opción pertenece al menú Edición.
Pulsa en siguiente, si no se indenta, ya sabes cómo debes hacerlo;
escribe un "-" en el Caption, mnuEditor
en el nombre, pero en índice escribe 1, ya que al llamarse de la
misma forma el menú, el Visual Basic esperará encontrarse con un
índice que lo diferencie. Haz lo mismo con el resto e las opciones
y recuerda usar índices correlativos, y por supuesto diferentes...
Cuando hayas introducido todas las opciones, cierra el diseñador
de menús… si te da algún tipo de error, puede ser porque no
hayas usado el mismo nombre de menú para todas las opciones del
menú edición, porque no estén los índices correlativos o porque
no estén todos indentados en el mismo nivel, es decir con tres
puntos suspensivos a la izquierda (esto es lo que se muestra en la
lista y no tienes que escribirlos).
Este sería el aspecto:

Recuerda que los elementos de un array de menús deber ser
correlativos y estar en el mismo nivel de indentación
("osease" pertenecer al mismo menú).
Si todo está bien, al mostrar el formulario en tiempo de
diseño, no en ejecución, y pulsar en el menú edición, verás que
se muestra las opciones que hemos escrito. Pulsa en cualquier de
ellas y verás que siempre se muestra el mismo evento en la pantalla
de código:
mnuEditor_Click (Index As Integer)
El parámetro index será el que nos indique
cual de las opciones ha sido la que se ha coleccionado.
Para poder hacer cosas diferentes según la opción seleccionada
haremos algo como esto:
'
Private Sub mnuEditor_Click(Index As Integer)
Select Case Index
Case 0
' Deshacer
Case 2
' Cortar
' Etc...
'
End Select
End Sub
Pero para que resulte más fácilmente entendible y modificable,
en lugar de números, vamos a usar constantes, de esta forma, si
añadimos o eliminamos alguna de las opciones del menú, sólo
tendremos que cambiar el valor de la constante y el resto del
código no habrá que modificarlo.
Así pues, en la ventana de código, selecciona la parte general
de las declaraciones y añade esto:
'
' Constantes para el menú de Edición.
' Los valores se corresponden con el índice de mnuEditor
Const cEdDeshacer = 0
Const cEdCortar = 2
Const cEdCopiar = 3
Const cEdPegar = 4
Const cEdSeleccionarTodo = 6
Ahora las distintas opciones de "select" en el evento
mnuEditor_Click quedarán así:
'
Private Sub mnuEditor_Click(Index As Integer)
Select Case Index
Case cEdDeshacer
'
Case cEdCortar
'
Case cEdCopiar
'
Case cEdPegar
'
Case cEdSeleccionarTodo
'
End Select
End Sub
Con lo cual hemos ganado en "legibilidad" en el código
y, aunque aún no lo "sepas", en facilidad a la hora de
modificar el código.
El código a usar será el contenido de la siguiente entrega, ya
que esta se acaba aquí.
Además del código a usar, veremos cómo añadirle, a las
opciones del menú, teclas de acceso rápido, por ejemplo:
Control + X para cortar, etc.
Pero eso será en nuestro siguientes episodio.
Permanezca atento a la pantalla… continuará.
Nos vemos
|