Está en la página 1de 55

Desarrollo de aplicaciones Windows.

Aspectos avanzados

Luis Miguel Blanco

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

Madrid, septiembre de 2009 ISBN: 978-84-92684-52-6 Versin 1.0 (27-09-2009)

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.

DESARROLLO DE APLICACIONES WINDOWS. ASPECTOS AVANZADOS


Luis Miguel Blanco

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.

GDI+ y construccin de controles personalizados


GDI+ representa la API de programacin grfica de la plataforma .NET, mediante la cual podremos dotar a nuestras aplicaciones de notables efectos visuales. Tambin nos permitir aplicar su potencial en la creacin de controles de usuario derivados de los ya existentes, o bien en el desarrollo de nuevos controles creados a partir de cero, sin olvidar la herencia visual de formularios, un aspecto del desarrollo que facilita la creacin visual de formularios derivados.

ADO.NET y el enlace de datos a controles


En el apartado de los mantenimientos de datos con ADO.NET, el enlace entre orgenes de datos y controles Data Binding- incorpora nuevas clases y componentes, destinados a facilitar la labor del

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.

Flujos de datos y manipulacin de archivos


Mediante el conjunto de clases de tipo Stream, manejaremos flujos de datos que nos permitirn la lectura y escritura de informacin en el sistema de archivos de la mquina, pudiendo desarrollar procesos de monitorizacin en dicho sistema, que nos permitan rastrear los cambios a nivel de archivos y directorios que se produzcan.

Utilizacin del Portapapeles y de las operaciones de Arrastrar y soltar


La plataforma .NET ofrece soporte para implementar en nuestras aplicaciones dos de las caractersticas de mayor uso entre los usuarios de sistemas Windows, como son el Portapapeles y Arrastrar y soltar, que nos permiten realizar intercambio de informacin entre diferentes aplicaciones. Con ello, nuestros desarrollos ganarn en productividad y facilidad de manejo.

Programacin de procesos asncronos y multihebra


Con el fin de poder ejecutar ms de una tarea simultneamente, disponemos de un conjunto de clases y componentes, que nos permitirn implementar en un proyecto capacidades de ejecucin asncrona, de manera que podemos lanzar la ejecucin de un proceso en una hebra aparte, impidiendo que los controles del formulario de trabajo queden bloqueados debido a tareas intensivas que realicen un gran consumo de recursos del sistema.

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

GDI+. Manipulacin de grficos en .NET Framework


GDI+ (Graphics Device Interface) representa aquella parte en la arquitectura de la plataforma .NET encargada de la comunicacin con el motor grfico del sistema operativo. Se trata de una interfaz de programacin independiente del dispositivo fsico sobre el que se van a generar los grficos; con ello, el programador gana en flexibilidad, ya que no debe preocuparse de si el grfico generado se va a mostrar por el monitor, impresora, etc., siendo esta una labor resuelta por GDI+, que asla el programa del hardware a manejar. Se trata de un subsistema grfico que ha evolucionado del antiguo GDI, perteneciente a versiones anteriores de Windows, por lo que incluye una gran cantidad de mejoras y potencia en el tratamiento de imgenes, texto, etc., con respecto a su predecesor. GDI+ divide su campo de trabajo en tres reas principales. Generacin de grficos vectoriales 2D Manipulacin de imgenes en los formatos grficos ms habituales. Visualizacin de texto en un amplio abanico de tipos de letra.

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.

Especificando coordenadas. La clase Point


Esta clase nos permite especificar puntos o coordenadas en las que se dibujarn los grficos. Se trata de una clase auxiliar, que deberemos utilizar con diversos objetos de dibujo para indicar dnde dibujaremos un objeto grfico.

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

Definiendo tamaos. La clase Size


Al igual que la clase anterior, Size es una clase auxiliar, que nos permite definir tamaos y que utilizaremos en diversas situaciones durante nuestro trabajo manipulando grficos. Podemos crear objetos Size con tamaos basados en valores enteros, o bien usar la clase SizeF para definir tamaos con valores de precisin decimal. Ver el Cdigo fuente 3.
Dim oSize As New Size(50, 100) Dim oSizeF As SizeF oSizeF = New SizeF(58.4, 125.6) Size oSize = new Size(50,100); SizeF oSizeF; oSizeF = new SizeF(58.4, 125.6); Cdigo fuente 3

