Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-44651
Darrin
2003-07-02 11:41
2003.07.14
Зависание MDI приложения.


11-44620
yar
2002-11-07 14:40
2003.07.14
Перетаскивать форму за клиентскую часть в KOL ?


1-44738
MARcoDEN
2003-06-30 14:11
2003.07.14
Меню наподобие Пуска


14-44909
INTAARI
2003-06-27 12:33
2003.07.14
Где найти информацию по контрольной сумме 8-бит XOR?


1-44703
Demetrius2003
2003-07-01 01:06
2003.07.14
Invalid Floating operation ???





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский