1

我正在尝试创建一个控件,它在设计时和运行时创建 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.

有没有人可以向我展示一种为我的任务找到解决方案的方法?
提前致谢。

4

3 回答 3

3

这可以通过多种方式实现,具体取决于您的具体愿望。因为您的代码确实只显示了面板的创建,所以我假设您需要非常基础的知识,然后才能意识到您的愿望到底是什么,但是对于新手组件构建器来说,基础知识可能有点困难。

首先:对于在对象检查器中可编辑的东西,它必须是一个组件或者是一个组件的(部分)已发布属性。现在,您的面板只是私有字段。因此,您可以尝试在属性中发布您的面板。或者,您可以为所有面板添加一个属性,该属性将由选定的索引属性进行区分。

您还可以通过将面板添加为单独的组件来模仿页面控制组件。在这种情况下,您可能需要在其上下文菜单中为“新页面”命令添加组件编辑器。

一些注意事项: 不需要该控件样式设置,除非通过设计器将组件设置为其他控件的父级。此外,您的析构函数是多余的。

然后尝试问一个非常具体的组件写作问题。

于 2016-02-29T20:39:37.657 回答
3

如果您想允许用户在设计时实际单击其中一个面板(或任何其他子控件,就此而言),您的主要组件需要处理该CM_DESIGNHITTEST消息并为任何鼠标坐标返回一个非零值属于所需的子控件。消息在其lParam字段中包含鼠标坐标(您可以将消息作为TWMMouse记录接收,其中有一个Pos字段,您可以TPoint使用该SmallPointToPoint()函数将其转换为一个字段)。

于 2016-02-29T20:51:36.180 回答
0

我的问题有一个解决方案。
我们需要使用 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.
于 2016-03-03T18:26:50.723 回答