Zunächst muss man unterscheiden ob die Aktion im normalen Thread läuft oder einen eigenen hat.
Ein eigener Thread muss man per Signal oder Event zum Abbruch bringen ... das führt jetzt zu weit.
Wenn alles in einem Thread abläuft und GUI=YES ist, hast du hier ein Problem mit der Eventverarbeitung.
Unter Clipper und XBase ohne GUI würde man einfach ein INKEY(1) integrieren und diese Taste abfragen ...
mit GUI geht das so direkt nicht (es sind zu viele Events).
Zuerst die Eventloop erreichbar machen:
in Main wurde die Schleife durch eine Funktion ersetzt:
Code: Alles auswählen
in main:
...
// Das Programm wird in AppQuit() abgebrochen
DoEventLoop() // Aufruf ohne Endeparameter !
...
Funktion:
*-----------------------------------------------------------------------------
FUNCTION DoEventLoop(nSeconds) // For Next Schleifen unterbrechen und Events verarbeiten !
local nBisSeconds, nEvent, mp1, mp2, oXbp
DEFAULT nSeconds to 0 // Standard ist endlose Ausfhrung
nBisSeconds := seconds() + nSeconds
DO WHILE .T.
nEvent := AppEvent( @mp1, @mp2, @oXbp, nSeconds)
do case
case nEvent = xbe_None
* nichts tun ist hier Standard
case nEvent = xbeP_Keyboard .and. mp1 == xbeK_F1
* xbeP_HelpRequest erscheinen fr jede Xbp Instanz, also zu oft !
MsgBox("Die Hilfe ist fr dieses Programm noch nicht erstellt.")
otherwise
oXbp:handleEvent( nEvent, mp1, mp2 )
endcase
if nSeconds > 0 .and. nBisSeconds < seconds() // nur wenn keine endlose Ausfhrung
exit
endif
ENDDO
return nil
In beiden Fällen muss man dafür sorgen, dass Events auch in Endlosschleifen verarbeitet werden.
Man braucht eine FLAG (Funktion, Variable, Object ...)
Code: Alles auswählen
IsAbbruch(.f.) // wir merken uns kein Abbruch
do while .not. oTable:EOF
...
DoEventLoop(0.01) // 1/100 Sekunde die Oberfläche bedienen !
* if LastAppEvent() ???? in 0.01 Sekunden werden hunderte Events verarbeitet ...
* ich glaube nicht dass diese hier Sinn machen würde.
* In der Eventloop könnte man eine generelle Abbruchsituation
* vorsehen, aber diese ist auf das Fenster begrenzt.
if IsAbbruch()
exit
endif
oTable:skip(1)
enddo
function IsAbbruch(lCancel)
local IsToStop := .f.
if lCancel # NIL
IsToStop := lCancel
endif
return IsToStop
So jetzt müssen wir eine Möglichkeit einbauen den Zustand der FLAG zu ändern:
Pushbutton:
oPB_BrichsEinfachAb:activate := {|| IsAbbruch(.t.) }
oder Keyboard:
oDLG:keyboard := {|nKeyCode, uNil, oXbp| iif(nKeyCode=MeinKillerCode, IsAbbruch(.t.) , nil) }
so müsste es gehen. In der Abbruchfunktion sollte eventuell noch eine Sicherheitsabfrage enthalten sein
und du mußt natürlich sicherstellen, dass ein Abbruch ohne böse Folgen bleibt
Befehle wie COPY TO etc. können so natürlich nicht abgebrochen werden ...