Консультация № 98754
17.08.2007, 21:03
0.00 руб.
0 3 3
Уважаемые эксперты, здравия желаю!
Вопрос у меня к Вам появился. Мне надо в программе показывать несколько однотипных окон. Я создал главную форму Form и форму для показа информации FormInf. В опциях проекта форму FormInf перенес в список Available forms. Затем я в разделе implementation главной формы объявил переменную FormInfChild : TFormInf. Там, где надо появление окна пишу такой код:
===================
FormInfChild:=TFormInf.Create(Application);{}
. . .
{Здесь я задаю различные значения параметров компонентов окна}
. . .
FormInfChild.Show;
===================
Все отлично. Когда надо, может показывается сразу несколько окон. Проблема в том, что при закрытии окна память-то обратно не освобождается. Если создать одну форму таким образом и, не создавая другой, применить к созданной форме метод Free, то тогда все нормально. Однако если этот метод применить после создания нескольких форм, то в памяти освобождается лишь тот участок, который был занят под последнюю созданную форму. Вопрос: как в нужный мне момент (например, когда все созданные формы пользователь закрыл) освободить память от всех созданных форм?
Заранее благодарен.
Зимородкин Александр

Обсуждение

Неизвестный
17.08.2007, 21:30
общий
это ответ
Здравствуйте, Зимородкин Александр!
Все очень просто. Вы указатель на эту область памяти (выделенную для очередного дочернего окна) записываете всегда в переменную FormInfChild. Когда создаете очередную форму, то перезаписываете указатель новым значением, а старое у вас теряется безвозвратно. Сделайте у формы private-поле:
ChildForms: TList;
TList — это тоже объект и его надо создавать.
Впоследствии при создании очередного окна делайте вот такой вызов:
ChildForms.Add(TFormInf.Create(Application));
А если захотите очистить всю память, то используйте вот такой код:
for i := 0 to ChildForms.Count-1 do ChildForms[i].Free;
ChildForms.Clear; // Теперь память очищена и недействительные указатели надо удалить, чтобы случайно не сделать запрос по этой памяти.
Если захотите реализовать какую-то более сложную схему работы — почитайте как работать с TList, в т.ч. в справке.

Можно сделать и массивом. Главное, чтобы сохранять каждый объект (указатель) в отдельную переменную.
Неизвестный
17.08.2007, 22:52
общий
это ответ
Здравствуйте, Зимородкин Александр!

Суть вашего вопроса подводит к использованию дочерних окон – т.е. указать для дочерних окон, в свойстве FormStyle = fsMDIChild. Таким образом, вы будите работать по схеме «документ – представление», т.е. по аналогии с MS Word и т.д. – используя MDI интерфейс (множественный окна).
Тогда, вам будет легко управлять этими окнами, да и логике приложения они будут более соответствовать.

Второй способ, открывать обычные окна (для однотипных окон это неверно, но иногда приемлемо), как вы и делаете. Тогда, эти окна открываются ведь по событию.. например, выбор меню, кнопки и т.д. и каждое окно несёт свою функциональность. В этом случае, достаточно в обработчике дочерней формы OnClose присвоить параметру Action знасение caFree:
<code>
procedure TFormInf.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
</code>

А в главной форме можно запускать так:
<code>
implementation

uses Unit2;
var FormInfChild :TFormInf;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
FormInfChild := TFormInf.Create(self);
frm.Show;
end;
</code>
Неизвестный
20.08.2007, 10:53
общий
это ответ
Здравствуйте, Зимородкин Александр!
поместите в FormClose вашей формы (TFormInf) строку
Action:=caFree;
т.е. при закрытии этой формы будут освобождены ресурсы этой формы (только этого экземпляра формы)
Форма ответа