Capítulo 18 Objetos básicos del GDI: La pluma (Pen)

La pluma se utiliza para trazar líneas y curvas. En este capítulo veremos cómo crearlas, seleccionarlas y destruirlas, y cómo elegir el estilo, grosor y color para una pluma.

El proceso con los objetos es siempre el mismo, hay que crearlos, seleccionarlos y, cuando ya no se necesiten, destruirlos.

Plumas de Stock

La única excepción a lo dicho antes es un pequeño almacén de objetos que usa el sistema y que están disponibles para usar en nuestros programas.

El ejemplo anterior funciona gracias a ello, ya que usa la pluma por defecto del DC. En el caso de los objetos de stock, no es necesario crearlos ni destruirlos (aunque esto último no está prohibido), siempre podemos obtener un manipulador y seleccionarlo para usarlo.

Concretamente, en el caso de las plumas, existen tres en el stock:

Valor Significado
BLACK_PEN Pluma negra
NULL_PEN Pluma nula
WHITE_PEN Pluma blanca

Para obtener un manipulador para una de esos objetos de stock se usa la función GetStockObject. Dependiendo del valor que usemos obtendremos un tipo de objeto diferente.

Plumas cosméticas y geométricas

Existen dos categorías de plumas.

Las cosméticas se crean con un grosor expresado en unidades de dispositivo, es decir, las líneas que se tracen con estas plumas tendrán siempre el mismo grosor. Estas plumas sólo tienen tres atributos: grosor, color y estilo. Las plumas de stock son de este tipo.

Las geométricas se crean con un grosor expresado en unidades lógicas. Esto significa que el grosor de las líneas puede ser escalado, y depende de la transformaciones actuales del "mundo actual" (veremos esto en siguientes capítulos). Además de los tres atributos que también tienen las plumas cosméticas, las geométricas poseen otros cuatro: plantilla, trama opcional, estilos para extremos y para uniones.

Las líneas trazadas con plumas cosméticas son entre tres y diez veces más rápidas que las de las geométricas.

Crear una pluma

Si no vamos a utilizar una pluma de stock, (la verdad es que están muy limitadas), podemos crear nuestras propias plumas.

Para ello disponemos de la función CreatePen. Esta función también nos devuelve un manipulador, en este caso de pluma, que podremos usar posteriormente para seleccionar la nueva pluma.

CreatePen nos pide tres parámetros. El primero es el estilo de línea, podemos elegir uno de los siguientes valores:

Estilo Descripción
PS_SOLID Las líneas serán continuas y sólidas.
PS_DASH Líneas de trazos. Este estilo sólo es válido cuando el ancho de la pluma sea uno o menos en unidades de dispositivo.
PS_DOT Líneas de puntos. Este estilo sólo es válido cuando el ancho de la pluma sea uno o menos en unidades de dispositivo.
PS_DASHDOT Líneas alternan puntos y trazos. Este estilo sólo es válido cuando el ancho de la pluma sea uno o menos en unidades de dispositivo.
PS_DASHDOTDOT Líneas alternan líneas y dobles puntos. Este estilo sólo es válido cuando el ancho de la pluma sea uno o menos en unidades de dispositivo.
PS_NULL Las líneas son invisibles.
PS_INSIDEFRAME Las líneas serán sólidas. Cuando ésta pluma se usa en cualquier función de dibujo del GDI que requiera un rectángulo que sirva como límite, las dimensiones de la figura se reducirán para que se ajusten por completo al interior del rectángulo, teniendo en cuenta el grosor de la pluma. Esto sólo se aplica a plumas geométricas.

El segundo parámetro es el grosor de la línea en unidades lógicas, si se especifica un grosor de cero, la línea tendrá un pixel de ancho.

El último parámetro es un COLORREF, que será el color de las líneas.

Evidentemente, CreatePen sólo puede crear plumas cosméticas.

Existen otras dos funciones para crear plumas: CreatePenIndirect y ExtCreatePen.

La primera sirve también para crear plumas cosméticas, pero lo hace a través de una estructura LOGPEN, que almacena en su interior los mismos parámetros que se pasan a la función CreatePen. Esto puede ser útil cuando creemos muchas plumas distintas o varias con muy pocas diferencias.

La segunda nos permite crear tanto plumas cosméticas como geométricas. De momento no veremos este tipo de plumas, las dejaremos para capítulos más avanzados.

Seleccionar una pluma

Aunque podemos disponer de un repertorio de manipuladores de pluma, sólo puede haber una activa en cada momento, para seleccionar la pluma activa se usa la función SelectObject.

En realidad, ésta función sirve para seleccionar cualquier tipo de objeto, no sólo plumas. El tipo de objeto seleccionado depende el parámetro que se pase a la función. El nuevo objeto seleccionado reemplaza al actual, y se devuelve el manipulador del objeto seleccionado anteriormente.

Se debe guardar el manipulador de la pluma por defecto seleccionada antes de cambiarla por primera vez, y restablecerlo antes de terminar el procedimiento de pintar.

