2

我有一个用于编辑属性的属性编辑器(TPropertyEditor 的后代)。

当需要编辑我的属性时,我怎么知道我正在编辑什么对象的哪个属性?如果我要编辑一个属性,我必须知道我正在编辑什么属性。

我一直在努力筛选 Delphi 帮助、在线帮助以及 TPropertyEditor 和后代源代码,但我找不到答案。

我期待的是:

TPropertyEditor = class(...)
public
    procedure Initialize(TheObject: TObject; ThePropertyName: string);
end;

据我所知,我的属性编辑器已创建,我将被告知“编辑”,我只需要猜测他们希望我编辑的属性。


从帮助:

整体编辑属性

您可以选择提供一个对话框,用户可以在其中直观地编辑属性。属性编辑器最常见的用途是用于本身就是类的属性。一个例子是字体属性,用户可以打开一个字体对话框来一次选择字体的所有属性。

要提供整体属性编辑器对话框,请覆盖属性编辑器类的 Edit方法。

编辑方法使用与编写 GetValueSetValue方法相同的 Get 和 Set方法。实际上,Edit方法同时调用 Get 方法和 Set 方法。因为编辑器是特定类型的,所以通常不需要将属性值转换为字符串。编辑器通常处理“检索到的”值。</p>

当用户单击属性旁边的“...”按钮或双击值列时,对象检查器会调用属性编辑器的Edit 方法。

Edit方法的实现中,请执行以下步骤:

  1. 构建您用于属性的编辑器。
  2. 读取当前值并使用 Get 方法将其分配给属性。
  3. 当用户选择一个新值时,使用 Set 方法将该值分配给属性。
  4. 销毁编辑器。

回答

它被隐藏起来,没有记录,但我发现了如何。我正在编辑的属性:

TheCurrentValue := TMyPropertyThing(Pointer(GetOrdValue));

现在我有了值,我可以编辑它。如果我想用其他对象替换该属性:

SetOrdValue(Longint(TheNewValue));

完整代码:

创建一个继承自TClassProperty的属性编辑器:

TMyPropertyEditor = class(TClassProperty)
public
   procedure Edit; override;
   function GetAttributes: TPropertyAttributes; override;
end;

首先是家务,告诉Delphi的对象检查器我的属性编辑器会显示一个对话框,这会使属性旁边出现一个“...”:

function TMyPropertyEditor.GetAttributes: TPropertyAttributes;
begin
   //We show a dialog, make Object Inspector show "..."
   Result := [paDialog];
end;

接下来是实际工作。当用户单击“...”按钮时,对象检查器会调用我的Edit方法。我缺少的技巧是我调用了我的GetOrdValue方法。即使我的属性不是ordinal,您仍然可以使用它,并将生成的东西转换为对象:

procedure TMyPropertyEditor.Edit;
var
   OldThing: TMyPersistentThing;
   NewThing: TMyPersistentThing;
begin
   //Call the property's getter, and return the "object" i'm editing:
   OldThing:= TMyPersistentThing(Pointer(GetOrdValue));

   //now that i have the thing i'm editing, do stuff to "edit" it
   DoSomeEditing(OldThing);


   //i don't have to, but if i want to replace the property with a new object
   //i can call the setter:
   NewThing := SomeVariant(OldThing);
   SetOrdValue(Longint(NewThing));
end;
4

3 回答 3

4

如果我理解你的问题,你想知道你应该如何实际找到你需要编辑的值,特别是如果有问题的对象包含多个对象。答案是 IDE 会为您设置好,并且属性编辑器会在调用 Edit 时“预加载”。TPropertyEditor 带有一堆 GetValue 方法,您的 Edit 函数可以使用这些方法来检索值。或者,如果它不是这些类型之一(例如,如果它是从 TPersistent 派生的对象),那么您可以调用 GetOrdValue 并将结果转换为 TPersistent。

此外,您可能希望查看 JVCL 的 JvDsgnEditors 单元中的 TJvPersistentPropertyEditor 以用作基类。它为您提供了一些功能。

顺便说一句,如果你真的需要它,你可以使用 GetName 方法,它会给你属性的名称,但你通常不应该这样做。如果您从 TPropertyEditor 本身以外的其他东西继承,请小心,因为 GetName 是虚拟的并且可以被覆盖。

于 2010-01-04T05:28:49.243 回答
3

属性编辑器将有关它正在编辑的对象和属性的信息保存在私有FPropList变量中。IDE 通过调用编辑器的SetPropEntry方法来填充它。然后,您通常应该调用各种方法TPropertyEditor来找出属性的值。

您被要求编辑哪个属性并不重要。您的属性编辑器编辑特定类型的属性。对于就地编辑,您的编辑器提供了一个实现,SetValue它将来自 Object Inspector 的字符串转换为属性的正确类型的值,然后您调用适当的Set函数,例如SetOrdValueor SetIntfValue。对于整体属性编辑,IDE 不会调用SetValue. 相反,它将调用Edit,并且您应该调用GetOrdValueor GetIntfValue(例如)您自己,因为您的编辑器已经知道它旨在编辑什么类型的属性。

请记住,属性编辑器通常可以同时编辑多个属性。它们的属性名称相同,但它们所属的组件类型可能不同,因此它们的 getter 和 setter 也可能不同。调用您的属性编辑器的GetName方法来找出名称。要获取对象,请调用GetComponent从 0 到 - 1 的每个索引PropCount。(小心;这些Get函数中没有范围检查。)您还可以通过调用来检查特定对象是否在列表中HasInstance。该GetPropInfo方法将告诉您第一个PPropInfo属性的指针,但我认为它不一定等于所有其他属性的指针。除此之外,您无法直接访问PPropInfo数据,但同样,这真的不重要。如果您认为您的编辑器需要它,那么您可能做错了什么;发布一个新问题,其中包含有关您的基础任务的更具体信息。

于 2010-01-04T06:18:32.153 回答
2

属性编辑器只关心(并注册)属性的类型,而不是特定的属性本身。

于 2010-01-04T04:03:28.760 回答