delphi组件属性:TObjectList<;t图片>;

delphi组件属性:TObjectList<;t图片>;,delphi,vcl,Delphi,Vcl,我正在尝试创建一个VCL组件,它允许您插入多个不同大小的TIMAGE作为属性。 我被告知最好使用TObjectList(),但现在我正在努力使单个TPictures在属性编辑器中可分配 我现在拥有的:(它编译) 单元图像多状态; 接口 使用 图形、Vcl.StdCtrls、System.SysUtils、System.class、Vcl.Controls、Vcl.ExtCtrls、表单、泛型、集合; 类型 TImageMultiStates=类别(TImage) 私有的 照片:TObjectLi

我正在尝试创建一个VCL组件,它允许您插入多个不同大小的TIMAGE作为属性。 我被告知最好使用TObjectList(),但现在我正在努力使单个TPictures在属性编辑器中可分配

我现在拥有的:(它编译)

单元图像多状态;
接口
使用
图形、Vcl.StdCtrls、System.SysUtils、System.class、Vcl.Controls、Vcl.ExtCtrls、表单、泛型、集合;
类型
TImageMultiStates=类别(TImage)
私有的
照片:TObjectList;
过程SetPicture(其中:整数;顶点:TPicture);
函数GetPicture(其中:整数):TPicture;
公众的
计数:整数;
构造函数创建(AOwner:TComponent);推翻
毁灭者毁灭;推翻
程序激活(其中:整数);
出版
//属性图片:TObjectList读取GetPicture写入SetPicture;
//属性图片[索引:整数]:TObjectList读取GetPicture写入SetPicture;
属性图片:TObjectList读取FPictures写入FPictures;
结束;
程序登记册;
实施
构造函数timanagemultistates.Create(AOwner:TComponent);
开始
继承的创建(AOOwner);
FPictures:=TObjectList.Create;
结束;
毁灭者激励机制。毁灭;
开始
免费的;
继承性破坏;
结束;
过程TImageMultiStates.SetPicture(其中:整数;顶点:TPicture);
开始
F图片[其中]:=顶点;
如果哪个=0,那么
图片。分配(顶点);
结束;
函数TImageMultiStates.GetPicture(其中:整数):TPicture;
开始
结果:=FPictures[其中];
结束;
过程TImageMultiStates.Activate(其中:整数);
开始
图片分配(图片[其中]);
结束;
程序登记册;
开始
注册表组件(‘标准’,[TIMAGEMENTERSTATES]);
结束;
结束。
不起作用的是PropertyEditor中的最终结果。它显示一个名为“Pictures”的项目,其值为“(TObjectList)”。点击它没有任何作用,我找不到合适的编辑器。该行的其他想法已被注释掉,它们带来了其他错误:
第一个抛出编译器错误“E2008不兼容类型”,第二个抛出“发布的属性‘图片’不能是数组类型”。

IDE不知道如何在设计时编辑
TObjectList
,DFM流媒体系统也不知道如何流式处理
TObjectList
。您必须实现自定义属性编辑器和自定义流逻辑。虽然这当然是可能的,但需要做大量的工作

使用
System.Classes.TCollection
可以更好地处理您试图执行的操作。IDE和DFM流媒体系统都内置支持为您自动处理
t收集
编辑和流媒体

尝试类似以下内容:

unit ImageMultiStates;

interface

uses
  System.Classes, Vcl.Controls, Vcl.ExtCtrls, Vcl.Graphics;

