![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как лучше закрыть несколко одинаковых форм? [D7, WinXP]
Дмитрий Белькевич © (2009-06-04 14:00:00)Есть некоторое количество одинаковых форм. Они могут быть на одном мониторе, либо на нескольких. Быть как MDI, так и SDI. При закрытии одной из них нужно по некоторому критерию (формы 'связаны' через специальный идентификатор) закрывать некоторые другие с таким же идентификатором.
Как такое лучше орагинизовать?
Дмитрий Белькевич (2009-07-28 16:04:00) [1]>Как-то очень не универсально. Для остальных 13 форма свои циклы и константы FM_CLOSExx?
Нет - у меня 14-тых форм может быть 4-5 штук, а то и больше. Остальных - по одной.
Kolan (2009-07-28 13:56:00) [2]Как-то очень не универсально. Для остальных 13 форма свои циклы и константы FM_CLOSExx?
Дмитрий Белькевич (2009-07-25 21:52:00) [3]Окончательно. В FormDestroy:
for i := 0 to Screen.FormCount - 1 do
if Screen.Forms[i] is TForm14 then
PostMessage(Screen.Forms[i].Handle, FM_CLOSE14, SeriesID, Handle);
Обработчик сообщения:
procedure TForm14.Form14Close(var Msg: TMessage);
begin
if Msg.WParam = SeriesID then
Close;
end;
Похоже, что работает... И само себя себя не успевает повторно вызывать - умирает раньше. Можно было бы дополнительно на совпедение передаваемого Hadle'а с Handle'ом Self'а проверять, но убрал - работает и без этого.
Kolan (2009-07-24 15:44:00) [4]KSergey, передайте автору, что я предлагаю использовать флаг. :)
При закрытии подобных надо ставить флаг в фолс, а при получении сообщения надо проверять стоит ли на него реагировать или нет.
Принципиальный код:
procedure CloseEventHandler;
begin
if ReactOnClose then
begin
ReactOnClose := False;
try
for ... do
Form[I].Close;
finally
ReactOnClose := True;
end;
end;
end;
KSergey (2009-07-24 14:28:00) [5]> Kolan © (23.07.09 16:40) [26]
> О закрытии надо уведомлять контроллер, который и должен закрывать все подобные.
Автор опасается, что "каждое подобное" при своём закрытии будет снова уведомлять контроллер о необзодимости "закрыть все подобные". Другое участинки предлагают как этого избехать или не бояться.
Kolan (2009-07-23 16:40:00) [6]О закрытии надо уведомлять контроллер, который и должен закрывать все подобные.
Юрий Зотов (2009-06-07 11:28:00) [7]Unit1:
type
TForm1 = class(TForm)
btnCreate1: TButton;
btnCreate2: TButton;
procedure btnCreate1Click(Sender: TObject);
procedure btnCreate2Click(Sender: TObject);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
end;
procedure TForm1.btnCreate1Click(Sender: TObject);
begin
TForm2.Create(Self, 1).Show
end;
procedure TForm1.btnCreate2Click(Sender: TObject);
begin
TForm2.Create(Self, 2).Show
end;
procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
var
i: integer;
begin
inherited;
if (Operation = opRemove) and not (csDestroying in ComponentState) and (AComponent is TForm2) then
for i := ComponentCount - 1 downto 0 do
if (Components[i] is TForm2) and not (csDestroying in Components[i].ComponentState)
and (Components[i].Tag = AComponent.Tag) then
TForm2(Components[i]).Close
end;
Unit2:
type
TForm2 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
public
constructor Create(AOwner: TComponent; ATag: integer); reintroduce; overload;
end;
constructor TForm2.Create(AOwner: TComponent; ATag: integer);
begin
inherited Create(AOwner);
Tag := ATag;
Caption := IntToStr(Tag)
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree
end;
Медвежонок Пятачок (2009-06-05 15:50:00) [8]остается только выйти из кода вызвавшего метод главной формы
MsGuns (2009-06-05 15:18:00) [9]Если же закрыытие всех однотипных форм нужно выполнять автоматически, то добавить глобальную переменную-флажок и его обработку:
- в процедуре закрытия в начале кода поднимать его, а в конце опускать
- в событиях OnClose дочек проверять его и если он поднят, то никаких действий не производить.
В результате вызов закрывающей процедуры будет выполнен только один раз - при обращении формы-инициатора, остальные закрываемые формы закроются мовчки ;)
MsGuns (2009-06-05 15:10:00) [10]В гл.форме процедура закрытия всех окон определенного типа. Дочь, инициирующая закрытие всех, просто обращается к этой процедуре, передавая ей нужный класс окна. Никаких сообщений от закрываемых таким образом форм не будет - все просто будут закрыты.
Игорь Шевченко (2009-06-05 12:24:00) [11]
> Имел в виду форму...
У форм вроде тоже нет. Очереди (сообщений) есть у потоков - одна очередь на все сообщения всем окнам потока
Дмитрий Белькевич (2009-06-05 12:07:00) [12]>У окон нет очередей
Имел в виду форму...
Юрий Зотов (2009-06-05 04:42:00) [13]> Игорь Шевченко © (04.06.09 18:18) [17]
А это смотря что понимать под словом "сообщение". Не обязательно интерпретировать его именно как сообщение Windows. Например, это может быть вызов какого-то метода (аналог Notification).
Медвежонок Пятачок (2009-06-04 18:22:00) [14]if LParam <> Handle then Release
Игорь Шевченко (2009-06-04 18:18:00) [15]
> if not (csDestroying inComponentState) then Release;
Я что-то не могу представить ситуацию, когда сообщение может быть получено при csDestroying in ComponentState
Юрий Зотов (2009-06-04 17:46:00) [16]1. Сообщение рассылать из деструктора.
2. При получении сообщения:
if not (csDestroying inComponentState) then Release;
Игорь Шевченко (2009-06-04 17:45:00) [17]Дмитрий Белькевич (04.06.09 16:27) [14]
> Очередь окна
У окон нет очередей
Дмитрий Белькевич (2009-06-04 16:27:00) [18]
> какая именно очередь ?
Очередь окна, которое только что разрушалось и послало всем остальным (но уже не самому себе) об этом сообщение.
Игорь Шевченко (2009-06-04 15:54:00) [19]
> Смысла, наверно, немного - всё равно очередь будет уже убита.
какая именно очередь ?
Дмитрий Белькевич (2009-06-04 15:44:00) [20]
> Если юзер успеет нажать в них кнопку "закрыть все такие"
> после того, как он нажал ее же в активной форме
OnDestroy у всех случается, вообще-то... Только что если, как Игорь советовал, Wm_SysCommand ловить.