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


Автор: Gnus 20.3.2012, 16:12
Доброго времени суток.

Преамбула.
Штатный проект в дельфи 6.
Код

  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;

В главной форме при создании делаю следующее:
Код

procedure TMainForm.FormCreate(Sender: TObject);
begin
...
  PostMessage(Handle, WM_InitMain, 0, 0);
end;

В обработчике сообщения WM_InitMain скрываю основную форму методом Hide и порождаю и показываю вторую форму.
Код

procedure TMainForm.WMInitMain(var Msg: TMessage);
begin
// здесь порождаются необходимые объекты и регистрируется функция обратного вызова
...
  Self.Hide;
  Application.CreateForm(TSplash, Splash);
  ...
  Splash.Show;
  Splash.Update;
...
end;

Функция обратного вызова реагирует на состояние объекта и передает его состояние второй форме:
Код

procedure TMainForm.CMC(AMode: TConnMode; AError: Cardinal);
begin
  if (AMode = cmIdle) and (FLastMode = cmConnecting) and Assigned(Splash) then begin
    PostMessage(Splash.Handle, WM_CLOSE, 0, 0); 
    Splash := nil;
    Self.Show;
    Self.Update;
    SD.Init;
  end;
  if Assigned(Splash) then
    Splash.SetParams(AMode, AError);
  FLastMode := AMode;
end;

Вторая форма изменяет свое состояние в зависимости от состояния объекта: выводит сообщения об ошибках, показывает кнопки переподключения и выхода в случае ошибки соединения. В случае успешного подключения, эта форма уничтожается в приведенной выше функции, далее вызываются методы Show и Update главной формы.

Все вроде работает, но:
1. При запуске до вызова Hide главная форма успевает "мигнуть" на экране.
2. Так же заметна "чехарда" с кнопками в панели задач.
3. После закрытия второй формы, главная оказывается не в фокусе.

Что посоветуете?

ПС: Обращаю внимание, что главная форма должна быть главной и порождаться первой, т.к. она порождает объект и содержит обработчик обратного вызова от этого объекта.
Тестил Application.ShowMainForm := False в обработчике FormCreate: все работает без миганий, но вот при показе основной формы виснет намертво.  smile 

Автор: northener 20.3.2012, 16:23
Вариант создания и показа сплеш-скрина из Demos в стандартной поставке Дельфи (mastapp) чем не устроил?

Автор: Gnus 20.3.2012, 16:34
Цитата(northener @ 20.3.2012,  16:23)
Вариант создания и показа сплеш-скрина из Demos в стандартной поставке Дельфи (mastapp) чем не устроил?

Не устроил тем, что:
1. сплэш-форме передается указатель на объект, созданный главной формой, поэтому порождаться она должна после создания главной формы
2. сплэш-форма уничтожается по событию, обработанному главной формой.

вобщем жизненный цикл сплэш-формы происходит после создания главной формы и вызова Application.Run


С фокусом, кстати, разобрался при помощи PostMessage(Self.Handle, WM_SETFOCUS, 0, 0);

Автор: Snowy 20.3.2012, 18:47
Цитата(Gnus @  20.3.2012,  17:34 Найти цитируемый пост)
1. сплэш-форме передается указатель на объект, созданный главной формой, поэтому порождаться она должна после создания главной формы
Зачем?

Цитата(Gnus @  20.3.2012,  17:34 Найти цитируемый пост)
2. сплэш-форма уничтожается по событию, обработанному главной формой.
Во время работы сплэшформы главной формы еще не существует.

Цитата(Gnus @  20.3.2012,  17:34 Найти цитируемый пост)
вобщем жизненный цикл сплэш-формы происходит после создания главной формы и вызова Application.Run

жизненный цикл сплэш-формы происходит ДО создания главной формы и вызова Application.Run

Создается сплэшформа, показывается модально. Если mrOK, то создать главную форму и запустить Application.

Автор: Gnus 21.3.2012, 09:12
Уважаемый Snowy! 
Боюсь, Вы не прочли первый пост. 

Цитата(Snowy @  20.3.2012,  18:47 Найти цитируемый пост)
Во время работы сплэшформы главной формы еще не существует.
жизненный цикл сплэш-формы происходит ДО создания главной формы и вызова Application.Run


Это всё хорошо, но не надо считать эту форму сплэш-формой в классическом понимании заставки.
Моя сплэш-форма позволяет пользователю сменить адрес устройства и произвести повторной подключение в случае неудачи связи. Также сплэш-форма имеет кнопку завершения работы приложения.

Если подробно: есть dll, которая содержит функции связи с некоторым устройством. Сам канал связи может быть строго определенных состояниях: не соединено, соединяется, свободно, занято, ошибка, разъединено. Смена состояния осуществляет обратный вызов функции, определенной в главной форме. Адрес этой функции обратного вызова передается библиотечной функции Connect, которая также возвращает дескриптор экземпляра устройства. Так порождение библиотечного объекта и передача ему адреса функции обратного вызова происходит в главной форме, а функция обратного вызова в свою очередь информирует сплэш-форму о смене состояния объекта.

Вопрос не в том, как показать сплэш-форму.
Вопрос в том, как создать скрытую главную форму (без всяких миганий на экране) и при определенных условиях корректно ее показать.

Автор: Snowy 21.3.2012, 11:44
Форма - всего лишь отображение.
Совсем не стоит завязывать логику на интерфейс.
Как раз наоборот.
Логику нужно засунуть в отдельный модуль.
Если требуется какая-то реакция на изменение логики, то для этого есть механизм событий.

Как компромиссный вариант, могу предложить создать новую форму без заголовка, размером в 0 пикселей и сделать её главной.
И уже из неё управлять остальными формами в том порядке, какой больше нравится.

Автор: Gnus 23.3.2012, 09:51
Последовал советам. Получилось так: вначале порождаю девайс, потом порождаю и показываю сплэш-форму, говорю девайсу соединиться и жду закрытия сплэш-формы (она закрывается вручную пользователем при сбое связи или функцией обратного вызова при успешном установлении связи. в последнем случае выставляется свойство девайса OnLine в истину). Далее в зависимости от того, подключено устройство или нет, показываю главную форму или завершаю приложение:
Код

  Application.Initialize;
  SD := TDevice.Create(ExtractFilePath(ParamStr(0)) + fnIni, Integer(@CMCCBP));
  Splash := TSplash.Create(Application);
  Splash.Show;
  Splash.Update;
  SD.Connect;
  while Assigned(Splash) and Splash.Visible do
    Application.ProcessMessages;
  if SD.OnLine then begin
    Application.CreateForm(TSDForm, SDForm);
    Application.BringToFront;
    Application.Run;
  end;

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