-2

Delphi XE6 で 2 つのフォームを持つアプリケーションを作成しようとしています。設定に応じて、ParamStrForm2 が Form1 の前に表示される場合と表示されない場合があります。

簡単なテスト アプリでは、両方のフォームがForm1.Show呼び出される前に作成されます - その間 Form2 が表示されるかどうか

procedure TForm1.FormShow(Sender: TObject);
begin
  if ParamStr(1) = 'foo' then
      Form2.FooShow;
end;

procedure TForm2.FooShow;
begin
   ShowModal;
end;

ただし、「実際の」アプリケーションでは、別の動作が見られます。

この場合Form1.Show、 が呼び出されるとすぐにApplication.CreateForm(TForm1, Form1)呼び出されます。これはForm2 が作成される前であり、必要なときに Form2 が存在しないため問題が発生しています。

動作が異なる理由は何ですか? プロジェクト>オプションのどこかに埋もれた設定がありませんか

4

1 に答える 1

3

フォームが True に設定されて永続化されている場合、フォームはVisible作成されるとすぐに表示されます。

プロパティを False に設定すると、問題が解決するはずです。

編集

VisiblePS:が に設定されていても、同様の問題を抱えている人がメインフォームを予期せず表示する場合に備えてFalse。これは、既定では、アプリケーションがVisibleへの呼び出しのプロパティに関係なく、メイン フォームを表示するために発生しますApplication.Run
もしそうなら、次の質問が役に立ちます:非表示のメイン フォームで Delphi アプリケーションを開始するにはどうすればよいですか?

EDIT2

完全を期すために、フォームが作成されるとすぐに表示される可能性のある他のいくつかのことがあります。ただし、これらはおそらくこの特定の質問には当てはまりません。

  • フォームの作成時にフォームを明示的に表示するコード (OnCreateイベントなど) は、明らかにフォームを表示します。ただし、そのような行動がこの種の質問につながらないことを願っています。
  • MDI 子フォームを非表示にすることはできません。せいぜいそれを最小限に抑えることができます。

ヒント

このような質問に対する答えを見つける最も簡単な方法は、通常、ほんの少しのデバッグです。

  • メソッドにブレークポイントを設定しますFormShow
  • Compiler Settings に移動し、デバッグ DCU でビルドするオプションを有効にします。(VCL コードを参照してください。)
  • アプリケーションを再構築して実行します。
  • ブレークポイントに到達したら、コール スタック デバッグ ウィンドウを開きます。
  • 呼び出しスタックをナビゲートしてトリガーを探します。

この場合、次のコードが にあるはずですForms.pas

procedure TCustomForm.DoCreate;
begin
  //...
  if fsVisible in FFormState then Visible := True; //<-- The trigger
end;

そして、もう少し調査するfsVisibleと、根本的な原因が次のように明らかになります。Visibleプロパティはに設定されていTrueます。


とはいえ、グローバルを介して依存関係を作成しているため、この方法でコーディングすることは望ましくありません。これはエラーが発生しやすいです。あなたの小さな実験ショーは、問題を引き起こす可能性のある多くの微妙な事柄の 1 つにすぎないことを示しています。

むしろ、DPR に次のような変更を加えてグローバルを回避します。

begin
  Application.Initialize;
  ShowForms;
end;

ShowFormsは次のように実装されています。

procedure ShowForms;
var
  LForm1: TForm1;
  LForm2: TForm2;
begin
  Application.CreateForm(TFrom1, LForm1);
  Application.CreateForm(TFrom2, LForm2);

  if (ParamStr(1) = 'foo') then
    LForm2.Show
  else
   LForm1.Show;
end;

フォーム間に依存関係がない場合は、上記で十分です。Form2 が Form1 を使用するなど、依存関係がある場合は、フォームを作成した後、フォームで何かを開始する前に、明示的に参照を渡すことができます。

//Define a property on TForm2 E.g.
property MainForm: TForm1 read FMainForm write SetMainForm;

//Immediately after creating both forms tell form2 which to use as its main form.
LForm2.MainForm := LForm1;
于 2014-06-30T10:53:56.157 に答える