SDK Multiplataforma en C logo

SDK Multiplataforma en C

Window

❮ Anterior
Siguiente ❯

Funciones

Window*window_create (...)
voidwindow_destroy (...)
voidwindow_panel (...)
voidwindow_OnClose (...)
voidwindow_OnMoved (...)
voidwindow_OnResize (...)
voidwindow_title (...)
voidwindow_show (...)
voidwindow_hide (...)
uint32_twindow_modal (...)
voidwindow_stop_modal (...)
voidwindow_hotkey (...)
voidwindow_cycle_tabstop (...)
gui_focus_twindow_next_tabstop (...)
gui_focus_twindow_previous_tabstop (...)
gui_focus_twindow_focus (...)
GuiControlwindow_get_focus (...)
voidwindow_update (...)
voidwindow_origin (...)
voidwindow_size (...)
V2Dfwindow_get_origin (...)
S2Dfwindow_get_size (...)
S2Dfwindow_get_client_size (...)
voidwindow_defbutton (...)
voidwindow_cursor (...)

Los objetos Window son los contenedores de más alto nivel dentro de la interfaz de usuario (Figura 1). Están compuestos por la barra de título, donde se ubican los botones de cerrar, maximizar y minimizar, la zona interior y el marco. Si la ventana admite redimensionado, dicho marco podrá ser arrastrado con el ratón para cambiar su tamaño. La zona interior o área cliente de la ventana, se configura mediante un panel principal. En ¡Hola Mundo! tienes un ejemplo sencillo de composición y muestra de una ventana.

  • Utiliza window_create para crear una ventana.
  • Utiliza window_panel para asignar el panel principal.
  • Utiliza window_show para mostrar una ventana.
  • Utiliza el flag ekWINDOW_TITLE para incluir barra de título.
  • Utiliza window_title para asignar un título.
  • Captura del sistema operativo Windows 3.
    Figura 1: El concepto de ventana aparece desde los primeros sistemas de escritorio.
NAppGUI no distingue entre ventana, cuadro de diálogo, caja de mensaje, etc. El rol de cada ventana irá en función de los controles que contenga, su ubicación y su comportamiento.

1. Tamaño de la ventana

En principio, el tamaño de la ventana se calcula automáticamente en función del Dimensionado natural de su panel principal, pero puede ser alterado en cualquier momento.

  • Utiliza window_size para cambiar el tamaño del panel principal.
  • Utiliza el flag ekWINDOW_MAX para incluir el botón de maximizar en la barra de título.
  • Utiliza el flag ekWINDOW_MIN para incluir el botón de minimizar en la barra de título.
  • Utiliza el flag ekWINDOW_RESIZE para crear una ventana con bordes redimensionables.

El cambio en las dimensiones del área cliente lleva implícita una re-ubicación y re-dimensionado de los controles interiores. Esto se gestiona automáticamente por medio de los objetos layout, en función de como se haya configurado su Expansión de celdas y que se propagará de manera recursiva por todos los sublayouts. En Die tienes un ejemplo del redimensionado de una ventana (Figura 2).

Muestra como se reparte entre los controles el exceso al tamaño al redimensionar la ventana.
Figura 2: Redimensionado de la ventana en la demo Die.

2. Cierre de la ventana

Normalmente una ventana se cierra pulsando el botón [X] ubicado a la derecha de la barra de título. Pero, en ocasiones, puede ser útil cerrarla también mediante la teclas [ENTER] o [ESC]. Cerrar una ventana implica ocultarla, pero no destruirla. Es decir, podemos volver a mostrar una ventana ya cerrada utilizando window_show. En el caso de que el cierre esté condicionado a un estado de la aplicación, como guardar un archivo por ejemplo, deberemos asignar un manejador mediante window_OnClose y decidir ahí si se cierra o no.

Destruir una ventana destruye implícitamente todos sus elementos y controles internos.

3. Ventanas modales

Son aquellas que, al ser lanzadas, bloquean a la ventana anterior (o padre) hasta que no se produzca el cierre de la misma (Figura 3). El ser o no "modal" no es una característica de la ventana en sí, si no del modo de lanzarla. En ¡Hola Modal Window! tienes un ejemplo de uso.

  • Utiliza window_modal para mostrar una ventana en modo modal.
  • Utiliza window_stop_modal para ocultarla y detener el ciclo modal.
  • Varias ventanas modales.
    Figura 3: Varias ventanas modales.

