2012-07-26 2 views
2

Можно создать дубликат:
Splash Screen Programatically
Show a splash screen while a database connection (that might take a long time) runsКакое место лучше всего инициализировать?

Что является лучшим местом для инициализации коды, такой как загрузка INI-файл? Сначала я хочу показать форму на экране, чтобы пользователь знал, что приложение загружается, и ТОЛЬКО после этого я хочу вызвать длительные функции, такие как LoadIniFile или IsConnectedToInternet (последний из них ДЕЙСТВИТЕЛЬНО медленный).

The OnCreate не является хорошим, потому что форма еще не готова, и она не появится на экране.

я делаю это я DPR, но не работает всегда:

program Test; 
begin 
    Application.Initialize; 
    Application.Title := 'Test app'; 
    Application.CreateForm(TfrmTest, frmTest); 
    frmTest.Show;    <---------------------- won't show 
    LateInitialize; 
    Application.Run; 
end. 

форма не будет отображаться до тех пор, LateInitialize (4-5 секунд) не выполняется.


procedure LateInitialize; 
begin 
CursorBussy; 
TRY 
    // all this won't work also. the form won't show 
    frmTest.Visible:= TRUE; 
    Application.ProcessMessages; 
    frmTest.Show; 
    Application.ProcessMessages; 
    frmTest.BringToFront; 
    frmTest.Update; 
    Application.ProcessMessages; 

    DoSomethingLengthy;  {4-5 seconds} 
FINALLY 
    CursorNotBussy; 
END; 
end;  <--------- Now the form shows. 

И да, frmTest это моя единственная форма (основная форма).

+0

Эти сообщения не имеют принятого ответа, и они ТОЧНО на ту же тему. – Ampere

+2

Ум, да. Это [прямо здесь] (http://stackoverflow.com/a/3359841/62576) - тот, у которого есть большая зеленая галочка и три надписи. И да, они на одной теме. Итак, ваш вопрос, поэтому я отметил его как [дубликат] (http://dictionary.reference.com/browse/duplicate). –

+4

Если они точно соответствуют одному и тому же вопросу, то они являются точными дубликатами этого вопроса по собственному признанию. Неважно, принимали ли они ответы. «Дубликат» является свойством вопроса, полностью независимым от любых ответов, которые могут быть. Тем не менее, * оба вопроса связаны с ответами Кен. Если у вас есть вопросы, которые уже заданы здесь, и у них нет подходящих ответов на вашу ситуацию, тогда есть способы привлечь внимание к этим вопросам, чтобы люди ответили на них. Задавать двойной вопрос - это один из способов. –

ответ

2

Простой способ сделать это - отправить сообщение самому себе. Я делаю это все время

const 
    MSG_AFTERCREATE = WM_APP + 4711; 

... 
procedure OnCreate(Sender: TObject); 
procedure AfterCreate(var message: TMessage); message MSG_AFTERCREATE; 
... 


Implementation 

procedure OnCreate(Sender: TObject); 
begin 
    PostMessage(Self.Handle, MSG_AFTERCREATE, 0, 0); 
end; 

procedure AfterCreate(var message: TMessage); 
begin 
    //Do initializing here... the form is done creating, and are actually visible now... 
end; 
+0

Мне это нравится! Я попробую. БЛАГОДАРЮ. Очень элегантно. Интересно, как никто не приходил и так не отвечал до сих пор! – Ampere

0

Давным-давно, на другом форуме, далеком расстоянии, кто-то опубликовал следующее для документирования жизненного цикла формы. Я нашел это полезным, поэтому поделись им здесь.

Create  OnCreate 
Show   OnShow 
Paint  OnPaint 
Activate  OnActivate 
ReSize  OnResize 
Paint  OnPaint 

Close query OnCloseQuery 
Close  OnClose 
Deactivate OnDeactivate 
Hide   OnHide 
Destroy  OnDestroy 

Попробуйте событие OnActivate.

+1

Но помните, что 'OnActivate' может срабатывать много раз в ходе программы. –

+1

-1. OnActivate срабатывает каждый раз, когда форма теряет фокус, а затем снова получает его (например, пользователь нажимает на другую форму в вашем приложении или переключается на другое приложение, а затем возвращается к вашему). Если ваш код инициализации не может выполняться несколько раз, OnActivate - это совершенно неправильное место для его размещения. –

+2

@ Роб Кеннеди и Кен Уайт: Вы, ребята, эксперты, поэтому я буду откладывать ваши превосходные знания. Тем не менее, я делаю что-то подобное все время (но чаще в событии OnShow). Я просто добавляю переменную флага, чтобы указать, был ли запущен код инициализации. Если инициализация произошла, я пропущу код инициализации. Он спросил, куда поставить код инициализации, а не как его кодировать. –

3

После звонка frmTest.Show, вы можете позвонить frmTest.Update, чтобы он отображался на экране, а затем звонил LateInitialize. Но до тех пор, пока не назовется Application.Run, основной цикл сообщения не будет запущен, поэтому форма пока не сможет ничего сделать.

Другой вариант заключается в использовании OnShow событий формы, чтобы отправить сообщение на заказ окна обратно в форму через PostMessage(), то есть форма вызова LateInitialize когда он получает это сообщение в более позднее время. Это позволит форме обрабатывать сообщения для рисования обычно до тех пор, пока не вызывается LateInitialize.

Все, что блокирует основной поток более чем на несколько миллисекунд/секунду, действительно должно быть перемещено в отдельный рабочий поток (особенно такие вещи, как IsConnectedToInternet). Основной поток должен использоваться для запуска пользовательского интерфейса.

1

Вариант 1: Использование TTimer с секундной задержкой 1, запустить его из главной формы OnShow В TTimer сделать инициализацию Это даст время для большинства компонентов, чтобы инициализировать и сделать себя Вариант 1.1: использование метода сообщение функции и вызов Win API PostMessage (но не SendMessage aka Perform) из OnShow. Это похоже, но дешевле и быстрее. Однако такое сообщение «do init now» иногда может быть получено до того, как какой-нибудь сложный компонент в форме будет полностью нарисован.

Вариант 2: использование нитей (OmniThreadsLib или даже обычный TThread) Запускаем из MainForm OnCreate и пусть это подготовить все данные в фоновом режиме, а затем включить все необходимые кнопки, меню и т.д. Это действительно лучший способ, если у вас есть длинные и блокирующие функции, вы описали IsConnectedToInternet.

Вариант 3: используйте SplashScreen перед тем, как показывать основную форму. Это хорошо, потому что пользователи видят, что приложение еще не прочитано. Это плохо по этой причине - люди начинают чувствовать, что ваша программа идет медленно. Google Chrome было сказано сделать свою основную форму как изображение в 1-й момент, чтобы посмотреть, «мы уже начали», даже фактический контроль будет готов немного позже.

+0

Вариант 1: что, если процессор и основная форма не успели обновить себя, но время на TTimer истекло (второе прошло)? – Ampere

+0

Variant2: при инициализации мне нужно сделать много файлов GUI (INI) и глобальных инициализаций vars. Нить будет взаимодействовать с основной формой. – Ampere

+0

Вариант 3: мне это нравится – Ampere

Смежные вопросы