Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Открытие новой формы и закрытие текущей.


Автор: Robus 4.2.2011, 06:45
Здравствуйте.

Столкнулся с проблемой запуска приложения на Windows-7 ... В программе есть две формы. Из первой формы вызывается вторая, при этом первая форма делается hide. Во второй форме по закрытию делался "form.close" или "HALT", который на ХР прекрасно всё закрывал, на Windows 7 в итоге получается "фаталл-еррор", и приложение остаётся висеть в задачах, при этом честно освобождаются все порты и закрываются все потоки. Каждая из форм отдельно друг от друга прекрасно работает и корректно закрывается. Так же прекрасно закрывается первая форма не загрузившая вторую.

Собственно вариант делать hide первой форме мне не нравился, поскольку не вижу смысла работе на заднем фоне формы к которой уже никогда не вернусь. Но попытки закрыть первую форму приводило к полному закрытию всех форм.

Как можно загрузить форму-2, и закрыть форму-1 ?

Язык - Delphi 7

Автор: Poseidon 4.2.2011, 09:35
Что-то мне подсказывает, что первая форма - главная.

Автор: chip_and_dayl 4.2.2011, 10:02
Тогда сделать вторую форму главной, а перед запуском главной формы уже второй формы грузить первую. Тогда можно спокойно закрывать то окно которое не нужно

Автор: Robus 4.2.2011, 12:38
Цитата(Poseidon @  4.2.2011,  09:35 Найти цитируемый пост)
Что-то мне подсказывает, что первая форма - главная.

Да - главная !

Цитата(chip_and_dayl @  4.2.2011,  10:02 Найти цитируемый пост)
Тогда сделать вторую форму главной, а перед запуском главной формы уже второй формы грузить первую.

Но мне вторая форма без первой не нужна ! В первой форме выбирается одно из 64 CAN устройств в под сети. Если запустить просто первую форму, то выберется первое из найденных устройств. Для этого и существует первая форма, что бы выбрать нужные конфигурации для второй формы.

Странно, я заметил, что в делфи часто люди выходят из положений выгрузки формы простым hide'ом, который просто не отображает содержимое оной. Этот способ оставляет зарезервированную память, тратит ресурсы процессора, да и вообще не красив. Почему такая сложность передать права главной формы другой форме ?

Единственный выход из положения, который я вижу, это создание третьей формы, которая будет главная, вечная, и которая будет решать какую форму нужно загружать или выгружать ?


Автор: Keeper89 4.2.2011, 12:49
Похоже на мастер, почему бы не сделать на одной форме?

Автор: Robus 4.2.2011, 13:11
Цитата(Keeper89 @  4.2.2011,  12:49 Найти цитируемый пост)
Похоже на мастер, почему бы не сделать на одной форме?

При создании (FormCreate) запускается два три потока. И так всё устроено, что форма не должна показаться пользователю до создания этих потоков. Иначе придётся наворачивать код всякими IF'ами, где они совсем не нужны. Допустим у меня есть в форме список устройство в одной из подсетей. Само появление формы гласит о том, что одно из устройств есть в подсети, и мне нужно постоянно его пере-запрашивать. Каждый пере-запрос или конфигурация на той стороне ведётся учётом. Вообщем программа начнёт обрастать лишним кодом лишь от того, что нельзя в нужный момент времени загрузить форму.
Да и не хочется затыкать код "костылями". Если язык программирования позволяет, а я думаю, что он позволяет выгрузить одну форму и загрузить вторую, то грех не научиться это делать.

Автор: Poseidon 4.2.2011, 14:22
Цитата(Robus @  4.2.2011,  12:38 Найти цитируемый пост)
Да - главная !
Ну тогда ты должен понимать, что закрытие (Close) этой формы будет означать завершение работы программы. Тебе именно это надо?


Автор: Robus 4.2.2011, 17:39
Цитата(Poseidon @  4.2.2011,  14:22 Найти цитируемый пост)
Ну тогда ты должен понимать, что закрытие (Close) этой формы будет означать завершение работы программы. Тебе именно это надо?


Мне нужно закрытие обеих форм действием к закрытию программы. Или эту же проблему решит вопрос - "как сделать главной другую форму" ?

Автор: Robus 4.2.2011, 18:44
Ура ... Ура !!! Уря ...

