Форум: "Основная";
Текущий архив: 2003.07.14;
Скачать: [xml.tar.bz2];
ВнизКак нажатием на кнопку прервать программный цикл? Найти похожие ветки
← →
BillyJeans (2003-06-23 11:47) [0]Как нажатием на кнопку прервать программный цикл?
имею цикл:
Repeat
{процедуры...}
{а что вставить здесь, для опроса кнопки?}
until CheckStop;
и обработчик кнопки:
procedure TForm1.StopClick(Sender: TObject);
begin
CheckStop := True;
end;
← →
gek (2003-06-23 11:52) [1]
имею цикл:
Repeat
{процедуры...}
{а что вставить здесь, для опроса кнопки?}
if CheckStop then break
until false;
и обработчик кнопки:
procedure TForm1.StopClick(Sender: TObject);
begin
CheckStop := True;
end;
← →
Skier (2003-06-23 11:52) [2]Repeat
{процедуры...}
Application.ProcessMessages;
until CheckStop;
← →
Anatoly Podgoretsky (2003-06-23 11:57) [3]gek © (23.06.03 11:52)
Просил для опроса, а не замены until CheckStop на ненужный Break
← →
BillyJeans (2003-06-23 12:01) [4]
> Skier © (23.06.03 11:52)
Спасибо, получилось!
← →
gek (2003-06-23 12:12) [5]
> Anatoly Podgoretsky © (23.06.03 11:57)
Да, согласен. Не так понял. Поторопился
← →
Anatoly Podgoretsky (2003-06-23 12:20) [6]BillyJeans © (23.06.03 12:01)
И в других местах также не забывай обрабатывать сообщения, сам опрос Application.ProcessMessages времени не занимает, до нескольких миллионов в секунду, обработка сообщений другое дело, а у тебя могут быть и таймеры и многое другое, что требует реакции.
← →
BillyJeans (2003-06-25 08:51) [7]
> Anatoly Podgoretsky © (23.06.03 12:20)
Вот с этим я похоже и столкнулся... Имею кнопку, в обработчике нажатия на которой стоит Close. Так вот, нажать на нее теперь получается, а приложение не закрывается :( Подскажи, что необходимо добавить?
← →
Думкин (2003-06-25 09:01) [8]> BillyJeans © (25.06.03 08:51)
Тебе покажут тысячи приложений - где при нажатии на кнопку
> в обработчике нажатия на которой стоит Close. приложение закроется.
Значит - или приводи 17-ую строку или ищи ее сам.
← →
неРуль (2003-06-25 09:15) [9]может попробовать использовать TThread
← →
Nucl (2003-06-25 09:20) [10]внутри цикла делаешь проверку переменной
а по кнопке меняешь ее значение.
procedure onBtnClick;
begin
StopFor := true;
end;
for i:=1 to 100... do
begin
// это чтобы очередь сообщений разгребалась
Application.ProcessMessages;
// а это твой выход
if StopFor then Break
else
begin
.... вычисления
end;
end;
← →
mzu (2003-06-25 09:21) [11]пользовать отдельную нитку, проверяя свойство Terminated в цикле каждый раз.
При Close - устанавливать Terminated (Путём вызова Terminate) и ждать реакции от нитки.
← →
delphimun (2003-06-25 09:23) [12]У меня вроде работает:
procedure TForm1.ButtonClose1Click(Sender: TObject);
begin
checkstop:= true;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
i:integer;
begin
Repeat
i := i+1;
form1.Caption := inttostr(i);
Application.ProcessMessages;
until CheckStop;
close;
end;
← →
Ihor Osov'yak (2003-06-25 09:31) [13]2 BillyJeans © (25.06.03 08:51)
Здесь дело посложнее. Дело в том, что использование Application.ProcessMessages запускает цыкл виборки сообщений.
И вполне может быть (при определенной технике программирования), что некоторое сообщения будут обрабатыватся в этом цыкле выборки.. Который работает внутри нашего рабочего цыкла (см. BillyJeans © (23.06.03 11:47), который вызван с какой-то нашей процедуры.. Вот для такой ситуации вызов Close и игнорируется.. Сделано наверно это для того, чтобы пресесь попытку "убить самого себя", для обеспечения корректности которой нужно делать неслабые манипуляции со стеком. Конкретно разбираться с этим делом на уровне кода VCL руки не доходили, этот вывод сделан на основании логических рассуждений, и думаю, не далек от истины..
Если есть желание докопаться до истины - плиз, сырцы VCL..
Что же делать для Вашей сипуации? Примерно так:
flQuitWasPressed := false;
flLoopIsRunning := true;
try
Repeat
{процедуры...}
Application.ProcessMessages;
until CheckStop;
finally
flLoopIsRunning := false;
flQuitWasPressed := false;
if flQuitWasPressed then PostMessage(Self.Handle,WM_Close,0,0);
end
procedure TForm1.StopClick(Sender: TObject);
begin
CheckStop := True;
end;
procedure TForm1.QuitClick(Sender: TObject);
begin
CheckStop := True;
if not flLoopIsRunning then Close
else flQuitWasPressed := true;
end;
Зы - но, имхо, такой техники кодирования нужно избегать..
← →
delphimun (2003-06-25 09:48) [14]А можно еще и через отдельный поток. Как нибудь вот так:
Unit1:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,unit2, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
i:integer;
th:tabc;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
th.Terminate;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
th := tabc.Create(false);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
close;
end;
end.
Unit2:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,unit2, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
i:integer;
th:tabc;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
th.Terminate;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
th := tabc.Create(false);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
close;
end;
end.
← →
Edward (2003-06-25 10:44) [15]Нечего городить с нитями и таймерами, я бы сделал так:
var CheckStop: Boolean;
//Закрыть форму
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
//Запустить цикл
procedure TForm1.Button2Click(Sender: TObject);
var i: Integer;
begin
CheckStop := False;
Repeat
i := i + 1;
Form1.Caption := "Form1 - " + IntToStr(i);
Application.ProcessMessages;
until CheckStop;
CheckStop := True;
end;
//Прервать цикл
procedure TForm1.Button3Click(Sender: TObject);
begin
CheckStop := True;
end;
//Событие закрытия формы
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if CheckStop then Action := caFree else Action := caNone;
end;
← →
BillyJeans (2003-06-25 10:53) [16]
> Edward (25.06.03 10:44)
Action := caFree не отрабатывает, так же, как и Close :(
← →
Ihor Osov'yak (2003-06-25 11:50) [17]2 BillyJeans © (25.06.03 10:53)
Извини за настойчавость - см. Ihor Osov"yak © (25.06.03 09:31)
← →
NikB (2003-06-25 13:13) [18]To Ihor Osov"yak © (25.06.03 09:31)
A eto kak budet vigliadit, esli hochem srabotat "System menu\Close"?
← →
Adil Aliev (2003-06-26 00:35) [19]Мне кажется это не очень хороший метод.
Лучше использывать потоки ( TThread ).
← →
Ihor Osov'yak (2003-06-26 01:32) [20]2 NikB (25.06.03 13:13)
Один из вариантов:
procedure ControlWindow(Var Msg:TMessage); message WM_SYSCOMMAND;
...
procedure TForm1.ControlWindow(var Msg: TMessage);
begin
case Msg.WParam of
SC_Close:begin
CheckStop := True;
if not flLoopIsRunning then Close
else flQuitWasPressed := true;
end;
else inherited;
end;
end;
2 Adil Aliev (26.06.03 00:35)
Я же говорил, что такой техники нужно избегать.. Один из вариантов избегания - использовать рабочие потоки..
← →
BillyJeans (2003-06-26 09:20) [21]
> flQuitWasPressed := false;
> if flQuitWasPressed then PostMessage(Self.Handle,WM_Close,0,0);
Это как?
← →
BigDAN (2003-07-01 09:27) [22]По моему скромному мнению в этой ситуации оченно хорошо подходит компонент ApplicationsEvents и обработчик события onIdle. Надо только не забывать выставлять Done в False
procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
begin
Done:= false;
if NeedToCalculate then
// тело цикла
end;
// запускаем цикл
procedure TForm1.Button1Click(Sender: TObject);
begin
NeedToCalculate:= True;
end;
Потоки надо синхронизовывать , а такой подход обеспечивает нормальную обработку сообщений с одновременным выполнением тела цикла без геморроя. При длительных вычислениях всегда пользуюсь таким методом. Песня!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.07.14;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.009 c