Capítulo 40 Control List box avanzado

Insertar controles list box durante la ejecución

Al igual que vimos con los controles edit, también es posible insertar controles list box durante la ejecución. En el caso del control list box tendremos que insertar una ventana de la clase "LISTBOX". Para insertar el control también usaremos las funciones CreateWindow y CreateWindowEx.

    HWND hctrl;
...
        case WM_CREATE:
           hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
           /* Insertar control Edit */
           hctrl = CreateWindowEx(
              0,
              "LISTBOX",       /* Nombre de la clase */
              "",              /* Texto del título, no tiene */
              LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, /* Estilo */ 
              9, 19,           /* Posición */
              104, 99,         /* Tamaño */
              hwnd,            /* Ventana padre */
              (HMENU)ID_LISTA, /* Identificador del control */
              hInstance,       /* Instancia */
              NULL);           /* Sin datos de creación de ventana */ 
           /* Inicialización de los datos de la aplicación */
           SendMessage(hctrl, LB_ADDSTRING, 0, (LPARAM)"Cadena nº 1");
           SendMessage(hctrl, LB_ADDSTRING, 0, (LPARAM)"Cadena nº 4");
           SendMessage(hctrl, LB_ADDSTRING, 0, (LPARAM)"Cadena nº 3");
           SendMessage(hctrl, LB_ADDSTRING, 0, (LPARAM)"Cadena nº 2");
           SendMessage(hctrl, LB_SELECTSTRING, (UINT)-1, (LPARAM)Datos.Item);
           SetFocus(hctrl);
           return 0;

Como vemos, usamos los mismos valores que en el fichero de recursos: identificador, clase de ventana (en este caso "LISTBOX"), estilo, posición y dimensiones.

Al igual que en el caso del control edit, el identificador del control se suministra a través del parámetro hMenu, por lo que será necesario hacer un casting del valor del identificador a HMENU.

Ahora será nuestro procedimiento de ventana, (si el control se ha insertado en una ventana), el encargado de procesar los mensajes procedentes del control. Recordemos que en los ejemplos que hemos visto hasta ahora esto lo hacía el procedimiento de diálogo.

Cambiar la fuente de un control list box

También es posible modificar la fuente de un control list box enviando un mensaje WM_SETFONT. El lugar apropiado es, por supuesto, al procesar el mensaje WM_INITDIALOG cuando se inicie un cuadro de diálogo, o al procesar el mensaje WM_CREATE cuando se inicie una ventana,.

En el parámetro wParam pasamos un manipulador de fuente, y usaremos la macro MAKELPARAM para crear un valor LPARAM, en el que especificaremos la opción de repintar el control, que se almacena en la palabra de menor peso de LPARAM.

Esto nos permite modificar la fuente durante la ejecución, reflejando los cambios en pantalla.

   static HFONT hfont;
...
           hfont = CreateFont(24, 0, 0, 0, 300,
              FALSE, FALSE, FALSE, DEFAULT_CHARSET,
              OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
              PROOF_QUALITY, DEFAULT_PITCH | FF_ROMAN,
              "Times New Roman");
           SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
...
        case WM_DESTROY:
           DeleteObject(hfont);
...

En el caso de crear una fuente especial para nuestros controles, debemos recordar destruirla cuando ya no sea necesaria, generalmente al destruir la ventana.

Por supuesto, también podemos usar una fuente de stock:

           hfont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
           SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));

Cambiar los colores de un control list box

Para terminar, también podemos personalizar más nuestros controles list box, cambiando los colores del texto y del fondo. Para ello deberemos procesar el mensaje WM_CTLCOLORLISTBOX.

Este mensaje se envía a la ventana padre del control justo antes de que el sistema lo vaya a dibujar, y nos permite cambiar los colores del texto y fondo. Para ello nos suministra en el parámetro wParam un manipulador del contexto de dispositivo del control, y en lParam un manipulador del control, mediante el cual podemos saber a qué control concreto se refiere el mensaje.

El valor de retorno, si se procesa este mensaje, debe ser un manipulador de pincel con el color de fondo del control.

    static HBRUSH pincel;
    HWND hcrtl;

    switch (msg)                  /* manipulador del mensaje */
    {
        case WM_CREATE:
           hcrtl = CreateWindowEx(...);
           pincel = CreateSolidBrush(RGB(0,255,0));
           SetFocus(hcrtl);
           return 0;
        case WM_CTLCOLORLISTBOX:
           SetBkColor((HDC)wParam, RGB(0,255,0));
           SetTextColor((HDC)wParam, RGB(255,255,255));
           return (LRESULT)pincel;
        case WM_DESTROY:
           DeleteObject(pincel);
           PostQuitMessage(0);    /* envía un mensaje WM_QUIT a la cola de mensajes */
           break;
...

Ejemplo 56


  Nombre Fichero Fecha Tamaño Contador Descarga
D Ejemplo 56 win056.zip 2007-03-15 3135 bytes 250

Mensajes de notificación

Los list box también envían mensajes de notificación para informar sobre determinados eventos.

Los mensajes de notificación se reciben a través de un mensaje WM_COMMAND. En la palabra de menor peso del parámetro wParam se envía el identificador del control. El manipulador del control se envía en el parámetro lParam y el código del mensaje de notificación en la palabra de mayor peso de wParam.

Nota: en el API de Windows 3.x el código del mensaje de notificación se envía en el parámetro lParam. Hay que tener esto en cuenta si se intenta portar código entre estas plataformas.

Veamos a continuación los mensajes de notificación que existen para los controles list box:

Doble clic

Cada vez que el usuario hace doble clic sobre uno de los ítems de un list box, se envía un mensaje de notificación LBN_DBLCLK a la ventana padre.

Falta espacio

Si no es posible conseguir memoria para completar una operación sobre el list box, se envía un mensaje de notificación LBN_ERRSPACE.

Pérdida y recuperación de foco

Cada vez que el usuario selecciona otro control se envía un mensaje de notificación LBN_KILLFOCUS.

Cuando el usuario selecciona un control list box, se envía un mensaje de notificación LBN_SETFOCUS.

Selección y deselección

Cada vez que la selección de un list box se modifique se envía un mensaje LBN_SELCHANGE.

Cuando el usuario cancela la selección de un ítem, se envía el mensaje LBN_SELCANCEL.

   /* Respuesta a mensaje de notificación de cambio de selección:
    Si la selección cambia se actualiza la ventana. */
        case WM_COMMAND:
           switch(LOWORD(wParam)) {
              case ID_LISTA:
                 switch(HIWORD(wParam)) {
                   case LBN_SELCHANGE:
                      InvalidateRect(hwnd, NULL, TRUE);
                      break;
                 }
                 break;