Actualmente estoy trabajando con Fivewin 11.06 y no me he podido cambiar a la versión 15.03 porque al usar el xbrowse pierde el foco cuando
utilizo en el valid y en la validación uso un dialogo para dar ciertas opciones, ya probe en 32 y 64 Bits y trabaja bien todo, solo lo del browse.
A continuación coloco un ejemplo completo que están en el foro y ejemplo en samples, pero funcional 100% para poder ver la perdida del foco en xbrowse
y se va para el primer campo del get, el problema es que al irse al primer get.
si puedo usar obrw:SetFocus(), pero el problema es que se va al primer get y este get puede tener un valid que haga ciertas cosas como volver a
a traer toda la información del browse.
La funcion es ValCuenta() y estoy validando el primer campo del BROWSE
- Code: Select all Expand view
#include "FiveWin.ch"
#include "InKey.ch"
#include "xbrowse.ch"
//----------------------------
Function Main()
LOCAL oDlg, oGet
LOCAL cCad := "Testing " // pad("Testing Gets",40)
LOCAL nNum := 0
LOCAL dDat := Date()
local oBrw, oCol, cAlias
local n:=0
local nTotal1:=0, nTotal2:=0
local aDbf := {}
aadd( aDbf, {"cta" , "C", 10, 00} )
aadd( aDbf, {"scta" , "C", 10, 00} )
aadd( aDbf, {"nombre" , "C", 40, 00} )
aadd( aDbf, {"debe" , "n", 12, 02} )
aadd( aDbf, {"haber" , "n", 12, 02} )
aadd( aDbf, {"concepto", "C", 40, 00} )
if !file( "DATOS.DBF" )
dbcreate( "datos.dbf", aDbf )
Endif
DbUseArea(.T.,,"Datos","Datos",.F.)
if lastrec() = 0
dbappend()
rlock()
field->cta := "6130380125"
field->scta := "3230"
field->nombre := "NOMBRE CUENTA"
dbunlock()
endif
cAlias:=Alias()
dbSelectArea(cAlias)
DEFINE DIALOG oDlg TITLE "TGet from " + FWDESCRIPTION size 600,400
@ 1, 2 SAY "Text..:" OF oDlg
@ 1, 6 GET oGet VAR cCad OF oDlg SIZE 60, 10 COLOR "W/G" PICTURE "@K"
@ 1.8, 2 SAY "Number:" OF oDlg
@ 2, 6 GET oGet VAR nNum OF oDlg SIZE 60, 10 PICTURE "9999999.99"
@ 2.6, 2 SAY "Date:" OF oDlg
@ 3, 6 GET oGet VAR dDat PICTURE "@E" OF oDlg SIZE 60, 10 // "@D"
oBrw := TXBrowse():New( oDlg )
oBrw:cAlias := cAlias
oBrw:nTop := 50
oBrw:nLeft := 10
oBrw:nBottom := 350
oBrw:nRight := 450
oBrw:nColDividerStyle := LINESTYLE_INSET
oBrw:nRowDividerStyle := LINESTYLE_INSET
oBrw:lColDividerComplete := .t. //completa pintado sobre el footer cuando lineas no llenan todo el browse
oBrw:nHeaderHeight := 30 //Altura cabeceras de col
oBrw:lFooter := .t. //Que tendrá footer
oBrw:nFooterLines := 1 //Lineas del footer
oBrw:nFooterHeight := 24 //Altura del Footer
oBrw:lRecordSelector := .t. //poner o no, COL de la flechita de la izq
oBrw:bClrHeader := {|| { nRGB(140, 0, 0), nRGB(229,0,0) } } // VERDECITO
oBrw:bClrFooter := oBrw:bClrHeader
oBrw:bClrStd := {|| { nRGB( 0, 0, 0), nRGB(255,248,220) } } // colores para lineas normales
oBrw:bClrSel := {|| { nRGB(255,255,255), nRGB(241,222,088) } } // para barra de linea selecc cuando el control no tiene el foco
oBrw:bClrSelFocus := {|| { nRGB( 0, 0, 0), nRGB(248,195, 34) } } // para barra de linea selecc cuando el control tiene el foco
oBrw:nMarqueeStyle := MARQSTYLE_HIGHLCELL //solo ilumina la celda actual
oBrw:nRowHeight := 20 //altura entre lineas
oBrw:lFastEdit := .t.
//Aqui uso DbPack() porque es una dbf pequeña y temporal. En grandes usar function de mantenimiento.
oCol = oBrw:AddCol()
oCol:bStrData = { || (cAlias)->cta }
oCol:cHeader = "CTA"
oCol:nEditType = EDIT_GET
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),) ,;
If( nKey == VK_RETURN, (cAlias)->Cta := xVal, ) ,;
If( nKey == VK_ESCAPE .and. Empty((cAlias)->Cta), ( (cAlias)->(dbDelete()),(cAlias)->(__dbPack()),(cAlias)->(dbGoBottom()),oBrw:Refresh() ), ) }
oCol:bEditValid := {|oGet,oBrwCol| ValCuenta(oDlg,oGet,oBrwCol,oCol) }
oCol:nWidth = 80
oCol = oBrw:AddCol()
oCol:bStrData = { || (cAlias)->Scta }
oCol:cHeader = "SC4"
oCol:nEditType = EDIT_GET
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),) ,;
If( nKey == VK_RETURN, if(lCtaOK(oBrw),(cAlias)->Scta := xVal, oBrw:GoLeftMost()),) }
oCol:nWidth = 80
oCol = oBrw:AddCol()
oCol:bStrData = { || (cAlias)->NOMBRE }
oCol:cHeader = "DESCRIPCION DE LA CUENTA"
oCol:cFooter = "BALANCE ---> "
oCol:nFootStrAlign := 1
oCol:nEditType = 0 //no editable
oCol:nWidth = 80
oCol = oBrw:AddCol()
oCol:bStrData = { || Transform((cAlias)->DEBE,"9,999,999,999.99") }
oCol:nDataStrAlign := 1 //alineado a la derecha
oCol:cHeader = "DEBITOS"
oCol:nEditType = EDIT_GET
oCol:lTotal := .t. //para totalizar cols a report y/o excel
oCol:bFooter = {|| TRANSFORM(nTotal1,"9,999,999,999.99") }
oCol:nFootStrAlign := 1
oCol:bEditWhen := {|| (cAlias)->Haber =0 }
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),),;
If( nKey == VK_RETURN,;
if(lCtaOK(oBrw),( nTotal1+=(Val(xVal)-(cAlias)->DEBE), oCol:RefreshFooter(), (cAlias)->DEBE := Val(xVal) ), oBrw:GoLeftMost()) ,) }
oCol:nWidth = 80
oCol = oBrw:AddCol()
oCol:bStrData = { || Transform((cAlias)->HABER,"9,999,999,999.99") }
oCol:nDataStrAlign := 1
oCol:cHeader = "CREDITOS"
oCol:nEditType = EDIT_GET
oCol:lTotal := .t. //para totalizar cols a report y/o excel
oCol:bFooter = {|| TRANSFORM(nTotal2,"9,999,999,999.99") }
oCol:nFootStrAlign := 1
oCol:bEditWhen := {|| (cAlias)->Debe =0 }
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),),;
If( nKey == VK_RETURN,;
if(lCtaOK(oBrw), ( nTotal2+=(Val(xVal)-(cAlias)->HABER), oCol:RefreshFooter(), (cAlias)->HABER := Val(xVal) ), oBrw:GoLeftMost()) ,) }
oCol:nWidth = 80
oCol = oBrw:AddCol()
oCol:bStrData = { || (cAlias)->CONCEPTO }
oCol:cHeader = "CONCEPTO"
oCol:nEditType = EDIT_GET
//Es la ultima columna, agrega nuevo registro en blanco y se va a primer columna,
//solo si la cta y/o valores están OK
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, DbAppend(),),;
If( nKey == VK_RETURN, (cAlias)->CONCEPTO := xVal ,) ,;
if( !lCtaOK(oBrw),(oBrw:GoLeftMost(), oBrw:Refresh()),;
if ( (cAlias)->(Recno())==(cAlias)->(Reccount()) .and. lDebHabOK((cAlias)->debe+(cAlias)->haber), (DbAppend(), oBrw:GoLeftMost(), oBrw:Refresh()),) ) }
oCol:nWidth = 100
oBrw:SetRDD()
oBrw:CreateFromCode()
oBrw:bKeyDown :={ | nKey | Teclas(nKey, oBrw, cAlias) }
oDlg:oClient := oBrw
ACTIVATE DIALOG oDlg CENTERED
RETURN NIL
//--------------------
Function ValCuenta(oDlg,oGet,oBrwCol,oCol)
Local oDlgV,nValue := 3
DEFINE DIALOG oDlgV TITLE "TGet from " + FWDESCRIPTION
@ 0, 2 RADIO oRad VAR nValue ;
ITEMS "&One", "&Two", "T&hree" _3D SIZE 150, 14 ;
HELPID 100, 101, 102 ;
ON CHANGE MsgBeep()
@ 3, 7 BUTTON "&Ok" OF oDlgV SIZE 30, 12 ACTION oDlgV:End()
@ 3, 16 BUTTON "&Cancel" SIZE 30, 12 OF oDlgV ACTION oDlgV:End() CANCEL
ACTIVATE DIALOG oDlgV CENTERED
return(.t.)
//
Function Teclas(nKey, oBrw, cAlias)
Do Case
Case nKey == VK_DELETE
if MsgNoYes("¿Está seguro(a) de borrar este registro?","Borrar registro de "+cAlias)
(cAlias)->(dbDelete())
(cAlias)->(dbPack())
oBrw:GoBottom()
oBrw:Refresh()
endif
EndCase
Return nil
//----------------//
Function lCtaOK(oBrw)
//tu codigo de validacion
(oBrw:cAlias)->nombre := "Nombre de la Cuenta, si existe..."
oBrw:Refresh()
Return .t.
//----------------------------//No permitir registro sin valores
Function lDebHabOK(nValor)
if nValor = 0
MsgStop("Omision de Valores","Alto")
return .f.
endif
Return .t.
//ESTAS FUNCIONES SON PARA COLORES PERSONALIZADOS DEL XBROWSE YA PUBLICADAS
//No son necesarias a menos que quieras emplear las classes modificadas.
//-------------------COLOR BUTTONBAR
Function ClrMsgBar()
Return {nRGB(255,228,150),nRGB(167,128,0)}
//-------------------COLOR HEARDERS DEL TXBROWSE
Function ClrHeader()
Return { nRGB(255,248,220), nRGB(157, 138,0) } //VERDECITO
//-------------------COLOR FOOTER DEL TXBROWSE
Function ClrFooter()
Return { nRGB(255,248,220), nRGB(157, 138,0) } //VERDECITO
//Funciones por cambio a Harbour
Function DbSkipper( x )
return __DbSkipper( x )
Function DbPack()
return __DbPack()
Function CurDrive( x )
return hb_CurDrive( x )
De antemano Gracias
Ing. Luis Duque