2

重複の可能性:
スプラッシュ スクリーン
データベース接続 (時間がかかる場合があります) の実行中にスプラッシュ スクリーンをプログラムで表示する

INI ファイルのロードなどのコードを初期化するのに最適な場所はどれですか? 最初にフォームを画面に表示して、アプリが読み込まれていることをユーザーに知らせ、その後のみ LoadIniFile や IsConnectedToInternet などの長い関数を呼び出したい (最後の関数は非常に遅い)。

フォームがまだ準備できておらず、画面に表示されないため、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 は私の唯一のフォーム (メイン フォーム) です。

4

4 に答える 4

3

を呼び出した後、 を呼び出して画面上にレンダリングさせてからfrmTest.Show、 を呼び出すことができます。しかし、が呼び出されるまで、メインのメッセージ ループは実行されないため、フォームはそれまで何もできません。frmTest.UpdateLateInitializeApplication.Run

もう 1 つのオプションは、フォームのOnShowイベントを使用してカスタム ウィンドウ メッセージを 経由でフォームにポストし、後でそのメッセージを受信したときにPostMessage()フォームを呼び出すことです。LateInitializeこれにより、LateInitializeが呼び出されるまで、フォームは描画メッセージを正常に処理できます。

メイン スレッドを数ミリ秒/秒以上ブロックするものはすべて、代わりに別のワーカー スレッドに移動する必要があります (特に のようなものIsConnectedToInternet)。UI の実行には、メイン スレッドを使用する必要があります。

于 2012-07-27T01:24:34.797 に答える
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;
于 2012-07-27T08:39:51.677 に答える
1

バリアント 1: TTimer を 1 秒の遅延で使用し、メイン フォームの OnShow から実行します TTimer で初期化を行います これにより、ほとんどのコンポーネントが初期化して自分自身を描画する時間が与えられます バリアント 1.1: 関数でメッセージ メソッドを使用し、Win API PostMessage を呼び出します (ただし、 OnShow の SendMessage 別名 Perform)。これは似ていますが、より安価で高速です。ただし、フォーム上の複雑なコンポーネントが完全に描画される前に、「do init now」というメッセージを受信する場合があります。

バリアント 2: スレッド (OmniThreadsLib または単純な TThread) を使用する MainForm OnCreate から起動し、バックグラウンドですべてのデータを準備してから、必要なすべてのボタン、メニューなどを有効にします。 IsConnectedToInternet について説明しました。

バリエーション 3: メイン フォームを表示する前に SplashScreen を使用します。ユーザーはアプリケーションがまだ読まれていないことを確認できるため、これは良いことです。それはまさにその理由で悪いです-人々はあなたのプログラムが遅いと感じ始めます。Google Chrome は、実際のコントロールが少し後で準備ができたとしても、「すでに開始されている」ように見せるために、最初の瞬間にメイン フォームを絵として描画するように指示されました。

于 2012-07-27T07:44:32.053 に答える
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 イベントを試してください。

于 2012-07-27T00:16:27.350 に答える