Fake modal dialog using Show?

前端 未结 3 695
我寻月下人不归
我寻月下人不归 2020-12-17 04:19

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

相关标签:
3条回答
  • 2020-12-17 04:31

    You will have to do the following:

    1. Have an identity for each module
    2. Have a flag that is active or inactive for each module
    3. Have a flag that stores the modality of the attached dialog. If it is modal and the module is active, then call the show method in the appropriate eventhandler. Remember to update these values in the onshow and onclose events of each dialog.

    You may have to fine tune this suggestion till you achieve the exact functionality that you require.

    0 讨论(0)
  • 2020-12-17 04:48

    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 :)

    0 讨论(0)
  • 2020-12-17 04:57

    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.

    0 讨论(0)
提交回复
热议问题