Bleh... bugs DO exist
In TPowerDraw.Destroy, you call Finalize.
Finalize calls DoneDevice which executes the handler and so forth.
Usually this is no problem, but for my program, I have to Finalize Powerdraw already in the OnDestroy handler of my form myself, because I have a few helperclasses which PowerFont's and Imagelists rely on TPowerDraw and as you know those need to know about the DoneDevice event. So I called the proper method in my helperclasses to ensure everything was finalized properly.
Then I got an AV. What went wrong? Your TPowerDraw.Destroy calls Finalize. Finalize in turn, calls DoneDevice. Finalize nor DoneDevice performs any checking whatsoever if the device has already been 'done'. So in the second line of the TPowerDraw.DoneDevice my event handler was called again. Only, this time, all my objects were already freed. After some debugging I found this workaround:
[pascal]
procedure TMForm.FormDestroy(Sender: TObject);
begin
PowerDraw.Finalize; {<-- this line HAS to be here! }
while FSceneList.Count > 0 do
begin
TObject(FSceneList[0]).Free;
FSceneList.Delete(0);
end;
FSceneList.Free;
FResourceKeeper.Free;
FConfigManager.Free;
end;
...
procedure TMForm.PowerDrawDoneDevice(Sender: TObject);
var
i: Integer;
begin
{ The next line guards us against a nasty AV caused by a double call
to DoneDevice without checking if the device was already done }
if not PowerDraw.DeviceActive then
Exit;
{ First notify scenes }
for i := 0 to FSceneList.Count - 1 do
begin
TScene(FSceneList[i]).DoneDevice;
end;
{ Now, notify Resource Keeper }
FResourceKeeper.DoneDevice;
end;
[/pascal]
Sorry about the long explanation, tried to explain as well as I could. Anyway.. I hope this might help some people who get a nasty AV like me
[Edit]After some thinking, I think Finalize needs an extra check on FInitialized and DoneDevice on FDeviceActive. This way, it's supersafe [/Edit]
Bookmarks