dcget keyblock
-
- Posts: 147
- Joined: Thu Jan 28, 2010 9:24 am
- Location: Nitra, Slovakia
- Contact:
dcget keyblock
Hi Roger,
is it possible add new additional parameter e.g. called KB_DELAY <nSeconds>, which will work with KEYBLOCK parameter, and associated <bKeyBlock> of current DCGET object will be performed only if delay between typing of characters are equal or more as <nSeconds>?
e.g. examaple:
nMyDelay := 0.25 // 0.5 or any other needed values
DCGET cName ;
KEYBLOCK { |a,b,o| My_Set_Scope_Or_Filter_Or_Something( a, b, o, oBrowse, @cName ) } ;
KB_DELAY nMyDelay
Problem is, when in database are more records and/or KEYBLOCK clause must do more actions(e.g. set filter/scope, check/find some other needed info/validations etc...), continuously refreshing of browse object is huge slowdown and sometimes in not needed immediatelly.
So I want(and I think this will appreciate more/most eXpress users) while end-user typing some characters into get, only when there is delay(default value will be 0, so like it is now - immediately) more then <nDelay>, keyblock clause will be done.
Or have someone else any other solution for this?
Many thanks
Zdeno
is it possible add new additional parameter e.g. called KB_DELAY <nSeconds>, which will work with KEYBLOCK parameter, and associated <bKeyBlock> of current DCGET object will be performed only if delay between typing of characters are equal or more as <nSeconds>?
e.g. examaple:
nMyDelay := 0.25 // 0.5 or any other needed values
DCGET cName ;
KEYBLOCK { |a,b,o| My_Set_Scope_Or_Filter_Or_Something( a, b, o, oBrowse, @cName ) } ;
KB_DELAY nMyDelay
Problem is, when in database are more records and/or KEYBLOCK clause must do more actions(e.g. set filter/scope, check/find some other needed info/validations etc...), continuously refreshing of browse object is huge slowdown and sometimes in not needed immediatelly.
So I want(and I think this will appreciate more/most eXpress users) while end-user typing some characters into get, only when there is delay(default value will be 0, so like it is now - immediately) more then <nDelay>, keyblock clause will be done.
Or have someone else any other solution for this?
Many thanks
Zdeno
Re: dcget keyblock
Zdeno -
I agree that this can be useful but it is not something that I would want to add to eXpress++. This can be done in your own code as shown below.
I suggest adding the function MyKeyDelay() to your library, then you can use it whenever you need it in your KEYBLOCK clauses.
Compile and run the below code. It will function as you requested.
Roger
I agree that this can be useful but it is not something that I would want to add to eXpress++. This can be done in your own code as shown below.
I suggest adding the function MyKeyDelay() to your library, then you can use it whenever you need it in your KEYBLOCK clauses.
Compile and run the below code. It will function as you requested.
Roger
Code: Select all
#INCLUDE "dcdialog.CH"
FUNCTION Main()
LOCAL GetList[0], cGet := Space(50), aDir := Directory(), oBrowse
@ 0,0 DCGET cGet KEYBLOCK {|n,x,oGet|MyKeyDelay(n,.3), MyKeyboard(n,oBrowse,oGet)}
@ 2,0 DCBROWSE oBrowse DATA aDir SIZE 60,10
DCBROWSECOL ELEMENT 1 HEADER 'File Name' WIDTH 50 PARENT oBrowse
DCREAD GUI FIT
RETURN nil
* ----------
FUNCTION MyKeyDelay( nKey, nDelay )
LOCAL nEvent, oXbp, mp1, mp2, nSeconds := Seconds()
DEFAULT nDelay := 0
IF nDelay > 0
DO WHILE Seconds() - nSeconds < nDelay .AND. nKey < 60000
nEvent := AppEvent(@mp1,@mp2,@oXbp,.1)
IF Valtype(oXbp) == 'O'
oXbp:handleEvent(nEvent,mp1,mp2)
ENDIF
ENDDO
ENDIF
RETURN nil
* -------------
STATIC FUNCTION MyKeyboard( nKey, oBrowse, oGet )
LOCAL cBuffer := Trim(oGet:get:buffer), nArrayElement
nArrayElement := AScan(oBrowse:dataSource,{|a|Upper(a[1])=Upper(cBuffer)})
IF nArrayElement > 0
oBrowse:arrayElement := nArrayElement
ENDIF
oBrowse:refreshAll()
RETURN nil
* -------------
PROC appsys ; return
The eXpress train is coming - and it has more cars.
-
- Posts: 147
- Joined: Thu Jan 28, 2010 9:24 am
- Location: Nitra, Slovakia
- Contact:
Re: dcget keyblock
Hi Roger,
many thanks for workaround, it works, but not exactly, how I thinked/want/need.
There is one little problem:
after wanted nDelay(in your sample 0.3) next MyKeyboard() action is performed N times,
where N is number of characters typed into get while MyKexDelay() waits for suspended typing into get.
You can simple simulate this in your sample,
just change 0.3 to e.g. 1.5 like parameter into MyKeyDelay(n,1.5)
and add in function MyKeyboard() line dcdebug nArrayElement after nArrayElement := AScan(oBrowse:data ...
now start typing any file name from oBrowse list, minimal e.g. 4 or 5 file characters
as you can now see, code in MyKeyboard() is done 4 or 5 times(== number of entered chars), not only once
It looks like events in MyKeyboard() must be any proccessed, characters typed into get must be still continuously showing, and after nDelay only once keyblock's action must be done. Or may be I am wrong...
But I have no idea, how do it in your code.
Please, can you look at this?
Many thanks
Zdeno
many thanks for workaround, it works, but not exactly, how I thinked/want/need.
There is one little problem:
after wanted nDelay(in your sample 0.3) next MyKeyboard() action is performed N times,
where N is number of characters typed into get while MyKexDelay() waits for suspended typing into get.
You can simple simulate this in your sample,
just change 0.3 to e.g. 1.5 like parameter into MyKeyDelay(n,1.5)
and add in function MyKeyboard() line dcdebug nArrayElement after nArrayElement := AScan(oBrowse:data ...
now start typing any file name from oBrowse list, minimal e.g. 4 or 5 file characters
as you can now see, code in MyKeyboard() is done 4 or 5 times(== number of entered chars), not only once
It looks like events in MyKeyboard() must be any proccessed, characters typed into get must be still continuously showing, and after nDelay only once keyblock's action must be done. Or may be I am wrong...
But I have no idea, how do it in your code.
Please, can you look at this?
Many thanks
Zdeno
Re: dcget keyblock
Try this:
Code: Select all
#INCLUDE "dcdialog.CH"
FUNCTION Main()
LOCAL GetList[0], cGet := Space(50), aDir := Directory(), oBrowse
@ 0,0 DCGET cGet KEYBLOCK {|n,x,oGet|MyKeyDelay(n,.3,oGet,{|oGet|MyKeyboard(oBrowse,oGet)})}
@ 2,0 DCBROWSE oBrowse DATA aDir SIZE 60,10
DCBROWSECOL ELEMENT 1 HEADER 'File Name' WIDTH 50 PARENT oBrowse
DCREAD GUI FIT
RETURN nil
* ----------
FUNCTION MyKeyDelay( nKey, nDelay, oGet, bBlock )
LOCAL nEvent, oXbp, mp1, mp2, nSeconds := Seconds()
wtf nKey
DEFAULT nDelay := 0
IF nDelay > 0
DO WHILE Seconds() - nSeconds < nDelay .AND. nKey < 60000
nEvent := AppEvent(@mp1,@mp2,@oXbp,.1)
IF Valtype(oXbp) == 'O'
oXbp:handleEvent(nEvent,mp1,mp2)
ENDIF
ENDDO
ENDIF
Eval(bBlock,oGet)
RETURN nil
* -------------
STATIC FUNCTION MyKeyboard( oBrowse, oGet )
LOCAL cBuffer := Trim(oGet:get:buffer), nArrayElement
nArrayElement := AScan(oBrowse:dataSource,{|a|Upper(a[1])=Upper(cBuffer)})
IF nArrayElement > 0
oBrowse:arrayElement := nArrayElement
ENDIF
oBrowse:refreshAll()
RETURN nil
* -------------
PROC appsys ; return
The eXpress train is coming - and it has more cars.
-
- Posts: 147
- Joined: Thu Jan 28, 2010 9:24 am
- Location: Nitra, Slovakia
- Contact:
Re: dcget keyblock
Hi Roger,
unfortunately, with your updated code result is the same.
If you add debug line
dcdebug cBuffer, Len( cBuffer ), nArrayElement
in fnc. MyKeyboard(),
you will see, that this function is executed N times and not only once.
It looks like keyboard's action is only stopped for that time
(more better for tests will be value e.g. 1.5 then your 0.3),
but then it is evaluated N times for all entered characters at once.
Hmmm, may be there is something internal code in eXpress++
for KEYBOARD cluase, which overwrites this your new code.
I kindly ask you for any next idea - thanks
Zdeno
unfortunately, with your updated code result is the same.
If you add debug line
dcdebug cBuffer, Len( cBuffer ), nArrayElement
in fnc. MyKeyboard(),
you will see, that this function is executed N times and not only once.
It looks like keyboard's action is only stopped for that time
(more better for tests will be value e.g. 1.5 then your 0.3),
but then it is evaluated N times for all entered characters at once.
Hmmm, may be there is something internal code in eXpress++
for KEYBOARD cluase, which overwrites this your new code.
I kindly ask you for any next idea - thanks
Zdeno
Re: dcget keyblock
Are you sure you are compiling the code sample I gave you?
I do not get such a result as you.
I do not get such a result as you.
The eXpress train is coming - and it has more cars.
-
- Posts: 147
- Joined: Thu Jan 28, 2010 9:24 am
- Location: Nitra, Slovakia
- Contact:
Re: dcget keyblock
Hi Roger,
as you can see in attached video, function MyKeyboard() is evaluated N times(lenght of just entered text).
What do I wrong?
http://www.acesystem.sk/domain/programy/keyblock.zip
Zdeno
as you can see in attached video, function MyKeyboard() is evaluated N times(lenght of just entered text).
What do I wrong?
http://www.acesystem.sk/domain/programy/keyblock.zip
Zdeno
Re: dcget keyblock
Hi Zdeno,
It will be very difficult to implement this. I think it can't be added to the KEYBLOCK.
What in the following case: Enter 5 characters fast and stop typing.
You expect that the keyblock isn't avaluated, because you typed fast.
The moment you stop the typing, the KEYBLOCK isn't called anymore.
Result: nothing happened.
It will be very difficult to implement this. I think it can't be added to the KEYBLOCK.
What in the following case: Enter 5 characters fast and stop typing.
You expect that the keyblock isn't avaluated, because you typed fast.
The moment you stop the typing, the KEYBLOCK isn't called anymore.
Result: nothing happened.
-
- Posts: 147
- Joined: Thu Jan 28, 2010 9:24 am
- Location: Nitra, Slovakia
- Contact:
Re: dcget keyblock
Hi Roger,Zdeno Bielik wrote: as you can see in attached video, function MyKeyboard() is evaluated N times(lenght of just entered text).
What do I wrong?
http://www.acesystem.sk/domain/programy/keyblock.zip
if you will have a little free time, can you look at my video and sample?
Thanks
Zdeno
Re: dcget keyblock
Hello,
Assuming you want a delayed auto-seek.
Typing quicly 5 charachters, and then if no charcacter is pressed for 0.5 seconds, or [Enter] is pressed, the seek comences.
In your keyblock, insert the code:
below the code for Sy_Timer():New()
I hope this works for you.
Regards,
Jack Duijf
Assuming you want a delayed auto-seek.
Typing quicly 5 charachters, and then if no charcacter is pressed for 0.5 seconds, or [Enter] is pressed, the seek comences.
In your keyblock, insert the code:
Code: Select all
Procedure _MyKeyblock(....)
LOCAL oTimer := Sy_Timer():New()
LOCAL nDelay := 0.5
LOCAL nEvent := 0
LOCAL mp1, mp2, oXbp
LOCAL cSeek := o:EditBuffer() // Content of current DCGET object
.......
oTimer:Mark(nDelay)
do while !oTimer:Timeout()
nEvent := NextAppEvent( @mp1, @mp2, @oXbp )
if nEvent <> xbe_None
nEvent := AppEvent( @mp1, @mp2, @oXbp )
if ValType(oXbp) = "O"
if nEvent = xbeP_Keyboard // a Key was hit
oTimer:Mark(nDelay) // Reset timeout
do case
case mp1 = 13
nKey := xbeK_ENTER
exit
case mp1 = xbeK_BS
if !Empty(oXbp:EditBuffer())
oXbp:HandleEvent(nEvent,mp1,mp2)
endif
case mp1 <> 10
oXbp:HandleEvent(nEvent,mp1,mp2)
endcase
else
oXbp:HandleEvent(nEvent,mp1,mp2)
endif
endif
endif
enddo
endif
cSeek := o:editbuffer()
lSoftSeek := Set(_SET_SOFTSEEK,.t.)
SEEK AllTrim(cSeek))
Set(_SET_SOFTSEEK,lSoftSeek)
endif
....
Code: Select all
/*
Timer class
By Jack Duijf
Date 17-09-2005
This simple timer class prodvides a simple mechanism determin timeouts on a max 24h basis
::Mark() sets the starting point.
::TimeOut() checks if timeout has occured
Procedure Sample
LOCAL oTimout := Sy_Timer():New()
oTimeOut:Mark(20) // 20 second timeout
Do while .T.
if oTimeOut:Timeout()
exit
endif
....
Enddo
Return
*/
CLASS Sy_Timer
HIDDEN:
VAR nStartTime
VAR nStopTime
VAR dStart
VAR lEnable
INLINE METHOD Now ; Return ((Date() - ::dStart) * 86400) + Seconds() // Current elapsed in seconds
EXPORTED:
METHOD Init
METHOD Mark // Mark timerout in seconds
METHOD TimeOut // Check timout elapsed
METHOD MarkTime // Mark timout in hh:mm:ss
METHOD EndTime // Date and time of timeout moment
INLINE METHOD Enable ; ::lEnable := TRUE ; Return // Enable Timer
INLINE METHOD Disable ; ::lEnable := FALSE ; Return // Disable Timer
VAR Cargo
ENDCLASS
METHOD Sy_Timer:Init()
::dStart := Date() // Date of instance create
::Mark() // Set marker
Return SELF
METHOD Sy_Timer:Mark(nTimeout) // Mark start-time
Default nTimeOut To 0
::nStartTime := ::Now() // Save current time
::nStopTime := ::nStartTime + nTimeOut // Calculate stop time
::Enable() // Enable Time-out
Return
METHOD Sy_Timer:TimeOut(nTimeOut)
LOCAL nNow := ::Now() // Capcure now in seconds
if ValType(nTimeOut) = "N" // Alternative timeout in seconds
Return (nNow >= (::nStartTime + nTimeOut)) // nTimeout passed marker ?
endif
Return ::lEnable .and. (nNow >= ::nStopTime)
METHOD Sy_Timer:EndTime() // Text persentation of timout moment
LOCAL cRet := ""
LOCAL nSecs := ::nStopTime // Current timeout in seconds
LOCAL nDays := 0
LOCAL nHours := 0
LOCAL nMins := 0
nDays := Int(nSecs /86400) ; nSecs -= (nDays * 86400)
nHours := Int(nSecs / 3600) ; nSecs -= (nHours * 3600)
nMins := Int(nSecs / 60) ; nSecs -= (nMins * 60)
if nDays > 0
cRet := Dtoc(::dStart + nDays) + " "
endif
cRet += StrZero(nHours,2) + ":"
cRet += StrZero(nMins,2)
if nSecs > 0
cRet += ":" + StrZero(nSecs,2)
endif
Return cRet
METHOD Sy_Timer:MarkTime(cTime,dDate)
//
// cTime = HH:MM:SS
// dDate = Date() (Optional)
//
LOCAL nSecs := 0
Default dDate To Date()
cTime := Padr(cTime,8,"0") // Add "0" if absent
nSecs := Val(Substr(cTime,1,2)) * 3600 // Hours
nSecs += Val(SubStr(cTime,4,2)) * 60 // Minutes
nSecs += Val(SubStr(cTime,7,2)) // Seconds
::nStopTime := ((dDate - ::dStart) * 86400) + nSecs // Stop-time
::Enable() // Enable Time-out
Return
Regards,
Jack Duijf
Regards,
Jack Duijf
Jack Duijf