7

アプリの初期化が完了し、メイン フォームが作成された後に実行したい機能があります。フォームの OnShow イベントにコード (ProcedureX と呼びます) がありましたが、OnShow が 2 回起動しているため、コードが 2 回呼び出されていることに気付きました。メインプログラムの DPR が以下を呼び出すと起動します。

Application.CreateForm(TMainForm, MainForm) ;  

私が期待するように。しかしその後、画面上のフォームの位置を含む INI ファイルから内容を読み取ると、次の呼び出しが発生します。

MainForm.position := poScreenCenter ;

これにより、OnShow イベントが再び発生するように見えます。

ProcedureX への呼び出しをどこに置くことができますか? これは 1 回だけ呼び出す必要があり、実行する前にメイン フォームを作成する必要があります。

4

6 に答える 6

9

コードをフォームの作成ごとに 1 回だけ実行する必要がある場合 (またはアプリケーションごとに実行し、アプリケーションの実行ごとにフォームを 1 回だけ作成する必要がある場合)、コードをフォームの OnCreate ハンドラーに配置します。それが行くのは自然な場所です。

最近では (D3 以降だと思います)、OnCreate は AfterConstruction メソッドの構築プロセスの最後に起動します。OldCreateOrder を True (デフォルトでは False) に設定した場合にのみ、Create コンストラクターの最後で OnCreate が発生するため、問題が発生する可能性があります。

于 2010-09-24T06:46:01.770 に答える
6

@セルタック、

FRUNOnce フィールドはまったく必要ありません。FormShow メソッドの最初の行として OnShow=NIL を実行するだけです。

参考までに、イベント ハンドラの最初の行でイベント ハンドラ フィールドを NIL に設定する「1 回実行」というイディオムは、フォームが完全に初期化された後にコードを起動して実行する場合にも非常に役立ちます。コードを FormActivate メソッドに入れ、メソッドの最初の行として OnActivate=NIL を設定します。

于 2010-09-24T19:18:55.697 に答える
6

フォームの通常の実行順序は次のとおりです。

  • AfterConstruction: フォームとそのコンポーネントがすべてのプロパティで完全に作成されたとき。
  • OnShow: フォームを表示する準備ができているときはいつでも (そして、はい、原因となる変更はCM_SHOWINGCHANGEDをトリガーできますOnShow)
  • Activate: フォームがフォーカスを取得するたびに

したがって、ProcedureX で必要なものによっては、AfterConstruction十分な場合があり、一度だけ実行されます。それをオーバーライドして、ProcedureX を の後に追加するだけinheritedです。後になりますOnCreate

そうでない場合は、カスタム メッセージを からフォームに投稿できます。メッセージAfterConstructionはキューに入れられ、他のメッセージが処理された後にカスタム ハンドラに到達します。

どちらの場合も、追加のブール フィールドは必要ありません。

于 2010-09-24T03:12:40.907 に答える
4

プロシージャを初めて呼び出すと、フラグをテストして設定できます。そのようです:

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
  private
    FRunOnce: Boolean;
  public
    [...]

[...]

procedure TForm1.FormShow(Sender: TObject);
begin
  if not FRunOnce then begin
    FRunOnce := True;
    ProcedureX;
  end;
end;
于 2010-09-24T01:45:04.280 に答える
4

Application.CreateForm の後に、DPR ファイルにプロシージャを追加できます。初期化に必要なすべてのコードをそのプロシージャに入れます。アプリに複数のフォームがある場合に最適です。

また、初期化に時間がかかる場合は、プログラムでフォームを画面に表示して、ユーザーがアプリの読み込み中であることを認識できるようにします。

例:

PROGRAM MyProgram;
begin
    Application.Initialize;
    Application.CreateForm(TMyForm, MyForm);
    MyForm.Show;

    LateInitialize;        <----------- here

    Application.Run;
end. 
于 2012-09-13T17:34:42.900 に答える
0

@ Sertec、

すべての再表示イベントに対してコードを実行する場合も、コードは機能しません(frunonceフィールドをリセットするためのコードを入力していません)。

したがって、メソッドはfrunonceフィールドをリセットする必要があり、私のメソッドはOnShow=FormShowを設定する必要があります。追加のフィールドが必要なことを除いて、同じ違いです。

于 2010-09-27T15:51:00.487 に答える