![]() |
Delphi-Version: 2005
Schleifenabbruch durch Esc Taste...
Hallo,
in der CodeLib auf Delphi Praxis gibt es die Beschreibung eines Schleifenabbruchs per Tastaturdruck mit Messagedialog Abfrage: ![]()
Delphi-Quellcode:
Beim Tastendruck wird das Hochzählen der Variablen i sofort gestoppt, aber der Messagedialog in der Funktion EscPressed wird erst 7 - 12 Sekunden später angezeigt.
procedure TForm1.Button1Click(Sender: TObject);
var i : Integer; begin ResetEscPressed; for i := 0 to 10000000 do begin Caption := inttostr(i); if EscPressed('Schleife abbrechen ?') then Break; end; end; Kann man da irgendwie was machen, dass der Dialog nahezu zeitgleich angezeigt wird? |
AW: Schleifenabbruch durch Esc Taste...
Zitat:
Zitat:
Und nicht die ESC-Taste zu lange drücken. :warn: -> Wenn Taste gedrückt, dann zeige den Dialog an und frag nach, ob wirklich abgebrochen werden soll. |
AW: Schleifenabbruch durch Esc Taste...
Zitat:
Delphi-Quellcode:
Also ich drücke den Button, die Schleife wird ausgeführt und im Form1.Caption wird das Hochzählen der Schleife angezeigt. Wenn ich jetzt ESC drücke, hört das Hochzählen sofort auf, aber der 'Schleife abbrechen' Dialog wird erst nach weiteren ~7 Sekunden angezeigt. Merkwürdig... Liegt es an Windows 7 64bit?Unit1 procedure TForm1.Button1Click(Sender: TObject); var i : Integer; begin ResetEscPressed; for i := 0 to 10000000 do begin Caption := inttostr(i); if EscPressed('Schleife abbrechen ?') then break; end; end; ... ... ... unit Tastendruck; interface uses Windows, Dialogs, Controls; function EscPressed(const Msg:string):Boolean; procedure ResetEscPressed; implementation function EscPressed(const Msg:string):Boolean; begin // Aus der WinAPI-Doku zu GetAsyncKeyState: // if the function succeeds, the return value specifies whether the key was pressed // since the last call to GetAsyncKeyState, and whether the key is currently up or down. // If the most significant bit is set, the key is down, and if the least significant bit is set, // the key was pressed after the previous call to GetAsyncKeyState. // The return value is zero if a window in another thread or process currently has the keyboard focus Result := ((GetAsyncKeyState(VK_ESCAPE) and $8001) <> 0) or ((GetAsyncKeyState(VK_PAUSE) and $8001) <> 0); if Result then begin Result := (MessageDlg(Msg, mtConfirmation, [mbYes,mbNo], 0) = mrYes); end; end; // muss vor dem Benutzen von EscPressed() aufgerufen werden procedure ResetEscPressed; begin GetAsyncKeyState(VK_ESCAPE); GetAsyncKeyState(VK_PAUSE); end; Während der 7 Sekunden geht am Rechner nichts anderes mehr. |
AW: Schleifenabbruch durch Esc Taste...
Wenn man sowieso IMMER abbrechen will, kann man sich den Dialog sparen.
Delphi-Quellcode:
function EscPressed(const Msg:string):Boolean;
begin Result := ((GetAsyncKeyState(VK_ESCAPE) and $8001) <> 0) or ((GetAsyncKeyState(VK_PAUSE) and $8001) <> 0); if Result then Result := TRUE; end; |
AW: Schleifenabbruch durch Esc Taste...
Zitat:
|
AW: Schleifenabbruch durch Esc Taste...
Klingt so, als wenn im Hintergrund die Schleife noch laufen und das Formular blockieren würde. Entweder man ruft in der Schleife Application.ProcessMessages auf oder man lagert das alles in einen Thread au.
|
AW: Schleifenabbruch durch Esc Taste...
Zitat:
Delphi-Quellcode:
Application.ProcessMessages bringt keine Änderung.
procedure TForm1.Button1Click(Sender: TObject);
var i : Integer; begin ResetEscPressed; for i := 0 to 10000000 do begin Application.ProcessMessages; Caption := inttostr(i); if EscPressed('Schleife abbrechen ?') then break; end; //For Label1.Caption:= 'stop'; end; //proc Beim Klick auf ESC zeigt das Label sofort 'Stop' an, die Schleife wird also sofort verlassen. Es muss einen anderen Grund geben. Gibt es eine andere Möglichkeit als GetAsyncKeyState? |
AW: Schleifenabbruch durch Esc Taste...
Keine Ahnung, was bei dir los ist, aber bei mir funktioniert dein Code. Ich würde in jedem Fall in die Schleife ein Sleep einbauen, damit andere Threads und Prozesse Zeit bekommen und dein Thread nicht die CPU voll auslastet. Ein
Delphi-Quellcode:
reicht da schon aus. Warum überhaupt eine for-Schleife mit einem hohen Zahlenwert als Abbruchbedingung statt einer while- oder repeat-until-Schleife?
Sleep(1);
MfG Dalai |
AW: Schleifenabbruch durch Esc Taste...
Zitat:
das Sleep(1) sorgt tatsächlich dafür, dass ich nach dem Klick auf ESC das Formular schließen kann. Ich habe das Sleep einfach mal so eingefügt:
Delphi-Quellcode:
Was ich gern verstehen würde, warum das so funktioniert, denn:
procedure TForm1.Button1Click(Sender: TObject);
var i : Integer; begin ResetEscPressed; for i := 0 to 10000000 do begin Application.ProcessMessages; Caption := inttostr(i); Sleep(1); //<- Sleep in der Schleife if EscPressed('Schleife abbrechen ?') then break; end; //For Label1.Caption:= 'stop'; Application.ProcessMessages; Button1.Enabled:=false; end; //proc Denn auch ohne Sleep zeigt das Label1 sofort 'Stop' an,wenn ich ESC drücke, das heißt doch, dass die Schleife auch verlassen ist. Warum brauche ich jetzt das Sleep um das Form schließen zu können? Was passiert da noch im Hintergrund? Und ich wäre jetzt nicht darauf gekommen da ein Sleep einzubauen. Und warum nun eine 4Kern CPU von einer Form.exe total eingenommen wird, wenn da ein GetAsyncKeyState(VK_ESCAPE) in einer Schleife drin ist, verstehe ich ebenfalls nicht. |
AW: Schleifenabbruch durch Esc Taste...
Ganz einfach: das Sleep erlaubt, anderen Prozessen und Threads zu arbeiten. Ohne das Sleep geht die Schleife so schnell durch, wie es dein Prozessor erlaubt - und "blockiert" damit auch den Thread, der sich um die GUI kümmert. Übrigens wird nur ein Kern ausgelastet, nicht mehr - ist ja nur ein Thread und ein Thread kann gleichzeitig nur auf einem Kern laufen.
MfG Dalai |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz