Tutorial: Manejo de Eventos
Los eventos son la columna vertebral de las aplicaciones interactivas. Cada vez que un usuario hace clic en un boton, escribe una tecla, redimensiona una ventana o cierra un formulario, HarbourBuilder dispara un evento que su codigo puede manejar. Este tutorial cubre todos los tipos principales de eventos y las diferentes formas de responder a ellos.
Paso 1: Comprender los Eventos en HarbourBuilder
Cada control de HarbourBuilder expone un conjunto de propiedades de evento (ej. OnClick, OnChange). Asigna un bloque de codigo o una referencia a metodo a estas propiedades. Cuando el evento se dispara, HarbourBuilder ejecuta su manejador.
(clic, tecla, redimensionar)"] --> B["Mensaje del SO
WM_COMMAND etc."] B --> C["Despachador de Eventos
HarbourBuilder"] C --> D["Su Manejador
Bloque de Codigo / Metodo"] style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style B fill:#d2a8ff,stroke:#bc8cff,color:#0d1117 style C fill:#3fb950,stroke:#2ea043,color:#0d1117 style D fill:#f0883e,stroke:#d18616,color:#0d1117
Paso 2: Generar Manejadores de Eventos mediante el Inspector de Objetos
- Seleccione un control en el formulario (ej. un Boton).
- En el Inspector de Objetos, cambie a la pestania Eventos.
- Haga doble clic en el nombre del evento (ej.
OnClick). - El IDE automaticamente:
- Crea un esqueleto de
static functionen su archivo fuente. - Asigna el bloque de codigo para llamar a esa funcion.
- Lleva el cursor al cuerpo de la nueva funcion para que comience a codificar.
- Crea un esqueleto de
Hacer doble clic en un evento en el Inspector de Objetos es el flujo de trabajo recomendado. Genera manejadores con nombres adecuados (ej. OnBtnSaveClick) y conecta el bloque de codigo automaticamente.
Paso 3: OnClick — Clics en Botones y Controles
El evento mas comun. Se dispara cuando el usuario hace clic en un boton, etiqueta, imagen o cualquier control que acepte clics.
Bloque de codigo en linea (logica simple):
oBtn:OnClick := { || MsgInfo( "Se hizo clic en el boton!" ) }
Llamar a una funcion separada (logica compleja):
oBtn:OnClick := { || OnBtnSaveClick( oForm, oGet ) } static function OnBtnSaveClick( oForm, oGet ) local cValue := oGet:GetValue() if Empty( cValue ) MsgAlert( "Por favor ingrese un valor." ) return nil endif MsgInfo( "Guardado: " + cValue ) oForm:SetTitle( "Guardado!" ) return nil
Paso 4: OnChange — Cambios de Valor
Se dispara cada vez que cambia el valor de un control de entrada. Util para TextBox (TGet), ComboBox, CheckBox y controles Spinner.
oGetSearch:OnChange := { || OnSearchChange( oGetSearch, oListBox ) } static function OnSearchChange( oGet, oList ) local cFilter := oGet:GetValue() oList:Filter( { |cItem| Upper( cFilter ) $ Upper( cItem ) } ) return nil
Para controles TextBox, OnChange se dispara despues de cada caracter tecleado. Si esta realizando operaciones costosas (como consultas a base de datos), considere usar un TTimer para aplicar un retardo (debounce) a la entrada.
Paso 5: OnKeyDown — Entrada de Teclado
Se dispara cuando se presiona una tecla mientras el control tiene el foco. El manejador recibe el codigo de tecla y las banderas de modificador como parametros.
oGet:OnKeyDown := { |nKey, nFlags| OnGetKeyDown( nKey, nFlags, oGet ) } static function OnGetKeyDown( nKey, nFlags, oGet ) do case case nKey == VK_RETURN MsgInfo( "Enter presionado! Valor: " + oGet:GetValue() ) case nKey == VK_ESCAPE oGet:SetValue( "" ) case nKey == VK_F1 MsgInfo( "Ayuda: escriba un valor y presione Enter." ) endcase return nil
Constantes de teclas comunes: VK_RETURN, VK_ESCAPE, VK_TAB, VK_DELETE, VK_F1 hasta VK_F12, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT.
Paso 6: OnResize — Redimensionamiento de Formularios y Controles
Se dispara cuando el usuario redimensiona el formulario. Util para reposicionar o redimensionar controles dinamicamente para un diseno adaptable.
oForm:OnResize := { || OnFormResize( oForm, oMemo, oStatusBar ) } static function OnFormResize( oForm, oMemo, oStatusBar ) local nW := oForm:nWidth local nH := oForm:nHeight // Hacer que el memo llene el formulario con un margen de 10 pixeles oMemo:SetSize( nW - 20, nH - 80 ) // Mantener la barra de estado en la parte inferior oStatusBar:SetPos( nH - 30, 0 ) oStatusBar:SetSize( nW, 30 ) return nil
Paso 7: OnClose — Cierre del Formulario
Se dispara cuando el usuario intenta cerrar el formulario (haciendo clic en el boton X, presionando Alt+F4, o llamando a Close()). Devuelva .F. desde el manejador para prevenir que el formulario se cierre — util para avisos de cambios no guardados.
oForm:OnClose := { || OnFormClose( oForm ) } static function OnFormClose( oForm ) local nAnswer if lDataModified nAnswer := MsgYesNoCancel( "Guardar cambios antes de cerrar?" ) do case case nAnswer == 1 // Si SaveData() return .T. case nAnswer == 2 // No return .T. case nAnswer == 3 // Cancelar return .F. // Prevenir el cierre endcase endif return .T.
Este es un patron potente para formularios de entrada de datos. Siempre de al usuario una forma de forzar el cierre (ej. la opcion Cancelar) para que nunca quede atrapado en un formulario del que no pueda salir.
Resumen de Parametros de Eventos
| Evento | Parametros | Retorno | Controles |
|---|---|---|---|
OnClick |
(ninguno) | ignorado | Button, Label, Image, Panel |
OnChange |
(ninguno) | ignorado | TGet, ComboBox, CheckBox, Spinner |
OnKeyDown |
nKey, nFlags |
ignorado | Todos los controles con foco |
OnResize |
(ninguno) | ignorado | TForm |
OnClose |
(ninguno) | .T. permitir, .F. prevenir |
TForm |
Bloque de Codigo vs. Manejador de Metodo
HarbourBuilder soporta dos estilos para manejadores de eventos:
Bloque de codigo — ideal para logica corta en linea:
oBtn:OnClick := { || oLabel:SetValue( Time() ) }
Manejador de metodo — ideal para logica compleja que necesita su propia funcion:
oBtn:OnClick := { || OnBtnClick( oForm ) } static function OnBtnClick( oForm ) // Logica compleja aqui: llamadas a BD, validacion, etc. ... return nil
Si el manejador tiene mas de una expresion, use una funcion separada. Mantiene su definicion de formulario limpia y facilita la depuracion y prueba de la logica.
Ahora que comprende los eventos, continue al tutorial de CRUD de Base de Datos para construir una aplicacion basada en datos con SQLite.