Как выбрать подконтроль в моем пользовательском элементе управления во время разработки в Delphi
Я пытаюсь создать элемент управления, который создает 3 стандартных TPanel на себя во время разработки и выполнения. Все хорошо: управление создает панели отлично. Но я столкнулся с одной проблемой: во время разработки я хочу иметь возможность выбрать одну из панелей.
Я хочу воспроизвести стандартное поведение TPageControl: когда пользователь нажимает на TabSheet на экране, TabSheet становится редактируемым через инспектор объектов.
Ниже прилагается код моего контроля:
unit MyContainer;
interface
uses
Windows,
Messages,
SysUtils,
Classes,
Graphics,
Controls,
Forms,
StdCtrls,
ExtCtrls,
StrUtils,
Dialogs;
type
TMyContainer = class(TCustomControl)
private
FPanelA: TPanel;
FPanelB: TPanel;
FPanelC: TPanel;
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
procedure register;
implementation
{ TMyContainer }
procedure Register;
begin
RegisterComponents('MyComps', [TMyContainer]);
end;
constructor TMyContainer.Create(AOwner: TComponent);
begin
Inherited Create(AOwner);
Width := 200;
Height := 200;
ControlStyle := ControlStyle + [csAcceptsControls];
FPanelA := TPanel.Create(Self);
FPanelA.Parent := Self;
FPanelA.Width := 100;
FPanelA.Height := 60;
FPanelA.Left := 10;
FPanelA.Top := 10;
FPanelB := TPanel.Create(Self);
FPanelB.Parent := Self;
FPanelB.Width := 100;
FPanelB.Height := 60;
FPanelB.Left := 10;
FPanelB.Top := 80;
FPanelC := TPanel.Create(Self);
FPanelC.Parent := Self;
FPanelC.Width := 100;
FPanelC.Height := 60;
FPanelC.Left := 10;
FPanelC.Top := 160;
end;
destructor TMyContainer.Destroy;
begin
FreeAndNil(FPanelA);
FreeAndNil(FPanelB);
FreeAndNil(FPanelC);
Inherited Destroy;
end;
procedure TMyContainer.Paint;
begin
Canvas.Brush.Color := clBlue;
Canvas.FillRect(Canvas.ClipRect);
end;
end.
Есть ли кто-то, кто может показать мне способ получить решение для моей задачи?
Заранее спасибо.
3 ответа
Это может быть реализовано разными способами, в зависимости от ваших конкретных пожеланий. Поскольку ваш код показывает не что иное, как создание панелей, я предполагаю, что вам нужны самые основы, прежде чем вы сможете даже понять, какие именно ваши пожелания, но тогда основы могут быть немного сложными для начинающего компонента.
Прежде всего: для того, чтобы что-то было редактируемым в инспекторе объектов, оно должно быть компонентом или (частью) опубликованного свойства компонента. Прямо сейчас ваши панели - это просто частные поля. Таким образом, вы можете попытаться опубликовать свои панели в свойствах. Или вы можете добавить одно свойство для всех панелей, которое будет выделяться выбранным индексным свойством.
Вы также можете имитировать компонент управления страницей, добавляя панели как отдельные компоненты. В этом случае вам может понадобиться добавить редактор компонентов для команды "Новая страница" в его контекстном меню.
Некоторые примечания: Эта настройка стиля элемента управления не требуется, если только компонент не станет родителем других элементов управления с помощью дизайнера. Кроме того, ваш деструктор лишний.
Затем попробуйте задать очень конкретный вопрос о написании компонента.
Если вы хотите, чтобы пользователь мог фактически нажимать на одну из панелей во время разработки (или любой другой дочерний элемент управления, в этом отношении), ваш главный компонент должен обрабатывать CM_DESIGNHITTEST
сообщение и возвращает ненулевое значение для любых координат мыши, попадающих в требуемый дочерний элемент управления. Сообщение содержит координаты мыши в его lParam
поле (вы можете получить сообщение как TWMMouse
запись, которая имеет Pos
поле, которое вы можете превратить в TPoint
с использованием SmallPointToPoint()
функция).
Есть решение для моего вопроса.
Нам нужно использовать TComponentEditor, чтобы получить возможность создавать панели во время разработки, аналогично TPageControl. Спасибо пользователю NGLN за полезную ссылку.
Код ниже зарегистрируйте TComponentEditor для моего компонента (который был описан в вопросе).
unit MyEditor;
interface
uses
Classes,
SysUtils,
TypInfo,
StdCtrls,
ComCtrls,
ExtCtrls,
Dialogs,
ToolsAPI,
DesignIntf,
DesignEditors,
VCLEditors,
MyContainer; // our control
type
{>>>>>>>>>>>>>>>>>>>>>>>>>}
TMyContainerEditor = class(TComponentEditor)
private
procedure ExecuteVerb(Index: Integer); override;
function GetVerbCount: Integer; override;
function GetVerb(Index: Integer): string; override;
procedure Edit; override;
end;
{<<<<<<<<<<<<<<<<<<<<<<<<<}
procedure Register;
implementation
{ TMyContainerEditor}
procedure Register;
begin
RegisterComponentEditor(TMyContainer, TMyContainerEditor )
end;
procedure TMyContainerEditor.Edit;
begin
ShowMessage('TMyContainerEditor editor');
end;
procedure TMyContainerEditor.ExecuteVerb(Index: Integer);
var
Panel: TPanel;
begin
Inherited ExecuteVerb(Index);
case Index of
0:
ShowMessage('Design editor');
1:
begin
Panel:= TPanel.Create(Designer.Root);
Panel.Parent := Designer.Root;
Panel.Name := Designer.UniqueName('Panel');
Designer.SelectComponent(Panel);
Designer.Modified;
end;
end;
end;
function TMyContainerEditor.GetVerb(Index: Integer): string;
begin
case Index of
0: Result := 'Show info...';
1: Result := 'Add page';
end;
end;
function TMyContainerEditor.GetVerbCount: Integer;
begin
Result := 2;
end;
end.