Friday, December 19, 2008

Delphi Wizard Framework - SetAllowDeletion

In my previous posts about my wizard framework, I discussed some of the original design decisions, as well as how to perform simple forward navigation.

The Delphi Wizard Framework is currently being hosted by google code hosting, which I briefly reviewed in a previous post.

One of the problems that I ran into quickly after starting this system was the issue of displaying a wizard form that doesn't allow user input but is there to show the user that something is being performed, to please wait patiently. The wizard framework as it navigates from one form to another automatically adds the last form displayed to the deleted queue and sends itself a message which will free all the forms in the queue. This works great and performing cleanup, but can cause access violations if someone wants to do something like the following:

begin
fWizMgr.NavigateToPage('TStatuspage');
if not Supports(fWizMgr.CurrForm,IWizPerformStatus,StatusForm) then
raise Exception.Create('form does not support IWizPerformStatus');
for ix := 0 to 100 do
begin
StatusForm.DoWork(ix);
StatusForm.ShowProgress(ix);
Application.ProcessMessages;
end;
fWizMgr.NavigateToPage('TResultspage',false);
end;

Now the intentions here are good, but the second the ProcessMessages is handled by the system the form which is executing this code is going to be freed, which will ultimately generate an exception. The solution to this is to use the framework method SetAllowDeletion to delay the deletion of the current form until later. Using it the correct method of the above routine should look like the following:

begin
fWizMgr.SetAllowDeletion(false);
try
fWizMgr.NavigateToPage('TStatuspage');
if not Supports(fWizMgr.CurrForm,IWizPerformStatus,StatusForm) then
raise Exception.Create('form does not support IWizPerformStatus');
for ix := 0 to 100 do
begin
StatusForm.DoWork(ix);
StatusForm.ShowProgress(ix);
Application.ProcessMessages;
end;
fWizMgr.NavigateToPage('TResultspage',false);
finally
fWizMgr.SetAllowDeletion(True);
end;
end;

No comments: