Programacion Visual en C#
Programacion Visual en C#
NET
Dpto. de Computacin
Guin de la prctica 1
OBJETIVOS
Aplicaciones que soportan mltiples documentos Barras de herramienta y de estado Uso de imgenes
TEMPORIZACIN
Desarrollo de la prctica: 2 semanas
BIBLIOGRAFA
Enciclopedia de Microsoft Visual C# Autor: Fco. Javier Ceballos Editorial: RA-MA.
Pgina 1
Guin de la prctica 1
PRCTICA 1 MDI
TABLA DE CONTENIDOS:
Introduccin ............................................................................................. 3 10. Esqueleto de una aplicacin MDI ..................................................... 4 10.1 Crear una ventana hija nueva .......................................................... 4 10.2 Cargar una imagen desde un recurso ............................................... 6 10.3 Ajustar la imagen a la ventana hija .................................................. 6 10.4 Rotar la imagen 90 ......................................................................... 7 10.5 Aadir texto a la imagen ................................................................. 8 10.6 Convertir la imagen a escala de grises ............................................. 8 10.7 Abrir y guardar imgenes .............................................................. 9 10.8 Aadir soporte para arrastrar y soltar ...................................... 11 10.9 Barras de herramientas y de estado................................................ 12 Posibles mejoras (Opcional) .................................................................. 14
Pgina 2
Guin de la prctica 1
Introduccin
Se crear una nueva aplicacin MDI que mostrar imgenes en sus ventanas hijas:
El programa podr mostrar las imgenes en su resolucin original (con barras de desplazamiento si fueran necesarias), o adaptadas al tamao de la ventana hija. Adems, ser posible realizar transformaciones a las imgenes, tales como aadir una rotacin de 90 o un texto predefinido. Las imgenes se cargarn desde los recursos del propio programa, o bien desde archivos bmp, jpg, gif, etc., durante la ejecucin. Tambin se permitir guardar las imgenes.
Pgina 3
Guin de la prctica 1
Agregue al men Archivo las rdenes Salir (cerrar el programa en su totalidad), Cerrar (cerrar la ventana hija activa) y Nuevo (crear una nueva ventana hija). Los manejadores de las dos ltimas rdenes los implementaremos posteriormente, mientras que el de Salir lo puede implementar ya (debe consistir simplemente en una llamada al mtodo Close del formulario principal).
Compilar y ejecutar para ver el resultado.
Pgina 4
Guin de la prctica 1
Haga clic con el botn derecho sobre la llamada a NuevaHija, y seleccione la opcin Generar cdigo auxiliar del mtodo. Modifique el mtodo generado segn se indica a continuacin:
private void NuevaHija(string ttulo) { VentanaHija hija = new VentanaHija(ttulo); hija.MdiParent = this; hija.PictureBox.SizeMode = PictureBoxSizeMode.AutoSize; hija.AutoScroll = true; hija.Show(); }
La clase VentanaHija no ha sido creada an. Para hacerlo, vaya al men Proyecto y seleccione la opcin Agregar Windows Forms> Windows Forms. Introduzca VentanaHija.cs como nombre para el nuevo archivo de cdigo. Arrastre un control PictureBox sobre el formulario de nombre m_PictureBox. Aada la siguiente propiedad a la clase VentanaHija recin creada:
public PictureBox PictureBox { get { return m_PictureBox; } }
A continuacin modifique el constructor de VentanaHija para que tome un parmetro ttulo de tipo string. Dentro del cuerpo de dicho constructor, aada la siguiente lnea tras la llamada a InitializeComponent:
this.Text = ttulo;
Esta propiedad nos permite acceder rpidamente a la ventana hija activa, y adems realiza la conversin cast a la clase VentanaHija de forma automtica. Aada ahora el siguiente manejador a la orden Archivo > Cerrar, que muestra cmo se utiliza la propiedad que acabamos de aadir:
private void archivo_cerrar_Click(object sender, EventArgs e) { this.HijaActiva.Close(); }
Sepa que el evento MdiChildActivate del formulario principal nos avisa cuando el usuario cambia la ventana hija activa.
Pgina 5
Guin de la prctica 1
Este mtodo asigna al control PictureBox de la ventana activa una imagen obtenida a partir de los recursos de la aplicacin.
Compilar y ejecutar para ver el resultado.
En el estado actual de la aplicacin, desde que el usuario crea una nueva ventana ejecutando Archivo > Nuevo hasta que carga una imagen con la orden correspondiente, la ventana no tiene ninguna imagen asociada, lo que posibilita actuaciones incorrectas. Para evitar esto, haga que al crear una nueva ventana se cargue automticamente la imagen del recurso. Elimine a continuacin la orden Imagen > Cargar, que ya no es necesaria.
Compilar y ejecutar para ver el resultado.
Al ejecutar la aplicacin puede ver que la barra de mens de la ventana hija se integra con la barra de mens del formulario principal, y que desaparece cuando no existe ninguna ventana hija. Sin embargo, existe un pequeo problema ya que el men Imagen aparece a la derecha de los mens Ventana y Ayuda, lo cual no es el comportamiento habitual de las aplicaciones de Windows. Para solucionar esto,
Pgina 6
Guin de la prctica 1
seleccione el men Imagen y cambie su propiedad MergeAction por Insert, y su propiedad MergeIndex por 2.
Compilar y ejecutar para ver el resultado.
Qu pasa cuando selecciona la opcin Ajustar a ventana y cambia el tamao de la ventana hija? Solucione este problema aadiendo un manejador al evento Resize de la clase VentanaHija. Modifique este manejador como se indica:
private void VentanaHija_Resize(object sender, EventArgs e) { if (this.PictureBox.SizeMode == PictureBoxSizeMode.Zoom) this.PictureBox.Size = this.ClientSize; }
Es importante dar informacin al usuario sobre si el modo Ajustar est activado en un determinado momento. Para ello, aada la siguiente lnea al final del manejador imagen_ajustar_Click (se supone que ha cambiado la propiedad Name de la orden Ajustar a ventana por menImagenAjustar):
menImagenAjustar.Checked = this.PictureBox.SizeMode == PictureBoxSizeMode.Zoom;
Pgina 7
Guin de la prctica 1
ello el mtodo RotateFlip de la clase Image. Tenga en cuenta que tendr que modificar el tamao del control PictureBox antes de efectuar la rotacin, o de lo contrario parte de la imagen se perder en el caso de no ser perfectamente cuadrada. Adems, no olvide llamar al mtodo Refresh del PictureBox cuando haya finalizado la rotacin, para repintarlo correctamente.
Compilar y ejecutar para ver el resultado.
El mtodo esttico FromImage de la clase Graphics nos proporciona un objeto con el que podemos dibujar sobre una imagen.
Compilar y ejecutar para ver el resultado.
Pgina 8
Guin de la prctica 1
new float[]{0.11f,0.11f,0.11f,0,0}, new float[]{0,0,0,1,0}, new float[]{0,0,0,0,1}}); ImageAttributes ia = new ImageAttributes(); ia.SetColorMatrix(cm); // Utilizar el mtodo DrawImage de gfx para redibujar la // imagen usando los atributos de imagen especificados por ia } // Refrescar el picture box }
Para que este cdigo funcione tendr que hacer visible el espacio de nombres System.Drawing.Imaging, al que pertenecen la clase ColorMatrix e ImageAttributes.
Compilar y ejecutar para ver el resultado.
Aada un men Archivo a la barra de mens del formulario VentanaHija. Cambie su propiedad MergeAction por MatchOnly. Esto har que se integre con el men
Pgina 9
Guin de la prctica 1
Archivo del formulario principal. Agregue al nuevo men dos rdenes Guardar y Guardar como, que se encargarn de guardar en disco la imagen mostrada en la ventana activa, y un separador. Cambie la propiedad MergeAction de estos tres elementos por Insert, y su propiedad MergeIndex por 3, 4 y 5, respectivamente, para que se inserten en el lugar apropiado del men Archivo del formulario principal. Utilice el siguiente esquema para el manejador de Guardar como:
private void archivo_guardarComo_Click(object sender, EventArgs e) { // Mostrar dilogo SaveFileDialog y configurarlo de forma // anloga al OpenFileDialog de la opcin "Abrir" // Si el resultado del dilogo es distinto de OK, terminar if (dlgGuardar.FileName.ToUpper().EndsWith(".JPG")) // Usar el mtodo Save para guardar la imagen en formato jpg //Anlogamente con el resto de formatos permitidos // Actualizar ttulo de esta ventana }
Respecto al manejador de Guardar, debe tener en cuenta que si el ttulo de la ventana es DocN entonces la imagen no ha sido guardada con anterioridad, por lo que el proceso es anlogo al de Guardar como. En cambio, si el ttulo de la ventana ya es el de una ruta de un archivo, simplemente hay que guardar la imagen en esa ruta:
private void archivo_guardar_Click(object sender, EventArgs e) { if (ttulo de la hija activa comienza con "Doc") // Mismo cdigo que "Guardar como..." else // La guardamos en el mismo archivo del que se la lemos }
Para evitar tener cdigo duplicado, utilice la herramienta de refactorizacin para convertir el cdigo del manejador de Guardar como en un nuevo mtodo GuardarComo al que llamen tanto dicho manejador como el de Guardar.
Compilar y ejecutar para ver el resultado.
Ejecute su aplicacin y seleccione, sin haber abierto ninguna ventana, la orden Archivo > Cerrar. Qu pasa? El manejador de dicha orden espera que exista una ventana activa sobre la que trabajar, pero en este caso no la hay (la propiedad ActiveMdiChild vale null). Como resultado, el entorno de ejecucin lanza una excepcin de tipo NullReferenceException. Para evitar esto existen dos enfoques posibles. Uno de ellos pasa por comprobar, en los mtodos de la clase VisorImgenes en los que sea oportuno, que existe una ventana activa. As por ejemplo, podramos aadir al comienzo del manejador de la orden Archivo > Cerrar el siguiente cdigo:
private void archivo_cerrar_Click(object sender, EventArgs e) { if(this.HijaActiva == null)
Pgina 10
Guin de la prctica 1
MessageBox.Show("No hay ninguna ventana activa","Error", MessageBoxButtons.OK,MessageBoxIcon.Error); return; } // Lo dems igual que antes }
Otro enfoque ms intuitivo para el usuario consiste en no mostrar las rdenes que trabajan sobre la ventana activa cuando dicha ventana no existe, o mostrarlas inhabilitadas. Un buen sitio para hacer esto es el manejador del evento MdiChildActivate, que es invocado cada vez que se cambia la ventana hija activa. Por ejemplo, para conseguir que la orden Archivo > Cerrar aparezca inhabilitada cuando no exista ninguna ventana sobre la que trabajar, aada el siguiente cdigo al final de dicho manejador:
menArchivoCerrar.Enabled = this.HijaActiva != null;
Deber hacer lo propio con el resto de opciones de men que no tengan sentido si no existe una ventana activa (por ejemplo, Ventana > Mosaico). Use la herramienta de refactorizacin para extraer todo este cdigo en un nuevo mtodo llamado ActualizarMens, y llame a este mtodo tambin desde el constructor para que inicialmente los mens aparezcan en el estado correcto.
Compilar y ejecutar para ver el resultado.
Pgina 11
Guin de la prctica 1
if (!file.ToUpper().EndsWith(".JPG") && !file.ToUpper().EndsWith(".BMP") && !file.ToUpper().EndsWith(".GIF")) { e.Effect = DragDropEffects.None; // Uno de los archivos no // es una imagen return; } } e.Effect = DragDropEffects.Copy; // Correcto, son todo imgenes }
Este manejador nos permite seleccionar qu tipos de objetos se pueden arrastrar sobre nuestra aplicacin (en este caso, archivos de extensin jpg, bmp o gif). Si el usuario arrastra un objeto que no corresponde a esta descripcin, el cursor adopta la forma de un signo de prohibicin y la operacin no se puede finalizar.
Compilar y ejecutar para ver el resultado.
Aada a continuacin el siguiente manejador del evento DragDrop, que se encarga de abrir los archivos arrastrados una vez que el usuario ha soltado el botn del ratn:
private void VisorImgenes_DragDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach (string file in files) AbrirArchivo(file); }
Deber aadir el mtodo AbrirArchivo, que tendr una implementacin similar a la de las ltimas lneas del manejador de la orden Archivo > Abrir. Para evitar duplicar cdigo, genere este mtodo usando la herramienta de refactorizacin Extraer mtodo.
Compilar y ejecutar para ver el resultado.
Pgina 12
Guin de la prctica 1
Como vimos en un apartado anterior, el men Imagen y la parte del men Archivo correspondiente a las rdenes de guardar son especiales, ya que pertenecen a la ventana hija activa, pero aparecen integrados con el men principal. Sus correspondientes botones de barra de herramientas se comportarn de forma anloga. Para ello, aada una barra de herramientas al formulario VentanaHija. Desactive la propiedad Visible de esta barra de herramientas, y aada botones para las rdenes Guardar, Ajustar a ventana, Aadir texto, Rotar y Escala de grises. Inserte un separador entre las dos primeras y asocie a cada botn el manejador de la opcin de men correspondiente. Para que los botones de la nueva barra de herramientas se inserten en el lugar apropiado de la barra principal tendr que cambiar su propiedad MergeAction por Insert. Cambie tambin su propiedad MergeIndex dndole a cada botn un valor que permita que se inserte donde le corresponde (ver figura siguiente). A diferencia de las barras de mens, la fusin de las barras de herramientas no es automtica, sino que hay que llamar explcitamente al mtodo Merge de ToolStripManager. El sitio ms apropiado para realizar esta operacin es el manejador del evento MdiChildActivate del formulario MDI:
private void VisorImgenes_MdiChildActivate( object sender, EventArgs e) { // ... ToolStripManager.RevertMerge(this.barraHerramientas); VentanaHija ventanaHijaActiva = this.ActiveMdiChild as VentanaHija; if (ventanaHijaActiva != null) ToolStripManager.Merge(ventanaHijaActiva.barraHerramientas, this.barraHerramientas); }
Guin de la prctica 1
No olvide que el botn correspondiente a la orden Ajustar a ventana debe aparecer marcado (Checked=true) cuando esta opcin se encuentre activada para la ventana hija activa.
Compilar y ejecutar para ver el resultado.
A continuacin aadir una barra de estado. Para ello, aada un control StatusStrip al formulario VisorImgenes desde la caja de herramientas. A continuacin, coloque en ella una etiqueta de texto de estado (StatusLabel) llamada etiquetaEstado. Active la propiedad Spring de esta etiqueta, y cambie su propiedad TextAlign a MiddleLeft. Haciendo uso de los eventos MouseEnter y MouseLeave de los mens, botones, etc., muestre la informacin que desee en la barra de estado (por ejemplo, para la orden de men Archivo > Nuevo y para su correspondiente botn de la barra de herramientas puede mostrar el texto Crea una nueva ventana con una imagen predefinida.
Compilar y ejecutar para ver el resultado.
Para finalizar deber agregar al men Ver rdenes que permitan mostrar u ocultar la barra de estado y la barra de herramientas. Estas rdenes debern aparecer marcadas (Checked=true) cuando la barra correspondiente est visible (pista: use el evento DropDownOpened del men Ver).
Compilar y ejecutar para ver el resultado.
Pgina 14