17 Objetos básicos del GDI:
El Contexto de dispositivo, DC

La estructura del DC, como la del resto de los objetos del GDI, no es accesible directamente desde las aplicaciones. Contiene los valores de ciertos atributos que determinan la posición y apariencia de la salida hacia un dispositivo.

Cada vez que se crea un DC, cada atributo tiene un valor por defecto conocido. Los atributos almacenados en el DC, y sus valores por defecto son:

Atributo Valor por defecto
Color de fondo Blanco (Depende del seleccionado en el panel de control)
Modo del fondo Opaco
Mapa de bits (bitmap) Ninguno
Pincel (Brush) WHITE_BRUSH (Blanco)
Origen para el pincel (0,0)
Región de recorte (Clipping region) Toda la superficie visible de la ventana
Paleta de colores DEFAULT_PALETTE (paleta por defecto)
Posición actual de la pluma (0,0)
Origen del dispositivo

Esquina superior derecha de la ventana o del área de cliente.

Modo de trazado R2_COPYPEN (sustitución del valor actual en pantalla)
Fuente SYSTEM_FONT (fuente del sistema)
Espacio entre caracteres 0
Modo de mapeo MM_TEXT (coordenadas de texto)
Pluma BLACK_PEN (negra)
Modo para el relleno de polígonos ALTERNATE (alternativo)
Modo de estiramiento (Stretching mode) BLACKONWHITE
Color de texto Negro
Tamaño del Viewport (1,1)
Origen del Viewport (0,0)
Tamaño de la ventana (1,1)
Origen de la ventana (0,0)

Existen funciones para acceder a los valores del DC, mediante un manipulador, ya sea para leer sus valores o para modificarlos. En próximos capítulos veremos algunas de ellas.

Actualizar el área de cliente de una ventana, el mensaje WM_PAINT

Todos los ejemplos estarán centrados en el proceso del mensaje WM_PAINT, que le indica al procedimiento de ventana que parte o toda su superficie debe ser actualizada.

En nuestros primeros ejemplos y mientras veamos los diferentes objetos, funciones y estructuras, no necesitaremos crear un DC, simplemente obtendremos un manipulador para el DC de la ventana de nuestro programa. Cada ventana tiene asociados varios DCs. A nosotros nos interesa el que está asociado al área de cliente.

Para actualizar el área de cliente de nuestra ventana tendremos que seguir una especie de "ritual". Eso es imprescindible, y a menudo se siguen estas "fórmulas" en muchos procesos de los programas Windows, muchas veces sin saber el motivo de cada paso. Pero en este curso intentaremos explicar el por qué de cada uno de los pasos, y que acciones desempeña cada uno de ellos.

Lo que sigue es un ejemplo muy sencillo de cómo se procesa un mensaje WM_PAINT:

    HDC hDC;
    PAINTSTRUCT ps;
...
        case WM_PAINT:
           hDC = BeginPaint(hwnd, &ps);
           Ellipse(hDC, 10, 10, 50, 50);
           EndPaint(hwnd, &ps);
           break;

Hay más formas de enviar salidas a una ventana, y las veremos más adelante, pero la más sencilla es ésta.

Utilizaremos la función BeginPaint para poder obtener un DC a nuestra ventana. Esta función además ajusta el área de "clipping", eso sirve para que sólo se actualice la parte de la ventana que sea necesario. Por ejemplo, imaginemos que nuestra ventana está parcialmente oculta por otras, y que la pasamos a primer plano. En ese caso, el área de "clipping" será sólo la correspondiente a las partes que estaban ocultas previamente, el resto de la ventana no se actualizará. Esto ahorra bastante tiempo de proceso, ya que dibujar gráficos suele ser un proceso lento.

El segundo parámetro es un puntero a una estructura PAINTSTRUCT que es necesario para la llamada. Los datos obtenidos mediante esa estructura pueden sernos útiles en algunas ocasiones, pero de momento sólo la usaremos para obtener un DC del área de cliente de la ventana.

Una vez que hemos obtenido un DC para nuestra ventana, podremos utilizarlo para dibujar en ella. En este ejemplo sólo se dibuja una circunferencia, usando al función Ellipse. En próximos ejemplos iremos complicando más esa parte.

Por último, una vez que hemos terminado de pintar, liberamos el DC usando la función EndPaint. Es muy importante hacer esto cada vez que obtengamos un DC mediante BeginPaint.

Colores

Windows almacena los colores en un entero de 32 bits en formato RGB, hay un tipo definido para eso, se llama COLORREF. Los 8 bits de menor peso se usan para almacenar la componente de rojo, los 8 siguientes para el verde, los 8 siguientes para el azul y el resto no se usa, y debe ser cero.

Para referenciar o asignar un color se usa la macro RGB, que admite tres parámetros de tipo BYTE, cada uno de ellos indica la intensidad relativa de una de las componentes: rojo, verde o azul, y devuelve un COLORREF.

También es posible obtener cada una de las componentes de un COLORREF mediante las macros GetRValue, GetGValue y GetBValue.