Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Desarrollo de Aplicaciones Windows. Aspectos Avanzados (Ejemplo)
Desarrollo de Aplicaciones Windows. Aspectos Avanzados (Ejemplo)
Aspectos avanzados
Sipnosis
Texto dirigido a aquellas personas que quieran iniciarse en la creacin de aplicaciones para entorno Windows, empleando Visual Studio 2005. Como lenguajes de programacin se utilizan Visual Basic y C#. Se trata de una obra organizada alrededor de tres bloques principales de contenidos. El primer bloque abarca los captulos versados en la creacin de proyectos sencillos, utilizando Visual Studio 2005 como herramienta de desarrollo. El segundo bloque se adentra en los dos lenguajes de programacin, explicando aquellas caractersticas ms importantes de cada uno. Finalmente, el tercer bloque se encuentra enfocado en el diseo e implementacin de aplicaciones Windows, haciendo uso del conjunto de tipos ofrecidos por la plataforma .NET Framework al programador, as como del numeroso grupo de diseadores y asistentes del entorno de desarrollo. A lo largo de todo el texto, el lector encontrar un gran nmero de ejemplos prcticos que le permitirn aplicar de forma inmediata todos aquellos conceptos aprendidos en los diferentes captulos de que se compone esta obra.
Luis Miguel Blanco trabaja como Arquitecto de Software en Alhambra Eidos, siendo uno de los titulados MCSD de reconocido prestigio entre el colectivo de desarrolladores .NET en Espaa y Latinoamerica. Desde su posicin en la compaa ha partipado en numerosos proyectos de desarrollo de software, tanto para la administracin pblica como para la empresa privada. En lneas generales, sus reas de especializacin abarcan Visual Basic .NET, ASP.NET y SQL Server en sus aspectos relacionados con los servicios OLAP y Reporting Services. Mantiene un blog relacionado con diversos aspectos del desarrollo en la plataforma .NET, tales como ASP.NET, AJAX, Silverlight, etc., en la direccin: http://geeks.ms/blogs/lmblanco/.
Luarna
Desarrollo de Aplicaciones Windows. Aspectos Avanzados Luis Miguel Blanco Alhambra Eidos De esta edicin: 2009, Luarna Ediciones, S.L. www.luarna.com
Cualquier forma de reproduccin, distribucin, comunicacin pblica o transformacin de esta obra solo puede ser realizada con la autorizacin de sus titulares, salvo excepcin prevista por la ley. Dirjase a CEDRO (Centro Espaol de Derechos Reprogrficos, www.cedro.org) si necesita fotocopiar, escanear o hacer copias digitales de algn fragmento de esta obra.
A mi hijo David, un muchacho valiente a pesar de su juventud, cuya contagiosa alegra llena de felicidad mis das. A mi esposa Olga, la mejor compaera que nadie podra desear para recorrer el viaje de la vida. Su compaa hace que el camino sea ms liviano y alegre. A mi madre Antonia, por todos los nimos que me ha dado siempre que me he embarcado en la dura, pero gratificante labor de escribir un libro. A mi hermano Carlos, por su admirable espritu libre e indmito. A mi hermano Roberto, del que espero cumpla su sueo de viajar al pas del sol naciente. Ha trabajado para ello como pocos, y se lo merece ms que muchos. A mi padre Isaas, por transmitirme la aficin al sptimo arte.
Indice
Introduccin .................................................................................................................................... 12 Caractersticas avanzadas, pero en gran medida necesarias ............................................................ 12 GDI+ y construccin de controles personalizados .......................................................................... 12 ADO.NET y el enlace de datos a controles .................................................................................... 12 Creacin de informes .................................................................................................................... 13 Flujos de datos y manipulacin de archivos ................................................................................... 13 Utilizacin del Portapapeles y de las operaciones de Arrastrar y soltar .......................................13 Programacin de procesos asncronos y multihebra ....................................................................... 13 Instalacin de aplicaciones ............................................................................................................ 13 GDI+. Manipulacin de grficos en .NET Framework .................................................................14 System.Drawing............................................................................................................................ 15 La clase Graphics .......................................................................................................................... 15 Especificando coordenadas. La clase Point .................................................................................... 15 Definiendo tamaos. La clase Size ................................................................................................ 16 Combinando coordenadas y tamaos. La clase Rectangle .............................................................. 16 La clase Pen. Componiendo todo para dibujar ............................................................................... 17 La estructura Color ....................................................................................................................... 18 Repintado de reas invalidadas ......................................................................................................18 Dibujo de figuras varias con la clase Pen ....................................................................................... 19 La clase Brush .............................................................................................................................. 23 Creacin de figuras complejas con la clase GraphicsPath .............................................................. 25 Aplicacin de efectos avanzados con la clase Brush ...................................................................... 27 Objetos grficos con caractersticas del sistema ............................................................................. 29 Dibujo de texto en el formulario .................................................................................................... 30 Personalizacin de la imagen de fondo del formulario ................................................................... 31 Manipulacin de los eventos de pintado en la clase form ........................................................... 31 El control picturebox ................................................................................................................. 32 Manipulando el grado de opacidad del formulario ......................................................................... 33 Creacin de formularios con formas irregulares ............................................................................. 37 Usando la clase region............................................................................................................... 37 Usando una imagen para definir la superficie del formulario ...................................................... 40 Dibujo manual de elementos de un control .................................................................................... 44 La clase ToolStripRenderer.Aplicando GDI+ en la presentacin de la barra de herramientas ......... 49 Caso prctico. Creacin y aplicacin de un degradado de colores .................................................. 55 Creacin de controles de usuario....................................................................................................56 Crear una clase derivada de un control concreto ............................................................................ 56 Provocar por cdigo un evento del control ................................................................................. 59 Creacin de controles de usuario. Heredando de UserControl ........................................................ 61 Diseo visual ............................................................................................................................ 62 Probando el control en el formulario.......................................................................................... 63 Agregando propiedades al control ............................................................................................. 65 Codificacin de los mtodos ...................................................................................................... 67 Redimensionamiento de los controles constituyentes ................................................................. 68 Proporcionar informacin adicional al control mediante atributos .............................................. 70 Asignacin de una imagen para el cuadro de herramientas ......................................................... 73 Caso prctico. Desarrollo y utilizacin de un control de usuario .................................................... 75
Pgina |6
Creacin de controles personalizados ............................................................................................ 77 Heredando de la clase Control ....................................................................................................... 77 El control a crear ........................................................................................................................... 77 Creacin del proyecto ................................................................................................................... 78 La clase del control personalizado y la clase Control, muchos aspectos en comn.......................... 79 El rombo para la casilla de marcado ..............................................................................................80 Dibujando el resto de elementos de la casilla ................................................................................. 82 Visualizando el literal del ttulo ..................................................................................................... 84 Organizando las operaciones de dibujo en el cdigo de la clase ..................................................... 86 Controlando por cdigo el marcado de la casilla ............................................................................ 89 Refinando el marcado inicial de la casilla ...................................................................................... 91 Marcando la casilla con el ratn ....................................................................................................92 La barra espaciadora tambin cambia el estado de la casilla ...........................................................95 Detectando el estado desde el cdigo cliente ................................................................................. 95 Indicacin visual de la captura del foco ......................................................................................... 96 Cambiando la alineacin de la casilla ............................................................................................ 99 Coloreando el rombo ................................................................................................................... 107 Creacin de formularios derivados .............................................................................................. 110 El selector de herencia de VS 2005 ............................................................................................. 110 Desarrollo del formulario base .................................................................................................... 110 Creacin del formulario derivado mediante el selector de herencia .............................................. 112 Tratamiento de errores ................................................................................................................. 116 Errores, ese mal comn ............................................................................................................... 116 Errores de escritura ................................................................................................................. 116 Errores de ejecucin ................................................................................................................ 117 Errores lgicos ........................................................................................................................ 118 Errores y excepciones ................................................................................................................. 118 Manipuladores de excepciones .................................................................................................... 118 Manipulacin estructurada de errores .......................................................................................... 118 La estructura try...end try / try {} ......................................................................................... 118 La clase exception ................................................................................................................... 122 Captura de excepciones de diferente tipo en el mismo controlador de errores ........................... 123 Establecer en vb una condicin para un manipulador de excepciones ....................................... 125 La influencia del orden de los manipuladores de excepciones .................................................. 127 Forzar la salida de un controlador de errores en vb mediante exit try........................................ 129 Manipulacin no estructurada de errores en VB........................................................................... 132 El objeto err ............................................................................................................................ 133 On error .................................................................................................................................. 133 On error goto etiqueta ............................................................................................................. 133 On error resume next ............................................................................................................... 134 Creacin de errores con el objeto err........................................................................................ 134 On error goto 0 ........................................................................................................................ 135 Manipulacin de datos con ADO.NET ......................................................................................... 136 Aplicaciones de gestin de datos ................................................................................................. 136 El acceso a datos desde ADO.NET.............................................................................................. 136 Trabajo con datos en modo conectado ......................................................................................... 138 Crear una copia de la base de datos ............................................................................................. 138 Conexin con un origen de datos. La clase Connection................................................................ 142 Ejecutando sentencias. La clase Command .................................................................................. 144 Recorriendo conjuntos de resultados. La clase DataReader .......................................................... 149 Trabajo con datos en modo desconectado .................................................................................... 153 Estructuras de datos en memoria. La clase DataSet y sus complementarias .................................. 154
Pgina |7
Adaptadores de datos. La clase DataAdapter ............................................................................... 157 Creacin de mantenimientos de datos .......................................................................................... 162 Mantenimiento de datos en modo desconectado .......................................................................... 162 Creacin de un mantenimiento manual ........................................................................................ 163 Agregar seleccin de valores desde tablas catlogo...................................................................... 172 Mantenimiento con enlace automtico de controles a datos. Data Binding ................................... 179 Controlar errores de edicin mediante un componente ErrorProvider ........................................... 185 Creacin manual del enlace entre controles y datos ..................................................................... 188 Enlazar controles con campos de valores especiales .................................................................... 191 Bsquedas y vistas de datos .......................................................................................................... 194 Proporcionar capacidades de bsqueda, filtro y ordenacin de registros ....................................... 194 Crear un sistema de bsqueda mediante el componente TableAdapter ......................................... 194 Invocar la consulta por cdigo ................................................................................................. 196 Obtener varios registros de la consulta..................................................................................... 197 Restaurar el conjunto de registros inicial ................................................................................. 197 Vistas de datos. La clase DataView ............................................................................................. 198 Vista bsica y predeterminada ................................................................................................. 199 Creacin de un filtro mediante una vista .................................................................................. 200 Vistas simultneas de la misma tabla ....................................................................................... 202 Ordenacin de registros ........................................................................................................... 203 Caso prctico. Realizacin de un mantenimiento de datos con Data Binding automtico .............. 205 El control DataGridView. Diseo visual ...................................................................................... 206 Creacin y diseo visual ............................................................................................................. 206 Agregar y eliminar columnas ...................................................................................................... 207 Configuracin de slo consulta.................................................................................................... 209 Cambiar las posiciones originales de las columnas ...................................................................... 210 Establecer columnas fijas ............................................................................................................ 210 Ordenar columnas ....................................................................................................................... 211 Estilo de cabeceras de columna ................................................................................................... 211 Estilo y propiedades de celdas ..................................................................................................... 212 Estilo de cabeceras de fila ........................................................................................................... 214 Estilo de seleccin de columna .................................................................................................... 214 Visualizacin de filas con colores alternos................................................................................... 215 Visualizacin de campos de tipo imagen ..................................................................................... 216 El control DataGridView. Manipulacin por cdigo .................................................................. 218 Creacin y manipulacin por cdigo ........................................................................................... 218 Manejo bsico de columnas y ordenacin .................................................................................... 218 Creacin de estilos y aplicacin de formatos ............................................................................... 221 Pintado manual de celdas. El evento CellPainting, la clase DataGridViewCellPaintingEventArgs y la clase TextRenderer .................................................... 224 Dividiendo el texto de la celda en varias lneas ........................................................................ 228 Edicin de datos .......................................................................................................................... 231 Obtener informacin relativa a la fila y columna actual. El evento cellenter ............................. 233 Borrando filas. El evento userdeletingrow ............................................................................... 234 Manejo de errores de edicin. El evento dataerror.................................................................... 235 Validacin de celdas. Los eventos cellvalidating y rowvalidating ............................................ 236 Tipos de columna del control DataGridView ............................................................................... 238 DataGridViewCheckBoxColumn ............................................................................................ 239 DataGridViewButtonColumn .................................................................................................. 240 DataGridViewComboBoxColumn ........................................................................................... 244 DataGridViewImageColumn ................................................................................................... 248 DataGridViewLinkColumn ..................................................................................................... 251
Pgina |8
Construccin de un formulario de consulta maestro/detalle utilizando controles DataGridView ... 254 Caso prctico. Visualizacin de datos mediante el control DataGridView .................................... 258 Impresin y generacin de informes ............................................................................................ 260 El proceso de impresin en la plataforma .NET Framework ........................................................ 260 La clase PrintDocument .............................................................................................................. 260 El mecanismo de impresin......................................................................................................... 261 Impresin de una lnea de texto ................................................................................................... 261 Visualizacin previa de la impresin ........................................................................................... 263 Previsualizando mediante PrintPreviewDialog......................................................................... 263 Previsualizar manualmente con el control PrintPreviewControl ............................................... 264 Impresin de varias lneas de texto .............................................................................................. 266 Configuracin del trabajo de impresin ....................................................................................... 270 Configuracin de la pgina a imprimir ........................................................................................ 272 Impresin de grficos .................................................................................................................. 274 Impresin de grficos a color................................................................................................... 276 El control ReportViewer ............................................................................................................. 278 Imprimir con Crystal Reports para Visual Studio .NET ............................................................... 280 Espacios de nombres de Crystal Reports para Visual Studio 2005 ............................................... 281 Creacin de un informe con el asistente de Crystal Reports ......................................................... 281 El diseador de informes ............................................................................................................. 286 El control CrystalReportViewer .................................................................................................. 288 Establecer por cdigo la informacin de conexin al origen de datos ........................................... 291 Caso prctico. Impresin de un archivo de texto .......................................................................... 292 Flujos de datos .............................................................................................................................. 294 El espacio de nombres System.IO ............................................................................................... 294 Objetos Stream ........................................................................................................................... 294 Las clases TextReader y TextWriter ............................................................................................ 295 La clase StreamWriter ................................................................................................................. 295 La clase StreamReader ................................................................................................................ 297 Las clases StringWriter y StringReader ....................................................................................... 300 La clase Stream........................................................................................................................... 300 La clase FileStream ..................................................................................................................... 301 Grabacin y recuperacin de documentos en una base de datos................................................ 303 Manejo de datos binarios ............................................................................................................. 306 Caso prctico. Lectura y escritura de archivos mediante flujos de datos ....................................... 307 Manipulacin del sistema de archivos .......................................................................................... 308 Manipulacin de archivos mediante File y FileInfo ..................................................................... 308 Manipulacin de directorios mediante Directory y DirectoryInfo ................................................. 311 La clase Path ............................................................................................................................... 315 El control SplitContainer ............................................................................................................. 315 El componente ImageList ............................................................................................................ 316 El control TreeView .................................................................................................................... 317 Creacin y diseo .................................................................................................................... 318 Manipulacin por cdigo ......................................................................................................... 321 Creacin a partir de un origen de datos XML........................................................................... 328 El control ListView ..................................................................................................................... 331 Creacin y diseo .................................................................................................................... 332 Manipulacin por cdigo ......................................................................................................... 337 Cuadros de dilogo para la gestin del sistema de archivos .......................................................... 343 OpenFileDialog ....................................................................................................................... 344 FolderBrowserDialog .............................................................................................................. 346 SaveFileDialog........................................................................................................................ 347 El componente FileSystemWatcher. Monitorizacin del sistema de archivos ............................... 349
Pgina |9
Deteccin con espera, de eventos producidos sobre archivos ................................................... 352 Manipulacin de archivos mediante funciones de VB .................................................................. 353 Caso prctico. Creacin de un formulario de navegacin por tipo de archivo ............................... 354 Manejo del Portapapeles y procesos de Arrastrar y soltar ...................................................... 355 El Portapapeles del sistema. Un medio efectivo para intercambiar informacin ........................... 355 Situar informacin en el Portapapeles .......................................................................................... 355 Obtener contenidos del Portapapeles ........................................................................................... 356 Manipulando un objeto propio en el Portapapeles ........................................................................ 357 Desplazamiento de informacin mediante Arrastrar y soltar ..................................................... 359 Creacin de una operacin de arrastrar y soltar sencilla ........................................................... 360 Comienzo de la operacin. Arrastrar un valor ...................................................................... 360 Fin de la operacin. Soltar el valor ....................................................................................... 361 Copiar y mover datos al arrastrar y soltar................................................................................. 362 Copiar archivos mediante un formulario explorador propio...................................................... 366 Caso prctico. Desarrollo de un proceso de arrastrar y soltar........................................................ 369 Programacin de procesos asncronos. Manipulacin de hebras de ejecucin ........................... 370 El problema en la ejecucin de tareas simultneas ....................................................................... 370 BackgroundWorker ..................................................................................................................... 371 Controlando el progreso de la ejecucin en segundo plano....................................................... 376 Cancelando la ejecucin de la tarea en segundo plano.............................................................. 379 Manejo de controles con soporte de funcionamiento asncrono .................................................... 381 Hebras de ejecucin .................................................................................................................... 383 La clase Thread ........................................................................................................................... 383 Ejecucin de procesos en hebras.................................................................................................. 384 La clase manipuladora de hebras ............................................................................................. 384 Comunicacin entre hebras y formulario ................................................................................. 390 Creacin y ejecucin de hebras desde el propio formulario .......................................................... 395 Control de procesos indefinidos .................................................................................................. 397 Ejecucin multihebra .................................................................................................................. 400 Ejecucin multihebra de mltiples procesos ................................................................................ 402 Creando un proceso de monitorizacin ........................................................................................ 412 Inicios de aplicacin con dos formularios empleando hebras ....................................................... 415 Caso prctico. Ejecucin de una tarea en segundo plano .............................................................. 417 Configuracin de programas mediante ajustes de aplicacin ..................................................... 418 Configurando la aplicacin desde el exterior ............................................................................... 418 Creacin de ajustes de aplicacin ................................................................................................ 419 Creacin de un ajuste de aplicacin desde la ventana de propiedades del formulario ................ 419 Creacin de un ajuste de aplicacin desde la ventana de propiedades del proyecto ................... 421 El contenido del archivo de configuracin ................................................................................... 422 Modificacin de ajustes de aplicacin ......................................................................................... 423 Manteniendo los cambios realizados a los ajustes ........................................................................ 424 Restaurando los valores originales de los ajustes ......................................................................... 424 Enlace entre ajustes de aplicacin y propiedades de objetos ......................................................... 425 Caso prctico. Creacin de ajustes de aplicacin ......................................................................... 427 El control PropertyGrid ............................................................................................................... 428 Edicin visual de propiedades con PropertyGrid.......................................................................... 428 Cambiando la presentacin del control PropertyGrid ............................................................... 436 Caso prctico. Configuracin de las propiedades de un objeto mediante el control PropertyGrid .. 438 Resolucin Casos prcticos ........................................................................................................... 439 Captulo 2 ................................................................................................................................... 439 Captulo 3 ................................................................................................................................... 442
P g i n a | 10
Captulo 9 ................................................................................................................................... 450 Captulo 11 ................................................................................................................................. 456 Captulo 12 ................................................................................................................................. 460 Captulo 13 ................................................................................................................................. 464 Captulo 14 ................................................................................................................................. 466 Captulo 15 ................................................................................................................................. 470 Captulo 16 ................................................................................................................................. 472 Captulo 17 ................................................................................................................................. 477 Captulo 18 ................................................................................................................................. 480
P g i n a | 11
Introduccin
Caractersticas avanzadas, pero en gran medida necesarias
En el presente texto realizaremos un recorrido por aquellos aspectos avanzados de la programacin con formularios Windows, lo cual no significa que algunos de ellos no se encuentren entre las caractersticas que debemos implementar en la mayora de las aplicaciones que habitualmente desarrollamos. A grandes rasgos, los siguientes apartados describen las reas del desarrollo que abordaremos en la actual obra.
P g i n a | 12
programador en el tratamiento de la informacin. El nuevo control DataGridView, sucesor de DataGrid, ofrece un elevado nmero de caractersticas que le confieren una potencia en la presentacin y edicin de datos muy superior a su antecesor.
Creacin de informes
La gestin de los procesos de impresin y generacin de informes tambin es abordada en esta obra, donde se tratan tanto las tcnicas para la impresin manual de documentos mediante los tipos disponibles en .NET Framework-, como a travs del control ReportViewer, que permite el diseo de informes para SQL Server Reporting Services, y el tambin generador de informes Crystal Reports.
Instalacin de aplicaciones
Gracias a la tecnologa ClickOnce, el despliegue e instalacin de una aplicacin se simplifica enormemente. Podemos configurar un proyecto de instalacin desde variados orgenes: ruta de archivo tradicional, sitio Web, servidor FTP, etc., lo cual facilita y flexibiliza las posibilidades de distribucin del programa. Tambin es posible configurar el despliegue de una aplicacin para que su ejecucin se realice desde un servidor centralizado, o sea descargada en las mquinas cliente del usuario, as como efectuar actualizaciones peridicas de dicha aplicacin.
P g i n a | 13
Si somos programadores de VB, recordaremos que en las versiones de este lenguaje anteriores a .NET, el objeto Form dispona de una serie de mtodos y controles para el dibujo sobre la superficie del formulario. La mayor parte de esos elementos han desaparecido en la versin de VB para .NET, integrndose todas las operaciones de dibujo en los diversos tipos de la plataforma .NET Framework relacionados con el apartado grfico; gracias a esta caracterstica, lo que aprendamos trabajando con grficos en un lenguaje orientado a .NET utilizando GDI+, nos servir igualmente si en un futuro
P g i n a | 14
debemos abordar un proyecto en otro lenguaje de la plataforma, ya que las clases pertenecen a .NET Framework y no a un lenguaje en particular. Otro problema con el que nos enfrentbamos anteriormente era el hecho de que al necesitar alguna manipulacin grfica especial, tenamos que recurrir al acceso directo a la API de Windows, con las complejidades que ello comportaba. A partir de ahora esto no ser necesario, ya que como hemos comentado, es el propio entorno de ejecucin de .NET el que nos proporciona dicho acceso, por lo que no ser necesario acudir a la API del sistema operativo.
System.Drawing
Se trata del espacio de nombres contenedor de los tipos principales para el trabajo con grficos en NET, por lo que deberemos declararlo al comienzo de nuestros archivos de cdigo, o especificarlo al acceder a cualquiera de sus clases, estructuras, etc. System.Drawing contiene el conjunto de tipos principales, aunque no es el nico espacio de nombres de GDI+. Para tareas de mayor especializacin con grficos deberemos recurrir a otros espacios de nombres que tambin estn dentro de System.Drawing: Drawing2D (generacin de grficos complejos), Imaging (tratamiento de archivos de imagen), Text (manipulacin de texto), Printing (impresin de grficos), etc.
La clase Graphics
La clase Graphics representa el denominado Contexto de dispositivo grfico (Graphics device context), o elemento (objeto) sobre el que se va a realizar una operacin de dibujo, por ejemplo, el formulario. Debido a la arquitectura del sistema grfico, no es posible tomar un objeto Form y realizar una operacin directa de dibujo sobre el mismo, sino que precisamos en primer lugar, obtener una referencia hacia el rea de dibujo de dicho formulario, o contexto grfico, y una vez obtenida esa referencia, efectuar el dibujo. Esta rea la vamos a obtener mediante el mtodo CreateGraphics() de la clase Form, que devuelve un objeto Graphics con la informacin del contexto de dispositivo grfico del formulario. Ver el Cdigo fuente 1.
Dim oGraphics As Graphics oGraphics = Me.CreateGraphics() Graphics oGraphics; oGraphics=this.CreateGraphics(); Cdigo fuente 1
Obtenido el contexto grfico sobre el que vamos a dibujar, ya podemos generar grficos en el formulario utilizando alguno de los mtodos de esta clase, como veremos posteriormente.
P g i n a | 15
Point trabaja con valores enteros, pero si necesitamos ser ms precisos al indicar las coordenadas de dibujo, disponemos tambin de la clase PointF, que nos permite establecer coordenadas con precisin decimal. Ver el Cdigo fuente 2.
Dim oPuntoUno As New Point(10, 150) Dim oPuntoDos As PointF oPuntoDos = New PointF(45.6, 88.2) Point oPuntoUno = new Point(10, 150); PointF oPuntoDos; oPuntoDos = new PointF(45.6, 88.2); Cdigo fuente 2
P g i n a | 16
Asociando este cdigo a la pulsacin de un botn en el formulario, el resultado ser el dibujo del crculo mostrado en la Figura 1.
P g i n a | 17
La estructura Color
Esta estructura nos permite seleccionar los colores existentes y definir colores personalizados. Su uso ms simple consiste en escribir su nombre seguido del operador punto y el nombre del color a utilizar, tal y como acabamos de comprobar en el ejemplo previo. Tambin posible la creacin de un color mediante su mtodo FromArgb(), en el que definimos un color mediante un conjunto de valores numricos que permiten especificar el grado de transparencia (Alpha) y los colores bsicos rojo, verde y azul. El parmetro Alpha es opcional, no siendo necesario su uso si no necesitamos usar el grado de transparencia. Otros mtodos disponibles para la creacin de un color son FromName(), que recibe una cadena con el nombre del color a crear, y FromKnownColor(), al que pasamos un valor de la enumeracin KnownColor, que contiene un conjunto de colores predefinidos. Veamos unos ejemplos en el Cdigo fuente 6.
Dim oColor As Color oColor = Color.FromArgb(140, 200, 30, 60) oColor = Color.FromName("Yellow") oColor = Color.FromKnownColor(KnownColor.Firebrick) Color oColor; oColor = Color.FromArgb(140, 200, 30, 60); oColor = Color.FromName("Yellow"); oColor = Color.FromKnownColor(KnownColor.Firebrick); Cdigo fuente 6
P g i n a | 18
Dim oGraph As Graphics = e.Graphics ' dibujar en el formulario oGraph.DrawRectangle(oPen, New Rectangle(40, 80, 70, 70)) oGraph.Dispose() End Sub private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { // crear objeto Pen Pen oPen = new Pen(Color.MediumVioletRed, 6); // obtener el contexto de dispositivo // grfico del formulario; // en este caso usaremos el objeto que contiene // los argumentos de evento para obtener dicho // contexto de dispositivo Graphics oGraph = e.Graphics; // dibujar en el formulario oGraph.DrawRectangle(oPen, new Rectangle(40, 80, 70, 70)); Cdigo fuente 7
Al ejecutar el programa, el rectngulo ser mostrado en todo momento, aunque minimicemos el formulario, lo ocultemos parcial o totalmente, etc., ya que este evento se ejecuta automticamente cada vez que el formulario detecta que su superficie ha quedado invalidada y necesita repintarse. Ver la Figura 2.
P g i n a | 19
' obtener el contexto de dispositivo ' grfico del formulario Dim oGraphics As Graphics = Me.CreateGraphics() ' dibujar en el formulario oGraphics.DrawEllipse(oPen, New Rectangle(250, 150, 65, 120)) oGraphics.Dispose() End Sub private void mnuElipse_Click(object sender, EventArgs e) { // crear objeto Pen Pen oPen = new Pen(Color.DarkTurquoise, 2); // obtener el contexto de dispositivo // grfico del formulario Graphics oGraphics = this.CreateGraphics(); // dibujar en el formulario oGraphics.DrawEllipse(oPen, new Rectangle(250, 150, 65, 120)); oGraphics.Dispose(); Cdigo fuente 8
Al dibujar un rectngulo vamos a modificar el estilo de lnea mediante la propiedad DashStyle. Esta propiedad contiene una enumeracin con la que podemos hacer que la lnea se muestre como guiones, guiones y puntos, etc. Ver el Cdigo fuente 9.
Private Sub mnuRectangulo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuRectangulo.Click ' crear objeto Pen Dim oPen As New Pen(Color.Firebrick, 4) ' aplicar un estilo de lnea con la propiedad ' DashStyle --> guin, punto oPen.DashStyle = Drawing.Drawing2D.DashStyle.DashDot ' obtener el contexto de dispositivo ' grfico del formulario Dim oGraphics As Graphics = Me.CreateGraphics() ' dibujar en el formulario oGraphics.DrawRectangle(oPen, New Rectangle(280, 75, 120, 40)) oGraphics.Dispose() End Sub private void mnuRectangulo_Click(object sender, EventArgs e) { // crear objeto Pen Pen oPen = new Pen(Color.Firebrick, 4); // aplicar un estilo de lnea con la propiedad // DashStyle --> guin, punto oPen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot; // obtener el contexto de dispositivo // grfico del formulario Graphics oGraphics = this.CreateGraphics(); // dibujar en el formulario oGraphics.DrawRectangle(oPen, new Rectangle(280, 75, 120, 40)); oGraphics.Dispose(); Cdigo fuente 9
P g i n a | 20
Si queremos aplicar ms estilos a la lnea del objeto Pen, disponemos tambin de las propiedades StartCap, EndCap, DashCap. El Cdigo fuente 10 muestra el dibujo de una curva con varios efectos de lnea. Al dibujar una curva, necesitamos pasar al mtodo DrawCurve() un array de tipos Point, con las coordenadas de referencia a usar para el dibujo de este tipo de figura.
Private Sub mnuCurva_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuCurva.Click ' crear objeto Pen Dim oPen As New Pen(Color.MediumPurple, 5) ' configurar estilo de lnea oPen.DashStyle = Drawing.Drawing2D.DashStyle.DashDot oPen.StartCap = Drawing.Drawing2D.LineCap.Triangle oPen.EndCap = Drawing.Drawing2D.LineCap.DiamondAnchor oPen.DashCap = Drawing.Drawing2D.DashCap.Triangle ' obtener el contexto de dispositivo ' grfico del formulario Dim oGraphics As Graphics = Me.CreateGraphics() ' crear un array de puntos-coordenadas necesario ' para dibujar una curva Dim oPuntos(4) As Point oPuntos(0) = New Point(10, 300) oPuntos(1) = New Point(40, 200) oPuntos(2) = New Point(100, 175) oPuntos(3) = New Point(130, 200) oPuntos(4) = New Point(200, 300) ' dibujar en el formulario oGraphics.DrawCurve(oPen, oPuntos) oGraphics.Dispose() End Sub private void mnuCurva_Click(object sender, EventArgs e) { // crear objeto Pen Pen oPen = new Pen(Color.MediumPurple, 5); // configurar estilo de lnea oPen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot; oPen.StartCap = System.Drawing.Drawing2D.LineCap.Triangle; oPen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; oPen.DashCap = System.Drawing.Drawing2D.DashCap.Triangle; // obtener el contexto de dispositivo // grfico del formulario Graphics oGraphics = this.CreateGraphics(); // crear un array de puntos-coordenadas necesario // para dibujar una curva Point[] oPuntos = new Point[5]; oPuntos[0] = new Point(10, 300); oPuntos[1] = new Point(40, 200); oPuntos[2] = new Point(100, 175); oPuntos[3] = new Point(130, 200); oPuntos[4] = new Point(200, 300); // dibujar en el formulario oGraphics.DrawCurve(oPen, oPuntos); oGraphics.Dispose(); Cdigo fuente 10
En cuanto a las curvas de tipo Bezier, el mtodo DrawBezier() recibe como parmetros un objeto Pen y una lista de coordenadas para el dibujo. Ver el Cdigo fuente 11.
P g i n a | 21
Private Sub mnuBezier_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBezier.Click ' dibujar curva estilo Bezier Dim oGraphics As Graphics = Me.CreateGraphics() oGraphics.DrawBezier(New Pen(Color.MediumSeaGreen, 2), 20, 45, 100, 90, 140, 200, 300, 25) oGraphics.Dispose() End Sub private void mnuBezier_Click(object sender, EventArgs e) { // dibujar curva estilo Bezier Graphics oGraphics = this.CreateGraphics(); oGraphics.DrawBezier(new Pen(Color.MediumSeaGreen, 2), 20, 45, 100, 90, 140, 200, 300, 25); oGraphics.Dispose(); } Cdigo fuente 11
Para dibujar una figura con forma irregular utilizaremos el mtodo DrawPolygon(), en el que al igual que con el dibujo de curvas, debemos pasarle un objeto Pen y un array de puntos. Ver el Cdigo fuente 12.
Private Sub mnuPoligono_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuPoligono.Click Dim oGraphics As Graphics = Me.CreateGraphics() Dim oPuntos(5) As Point oPuntos(0) = New Point(30, 70) oPuntos(1) = New Point(90, 115) oPuntos(2) = New Point(220, 90) oPuntos(3) = New Point(120, 80) oPuntos(4) = New Point(100, 100) oPuntos(5) = New Point(110, 65) oGraphics.DrawPolygon(New Pen(Color.SandyBrown, 3), oPuntos) oGraphics.Dispose() End Sub private void mnuPoligono_Click(object sender, EventArgs e) { Graphics oGraphics = this.CreateGraphics(); Point[] oPuntos = new Point[6]; oPuntos[0] = new Point(30, 70); oPuntos[1] = new Point(90, 115); oPuntos[2] = new Point(220, 90); oPuntos[3] = new Point(120, 80); oPuntos[4] = new Point(100, 100); oPuntos[5] = new Point(110, 65); oGraphics.DrawPolygon(new Pen(Color.SandyBrown, 3), oPuntos); oGraphics.Dispose(); Cdigo fuente 12
P g i n a | 22
Si en un momento dado, necesitamos borrar los elementos grficos dibujados en la superficie del formulario, utilizaremos el mtodo Invalidate() de la clase Form, tal como vemos en el Cdigo fuente 13.
Private Sub mnuBorrar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBorrar.Click ' borrar las figuras dibujadas en el formulario Me.Invalidate() End Sub private void mnuBorrar_Click(object sender, System.EventArgs e) { // borrar las figuras dibujadas en el formulario this.Invalidate(); } Cdigo fuente 13
La clase Brush
Esta clase representa un objeto de tipo pincel, utilizado para rellenar las figuras dibujadas sobre el formulario. Se trata de una clase abstracta, por lo que tendremos que utilizar alguna de sus diversas clases derivadas, segn el estilo de pincel que necesitemos aplicar. Debido a las caractersticas 2D de algunas de estas clases, ser necesario declarar en nuestro cdigo el espacio de nombres Drawing2D. Los mtodos de la clase Graphics que utilizaremos para dibujar con pinceles sern los que comienzan por el nombre FillTipoObjeto(). La clase ms bsica es SolidBrush, que permite rellenar en un estilo sencillo un rea dibujada. Ver el Cdigo fuente 14.
Private Sub mnuBrushSolid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushSolid.Click Dim oBrush As New SolidBrush(Color.MidnightBlue) Dim oGraphics As Graphics = Me.CreateGraphics()
P g i n a | 23
oGraphics.FillRectangle(oBrush, New Rectangle(150, 160, 150, 50)) oGraphics.Dispose() End Sub private void mnuBrushSolid_Click(object sender, EventArgs e) { SolidBrush oBrush = new SolidBrush(Color.MidnightBlue); Graphics oGraphics = this.CreateGraphics(); oGraphics.FillRectangle(oBrush, new Rectangle(150, 160, 150, 50)); oGraphics.Dispose(); } Cdigo fuente 14
A continuacin tenemos la clase HatchBrush, que permite la creacin de pinceles que al pintar aplican un efecto de tramado, con un color de fondo y otro de frente. Ver el Cdigo fuente 15.
Imports System.Drawing.Drawing2D '.... Private Sub mnuBrushHatch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushHatch.Click ' pintar con pincel de tipo hatch; ' para utilizar este tipo de pincel ' necesitamos importar System.Drawing.Drawind2D ' crear objeto HatchBrush Dim oHatchBrush As New HatchBrush(HatchStyle.Vertical, Color.Fuchsia, Color.Aqua) ' dibujar y pintar un polgono Dim oGraphics As Graphics = Me.CreateGraphics() oGraphics.FillEllipse(oHatchBrush, New Rectangle(25, 40, 150, 50)) oGraphics.Dispose() End Sub using System.Drawing.Drawing2D; //.... private void mnuBrushHatch_Click(object sender, EventArgs e) { // pintar con pincel de tipo hatch; // para utilizar este tipo de pincel // necesitamos usar System.Drawing.Drawind2D // crear objeto HatchBrush HatchBrush oHatchBrush = new HatchBrush(HatchStyle.Vertical, Color.Fuchsia, Color.Aqua); // dibujar y pintar un polgono Graphics oGraphics = this.CreateGraphics(); oGraphics.FillEllipse(oHatchBrush, new Rectangle(25, 40, 150, 50)); oGraphics.Dispose(); Cdigo fuente 15
Podemos emplear un bitmap como base para la zona de relleno que tendr que pintarse, para ello usaremos la clase TextureBrush, pasndole como parmetro un objeto Bitmap, que previamente habremos creado a partir de un archivo grfico que contenga la textura necesaria. Ver el Cdigo fuente 16.
Private Sub mnuBrushTexture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushTexture.Click ' crear un bitmap Dim oBitmap As New Bitmap("textura1.bmp") ' crear una brocha de textura Dim oTextureBrush As New TextureBrush(oBitmap)
P g i n a | 24
' dibujar una figura y pintarla con la brocha de textura Dim oGraphics As Graphics = Me.CreateGraphics() oGraphics.FillEllipse(oTextureBrush, New Rectangle(220, 50, 100, 75)) oGraphics.Dispose() End Sub private void mnuBrushTexture_Click(object sender, EventArgs e) { // crear un bitmap Bitmap oBitmap = new Bitmap("textura1.bmp"); // crear una brocha de textura TextureBrush oTextureBrush = new TextureBrush(oBitmap); // dibujar una figura y pintarla con la brocha de textura Graphics oGraphics = this.CreateGraphics(); oGraphics.FillEllipse(oTextureBrush, new Rectangle(220, 50, 100, 75)); oGraphics.Dispose(); Cdigo fuente 16
P g i n a | 25
' dibujar el GraphicsPath en el formulario Dim oGraph As Graphics = Me.CreateGraphics oGraph.DrawPath(New Pen(Color.DarkTurquoise, 8), oGraphPath) oGraph.Dispose() End Sub private void mnuGPathAbierta_Click(object sender, EventArgs e) { // crear el objeto GraphicsPath GraphicsPath oGraphPath = new GraphicsPath(); // aadir figuras dentro del objeto oGraphPath.AddEllipse(40,40 , 100, 100); oGraphPath.AddLine(new Point(50,70), new Point(115,70)); oGraphPath.AddCurve(new Point[] {new Point(60,90), new Point(70, 125), new Point(100, 100)}); // dibujar el GraphicsPath en el formulario Graphics oGraph = this.CreateGraphics(); oGraph.DrawPath(new Pen(Color.DarkTurquoise, 8), oGraphPath); oGraph.Dispose(); Cdigo fuente 17
Si queremos que las figuras aadidas al objeto GraphicsPath, queden unidas desde el punto inicial de la primera figura hasta el punto final de la ltima, llamaremos al mtodo StartFigure() antes de empezar a aadir la primera figura, y a CloseFigure() despus de aadir la ltima. Ver el Cdigo fuente 18.
Private Sub mnuGPathCerrada_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuGPathCerrada.Click ' crear el objeto GraphicsPath Dim oGraphPath As New GraphicsPath ' comenzar a aadir figuras dentro del objeto oGraphPath.StartFigure() oGraphPath.AddEllipse(40, 40, 120, 100) oGraphPath.AddLine(New Point(30, 30), New Point(90, 30)) oGraphPath.AddCurve(New Point() {New Point(40, 40), New Point(70, 110), New Point(100, 60)}) ' cerrar el objeto oGraphPath.CloseFigure() ' dibujar el GraphicsPath en el formulario Dim oGraph As Graphics = Me.CreateGraphics oGraph.DrawPath(New Pen(Color.LightSteelBlue, 5), oGraphPath) oGraph.Dispose() End Sub
P g i n a | 26
private void mnuGPathCerrada_Click(object sender, System.EventArgs e) { // crear el objeto GraphicsPath GraphicsPath oGraphPath = new GraphicsPath(); // comenzar a aadir figuras dentro del objeto oGraphPath.StartFigure(); oGraphPath.AddEllipse(40, 40, 120, 100); oGraphPath.AddLine(new Point(30, 30), new Point(90, 30)); oGraphPath.AddCurve(new Point[] {new Point(40, 40), new Point(70, 110), new Point(100, 60)}); // cerrar el objeto oGraphPath.CloseFigure(); // dibujar el GraphicsPath en el formulario Graphics oGraph = this.CreateGraphics(); oGraph.DrawPath(new Pen(Color.LightSteelBlue, 5), oGraphPath); oGraph.Dispose(); Cdigo fuente 18
La Figura 6 muestra un conjunto de imgenes unidas por todos sus puntos, creadas con GraphicsPath.
P g i n a | 27
oGraphics.FillClosedCurve(oLGB, oPuntos) oGraphics.Dispose() End Sub '-----------------------------------Private Sub mnuBrushPathGradient_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushPathGradient.Click ' array de coordenadas Dim oPuntos(2) As Point oPuntos(0) = New Point(150, 150) oPuntos(1) = New Point(225, 80) oPuntos(2) = New Point(260, 150) ' crear pincel de tipo PathGradient, ' y configurar el objeto Dim oPGB As New PathGradientBrush(oPuntos) oPGB.CenterColor = Color.Indigo oPGB.SurroundColors = New Color() {Color.Beige, Color.LightGreen} ' crear grfico y pintar polgono Dim oGraphics As Graphics = Me.CreateGraphics() oGraphics.FillPolygon(oPGB, oPuntos) oGraphics.Dispose() End Sub private void mnuBrushLinearGradient_Click(object sender, EventArgs e) { // crear brocha de tipo LinearGradient LinearGradientBrush oLGB = new LinearGradientBrush(new Rectangle(10, 50, 40, 60), Color.Aquamarine, Color.Azure, LinearGradientMode.Horizontal); // crear array de coordenadas Point[] oPuntos = new Point[3]; oPuntos[0] = new Point(20, 200); oPuntos[1] = new Point(75, 100); oPuntos[2] = new Point(140, 220); // obtener contexto grfico Graphics oGraphics = this.CreateGraphics(); // dibujar y pintar una curva cerrada oGraphics.FillClosedCurve(oLGB, oPuntos); oGraphics.Dispose();
} //-----------------------------------private void mnuBrushPathGradient_Click(object sender, EventArgs e) { // array de coordenadas Point[] oPuntos = new Point[3]; oPuntos[0] = new Point(150, 150); oPuntos[1] = new Point(225, 80); oPuntos[2] = new Point(260, 150); // crear brocha de tipo PathGradient, // y configurar el objeto PathGradientBrush oPGB = new PathGradientBrush(oPuntos); oPGB.CenterColor = Color.Indigo; oPGB.SurroundColors = new Color[] { Color.Beige, Color.LightGreen }; // crear grfico y pintar polgono Graphics oGraphics = this.CreateGraphics(); oGraphics.FillPolygon(oPGB, oPuntos); oGraphics.Dispose(); Cdigo fuente 19
La Figura 7 muestra alguna de las formas dibujadas utilizando objetos con efecto de gradiente
P g i n a | 28
P g i n a | 29
// grfico del formulario Graphics oGraphics = this.CreateGraphics(); // dibujar en el formulario oGraphics.DrawEllipse(oPen, new Rectangle(150, 120, 100, 100)); oGraphics.Dispose();
} //---------------------private void mnuBrushSistema_Click(object sender, System.EventArgs e) { // crear un objeto brush con un color de sistema SolidBrush oBrush = new SolidBrush(SystemColors.ControlDark); Graphics oGraphics = this.CreateGraphics(); oGraphics.FillEllipse(oBrush, new Rectangle(200, 200, 150, 50)); oGraphics.Dispose(); } Cdigo fuente 20
P g i n a | 30
P g i n a | 31
Queda todava un paso ms, ya que aunque la imagen se muestra como fondo del formulario, si redimensionamos este, slo se repinta la parte nueva redimensionada, produciendo un efecto no deseado. Ver la Figura 9.
Para conseguir que se pinte de nuevo toda la imagen, debemos utilizar el evento Resize para invalidar la zona grfica del formulario mediante el mtodo Form.Invalidate(). Este evento se produce cada vez que cambia el tamao del formulario. Ver el Cdigo fuente 23.
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize ' cada vez que cambie el tamao del formulario ' invalidamos su rea de dibujo para que ' el evento Paint pinte toda la superficie Me.Invalidate() End Sub private void Form1_Resize(object sender, System.EventArgs e) { // cada vez que cambie el tamao del formulario // invalidamos su rea de dibujo para que // el evento Paint pinte toda la superficie this.Invalidate(); } Cdigo fuente 23
El control picturebox
Despus de la tcnica compleja (slo en parte), pasemos ahora al modo fcil para crear una imagen de fondo, empleando el control PictureBox. Este control nos permite la visualizacin de imgenes en el formulario de un modo sencillo, ya que toda la mecnica de generacin la lleva incorporada, con lo que el programador se despreocupa de la manipulacin del grfico a mostrar. Una vez insertado un PictureBox en el formulario, asignaremos a su propiedad Dock el valor Fill, de forma que el control ocupe por completo la superficie del formulario.
P g i n a | 32
A continuacin asignaremos el archivo de imagen a la propiedad Image, y por ltimo estableceremos la propiedad SizeMode al valor StretchImage. Estas operaciones podemos realizarlas tanto en modo de diseo como por cdigo, lo cual vemos en el Cdigo fuente 24.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.picImagenFondo.Image = New Bitmap("LogoWinXP.gif") Me.picImagenFondo.SizeMode = PictureBoxSizeMode.StretchImage End Sub private void Form1_Load(object sender, EventArgs e) { this.picImagenFondo.Image = new Bitmap("LogoWinXP.gif"); this.picImagenFondo.SizeMode = PictureBoxSizeMode.StretchImage; } Cdigo fuente 24
Al ejecutar la aplicacin, la imagen quedar en todo momento ajustada al formulario; el mismo resultado que con el anterior ejemplo, pero ms sencillo en este caso. Ver la Figura 10.
Figura 11. Propiedad Opacity establecida desde la ventana de propiedades del IDE.
P g i n a | 33
En el Cdigo fuente 25 establecemos, desde el evento DoubleClick del formulario, la opacidad de este ltimo a un grado del cuarenta y cinco por ciento.
Private Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick Me.Opacity = 0.45 End Sub private void Form1_DoubleClick(object sender, System.EventArgs e) { this.Opacity = 0.45; } Cdigo fuente 25
Podemos proporcionar una mayor interaccin al usuario para esta propiedad, aadiendo al formulario un control TrackBar, que con el estilo de un control de volumen, nos va a permitir graduar el nivel de opacidad del formulario. Mediante las propiedades Maximum y Minimum estableceremos el rango de opacidad respectivamente a diez y cero. Por otra parte, asignaremos a la propiedad LargeChange el valor uno, para que el desplazamiento del indicador del control sea ms suave; mientras que en la propiedad Value asignaremos el valor diez, para partir de la mxima opacidad e ir disminuyendo. Como efectos visuales de este control, las propiedades Orientation y TickStyle nos permiten establecer la orientacin del indicador de posicin y su apariencia. Finalmente, el evento Scroll se producir cada vez que movamos el indicador de posicin en el control, ejecutando el cdigo de su procedimiento manipulador, que vemos en el Cdigo fuente 26.
Private Sub tkbOpaco_Scroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles tkbOpaco.Scroll ' cada vez que se mueve el desplazador ' del TrackBar se modifica la opacidad Select Case Me.tkbOpaco.Value Case 0 Me.Opacity = 0 Case 10 Me.Opacity = 1 Case Else Me.Opacity = Me.tkbOpaco.Value / 10
P g i n a | 34
End Select End Sub private void tkbOpaco_Scroll(object sender, System.EventArgs e) { // cada vez que se mueve el desplazador // del TrackBar se modifica el grado de opacidad switch (this.tkbOpaco.Value) { case 0: this.Opacity=0; break; case 10: this.Opacity=1; break; default: this.Opacity=(double)this.tkbOpaco.Value / (double)10; break;
Cdigo fuente 26
Esta til caracterstica de los formularios nos permite, por ejemplo, proporcionar un efecto de fundido durante su proceso de cierre. Para conseguirlo, escribiremos el cdigo necesario en el manipulador del evento FormClosing del formulario. Este evento es producido cuando el formulario est a punto de cerrarse, y lo que haremos ser cancelar el cierre del formulario, creando un temporizador que ser el que a lo largo de varios intervalos de tiempo, realizar el fundido y cierre. En el cdigo del evento Tick crearemos el efecto de fundido, disminuyendo el grado de opacidad del formulario hasta hacerlo invisible, punto en el que cerraremos el formulario. Esto har que se vuelva a pasar por el evento FormClosing, pero en esta ocasin, como la opacidad del formulario estar a cero, no se volver a realizar el proceso de fundido. Ver el Cdigo fuente 27.
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.FormClosing Dim oTiempo As Timer ' el formulario debe tener el valor 1 ' en Opacity para conseguir el efecto If Me.Opacity <> 0 Then
P g i n a | 35
' cancelamos el cierre del formulario e.Cancel = True ' iniciamos un temporizador cada medio segundo oTiempo = New Timer() oTiempo.Interval = 500 ' conectamos el temporizador con un manipulador ' de su evento Tick AddHandler oTiempo.Tick, AddressOf TickTiempo oTiempo.Start() End If End Sub '---------------------------------------Private Sub TickTiempo(ByVal sender As Object, ByVal e As EventArgs) ' este manipulador del evento del temporizador, ' cada medio segundo ir disminuyendo el grado ' de opacidad del formulario hasta hacerlo invisible Static dbContador As Double = 1 dbContador -= 0.1 Me.Opacity = dbContador ' cuando el formulario es invisible If Me.Opacity = 0 Then ' parar el temporizador CType(sender, Timer).Stop() ' cerrar el formulario Me.Close() End If End Sub
private void Form1_FormClosing(object sender, System.ComponentModel.CancelEventArgs e) { Timer oTiempo; // el formulario debe tener el valor 1 // en Opacity para conseguir el efecto if (this.Opacity != 0) { // cancelamos el cierre del formulario e.Cancel = true; // iniciamos un temporizador cada medio segundo oTiempo = new Timer(); oTiempo.Interval = 500; // conectamos el temporizador con un manipulador // de su evento Tick oTiempo.Tick += new EventHandler(TickTiempo); oTiempo.Start();
private void TickTiempo(Object sender, EventArgs e) { // este manipulador del evento del temporizador, // cada medio segundo ir disminuyendo el grado // de opacidad del formulario hasta hacerlo invisible dbContador -= 0.1; this.Opacity = dbContador; // cuando el formulario es invisible if (this.Opacity == 0) { // parar el temporizador ((Timer)sender).Stop();
P g i n a | 36
Cdigo fuente 27
P g i n a | 37
using System.Drawing.Drawing2D; //.... private void btnCirculo_Click(object sender, EventArgs e) { // crear un GraphicsPath y aadirle un crculo GraphicsPath oGPath = new GraphicsPath(); oGPath.AddEllipse(new Rectangle(0, 0, 200, 260)); // crear una regin con el objeto GraphicsPath // y asignarla a la regin del formulario this.Region = new Region(oGPath);
private void btnPoligono_Click(object sender, EventArgs e) { // mostrar el formulario con la forma // de un tringulo utilizando tambin // un objeto GraphicsPath y un Region Point[] oPuntos = new Point[3]; oPuntos[0] = new Point(-20, -20); oPuntos[1] = new Point(-20, 200); oPuntos[2] = new Point(220, 90); GraphicsPath oGPath = new GraphicsPath(); oGPath.AddPolygon(oPuntos); } this.Region = new Region(oGPath); Cdigo fuente 28
P g i n a | 38
Los efectos que acabamos de aplicar sobre la forma del formulario tienen el inconveniente de que ocultan los botones de la barra de ttulo del mismo. Para modificar la forma de una ventana pero manteniendo su barra de ttulos visible al completo, tenemos que seguir los siguientes pasos: crear un objeto Rectangle con el tamao del formulario, aplicar la modificacin de forma al objeto GraphicsPath; crear una nueva regin de dibujo; modificar el rectngulo adaptndolo al tamao de la barra de ttulos; unir el rectngulo con la regin; y finalmente asignar la regin a la propiedad Region del formulario. El Cdigo fuente 29 muestra un ejemplo con las operaciones que acabamos de describir.
Private Sub btnBarraTitulo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBarraTitulo.Click ' crear un rectngulo con las dimensiones del formulario Dim oRectangulo As Rectangle oRectangulo = New Rectangle(0, 0, Me.Size.Width, Me.Size.Height) ' crear un GraphicsPath Dim oGraphPath As GraphicsPath = New GraphicsPath ' aadir al GraphicsPath una elipse ' con las dimensiones del rectngulo oGraphPath.AddEllipse(oRectangulo) ' crear un objeto Region usando el objeto GraphicsPath Dim oRegion As Region = New Region(oGraphPath) ' modificar tamao del rectngulo para ' que se ajuste a las dimensiones de la ' barra de ttulo del formulario oRectangulo.Width = 400 oRectangulo.Height = 25 ' une el objeto region con el rectngulo oRegion.Union(oRectangulo) ' asigna el objeto Region ' a la regin de dibujo del formulario Me.Region = oRegion End Sub private void btnBarraTitulo_Click(object sender, System.EventArgs e) { // crear un rectngulo con las dimensiones del formulario Rectangle oRectangulo; oRectangulo = new Rectangle(0, 0, this.Size.Width, this.Size.Height); // crear un GraphicsPath
P g i n a | 39
GraphicsPath oGraphPath = new GraphicsPath(); // aadir al GraphicsPath una elipse // con las dimensiones del rectngulo oGraphPath.AddEllipse(oRectangulo); // crear un objeto Region usando el objeto GraphicsPath Region oRegion = new Region(oGraphPath); // modificar tamao del rectngulo para // que se ajuste a las dimensiones de la // barra de ttulo del formulario oRectangulo.Width = 400; oRectangulo.Height = 25; // une el objeto region con el rectngulo oRegion.Union(oRectangulo); // asigna el objeto Region // a la regin de dibujo del formulario this.Region = oRegion; Cdigo fuente 29
La Figura 16 muestra el resultado de un formulario con su forma modificada, pero con la barra de ttulo completa.
P g i n a | 40
Seguidamente crearemos un proyecto y comenzaremos definiendo la parte visual del formulario. En primer lugar asignaremos a la propiedad FormBorderStyle el valor None; en la propiedad BackgroundImage estableceremos el archivo grfico que hemos creado inicialmente, y por ltimo, a la propiedad TransparencyKey le asignaremos el valor Transparent. A continuacin agregaremos dos botones para cerrar el formulario y visualizar un mensaje, cuyo cdigo vemos en el Cdigo fuente 30.
Private Sub btnSalir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalir.Click Me.Close() End Sub Private Sub btnMensaje_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMensaje.Click MessageBox.Show("Formulario con forma irregular") End Sub private void btnSalir_Click(object sender, EventArgs e) { this.Close(); } private void btnMensaje_Click(object sender, EventArgs e) { MessageBox.Show("Formulario con forma irregular"); } Cdigo fuente 30
P g i n a | 41
Puesto que hemos eliminado la barra de ttulo del formulario, nos encontramos actualmente con el problema de proporcionar al usuario la capacidad de mover la ventana por el escritorio de Windows; ello significa que tendremos que escribir cdigo para los eventos del ratn, que posibiliten suministrar de nuevo esta funcionalidad, como vemos en el Cdigo fuente 31.
Public Class frmImagen Private oUbicacionRaton As Point Private bRatonPulsado As Boolean '.... Private Sub frmImagen_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown Dim nCoordX As Integer Dim nCoordY As Integer ' al pulsar el botn izquierdo, activar el movimiento del formulario If e.Button = Windows.Forms.MouseButtons.Left Then bRatonPulsado = True nCoordX = -e.X - SystemInformation.FrameBorderSize.Width nCoordY = -e.Y - SystemInformation.CaptionHeight SystemInformation.FrameBorderSize.Height oUbicacionRaton = New Point(nCoordX, nCoordY) End If End Sub Private Sub frmImagen_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove ' si mantenemos pulsado el botn del ratn, arrastrar el formulario If bRatonPulsado Then Dim oPosicionRaton As Point = Control.MousePosition oPosicionRaton.Offset(oUbicacionRaton.X, oUbicacionRaton.Y) Me.Location = oPosicionRaton End If End Sub Private Sub frmImagen_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp ' al soltar el botn izquierdo, desactivar el movimiento del formulario If e.Button = Windows.Forms.MouseButtons.Left Then bRatonPulsado = False End If
P g i n a | 42
End Sub End Class public partial class frmImagen : Form { Point oUbicacionRaton; Boolean bRatonPulsado; //.... private void frmImagen_MouseDown(object sender, MouseEventArgs e) { int nCoordX; int nCoordY; // al pulsar el botn izquierdo, activar el movimiento del formulario if (e.Button == MouseButtons.Left) { bRatonPulsado = true; nCoordX = -e.X - SystemInformation.FrameBorderSize.Width; nCoordY = -e.Y - SystemInformation.CaptionHeight SystemInformation.FrameBorderSize.Height; oUbicacionRaton = new Point(nCoordX, nCoordY); } } private void frmImagen_MouseMove(object sender, MouseEventArgs e) { // si mantenemos pulsado el botn del ratn, arrastrar el formulario if (bRatonPulsado) { Point oPosicionRaton = Control.MousePosition; oPosicionRaton.Offset(oUbicacionRaton.X, oUbicacionRaton.Y); this.Location = oPosicionRaton; } } private void frmImagen_MouseUp(object sender, MouseEventArgs e) { // al soltar el botn izquierdo, desactivar el movimiento del formulario if (e.Button == MouseButtons.Left) { bRatonPulsado = false; } } Cdigo fuente 31
La Figura 19 muestra en ejecucin, este formulario con la superficie basada en una imagen.
P g i n a | 43
Valor
Normal OwnerDrawFixed OwnerDrawVariable
Descripcin
El sistema operativo es el encargado de dibujar los elementos. Todos tendrn el mismo tamao El programador es el encargado de dibujar los elementos. Todos tendrn el mismo tamao El programador es el encargado de dibujar los elementos, los cuales pueden tener tamaos distintos
Tabla 1. Valores de la enumeracin DrawMode.
Una vez realizada esta asignacin, deberemos crear un mtodo manipulador del evento MeasureItem, que se producir por cada elemento cuyas dimensiones tengan que ser calculadas antes de dibujarse en
P g i n a | 44
la lista. En este mtodo estableceremos el tamao del elemento utilizando el parmetro MeasureItemEventArgs, que entre otras propiedades dispone de ItemWidth e ItemHeight para este cometido. El otro evento que debemos codificar para realizar este proceso es DrawItem, que sucede cada vez que un elemento de la lista necesita ser dibujado, y resulta ms importante si cabe que el anterior, ya que ser aqu donde tendremos que codificar toda la lgica de dibujo. Como ejemplo demostrativo crearemos un proyecto con el nombre DibujoElementosLista 1: http://www.elcampusdigital.com/FtpTextos/AplicacionWindowsAvanzado/DibujoElementosLista.zip En el formulario agregaremos un ComboBox que ser utilizado para nuestras pruebas, y al que aadiremos tres elementos. La Figura 20 muestra este control con su aspecto estndar, antes de que procedamos a manipular sus operaciones de dibujo.
Figura 20.
De cara a conseguir el mejor resultado en nuestra personalizacin del dibujo de este control, debemos tener en cuenta una importante caracterstica de su comportamiento relacionada con los eventos que vamos a manejar: cuando la lista de elementos del ComboBox est cerrada y se pulsa su botn de despliegue, los eventos DrawItem y MeasureItem ocurrirn tantas veces como elementos tenga la lista. Una vez abierta dicha lista, segn nos vayamos desplazando por la misma bien con el teclado o ratn, por cada desplazamiento que hagamos a un nuevo elemento, los eventos DrawItem y MeasureItem se producirn dos veces: una por el elemento que hasta el momento era el seleccionado y est a punto de dejar de serlo; y otra por el elemento que pasa a ser el nuevo seleccionado. Todo este funcionamiento ser el que tengamos que aprovechar para que nuestras operaciones de dibujo de elementos sean correctas, ya que deberemos pintar el elemento seleccionado con un color diferente del resto, que nos sirva para destacarlo. A continuacin pasaremos al cdigo del formulario, declarando en primer lugar dos variables con mbito de clase, que usaremos como soporte para las operaciones de dibujo. La primera de estas variables: nContadorDibujoItems, la usaremos para controlar el nmero de veces que el evento DrawItem se ejecuta al ser abierta la lista desplegable del ComboBox, ya que en este caso los elementos sern dibujados sin usar el color de seleccin. La otra variable: nSeleccionadoActual, determinar si el evento DrawItem que se ha producido corresponde al elemento que acaba de perder su condicin de seleccionado, o bien al que acaba de ganarla. Seguidamente, dentro del evento Load del formulario, configuraremos el ComboBox para realizar el dibujo personalizado de elementos; inicializaremos el contador de elementos dibujados en el evento DropDown, que ocurre al desplegar la lista; y estableceremos las dimensiones de los elementos en el evento MeasureItem.
Todos los ejemplos del texto los puede bajar desde la direccin: http://www.elcampusdigital.com/FtpTextos/AplicacionWindowsAvanzado/Ejemplos.zip
P g i n a | 45
Por ltimo pasaremos al evento DrawItem, en el que crearemos los objetos de color y tipo de letra para el elemento de la lista a dibujar. Despus calcularemos si debemos pintar el elemento como seleccionado o no, para finalmente proceder a su dibujo. Todas estas operaciones se muestran en el Cdigo fuente 32.
Public Class Form1 ' variables complementarias Dim nContadorDibujoItems As Integer Dim nSeleccionadoActual As Integer = -1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' establecer la altura de la lista desplegable ' y que el dibujo del control se realizar ' manualmente Me.cboLista.DropDownHeight = 150 ' especificar que el dibujo del control ' ser realizado manualmente Me.cboLista.DrawMode = DrawMode.OwnerDrawVariable End Sub Private Sub cboLista_DropDown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboLista.DropDown ' inicializar el contador de elementos dibujados ' al ser abierta la lista desplegable del control Me.nContadorDibujoItems = 1 End Sub ' este evento se produce para asignar ' las dimensiones de los elementos del ComboBox Private Sub cboLista_MeasureItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles cboLista.MeasureItem e.ItemWidth = 200 e.ItemHeight = 21 End Sub ' cada vez que se necesite dibujar un elemento ' de la lista se produce este evento Private Sub cboLista_DrawItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles cboLista.DrawItem Dim oColorElemento As Color = Color.Empty Dim oColorLetra As Color = Color.Black Dim oTipoLetra As Font = New Font("Comic Sans MS", 8, FontStyle.Bold) Dim oRectElemento As Rectangle ' dibujar el fondo del elemento e.DrawBackground() ' seleccionar el color del elemento a dibujar Select Case e.Index Case 0 oColorElemento = Color.LightGreen Case 1 oColorElemento = Color.Yellow Case 2 oColorElemento = Color.LightSkyBlue End Select ' comprobar si se estn dibujando los items ' debido a que la lista se acaba de desplegar ' o bien porque ya est desplegada y el usuario ' se desplaza por los mismos If Me.nContadorDibujoItems <= Me.cboLista.Items.Count Then ' la lista se est desplegando, ' dibujar el item con su color
P g i n a | 46
Else
Me.nContadorDibujoItems += 1
' la lista ya est desplegada If Me.cboLista.SelectedIndex <> -1 And Me.nSeleccionadoActual = -1 Then ' el elemento acaba de ser seleccionado oColorElemento = SystemColors.Highlight oColorLetra = SystemColors.HighlightText Me.nSeleccionadoActual = Me.cboLista.SelectedIndex Else ' el elemento ha dejado de estar seleccionado If Me.cboLista.SelectedIndex = Me.nSeleccionadoActual Then Me.nSeleccionadoActual = -1 End If End If End If
' dibujar el rectngulo del elemento de la lista ' con el color que le corresponda oRectElemento = New Rectangle(e.Bounds.Location, e.Bounds.Size) e.Graphics.FillRectangle(New SolidBrush(oColorElemento), oRectElemento) ' dibujar el texto del elemento de la lista e.Graphics.DrawString(Me.cboLista.Items(e.Index), _ oTipoLetra, _ New SolidBrush(oColorLetra), _ e.Bounds.Location) End Sub End Class public partial class Form1 : Form { // variables complementarias int nContadorDibujoItems; int nSeleccionadoActual = -1; //.... private void Form1_Load(object sender, EventArgs e) { // establecer la altura de la lista desplegable // y que el dibujo del control se realizar // manualmente this.cboLista.DropDownHeight = 150; // especif (icar que el dibujo del control // ser realizado manualmente this.cboLista.DrawMode = DrawMode.OwnerDrawVariable;
private void cboLista_DropDown(object sender, EventArgs e) { // inicializar el contador de elementos dibujados // al ser abierta la lista desplegable del control this.nContadorDibujoItems = 1; } // este evento se produce para asignar // las dimensiones de los elementos del ComboBox private void cboLista_MeasureItem(object sender, MeasureItemEventArgs e) { e.ItemWidth = 200; e.ItemHeight = 21; } // cada vez que se necesite dibujar un elemento // de la lista se produce este evento private void cboLista_DrawItem(object sender, DrawItemEventArgs e) { Color oColorElemento = Color.Empty; Color oColorLetra = Color.Black; Font oTipoLetra = new Font("Comic Sans MS", 8, FontStyle.Bold);
P g i n a | 47
Rectangle oRectElemento; // dibujar el fondo del elemento e.DrawBackground(); // seleccionar el color del elemento a dibujar switch (e.Index) { case 0: oColorElemento = Color.LightGreen; break; case 1: oColorElemento = Color.Yellow; break; case 2: oColorElemento = Color.LightSkyBlue; break; comprobar si se estn dibujando los items debido a que la lista se acaba de desplegar o bien porque ya est desplegada y el usuario se desplaza por los mismos (this.nContadorDibujoItems <= this.cboLista.Items.Count) // la lista se est desplegando, // dibujar el item con su color this.nContadorDibujoItems += 1;
} // // // // if {
} else {
// la lista ya est desplegada if (this.cboLista.SelectedIndex != -1 & this.nSeleccionadoActual == -1) { // el elemento acaba de ser seleccionado oColorElemento = SystemColors.Highlight; oColorLetra = SystemColors.HighlightText; this.nSeleccionadoActual = this.cboLista.SelectedIndex; } else { // el elemento ha dejado de estar seleccionado if (this.cboLista.SelectedIndex == this.nSeleccionadoActual) { this.nSeleccionadoActual = -1; } }
// dibujar el rectngulo del elemento de la lista // con el color que le corresponda oRectElemento = new Rectangle(e.Bounds.Location, e.Bounds.Size); e.Graphics.FillRectangle(new SolidBrush(oColorElemento), oRectElemento); // dibujar el texto del elemento de la lista e.Graphics.DrawString(this.cboLista.Items[e.Index].ToString(), oTipoLetra, new SolidBrush(oColorLetra), e.Bounds.Location);
La Figura 21 muestra nuestro control con la lista desplegada en dos vistas diferentes: una de ellas muestra los elementos con sus colores normales, y otra con uno seleccionado.
P g i n a | 48
Professional. Visualiza el objeto utilizando la combinacin visual mejorada de colores, letras, etc., correspondiente a WindowsXP. Ver la Figura 23.
ManagerRenderMode. Visualiza el objeto utilizando un objeto que contiene una presentacin personalizada creada por el programador. Inicialmente, el componente ToolStrip tiene por defecto este valor, y la apariencia visual que proporciona ser la misma que la
P g i n a | 49
correspondiente al valor Professional, hasta que el programador escriba su propio cdigo de visualizacin, lo cual haremos seguidamente. Para crear una presentacin personalizada para los contenidos de un objeto ToolStrip, despus de asegurarnos que su propiedad RenderMode tiene el valor ManagerRenderMode, crearemos una clase que herede de ToolStripRenderer, a la que podemos llamar GeneradorPersonalizado, y reemplazaremos aquellos mtodos en los que vayamos a crear nuestra propia visualizacin personalizada, teniendo en cuenta que en cada uno de los mtodos que reemplacemos, deberemos llamar tambin a la implementacin de ese mismo mtodo en su clase base. Si consultamos los mtodos disponibles para esta clase en la documentacin de la plataforma, comprobaremos que existe una buena cantidad de todos aquellos dedicados a las labores de presentacin, y que adems son los mtodos llamados cuando se produce un evento de cambio en algn aspecto visual del componente. Como convencin, estos mtodos llevan el nombre OnNombreMtodo(). De esta manera, si queremos por ejemplo que el objeto ToolStrip tenga un color de fondo personalizado, basado en un fundido de dos colores, en la clase GeneradorPersonalizado reemplazaremos el mtodo OnRenderToolStripBackground y escribiremos el cdigo mostrado en el Cdigo fuente 33.
Imports System.Drawing.Drawing2D Public Class GeneradorPersonalizado Inherits ToolStripRenderer Protected Overrides Sub OnRenderToolStripBackground(ByVal e As _ ToolStripRenderEventArgs) ' obtener el objeto Graphics del parmetro del evento Dim oGraphics As Graphics = e.Graphics ' crear un color con degradado para situar como fondo del ToolStrip Dim oLGB As LinearGradientBrush = New LinearGradientBrush(e.AffectedBounds, Color.DarkOrange, Color.MediumSpringGreen, LinearGradientMode.Vertical) oGraphics.FillRectangle(oLGB, e.AffectedBounds) oLGB.Dispose() ' ejecutar el cdigo de este mtodo ' que est en la clase base MyBase.OnRenderToolStripBackground(e) End Sub '.... End Class //.... using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; class GeneradorPersonalizado : ToolStripRenderer { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { // obtener el objeto Graphics del parmetro del evento Graphics oGraphics = e.Graphics; // crear un color con degradado para situar como fondo del ToolStrip LinearGradientBrush oLGB = new LinearGradientBrush(e.AffectedBounds, Color.DarkOrange, Color.MediumSpringGreen, LinearGradientMode.Vertical); oGraphics.FillRectangle(oLGB, e.AffectedBounds);
P g i n a | 50
oLGB.Dispose(); // ejecutar el cdigo de este mtodo // que est en la clase base base.OnRenderToolStripBackground(e);
Para que este efecto visual pueda ser aplicado al componente, necesitamos instanciar un objeto de nuestra clase GeneradorPersonalizado y asignarlo a la propiedad ToolStrip.Renderer. Un buen lugar para ello sera en el evento Load del formulario, como vemos en el Cdigo fuente 34
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.tsBHerramientas.Renderer = New GeneradorPersonalizado() End Sub End Class public partial class Form1 : Form { //.... private void Form1_Load(object sender, EventArgs e) { this.tsBHerramientas.Renderer = new GeneradorPersonalizado(); } } Cdigo fuente 34
Ahora slo queda ejecutar el proyecto y observar el resultado, que debera parecerse al mostrado en la Figura 24.
Como ya hemos mencionado, la profusin de mtodos en la clase ToolStripRenderer permite configurar los ms variados aspectos visuales del objeto ToolStrip. A continuacin vamos a reemplazar algunos mtodos adicionales, para completar el ejemplo que estamos desarrollando. El mtodo OnRenderItemText se utiliza cuando se va a dibujar el texto correspondiente a un elemento del ToolStrip. Por otra parte, el mtodo OnRenderButtonBackground se emplea para pintar el color de fondo de los controles de tipo botn de la barra de herramientas. Finalmente, el mtodo OnRenderMenuItemBackground realiza la misma labor que el anterior, pero en este caso para las opciones de men, las cuales pueden usarse tanto desde un objeto ToolStrip como desde alguna de sus clases derivadas: MenuStrip y StatusStrip. Todo ello lo vemos en el Cdigo fuente 35.
Protected Overrides Sub OnRenderItemText(ByVal e As _ ToolStripItemTextRenderEventArgs) ' mostrar el texto de los elementos del ToolStrip
P g i n a | 51
' con un nuevo tipo de letra y color e.TextColor = Color.DarkViolet e.TextFont = New Font("Comic Sans MS", 7, FontStyle.Bold Or FontStyle.Italic) MyBase.OnRenderItemText(e) End Sub Protected Overrides Sub OnRenderButtonBackground(ByVal e As _ ToolStripItemRenderEventArgs) ' pintar el fondo de un botn del ToolStrip ' con un color degradado distinto ' en funcin de si est o no seleccionado MyBase.OnRenderButtonBackground(e) Dim oGraphics As Graphics = e.Graphics Dim oRectangulo As Rectangle oRectangulo = New Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height) ' si el botn est seleccionado... If e.Item.Selected Then ' ...si el botn est adems pulsado If e.Item.Pressed Then Dim oLGB As LinearGradientBrush oLGB = New LinearGradientBrush(oRectangulo, _ Color.Crimson, Color.Gold, _ LinearGradientMode.BackwardDiagonal) Else oGraphics.FillRectangle(oLGB, oRectangulo)
' si el botn no est pulsado (el ratn slo est pasando encima) ' pintamos el color con una estructura Using ' para optimizar recursos del sistema Using oLGB As LinearGradientBrush = _ New LinearGradientBrush(oRectangulo, _ Color.SpringGreen, Color.Beige, LinearGradientMode.ForwardDiagonal) oGraphics.FillRectangle(oLGB, oRectangulo) End Using End If End If End Sub Protected Overrides Sub OnRenderMenuItemBackground(ByVal e As System.Windows.Forms.ToolStripItemRenderEventArgs) ' pintar el fondo de una opcin de men ' con un color distinto en funcin de si la opcin ' est o no seleccionada MyBase.OnRenderMenuItemBackground(e) Dim oGraphics As Graphics = e.Graphics Dim oLGB As LinearGradientBrush Dim oRectangulo As Rectangle oRectangulo = New Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height) If e.Item.Selected Then If e.Item.Pressed Then oLGB = New LinearGradientBrush(New Rectangle(0, 0, _ e.Item.Bounds.Width, e.Item.Bounds.Height), _ Color.Maroon, Color.MediumAquamarine, _ LinearGradientMode.Horizontal) Else oLGB = New LinearGradientBrush(New Rectangle(0, 0, _ e.Item.Bounds.Width, e.Item.Bounds.Height), _ Color.Aqua, Color.Crimson, _ LinearGradientMode.ForwardDiagonal) End If Else oLGB = New LinearGradientBrush(New Rectangle(0, 0, _ e.Item.Bounds.Width, e.Item.Bounds.Height), _
P g i n a | 52
End If
oGraphics.FillRectangle(oLGB, New Rectangle(0, 0, _ e.Item.Bounds.Width, e.Item.Bounds.Height)) End Sub protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { // mostrar el texto de los elementos del ToolStrip // con un nuevo tipo de letra y color e.TextColor = Color.DarkViolet; e.TextFont = new Font("Comic Sans MS", 7, FontStyle.Bold | FontStyle.Italic); base.OnRenderItemText(e); } protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) { // pintar el fondo de un botn del ToolStrip // con un color degradado distinto // en funcin de si est o no seleccionado base.OnRenderButtonBackground(e); Graphics oGraphics = e.Graphics; Rectangle oRectangulo; oRectangulo = new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height); // si el botn est seleccionado... if (e.Item.Selected) { // ...si el botn est adems pulsado if (e.Item.Pressed) { LinearGradientBrush oLGB; oLGB = new LinearGradientBrush(oRectangulo, Color.Crimson, Color.Gold, LinearGradientMode.BackwardDiagonal); oGraphics.FillRectangle(oLGB, oRectangulo); } else { // si el botn no est pulsado (el ratn slo est pasando encima) // pintamos otro color LinearGradientBrush oLGB = new LinearGradientBrush(oRectangulo, Color.SpringGreen, Color.Beige, LinearGradientMode.ForwardDiagonal); } oGraphics.FillRectangle(oLGB, oRectangulo);
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { // pintar el fondo de una opcin de men // con un color distinto en funcin de si la opcin // est o no seleccionada base.OnRenderMenuItemBackground(e); Graphics oGraphics = e.Graphics; LinearGradientBrush oLGB; Rectangle oRectangulo; oRectangulo = new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height); if (e.Item.Selected) {
P g i n a | 53
} else {
if (e.Item.Pressed) { oLGB = new LinearGradientBrush(new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height), Color.Maroon, Color.MediumAquamarine, LinearGradientMode.Horizontal); } else { oLGB = new LinearGradientBrush(new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height), Color.Aqua, Color.Crimson, LinearGradientMode.ForwardDiagonal); }
Al volver a ejecutar el formulario, la presentacin de los botones al ser pulsados, opciones de men, etc., tambin se ver afectada por nuestra clase generadora de elementos visuales, como vemos en la Figura 25.
La clase ToolStrip, adems de utilizarse para la creacin de barras de herramientas, acta como clase base de StatusStrip y MenuStrip, por lo que igualmente podemos alterar la presentacin del men y la barra de estado del formulario, escribiendo una clase derivada de ToolStripRenderer, y asignando una instancia de la misma a la propiedad Renderer de estos objetos. En el caso de que necesitemos que la apariencia personalizada de todos estos elementos del formulario: barras de herramientas, estado y men, sea igual, podemos asignar el mismo objeto a la propiedad Renderer, o lo que es preferible, utilizar la clase ToolStripManager, y asignar el objeto con la visualizacin personalizada a su mtodo Renderer, como vemos en el Cdigo fuente 36.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ToolStripManager.Renderer = New GeneradorPersonalizado() End Sub private void Form1_Load(object sender, EventArgs e)
P g i n a | 54
{ }
P g i n a | 55