| |||||||||||||||||||||||||||||||
Controles Este capítulo supone que tienes conocimeintos previos en. . . 6.1 Controles de WindowsExisten una serie de controles que tienen la función de interactuar con el usuario. Un control es un tipo especial de ventana que permite un tipo específico de interacción del usuario. Por ahora nos concentraremos en 3 de los controles más utilizados en Windows: control etiqueta, control caja de texto y control botón.
Antes de analizar líneas de código e introducirle en la teoría, me gustaría que viese el resultado de generar el Programa5.cpp ya que así le será más fácil imaginar el alcance de este capítulo. Para generar una ventana como la que se muestra en la figura anterior, es necesario seguir los siguientes pasos:
#include <windows.h> HWND CreaVentana(char szNombreAplicacion[], int ancho, int alto, HINSTANCE hInstancia, WNDPROC ProcedimientoVentana) { HWND hwnd; WNDCLASSEX ventana; //Configuramos la ventana ventana.cbSize = sizeof(ventana); ventana.style = CS_HREDRAW | CS_VREDRAW; ventana.lpfnWndProc = ProcedimientoVentana; ventana.hInstance = hInstancia; ventana.lpszClassName = szNombreAplicacion; ventana.hIcon = LoadIcon (NULL, IDI_APPLICATION); ventana.hIconSm = LoadIcon (NULL, IDI_APPLICATION); ventana.hCursor = LoadCursor (NULL, IDC_ARROW); ventana.lpszMenuName = NULL; ventana.cbClsExtra = 0; ventana.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1); ventana.cbWndExtra = 0; // Registrar la clase de ventana, si falla, salir del programa if(!RegisterClassEx(&ventana)) return (FALSE); hwnd = CreateWindowEx( 0, szNombreAplicacion, //Nombre de clase de la ventana a la que pertenece szNombreAplicacion, //Título de la ventana WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, ancho, //Ancho alto, //Alto HWND_DESKTOP, NULL, hInstancia, NULL); ShowWindow(hwnd, SW_SHOWNORMAL); return hwnd; }
#include "ventana.h" // Se encarga de informar si hubo un error al crear el control // y cambia la fuente por la predeterminada en el Panel de Control HWND Control(HWND hwndHija, HWND hwndPadre) { if (hwndHija == NULL) MessageBox(hwndPadre, "No se puede crear el control.", "¡Error!", MB_OK | MB_ICONERROR); else SendMessage(hwndHija, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); return hwndHija; } // Crea una Etiqueta o Labelbox //============================== HWND Etiqueta(HWND hPadre, LPSTR texto, int x, int y, int ancho, int alto) { HWND hEtiqueta; hEtiqueta = CreateWindowEx(NULL, "STATIC", texto, WS_CHILD | WS_VISIBLE, x, y, ancho, alto, hPadre, NULL, NULL, NULL); return Control(hEtiqueta, hPadre); } // Crea una Caja de Texto o Textbox //================================== HWND Caja_Texto(HWND hPadre, LPSTR texto, int x, int y, int ancho, int alto) { HWND hCaja_Texto; hCaja_Texto = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", texto, WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, x, y, ancho, alto, hPadre, NULL, NULL, NULL); return Control(hCaja_Texto, hPadre); } // Crea un Botón //=============== HWND Boton(HWND hPadre, LPSTR texto, int x, int y, int ancho, int alto) { HWND hBoton; hBoton = CreateWindowEx(NULL, "BUTTON", texto, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, x, y, ancho, alto, hPadre, NULL, NULL, NULL); return Control(hBoton, hPadre); } HWND hETIQUETA, hCAJATEXTO, hBOTON; LRESULT CALLBACK ProcedimientoVentana(HWND hPadre, UINT mensaje, WPARAM wParam, LPARAM lParam) { switch (mensaje) { case WM_CREATE: { //Aquí deberán crearse los controles //================================== hETIQUETA = Etiqueta(hPadre,"Etiqueta", 10, 10, 180, 20); hCAJATEXTO = Caja_Texto(hPadre,"Caja Texto", 10, 40, 180, 20); hBOTON = Boton(hPadre,"Botón", 50, 70, 100, 30); break; } case WM_DESTROY: { PostQuitMessage (0); return 0; } } return DefWindowProc (hPadre, mensaje, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstancia, HINSTANCE hInstanciaPrev, LPSTR lpLineaCmd, int nEstadoVentana) { CreaVentana("Programa 5", 208, 150, hInstancia, ProcedimientoVentana); // Bucle de mensajes: MSG mensaje; while(GetMessage(&mensaje, 0, 0, 0) > 0) { TranslateMessage(&mensaje); DispatchMessage(&mensaje); } return (int) mensaje.wParam; }
¡Listo! Juege con la ventana. Quizás le parezcan muchas líneas para mostrar 1 ventana y 3 controles. Observe que puede maximizar la ventana, minimizarla, escribir en la caja de texto, seleccionar texto, copiar y pegar, el efecto sobre el botón de que se sumerge y vuelve a emerger al oprimirlo, etcétera. En realidad son unas cuantas líneas las necesarias para generar este programa si se toma en cuenta que pueden crearse funciones genéricas reutilizables en un archivo adicional (nuestra propia librería) tal como se hizo con ventana.h. 6.2 ¿Qué son los controles?En realidad, para Windows, los controles no son más que ventanas que reciben y procesan ciertos mensajes de una u otra forma. Es por ello que para crear un control se utiliza la función que hemos estado utilizado para crear ventanas en el capítulo 3, Para indicar que se trata de una ventana hija, se manda la constante Toda ventana tiene un Procedimiento de Ventana asociado. Windows proporciona una serie de clases de ventana las cuales implementan el comportamiento de los controles por medio de procedimientos de ventana por defecto
HWND hCONTROL; LRESULT CALLBACK ProcedimientoVentana(HWND hPadre, UINT mensaje, WPARAM wParam, LPARAM lParam) { switch (mensaje) { case WM_CREATE: { //Aquí deberán crearse los controles //================================== hCONTROL = CreateWindowEx(...); break; } case WM_DESTROY: { ... } } return DefWindowProc (hPadre, mensaje, wParam, lParam); } 6.3 Control EtiquetaEl control etiqueta resulta de mucha utilidad para mostrar un texto al usuario sin que este pueda modificarlo. Para crear una etiqueta es necesario especificar la clase "STATIC" como segundo parámetro de la función
HWND hEtiqueta = CreateWindowEx(0, "STATIC", "Texto etiqueta", WS_CHILD | WS_VISIBLE, x, y, ancho, alto, hPadre, NULL, NULL, NULL); Recuerde que la función
Se puede pensar que después de llamar a
HWND Etiqueta(HWND hPadre, LPSTR texto, int x, int y, int ancho, int alto) { HWND hEtiqueta; //Añadir WS_BORDER para agregar un borde a la etiqueta hEtiqueta = CreateWindowEx(0, "STATIC", texto, WS_CHILD | WS_VISIBLE, x, y, ancho, alto, hPadre, NULL, NULL, NULL); if (hEtiqueta == NULL) { MessageBox(hPadre, "No se puede crear etiqueta.", "¡Error!", MB_OK | MB_ICONERROR); } else { //Opcional: Ponemos la fuente configurada por defecto en el sistema SendMessage(hEtiqueta, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); } return hEtiqueta; } Modificando el primer y cuarto parámetro (
//NOTA: falta verificar si se ha creado la ventana o de lo contrario mostrar un // mensaje de error if (hEtiqueta == NULL) { mensaje... } // Este código es meramente didáctico. HWND hETIQUETA = CreateWindowEx(NULL, "STATIC", "Etiqueta, fuente Windows 3.11", WS_CHILD | WS_VISIBLE, 10, 10, 180, 18, hPadre, NULL, NULL, NULL); HWND hETIQUETA1 = CreateWindowEx(NULL, "STATIC", "Etiqueta1", WS_CHILD | WS_VISIBLE, 10, 40, 180, 18, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA1, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA2 = CreateWindowEx(NULL, "STATIC", "Etiqueta2 con WS_DISABLED", WS_CHILD | WS_VISIBLE | WS_DISABLED, 10, 70, 180, 18, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA2, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA3 = CreateWindowEx(NULL, "STATIC", "Etiqueta3 con WS_BORDER", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 100, 180, 18, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA3, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA4 = CreateWindowEx(NULL, "STATIC", "Etiqueta4 con WS_DLGFRAME", WS_CHILD | WS_VISIBLE | WS_DLGFRAME, 10, 130, 180, 21, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA4, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA5 = CreateWindowEx(NULL, "STATIC", "Etiqueta5 con WS_THICKFRAME", WS_CHILD | WS_VISIBLE | WS_THICKFRAME, 10, 160, 180, 21, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA5, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA6 = CreateWindowEx(WS_EX_CLIENTEDGE, "STATIC", "Etiqueta6 con WS_EX_CLIENTEDGE", WS_CHILD | WS_VISIBLE, 210, 40, 230, 21, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA6, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA7 = CreateWindowEx(WS_EX_DLGMODALFRAME, "STATIC", "Etiqueta7 con WS_EX_DLGMODALFRAME", WS_CHILD | WS_VISIBLE, 210, 70, 230, 21, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA7, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); HWND hETIQUETA8 = CreateWindowEx(WS_EX_STATICEDGE, "STATIC", "Etiqueta8 con WS_EX_STATICEDGE", WS_CHILD | WS_VISIBLE, 210, 100, 230, 21, hPadre, NULL, NULL, NULL); SendMessage(hETIQUETA8, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); 6.4 Control Caja de textoEl control caja de texto permite al usuario introducir información a través del teclado. Para crear una caja de texto es necesario especificar la clase "EDIT" como segundo parámetro de la función
HWND hCTexto = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, x, y, ancho, alto, hPadre, NULL, NULL, NULL); Es muy importante que la función De manera similar al control etiqueta, es posible modificar los parámetros
6.5 Control BotónEl control botón permite al usuario disparar acciones al oprimir sobre este con un clic. Pertenece a la clase "BUTTON". Igual que en los controles anteriores, deberá indicarse
HWND hBoton = CreateWindowEx(NULL, "BUTTON", "", WS_CHILD | WS_VISIBLE, x, y, ancho, alto, hPadre, NULL, NULL, NULL); 6.6 TranslateMessage()Típicamente se utiliza dentro del bucle de mensajes. La función Se acostumbra a incluirla ya que no entorpece la ejecución del programa y a menos que se trate de un programa muy simple, casi siempre es necesaria. En caso de que se requiera tener una caja de texto en el programa, se debe incluir por obligación.
// Bucle de mensajes: MSG mensaje; while(GetMessage(&mensaje, 0, 0, 0) > 0) { TranslateMessage(&mensaje); DispatchMessage(&mensaje); } 6.7 ConclusiónLos controles permiten al usuario efectuar acciones sobre el programa para comunicar algún tipo de información. En el siguiente capítulo veremos como podemos crear nuestras propias librerías de código reutilizable, que harán que nuestros programas sean mucho más legibles y fáciles de codificar. | |||||||||||||||||||||||||||||||
|