Professional Documents
Culture Documents
TEMA 5
Formulario Principal
Posteriormente debemos Crear el formulario base que ser la plantilla que tendrn nuestros
formularios child. En nuestro caso hemos tratado de simular un editor de texto bastante simple
pero con soporte MDI.
Agregamos un nuevo formulario a nuestro proyecto.
Agregamos un primer panel en la parte inferior que podr contener botones si as lo deseamos,
para hacer eso establecemos la propiedad Dock del panel en Bottom.
Despus agregamos un segundo panel que contendr nuestro cuadro de texto y establecemos la
propiedad Dock en Fill.
P g i n a 1 | 19
Progamacion Visual
TEMA 5
Agregamos un botn al panel de la parte inferior que sera la simulacin de un botn que servir
para guardar nuestro documento. Con esto tendremos nuestro formulario base.
P g i n a 2 | 19
Progamacion Visual
TEMA 5
Formulario Base
Ahora crearemos un men para tener una administracin muy sencilla de las ventanas child (en
el formulario Principal). Observemos que la opcin "Lista ->" no tiene subelementos ya que los
crearemos en tiempo de ejecucin
Para crear ventanas nuevas manejaremos el evento clic del men Nueva Ventana.
Debemos crear un nuevo objeto de nuestro formulario base (en nuestro caso FrmChildBase) y
establecer su propiedad MdiParent.
Progamacion Visual
TEMA 5
Para ordenar nuestras ventanas debemos de manejar el evento clic de nuestro Men Horizontal,
Vertical y Cascada. Para cambiar el ordenamiento de las ventanas existe la funcin
LayoutMdi() que acepta una enumeracin MdiLayout. Aqu el ejemplo de las 3 opciones:
Una gran utilidad es el saber que ventana se encuentra activa, para eso existe la propiedad
ActiveMdiChild que nos devuelve el formulario que se encuentra activo. En nuestro ejemplo
manejaremos el evento clic del men Ventana Activa y tendremos este cdigo:
P g i n a 4 | 19
Progamacion Visual
TEMA 5
P g i n a 5 | 19
Progamacion Visual
TEMA 5
Forms en paneles
Lo primero que vamos a hacer es crear un proyecto de tipo Windows Forms, a este le vamos a
agregar tres Forms (Padre, Hijo1, Hijo2):
Y en los Forms hijos agregamos etiquetas grandes y distintivas (o lo que quieras agregar), as:
P g i n a 6 | 19
Progamacion Visual
TEMA 5
Ahora, en el lado que nos gusta (el lado del cdigo) veamos cmo implementar estos formularios
en el panel, en el evento click del botn btMostrarHijo1 agregamos el siguiente cdigo:
1
private void btMostrarHijo1_Click(object sender, EventArgs e)
2 {
3
if (this.panelContenedor.Controls.Count > 0)
this.panelContenedor.Controls.RemoveAt(0);
4
Hijo1 form =
5
6 Application.OpenForms.OfType<Hijo1>().FirstOrDefault();
Hijo1 hijo1 = form ?? new Hijo1();
7
hijo1.FormBorderStyle = FormBorderStyle.None;
8
hijo1.Dock = DockStyle.Fill;
this.panelContenedor.Controls.Add(hijo1);
9
this.panelContenedor.Tag = hijo1;
10
hijo1.Show();
11}
12
La explicacin de cmo funciona este cdigo es muy simple, primero preguntamos si existe
algn control en el interior del panel, de ser verdadero lo eliminamos. Luego creamos una nueva
instancia del formulario a agregar Luego preguntamos si existe algn formulario del tipo Hijo1
que ya este abierto, si existe usamos esa misma instancia, de lo contrario creamos una nueva y
sobre este objeto reescribimos algunas de sus propiedades, TopLevel establece si el formulario
debe mostrarse como ventana nivel superior, FormBorderStyle define el estilo de los bordes de
nuestro formulario (en nuestro caso no queremos mostrarlos), Dock establece como se acoplara el
control a su contenedor principal (en nuestro caso queremos que rellene todo el panel), Por
ultimo lo agregamos al panel, establecemos la instancia como contenedor de datos de nuestro
panel y lo mostramos, el resultado se ver as:
P g i n a 7 | 19
Progamacion Visual
TEMA 5
Y si tengo 50 botones en mi formulario padre, tengo que escribir todo este cdigo 50 veces? La
respuesta es NO, por fortuna para nosotros podemos escribir un mtodo que nos ahorre a un ms
el trabajo, en nuestro caso crearemos un mtodo void (sin retorno de datos) que recibir como
parmetro la instancia del Formulario a mostrar, as:
1
2 private void AddFormInPanel(Form fh)
3 {
if (this.panelContenedor.Controls.Count &gt; 0)
4
this.panelContenedor.Controls.RemoveAt(0);
5
fh.TopLevel = false;
fh.FormBorderStyle = FormBorderStyle.None;
6
fh.Dock = DockStyle.Fill;
7
this.panelContenedor.Controls.Add(fh);
8
this.panelContenedor.Tag = fh;
9
fh.Show();
10}
11
Y para acudir a este, desde el evento click del botn lo hacemos as:
1private void btMostrarHijo2_Click(object sender, EventArgs e)
2{
3
var form = Application.OpenForms.OfType<Hijo2>().FirstOrDefault();
Hijo2 hijo = form ?? new Hijo2();
4
AddFormInPanel(hijo);
5
}
6
P g i n a 8 | 19
Progamacion Visual
TEMA 5
Mirando cmo el diseador del Visual Studio declara y asigna las propiedades a los controles, hice lo
mismo para mis arrays de controles, pero dentro de un bucle. Aqu muestro la funcin que crea los
CheckBoxes:
P g i n a 9 | 19
Progamacion Visual
TEMA 5
Dentro del bucle asigno los delegados para los eventos respectivos de cada control. Para saber cul
control del array es el que lanza el evento debo examinar el objeto "sender" que es el control quien
"enva" o lanza el evento. Para saber el ndice del control dentro del array lo almaceno en una
propiedad del control: puede ser el nombre, el TabIndex, o el Tag. En realidad puede ser cualquier
propiedad cuyo valor no vamos a modificar a lo largo de la aplicacin, ya que desde la cual vamos a
saber el ndice del control dentro del array.
Un dato interesante acerca de los eventos es que estos no se ejecutan al declararlos dentro del
bucle que crea los controles. Aqu slo declaramos el evento y lo asignamos a su respectivo control,
el evento recin se ejecuta cuando el control lo "lanza" (es decir: cuando se ejecuta la accin que
llama al evento. Esto me ha recordado un poco a la "Evaluacin Perezosa" de la programacin
funcional, no s si ser exactamente lo mismo, pero se le parece mucho).
Las dos lneas con el comentario "poned un breakpoint ac" hacen exactamente lo mismo: Si deseo
leer el ndice guardado en el nombre del control que lanza el evento, utilizo la variable "n", o ms
P g i n a 10 | 19
Progamacion Visual
TEMA 5
directamente puedo leer el ndice usando la propiedad "Tag". Ambas lneas de cdigo cambian el
valor del elemento con ndice "n" ndice "Tag" (ambos tienen el mismo valor) del array "dias" a
verdadero falso, segn sea el valor de la propiedad "Checked" del CheckBox con ndice "n" "Tag"
dentro del array de ChackBoxes.
Y esta es la funcin de los TextBoxes:
En el caso de los TextBoxes, mandarn un saludo al texto de su formulario (el cual se llama "Form1")
al recibir el cursor (el ndice del respectivo TextBox se lee desde la propiedad "Tag"):
P g i n a 11 | 19
Progamacion Visual
TEMA 5
Si se pone un punto de quiebre en las lneas donde dice "poned un breakpoint ac" se podr ver cmo
la ejecucin del programa "salta" a la declaracin del evento para cambiar los valores a los elementos
del array "dias" cuando se pone o quita el "check" de los CheckBoxes.
Y qu sucede si deseo enviar mensajes a otros formularios? Debo crear un delegado y su respectivo
evento:
P g i n a 12 | 19
Progamacion Visual
TEMA 5
Tambin debo crear el otro formulario que va a recibir los mensajes. Lo he llamado Form2, slo
posee un label llamado "label1" y ste es su cdigo:
P g i n a 13 | 19
Progamacion Visual
TEMA 5
Ahora voy a crear un array de botones en Form1 con los que le mandar mensajes a Form2:
Debo tener cuidado de evaluar que mi evento "Enviar" no sea nulo o lanzar una excepcin. Esto
ocurre si Form2 no se ha cargado. Luego aado un botn desde la barra de herramientas del Visual
Studio con el que abrir Form2:
P g i n a 14 | 19
Progamacion Visual
TEMA 5
Si ejecuto la aplicacin, y abro tambin Form2, se ver cmo recibe los mensajes desde los botones
creados en el array:
P g i n a 15 | 19
Progamacion Visual
TEMA 5
P g i n a 16 | 19
Progamacion Visual
TEMA 5
Progamacion Visual
TEMA 5
C#
//Recorremos con un ciclo for each cada control que hay en la coleccion Controls de un objeto
llamado 'control'
foreach(Control contHijo in control.Controls){
//Aqui va la lgica de lo queramos hacer, en mi ejemplo, voy a pintar de color azul el fondo de
todos los controles
contHijo.BackColor = Color.Blue;
}
VB.NET
'Recorremos con un ciclo for each cada control que hay en la coleccion Controls de un objeto
llamado 'control'
For Each contHijo As Control In control.Controls
'Aqui va la lgica de lo queramos hacer, en mi ejemplo, voy a pintar de color azul el fondo de
todos los controles
contHijo.BackColor = Color.Blue
Next
C#
Progamacion Visual
TEMA 5
//Preguntamos si el control tiene uno o mas controles dentro del mismo con la propiedad
'HasChildren'
//Si el control tiene 1 o ms controles, entonces llamamos al procedimiento de forma recursiva,
para que siga recorriendo los dems controles
if (contHijo.HasChildren) this.RecControles(contHijo);
//Aqui va la lgica de lo queramos hacer, en mi ejemplo, voy a pintar de color azul el fondo de
todos los controles
contHijo.BackColor = Color.Blue;
}
}
VB.NET
P g i n a 19 | 19