type
  TImagePictureItem = class(TCollectionItem)
  private
    FPicture: TPicture;
    procedure PictureChanged(Sender: TObject);
    procedure SetPicture(Value: TPicture);
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
  published
    property Picture: TPicture read FPicture write SetPicture;
  end;

  TImagePictureEvent = procedure(Sender: TObject; Index: Integer) of object; 

  TImagePictures = class(TOwnedCollection)
  private
    FOnPictureChange: TImagePictureEvent;
    function GetPicture(Index: Integer): TImagePictureItem;
    procedure SetPicture(Index: Integer; Value: TImagePictureItem);
  protected
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(Owner: TComponent); reintroduce;
    property Pictures[Index: Integer]: TImagePictureItem read GetPicture write SetPicture; default;
    property OnPictureChange: TImagePictureEvent read FOnPictureChange write FOnPictureChange;
  end;

  TImageMultiStates = class(TImage)
  private
    FActivePicture: Integer;
    FPictures: TImagePictures;
    function GetPicture(Index: Integer): TPicture;
    procedure PictureChanged(Sender: TObject; Index: Integer);
    procedure SetActivePicture(Index: Integer);
    procedure SetPicture(Index: Integer; Value: TPicture);
    procedure SetPictures(Value: TImagePictures);
  protected
    procedure Loaded; override;
  public
    constructor Create(Owner: TComponent); override;
    function Count: integer;
    property Pictures[Index: Integer]: TPicture read GetPicture write SetPicture;
  published
    property ActivePicture: Integer read FActivePicture write SetActivePicture default -1;
    property Picture stored False;
    property Pictures: TImagePictures read FPictures write SetPictures;
  end;

procedure Register;

implementation

{ TImagePictureItem }

constructor TImagePictureItem.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  FPicture := TPicture.Create;
  FPicture.OnChange := PictureChanged;
end;

destructor TImagePictureItem.Destroy;
begin
  FPicture.Free;
  inherited;
end;

procedure TImagePictureItem.PictureChanged(Sender: TObject);
begin
  Changed(False);
end;

procedure TImagePictureItem.SetPicture(Value: TPicture);
begin
  FPicture.Assign(Value);
end;

{ TImagePictures }

constructor TImagePictures.Create(Owner: TComponent);
begin
  inherited Create(Owner, TImagePictureItem);
end;

function TImagePictures.GetPicture(Index: Integer): TImagePictureItem;
begin
  Result := TImagePictureItem(inherited GetItem(Index));
end;

procedure TImagePictures.SetPicture(Index: Integer; Value: TImagePictureItem);
begin
  inherited SetItem(Index, Value);
end;

procedure TImagePictures.Update(Item: TCollectionItem);
begin
  if Assigned(FOnPictureChange) then
  begin
    if Item <> nil then
      FOnPictureChange(Self, Item.Index)
    else
      FOnPictureChange(Self, -1);
  end;
end;

{ TImageMultiStates }

constructor TImageMultiStates.Create(Owner: TComponent);
begin
  inherited Create(Owner);
  FPictures := TImagePictures.Create(Self);
  FPictures.OnPictureChange := PictureChanged;
  FActivePicture := -1;
end;

procedure TImageMultiStates.Loaded;
begin
  inherited;
  PictureChanged(nil, FActivePicture);
end;

function TImageMultiStates.Count: Integer;
begin
  Result := FPictures.Count;
end;

procedure TImageMultiStates.PictureChanged(Sender: TObject; Index: Integer);
begin
  if (FActivePicture <> -1) and ((Index = -1) or (Index = FActivePicture)) then
    Picture.Assign(GetPicture(FActivePicture));
end;

function TImageMultiStates.GetPicture(Index: Integer): TPicture;
begin
  Result := FPictures[Index].Picture;
end;

procedure TImageMultiStates.SetPicture(Index: Integer; Value: TPicture);
begin
  FPictures[Index].Picture.Assign(Value);
end;

procedure TImageMultiStates.SetActivatePicture(Value: Integer);
begin
  if FActivePicture <> Value then
  begin
    if ComponentState * [csLoading, csReading] = [] then
      Picture.Assign(GetPicture(Value));
    FActivePicture := Value;
  end;
end;

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

  // the inherited TImage.Picture property is published, and you cannot
  // decrease the visibility of an existing property.  However, if you move
  // this procedure into a separate design-time package, you can then use
  // DesignIntf.UnlistPublishedProperty() to hide the inherited
  // Picture property at design-time, at least:
  //
  // UnlistPublishedProperty(TImageMultiStates, 'Picture');
  //
  // Thus, users are forced to use the TImageMultiStates.Pictures and
  // TImageMultiStates.ActivePicture at design-time.  The inherited
  // Picture property will still be accessible in code at runtime, though...
