加载自定义组件时IDE出错, Delphi bug还是我的错误?

p4rjhz4m  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(107)

我发现一个自定义组件有一个奇怪的问题,它动态地创建/销毁子组件。

type
  TPanelTest = class(TPanel)
  private
    FShowPanel : Boolean;
    FPanel : TPanel;
    function GetShowPanel: Boolean;
    procedure SetShowPanel(const Value: Boolean);
    procedure CreateSubPanel;
    procedure DestroySubPanel;
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property ShowPanel : Boolean read GetShowPanel write SetShowPanel;
  end;

...

{ TPanelTest }
constructor TPanelTest.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetBounds(0, 0, 300, 300);
  ShowPanel := True;
end;

procedure TPanelTest.CreateSubPanel;
begin
  if not Assigned(FPanel) then
  begin
    FPanel := TPanel.Create(Self);
    with FPanel do
    begin
      SetSubComponent(True);
      Parent := Self;
      Caption := '';
      Top := 0;
      Left := 0;
      Height := 50;
      Align := alTop;
    end;
  end;
end;

procedure TPanelTest.DestroySubPanel;
begin
  if Assigned(FPanel) then
    FreeAndNil(FPanel);
end;

function TPanelTest.GetShowPanel: Boolean;
begin
  Result := FShowPanel;
end;

procedure TPanelTest.SetShowPanel(const Value: Boolean);
begin
  FShowPanel := Value;
  if Value then
    CreateSubPanel
  else
    DestroySubPanel;
end;

在运行时和设计时,一切(创建和销毁FPanel)都是正确的,但是如果我将ShowPanel设置为False,然后保存项目,关闭并再次打开它,我会得到一个错误:
创建表单时出错:模块“vcl270.bpl”中的地址50 CF 4 B 9 C处存在访问冲突。读取地址00000000。
如果我在.dfm文件中手动将ShowPanel更改为True,则一切都将重新正常工作。
我错过了什么我用的是 Delphi 10.4.2 CE
现在,我使用了一种变通方法,使SubPanel不可见,而不是销毁它,但我想使它正确。

2hh7jdfx

2hh7jdfx1#

问题在SetSubComponent(True)
与顶级组件不同,子组件不与它们所在的窗体或数据模块一起保存。相反,子组件显示为其所有者的已发布属性的值,其已发布属性和事件与所属组件一起保存在表单文件中。
在本例中,我不需要将FPanel设置为TPanelTest的子组件。

相关问题