Вопрос № 98754: Уважаемые эксперты, здравия желаю!
Вопрос у меня к Вам появился. Мне надо в программе показывать несколько однотипных окон. Я создал главную форму Form и форму для показа информации FormInf. В опциях проекта форму FormInf перенес в список Availab...
Вопрос № 98.754
Уважаемые эксперты, здравия желаю!
Вопрос у меня к Вам появился. Мне надо в программе показывать несколько однотипных окон. Я создал главную форму Form и форму для показа информации FormInf. В опциях проекта форму FormInf перенес в список Available forms. Затем я в разделе implementation главной формы объявил переменную FormInfChild : TFormInf. Там, где надо появление окна пишу такой код:
===================
FormInfChild:=TFormInf.Create(Application);{}
. . .
{Здесь я задаю различные значения параметров компонентов окна}
. . .
FormInfChild.Show;
===================
Все отлично. Когда надо, может показывается сразу несколько окон. Проблема в том, что при закрытии окна память-то обратно не освобождается. Если создать одну форму таким образом и, не создавая другой, применить к созданной форме метод Free, то тогда все нормально. Однако если этот метод применить после создания нескольких форм, то в памяти освобождается лишь тот участок, который был занят под последнюю созданную форму. Вопрос: как в нужный мне момент (например, когда все созданные формы пользователь закрыл)
освободить память от всех созданных форм?
Заранее благодарен.
Зимородкин Александр
Отвечает: Сухомлин Кирилл Владимирович
Здравствуйте, Зимородкин Александр!
Все очень просто. Вы указатель на эту область памяти (выделенную для очередного дочернего окна) записываете всегда в переменную 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, 21:30 Оценка за ответ: 5 Комментарий оценки: Благодарю за ответ. То что надо. Правда немного его подправил. Во-первых, Delphi ругается на строку for i := 0 to ChildForms.Count-1 do ChildForms[i].Free; Я сделал так: for i := 0 to ChildForms.Count-1 do begin FormInfChild:=ChildForms[i]; FormInfChild.Free; end; Да и показ созданной формы типа ChildForms[i].Show тоже не идет.
Я сделал так: ChildForms.Add(TFormInf.Create(Application)); FrmInfChild:=ChildForms[ChildForms.count-1]; FrmInfChild.show; И все получилось. так что, пятерка Ваша.
Отвечает: Виктор Пырлик
Здравствуйте, Зимородкин Александр!
Суть вашего вопроса подводит к использованию дочерних окон – т.е. указать для дочерних окон, в свойстве Formstyle="fsMDIChild." Таким образом, вы будите работать по схеме «документ – представление», т.е. по аналогии с MS Word и т.д. – используя MDI интерфейс (множественный окна).
Тогда, вам будет легко управлять этими окнами, да и логике приложения они будут более соответствовать.
Второй способ, открывать обычные окна (для однотипных окон это неверно, но иногда приемлемо), как вы и делаете. Тогда, эти окна открываются ведь по событию.. например, выбор меню, кнопки и т.д. и каждое окно несёт свою функциональность. В этом случае, достаточно в обработчике дочерней формы OnClose присвоить параметру Action знасение caFree:
procedure TFormInf.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
А в главной форме можно запускать так:
implementation
uses Unit2;
var FormInfChild :TFormInf;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
FormInfChild := TFormInf.Create(self);
frm.Show;
end;
--------- Если ничего не помогло - надо читать инструкцию
Ответ отправил: Виктор Пырлик (статус: Студент)
Ответ отправлен: 17.08.2007, 22:52 Оценка за ответ: 5 Комментарий оценки: Нет, Виктор. Мое приложение не должно быть MDI. Формы обыкновенные, и появляются в определенное время. Правда закрывает их пользоватьель. Тем не менее, Ваш совет в процедуре TFormInf.FormClose(Sender: TObject; var Action: TCloseAction) присвоить Action значение caFree мне подходит. Поэтому пять стопроцентное.
Отвечает: Mishell
Здравствуйте, Зимородкин Александр!
поместите в FormClose вашей формы (TFormInf) строку
Action:=caFree;
т.е. при закрытии этой формы будут освобождены ресурсы этой формы (только этого экземпляра формы)
Ответ отправил: Mishell (статус: 5-ый класс)
Ответ отправлен: 20.08.2007, 10:53