【问题标题】:How do I group my component's properties in the Object Inspector?如何在对象检查器中对组件的属性进行分组?
【发布时间】:2012-03-15 02:52:45
【问题描述】:

我希望我的非可视组件将其发布的属性置于不在 Object Inspector 顶层的类别下。

举个例子:

type
  TMyComponent = class(TComponent)
  protected
    function GetSomeValue: string;
    function GetSomeValueExt: string;
  published
    property SomeValue: string read GetSomeValue;
    property SomeValueExt: string read GetSomeValueExt;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('My Component', [TMyComponent]);
end;

function TMyComponent.GetSomeValue: string;
begin
  Result := 'test';
end;

function TMyComponent.GetSomeValueExt: string;
begin
  Result := 'extended..';
end;

如何让我的组件在名为 MyProperties 的类别下使用 SomeValue 和 SomeValueExt 在 Object Inspector 中注册?

插图:

我的组件可能有很多已发布的属性,我希望它们位于对象检查器的自己级别子类别下,以使其远离名称和标签等常见属性。

谢谢:)

【问题讨论】:

  • 您是在谈论对象检查器使用的类别术语吗?这就是您右键单击 OI 并选择“按类别查看”的功能。
  • 例如,您单击 TForm 或其他组件,某些属性位于 Anchors、BorderIcons 和 Font 等类别下。如果有意义的话,我希望我的一些属性有自己的父级。
  • AnchorsBorderIcons 是集合。你不想要那个。 Font 属性是一个类。因此,您可以将子属性包装在一个类中,然后免费获得您想要的行为。
  • 所以我可以把 SomeValue 和 SomeValueExt 放在自己的类中,它是 TMYComponent 的父类,对吗?
  • 然后将屏幕截图替换为说明类别视图的屏幕截图。或者,我们没有得到您真正想要的 XY。

标签: delphi custom-component


【解决方案1】:

创建一个具有这些属性的类,然后为您的组件提供该类类型的单个属性。属性类应该是 TPersistent 后代:

type
  TComponentProperties = class(TPersistent)
  private
    function GetSomeValue: string;
    function GetSomeValueExt: string;
  published
    property SomeValue: string read GetSomeValue;
    property SomeValueExt: string read GetSomeValueExt;
  end;

  TMyComponent = class(TComponent)
  private
    FProperties: TComponentProperties;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Properties: TComponentProperties read FProperties;
  end;

组件拥有自己的属性对象,所以需要创建和销毁:

constructor TMyComponent.Create;
begin
  inherited;
  FProperties := TComponentProperties.Create;
end;

destructor TMyComponent.Destroy;
begin
  FProperties.Free;
  inherited;
end;

使用该代码,组件的属性现在应该列在“属性”项下。不过,它不是一个类别。类别完全是另一回事。类别不会重新排列组件;它们只是更改属性在对象检查器中的显示方式。请注意,在我的代码中,TMyComponent 不再具有任何 SomeValue 属性。相反,它只有一个属性Properties,而那个 对象还有其他属性。考虑这是否真的是您希望组件的使用者必须访问它的方式。


如果Properties属性不是只读的,那么它需要有一个属性设置器;你不能让它直接写给FProperties。像这样写:

procedure TMyComponent.SetProperties(const Value: TProperties);
begin
  FProperties.Assign(Value);
end;

这也要求您重写 Assign 方法来做正确的事情:

procedure TComponentProperties.Assign(Other: TPersistent);
begin
  if Other is TComponentProperties then begin
    SomeValue := TComponentProperties(Other).SomeValue;
    SomeValueEx := TComponentProperties(Other).SomeValueEx;
  end else
    inherited;
end;

我们还假设属性对象的属性也不是只读的。当属性对象的属性发生变化时,拥有对象可能想知道它,因此它应该有一个事件,组件为其赋值。当属性发生变化时,它们会触发事件。

【讨论】:

  • 感谢您提供的信息,我感觉类别可能无法最好地解释这一点。我将 Delphi 用于个人用途,因此不会有其他人真正使用我的组件,但如果将来有人使用它,总是值得考虑的。谢谢:)
  • 当我说“你的组件的消费者”时,那包括你。 想一直输入Properties.SomeValue吗?
  • 别担心我会去,给我机会检查一下,确保我先理解它! :)
  • @RobKennedy 属性将是只读的,但再次感谢您提供这些额外信息 - 如果我需要写入属性,它将很有用。我刚刚尝试过这个,它按我希望的那样工作,实际上它看起来比我想象的要简单得多 - 这要归功于一个写得很好的例子和易于理解的信息。
  • 我对此表示怀疑,@Mjn。它不是一个组件。此外,如果需要,退休是新的; Delphi 2005 不需要那个。
猜你喜欢
  • 2021-11-25
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多