gpt4 book ai didi

delphi - MainFormOnTaskbar + 工具提示导致焦点窃取

转载 作者:行者123 更新时间:2023-12-03 15:09:18 26 4
gpt4 key购买 nike

我使用 Delphi XE2 构建了下面的代码。它创建 Form1,Form1 立即创建 Form2 的实例。当我按下 Form2 上的按钮时,会创建第二个 Form2。

现在,如果我将鼠标悬停在第二个最上面的 Form2 上的按钮上,并等待工具提示出现,工具提示出现的那一刻,第一个 Form2 就会出现在前面,抢走焦点.

仅当 Application.MainFormOnTaskbarTrue 时才会出现此问题。它还依赖于从 Form1 的 FormCreate 方法创建的第一个 Form2。如果我使用 PostMessage() 延迟第一个 Form2 的创建,直到应用程序完成初始化,问题就会消失。

我想了解为什么会发生这种情况。我已经了解到Delphi的Application对象处理很多事情,包括提示显示,并且我知道Delphi可以在初始化期间重新创建窗口的句柄,但我无法遵循这一点来完全解释上述行为(或事实上上述两个事实是否相关)。

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.

最佳答案

这里的关键问题是,TForm2 的第一个实例被创建为应用程序窗口 Application.Handle 拥有的窗口。这里我指的是Windows meaning of owner 。在 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;

关于delphi - MainFormOnTaskbar + 工具提示导致焦点窃取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13836899/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com