【问题标题】:How to set a TCustomControl's Parent In Create如何在 Create 中设置 TCustomControl 的父级
【发布时间】:2011-09-18 04:40:15
【问题描述】:

当我们将组件创建为自定义控件并将控件拖放到面板上时,该控件始终显示在表单上而不是包含控件上。如何在 Create 中设置自定义控件的父级,以便当按钮拖放到面板上时,按钮父级就是面板?

TGlassButton = class(TCustomControl)
...
public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
...

constructor TGlassButton.Create(AOwner: TComponent);
  begin
    inherited;  ???????????
    inherited Create(AOwner); ????????????
    Parent := TWinControl( AComponent ); ??????????????
    ...
  end;

问题是设计时创建而不是运行时。这非常有效:

procedure TForm10.FormCreate(Sender: TObject);
begin
  GlassButton0 := TGlassButton.Create( Panel1 );
  GlassButton0.Parent := Panel1;
  GlassButton0.Left := 20;
  GlassButton0.Top := 6;
  GlassButton0.Width := 150;
  GlassButton0.Height := 25;
  GlassButton0.Caption := 'Created At RunTime';
end;

【问题讨论】:

  • 您正在寻找的行为是免费发生的。您的代码中的其他内容必须阻止它。解决方案肯定不是在构造函数中设置Parent
  • 你不需要做任何特别的事情,通常一个 TCustomControl 后代就像开箱即用一样工作。您可能编写了一些干扰正常 VCL 控件创建的代码。显示您的代码。
  • 是否有可能在将控件拖放到表单之前没有选择面板?
  • 在删除控件之前是否选择了面板并不重要。表单在设计时始终是父级。
  • 它可能是同一表单上的行为不端的自定义组件,或者是错误实现的设计时包。同样,通常 TCustomControl 后代会按预期放置在面板上。您的 TGlassButton 还包含哪些其他代码?您是否在设计时使用其他自定义组件在同一个表单上做一些可疑的事情?

标签: delphi


【解决方案1】:

不要在构造函数中设置 Parent 属性!正如其他人所说,IDE 和 DFM 流系统将在构造函数退出后自动分配父级。如果您需要在构造函数中执行依赖于分配的 Parent 的操作,那么您需要重新设计您的组件。覆盖虚拟的SetParent() 和/或Loaded() 方法,然后从那里进行操作。并在可以避免在设计时实际不需要的操作的地方使用if (csDesigning in ComponentState) then ... 检查。

【讨论】:

  • 将句柄特定代码从构造函数移动到Loaded 对我有用:D
  • @JerryDodge - Loaded 不是执行此操作的好地方,因为它仅在从 DFM 加载控件时调用,而不是在动态创建时调用。
  • @NAZCA 动态创建表单仍然从 DFM 加载。唯一不加载 DFM 的情况是没有,这是非常罕见的。
  • @JerryDodge-我说的是一个包含其他控件的控件,而不是表单。
  • 不仅如此。动态分配任何控件,即直接调用TGlassButton.Create(),不会调用其Loaded()方法。只有 DFM 流媒体可以做到这一点。因此,我建议替代 SetParent()
【解决方案2】:

父控件应该由创建控件的人设置。对于在设计时创建的控件,这将在创建表单时由流系统完成。对于在运行时创建的控件,应该在控件创建时完成:

var
  Control: TWinControl;
begin
  Control := TGlassButton.Create(<Form or Application>);
  Control.Parent := <Some other control on the form>;
end;

请注意,一般来说,表单是其上所有控件的所有者,无论是否为父。控件的父级是/应该是负责绘制它的控件:换句话说,它是视觉定位的控件。即 Panel、TabSheet、GroupBox 或其他容器。

【讨论】:

  • @Altar:雷米说的很对。在运行时创建的控件并不意味着它们必须在构造函数中创建。我经常使用 AfterConstruction 覆盖来确保构建过程中的所有内容,包括流式传输和为在设计时创建的控件调用 Loaded 都已完成。
  • @Rigel "... 与 Remy Lebeau 所说的相矛盾" - 不,事实并非如此。我说不要从正在创建的子控件的构造函数内部设置Parent。在 Marjan 的示例中,Parent 在子构造函数退出后设置,这非常好
猜你喜欢
  • 2019-04-18
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2013-03-04
  • 2016-06-20
  • 2023-03-16
相关资源
最近更新 更多