Tras la llamada a window_modal, el programa queda detenido en este punto, a la espera del cierre de la ventana, que podrá realizarse mediante [X], [ENTER], [ESC] o llamando a window_stop_modal (Listado 2). El valor retornado por esta función será:

  • ekGUI_CLOSE_ESC (1). Si la ventana modal se cerró pulsando [ESC].
  • ekGUI_CLOSE_INTRO (2). Si la ventana modal se cerró pulsando [ENTER].
  • ekGUI_CLOSE_BUTTON (3). Si la ventana modal se cerró pulsando [X].
  • El valor indicado en window_stop_modal.
  • Listado 2: Uso de ventanas modales.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    static void i_OnAcceptClick(Window *window, Event *e)
    {
        window_stop_modal(window, 300);
    }
    
    Window *window = i_create_window_with_accept_button();
    // The program will stop HERE until window is closed
    uint32_t ret = window_modal(window);
    
    if (ret == 1)
    {
        // Closed by ESC
    }
    else if (ret == 2)
    {
        // Closed by INTRO
    }
    else if (ret == 3)
    {
        // Closed by [X]
    }
    else if (ret == 300)
    {
        // Closed by window_stop_modal
    }
    
    window_destroy(&window);
    

Por defecto, la ventana modal se ocultará tras recibir la llamada a window_stop_modal, pero no se destruirá como ya hemos indicado anteriormente. En determinadas ocasiones (aunque no muy habituales), es posible que queramos relanzar la ventana tras acabar el ciclo modal sin que se produzca un anti-estético "parpadeo" debido a una nueva (y rápida) visualización tras el cierre de la ventana.

  • Utiliza el flag ekWINDOW_MODAL_NOHIDE al crear la ventana para evitar que se oculte tras el ciclo modal.

4. Foco del teclado

Determinadas ventanas, como los cuadros de diálogo, hacen un uso intensivo del teclado. Incluso es posible que el usuario deba gestionar la entrada de datos prescindiendo del ratón. Es por esto que tenemos que tener muy claro como se comportan los diferentes elementos ante las pulsaciones. Se denomina foco del teclado al único control que recibe los eventos de teclas dentro de una ventana determinada. Normalmente este control aparece con el borde resaltado.

El foco del teclado se asigna automáticamente al primer control de la tab-list cuando se activa la ventana y se puede cambiar de diferentes maneras:

  • Mediante [TAB] o [SHIFT]+[TAB] nos desplazaremos por los controles incluidos en la tab-list, como ya vimos en Tabstops.
  • Haciendo clic sobre el control al que queremos conectar el teclado.
  • Utilizando window_focus, que lo establecerá en el control deseado mediante código.
  • Utilizando window_next_tabstop que equivale a pulsar [TAB]. En ¡Hola IP-Input! tienes varios Edit que pasan al siguiente control cuando se introducen exactamente tres números.
  • Utilizando window_previous_tabstop que equivale a pulsar [SHIFT]+[TAB].

El cambio del foco entre controles no es directo, mas bien sigue un protocolo (Figura 4). Por lo general no nos tenemos que preocupar por esto, ya que cada control presenta un comportamiento por defecto a la hora de liberar o aceptar el foco. Los puntos a tener presentes son los siguientes:

  • Los controles Edit pueden retener el foco como respuesta a un evento OnChange, como vimos en Filtrar textos.
  • Las vistas personalizadas permiten tomar una decisión en tiempo de ejecución mediante los eventos OnResignFocus y OnAcceptFocus, como también vimos en Uso del teclado. Por defecto, aceptarán ambos casos.
  • Gráfico que muestra el intercambio de mensajes para cambiar el foco del teclado a un nuevo control.
    Figura 4: Protocolo para el cambio del foco.

Volviendo a la navegación mediante la tecla [TAB], lo habitual será que los tabstops funcionen de manera cíclica (por defecto). Es decir, si el último control de la tab-list tiene el foco y pulsamos [TAB], el foco pasará de nuevo al primer control de la tab-list. Es posible deshabilitar este comportamiento, quedando el foco fijo en el último control aunque pulsemos repetidamente la tecla [TAB]. De igual forma, el foco quedará fijo en el primer control aunque pulsemos [SHIFT]+[TAB].


