Capítulo 48 Listas de imágenes

Haremos un interludio en este capítulo. Las listas de imágenes no son extrictamente controles, al menos según mi opinión, aunque la documentación de Microsoft los considera como tales. Pero sí los usaremos en otros controles que veremos en próximos capítulos, como en las barras de herramientas, los TreeViews o los ListViews, por lo que será bueno conocerlos antes.

Las listas de imágenes se usan también para operaciones de arrastrar y soltar.

Para poder usar las listas de imágenes en nuestros programas es necesario incluir el fichero de cabecera "commctrl.h", enlazar con la librería "comctl32", y asecurarse de que la dll ha sido cargada invocando a la función InitCommonControls.

Una lista de imágenes es una colección de imágenes del mismo tamaño, a las que podemos acceder mediante un índice. Todas las imágenes se almacenan en un único mapa de bits, una a continuación de otra. Existe la opción de añadir un segundo mapa de bits monocromo con máscaras, de modo que las imágenes se puedan mostrar con una zona transparente, igual que los iconos.

El API suministra funciones y macros para crear y destruir listas de imágenes, añadir o eliminar imágenes de una lista, mostrarlas en pantalla, extraer iconos, etc.

Crear una lista de imágenes

Consideraremos las listas de imágenes como un recurso. Y como tal, las crearemos cuando las necesitemos y las destruiremos cuando ya no sean necesarias. Generalmente usaremos los mensajes de creación de ventanas o diálogos para crear las listas de imágenes, y los mensajes de destrucción para destruirlas.

Crear una lista de imágenes requiere varios pasos. El primero es crear la pripia lista, usando la función ImageList_Create. Esta función necesita varios parámetros:

  • La anchura y altura de las imágenes que contiene.
  • Unas banderas que indican la codificación de color y si se trata de una lista de imágenes con o sin máscara.
  • El número de imágenes iniciales de la lista.
  • Y el número de imágenes en el que la lista crecerá si es necesario añadir imágenes a ella.
    static HIMAGELIST hIml;
    static HIMAGELIST hIml2;
...
        hIml = ImageList_Create(32, 32, ILC_COLOR24, 10, 4);
        hIml2 = ImageList_Create(24, 24, ILC_COLOR8 | ILC_MASK, 15, 2);
...

Este ejemplo crea dos listas de imágenes. La primera con 10 imágenes de 32x32 pixels y 24 bits de profundidad de color. Si fuera necesario añadir imágenes, la lista crecerá en grupos de cuatro imágenes. La segunda con 15 imágenes de 24x24 pixels y 8 bits de profundidad de color, y que crecerá en grupos de dos imágenes.

Esta función crea una lista vacía, en el punto siguiente veremos cómo añadir imágenes.

Una vez terminado el trabajo con las listas de imágenes procederemos a destruirlas, de modo que se liberen los recursos usados, para ello usaremos la función ImageList_Destroy:

        ImageList_Destroy(hIml);
        ImageList_Destroy(hIml2);

Añadir y eliminar imágenes

Disponemos de una batería de funciones para añadir, eliminar y sustituir imágenes en una lista de imágenes.

Las dos funciones principales para añadir imágenes a una lista son ImageList_Add y ImageList_AddMasked.

A pesar de lo que pueda indicar el nombre, las dos funciones pueden insertar imágenes con máscara, aunque la forma de indicar esa máscara es diferente en cada caso.

ImageList_Add toma tres parámetros. El primero es un manipulador de la lista de imágenes a la que se añadirá la imagen. El segundo es un manipulador de mapa de bits con la imagen a añadir. El tercero es un manipulador de mapa de bits con la máscará para la imagen. Si este parámetro es 0, no se usará máscara.

           hbmp = LoadBitmap(hInstance, "mapabits");
           ImageList_Add(hIml, hbmp, 0);
           DeleteObject(hbmp);
...
           hbmp2 = LoadBitmap(hInstance, "docmask");
           hbmp = LoadBitmap(hInstance, "doc1");
           ImageList_Add(hIml2, hbmp, hbmp2);
           DeleteObject(hbmp);
           DeleteObject(hbmp2);

ImageList_AddMasked también toma tres parámetros. El primero es un manipulador de la lista de imágenes a la que se añadirá la nueva imagen. El segundo es un manipulador de mapa de bits con la imagen a añadir. El tercero es un valor COLORREF con el color que se usará para generar la máscara. Cada pixel de ese color en la imagen insertada corresponde con un bit puesto a uno en la máscara.

           hbmp = LoadBitmap(hInstance, "doc1");
           ImageList_AddMasked(hIml2, hbmp, RGB(255,0,128));
           DeleteObject(hbmp);

La función ImageList_Replace nos permite sustituir una imagen de una lista de imágenes. Los parámetros son los mismos que para ImageList_Add, salvo que se añade un parámetro entero después del manipulador de la lista, que indica el índice de la imagen a sustituir.

