![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Application.ProcessMessages, модальная форма и длительный цикл [D6, Win2k]
European © (2004-08-14 23:48:00)Здравствуйте, уважаемые! Есть 2 формы, одна из них модальная. После нажатия на кнопку на 2-ой форме начинает крутиться цикл. Внутри цикла стоит Application.ProcessMessages, обновление формы происходит, однако при закрытии обработка FormClose не происходит. Попытки закрыть форму штатными способами ни к чему не приводят. Что делать?
Пробовал сделать тот же самый цикл в 1-ой (не модальной) форме – всё ОК. Проблема в модальности или где? Что-то я торможу. Кстати, потоки для решения не предлагать.
QuasiLamo (2004-08-21 15:47:00) [1]
> European (15.08.04 14:45) [12]
А зачем нужна модальность? Если для того, чтобы юзер случайно не перешел к первой форме, то можно ее просто задизэйблить.
TeNY (2004-08-21 15:35:00) [2]а что такое поток?
European (2004-08-15 14:45:00) [3]Спасибо всем. Попробую сделать форму не модальной или перенесу код в поток.
Юрий Зотов (2004-08-15 14:42:00) [4]> European (15.08.04 12:38) [7]
> Подскажите, пожалуйста, как можно выйти из такой ситуации.
Все же лучший выход - это второй поток.
> А если форма будет не модальной?
Тогда ProcessMessages обработает WM_SYSCOMMAND и в FormClose выставится флаг прерывания цикла.
TeNY (2004-08-15 12:46:00) [5]ксати твой код использует
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
которая вообще редко работает как нужно лычше использовать event
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
TeNY (2004-08-15 12:42:00) [6]Я тоже встречался с подобной проблемой и при закрытии и при других обстоятельствах к примеру при вставка
Application.ProcessMessagesв функцию поиска если случайно нажать кнопку 2 раза то этот цикл будет выполнятся 2 раза на на кнопку закрыть не реагирует я решил это путем внедрения логической переменной
пример:
до
procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
begin
for i:=1 to maxint do
begin
Application.ProcessMessages;
Sleep(1);
end
end;
на закрытие не реагирует запускается сколько угодно раз
после
iRun:Boolean =False;
iExit:Boolean =False;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
begin
if not(iRun) then
begin
iRun:=True;
for i:=1 to maxint do
begin
if iExit then Exit;
Application.ProcessMessages;
Sleep(1);
end;
iRun:=false;
end else
MessageBoxA(Handle,'Уже запущено','<<<STOP>>>',0)
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
iExit:=true;
end;
а этот пример нормально реагирует на закрытие и остальное так же можно и останавливать процесс обработки.Правда постоянная проверка iExit может снижать производительность но на глаз и спомощью секундомера я этого не заметил :)
European (2004-08-15 12:40:00) [7]
> sniknik © (15.08.04 10:55) [6]
> кстати Repaint; лишний по моему.
Да, Repaint, действительно лишний
European (2004-08-15 12:38:00) [8]
> Юрий Зотов © (15.08.04 08:02) [5]
Спасибо, Юрий, я что-то подобное и предполагал. Подскажите, пожалуйста, как можно выйти из такой ситуации. А если форма будет не модальной?
sniknik (2004-08-15 10:55:00) [9]> Поэтому Application.ProcessMessages ничего не дает
ну чегото он всетаки делает, потому как если повесить это на кнопку оно всетаки срабатывает
вместо FormClose, это
procedure TForm2. Button2Click(Sender: TObject);
begin
bCloseForm:=true;
Close;
end;
неохота лезть в код, но похоже там цикл просто с ограниченным обработчиком сообщенией (Close в него просто не попал, дописать? как решение)
(Delphi 7! на других возможно отличия)
кстати Repaint; лишний по моему.
Юрий Зотов (2004-08-15 08:02:00) [10]> European
Если посмотреть код ShowModal, то увидим, что там крутится собственный цикл выборки сообщений. Поэтому Application.ProcessMessages ничего не дает, а цикл repeat-until в Button1Click не дает обрабатывать сообщения и модальной форме Form2 тоже. В итоге FormClose не отрабатывает и цикл получается бесконечным.
Andy BitOff (2004-08-15 02:04:00) [11]А мне лично интересно ПОЧЕМУ, а не как это реализовать. Почему представленный код не отрабатывает правильно. Вроде код верный, за исключением объявления переменных, но будем считать, что они глобальные, а в остальном... Сам не проверял, но интересно.
Где знатоки, пусть объяснят.
Андрей007 (2004-08-15 01:25:00) [12]А почему так принципиально делать цикл на второй форме, если на первой итак всё работает? Вы не ищете лёгких путей?
TUser (2004-08-15 01:17:00) [13]Испотзуй потоки. Весь расчет вынеси в отдельный поток.
European (2004-08-14 23:48:00) [14]Приведённый код отражает описанную выше проблему.
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2:=TForm2.Create(self);
Form2.ShowModal;
Form2.Free;
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
repeat
inc(i);
Label1.Caption:=IntToStr(i);
Repaint;
if i>100000 then i:=0;
Application.ProcessMessages;
until (bCloseForm)
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
bCloseForm:=true;
end;