I’m writing a Delphi expert. I need to be able to write a value to a property on a property which is an object. E.g. I have a GroupBox on the form and I want to edit the Margins.Left property. I’m using the following procedure to do it but if gives an AV on the marked line.
The procedure takes a component from the (property editor) the property name (eg ‘Margins.Left’) and the new value, parses out the property name, fetches the object, reads the current value and attempts to change it if different. It then calls a method to log any changes.
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 are all Integer properties, not Int64 properties, so you need to use GetOrdProp/SetOrdProp to read and modify them.
SetInt64Prop assumes it’s a 64-bit property, and tries calling the property setter function with a 64-bit parameter. As the property setter is expecting a 32-bit parameter, it fails to clean up the stack properly and thus causes the AV on return.
You can tell which functions to call according to the PropIsType call.
Get/SetOrdProp functions can also be used for Char and WideChar properties, which I guess is why the name isn’t 100% obvious.