También podemos añadir imágenes desde iconos, usando la macro ImageList_AddIcon o la función ImageList_ReplaceIcon. En el caso de la macro ImageList_AddIcon, el primer parámetro es un manipulador de la lista de imágenes a la que añadiremos la imagen, y el segundo un manipulador de icono.

           hicon = LoadIcon(hInstance, "tierra");
           ImageList_AddIcon(hIml2, hicon);

En el caso de la función ImageList_ReplaceIcon el primer argumento es el mismo, el segundo es un entero que indica el índice de la imagen a sustituir dento de la lista, y el tercero es un manipulador de icono. Si el segundo parámetro es -1, el icono se añade al final de la lista. Eso es lo que hace la macro ImageList_AddIcon.

Disponemos de una función similar para sustituir imágenes a partir de manipuladores de mapas de bits, en lugar de iconos, ImageList_Replace. El primer argumento es un manipulador de lista de imágenes, el segundo el índice de la imagen a sustituir, el tercero el manipulador del mapa de bits de la imagen, y el cuarto el manipulador del mapa de bits de la máscara.

           hicon = LoadIcon(hInstance, "casa");
           hbmp2 = LoadBitmap(hInstance, "docmask");
           hbmp = LoadBitmap(hInstance, "doc1");
           ImageList_Replace(hIml2, 9, hbmp, hbmp2);
           DeleteObject(hbmp2);
           DeleteObject(hbmp);
           ImageList_ReplaceIcon(hIml, 9, hicon);

Por último, también es posible eliminar imágenes de una lista mediante la función ImageList_Remove. Esta función sólo necesita dos argumentos. El primero, un manipulador de la lista de imágenes, y el segundo, el índice de la imagen a eliminar.

           ImageList_Remove(hIml2, 9);

Crear listas con imágenes

La función ImageList_LoadImage nos permite crear una lista de imágenes y añadir imágenes al mismo tiempo. Estos dos ejemplos son equivalentes:

           hIml = ImageList_LoadImage(hInstance, "mapabits", 32, 4, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION);

Y:

           hIml = ImageList_Create(32, 32, ILC_COLOR24, 10, 4);
           hbmp = LoadBitmap(hInstance, "mapabits");
           ImageList_Add(hIml, hbmp, 0);
           DeleteObject(hbmp);

La función ImageList_LoadImage necesita siete parámetros. El primero es un manipulador de la instancia desde donde se carga el mapa de bits. También puede ser cero, si se cargan mapas de bits OEM (mapas de bits, iconos o cursores del sistema).

El segundo parámetro es un identificador de recurso, un nombre de fichero o un entero que identifique un recurso de sistema.

El tercero indica la anchura en pixels de cada imagen. El número de imágenes se calcula a partir de las dimensiones del mapa de bits.

El cuarto parámetro indica la cantidad de imágenes en que crecerá la lista si es necesario añadir imágenes.

El quinto es el color utilizado para crear la máscara, o CLR_NONE para si no se quiere generar máscara.

El sexto indica el tipo de imagen a cargar, IMAGE_BITMAP, IMAGE_ICON o IMAGE_CURSOR.

El séptimo parámetro es un conjunto de banderas que especifican el modo de cargar la imagen. En nuestro caso hemos especificado LR_CREATEDIBSECTION para indicar que se preserve el número de bits por color de la imagen original. Hay banderas para indicar que se cargue la imagen desde un fichero, para que sean transparentes, etc.

Otra función similar es ImageList_LoadBitmap, salvo que sólo dispone de los primeros cinco parámetros, por lo que no es posible cargar mapas de bits desde ficheros ni usar mapas de bits de tipo DIB.

           hIml = ImageList_LoadBitmap(hInstance, "mapabits", 32, 4, CLR_NONE);

La última función de este grupo es ImageList_Merge. Esta función crea una nueva lista de imágenes con una única imagen que es el resultado de mezclar dos imágenes procedentes de dos listas de imágenes. Las dos listas pueden ser la misma. El primer y segundo parámetro son el manipulador de la lista de imágenes e índice de la primera imagen, el tercero y cuarto el manipulador de la lista e índice de la segunda imagen. El quinto y sexto es un desplazamiento de la segunda imagen sobre la primera.

           hIml3 = ImageList_Merge(hIml2, 2, hIml2, 10, 0, 0);

Obtener iconos

La función ImageList_GetIcon nos permite extraer un icono desde una lista de imágenes. El primer parámetro es el manipulador de una lista de imágenes, el segundo parámetro es el índice de la imagen. El tercero es una combinación de banderas análogas a las de la función ImageList_Draw. El resultado es el manipulador de un icono extraido de la lista.

    HICON hicon;
    ...
    hicon = ImageList_GetIcon(himl, 2, ILD_TRANSPARENT);

Mostrar imágenes

Todo lo anterior suele ser suficiente para muchas de las aplicaciones de las listas de imágenes. Por ejemplo, los controles ListView y TreeView se encargan de mostrar las imágenes para cada ítem, según su estado de forma automática. Sin embargo, también podemos mostrar imágenes de una lista de imágenes desde nuestros programas, para ello disponemos de un par de funciones.

