Delphi OTA和RTTI错误
时间:2020-03-06 14:49:37 来源:igfitidea点击:
我正在写一个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;
解决方案
我们是否尝试使用GetOrdProp,SetOrdProp代替GetInt64Prop,SetInt64Prop?
Margins.xyzzy都是Integer属性,而不是Int64属性,因此我们需要使用GetOrdProp / SetOrdProp读取和修改它们。
SetInt64Prop假定它是64位属性,然后尝试使用64位参数调用属性设置器函数。由于属性设置程序期望使用32位参数,因此无法正确清理堆栈,从而导致AV返回。
我们可以根据PropIsType调用确定要调用的函数。
- tkInt64:获取/设置Int64Prop
- tkInteger:获取/设置OrdProp
Get / SetOrdProp函数也可以用于Char和WideChar属性,我想这就是为什么名称不是100%明显的原因。