5. Botón por defecto

El botón por defecto es aquel que aparece resaltado dentro de la ventana y que recibirá un evento OnClick cada vez que se pulse la tecla [RETURN], independientemente de que control tenga el foco del teclado. En principio, no existe ningún botón por defecto, hay que indicarlo explícitamente en la ventana.

  • Utiliza window_defbutton para establecer el botón por defecto.
  • Captura que muestra una ventana donde aparece un botón por defecto.
    Figura 5: Botón por defecto.

6. Atajos de teclado

Como ya hemos indicado, el foco del teclado estará fijado en algún control del interior de la ventana ya sea un Edit, Button, View, etc. Pero es posible que queramos definir acciones globales asociadas a alguna tecla concreta.

Las hotkeys tendrán prioridad sobre el foco del teclado (Figura 6). Es decir, si tenemos una acción vinculada con la tecla [F9], la ventana capturará el evento ekGUI_EVENT_KEYDOWN (F9) y este no llegará al control que tiene actualmente el foco del teclado.

Atajo de teclado.
Figura 6: Procesamiento de un atajo de teclado.

Para concluir, resumimos todos los puntos a tener en cuenta a la hora de realizar una correcta gestión del teclado.

  • Cierre de la ventana con [RETURN] o [ESC.
  • Gestionar correctamente la tab-list y el foco del teclado.
  • Definir un botón por defecto, que se active al pulsar [RETURN].
  • Definir los atajos de teclado oportunos.
❮ Anterior
Siguiente ❯

window_create ()

Crea una nueva ventana.

Window*
window_create(const uint32_t flags);
flags

Combinación de valores window_flag_t.

Retorna

La ventana recién creada.


window_destroy ()

Destruye la ventana y todo su contenido.

void
window_destroy(Window **window);
window

La ventana. Será puesto a NULL tras la destrucción.

Observaciones

Se destruirán recursivamente paneles, layouts y componentes.


window_panel ()

Asocia el panel principal a una ventana.

void
window_panel(Window *window,
             Panel *panel);
window

La ventana.

panel

Panel principal, que integra todo el contenido de la ventana (vistas, controles, etc).

Observaciones

El tamaño de la ventana se ajustará en función del Dimensionado natural del panel principal.


window_OnClose ()

Establece un manejador para el evento de cierre de la ventana.

void
window_OnClose(Window *window,
               Listener *listener);
window

La ventana.

listener

Función callback que se llamará antes de cerrar una ventana.

Observaciones

Ver Cierre de la ventana.


window_OnMoved ()

Establece un manejador para el desplazamiento de la ventana por el escritorio.

void
window_OnMoved(Window *window,
               Listener *listener);
window

La ventana.

listener

Función callback que se llamará a medida que se arrastre la barra de título y se mueva la ventana por el escritorio.

Observaciones

Ver Eventos GUI.


window_OnResize ()

Establece un manejador para el redimensionado de la ventana.

void
window_OnResize(Window *window,
                Listener *listener);
window

La ventana.

listener

Función callback que se llamará a medida que se arrastren los bordes externos de la ventana para cambiar su tamaño.

Observaciones

El redimensionado y rehubicación de elementos se realiza de forma automática en función del Layout principal, por lo que no suele ser necesario que la aplicación responda a este evento. Ver Eventos GUI.


window_title ()

Establece el texto que mostrará la ventana en la barra de título.

void
window_title(Window *window,
             const char_t *text);
window

La ventana.

text

Cadena C UTF8 terminada en carácter nulo '\0'.


window_show ()

Muestra la ventana. Por defecto las ventanas se crean ocultas. Hay que mostrarlas explícitamente.

void
window_show(Window *window);
window

La ventana.


window_hide ()

Oculta la ventana.

void
window_hide(Window *window);
window

La ventana.


window_modal ()

Lanza una ventana en modo modal.

uint32_t
window_modal(Window *window,
             Window *parent);
window

La ventana.

parent

La ventana bloqueada.

Retorna

Valor retornado por window_stop_modal.

Observaciones

parent dejará de recibir eventos hasta que no se llame a window_stop_modal.


window_stop_modal ()

Termina el ciclo modal de una ventana.

void
window_stop_modal(Window *window,
                  const uint32_t return_value);
window

La ventana lanzada previamente con window_modal.

return_value

Valor que deberá devolver window_modal.


window_hotkey ()

Establece una acción asociada a la pulsación de una tecla.

void
window_hotkey(Window *window,
              const vkey_t key,
              const uint32_t modifiers);
window

La ventana.

key

La tecla.

modifiers

Modificadores. 0 o combinación de mkey_t.

Observaciones

Ver Atajos de teclado.


window_cycle_tabstop ()

Activa o desactiva el comportamiento cíclico de los tabstops.

void
window_cycle_tabstop(Window *window,
                     const bool_t cycle);
window

La ventana.

cycle

TRUE para activar los ciclos en tabstops (por defecto).

Observaciones

Ver Tabstops.


window_next_tabstop ()

Mueve el foco del teclado al siguiente control en la tab-list. Produce el mismo efecto que pulsar [TAB].

gui_focus_t
window_next_tabstop(Window *window);
window

La ventana.

Retorna

Resultado.


window_previous_tabstop ()

Mueve el foco del teclado al anterior control en la tab-list. Produce el mismo efecto que pulsar [SHIFT]+[TAB].

gui_focus_t
window_previous_tabstop(Window *window);
window

La ventana.

Retorna

Resultado.


window_focus ()

Establece el foco del teclado en un control concreto.

gui_focus_t
window_focus(Window *window,
             GuiControl *control);
window

La ventana.

control

El control que recibirá el foco.

Retorna

Resultado.


window_get_focus ()

Obtiene el control que posee el foco del teclado.

GuiControl
window_get_focus(Window *window);
window

La ventana.

Retorna

El control.


window_update ()

Recalcula la posición y tamaño de los controles tras modificar cualquier Layout.

void
window_update(Window *window);
window

La ventana.


window_origin ()

Mueve la ventana a unas coordenadas concretas del escritorio.

void
window_origin(Window *window,
              const V2Df origin);
window

La ventana.

origin

Posición (x,y) de la esquina superior-izquierda de la ventana.


window_size ()

Establece el tamaño del área cliente de la ventana.

void
window_size(Window *window,
            const S2Df size);
window

La ventana.

size

Tamaño del panel principal.

Observaciones

El tamaño final dependerá de la configuración del marco de la ventana y del tema de escritorio. Esta medida solo hace referencia al área interior.


window_get_origin ()

Obtiene la posición de la ventana.

V2Df
window_get_origin(const Window *window);
window

La ventana.

Retorna

Posición (x,y) de la esquina superior-izquierda de la ventana.


window_get_size ()

Obtiene las dimensiones totales de la ventana.

S2Df
window_get_size(const Window *window);
window

La ventana.

Retorna

Tamaño de la ventana.

Observaciones

Se tiene en cuenta el marco y barra de título.


window_get_client_size ()

Obtiene las dimensiones del área cliente de la ventana.

S2Df
window_get_client_size(const Window *window);
window

La ventana.

Retorna

Tamaño del panel principal.


window_defbutton ()

Establece el botón por defecto de la ventana. Será activado cuando se pulse [Intro].

void
window_defbutton(Window *window,
                 Button *button);
window

La ventana.

button

El botón.

Observaciones

Ver Botón por defecto.


window_cursor ()

Cambia el cursor del ratón.

void
window_cursor(Window *window,
              const gui_cursor_t cursor,
              const Image *image,
              const real32_t hot_x,
              const real32_t hot_y);
window

La ventana.

cursor

Identificador del nuevo cursor.

image

Imagen personalizada. Solo válido en ekGUI_CURSOR_USER.

hot_x

Coordenada x del punto de clic. Solo válido en ekGUI_CURSOR_USER.

hot_y

Coordenada y del punto de clic. Solo válido en ekGUI_CURSOR_USER.

Observaciones

hot_x, hot_y indican el punto "sensible" dentro de la imagen, que indicará la posición exacta del ratón.

❮ Anterior
Siguiente ❯