Текущий архив: 2002.06.24;
Скачать: CL | DM;
Вниз
Как правильно создавать формы? Найти похожие ветки
← →
Korona © (2002-06-09 21:11) [0]В книге С.Тейксейра и К.Пачеко "Delphi 5. Руководство разработчика" написано: "Избегайте следующей ошибки при использовании немодальных форм:
begin
Form1 := TForm1.Create(Application);
Form1.Show;
end;
Подобное решение может вызвать бесполезный расход памяти, поскольку при каждом создании экземпляра формы перекрывается текущее значение указателя Form1. В результате неоднократного выполнения этого кода вы получите формы, несвязанные ни с какими переменными. Хотя доступ к каждому из созданных экзепляров форм может быть осуществлен с помощью списка Screen.Forms, рекомендуется избегать подобных решений. Передача же в конструктор Create() параметра nil приведет к тому, что даже такой метод доступа к потерянным формам будет невозможен".
Так как же правильно динамически создать несколько форм?
← →
Anatoly Podgoretsky © (2002-06-09 21:25) [1]Что то ты неправильно прочитал, но переменная в данном контексте не нужна, можно with TForm1.Create(Application) Show;
← →
Korona © (2002-06-10 00:23) [2]2Anatoly Podgoretsky:
Переписано из книги лежащей передо мной слово в слово.
← →
Korona © (2002-06-10 00:38) [3]Как можно динамически создавать формы, которые не уничтожались бы при закрытии главной формы приложения?
← →
Project1 © (2002-06-10 01:13) [4]При закрытии главной формы осуществляется выход из приложения...
← →
Walker © (2002-06-10 01:42) [5]to Korona ©
создавай список форм (TList)
← →
IronHawk © (2002-06-10 02:23) [6]А это не MDI приложение мы обсуждаем ????
← →
Anatoly Podgoretsky © (2002-06-10 09:27) [7]С учетом вопроса Korona © (10.06.02 00:38)
точно ты неправильно читаешь, для тебя это просто набор символов, но вернемся к вопросу от (10.06.02 00:38) при закрытии главной формы приложения, само приложение закрывается, а может и в этот раз у тебя вопрос не тот, котрый ты пытаешься задать?
← →
Andrey007 (2002-06-10 09:49) [8]2Korona:
Если заранее известно максимальное количество экземляров формы, то вместо var Form1: TForm1; следует писать var Form1: array[0..100] of TForm1;
Если же Вы хотите засовывать формы в TList, то, как написано в процитированной Вами книжке, список Screen.Forms и так есть.
← →
Игорь Шевченко © (2002-06-10 09:49) [9]Авторы имели в виду, что утечка произойдет в случае многократного выполнения этого кода, без проверки на то, что форма уже создана. IMHO.
← →
Korona © (2002-06-10 19:45) [10]2Anatoly Podgoretsky:
Я имел ввиду: "Как сделать чтобы при закрытии главной формы приложение не закрывалось". Не могу точно сформулировать вопрос.
Задача такая:
на форме есть кнопка, при нажатии на нее создается новая форма в которой также есть кнопка при нажатии на которую происходит создание формы и т.д.
Так вот, как сделать, чтобы приложение закрывалось когда пользователь закроет последнее окно.
Последнее - по количеству.
← →
YurijNT (2002-06-11 00:39) [11]Прячь главную форму на первой кнопке а далее создавай с главной формы все последующие по цепочке пока не дойдешь до последней, после чего закрой приложение или покажи главную форму.
← →
Anatoly Podgoretsky © (2002-06-11 01:20) [12]Игорь Шевченко © (10.06.02 09:49)
Я не согласен, здесь речь идет оь использовании переменной, для освобождения формыЮ да с таким кодом неизбежно, но к утечки имеет только косвенное отношение, есди освободать через переменную, а если же через список, то код нормальный и утечки не будет, правда зачем здесь вообзе нужна переменная сообразить не могу.
Form1 := TForm1.Create(Application);
Form1.Show;
и
with TForm1.Create(Application) do Show;
абсолютно равноценны и утечки не вызывают, сколько раз не повторя эту конструкцию.
Korona © (10.06.02 19:45)
Опять же через список Screen, как только будет закрыто последнее окно этого класса, закрывать главное окно.
← →
Korona © (2002-06-11 02:56) [13]2Anatoly Podgoretsky:
А если пользователь закроет сначала главное окно. Что делать? Прятать его? А как определить что пользователь закрывает именно главную форму. Ведь обработчик события onClose, определенный динамически, работает для всех экземпляров класса TForm1 - независимо главная это форма или нет.
Хотелось бы сделать так чтобы при нажатии на кнопу закрыть окно закрывалось, ресурсы и дескриптор окна освобождались.
← →
Song © (2002-06-11 08:45) [14]IF Sender is MainForm then ...
← →
Zemal © (2002-06-11 10:30) [15]Какая, всё-таки, чушь :))). Ну создай ты пустую главную форму, да и все дела... при создании формы спрячь её и покажи свою рабочую форму, которая будет создавать следующую (и не забывай разрушать формы при их закрытии методом Free) при закрытии проверяй сколько у тебя ещё форм не закрытых (создай глобальную переменную типа integer и при создании прибавляй по единичке, а при разрушении отнимай - inc(count) и dec(count))... и можешь таймер на главную форму поставить, который будет проверять if count = 0 then Application.Terminate; ...а лучше всего создать нить, которая будет ждать закрытия формы :), но это уже другой сабж :). Ой! Что я несу?! Эту проверку можно включить при закрытии формы: пусть проверяет if count = 0 then... и закрывает приложение, если нет больше форм, т.е. count = 0. Вот и все дела :))).
И ещё вариант. Напиши одну главную форму в приложении и пусть она по нажатию на кнопку запускает ещё один экземпляр приложения (функция WinExec или ShellExecute), а путь к приложению можно получить так: Application.ExeName ...помоему это самый оптимальный вариант для тебя, Kopona :).
Ещё один вариант, но он тебе не понравится... создавай свою форму от класса главной формы: Application.CreateForm(TfMyWin, fMyWin) - так же как и в файле проекта написано. По идее при закрытии последней должно закрыться и приложение... но это только по идее, а вообще надо проверить :) ...это только мои догадки :).
← →
Zemal © (2002-06-11 10:52) [16]Нееее... Korona, на последний вариант не обращай внимания... лажу гоню :)... ничего не выходит - у объекта Application должна быть главная форма и только одна :(, хотя мне это кажется и не правильным :(. Может кто знает как переназначить главную форму приложения???!!!
← →
KSergey © (2002-06-11 10:56) [17]Позвольте высказать свое мнение. Возникает впечатление, что автору надо все же разжевать проблему. Попробую сделать это в меру своего понимания. Надеюсь, что меня поправят, если где привру.
Начнем с того, что как бы ни обидно было утверждение от Anatoly Podgoretsky "Что то ты неправильно прочитал", оно все же, по моему мнению, соответвует истине.
Рассмотрим (оставя в стороне, возможно, нек. нюансы) о чем пытались сказать писатели упомянутой книги. Создается форма, пусть кодом
Form1 := TForm1.Create(Application);
Form1.Show;
После в Form1 содержится, понятно, указатель на созданную форму. Если мы захотим уничтожить эту форму - просто воспользуется Form1.Free или Form1.Release - на вкус, эта проблема обсуждалась. Но теперь мы по коду создания/отображения проходимся, например, 2 раза. Что получается: первый раз форма создается, указатель на нее присваевается переменной Form1; второй раз форма обратно создается, и переменной Form1 присваивается указатель на второй экземпляр! Т.е. ссылку на первый экземпляр формы мы просто потеряли, из за чего уничтожить ее программно уже не в силах (ну кроме метода перебора форм, конечно). Вот об этой "утечке" авторы и пытались сказать (по моему мнению).
Но:
а) при закрытии приложения все выделенные ему ресурсы все равно уничтожаются
б) если я верно понимаю, форм (на экране) создастся так же 2! При этом, если пользователь закроет ("крестиком") одну из форм, ресурсы, ею занимаемые, нормально освободятся, т.к. самой среде (как Windows, так и библиотеке VCL) эта самая ссылка в Form1 глубоко фиолетова и не используется.
Отсюда могу сделать такой комментарий: почитайте еще раз внимательно текст вокруг приведенного фрагмента (к стати, ссылка на издание и номер страницы не помешали бы), и вы поймете, что проблема не столько в данном фрагменте, сколько в контексте его использования.
Теперь вернемся к собственно задаче.
[Перечитал я вопросы и как-то энтузазизма, что именно вышенаписанное автору было не совсем понятно у меня поубавилось. Но стирать не буду - а вдруг все же...]
Какие методы решения я вижу. Как и писали многие - сделать главной формой приложения не Form1, а другую, но скрытую. К стати, в ней не забыть создать хоть один экземпляр Form1 (где-нибудь в OnCreate, наверное). А дальше, например, так: в этой главной скрытой форме (назовем ее MainForm) поставить два обработчика на события, назовем их UM_FORMCREATE и UM_CLOSEFORM, которые необходимо пересылать в FormMain от каждого "дочернего" окна Form1. Ну и завести счетчик в MainForm. При поступлении UM_FORMCREATE счетчик инкремировать, при каждом UM_CLOSEFORM счетчик декремировать и проверять: если <1 - закрыть главную форму (т.е. завершить приложение).
Правда поднапрягшись и перепахав dpr-файл проекта можно, наверное, обойтись и вовсе без скрытой формы, поставив обработчики на Application.OnMessage, но это только теоретчески, какие будут практические трудности и возможно ли это - однозначно сказать не берусь. Вроде так возможно, но вдруг вылезет какой-нибудь дикий проблем... Со скрытой формой это точно можно.
[К стати (я понимаю, что многие это знают). Для каждого приложения библиотека VCL уже и так создает скрытое окно. через которое прогоняет все сообщения и оно-то, на самом деле, и является основным дял приложения. Только его нкогда не видно (явно)]
← →
KSergey © (2002-06-11 10:59) [18]Да, долго я кропал свою писанину...
Zemal © (11.06.02 10:30) меня обогнал по времени поста. Ну да ладно ;)
← →
oomneeq © (2002-06-11 11:59) [19]begin
if not Assigned(Form1) then
Form1 := TForm1.Create(Application);
Form1.Show;
end;
Не оно ли?
← →
Vladimir_Shk © (2002-06-11 12:33) [20]2KSergey
Освобождение при нажатии на крестик произойдет, только в том случае, если в обработчике OnClose Action=caFree.
Кстати, а не проще ли отказаться от объекта TApplication и создавать формы вручную, если уж поставили себе такую задачу?
Создать объект TObjectList, вписывать в него все создающиеся формы, при достижении Object Count = 0 завершить процесс?
← →
Freezer © (2002-06-11 13:30) [21]procedure FindShowForm(FormClass: TFormClass);
var
I: Integer;
Found: Boolean;
begin
Found := False;
for I := 0 to Screen.FormCount - 1 do
if Screen.Forms[I].ClassType = FormClass then begin
Screen.Forms[I].BringToFront;
Found := True;
Break
end;
if not Found then
FormClass.Create(Application);
end;
← →
Korona © (2002-06-11 20:01) [22]2Vladimir_Shk:
Как это: "отказаться от TApplication и создавать формы вручную"
2Zemal:
WinExec и подобные не подходят, так как необходимо работать с компонентами создаваемой формы. Это наверно и возможно с помощью WinApi, но слишком уж много в WinApi функций. Легче ведь написать, например, NewForm.Edit1.Text := ..., чем делать то же самое с помощью WinApi: нужно handle Edit1 определить, послать сообщение и т.д. Вобщем для новичка в Delphi, кем являюсь я, написание такого приложения превратится в непрерывный поиск описания различных функций WinApi (так ведь еще нужно найти нужную!).
А главную форму приложения можно как то переопределить обходным путем. В форуме где то Игорь Шевченко на подобный вопрос отвечал.
Страницы: 1 вся ветка
Текущий архив: 2002.06.24;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.019 c