there is a error in your design of the handling of dc_guitypeahead(). I worked several days on a problem, my customers complained about.
I try to explain in my poor english...
My Situation: My software opens new windows very often. Some of my customers write very fast, so i use dc_guitypeahead(). My Customers complain about missing characters or that characters are not in the correct order.
Example: User writes to a dcget, press Enter, a new window opens with a new dcget and he enter 1234. But the new get shows sometimes 234 or 2134 or 124
I looked for your mechanism for dc_guitypeahead() and found the reason (at least a part of it). You work like this (in :readgui()):
1. adding keyboard-events to :keyboardQueue
2. in your :eventloop() you use postappevent to fire these events back to the xbase eventqueue
Here we have two problems:
a. in the period between 1. and 2. there can be new keyboard events from the user
b. if there are more events in :keyboardQueue there can be new keyboard events from the user "between" firing the events
So it comes sometimes to a wrong order of keyboard events.
I found a way to correct this (in :eventloop(), base is express build 252:
was:
Code: Select all
IF snEventSpy > 0
nEvent := DllCall( snEventSpy, DLL_XPPCALL, 'SpyAppEvent', ;
@mp1, @mp2, @oXbp, IIF( Empty(nTimeOut), 0, 10 ) )
ELSE
nEvent := AppEvent( @mp1, @mp2, @oXbp, ;
IIF( Empty(nTimeOut), IIF(Empty(::keyboardQueue),nWait,1), Min(nWait,10) ) )
ENDIF
IF nEvent = 0 ...
Code: Select all
IF snEventSpy > 0
nEvent := DllCall( snEventSpy, DLL_XPPCALL, 'SpyAppEvent', ;
@mp1, @mp2, @oXbp, IIF( Empty(nTimeOut), 0, 10 ) )
ELSE
nEvent := AppEvent( @mp1, @mp2, @oXbp, ;
IIF( Empty(nTimeOut), IIF(Empty(::keyboardQueue),nWait,1), Min(nWait,10) ) )
ENDIF
// if there are Keyboard-Events in :keyboardQueue (dc_readguitypeahead()), "new" Keyboard-Events have to add to the :keyboardQueue...
if nEvent == xbeP_Keyboard .and. !empty(::keyboardQueue)
aadd(::keyboardQueue, mp1)
loop
endif
IF nEvent = 0 ...
and i don't use postappevent "for firing the :keyboardQueue:
was:
Code: Select all
IF nEvent = 0 .OR. (nEvent = xbeM_Motion .AND. mp1 == NIL) .OR. Valtype(oXbp) # 'O'
IF IsFunction('xbpHandleOcxEvents')
&('xbpHandleOcxEvents()')
ENDIF
IF lExitWhenQueueEmpty
RETURN .T.
ELSEIF nWait == 0
IF !Empty(::keyboardQueue)
PostAppEvent( xbeP_Keyboard, ::keyboardQueue[1],nil,SetAppFocus() )
ARemove(::keyboardQueue,1)
ENDIF
LOOP
ENDIF
ELSEIF Valtype(oGetList:loopWhenBlock) = 'B' .AND. !Eval(oGetList:loopWhenBlock)
LOOP
ELSE
nSeconds := Seconds()
ENDIF
Code: Select all
IF nEvent = 0 .OR. (nEvent = xbeM_Motion .AND. mp1 == NIL) .OR. Valtype(oXbp) # 'O'
IF IsFunction('xbpHandleOcxEvents')
&('xbpHandleOcxEvents()')
ENDIF
IF lExitWhenQueueEmpty
RETURN .T.
ELSEIF nWait == 0
IF !Empty(::keyboardQueue)
nEvent := xbeP_Keyboard
mp1 := ::keyboardQueue[1]
oXbp := setappfocus()
ARemove(::keyboardQueue,1)
ENDIF
ENDIF
ELSEIF Valtype(oGetList:loopWhenBlock) = 'B' .AND. !Eval(oGetList:loopWhenBlock)
LOOP
ELSE
nSeconds := Seconds()
ENDIF
With this changes, is much more better, but not perfect. Sometimes characters are still missing (but not more in wrong order) and i found no reason why.
Can you have a look to my changes and take them to the next release?
Perhaps you have an idea, why sometimes characters are missing?
This is a small test programm, which can show the problem:
Code: Select all
#include "dcdialog.ch"
#include "appevent.ch"
function Appsys()
return NIL
procedure main()
local getlist := {}, getoptions := {}, lRet, oButt
DC_ReadGuiTypeAhead(.t.)
@ 3, 3 dcpushbutton CAPTION "Test" SIZE 10, 2 OBJECT oButt ACTION {|| wDoSomething(), wTest(), setappfocus(oButt)}
DCGETOPTIONS TITLE "Test"
DCREAD GUI TO lRet OPTIONS getoptions ADDBUTTONS FIT eval {|| setappfocus(oButt)}
RETURN
function wTest()
local getlist := {}, getoptions := {}, cVar := space(20)
@ 5, 5 DCGET cVar
DCGETOPTIONS TITLE "Test"
DCREAD GUI TO lRet OPTIONS getoptions ADDBUTTONS FIT ENTEREXIT
return
function wDoSomething()
local atest := {}, i
for i := 1 to 1000
aadd(aTest, "0000")
next
return NIL