【问题标题】:"Control '' has no parent window" error“控件''没有父窗口”错误
【发布时间】:2014-06-12 12:36:24
【问题描述】:

当我将控件放在表单上时出现此错误。 错误出现在这里:

  TAssociateFileExt = class(TGroupBox)
  private
  protected
  public
    btnAssociate   : TButton;
    constructor Create(aOwner: TComponent); override;
  end;

constructor TAssociateFileExt.Create(aOwner: TComponent);
begin
 inherited Create(aOwner);
 Caption:= '';                       <-------- error here
 ClientHeight:= 125;                 <-------- and here
 ClientWidth := 170;
 DoubleBuffered:= TRUE;

 btnAssociate:= TButton.Create(Self);
 btnAssociate.Parent:= Self;
 btnAssociate.Visible:= TRUE;
 btnAssociate.Left:= 17;
 btnAssociate.Top:= 26;
 btnAssociate.Width:= 142;
 btnAssociate.Height:= 25;
 btnAssociate.Hint:= 'Associate this application with its files. When you double click a file this program will automatically start and load that file.';
 btnAssociate.Caption:= 'Associate';
 btnAssociate.DoubleBuffered:= TRUE;
 btnAssociate.ParentDoubleBuffered:= FALSE;
 btnAssociate.TabOrder:= 0;
 btnAssociate.OnClick:= btnAssociateClick;

 btnAssociateDel:= TButton.Create(Self);
 btnAssociateDel.Parent:= Self;
 btnAssociateDel.Visible:= TRUE;
 btnAssociateDel.Left:= 17;
 btnAssociateDel.Top:= 53;
 btnAssociateDel.Width:= 142;
 btnAssociateDel.Height:= 25;
 btnAssociateDel.Hint:= 'Remove association';
 btnAssociateDel.Caption:= 'Remove association';
 btnAssociateDel.DoubleBuffered:= TRUE;
 btnAssociateDel.ParentDoubleBuffered:= FALSE;
 btnAssociateDel.TabOrder:= 1;
 btnAssociateDel.OnClick:= btnAssociateDelClick;

 chkAllUsers:= TCheckBox.Create(Self);
 chkAllUsers.Parent:= Self;
 chkAllUsers.Visible:= TRUE;
 chkAllUsers.Left:= 31;
 chkAllUsers.Top:= 97;
 chkAllUsers.Width:= 115;
 chkAllUsers.Height:= 17;
 chkAllUsers.Hint:= 'Please note that if you want to do this for all users then you need administrator/elevated rights.';
 chkAllUsers.Caption:= 'Do this for all users';
 chkAllUsers.DoubleBuffered:= TRUE;
 chkAllUsers.ParentDoubleBuffered:= FALSE;
 chkAllUsers.TabOrder:= 2;
 chkAllUsers.OnClick:= chkAllUsersClick;
end;

答案可能是“标题需要一个有效的窗口句柄”。正确的?但是,David Intersimone (here) 的一篇文章说可以在构造函数中设置 Caption。

  1. 文章有误吗?
  2. 我应该在 CreateWnd 中移动代码(Caption 和 TButton.Create)吗(因为 AfterConstruction 不是一个好地方)?问题是 CreateWnd 可以被多次调用:“CreateWnd 在首次创建控件或必须销毁并重新创建底层屏幕对象以反映属性更改时自动调用。”

更新:
在将 (aOwner: TComponent) 添加到构造函数的声明(在实现中)后,按照 J... 的建议,错误移至下一行 (clientheight:= 90);

【问题讨论】:

  • 我猜你需要一个父窗口。 SSCCE 会有所帮助。
  • 嗨,大卫。我知道。但是他们(Embarcadero 在他们的文章中)是怎么做到的呢?
  • @J... - 不应该在构造函数中设置专利!
  • 您可以回答自己的问题,而不是在问题中发布新代码。
  • @JerryDodge - 我知道。我在等待一个可能更好的答案。例如为什么代码在 Embarcadero 的文章中有效,而不是在我的代码中。

标签: delphi delphi-xe


【解决方案1】:

我在 CreateWindowHandle 中移动了代码。现在它起作用了。 完整代码:

UNIT cAssociateExt;

INTERFACE

USES
  Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, Forms, StdCtrls;

TYPE
  TAssociateFileExt = class(TGroupBox)
  private
  protected
  public
    btnAssociate   : TButton;
    btnAssociateDel: TButton;
    chkAllUsers    : TCheckBox;
    constructor Create(aOwner: TComponent); override;
    procedure AfterConstruction;  override;
    procedure CreateWindowHandle(const Params: TCreateParams); override;
    ...
  published
  end;


procedure Register;


IMPLEMENTATION


procedure TAssociateFileExt.AfterConstruction;
begin
 inherited;         //Not a good place here
end;


procedure TAssociateFileExt.CreateWindowHandle(const Params: TCreateParams);
begin
 inherited;

 //DO NOT CREATE CONTROLS HERE! See: Sertac Akyuz's comment

 Caption:= '';    
 ClientHeight:= 125;
 ClientWidth := 170;
end;



constructor TAssociateFileExt.Create(aOwner: TComponent);
begin
 inherited Create(aOwner);
 DoubleBuffered:= TRUE;

 btnAssociate:= TButton.Create(Self);
 btnAssociate.Parent:= Self;
 btnAssociate.Visible:= TRUE;
 btnAssociate.Left:= 17;
 ...
end;

【讨论】:

  • 如果您在 CreateWindowHandle 中创建实例,请考虑在其对应项中销毁它们:DestroyWindowHandle。最好仅将 CreateWnd/WindowHandle 用于需要窗口句柄的事物。
  • @SertacAkyuz - 我不明白。我必须手动释放 btnAssociate (和其他控件)? btnAssociate.Owner 设置为 Self,因此 Self 应该释放 btnAssociate。对吗?
  • 您不必这样做。但是,如果您的 groupbox 的窗口由于某种原因被重新创建,您将拥有没有任何引用的活动按钮,它们只会在 groupbox 被销毁时被销毁。
  • 像以前一样在 OnCreate 中创建按钮。仅使用“CreateWindowHandle”设置需要窗口句柄的属性,例如设置客户端宽度/高度。
  • 好吧,我的 cmets 只是一些笔记。重要的是对 some 操作的句柄的要求。请把自己喜欢的任何东西融入到 cmets 的答案中。
【解决方案2】:

重要提示: 当您创建组件时,您需要在构造函数过程中使用此行以避免“控件没有父窗口”。

继承的创建(AOwner); 父级:=TWinControl(AOwner);

猜你喜欢
  • 2016-12-20
  • 2011-04-16
  • 2019-06-12
  • 2013-08-27
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 2012-06-30
  • 2014-10-31
相关资源
最近更新 更多