我正在写一位 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;
最佳答案
Margins.xyzzy 都是 Integer 属性,而不是 Int64 属性,因此需要使用 GetOrdProp/SetOrdProp 来读取和修改它们。
SetInt64Prop 假定它是 64 位属性,并尝试使用 64 位参数调用属性 setter 函数。由于属性 setter 需要 32 位参数,因此它无法正确清理堆栈,从而导致 AV 返回。
你可以根据PropIsType调用来判断要调用哪些函数。
- tkInt64:获取/设置Int64Prop
- tkInteger:获取/设置OrdProp
Get/SetOrdProp 函数也可用于 Char 和 WideChar 属性,我猜这就是为什么该名称不是 100% 显而易见的原因。
关于Delphi OTA 和 RTTI 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/143938/