UNIVERSIDAD DEL ISTMO Ingeniería en computación PROFESOR M. en C. J. Jesús Arellano Pimentel NÚMERO DE PRÁCTICA 4 NOMBRE DE LA PRÁCTICA Manejo simple de mapas de bits (imágenes). OBJETIVO GENERAL Aprender a desplegar mapas de bits (imágenes) en aplicaciones Win32. OBJETIVOS ESPECÍFICOS EQUIPO REQUERIDO SOFTWARE REQUERIDO - Desplegar una imagen en formato BMP asociada a un recurso en una aplicación. Computadora personal con 512 MB de RAM mínimo. - Windows XP/Vista/7 - Dev-Cpp 1.- Fundamentos1 Desplegar un mapa de bits (imagen BMP) requiere procesar el mensaje WM_PAINT de la ventana que lo visualizará. Si el BMP va a estar asociado a un recurso, entonces será necesario adicionar al proyecto dos archivos más a parte del archivo con extensión .c, estos dos archivos extra tendrán extensiones .rc y .h. Cómo adicionar estos dos archivos y su contenido será explicado en el desarrollo de la práctica. A manera de repaso se recordará que, desde la perspectiva del programador, el GDI está formado por varios cientos de llamadas a función y algunos tipos de datos, macros y estructuras asociadas [Petzold96]. Todo lo que se traza en el área cliente de una ventana se hace a través de un handle al GDI y el método más habitual para obtener un handle de contexto de dispositivo y luego liberarlo es utilizando las funciones BeginPaint (“comenzar a pintar”) y EndPaint (“finalizar pintura”) cuando se procesa un mensaje WM_PAINT: PAINTSTRUCT ps; HDC hdc; //… case WM_PAINT: hdc = BeginPaint(hwnd, &ps); //Lo que se quiera pintar o trazar EndPaint(hwnd, &ps); break; 1 Para una mejor comprensión de esta práctica se requiere haber realizado la práctica número 2 referente al GDI y el uso básico de recursos. Ingeniería en Computación M. C. J. Jesús Arellano Pimentel 1 2.- Desarrollo 2.1 Aplicación para desplegar un BMP a través de un recurso Paso 1 Iniciar el Dev-Cpp. Paso 2 Crear un Nuevo Proyecto. Hacer clic sobre el menú “Archivo” y seleccionar la opción “Nuevo -> Proyecto” (ver Figura 1). Figura 1. Menú para crear un nuevo proyecto. Paso 3 Configurar el Nuevo Proyecto. De la ventana referente al Nuevo Proyecto (ver Figura 2), seleccionar el icono de “Windows Application”, el lenguaje C y habilitar la casilla de “Lenguaje por omisión”. Finalmente dar nombre al proyecto, se sugiere BmpRecurso, y presionar el botón “Aceptar”. Figura 2. Configuración del Nuevo Proyecto Win32. Una vez que presionemos el botón “Aceptar” se solicitará guardar el proyecto, dejar el nombre dado previamente al proyecto es la mejor opción. Paso 4 Editar el código del archivo main.c y renombrarlo a BmpRecurso.c. En la línea 50 de la función WinMain correspondiente a la creación de la ventana principal modificar la cadena “Caption” por “BmpRecurso”, esto cambiará el título de la ventana. También se deben modificar los parámetros de las líneas 53 y 54 de la función CreateWindow por 400, 300, esto definirá el tamaño inicial para la ventana en 400 pixeles en x y 300 pixeles en y. Ingeniería en Computación M. C. J. Jesús Arellano Pimentel 2 En la función WndProc (línea 4) dar un salto de línea y agregar las dos siguientes variables previo a la estructura switch, estas dos variables son necesarias para tener la capacidad de pintar en el área cliente: PAINTSTRUCT ps; HDC hdc; En la misma función WndProc, dentro de la estructura switch, agregar el procesamiento del mensaje WM_PAINT antes del procesamiento del mensaje WM_CLOSE con el siguiente código: /*Todo el código para pintar va aquí*/ case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; } Guardar el archivo como BmpRecurso.c. Una vez hecho lo anterior se tiene lista la aplicación para desplegar el mapa de bits cuando se procese el mensaje WM_PAINT. Sin embargo, antes de codificar las instrucciones necesarias para visualizar la imagen se van a crear los archivos de encabezado y de recursos, posteriormente se indicarán las instrucciones parar desplegar la imagen. Paso 5 Crear el archivo de encabezado BmpRecurso.h. Del menú principal elegir la opción Archivo->Nuevo->Archivo Fuente, cuando aparezca el cuadro de diálogo para confirmar si deseamos añadir el nuevo archivo al proyecto, se debe responder que Si (Yes). Editar en el archivo las siguientes líneas de código (constantes simbólicas): /*Archivo de constantes simbólicas para recursos*/ #define IDB_IMAGEN1 201 Guardar el archivo como BmpRecurso.h. Paso 6 Crear el archivo de recursos Del menú principal elegir la opción Archivo->Nuevo->Archivo de Recursos (ver Figura 3). Aparecerá un cuadro de diálogo con la pregunta “¿Añadir Nuevo Archivo de Recursos al Proyecto?”, Se debe presionar el botón “Sí” (ver Figura 4). Ingeniería en Computación M. C. J. Jesús Arellano Pimentel 3 Figura 3. Menú para adicionar un nuevo Archivo de Recurso al proyecto. Figura 4. Cuadro de diálogo para un Nuevo Recurso. Paso 7 Editar el código del Nuevo Archivo de Recursos El código a editar en el nuevo archivo es el siguiente: #include "BmpRecurso.h" /* Imagen a desplegar */ IDB_IMAGEN1 BITMAP "Dibujito.bmp" Guardar el archivo con el nombre de BmpRecurso.rc. Considere que es importante tener una imagen en formato de mapa de bits (de cualquier gama de colores) en la ruta donde se esta creando la aplicación Win32, es decir, donde se encuentran todos los archivos creados hasta ahora. Para esta práctica en particular el nombre de dicha imagen debe ser exactamente “Dibujito.bmp”; si se quiere desplegar una imagen con otro nombre de archivo se deberá escribir dicho nombre en lugar de “Dibujito.bmp”. Paso 7 Modificar el archivo BmpRecurso.c para desplegar el BMP asociado al recurso Adicionar al principio del archivo, después de la línea de código #include <windows.h> la inclusión del archivo de cabecera creado en el paso 5 añadiendo la siguiente línea de código: #include “BmpRecurso.h” Agregar la declaración de cuatro variables más en la función WndProc, después de la última declaración al inicio de la función (HDC hdc;), de la siguiente forma: HDC hdcMem; static HBITMAP BITMAP bm; Ingeniería en Computación bmp1, bmpAnt; M. C. J. Jesús Arellano Pimentel 4 En la estructura switch se va agregar el código para el mensaje WM_CREATE para cargar el BMP una sola vez cuando se crea la aplicación, el código que debe ir dentro de dicha estructura es el siguiente: case WM_CREATE:{ bmp1=LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_IMAGEN1)); if(bmp1 == NULL) MessageBox(hwnd, "No se pudo cargar la imagen Dibujito.bmp", "Error", MB_OK | MB_ICONEXCLAMATION); break; } Ahora estamos en la posibilidad de adicionar el código necesario para desplegar la imagen en el procesamiento del mensaje WM_PAINT. Dicho código consta de diversas sentencias que permiten crear un dispositivo de contexto compatible para el BMP y así poder seleccionarlo y desplegarlo. Las sentencias que despliegan el BMP utilizadas son 2 BitBlt y StretchBlt, la primera de ellas despliega el BMP en sus dimensiones originales, la segunda permite redimensionarlo al tamaño que se desee. El código para procesar el mensaje WM_PAINT debe quedar de la siguiente forma: case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); hdcMem = CreateCompatibleDC(hdc); bmpAnt = SelectObject(hdcMem, bmp1); GetObject(bmp1, sizeof(bm), &bm); BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); StretchBlt(hdc, bm.bmWidth, 0, bm.bmWidth/2, bm.bmHeight/2, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); StretchBlt(hdc, bm.bmWidth+bm.bmWidth/2, bm.bmHeight/2, bm.bmWidth/4, bm.bmHeight/4, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); SelectObject(hdcMem, bmpAnt); DeleteDC(hdcMem); EndPaint(hwnd, &ps); break; } Observe que las dos llamadas a StretchBlt en el código anterior utilizan el propio tamaño del BMP para redimensionar la imagen haciéndola más pequeña, sin embargo el ancho y alto de la imagen puede tomar cualquier valor entero positivo. Ingeniería en Computación M. C. J. Jesús Arellano Pimentel 5 Por último también se debe limpiar el BMP cargado en el mensaje WM_CREATE, esto se logra adicionando una línea de código en el mensaje WM_CLOSE el cual es invocado cuando la ventana se cierra, la línea a adicionar es: DeleteObject(bmp1); de tal forma que el código del mensaje WM_CLOSE debería quedar de la siguiente manera: case WM_CLOSE: { DeleteObject(bmp1); DestroyWindow(hwnd); break; } Paso 5 Guardar, Compilar y Corregir Guardar todos los archivos y Compilar. El resultado de la compilación puede marcar un error en un archivo llamado BmpRecurso_private.rc, para corregirlo solo se cambia la cadena “Sin Nombre1.rc” por “BmpRecurso.rc”, Guardar y volver a Compilar y Ejecutar presionando la tecla F11. La ejecución de se muestra en la Figura 5. Figura 6. Ventana de la aplicación BmpRecurso. 3.- Ejercicios 3.1 Cargar y desplegar dos BMP Cargar y desplegar dos imágenes, una a la izquierda y otra a la derecha. Recuerde que debe adicionar otra constante simbólica más en el archivo .h y otro recurso más con el nombre del nuevo archivo bmp en el archivo .rc, finalmente deberá codificar los mensajes WM_CREATE, WM_PAINT y WM_CLOSE en el archivo .c para: a) cargar la imagen, b) desplegar la imagen y c) limpiar la carga de la imagen. 4.- Referencias [Petzold96] Petzold Charles, et al. Programación en Windows 95. Mc Graw Hill – Microsoft Press. 1996. Ingeniería en Computación M. C. J. Jesús Arellano Pimentel 6