5

DelphiXE2を使用して以下のコードを作成しました。Form1を作成し、Form1はすぐにForm2のインスタンスを作成します。Form2のボタンを押すと、2番目のForm2が作成されます。

ここで、この2番目の一番上のForm2のボタンの上にマウスを置いて、ツールチップが表示されるのを待つと、ツールチップが表示された瞬間に、最初のForm2が前面に表示され、フォーカスが奪われます。

問題は、がである場合Application.MainFormOnTaskbarにのみ発生しますTrue。また、Form1のFormCreateメソッドから作成された最初のForm2に依存しています。PostMessage()アプリケーションの初期化が完了するまで最初のForm2の作成を遅らせるために使用すると、問題は解決します。

なぜこれが起こっているのか理解したいのですが。Delphiのアプリケーションオブジェクトがヒント表示を含む多くのことを処理することをすでに学びました。Delphiは初期化中にウィンドウのハンドルを再作成できることを知っていますが、上記の動作を完全に説明するためにこれを実行することはできませんでした(または確かに、上記の2つの事実が関連しているかどうか)。

Project1.dpr

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True; // False makes problem go away
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit1.pas

unit Unit1;
interface
uses
  Vcl.Forms, Unit2;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  public
    procedure CreateForm2;
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateForm2;
end;

procedure TForm1.CreateForm2;
var
  frm : TForm2;
begin
  frm := TForm2.Create(Application); // (Could pass Self - makes no difference)
  frm.Show;
end;

end.

Unit2.pas

unit Unit2;
interface
uses
  Vcl.Forms, System.Classes, Vcl.Controls, Vcl.StdCtrls, WinApi.Windows;

type
  TForm2 = class(TForm)
    Button1: TButton; // This button has a hint
    procedure Button1Click(Sender: TObject);
  end;

var
  Form2: TForm2;

implementation
uses
  System.SysUtils, Unit1;

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.CreateForm2;
end;

end.
4

1 に答える 1

7

ここでの重要な問題は、の最初のインスタンスがTForm2アプリケーションウィンドウによって所有されるウィンドウとして作成されることですApplication.Handle。そしてここで私は所有者のWindowsの意味に言及しています。VCL言語では、これはポップアップの親と呼ばれます。

TForm2これで、その最初のインスタンスを作成するとき、Application.MainFormプロパティはまだnilです。また、を明示的に割り当てていないためPopupParent、のコードTCustomForm.CreateParamsは所有者をアプリケーションウィンドウに設定します。

あなたは単にあなたのウィンドウが隠されたアプリケーションウィンドウによって所有されることを望まない。TForm2これが、最初のインスタンスが他のすべてのウィンドウの背後、特にメインフォームの背後に表示されることがある理由です。間違った所有者で作成されただけです。

が所有するフォームはApplication.Handleに表示されTHintWindow.ActivateHintます。これは、を読み取る行が原因で発生しますParentWindow := Application.Handle。これに続いて呼び出しが行われ、SetWindowPos(Handle, ...)その結果、誤って所有されているフォームが前面に表示されます。も所有しているので、おそらくその形が前面に出てきApplication.Handleます。今のところ、正確なメカニズムについて明確な説明はありませんが、フォームが明らかに間違って設定されているため、それほど興味深いものではありません。

いずれにせよ、根本的な問題は、誤って所有されているウィンドウを作成したことです。したがって、解決策は、ウィンドウが正しく所有されていることを確認することです。を割り当ててそれを行いPopupParentます。例えば:

procedure TForm1.CreateForm2;
var
  frm : TForm2;
begin
  frm := TForm2.Create(Application); // (Could pass Self - makes no difference)
  frm.PopupParent := Self;
  frm.Show;
end;
于 2012-12-12T11:30:59.410 に答える