Ejemplo: app_three
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.
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.
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.
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.
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).
Versión en Español: Federico Pizarro - 2003