如何使用在设计时接受其他控件的子面板创建自定义控件?

时间:2008-12-17 12:52:30

标签: delphi custom-component

我编写了一个自定义控件,它有几个子面板。我希望这些子面板能够接受在设计时丢弃的任何其他控件。

不幸的是,任何在设计时被删除的控件都会在我的自定义控件上出现,而不是在面板上。这特别显示了我是否尝试删除标签:标签的蓝点显示,但标题不是,如果我取消选择标签,它就不再可见了。

简化代码(只有一个子面板):

type
  TMyContainer = class(TPanel)
    p_SubPanel: TPanel;
  public
    constructor Create(_Owner: TComponent); override;
  end;

  constructor TMyContainer.Create(_Owner: TComponent);
  begin
    inherited;
    p_SubPanel := TPanel.Create(Self);
    p_SubPanel.Parent := Self;
    p_SubPanel.Align := alClient;
  end;

我在这里做错了什么?

(以防万一重要:我使用的是Delphi 2007。)

[编辑]

我现在以不同的方式解决了它。该组件不再包含面板,但指的是外部面板。这使得它实际上更加灵活,但在不利方面,它不再直观易用。

我仍然想知道如何完成我原先描述的内容。是不是有一个开源组件可以做到这一点,所以我可以研究源代码?

3 个答案:

答案 0 :(得分:2)

这是一个很好的问题。通过将csAcceptControls添加到控件ControlStyle属性,您可以允许自定义TWinControl在设计时删除其他控件。

constructor TMyContainer.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptControls];
end;

但是在尝试解决这个问题时,我无法将控件放到自定义控件中的子面板上。将csAcceptControls添加到子面板的ControlStyle是不够的。我得到的最好的是一个黑客来说服子面板它的设计是这样的:

type
  TGiveMeProtected_Component = class(TComponent);

procedure TMyContainer.Create(AOwner: TComponent);
begin
  FSubPanel := TPanel.Create(Self);
  TGiveMeProtected_Component(FSubPanel).SetDesigning(True, True);
end;

使用该代码,您现在可以将控件拖放到子面板上,但这意味着您还可以选择子面板,更改其属性,甚至删除您肯定不想要的属性。对不起,我无法想出答案,我仍然很想知道你是否解决了这个问题。 :)

答案 1 :(得分:1)

我无法从详细信息中了解到,但您是否将标签的父级设置为子面板?如果在设计时你可能需要在主要组件中编写代码(例如,面板所在的容器),要确定哪个子面板正在接受该组件,并将标签父属性设置为该子面板。

我非常确定在添加或从其他组件中删除组件时会调用通知方法,这可以帮助您找到放置代码所需的位置。

答案 2 :(得分:0)

我这样做了,但最终用常规面板替换了控件,这些面板会在需要时显示/隐藏。

而不是从TPanel下降,我的控件从TCustomControl下降。我不认为我可以让它从TPanel下降,但不记得是什么问题。

容器控件:

TPageControl = class(TCustomControl)
private
  PageList:TObjectList;  // To hold references to all sub-pages for easy access.
end;

constructor TPageControl.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptsControls];
  PageList := TObjectList.Create;
  PageList.OwnsObjects := false;
end;

destructor TVstPageControl.Destroy;
begin
  PageList.Free;
  inherited;
end;

procedure TPageControl.NewPage;
var
  Page:TPage;
begin
  Page := TPage.Create(Self.Owner);
  Page.Parent := Self;
  Page.Align := alClient;

  PageList.Add(Page);
end;

procedure TPageControl.DeletePage(Index:integer);
var
  Page:TPage;
begin
  Page := PageList[Index] as TPage;
  Page.Free;
  PageList.Delete(Index);
end;

页面/子面板控件:

TVstPage = class(TCustomControl)
public
  constructor Create(AOwner: TComponent); override;
end;

constructor TPage.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptsControls];
end;