Проблему решил, поковыряв цикл делфи, там всего-то для главной формы созданный поинтер, где лежит адрес главной формы ... В цикле проверяется на nil. Итак делается это так ... Допустим, что Form1 это главная форма, а Form2 должна стать главной в зависимости от результата выполнения в Form1 ...

Код в Form1 пытающийся передать "главность" Form2:
Код

VAR G:POINTER;
BEGIN
  Application.CreateForm(TForm2, Form2);
  G:[email protected];
  Pointer(G^) := Form2;
  Form2.Show;
  Form1.Close();
END;


И всё честно ... Вторая форма становится активной, первая честно закрывается освобождая память !!!

Спасибо за помощь, кому приятно, не просто убирать видимость форме а честно её выгружать, - пользуйтесь на здоровье ! Может памяти у меня и гиг, но когда-то и 48к было то же океаном ...

Автор: V1Ray 31.5.2013, 14:09
Robus, спасибо, реально классная штука!!! Не зря провисела 2 года)))

Автор: superVad 31.5.2013, 18:44
V1Ray, я не уверен, что это корректный код. Т.к. Application.MainForm это не указатель, а свойство возвращающее указатель.
Буду рад если кто то объяснит, что там под капотом происходит при таких присваиваниях.

На самом деле - это все лишнее. Надо просто убрать из автосоздания форм - все формы. Тогда вообще не будет главной формы. И в файле проекта, вместо Application.Run запустить свою процедуру или объект (http://ins911.blogspot.com/2008/12/singletone-delphi.html) управляющие окнами. Ну и там же Application.Title что то присвоить.

Автор: V1Ray 8.6.2013, 23:24
superVad,http://www.cyberforum.ru/delphi-beginners/thread124078.html ссылка. Проще уже некуда smile 
Комментарий STRATEG-а. Там ссылка на толковый пример.

Автор: Illusion Dolphin 8.6.2013, 23:36
Поддержу superVad, это грязный хак. 
Можно просто сделать форму невидимую, она будет главной для приложения, но видна не будет, а остальные показывай-закрывай уже в любом порядке без проблем. 

Автор: northener 9.6.2013, 01:20
Цитата(V1Ray @  8.6.2013,  23:24 Найти цитируемый пост)
superVad,Вот ссылка. Проще уже некуда smile 
Комментарий STRATEG-а. Там ссылка на толковый пример.

Хм. А где в ответах STRATEG-а применялся этот "грязный фак" с подменой значения ссылки Application.MainForm?
Посмотрел несколько примеров STRATEG-а. Везде всё как предложил 
Цитата(Illusion Dolphin @  8.6.2013,  23:36 Найти цитируемый пост)
Можно просто сделать форму невидимую, она будет главной для приложения, но видна не будет, а остальные показывай-закрывай уже в любом порядке без проблем. 


P.S. 
Цитата

Можно просто сделать форму невидимую, она будет главной для приложения, но видна не будет

Возможно этот вариант не сочетается с не так давно появившемся (ИМХО в Д2005) свойством TApplication.MainFoirmOnTaskBar

Автор: bems 9.6.2013, 04:51
да, это хак. но с другой стороны можно понять людей которые это применяют. нехватает в vcl возможности сделать сабж без хаков, чо уж там

Автор: БелАмор 9.6.2013, 07:38
Цитата(bems @  9.6.2013,  05:51 Найти цитируемый пост)
но с другой стороны можно понять людей которые это применяют.

Не могу я понять таких людей. Это примерно как лезть в окно, вырезая решётку автогеном только из-за того, что дверь открывается не внутрь, а наружу. Человеку говоришь: "Ну потяни ты на себя дверь, и всё, никаких проблем..." А он гордо заявляет, что его задача решена, и посему такое решение его вполне устраивает, и добавляет: "Классная штука - автоген, что бы я без него делал? Спасибо тому парню, который мне его дал..."

Цитата(bems @  9.6.2013,  05:51 Найти цитируемый пост)
нехватает в vcl возможности сделать сабж без хаков, чо уж там 

В чем состоит проблема?
В том, что первая создаваемая форма в приложении назначается главной, а потом нельзя назначить главной формой другую?
Ну, так, Application.CreateForm как раз и предназначена для автоматического назначения главной формы. Т.е. человек сначала сам, своими собственными руками назначает главную форму, а потом думает, как бы её переназначить... Это какой-то мазохизм...
Если создавать форму через конструктор, например TPasswordForm.Create, то форма не назначается главной - создавай, отображай, закрывай, уничтожай хоть десяток, а первая созданная через Application.CreateForm будет назначена главной. И переназначать главную форму просто нет необходимости.

Автор: Illusion Dolphin 9.6.2013, 09:13
Цитата

Возможно этот вариант не сочетается с не так давно появившемся (ИМХО в Д2005) свойством TApplication.MainFoirmOnTaskBar

Это исправляется без проблем. 

Цитата

но с другой стороны можно понять людей которые это применяют.

Согласен, тут отнюдь не гибкое решение, которое не всегда приминимо, могли бы это уже и исправить. 

Цитата

Ну, так, Application.CreateForm как раз и предназначена для автоматического назначения главной формы. Т.е. человек сначала сам, своими собственными руками назначает главную форму, а потом думает, как бы её переназначить... Это какой-то мазохизм...

У меня в приложении нет главной формы smile Их много и выход происходит когда они все закрылись в любом порядке, тут приходится выкручиваться  smile 

Автор: bems 9.6.2013, 12:06
Цитата(БелАмор @  9.6.2013,  07:38 Найти цитируемый пост)
Классная штука - автоген, что бы я без него делал? Спасибо тому парню, который мне его дал...
это не автоген. скорее согнутая специальным образом заколка

Цитата(БелАмор @  9.6.2013,  07:38 Найти цитируемый пост)
В том, что первая создаваемая форма в приложении назначается главной, а потом нельзя назначить главной формой другую?

вторая половина

Цитата(БелАмор @  9.6.2013,  07:38 Найти цитируемый пост)
Ну, так, Application.CreateForm как раз и предназначена для автоматического назначения главной формы

да знают тут все для чего оно предназначено. но работает неудобно.

Автор: БелАмор 9.6.2013, 19:59
Цитата(Illusion Dolphin @  9.6.2013,  10:13 Найти цитируемый пост)
У меня в приложении нет главной формы  Их много и выход происходит когда они все закрылись в любом порядке, тут приходится выкручиваться  

Цитата(bems @  9.6.2013,  13:06 Найти цитируемый пост)
да знают тут все для чего оно предназначено.

Я ни в коем случае не отрицаю, что бывают какие-то специфические ситуации, но большинство вопросов по поводу переназначения главной формы связаны с заставками и запросами логинов/паролей, т.е. в большинстве случаев реальной необходимости переназначения нет. Однако, я практически не встречаю советов создавать форму через конструктор, чтобы она не назначалась главной.

Автор: Illusion Dolphin 9.6.2013, 21:27
Цитата

переназначения главной формы связаны с заставками и запросами логинов/паролей

Заставку хорошо бы делать на винапи (т.к. VCL не многопоточный) в отдельном потоке, чтобы не мешать загрузке приложения. Переназначение главной формы это всегда специфическая задача, и очень прескорбно, что до сих пор приходится людям писать костыли чтобы обойти "стандартное решение".

Автор: Poseidon 9.6.2013, 23:04
А по-моему, возникновение необходимости переназначить главную форму - это ошибка в архитектуре. В хорошо продуманных программах такой необходимости нет. Заставка? Она создается и уничтозается отдельно, пока главная форма грузится. Форма логинов? Так эту форму нужно показывать после загрузки главной. В голову вообще не приходят варианты, когда может понадобится переназначение главной формы и что бы это ну никак нельзя было обойти.

Автор: northener 10.6.2013, 01:24
Цитата(Poseidon @  9.6.2013,  23:04 Найти цитируемый пост)
Форма логинов? Так эту форму нужно показывать после загрузки главной. 

Вот с этим никак не согласен. Приложения требующие проверку учетной записи своего пользователя как правило довольно большие и их загрузка занимает довольно заметное время. Так зачем его тратить, если проверка даст отрицательный результат? Представте себе Winlogon, который проверяет учетную запись пользователя после полной загрузки ОС! Это конечно не полностью адекватный пример, но почти. Ведь трудно себе представить Дельфи-приложение, которое после "загрузки" главной формы ещё не готово выполнять все свои функции, если авторизация пройдет успешно.


Цитата(Illusion Dolphin @  9.6.2013,  21:27 Найти цитируемый пост)
Заставку хорошо бы делать на винапи (т.к. VCL не многопоточный) в отдельном потоке, чтобы не мешать загрузке приложения.

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1411 уже почти 4 года. (А может быть и больше).


Цитата(БелАмор @  9.6.2013,  19:59 Найти цитируемый пост)
Однако, я практически не встречаю советов создавать форму через конструктор, чтобы она не назначалась главной.

Ещё при царе горохе в демках в поставке Дельфи появился пример создания Splash Screen. В проекте MastApp.dpr
И советы посмотреть этот пример я встречал неоднократно. И сам советовал. Но воз и ныне там. Гугль и иже с ним возвращает только советы кульхацкеров уровня песочницы. :(
Хотя этот пример даже содержит хелп файл (правда на аглицком), в котором чёрным по белому написано:
The Splash screen appears when MASTAPP starts. MASTAPP.DPR calls TSplashForm.Create to create the splash screen and the instance of the application, calls SplashForm.Show to display the form while all other MASTAPP forms are created, and calls SplashForm.Update to display the application's "Loading ..." message on the form.
When all MASTAPP forms are created, MASTAPP.DPR calls SplashForm.Hide to hide the Splash screen display.

И никаких проблем с MainForm.

Автор: bems 10.6.2013, 08:39
Цитата(Poseidon @  9.6.2013,  23:04 Найти цитируемый пост)
В голову вообще не приходят варианты, когда может понадобится переназначение главной формы
ну это от узости кругозора

Автор: Poseidon 10.6.2013, 10:40
Цитата(northener @  10.6.2013,  01:24 Найти цитируемый пост)
Приложения требующие проверку учетной записи своего пользователя как правило довольно большие и их загрузка занимает довольно заметное время. Так зачем его тратить, если проверка даст отрицательный результат?
А кто говорит о том, что нужно сначала все загружать, а потом спрашивать логин? Создаем главную форму - создаем форму ввода логина и показываем ее - если логин проходит, грузим все что нам надо для работы. Создание главной формы не говорит о том, что нам тут же надо и все загружать сразу.

Автор: northener 10.6.2013, 12:47
Цитата(Poseidon @  10.6.2013,  10:40 Найти цитируемый пост)
Создание главной формы не говорит о том, что нам тут же надо и все загружать сразу.


Ну не скажи. Раз главное окно программы показано, то среднестатистический пользователь считает, что ему уже можно нажимать на всякие пупочки в этом окне чтобы получить желаемый результат. А если основной функционал программы ещё не загружен, то вышеуказанный пользователь очень огорчится когда у него ничего не выйдет smile

Автор: northener 11.6.2013, 01:07
Или я неправильно понял:
Цитата(Poseidon @  10.6.2013,  10:40 Найти цитируемый пост)
Создаем главную форму - создаем форму ввода логина и показываем ее - если логин проходит, грузим все что нам надо для работы. 

Где в таком случае размещаем создание и показ формы ввода логина? 

Автор: Poseidon 11.6.2013, 09:05
Цитата(northener @  11.6.2013,  01:07 Найти цитируемый пост)
Где в таком случае размещаем создание и показ формы ввода логина?

northener, шутки шутим? 
Цитата(Poseidon @  10.6.2013,  10:40 Найти цитируемый пост)
Создаем главную форму - создаем форму ввода логина и показываем ее - если логин проходит, грузим все что нам надо для работы.


Код

program Project1;

uses
  Vcl.Forms, Vcl.Controls,
  Unit1 in 'Unit1.pas' {MainForm},
  Unit2 in 'Unit2.pas' {LoginForm};

{$R *.res}

begin
  Application.Initialize;

  LoginForm:= TLoginForm.Create(Application);
  if LoginForm.ShowModal = mrOk then
  begin
    Application.CreateForm(TMainForm, MainForm);
    Application.Run;
  end;
end.


Код

procedure TLoginForm.OKButtonClick(Sender: TObject);
begin
  if (True) then // логин прошел
    ModalResult:= mrOk
  else // логин НЕ прошел
    ModalResult:= mrCancel
end;


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)