Hey guys, I'm fairly new to Lazarus with 14 years Delphi experience. FYI I don't currently have internet at home so forgive me if I don't reply quickly, I try to ensure I check emails etc at least a few times a week.
I seem to have a bit of an issue with some intermediate level features.
I've build an object hierarchy which uses interfaces and self draws to a canvas.
This isn't functional code, I'm just writing it out with a touch of copy/paste, but it should illustrate what's going on, forgive me for not writing out all object properties etc, the ones you see used are there in the real interface definition
unit Fake;
interface
type
TMyCustomObject = class(TInterfacedObject, IQRectDrawable, IQMultiView, IQExplosive,
IQThemeable, IQHitable);
//IQHitable Methods
function HitTest(x,y: Integer): Boolean;
function HitObject(x,y: Integer): TObject;
end;
TMyForm = class(TForm)
fvSelObject: TObject;
imgCanvas: TImage;
actMinimize: TAction;
actLess: TAction;
procedure imgCanvasMouseDown(Params shown in declaration);
procedure actSASMinLessUpdate(Sender: TObject);
end;
function TMyCustomObject .HitTest(x, y: Integer): Boolean;
var
lvHitRect: TRect;
begin
lvHitRect := FSizeRect;
MoveRect(lvHitRect,FDrawPos.x,FDrawPos.y);
Result := (x >= lvHitRect.Left) and (x <= lvHitRect.Right)
and (y >= lvHitRect.Top) and (y <= lvHitRect.Bottom);
end;
function TMyCustomObject .HitObject(x, y: Integer): TObject;
var
lvHitRect: TRect;
begin
Result := nil;
if HitTest(x,y) then
begin
lvHitRect := SetRect;
MoveRect(lvHitRect,FDrawPos.x,FDrawPos.y);
if (x >= lvHitRect.Left) and (x <= lvHitRect.Right)
and (y >= lvHitRect.Top) and (y <= lvHitRect.Bottom) then
Result := Self
else
begin
Result := FStorageTypes.HitObject(x,y);
if Result = nil then
Result := FDatabases.HitObject(x,y);
if Result = nil then
Result := FSystems.HitObject(x,y);
end;
end
else Result := nil;
end;
procedure TMyForm .imgCanvasMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
i: Integer;
lvSys: TSelfAwareSystem;
begin
fvSelObject := nil;
for i := 0 to Pred(fvSystemSets.Count) do
begin
lvSys := TSelfAwareSystem(fvSystemSets.Objects[i]);
if lvSys.HitTest(x,y) then
fvSelObject := lvSys.HitObject(x,y);
end;
end;
procedure TMyForm .actSASMinLessUpdate(Sender: TObject);
var
lvIQMV: IQMultiView;
begin
if Sender is TAction then
begin
if Assigned(fvSelObject) and (fvSelObject is TInterfacedObject) then
if TInterfacedObject(fvSelObject).GetInterface(GUID_IQMultiView,lvIQMV) then
TAction(Sender).Enabled := lvIQMV.LessPossible
else TAction(Sender).Enabled := False
else TAction(Sender).Enabled := False;
end;
end;
So the problems I'm getting are in the update events for the actions.
Everything appears to go through OK but the variable fvSelObject is only evaluating as a TInterfacedObject the first time I click on it and even so the call to GetInterface returns false. On the second click the object returns itself the same as the first time since it has no child objects yet but the check on (fvSelObject is TInterfacedObject) no longer comes back true and the debug code insight is different, showing only a vPtr memory reference rather than the object structure even though the memory address shown is the same in both scenarios.
I'll be proceeding to work around this by making the implementation less generic, though continuing down that path long term would invalidate the point of having designed a generic structure in the first place.
If this rings any bells with anyone I'd love to know if there's something I can do to get interfaces working with more generic holder objects. I've had no problems using them from correctly typed objects but that shouldn't be necessary when you should be able to do a check on whether the object is a TInterfacedObject and call GetInterface.
FYI the system I'm designing will be available for use on a open source inspired licence eventually. As much as I love open source we really need a system where programs can share source with authorized members and those devs can get paid based on their contributions if/when the product makes money as well. I hate seeing so many great ideas fall by the wayside because they're not commercial.