How do I create a custom control with a sub-panel that accepts other controls at designtime? [duplicate]

自作多情 提交于 2019-11-30 09:50:54

This is a good question. You can allow your custom TWinControl to have other controls dropped on it at design-time by adding csAcceptControls to your controls ControlStyle property.

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

But in trying to work this out, I've had little success with being able to drop controls onto a sub panel within a custom control. Adding csAcceptControls to a sub panel's ControlStyle isn't enough. The cloest I've gotten is a hack to convince the sub panel it's being designed like so:

type
  TGiveMeProtected_Component = class(TComponent);

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

Using that code, you can now drop controls onto the sub panel, but it means you can also select the sub panel, change it's properties and even delete it which you definately don't want. Sorry I couldn't come up with the answer, I'd still love to know if you work it out. :)

I cant tell from the details, but are you setting the parent of the label to you sub panel? If its at design time you may need to write code in your main component (eg the container that your panels are in), to figure out which subpanel is accepting the component and set the labels parent property to that subpanel.

I'm pretty sure the a notification method gets called when a component is added or removed from another component, this should help you track down where you need to put the code.

I did this, but ended up replacing the controls with regular panels which would be shown/hidden when required.

Instead of descending from TPanel my controls descend from TCustomControl. I don't think I could get it to work descending from TPanel but can't remember what the issue was.

The container control:

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;

The page/sub-panel control:

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

constructor TPage.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptsControls];
end;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!