[ contenidos | #winprog ]

Aplicaci�n Parte 1: Crear Controles en Tiempo de Ejecuci�n

Example: app_one

[images/app_one.gif]

Pienso que dar un ejemplo sobre crear controles en ejecuci�n, si bien es muy usado, podr�a ser en vano a menos que la aplicaci�n realmente haga algo �til, por lo tanto en esta secci�n voy a comenzar con el desarrolo de un editor de texto y lo iremos desarrollando hasta que alcanzemos un programa �til que soporte abrir, editar y guardar archivos de textos.

El primer paso, el cual es cubierto por esta secci�n, ser� simplemente crear la ventana y el control EDIT que servir� como centro de nuestro programa.

Comenzaremos con el esquelto del c�digo de la aplicaci�n Simple Window, agregaremos un #define para el ID de nuestro control y los siguientes dos manejadores de mensajes en nuestro window procedure:

#define IDC_MAIN_EDIT	101
    case WM_CREATE:
    {
        HFONT hfDefault;
        HWND hEdit;

        hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", 
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
            0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
        if(hEdit == NULL)
            MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);

        hfDefault = GetStockObject(DEFAULT_GUI_FONT);
        SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
    }
    break;
    case WM_SIZE:
    {
        HWND hEdit;
        RECT rcClient;

        GetClientRect(hwnd, &rcClient);

        hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
    }
    break;

Crear los controles

Para crear los controles, al igual que lo hacemos para cualquier otra ventana, utilizamos la API CreateWindowEx( ). Pasamos una clase pre-registrada, en este caso la clase del control "EDIT", y obtenemos un control edit est�ndar. Cuando usamos di�logos para crear nuestros controles, b�sicamente estamos escribiendo una lista de controles a crear, tal que, cuando llamamos a DialogBox( ) o CreateDialog( ) el sistema lee la lista de controles en el recurso di�logo y por cada uno llama a CreateWindowEx( ), con la posici�n y estilo con que fueron definidos.
    hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", 
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
        0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
    if(hEdit == NULL)
        MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
Puedes ver que esta llamada a CreateWindowEx( ) especifica cierta cantidad de estilos y no es extra�o tener alguno mas, especialmente para los controles comunes los cuales tienen una larga lista de opciones. Los primeros cuatro estilos WS_ deberian ser obvios, estamos creando el control como un hijo de nuestra ventana, queremos que sea visible y tenga barras de desplazamiento vertical y horizontal. Los tres estilos que son espec�ficos de los controles EDIT (ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL) especifican que el control edit debe poseer m�ltiples lineas de texto y desplazarse autom�ticamente cuando tipeamos mas alla del l�mite inferior de la ventana y del limite derecho de la misma.

Los estilos regulares (WS_*) puedes encontrarlos en: listed here. y los estilos extendidos (WS_EX_*) son explicados en: CreateWindowEx() estas referencias son de MSDN donde tambi�n puedes encontrar links a los estilos espec�ficos de cada control (ES_* en el caso del control EDIT).

Hemos especificado nuestro window handle como padre del control y le asignamos un ID de IDC_MAIN_EDIT, el cual usaremos luego para referirnos al control, de la misma manera que lo hariamos si el control hubiera sido creado en un di�logo. Los par�metros de posici�n y tama�o no importan mucho por el momento, debido a que cambiaremos el tama�o del control din�micamente con el mensaje WM_SIZE para que �ste siempre entre en nuestra ventana.

Cambio del tama�o de controles creados din�micamente

Generalmente, si el tama�o de nuestra ventana puede ser cambiado, tendremos alg�n c�digo para reposicionar o ajustar el tama�o de los controles que hemos creado dentro de ella, para que siempre sean mostrados apropiadamente.
    GetClientRect(hwnd, &rcClient);

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

Debido a que por ahora solo tenemos un control, la tarea es relativamente simple. Usamos GetClientRect( ) para obtener las dimensiones del Area Cliente de la ventana, la gran �rea vac�a (por ahora) que no inlcluye los bordes, men� o t�tulo. Esto llenar� nuestra estructura RECT con valores. Los valores left y top siempre ser�n 0, por lo tanto puedes ignorarlos. Los valores right and bottom indican el ancho y el alto del area cliente.

A Continuaci�n, simplemente obtenemos el handle a nuestro control EDIT usando GetDlgItem( ), el cual funciona bien en las ventanas regulares como en los di�logos y la llamada SetWindowPos( ) para mover y ajustar el tama�o para llenar todo el �rea cliente. Por su puesto, puedes cambiar los valores pasados en SetWindowPos( ) para hacer algo como s�lo llenar la mitad del alto de la ventana, dejando libre la parte inferior para ubicar otros controles.

Crear otros controles en tiempo de ejecuci�n

No voy a dar ejemplos de como crear din�micamente los otros controles, como listas, botones, etc... debido a que es b�sicamente lo mismo. Si visitas los links anteriores en MSDN o buscas en tu referencia de Win32 API, encotrar�s toda la informaci�n necesaria para crear cualquiera de los otros controles est�ndar.

Veremos mas sobre esto con los controles comunes, en la siguientes secciones, donde obtendr�s mas pr�ctica.


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

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