La función ImageList_Draw permite trazar una imagen de una lista de imágenes. Esta función requiere seis parámetros. El primero, un manipulador de la lista de imágenes. El segundo, un índice de la imagen a mostrar. El tercero, un manipulador de contexto de dispositivo de destino. El cuarto y quinto, las coordenadas donde se mostrará la imagen. Y el sexto el estilo de trazado.

Hay que tener en cuenta que si la lista de imágenes ha sido creada con la bandera ILC_COLORDDB, ILC_COLOR24 o ILC_COLOR32, los estilos resaltados ILD_BLEND25 e ILD_BLEND50 usarán una trama de puntos, y no se podrá distinguir entre ellos. El resto de las banderas de color usan una mezcla para hacer los resaltados, y en general, tendrán un aspecto diferente si se usa ILD_BLEND25 o ILD_BLEND50.

Los estilo ILD_BLEND25 e ILD_BLEND50 se añaden a ILD_NORMAL y ILD_TRANSPARENT para indicar que el usuario ha seleccionado la imagen.

Además, el modo normal con imágenes de listas sin máscara es equivalente al modo transparente, en ninguno de los dos casos hay transparencias.

Cuando estos estilos se aplican a imágenes que provienen de listas con máscaras, la diferencia es más sutil. Si se muestra en el estilo normal la parte del fondo enmascarada se muestra con el color de fondo de la lista de imágenes. Si se muestra en el estilo transparente la parte del fondo enmascarada conserva el contenido original.

Por último, el estilo ILD_MASK muestra la máscara, si existe.

    ImageList_Draw(hIml, 3, hDC, 10, 40, ILD_BLEND25 | ILD_NORMAL);

La función ImageList_DrawEx es más versatil. Además de los parámetros usados con ImageList_Draw, se deben especificar algunos más, lo que nos proporciona un control adicional sobre el aspecto de las imágenes.

Los cinco primeros parámetros son los mismos que para ImageList_Draw. Los dos siguientes indican la anchura y altura de la imagen a mostrar, pueden ser cero, para indicar que se muestre la anchura y altura por defecto. El octavo parámetro es un color usado para pintar el fondo. Puede ser cualquier color RGB, el valor CLR_NONE, para indicar que no hay color de fondo o CLR_DEFAULT para indicar que se use el color de fondo por defecto. El noveno parámetro es un color de usado para el primer plano, y también puede tomar los valores CLR_NONE o CLR_DEFAULT. Este cólor sólo se usa para los resaltados ILD_BLEND25 y ILD_BLEND50, y no se tiene en cuenta si no aparencen esas banderas. Si se usa el valor CLR_DEFAULT, el resultado es el mismo que con la función ImageList_Draw. El último parámetro es el mismo que el último de ImageList_Draw, e indica las banderas de estilo.

    ImageList_DrawEx(hIml, 3, hDC, 10, 40, 32, 32, GetSysColor(COLOR_MENU), RGB(255,0,0) , ILD_BLEND25 | ILD_NORMAL);

El color de fondo

Para cada lista de imágenes podemos establecer un color de fondo, que se usará para rellenar el espacio no enmascarado cuando se tracen imágenes en el estilo normal. Este color no afecta a listas de imágenes sin máscaras. Para asignar el color de fondo se usa la función ImageList_SetBkColor, indicando como parámetros el manipulador de la lista de imágenes y el color de fondo que se quiere establecer. Para recuperar el color de fondo de una lista de imágenes podemos usar la función ImageList_GetBkColor.

    ImageList_SetBkColor(hIml, GetSysColor(COLOR_MENU));

Imágenes superpuestas

Acceso directo
Acceso directo

En cada lista de imágenes se pueden indicar hasta cuatro imágenes que se podrán usar posteriormente como imágenes superpuestas. El efecto es similar al que usa Windows para crear los iconos de acceso directo, cuando añade una pequeña flecha en una de las esquinas al icono de la aplicación.

Estas imágenes se conocen en el API como "overlay masks". Se puede usar cualquier imagen de la lista como imagen superpuesta, tan sólo hay que especificar cuales de ellas lo pueden ser usando la función ImageList_SetOverlayImage. Hay que especificar tres parámetros. El primero un manipulador de la lista de imágenes, el segundo el índice de la imagen, y el tercero el número de la imagen superpuesta, entre 1 y 4.

Para trazar una imagen superpuesta se usan las funciones ImageList_Draw o ImageList_DrawEx, el índice de la imagen superpuesta se indica mediante la macro INDEXTOOVERLAYMASK añadida a las banderas de estilo.

    ImageList_SetOverlayImage(hIml2, 6, 1);
...
    ImageList_Draw(hIml2, 2, hDC, 10, 10, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1));

Ejemplo 81


  Nombre Fichero Fecha Tamaño Contador Descarga
D Ejemplo 81 win081.zip 2012-05-16 278884 bytes 233