6

我写了一个自定义控件,它有几个子面板。我希望这些子面板能够接受在设计时放置在它们上面的任何附加控件。

不幸的是,在设计时删除的任何控件最终都会出现在我的自定义控件上,而不是面板上。如果我尝试删除标签,这尤其显示:标签的蓝点已显示,但标题未显示,如果我取消选择标签,则根本不再可见。

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

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。)

[编辑]

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

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

4

3 回答 3

2

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

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

但是在尝试解决这个问题时,我未能成功地将控件拖放到自定义控件中的子面板上。将 csAcceptControls 添加到子面板的 ControlStyle 是不够的。我得到的 cloest 是一个 hack,可以说服子面板它的设计是这样的:

type
  TGiveMeProtected_Component = class(TComponent);

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

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

于 2009-01-09T01:15:24.187 回答
1

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

我很确定当从另一个组件中添加或删除组件时会调用通知方法,这应该可以帮助您跟踪需要放置代码的位置。

于 2008-12-17T15:33:43.080 回答
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;
于 2010-07-27T13:48:15.807 回答