Saludos, mi necesidad es la siguiente, tengo un COMBOBOX vacio o dbconbo con GET, necesito que al entrar un valor en el GET y dar enter, vaya a una función, alli voy buscar un una tabla con un query where y LIKE los registros coincidentes con el valor entrado en el GET y lluego con los registros que hayan, crear un array y cambiar el array vacío o el que tenga. Por el.nuevo array, y esos sean los valores a desplegar para seleccionar en el combo box.. el valor lo estoy viendo solo si le doy al botón del COMBOBOX para desplegar y necesito sea con el enter en el GET como un valid pero del GET y no del combobox .no se si eso es posible... y recuerden debo reemplazar el array del combobox por un nuevo array y liuego esos sean los valores a mostrar para seleccionar del combobox.. gracias
Usar valor del Get en COMBOBOX para luego rellenar array
- joseluisysturiz
- Posts: 2069
- Joined: Fri Jan 06, 2006 9:28 pm
- Location: Guatire - Caracas - Venezuela
- Contact:
Usar valor del Get en COMBOBOX para luego rellenar array
Gracias a mi Dios ante todo!
- Antonio Linares
- Site Admin
- Posts: 44515
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
Estimado Jose Luis,
Prueba así:
Code: Select all | Expand
#include "FiveWin.ch"
function Main()
local oDlg, cBuscar := Space( 40 ), oCbx, aVacio := {}
USE clientes NEW SHARED // tu tabla
DEFINE DIALOG oDlg TITLE "Búsqueda" SIZE 320, 200
@ 1, 2 SAY "Buscar:" OF oDlg
@ 3, 2 COMBOBOX oCbx VAR cBuscar ITEMS aVacio ;
SIZE 200, 120 ;
STYLE CBS_DROPDOWN ; // <-- editable (con GET)
VALID BuscarYRecargar( oCbx, cBuscar ) // se dispara al dar ENTER
@ 3, 26 BTNBMP ... OF oDlg // otros controles
ACTIVATE DIALOG oDlg CENTER
return nil
function BuscarYRecargar( oCbx, cTexto )
local aItems := {}
cTexto := AllTrim( cTexto )
// ===== Aquí tu QUERY WHERE ... LIKE =====
// SQL (FWMaria/ADO/SQLite): SELECT nombre FROM clientes
// WHERE UPPER(nombre) LIKE '%" + Upper(cTexto) + "%'
//
// Equivalente con DBF (recorriendo y filtrando con AT):
IF ! Empty( cTexto )
clientes->( dbGoTop() )
WHILE ! clientes->( Eof() )
IF AT( Upper( cTexto ), Upper( clientes->nombre ) ) > 0
AAdd( aItems, clientes->nombre )
ENDIF
clientes->( dbSkip() )
END
ENDIF
// =========================================
// Reemplaza el array vacío / anterior por el nuevo:
oCbx:SetItems( aItems, .T. )
// (Opcional) Despliega la lista de inmediato para elegir:
// oCbx:Open()
return .T. // .T. para que el foco pueda salir del control
Si quieres que al dar Enter la lista se abra sola y el foco se quede en el GET (sin saltar al siguiente control), intercepta el Enter en el oGet y evitas la navegación por defecto:
// después de crear oCbx:
Code: Select all | Expand
local bDef := oCbx:oGet:bKeyChar
oCbx:oGet:bKeyChar := { | nKey | ;
If( nKey == 13, ; // VK_RETURN
( BuscarYRecargar( oCbx, cBuscar ), ; // tu búsqueda
oCbx:Set( cBuscar ), ; // deja el texto tecleado
oCbx:Open(), ; // abre el desplegable
0 ), ; // 0 = no navegar
Eval( bDef, nKey ) ) } // resto de teclas normalY en BuscarYRecargar haz oCbx:SetItems( aItems, .T. ) y ya no necesitas el VALID (o puedes dejarlo también; no molesta).
Si usas TDbCombo (dbcombo con GET)
El método equivalente es SetItems( aItems, aList, .T. ) (III params). Lo mismo: búscalo en VALID y reemplaza el array.
¿Quieres que te adapte el ejemplo a tu motor concreto (FWMaria/ADO/SQLite o DBF) o a TDbCombo?
- joseluisysturiz
- Posts: 2069
- Joined: Fri Jan 06, 2006 9:28 pm
- Location: Guatire - Caracas - Venezuela
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
Saludos mr Antonio. Voy a probar lo que envías y luego comento.. gracias
Gracias a mi Dios ante todo!
- joseluisysturiz
- Posts: 2069
- Joined: Fri Jan 06, 2006 9:28 pm
- Location: Guatire - Caracas - Venezuela
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
***********************Antonio Linares wrote: Sun Jul 12, 2026 9:17 amEstimado Jose Luis,
Prueba así:
Code: Select all | Expand
#include "FiveWin.ch" function Main() local oDlg, cBuscar := Space( 40 ), oCbx, aVacio := {} USE clientes NEW SHARED // tu tabla DEFINE DIALOG oDlg TITLE "Búsqueda" SIZE 320, 200 @ 1, 2 SAY "Buscar:" OF oDlg @ 3, 2 COMBOBOX oCbx VAR cBuscar ITEMS aVacio ; SIZE 200, 120 ; STYLE CBS_DROPDOWN ; // <-- editable (con GET) VALID BuscarYRecargar( oCbx, cBuscar ) // se dispara al dar ENTER @ 3, 26 BTNBMP ... OF oDlg // otros controles ACTIVATE DIALOG oDlg CENTER return nil function BuscarYRecargar( oCbx, cTexto ) local aItems := {} cTexto := AllTrim( cTexto ) // ===== Aquí tu QUERY WHERE ... LIKE ===== // SQL (FWMaria/ADO/SQLite): SELECT nombre FROM clientes // WHERE UPPER(nombre) LIKE '%" + Upper(cTexto) + "%' // // Equivalente con DBF (recorriendo y filtrando con AT): IF ! Empty( cTexto ) clientes->( dbGoTop() ) WHILE ! clientes->( Eof() ) IF AT( Upper( cTexto ), Upper( clientes->nombre ) ) > 0 AAdd( aItems, clientes->nombre ) ENDIF clientes->( dbSkip() ) END ENDIF // ========================================= // Reemplaza el array vacío / anterior por el nuevo: oCbx:SetItems( aItems, .T. ) // (Opcional) Despliega la lista de inmediato para elegir: // oCbx:Open() return .T. // .T. para que el foco pueda salir del controlSi quieres que al dar Enter la lista se abra sola y el foco se quede en el GET (sin saltar al siguiente control), intercepta el Enter en el oGet y evitas la navegación por defecto:
// después de crear oCbx:Code: Select all | Expand
local bDef := oCbx:oGet:bKeyChar oCbx:oGet:bKeyChar := { | nKey | ; If( nKey == 13, ; // VK_RETURN ( BuscarYRecargar( oCbx, cBuscar ), ; // tu búsqueda oCbx:Set( cBuscar ), ; // deja el texto tecleado oCbx:Open(), ; // abre el desplegable 0 ), ; // 0 = no navegar Eval( bDef, nKey ) ) } // resto de teclas normalY en BuscarYRecargar haz oCbx:SetItems( aItems, .T. ) y ya no necesitas el VALID (o puedes dejarlo también; no molesta).
Si usas TDbCombo (dbcombo con GET)
El método equivalente es SetItems( aItems, aList, .T. ) (III params). Lo mismo: búscalo en VALID y reemplaza el array.
¿Quieres que te adapte el ejemplo a tu motor concreto (FWMaria/ADO/SQLite o DBF) o a TDbCombo?
Antonio, uso es DBCOMMBO, fijate, el VALID se dispara al dar el ENTER, pero no lleva a la funcion, el valor entrado en el GET, pero si le doy al boton de despliegue del DBCOMBO, entonces se dispara el VALID y si lleva el valor entrado en el GET, necesito es que lo lleve al dar enter...estoy usando mysql.. gracias
REDEFINE DBCOMBO aGetLla[10] VAR aVarLla[10] ID 4004 OF oFldx:aDialogs[1] UPDATE ; // NOM.SEC.ORI
ITEMS aSecOri1 ;
LIST aSecOri2 ;
VALID ( nuevo_buscador( aVarLla[10], aGetLla[10] ) )
FUNCTION nuevo_buscador( cSecOriDes, oGetOriDes ) // NUEVO BUSCADOR DESDE DBCOMBO - 26/06/2026
? "nuevo_buscador: ", cSecOriDes
RETURN .t.
Gracias a mi Dios ante todo!
- Antonio Linares
- Site Admin
- Posts: 44515
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
Estimado Jose Luis,
El síntoma que describes tiene una causa concreta en la clase TDBCombo: el VALID se evalúa a través del LostFocus, y en TDBCombo la variable enlazada (bSetGet) se actualiza después de llamar al LostFocus del padre (que es donde se dispara el VALID).
Mira el método LostFocus de TDBCombo:
source/classes/dbcombo.prg
Code: Select all | Expand
[code]METHOD LostFocus( hWndGetFocus ) CLASS TDBCombo
local nAt := ::SendMsg( CB_GETCURSEL )
...
uRet := ::Super:LostFocus( hWndGetFocus ) // <-- aquí se evalúa el VALID
if !::lIndexVar
Eval( ::bSetGet, uVal ) // <-- la variable se actualiza DESPUÉS
endif
return uRet[/code]
``` [0-cite-0](#0-cite-0)
Cuando das ENTER, la navegación provoca el `LostFocus`, y el `VALID` corre **antes** de que `Eval( ::bSetGet, uVal )` haya volcado el texto tecleado a `aVarLla[10]`. Por eso tu primer parámetro `cSecOriDes` llega vacío/con el valor anterior. [0-cite-1](#0-cite-1)
En cambio, cuando pulsas el botón de despliegue y seleccionas, se dispara `Change()`, que sí hace `Eval( ::bSetGet, ... )` y `::oGet:VarPut( Eval( ::bSetGet ) )` **antes** de perder el foco, por eso ahí sí llega el valor correcto. [0-cite-2](#0-cite-2)
## Solución
No dependas de la variable enlazada dentro del `VALID`; lee el texto directamente del control. En tu `VALID` ya estás pasando el objeto del combo (`aGetLla[10]`), así que usa su método `GetText()` (que devuelve el texto real del edit del combo, como se ve en `ListGet`): [0-cite-3](#0-cite-3)
```harbour
[code]REDEFINE DBCOMBO aGetLla[10] VAR aVarLla[10] ID 4004 OF oFldx:aDialogs[1] UPDATE ;
ITEMS aSecOri1 ;
LIST aSecOri2 ;
VALID ( nuevo_buscador( aGetLla[10] ) )
FUNCTION nuevo_buscador( oGetOriDes )
LOCAL cTexto := AllTrim( oGetOriDes:GetText() ) // texto tecleado real
? "nuevo_buscador: ", cTexto
// ... aquí tu SELECT ... WHERE ... LIKE '%' + cTexto + '%' (MySQL)
RETURN .t.[/code]Así, tanto en ENTER como al desplegar, GetText() te devuelve lo que hay escrito en el GET del combo, sin depender del orden en que se actualiza aVarLla[10].
Si prefieres seguir usando la variable, otra opción es forzar el volcado antes de buscar dentro de la función: oGetOriDes:oGet:GetText() sobre el oGet interno del control da el mismo resultado.
- joseluisysturiz
- Posts: 2069
- Joined: Fri Jan 06, 2006 9:28 pm
- Location: Guatire - Caracas - Venezuela
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
Saludos, Antonio reviso. Pruebo ...y luego comento.. gracias
Gracias a mi Dios ante todo!
- joseluisysturiz
- Posts: 2069
- Joined: Fri Jan 06, 2006 9:28 pm
- Location: Guatire - Caracas - Venezuela
- Contact:
Re: Usar valor del Get en COMBOBOX para luego rellenar array
Antonio Linares wrote: Fri Jul 17, 2026 8:44 amEstimado Jose Luis,
El síntoma que describes tiene una causa concreta en la clase TDBCombo: el VALID se evalúa a través del LostFocus, y en TDBCombo la variable enlazada (bSetGet) se actualiza después de llamar al LostFocus del padre (que es donde se dispara el VALID).
Mira el método LostFocus de TDBCombo:
source/classes/dbcombo.prg
Code: Select all | Expand
[code]METHOD LostFocus( hWndGetFocus ) CLASS TDBCombo local nAt := ::SendMsg( CB_GETCURSEL ) ... uRet := ::Super:LostFocus( hWndGetFocus ) // <-- aquí se evalúa el VALID if !::lIndexVar Eval( ::bSetGet, uVal ) // <-- la variable se actualiza DESPUÉS endif return uRet[/code] ``` [0-cite-0](#0-cite-0) Cuando das ENTER, la navegación provoca el `LostFocus`, y el `VALID` corre **antes** de que `Eval( ::bSetGet, uVal )` haya volcado el texto tecleado a `aVarLla[10]`. Por eso tu primer parámetro `cSecOriDes` llega vacío/con el valor anterior. [0-cite-1](#0-cite-1) En cambio, cuando pulsas el botón de despliegue y seleccionas, se dispara `Change()`, que sí hace `Eval( ::bSetGet, ... )` y `::oGet:VarPut( Eval( ::bSetGet ) )` **antes** de perder el foco, por eso ahí sí llega el valor correcto. [0-cite-2](#0-cite-2) ## Solución No dependas de la variable enlazada dentro del `VALID`; lee el texto directamente del control. En tu `VALID` ya estás pasando el objeto del combo (`aGetLla[10]`), así que usa su método `GetText()` (que devuelve el texto real del edit del combo, como se ve en `ListGet`): [0-cite-3](#0-cite-3) ```harbour [code]REDEFINE DBCOMBO aGetLla[10] VAR aVarLla[10] ID 4004 OF oFldx:aDialogs[1] UPDATE ; ITEMS aSecOri1 ; LIST aSecOri2 ; VALID ( nuevo_buscador( aGetLla[10] ) ) FUNCTION nuevo_buscador( oGetOriDes ) LOCAL cTexto := AllTrim( oGetOriDes:GetText() ) // texto tecleado real ? "nuevo_buscador: ", cTexto // ... aquí tu SELECT ... WHERE ... LIKE '%' + cTexto + '%' (MySQL) RETURN .t.[/code]Así, tanto en ENTER como al desplegar, GetText() te devuelve lo que hay escrito en el GET del combo, sin depender del orden en que se actualiza aVarLla[10].
Si prefieres seguir usando la variable, otra opción es forzar el volcado antes de buscar dentro de la función: oGetOriDes:oGet:GetText() sobre el oGet interno del control da el mismo resultado.
Saludos Antonio, lamentablemente o no supe como hacerlo o no funciono lo que me sugeriste, ya que aunque haga AllTrim( oGetOriDes:GetText(), en la funcion donde envio el oGet que es buscador(), solo muestra el valor del GET cuando se dispara el VALID que es cuando le doy al boton de despliegue... voy seguir haciendo prueba, lo que no quiero es hacer otro GET ya que el mismo DBCOMBO trae y asi evito dos objetos, si no hay manera, tendre que hacerlo, pero espero alguna otra sugerencia a ver..gracias
Gracias a mi Dios ante todo!