My application have several modules, each in one tab on the mainform. When using a dialog it is convenient to call ShowModal because you know when the dialog is finished. Bu
You will have to do the following:
You may have to fine tune this suggestion till you achieve the exact functionality that you require.
Do you still want to implement this with "you know when the dialog is finished" metaphor? So like
DoSomethingBeforeDialog();
Form:=TFakeFormDialog.Create(Nil);
try
Form.FakeShowModal();
finally
Form.Free;
end;
DoSomethingAfterDialog();
if the answer is yes, you would try to implement this with threads, like Google Chrome do this with tab pages. But without threads only you can catch message processing with a code like this
function TFakeModalDlg.FakeShowModal(FormParent: TWinControl): boolean;
begin
Parent:=FormParent;
SetBounds((FormParent.Width - Width) div 2, (FormParent.Height - Height) div 2,
Width, Height);
Show;
while NoButtonIsPressed() do
begin
Application.HandleMessage;
end;
Hide;
end;
And you even have code below...
Form:=TFakeModalDlg.Create(Nil);
try
(Sender as TButton).Caption:='Going modal...';
Form.FakeShowModal(TabSheet1);
(Sender as TButton).Caption:='Returned from modal';
finally
Form.Free;
end;
called multiply times from your tabs, but the problem is the these "dialogs" should be closed in "stack order" i.e. reverse to the order they were showed. I think it's impossible to force users to close forms in developers preference order :)
I have actually almost implemented local modal dialogs now. It is built around that when a TForms Enabled property is set To False the whole Form is locked from input. And my modules is just a descendant from TForm.
My ViewManager class that decide what modules is current add/close modules etc got 2 new methods. LockCurrentView and UnLOckCurrentView.
function TViewManager.LockCurrentView: TChildTemplate;
begin
Result := CurrentView;
Result.Enabled := False;
Result.VMDeactivate; // DeActivate menus and toolbas for this module
end;
procedure TViewManager.UnLockCurrentView(aCallerForm: TChildTemplate);
begin
aCallerForm.VMActivate; // Activate menus and toolbas for this module
aCallerForm.Enabled := True;
end;
TAttracsForm is the baseclass of all dialogs. I Override FormClose and add a new method ShowLocalModal to call instead of ShowModal. I also have to add a TNotifyEvent OnAfterDestruction to be called when the dialog is closed.
procedure TAttracsForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if Assigned(fCallerForm) then
begin
ClientMainForm.ViewManager.UnLockCurrentView(fCallerForm as TChildTemplate);
if Assigned(OnAfterDestruction) then
OnAfterDestruction(Self);
Action := caFree;
end;
end;
{ Call to make a dialog modal per module.
Limitation is that the creator of the module must be a TChildtemplate.
Several modal dialogs cannot be stacked with this method.}
procedure TAttracsForm.ShowLocalModal(aNotifyAfterClose: TNotifyEvent);
begin
fCallerForm := ClientMainForm.ViewManager.LockCurrentView; // Lock current module and return it
PopupParent := fCallerForm;
OnAfterDestruction := aNotifyAfterClose;
Show;
end;
Some test with simple dialogs looks promising. So the module just have to call ShowLocalModal(myMethod) which have a TNotifyEvent as parameter. This method is called when the dialog is closed.