2009-08-19 8 views
4

Mon application a plusieurs modules, chacun dans un onglet sur la mainform. Lorsque vous utilisez une boîte de dialogue, il est pratique d'appeler ShowModal car vous savez quand la boîte de dialogue est terminée. Mais pour l'utilisateur ce n'est pas bon car cela verrouille tout le programme jusqu'à ce que la boîte de dialogue se ferme.Faux dialogue modal en utilisant Afficher?

Je veux avoir un dialogue modal local. Ainsi, un module peut ouvrir une boîte de dialogue et verrouille uniquement le module en cours. L'utilisateur peut toujours passer à un autre module et continuer à travailler. Si l'utilisateur revient au premier module, la boîte de dialogue attend d'être fermée avant que l'utilisateur puisse continuer à travailler dans ce module.

Je dois créer une sorte de cadre pour cela que tous les dialogues dans l'application peuvent utiliser. J'ai un baseclass pour toutes les boîtes de dialogue TAttracsForm et je pense que voici l'endroit où ajouter ma méthode Show().

Ceci devrait bloquer l'accès à tous les contrôles de ligne uniquement dans le module en cours. Il devrait simuler un appel à ShowModal(). Comment puis-je atteindre cet objectif ?

Cordialement

Répondre

1

J'ai pratiquement implémenté des boîtes de dialogue modales locales maintenant. Il est construit autour de cela lorsqu'une propriété TForms Enabled est définie sur False, le formulaire entier est verrouillé à partir de l'entrée. Et mes modules sont juste un descendant de TForm.

Ma classe ViewManager qui décide quels modules sont des modules d'ajout/de fermeture courants, etc. a obtenu 2 nouvelles méthodes. LockCurrentView et 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 est la base de toutes les boîtes de dialogue.Je remplace FormClose et ajoute une nouvelle méthode ShowLocalModal à appeler au lieu de ShowModal. Je dois également ajouter un TNotifyEvent OnAfterDestruction à appeler lorsque la boîte de dialogue est fermée.

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; 

Certains tests avec des boîtes de dialogue simples semblent prometteurs. Ainsi, le module doit simplement appeler ShowLocalModal (myMethod) qui a un paramètre TNotifyEvent. Cette méthode est appelée lorsque la boîte de dialogue est fermée.

2

Vous devrez effectuer les opérations suivantes:

  1. Avoir une identité pour chaque module
  2. un drapeau qui est actif ou inactif pour chaque module
  3. Avoir un drapeau stocke la modalité du dialogue joint. Si elle est modale et que le module est actif, appelez la méthode show dans le gestionnaire d'événement approprié. N'oubliez pas de mettre à jour ces valeurs dans les événements onshow et onclose de chaque boîte de dialogue.

Vous devrez peut-être affiner cette suggestion jusqu'à ce que vous obteniez la fonctionnalité exacte dont vous avez besoin.

+0

Je me rends compte que certaines propriétés doivent être ajoutées dans le dialogue et le module. Oublions ça pour un moment. Mais le problème principal est comment puis-je désactiver localement tous les composants de mon module pendant que la boîte de dialogue est affichée. C'est une mauvaise solution de les boucler simplement parce qu'ils sont tellement nombreux. –

+1

Selon le type de contrôle contenu dans vos contrôles, vous devriez pouvoir désactiver le parent. Par exemple, si vos composants sont tous sur une feuille TTabSheet, la désactivation de la feuille TTabSheet empêche l'accès à tous ces contrôles. –

+1

J'ai juste une autre idée. Puis-je simplement définir la propriété Enabled sur False du module (qui hérite de TForm) pour verrouiller tous les composants? Un test rapide semble prometteur :) –

2

Voulez-vous toujours l'implémenter avec la métaphore «vous savez quand la boîte de dialogue est terminée»? Donc, comme

DoSomethingBeforeDialog(); 
Form:=TFakeFormDialog.Create(Nil); 
try 
    Form.FakeShowModal(); 
finally 
    Form.Free; 
end; 
DoSomethingAfterDialog(); 

si la réponse est oui, vous essayez de mettre en œuvre ce avec des fils, comme Google Chrome faire avec les pages de l'onglet. Mais sans fils que vous pouvez attraper le traitement des messages avec un code comme celui-ci

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; 

Et vous avez même le code ci-dessous ...

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; 

appelés temps de multiplication de vos onglets, mais le problème est le ces Les "boîtes de dialogue" doivent être fermées dans "l'ordre de la pile", c'est-à-dire inverser l'ordre dans lequel elles ont été affichées. Je pense qu'il est impossible de forcer les utilisateurs à fermer les formulaires dans l'ordre de préférence des développeurs :)

Questions connexes