6


1

Delphiアプリの初期化が完了した後、一度実行するコードはどこに置くべきですか?

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

Application.CreateForm(TMainForm, MainForm) ;

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

MainForm.position := poScreenCenter ;

これにより、OnShowイベントが再び発生します。

一度だけ呼び出す必要があり、実行する前にメインフォームを作成する必要があるProcedureXをどこに呼び出すことができますか?

6 Answer


9


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

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


6


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

  • AfterConstruction:フォームとそのコンポーネントが完全に作成されたとき すべてのプロパティを持ちます。

  • OnShow:フォームを表示する準備ができたとき(そして、はい、すべての変更 「CM_SHOWINGCHANGED」を引き起こすと「OnShow」をトリガーできる)

  • 「アクティブ化」:フォームがフォーカスを取得するたび

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

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

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


6


@Sertac、

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

参考までに、「1回実行」イディオム(イベントハンドラーの最初の行でイベントハンドラーフィールドをNILに設定)は、フォームが完全に初期化された後、コードを実行するのにも非常に便利です。 コードをFormActivateメソッドに配置し、メソッドの最初の行としてOnActivate = NILを設定します。


4


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

また、初期化に多くの時間がかかる場合は、プログラムが画面にフォームを表示して、ユーザーがアプリが読み込まれていることをユーザーに知らせるようにします。

例:

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

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

    Application.Run;
end.


3


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

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;


0


@Sertec、

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

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