Combinando coordenadas y tamaos. La clase Rectangle


Para dibujar un objeto grfico debemos especificar un rea rectangular, dentro de la cual ser dibujado el grfico. Esto lo conseguiremos mediante la clase Rectangle o RectangleF, a cuyos constructores pasaremos valores numricos (enteros o decimales), o bien sendos objetos Point y Size. Ver el Cdigo fuente 4.
Dim oRect As Rectangle oRect = New Rectangle(New Point(10, 40), New Size(100, 120)) Dim oRectF As New RectangleF(10.5, 40.8, 100.6, 120.9) Rectangle oRect; oRect = new Rectangle(new Point(10,40), new Size(100,120)); RectangleF oRectF = new RectangleF(10.5, 40.8, 100.6, 120.9); Cdigo fuente 4

P g i n a | 16

La clase Pen. Componiendo todo para dibujar


La clase Pen representa un objeto de tipo lapicero, que con un determinado color y grosor, utilizar los mtodos DrawTipoObjeto() de un objeto Graphics para dibujar lneas y formas sobre un contexto de dispositivo, es decir, el formulario. El Cdigo fuente 5 muestra un ejemplo de dibujo de un crculo sobre el formulario utilizando el mtodo DrawEllipse() de la clase Graphics. Este mtodo recibe como parmetro un objeto Pen con un color y grosor determinados, y un objeto Rectangle con las coordenadas y medidas necesarias para dibujar el crculo. Finalizado el dibujo, y ya que las operaciones grficas consumen gran cantidad de recursos, es recomendable llamar al mtodo Dispose() de la clase Graphics, para poder liberar correctamente los recursos que est utilizando.
' crear objeto Pen Dim oPen As New Pen(Color.DeepPink, 10) ' obtener el contexto de dispositivo ' grfico del formulario Dim oGraphics As Graphics = Me.CreateGraphics() ' dibujar en el formulario oGraphics.DrawEllipse(oPen, New Rectangle(150, 20, 100, 100)) oGraphics.Dispose() // crear objeto Pen Pen oPen = new Pen(Color.DeepPink,10); // obtener el contexto de dispositivo // grfico del formulario Graphics oGraphics = this.CreateGraphics(); // dibujar en el formulario oGraphics.DrawEllipse(oPen, new Rectangle(150, 20, 100, 100)); oGraphics.Dispose(); Cdigo fuente 5

Asociando este cdigo a la pulsacin de un botn en el formulario, el resultado ser el dibujo del crculo mostrado en la Figura 1.

Figura 1. Dibujar un crculo con un objeto Pen.

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

Repintado de reas invalidadas


El dibujo de figuras en la forma que acabamos de describir tiene un inconveniente: si la figura que hemos dibujado queda oculta parcial o totalmente por otro formulario o elemento de la interfaz de usuario, dicha zona ocultada ser borrada. Al rea de un formulario que queda oculta de esta manera se le denomina zona invalidada, requiriendo ser repintada para poder recuperar su aspecto original. Esta es una labor que actualmente no realizamos en el cdigo del formulario. Para mantener las figuras dibujadas en todo momento en el formulario, debemos recurrir al evento Paint() de la clase Form. Dicho evento se produce cada vez que el formulario necesita repintarse, debido a que parte o la totalidad de su superficie ha quedado invalidada Vamos por lo tanto a solucionar este problema, escribiendo un mtodo manipulador para el mencionado evento Paint(), en el que dibujaremos un rectngulo mediante el mtodo Graphics.DrawRectangle(). Como puede observar el lector, este evento recibe un parmetro de tipo PaintEventArgs, que utilizaremos para obtener el objeto Graphics con el que realizar el dibujo de la figura. Ver el Cdigo fuente 7.
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint ' crear objeto Pen Dim oPen As 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

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.

Figura 2. Figura persistente en la superficie del formulario gracias al evento Paint.

Dibujo de figuras varias con la clase Pen


