Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.14;
Скачать: CL | DM;

Вниз

Как нажатием на кнопку прервать программный цикл?   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.013 c
14-44861
Knight
2003-06-26 17:56
2003.07.14
Мыша...


7-44918
NoName
2003-05-01 20:36
2003.07.14
Как растянуть обои на рабочем столе?


7-44934
Ал
2003-04-22 15:56
2003.07.14
Работа с ActiveDesktop через CreateComObject


14-44814
int64
2003-06-29 19:03
2003.07.14
5 месяцев в цайтноте.


1-44691
ss300
2003-06-29 17:02
2003.07.14
Выбрать из ста 20 случайных неповторяющихся чисел