[ contenidos | #winprog ]

Aplicaci�n Parte 3: Barras de Herramientas y Barras de Estado

Ejemplo: app_three

[images/app_three.gif]

Una Palabra IMPORTANTE en los Controles Comunes

Al igual que con todos los controles comunes, debemos llamar a InitCommonControl ANTES de intentar usarlos. Necesitaremos #include <commctrl.h> para poder usar esta funci�n y para obtener la funciones y declaraciones necesarias para el uso de los controles comunes. Tambi�n necesitaremos agregar comctl32.lib en la configuraci�n de nuestro enlazador (linker), si no se encuentra configurado de esa manera. Observa que InitCommonControls( ) es una vieja API, para obtener mas control podemos usar InitCommonControlsEx( ) la cual es requerida por los m�s recientes controles comunes. Sin embargo, debido a que no voy a usar ninguna de las caracter�sticas avanzadas, InitCommonControls( ) ser� adecuado y mas simple.

Barras de Herramientas

Podemos crear una barra de herramientas usando CreateToolbarEx( ) pero no es la idea... Lo que necesitamos hacer es crear la barra de herramientas...

    hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
        hwnd, (HMENU)IDC_MAIN_TOOL, GetModuleHandle(NULL), NULL);

Esto es bastante simple, TOOLBARCLASSNAME es una constante definida por los encabezados (headers) de los controles comunes. hwnd es la ventana padre, la ventana en la que aparecer� la barra de herramientas. IDC_MAIN_TOOL es un identificador que podemos usar posteriormente para obtener el HWND de la barra de herramientas por medio de GetDlgItem( ).

     // Send the TB_BUTTONSTRUCTSIZE message, which is required for
     // backward compatibility.
     SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

Este mensaje es necesario para permitirle al sistema darse cuenta que versi�n de la librer�a de controles comunes estamos usando. Debido a que nuevas versiones agregan c�digo a la estructura, dando el tama�o de la misma el sistema puede darse cuenta que comportamiento estamos esperando.

Botones de la barra de Herramientas

Los botones con bitmaps para las barras de herramientas vienen en dos variedades, los botones est�ndar que son provistos por comctl32 y los botones definidos por el usuario, que son creados por �l mismo. NOTA: Los botones y bitmaps son agregados a las barras de herramientas en forma separada... primero agregamos una lista de im�genes a usar y luego agregamos la lista de botones. Por �ltimo especificamos que imagen usar en cada bot�n.

Agregado de Botones Est�ndar

Ahora que hemos creado una barra de herramientas, necesitamos agregarle algunos botones. Los bitmaps mas comunes est�n disponibles dentro de la librer�a de los controles comunes, por lo tanto no necesitamos crearlos o agregarlos en cada archivo .exe que los usa.

Primero declaramos TBBUTTON y TBADDBITMAP

    TBBUTTON tbb[3];
    TBADDBITMAP tbab;
y luego agregamos los los bitmaps est�ndar a la barra de herramientas usando la lista de im�genes en la libreria de los controles comunes...
    tbab.hInst = HINST_COMMCTRL;
    tbab.nID = IDB_STD_SMALL_COLOR;
    SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM)&tbab);
Ahora que hemos cargado nuestras im�genes, podemos agregar algunos botones que las utilicen...
    ZeroMemory(tbb, sizeof(tbb));
    tbb[0].iBitmap = STD_FILENEW;
    tbb[0].fsState = TBSTATE_ENABLED;
    tbb[0].fsStyle = TBSTYLE_BUTTON;
    tbb[0].idCommand = ID_FILE_NEW;

    tbb[1].iBitmap = STD_FILEOPEN;
    tbb[1].fsState = TBSTATE_ENABLED;
    tbb[1].fsStyle = TBSTYLE_BUTTON;
    tbb[1].idCommand = ID_FILE_OPEN;

    tbb[2].iBitmap = STD_FILESAVE;
    tbb[2].fsState = TBSTATE_ENABLED;
    tbb[2].fsStyle = TBSTYLE_BUTTON;
    tbb[2].idCommand = ID_FILE_SAVEAS;

    SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb);
Aqu� hemos agregado los botones New, Open y Save As usando las im�genes est�ndar, lo cual es una buena idea debido a que las personas suelen verlas y ya saben que significan.

Los �ndices de las lista de im�genes est�n definidos en los encabezados de los controles comunes y tambi�n son listados en MSDN.