En este apartado veremos diversos mtodos que tambin ofrece la clase Pen para el dibujo de otros tipos de figuras. Para organizar el cdigo, aadiremos un men al formulario, creando una opcin de men por cada operacin de dibujo. En primer lugar volveremos a utilizar el mtodo DrawEllipse() para dibujar una figura de este tipo con forma alargada. Ver el Cdigo fuente 8.
Private Sub mnuElipse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuElipse.Click ' crear objeto Pen Dim oPen As New Pen(Color.DarkTurquoise, 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

La Figura 3 muestra el resultado de la ejecucin de los anteriores ejemplos de cdigo.

P g i n a | 22

Figura 3. Figuras dibujadas con objetos de la clase Pen.

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

La Figura 4 muestra estas figuras con el relleno correspondiente.

Figura 4. Figuras con efecto de relleno.

Creacin de figuras complejas con la clase GraphicsPath


La clase GraphicsPath nos permite la generacin de dibujos ms complejos que los conseguidos hasta ahora con la clase Graphics. Un objeto GraphicsPath consiste en un contenedor de figuras, las cuales iremos aadiendo mediante los mtodos AddTipoObjeto() de esta clase, hasta conseguir el grfico final resultante. Ver el Cdigo fuente 17.
Private Sub mnuGPathAbierta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuGPathAbierta.Click ' crear el objeto GraphicsPath Dim oGraphPath As 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)})

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

La Figura 5 muestra el resultado de una figura creada con GraphicsPath.

Figura 5. Imagen generada con un objeto GraphicsPath.

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.

Figura 6. Imgenes unidas creadas con un objeto GraphicsPath.

Aplicacin de efectos avanzados con la clase Brush


Para efectos avanzados de relleno, consistentes en degradados de colores, utilizaremos las clases LinearGradientBrush y PathGradientBrush. Una vez instanciado un objeto de estas clases, aplicaremos un conjunto de colores, que sern mezclados para crear un efecto de degradado o fundido en el rea a pintar, utilizando el constructor y/o las propiedades de la clase que corresponda. Ver el Cdigo fuente 19.
Private Sub mnuBrushLinearGradient_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushLinearGradient.Click ' crear pincel de tipo LinearGradient Dim oLGB As New LinearGradientBrush(New Rectangle(10, 50, 40, 60), Color.Aquamarine, Color.Azure, LinearGradientMode.Horizontal) ' crear array de coordenadas Dim oPuntos(2) As Point oPuntos(0) = New Point(20, 200) oPuntos(1) = New Point(75, 100) oPuntos(2) = New Point(140, 220) ' obtener contexto grfico Dim oGraphics As Graphics = Me.CreateGraphics() ' dibujar y pintar una curva cerrada

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

Figura 7. Figuras con efecto de gradiente.

Objetos grficos con caractersticas del sistema


