By chance, I noticed a very strange behavior in xBrowse (ver. 10.06). Let me explain:
In MDI environment, I have a window oChild (of oWnd) containing a xBrowse to edit data.
This browser is conditioned to come to the end and beyond it (bPastEof), add a blank record ready for editing. If you do not enter any value and press enter, this state is evaluated and displays a dialog to choose the necessary data. (imagine that this dialog contains the catalog of products).
Well, if you use the directional keys on the items exceed xBrowse, everything works fine.
But ... if you use the arrow below the vertical scroll by surpassing add a blank record, and if it takes another click on the arrow and keep the mouse cursor over it, it triggers an event so overwhelming, opening the dialog, and this action does not stop until the mouse is placed on dialog, having to close each of them to continue. If this is not done immediately, it can consume all the resources of the cpu, and we know the results when this happens.
I coded a small example show here, in order to test the above. Use Clientes.dbf file found in the Samples folder.
- Code: Select all Expand view
- #include "FiveWin.ch"
#include "xbrowse.ch"
static oWnd
//----------------
Function Main()
SET DELETED ON
DEFINE WINDOW oWnd MDI TITLE "PRUEBA DE XBROWSE"
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON INIT Prueba()
return nil
//----------------------------//
Function Prueba()
local oChild, oBrw, oCol
local cAlias
local oBotSave,oBotCanc
DbUseArea(.t.,,"Clientes","Clientes",.F.)
cAlias:=Alias()
DEFINE WINDOW oChild MDICHILD OF oWnd TITLE "PRUEBA XBROWSE"
@34,700 BTNBMP oBotSave LEFT 2007 PROMPT "Guardar" SIZE 100,28 OF oChild ACTION msgInfo("Hola")
@oBotSave:nBottom+8,700 BTNBMP oBotCanc LEFT 2007 PROMPT "Cancelar" SIZE 100,28 OF oChild ACTION oWnd:End()
oBrw := TXBrowse():New( oChild )
oBrw:cAlias := cAlias
oBrw:nMarqueeStyle := MARQSTYLE_HIGHLCELL
oBrw:nColDividerStyle := LINESTYLE_INSET
oBrw:nRowDividerStyle := LINESTYLE_INSET
oBrw:lColDividerComplete := .t.
oBrw:lFooter := .t.
oBrw:lRecordSelector := .t.
oBrw:lFastEdit := .t.
oBrw:bPastEof = {|| if( lCCtaOK(oBrw), (Dbappend(), oBrw:GoLeftMost(), oBrw:Refresh(), oBrw:aCols[ 1 ]:Edit() ),) }
oCol = oBrw:AddCol()
oCol:bEditValue = { || (cAlias)->telefono }
oCol:cHeader := "TELEFONO"
oCol:nEditType = EDIT_GET
oCol:nWidth = 140
oCol:bGetChange = {| k, f, o, oCol | If( Len( RTrim( o:oGet:Buffer ) ) == Len( o:oGet:Buffer ),; //Daniel
( o:SendMsg( WM_KEYDOWN, VK_RETURN ) ), ) } //Daniel
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),) ,;
If( nKey == VK_RETURN, ((cAlias)->telefono := xVal,if(lCCtaOK(oBrw),oBrw:nColSel:=1,)) , ) ,;
If( nKey == VK_ESCAPE .and. Empty((cAlias)->telefono), ( (cAlias)->(dbDelete()),(cAlias)->(__dbPack()),(cAlias)->(dbGoBottom()),oBrw:Refresh() ), ) }
oCol = oBrw:AddCol()
oCol:bEditValue = { || (cAlias)->nombre }
oCol:cHeader := "NOMBRE"
oCol:nEditType = EDIT_GET
oCol:nWidth = 230
oCol:bGetChange = {| k, f, o, oCol | If( Len( RTrim( o:oGet:Buffer ) ) == Len( o:oGet:Buffer ),; //Daniel
( o:SendMsg( WM_KEYDOWN, VK_RETURN ) ), ) } //Daniel
oCol:bOnPostEdit = { | oCol, xVal, nKey | If( RecCount() == 0, ( DbAppend(), oBrw:Refresh() ),) ,;
If( nKey == VK_RETURN, ((cAlias)->nombre := xVal,if(lCCtaOK(oBrw),oBrw:nColSel:=1,)), ) }
oBrw:SetRDD()
oBrw:CreateFromCode()
oBrw:bKeyDown :={ | nKey | if(nKey == VK_DELETE, ( (oBrw:cAlias)->(dbdelete()), (oBrw:cAlias)->(dbpack()), oBrw:Refresh() ),) }
oChild:bGotFocus = { || dbselectarea( cAlias ) }
ACTIVATE WINDOW oChild MAXIMIZED;
ON INIT ( oBrw:nHeight := oChild:nHeight-163, oBrw:nWidth := oChild:nWidth-12, oBrw:nTop:=130 ) ;
VALID ( oBrw:CancelEdit(),(cAlias)->(dbCloseArea()), .T. )
RETURN NIL
//----------------//
Function lCCtaOK(oBrw)
local oDlg
local cCodigo:=(oBrw:cAlias)->telefono
if empty(cCodigo)
DEFINE DIALOG oDlg FROM 1,1 TO 30,60
ACTIVATE DIALOG oDlg CENTERED
return .f.
endif
Return .t.
Can you help me?
Sorry for my English.
Regards.
Francisco.