Hemos asignado a cada bot�n un ID (ID_FILE_NEW, etc...) lo cual es id�ntico a los IDs de los items equivalentes en el Men�. Estos botones generar�n mensajes WM_COMMAND identicos a los del Men�, por lo tanto no se requiere alg�n procesamiento extra! Si fueramos a agregar un bot�n para un comando que no aparece en el Men�, simplemente definimos un nuevo ID y agregamos un manejador a WM_COMMAND.

Si te est�s preguntando por qu� he pasado wParam a TB_ADDBUTTONS, bueno, est� realizando un c�lculo del n�mero de botones en el arreglo tbb para que no necesitemos especificar un valor. Si en lugar de esto, lo que hacemos es poner un 3, bien, estar�a correcto pero que sucede si queremos agregar otros botones... deber�amos cambiar este numero por 4 y en programaci�n eso no es muy bueno... queremos que los cambios provoquen la menor cantidad de cambios. Por ejemplo, si el tama�o de TBBUTON tiene 16 bits, debido a que tenemos 3 botones el tama�o del tbb deber�a ser de 16*3 = 48. Del mismo modo, 48/16 da el n�mero de botones, 3 en este caso.

Barras de Estado

Algo que se suele encontrar a menudo en las aplicaciones son las barras de estado, la peque�a barra en la parte inferior de la ventana que muestra informaci�n. Son muy f�cil de usar, solo hay que crearlas...
    hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
        WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0,
        hwnd, (HMENU)IDC_MAIN_STATUS, GetModuleHandle(NULL), NULL);
Y luego (opcionalmente) especificamos el numero de secciones que deseamos. Si no especificamos ninguna, simplemente tendr� una que usa el ancho entero de la barra. Podemos especificar o recuperar el texto usando SetWindowText( ) como con lo hac�amos con muchos de los otros controles. Si especificamos m�s de una secci�n, necesitamos especificar el ancho de cada una y luego usar SB_SETTEXT para especificar el texto de cada secci�n.

Para definir los anchos declaramos un arreglo de enteros donde cada valor es el ancho en pixeles de una secci�n. Si queremos que una secci�n use el espacio restante fijamos como valor -1.

El wParam nuevamente es para calcular cuantos elementos hay en el arreglo. Una vez que hemos terminado de agregar secciones, fijamos el primer valor (de �ndice 0) para verla en acci�n.

Tama�o Apropiado

A diferencia de los Men�es, las barras de estado y de herramientas son controles separados que viven dentro del �rea cliente de la ventana padre. Por lo tanto si solo dejamos nuestro c�digo WM_SIZE anterior, se van a solapar con el control edit que hemos agregado en los ejemplos anteriores. En WM_SIZE, ponemos las barras de estado y de herramientas en posici�n y luego restamos el alto del area cliente para que podamos mover nuestro control edit para rellenar el espacio restante...
    HWND hTool;
    RECT rcTool;
    int iToolHeight;

    HWND hStatus;
    RECT rcStatus;
    int iStatusHeight;

    HWND hEdit;
    int iEditHeight;
    RECT rcClient;

    // Size toolbar and get height

    hTool = GetDlgItem(hwnd, IDC_MAIN_TOOL);
    SendMessage(hTool, TB_AUTOSIZE, 0, 0);

    GetWindowRect(hTool, &rcTool);
    iToolHeight = rcTool.bottom - rcTool.top;

    // Size status bar and get height

    hStatus = GetDlgItem(hwnd, IDC_MAIN_STATUS);
    SendMessage(hStatus, WM_SIZE, 0, 0);

    GetWindowRect(hStatus, &rcStatus);
    iStatusHeight = rcStatus.bottom - rcStatus.top;

    // Calculate remaining height and size edit

    GetClientRect(hwnd, &rcClient);

    iEditHeight = rcClient.bottom - iToolHeight - iStatusHeight;

    hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
    SetWindowPos(hEdit, NULL, 0, iToolHeight, rcClient.right, iEditHeight, SWP_NOZORDER);

Desafortunadamente esta es una porci�n de c�digo bastante larga, pero es simple... las barras de herramiemntas se autoposicionar�n cuando env�emos el mensaje TB_AUTOSIZE y las barras de estado har�n lo mismo cuando enviemos WM_SIZE (las librer�as de los controles comunes no entienden nada a cerca de consistencia).


Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.

Versi�n en Espa�ol: Federico Pizarro - 2003