构造函数有运行后如何设置CreateParams?

How to set CreateParams after the constructor has run?

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

  TForm2 = class(TForm)
  private
    FAppWindow: Boolean;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    property AppWindow: Boolean read FAppWindow write FAppWindow;
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.Create(Self);
  Form2.AppWindow := True;
  Form2.Show;
end;

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
  inherited;
  if FAppWindow then begin
    Params.Style := Params.Style or WS_EX_APPWINDOW;
    Params.WndParent := 0;
  end;
end;

这行不通,因为 window 句柄是在 TForm 的构造函数中创建的,所以 CreateParams 运行 太早并且 FAppWindow 总是 False.

编写自定义构造函数也不起作用,因为您最终必须调用继承的构造函数来创建句柄,然后才能将任何数据保存到实例中:

constructor TForm2.CreateAppWindow(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FAppWindow := True;
end;

有没有办法:

如何更改 class 的 "outside" 表单的样式?

这似乎可以重新创建句柄,我的想法来自 RecreateAsPopup VCL 方法:

procedure TForm2.SetAppWindow(const Value: Boolean);
begin
  FAppWindow := Value;
  if HandleAllocated then
    RecreateWnd
  else
    UpdateControlState;
end;

最简单的解决方案是在窗体的构造函数中将参数传递给窗体,而不是等到窗体创建完成。

这意味着您需要为 TForm2 引入一个构造函数,它接受您需要在 CreateParams 中传递的任何信息作为参数。

在调用继承的构造函数之前记下任何状态。此外,当您将所有者设置为零时,无需设置 WS_EX_APPWINDOW

Delphi 的好处是派生构造函数不必调用 inherited 构造函数作为其 first 语句。所以你可以先设置你的 FAppWindow 成员,然后调用 inherited 构造函数来流式传输 DFM 并创建 window,例如:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.CreateAppWindow(Self);
  Form2.Show;
end;

constructor TForm2.CreateAppWindow(AOwner: TComponent);
begin
  FAppWindow := True;
  inherited Create(AOwner);
end;