end;

end.
单元图像多状态;
接口
使用
系统类、Vcl.控件、Vcl.ExtCtrls、Vcl.图形;
类型
TImagePictureItem=类(TCollectionItem)
私有的
照片:t照片;
程序图片更改(发送方:TObject);
程序设置图片(值:t图片);
公众的
构造函数创建(集合:TCollection);推翻
毁灭者毁灭;推翻
出版
属性图片:TPicture read FPicture write SetPicture;
结束;
TImagePictureEvent=对象的过程(发送方:ToObject;索引:Integer);
TImagePictures=类别(TOwnedCollection)
私有的
FOnPictureChange:TImagePictureEvent;
函数GetPicture(索引:整数):TImagePictureItem;
过程SetPicture(索引:整数;值:TImagePictureItem);
受保护的
程序更新(项目:t收集项目);推翻
公众的
构造函数创建(所有者:TComponent);重新引入;
属性图片[索引:整数]:TImagePictureItem read GetPicture write SetPicture;违约
PictureChange上的属性:TImagePictureEvent读取方PictureChange写入方PictureChange;
结束;
TImageMultiStates=类别(TImage)
私有的
事实图片:整数;
照片:TImagePictures;
函数GetPicture(索引:整数):t图片;
过程图片更改(发送方:TObject;索引:Integer);
程序SetActivePicture(索引:整数);
过程SetPicture(索引:整数;值:t图片);
程序设置图片(值:TImagePictures);
受保护的
加载程序;推翻
公众的
构造函数创建(所有者:TComponent);推翻
函数计数:整数;
属性图片[索引:整数]:t图片读取GetPicture写入SetPicture;
出版
属性ActivePicture:Integer read FActivePicture write SetActivePicture默认值-1;
物业图片存放不实;
属性图片:TImagePictures读取FPPictures写入SetPictures;
结束;
程序登记册;
实施
{TImagePictureItem}
构造函数TImagePictureItem.Create(集合:TCollection);
开始
继承创建(集合);
FPicture:=TPicture.Create;
FPicture.OnChange:=图片更改;
结束;
析构函数TImagePictureItem.Destroy;
开始
免费的;
继承;
结束;
程序TImagePictureItem.PictureChanged(发送方:ToObject);
开始
更改(假);
结束;
程序TImagePictureItem.SetPicture(值:TPicture);
开始
F图像分配(值);
结束;
{TImagePictures}
构造函数TImagePictures.Create(所有者:TComponent);
开始
继承创建(所有者,TImagePictureItem);
结束;
函数TImagePictures.GetPicture(索引:整数):TImagePictureItem;
开始
结果:=TImagePictureItem(继承的GetItem(索引));
结束;
过程TImagePictures.SetPicture(索引:整数;值:TImagePictureItem);
开始
继承的集合项(索引、值);
结束;
程序TImagePictures.Update(项目:TCollectionItem);
开始
如果已分配(FOnPictureChange),则
开始
如果项目为零,则
FOnPictureChange(自我、项目、索引)
其他的
Fonspicturechange(Self,-1);
结束;
结束;
{TImageMultiStates}
构造函数timanagemultistates.Create(所有者:TComponent);
贝吉
unit ImageMultiStates;

interface

uses
  System.Classes, Vcl.Controls, Vcl.ExtCtrls, Vcl.Graphics;

