Как создать настраиваемый элемент управления с помощью вспомогательной панели, которая принимает другие элементы управления во время разработки?
Я написал пользовательский элемент управления, который имеет несколько подпанелей. Я хочу, чтобы эти вспомогательные панели принимали любые дополнительные элементы управления, добавленные на них во время разработки.
К сожалению, любой элемент управления, который теряется во время разработки, оказывается на моем пользовательском элементе управления, а не на панелях. Это показывает, в частности, если я пытаюсь сбросить метку: отображаются синие точки метки, но заголовок отсутствует, а если я отменил выбор метки, она больше не видна.
упрощенный код (только одна подпанель):
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 ответа
Это хороший вопрос. Вы можете позволить своему пользовательскому TWinControl добавлять другие элементы управления во время разработки, добавляя csAcceptControls к свойству ControlStyle элементов управления.
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;
Используя этот код, вы теперь можете перетаскивать элементы управления на вспомогательную панель, но это означает, что вы также можете выбрать вспомогательную панель, изменить ее свойства и даже удалить ее, которую вы определенно не хотите. Извините, я не смог придумать ответ, я все равно хотел бы знать, решите ли вы его.:)
Я не могу сказать по деталям, но вы устанавливаете родительский ярлык для вашей под-панели? Если это во время разработки, вам может потребоваться написать код в вашем основном компоненте (например, контейнере, в котором находятся ваши панели), чтобы выяснить, какая субпанель принимает компонент и установить родительское свойство меток для этой субпанели.
Я уверен, что метод уведомления вызывается, когда компонент добавляется или удаляется из другого компонента, это должно помочь вам отследить, куда вам нужно поместить код.
Я сделал это, но в итоге заменил элементы управления обычными панелями, которые при необходимости показывались бы / скрывались.
Вместо того, чтобы опускаться из 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;