Delphi OTA和RTTI bug

时间:2008-09-27 16:24:51

标签: delphi plugins rtti

我正在写一个Delphi专家。我需要能够在属性作为对象的属性上写入值。例如。我在表单上有一个GroupBox,我想编辑Margins.Left属性。我正在使用以下程序来执行此操作,但如果在标记的行上给出了AV。

该过程从(属性编辑器)获取属性名称(例如'Margins.Left')的组件和新值,解析属性名称,获取对象,读取当前值并尝试更改它不同。然后它调用一个方法来记录任何更改。

procedure EditIntegerSubProperty(Component: IOTAComponent;const PropName: String;NewValue: Integer);
var AnObject: TObject;
  TK: TTypeKind;
  At: Integer;
  AClassName, APropName: String;
  PropInfo: PPropInfo;
  OldValue: Integer;
begin
  At := Pos('.', PropName);
  if At < 1 then
  raise Exception.Create('Invalid SubProperty Name: '+PropName);

  AClassName := Copy(PropName, 1, At-1);
  APropName := Copy(PropName, At+1, length(PropName));

  TK := Component.GetPropTypeByName(AClassName);
  if TK <> tkClass then
    EXIT;

  AnObject := GetObjectProp((Component as INTAComponent).GetComponent, AClassName);
  if PropIsType(AnObject, APropName, tkInteger) then
  begin
    OldValue := GetInt64Prop(AnObject, APropName);
    if OldValue <> NewValue then
    begin
      SetInt64Prop(AnObject, APropName, NewValue);  <----AV HERE
      ChangeLogInteger(Name, PropName, OldValue, NewValue);
    end;
  end;
end;

2 个答案:

答案 0 :(得分:3)

您是否尝试使用GetOrdProp,SetOrdProp而不是GetInt64Prop,SetInt64Prop?

答案 1 :(得分:3)

Margins.xyzzy都是Integer属性,而不是Int64属性,因此您需要使用GetOrdProp / SetOrdProp来读取和修改它们。

SetInt64Prop假设它是64位属性,并尝试使用64位参数调用属性setter函数。由于属性设置器需要32位参数,因此无法正确清理堆栈,从而导致AV返回。

您可以根据PropIsType调用确定要调用的函数。

  • tkInt64:Get / SetInt64Prop
  • tkInteger:Get / SetOrdProp

Get / SetOrdProp函数也可以用于Char和WideChar属性,我猜这就是为什么这个名字不是100%明显的。