组件创建 - 如何将组件连接在一起?

10

我刚开始学习组件创建,并尝试使用Delphi提供的标准VCL创建一些自定义派生组件。

我认为我可以将两个组件混合在一起,创建一个单一的组件。以下是我目前所拥有的想法,我的想法是将TImage放置在TScrollBox中:

unit MyComponent;

interface

uses
  Windows,
  Classes, 
  Controls,
  Forms,
  ExtCtrls;

type
  TMyPanel = class(TScrollBox)
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TMyPanel]);
end;

{ TMyPanel }

constructor TMyPanel.Create(AOwner: TComponent);
var
  AImage: TImage;
begin
  inherited Create(AOwner);

  AImage := TImage.Create(AOwner);
  AImage.Align := alClient;
  AImage.Parent := Self;
end;

destructor TMyPanel.Destroy;
begin
  inherited;
end;

end.

如果我将上述内容编译并安装到一个程序包中,结果如下所示:

enter image description here

enter image description here

问题

我希望我的组件能够被注册为一个单一的组件。但是这个组件应该是TScrollBox和TImage的组合体。主要的组件将是TScrollBox,但是它现在应该也有TImage的属性和事件等访问权限。

例如,TMyPanel可以共享TImage和TScrollBox的属性:

  • AutoSize
  • BorderStyle
  • HorzScrollBar
  • ParentBackground
  • Picture
  • VertScrollBar

我认为完全编写一个新组件来实现上述行为会过于冗长,而且我真的不知道从何开始。如果可以实现这一点,您可以创建一些有趣的组件,将它们组合成一个组件,但保留它们的原始属性、方法和事件等。

这就是我想要在TScrollBox内部放置TImage的效果。

解决方案

Uwe Raabe的答案已经可以正常工作。TImage现在注册在TScrollBox中,但是看起来像一个组件。TImage的属性在对象检查器中显示为Image,这将显示TImage的属性:)


4
请注意,您必须将Self作为子组件的所有者。如果使用与TMyPanel相同的所有者,则会导致DFM污染和流媒体问题。 - NGLN
1
确实,你还没有弄对。请看我的更新答案。 - Uwe Raabe
+1 感谢 Uwe 提供示例。 - user1175743
并+1 NGLN为谨慎提示。 - user1175743
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
14

您应该将图像作为TMyPanel的子组件:SetSubComponent

更新:这里有一个示例

unit MyComponent;

interface

uses
  System.Classes,
  VCL.Controls,
  VCL.Forms,
  VCL.ExtCtrls;

type
  TMyPanel = class(TScrollBox)
  private
    FImage: TImage;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Image: TImage read FImage;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TMyPanel]);
end;

constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  FImage := TImage.Create(Self);
  FImage.SetSubComponent(true);
  FImage.Align := alClient;
  FImage.Parent := Self;
end;

destructor TMyPanel.Destroy;
begin
  inherited;
end;

end.

+1 感谢您的快速回复,我有一种感觉可能还有其他事情需要我去做。让我再仔细看看这篇文章。 - user1175743
2
我建议给子组件命名。现在对象检查器将显示 MyPanel. ,但它可以看起来像 _MyPanel.SubImage_。 - NGLN
谢谢你的建议NGLN,我会为TImage使用一个合适的名称。 - user1175743
嗨Uwe - 你设置了FImage.Parent:= Self,但有些人反对。你能对此发表评论吗?谢谢。 - Gabriel
1
@Altar,如果您不使用子组件方法,那将是正确的。子组件的父级关系不是由DFM系统处理,而是由外部组件处理。 实际上,在DFM中不存在子组件,只有其属性被编写为外部组件属性的一部分。 如果您省略设置父项,它根本不起作用。 - Uwe Raabe
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,