type
  TImagePictureItem = class(TCollectionItem)
  private
    FPicture: TPicture;
    procedure PictureChanged(Sender: TObject);
    procedure SetPicture(Value: TPicture);
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
  published
    property Picture: TPicture read FPicture write SetPicture;
  end;

  TImagePictureEvent = procedure(Sender: TObject; Index: Integer) of object; 

  TImagePictures = class(TOwnedCollection)
  private
    FOnPictureChange: TImagePictureEvent;
    function GetPicture(Index: Integer): TImagePictureItem;
    procedure SetPicture(Index: Integer; Value: TImagePictureItem);
  protected
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(Owner: TComponent); reintroduce;
    property Pictures[Index: Integer]: TImagePictureItem read GetPicture write SetPicture; default;
    property OnPictureChange: TImagePictureEvent read FOnPictureChange write FOnPictureChange;
  end;

  TImageMultiStates = class(TImage)
  private
    FActivePicture: Integer;
    FPictures: TImagePictures;
    function GetPicture(Index: Integer): TPicture;
    procedure PictureChanged(Sender: TObject; Index: Integer);
    procedure SetActivePicture(Index: Integer);
    procedure SetPicture(Index: Integer; Value: TPicture);
    procedure SetPictures(Value: TImagePictures);
  protected
    procedure Loaded; override;
  public
    constructor Create(Owner: TComponent); override;
    function Count: integer;
    property Pictures[Index: Integer]: TPicture read GetPicture write SetPicture;
  published
    property ActivePicture: Integer read FActivePicture write SetActivePicture default -1;
    property Picture stored False;
    property Pictures: TImagePictures read FPictures write SetPictures;
  end;

procedure Register;

implementation

{ TImagePictureItem }

constructor TImagePictureItem.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  FPicture := TPicture.Create;
  FPicture.OnChange := PictureChanged;
end;

destructor TImagePictureItem.Destroy;
begin
  FPicture.Free;
  inherited;
end;

procedure TImagePictureItem.PictureChanged(Sender: TObject);
begin
  Changed(False);
end;

procedure TImagePictureItem.SetPicture(Value: TPicture);
begin
  FPicture.Assign(Value);
end;

{ TImagePictures }

constructor TImagePictures.Create(Owner: TComponent);
begin
  inherited Create(Owner, TImagePictureItem);
end;

function TImagePictures.GetPicture(Index: Integer): TImagePictureItem;
begin
  Result := TImagePictureItem(inherited GetItem(Index));
end;

procedure TImagePictures.SetPicture(Index: Integer; Value: TImagePictureItem);
begin
  inherited SetItem(Index, Value);
end;

procedure TImagePictures.Update(Item: TCollectionItem);
begin
  if Assigned(FOnPictureChange) then
  begin
    if Item <> nil then
      FOnPictureChange(Self, Item.Index)
    else
      FOnPictureChange(Self, -1);
  end;
end;

{ TImageMultiStates }

constructor TImageMultiStates.Create(Owner: TComponent);
begin
  inherited Create(Owner);
  FPictures := TImagePictures.Create(Self);
  FPictures.OnPictureChange := PictureChanged;
  FActivePicture := -1;
end;

procedure TImageMultiStates.Loaded;
begin
  inherited;
  PictureChanged(nil, FActivePicture);
end;

function TImageMultiStates.Count: Integer;
begin
  Result := FPictures.Count;
end;

procedure TImageMultiStates.PictureChanged(Sender: TObject; Index: Integer);
begin
  if (FActivePicture <> -1) and ((Index = -1) or (Index = FActivePicture)) then
    Picture.Assign(GetPicture(FActivePicture));
end;

function TImageMultiStates.GetPicture(Index: Integer): TPicture;
begin
  Result := FPictures[Index].Picture;
end;

procedure TImageMultiStates.SetPicture(Index: Integer; Value: TPicture);
begin
  FPictures[Index].Picture.Assign(Value);
end;

procedure TImageMultiStates.SetActivatePicture(Value: Integer);
begin
  if FActivePicture <> Value then
  begin
    if ComponentState * [csLoading, csReading] = [] then
      Picture.Assign(GetPicture(Value));
    FActivePicture := Value;
  end;
end;

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

  // the inherited TImage.Picture property is published, and you cannot
  // decrease the visibility of an existing property.  However, if you move
  // this procedure into a separate design-time package, you can then use
  // DesignIntf.UnlistPublishedProperty() to hide the inherited
  // Picture property at design-time, at least:
  //
  // UnlistPublishedProperty(TImageMultiStates, 'Picture');
  //
  // Thus, users are forced to use the TImageMultiStates.Pictures and
  // TImageMultiStates.ActivePicture at design-time.  The inherited
  // Picture property will still be accessible in code at runtime, though...
end;

end.