【问题标题】:How to set CreateParams after the constructor has run?构造函数运行后如何设置 CreateParams?
【发布时间】:2015-06-04 18:06:33
【问题描述】:
  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;

这样不行,因为窗口句柄是在TForm的构造过程中创建的,所以CreateParams运行得太早了,FAppWindow总是False

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

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

有没有办法:

  • 延迟创建窗口句柄?
  • 创建窗口句柄后更改窗口样式?
  • 在构造函数运行后重新创建窗口句柄?
  • 我还没有想到其他选项?

如何从类的“外部”更改表单的样式?

【问题讨论】:

  • 为该属性编写一个设置器,它将RecreateWnd
  • 或者,如果您不想重新创建窗口,您可以执行ChangeAppWindow 内部过程所做的事情。它通过SetWindowLong 在一对ShowWindow 调用中设置样式(SW_HIDESW_SHOWSW_MINIMIZE 对)。我更喜欢在这里重新创作。

标签: delphi window delphi-xe2 vcl


【解决方案1】:

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

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

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

【讨论】:

  • 在调用继承之前记下参数。这是要走的路。
  • 是的,CreateParented 就是这样做的
  • 我在尝试这样的事情时遇到了访问冲突,但现在它似乎工作了,很好奇。有没有可能Self在某些情况下没有在构造函数中初始化?
  • 1) 你调用构造函数而不分配。 TMyClass.Create();而不是c := TMyClass.Create(); 2)您使用变量而不是类调用构造函数。 c.Create(); 3) 您正在使用尚未初始化的Self 变量。
  • 您可以从字段中读取和写入,但它们将被默认初始化。
【解决方案2】:

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

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;

【讨论】:

    【解决方案3】:

    这似乎可以重新创建句柄,我从RecreateAsPopup VCL 方法中得到了这个想法:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 2021-11-27
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      相关资源
      最近更新 更多