Las clases SystemPens, SystemBrushes y SystemColors, nos permiten crear y manipular elementos grficos con la particularidad de que algunas de sus caractersticas sern iguales a las definidas para el sistema operativo. El Cdigo fuente 20 muestra unos ejemplos en los que creamos un objeto Pen del sistema, y un objeto Brush que tiene un color del sistema.
Private Sub mnuPenSistema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuPenSistema.Click ' crear objeto Pen del sistema Dim oPen As Pen oPen = SystemPens.ControlDark ' obtener el contexto de dispositivo ' grfico del formulario Dim oGraphics As Graphics = Me.CreateGraphics() ' dibujar en el formulario oGraphics.DrawEllipse(oPen, New Rectangle(150, 120, 100, 100)) oGraphics.Dispose() End Sub '-----------------------------------Private Sub mnuBrushSistema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuBrushSistema.Click ' crear un objeto brush con un color de sistema Dim oBrush As New SolidBrush(SystemColors.ControlDark) Dim oGraphics As Graphics = Me.CreateGraphics() oGraphics.FillEllipse(oBrush, New Rectangle(200, 200, 150, 50)) oGraphics.Dispose() End Sub private void mnuPenSistema_Click(object sender, System.EventArgs e) { // crear objeto Pen del sistema Pen oPen; oPen = SystemPens.ControlDark; // obtener el contexto de dispositivo

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

Dibujo de texto en el formulario


Aparte de los controles que nos permiten visualizar y editar texto, como Label, TextBox, etc., podemos realizar operaciones de dibujo de texto en la superficie del formulario, empleando el mtodo DrawString() de la clase Graphics. El texto visualizado mediante esta tcnica no es, evidentemente, editable, sino que se encamina fundamentalmente a ser mostrado con efectos adicionales, que no podramos conseguir mediante los controles tpicos. En el Cdigo fuente 21 creamos un objeto HatchBrush con un tramado especfico, un objeto Font de una determinada familia, y con ambos elementos, pintamos el texto mediante un objeto Graphics.
Private Sub mnuTextoGrafico_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTextoGrafico.Click ' crear un objeto Brush con efectos Dim oBrush As New HatchBrush(HatchStyle.Wave, Color.Aqua, Color.DarkGreen) ' crear el tipo de letra Dim oFont As New Font(New FontFamily("Georgia"), 50) ' obtener el dispositivo grfico del formulario ' y pintar el texto Dim oGraf As Graphics = Me.CreateGraphics() oGraf.DrawString("Texto en modo grfico", _ oFont, oBrush, New RectangleF(20, 20, 500, 200)) End Sub private void mnuTextoGrafico_Click(object sender, EventArgs e) { // crear un objeto Brush con efectos HatchBrush oBrush = new HatchBrush(HatchStyle.Wave, Color.Aqua, Color.DarkGreen); // crear el tipo de letra Font oFont = new Font(new FontFamily("Georgia"), 50); // obtener el dispositivo grfico del formulario // y pintar el texto Graphics oGraf = this.CreateGraphics(); oGraf.DrawString("Texto en modo grfico", oFont, oBrush, new RectangleF(20, 20, 500, 200)); oGraf.Dispose(); Cdigo fuente 21

P g i n a | 30

La Figura 8 muestra el texto dibujado en el formulario.

Figura 8. Dibujo de texto empleando las clases para manipulacin de grficos.

Personalizacin de la imagen de fondo del formulario


Para establecer una imagen de fondo en el formulario disponemos de la propiedad BackgroundImage, aunque su facilidad de uso tiene desafortunadamente un lado negativo, ya que el tamao de la imagen asignada, no se adapta automticamente al del formulario. Por tal motivo, en este apartado vamos a proporcionar al lector un par de tcnicas, que le permitirn crear imgenes de fondo para formularios con ajuste dinmico, de forma que la imagen adapte sus dimensiones a las del formulario, cuando este cambie su tamao en tiempo de ejecucin.

Manipulacin de los eventos de pintado en la clase form


El primer ejemplo se basa en la codificacin del evento Paint() de la clase Form, dentro de cuyo mtodo manipulador creamos un objeto Bitmap, que contenga la ruta hacia un archivo con el grfico a mostrar de fondo. A continuacin, mediante el objeto Graphics obtenido del parmetro EventArgs del evento, pintamos el objeto Bitmap. Ver el Cdigo fuente 22.
Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint ' crear un objeto bitmap Dim oBitmap As New Bitmap("LogoWinXP.gif") ' pintar el objeto con el contexto ' grfico del formulario; ' el area a pintar abarca desde la ' coordenada 0,0 y toma el ancho y alto ' del formulario de su propiedad Size Dim oGraphics As Graphics = e.Graphics oGraphics.DrawImage(oBitmap, 0, 0, Me.Size.Width, Me.Size.Height) oGraphics.Dispose() End Sub private void Form1_Paint(object sender, PaintEventArgs e) { // crear un objeto bitmap Bitmap oBitmap = new Bitmap("LogoWinXP.gif"); // // // // // pintar el objeto con el contexto grfico del formulario; el area a pintar abarca desde la coordenada 0,0 y toma el ancho y alto del formulario de su propiedad Size

P g i n a | 31

Graphics oGraphics = e.Graphics; oGraphics.DrawImage(oBitmap, 0, 0, this.Size.Width, this.Size.Height); oGraphics.Dispose(); Cdigo fuente 22

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.

Figura 9. Imagen de fondo con repintado irregular.

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 10. Imagen de fondo del formulario empleando un PictureBox.

Manipulando el grado de opacidad del formulario


La propiedad Opacity de la clase Form, contiene un valor numrico de tipo Double que permite establecer el grado de opacidad del formulario. Cuando esta propiedad contenga el valor uno, el formulario se mostrar en la forma habitual, y cuando el valor sea cero, el formulario ser transparente. Podemos asignar valores intermedios de modo que hagamos parcialmente transparente el formulario, mostrando los elementos que quedan bajo el mismo. Debemos tener en cuenta que cuando asignemos este valor mediante la ventana de propiedades del formulario en modo de diseo, el nmero asignado ser el porcentaje de opacidad. La Figura 11 muestra la ventana de propiedades para este caso con un setenta y cinco por ciento de opacidad para el formulario.

Figura 11. Propiedad Opacity establecida desde la ventana de propiedades del IDE.

La Figura 12 muestra este formulario con el anterior porcentaje de opacidad.

P g i n a | 33

Figura 12. Formulario parcialmente transparente debido a la propiedad Opacity.

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

La Figura 13 muestra este ejemplo en ejecucin.

Figura 13. Utilizando un TrackBar para graduar la opacidad de un formulario.

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 double dbContador = 1;

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

// cerrar el formulario this.Close();

Cdigo fuente 27

Creacin de formularios con formas irregulares


Las capacidades grficas de GDI+ nos permiten dotar a los formularios de efectos hasta la fecha muy difciles de conseguir, si no se conoca en profundidad el API de Windows. Aspectos como la transparencia del formulario tratada en el apartado anterior, o el cambio en su forma estndar, que veremos seguidamente, permiten la creacin de ventanas con una apariencia no convencional.

Usando la clase region


Para cambiar el aspecto rectangular de un formulario, dotndole de una forma irregular, debemos, en primer lugar, declarar en nuestro cdigo el espacio de nombres System.Drawing.Drawing2D. A continuacin crearemos un objeto de la clase GraphicsPath, y mediante alguno de sus mtodos AddTipoObjeto(), le aadiremos una figura que ser la que se utilice para la forma del formulario. Finalmente crearemos un objeto de tipo Region, al que pasaremos el objeto GraphicsPath con la figura creada previamente. Esto crear una regin con dicha figura, que asignaremos a la propiedad Region del formulario, consiguiendo de esta manera, modificar el aspecto del formulario en cuanto a su forma. El Cdigo fuente 28 muestra unos ejemplos de cmo modificar el aspecto del formulario, que incorpora sendos botones para cambiar su forma a un crculo y un tringulo respectivamente.
Imports System.Drawing.Drawing2D '.... Private Sub btnCirculo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCirculo.Click ' crear un GraphicsPath y aadirle un crculo Dim oGPath As GraphicsPath = New GraphicsPath() oGPath.AddEllipse(New Rectangle(0, 0, 200, 260)) ' crear una regin con el objeto GraphicsPath ' y asignarla a la regin del formulario Me.Region = New Region(oGPath) End Sub Private Sub btnPoligono_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPoligono.Click ' mostrar el formulario con la forma ' de un tringulo utilizando tambin ' un objeto GraphicsPath y un Region Dim oPuntos(2) As Point oPuntos(0) = New Point(-20, -20) oPuntos(1) = New Point(-20, 200) oPuntos(2) = New Point(220, 90) Dim oGPath As GraphicsPath = New GraphicsPath() oGPath.AddPolygon(oPuntos) Me.Region = New Region(oGPath) End Sub

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

La Figura 14 muestra el formulario con forma de elipse.

Figura 14. Formulario con forma de elipse.

La Figura 15 muestra el formulario con forma de tringulo.

P g i n a | 38

Figura 15. Formulario con forma triangular.

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.

Figura 16. Formulario con forma y barra de ttulo visible.

Usando una imagen para definir la superficie del formulario


Esta tcnica consiste en tomar cualquier aplicacin de manipulacin grfica y realizar un dibujo que constituir la superficie de nuestro formulario. Asignaremos un color al dibujo y otro color al fondo de la imagen, o bien la dejaremos con fondo transparente, que ser el caso del ejemplo que expondremos a continuacin. La Figura 17 muestra la imagen que usaremos como formulario.

P g i n a | 40

Figura 17. Imagen para establecer la superficie del formulario.

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

La Figura 18 muestra el formulario despus de aadirle estos controles.

P g i n a | 41

Figura 18. Controles para el formulario.

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

Figura 19. Formulario basado en imagen.

Dibujo manual de elementos de un control


Siguiendo con estos aspectos de personalizacin grfica de la interfaz de usuario, le llega el turno en esta ocasin a los controles, ms concretamente a los controles de lista como ComboBox, que ser el objeto del ejemplo a desarrollar en el presente apartado. Por defecto, al desplegar la lista de elementos de un control ComboBox, el color de fondo de la misma se muestra en blanco, o a lo sumo, de un color asignado a travs de la propiedad BackColor. Sin embargo, hay ocasiones en las que sera deseable poder mostrar cada uno de los elementos de la lista con un color de fondo diferente. El control ComboBox expone esta funcionalidad al programador, la cual requerir por su parte algo de trabajo extra en codificacin. No obstante, los resultados obtenidos merecern el esfuerzo extra empleado. Para acceder a las operaciones de dibujo de forma personalizada, en primer lugar debemos cambiar el valor por defecto de la propiedad DrawMode, cuyo contenido es un tipo enumerado del mismo nombre que dispone de los valores mostrados en la Tabla 1.

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);

Cdigo fuente 32.

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

Figura 21. ComboBox con dibujo personalizado de elementos.

La clase ToolStripRenderer.Aplicando GDI+ en la presentacin de la barra de herramientas


Entre las diversas aplicaciones y usos que podemos dar a GDI+, se encuentra la capacidad de generar de forma personalizada determinadas caractersticas visuales de los objetos ToolStrip y sus clases derivadas. Cuando aadimos un componente ToolStrip a un formulario y abrimos su etiqueta inteligente, podemos ver que existe una propiedad con el nombre RenderMode. Esta propiedad se utiliza para indicar al objeto cul va a ser el estilo de presentacin de sus elementos. Los valores disponibles para esta propiedad son los siguientes: System. Visualiza el objeto con la apariencia bsica del sistema operativo. Ver la Figura 22.

Figura 22. Control ToolStrip con apariencia bsica.

Professional. Visualiza el objeto utilizando la combinacin visual mejorada de colores, letras, etc., correspondiente a WindowsXP. Ver la Figura 23.

Figura 23. Control ToolStrip con apariencia mejorada.

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);

Cdigo fuente 33.

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.

Figura 24. Control ToolStrip con apariencia personalizada.

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

Color.Lime, Color.LavenderBlush, _ LinearGradientMode.Vertical)

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); }