Destruir una pluma

Por último, cuando ya no necesitemos más los manipuladores de plumas, debemos destruirlos, con el fin de liberar la memoria usada para almacenarlos. Esto se hace mediante la función DeleteObject.

Ejemplo 16


  Nombre Fichero Fecha Tamaño Contador Descarga
D Ejemplo 16 win016.zip 2004-01-18 2178 bytes 848

Comentarios de los usuarios (3)

Diego
2012-04-24 02:49:28

Hola, he leido ya los primeros 18 capítulos del curso WinAPI32, creando un proyecto por cada uno practicamente :), está todo muy completo, aunque ahora que comenzé a ver el GDI me surgieron algunas dudas.

Supongo que existen varias versiones del API de windows, yo en este momento estoy usando Dev-C++, ¿debería actualizar el API? ¿estas versiones podrían traer nuevas funciones, como me entero de ello y como usarlas en ese caso?

También leí sobre algo que se llamaba microsoft foundation classes, que si no entendí mal, era una adaptación de esta API escrita en C, a C++ usando objetos y encapsulamiento, ¿Que me podrían decir acerca de ello?

Por último leí sobre bibliotecas gráficas especializadas en el 3D, Direct3D y OpenGL, las cuales se ocupan principalmente en juegos bastante elaborados, y supongo que tienen relación con el GDI ¿Cual sería conveniente usar? ¿Como podrían influir en los programas para Windows y en lo que se enseña en este curso?

Ya sé que son muchas preguntas, solo que me he desorientado un poco y quisiera saber si me pueden echar una mano, saludos.

Steven R. Davidson
2012-04-24 03:34:38

Hola Diego,

La verdad es que no existen tantas versiones del API de MS-Windows. Principalmente, tenemos el apodo de "Win32" para referirnos a la versión de 32 bits de MS-Windows. Existe una versión de 64 bits, pero realmente se trata de unas cuantas funciones que usan enteros de 64 bits; no hay una gran diferencia entre ambas versiones. Ciertamente, algunas funciones han sido agregadas en diferentes versiones, pero el API fundamentalmente no ha cambiado.

Algunas funciones agregadas aparecen con nuevas versiones de Internet Explorer, como son algunos controles comunes (barras de progreso, control de pestañas, etc.). Otras funciones nuevas aparecen por otras razones. Me temo que tendrías que mirar la documentación oficial para estas otras funciones y posiblemente otras bibliotecas agregadas al API de MS-Windows para saber cuándo se agregaron y posiblemente necesites saber las constantes simbólicas a definir para indicar al compilador cuáles funciones - posteriormente añadidas al API - quieres usar.

El hecho de usar Dev-C++ es irrelevante en cuanto a las bibliotecas que usas, ya que el compilador que usa Dev-C++ por defecto es MinGW. Así que te interesa actualizar MinGW. Debería haber unos paquetes de Dev-C++ para actualizar MinGW o posiblemente solo el API de MS-Windows. El descargador de paquetes está en el menú de las herramientas. Elige los paquetes (bibliotecas) que quieres descargar e instalar.

Personalmente, me pasaría a usar Code::Blocks y MinGW, ya que CB es un proyecto activo mientras que Dev-C++ está en desuso.

En cuanto a las MFC, se crearon para los programadores de C++ y principalmente para organizar mejor el API de MS-Windows que, aun siendo básica, no es particularmente fácil de usar. Si quieres usar las MFC, adelante. El único problema es que vas a tener que aprender más nombres, porque están las clases más las funciones miembro. Al final, vas a usar el API de MS-Windows, tanto directa o indirectamente. Eso sí, las MFC no "envuelven" todo el API de MS-windows, por lo que en algunas ocasiones vas a tener que recurrir a una función que proviene directamente del API de MS-Windows.

DirectX es un API para videojuegos, aunque más centrada en gráficos, y OpenGL es una biblioteca para gráficos de alta calidad. Puedes usar el API de MS-Windows para crear el programa en sí y además programar la interfaz gráfica de usuario (GUI) si quieres que tenga un aspecto de MS-Windows. Sin embargo, la forma de programar DirectX u OpenGL con el API de MS-Windows es creando un "contexto de renderizado" (RC) que conceptualmente es similar al "contexto de dispositivo [gráfico]" (DC) del API. Todas las funciones gráficas de DirectX y OpenGL se usan con el RC mientras que las de la GDI se usan con el DC. En la práctica no tiene sentido usar la GDI para dibujar la geometría ya que las otras bibliotecas son superiores en rendimiento y ofrecen una gama más amplia de objetos gráficos como primitivos que los ofrecidos por la GDI.

Espero haber aclarado las dudas.

Steven

Diego
2012-04-24 04:34:00

Muchas gracias por la respuesta, me ha quedado bastante más claro, creo que mejor seguiré leyendo este curso, seguramente aclararé muchas dudas con el tiempo, después cuando esté familiarizado con el API de MS-Windows, veré las novedades de bibliotecas que tengan, saludos.