Как выбрать подконтроль в моем пользовательском элементе управления во время разработки в 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.
Другие вопросы по тегам