oLGB = new LinearGradientBrush(new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height), Color.Lime, Color.LavenderBlush, LinearGradientMode.Vertical);

oGraphics.FillRectangle(oLGB, new Rectangle(0, 0, e.Item.Bounds.Width, e.Item.Bounds.Height)); Cdigo fuente 35

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.

Figura 25. Efectos de presentacin en los elementos del control ToolStrip.

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

{ }

ToolStripManager.Renderer = new GeneradorPersonalizado(); Cdigo fuente 36

La Figura 26 muestra el resultado de aplicar el anterior cdigo fuente

Figura 26. Efectos de presentacin personalizados para todos los objetos.

Caso prctico. Creacin y aplicacin de un degradado de colores


Utilizando las caractersticas grficas de GDI+ debemos crear y aplicar un efecto de degradado de colores a la superficie de un formulario. Para seleccionar los colores que compondrn el degradado, emplearemos dos controles ListBox que rellenaremos con los nombres de los colores disponibles en la plataforma. Por otra parte, para elegir el modo de degradado a utilizar, aadiremos al formulario un control ComboBox, que igualmente rellenaremos con los nombres pertenecientes a este tipo de efecto. Una vez seleccionados todos los valores, mediante la pulsacin de un control Button, compondremos el degradado y lo aplicaremos al rea cliente del formulario.

P g i n a | 55

También podría gustarte