Bonjour à tous,
Je vais aller droit au but. J'ai une application dont l'architecture se résume à :
- Une TForm principale avec un menu, une toolbar etc, qui sert de conteneur
- Une dizaine d'écrans héritant de TFrame qui viennent s'intégrer dans cette fenêtre principale
On affiche les différents écrans via le menu de la fenêtre.
Ce que je veux faire :
- Disposer d'un moyen de reset l'écran en cours (le Free, puis le Create). Vider tous les champs etc ne m’intéresse pas. Je cherche un moyen générique que je peux appliquer à toutes mes frames, et éventuellement, plus globalement, à n'importe quel objet.
Ma solution actuelle :
- Dans la fiche de ma fenêtre principale, j'ai une variable par TFrame.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 type TFormMain = class(TForm) {...} end; var frameControl : TFrameControl; frameConfig : TFrameConfig;
- J'ai une procedure FenetrePrincipale.resetEcran(Sender : TObject)
Dans cette procedure, je viens tester la classe de Sender (TFrameControl, TFrameConfig ...)
puis en fonction de la classe de Sender, j'apelle la même procedure que pour pop simplement mon écran :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 procedure TFenetrePrincipale.ResetEcran(Sender: TObject); var mesClasses: TStringList; sourceClass: String; begin mesClasses := TStringList.Create; mesClasses.AddStrings(['TFrameControl', 'TFrameConfig']); sourceClass := (Sender as TFrame).ClassName; FreeAllFrames; //Méthode se chargeant de tenter un free sur tous mes écrans case mesClasses.indexOf(sourceClass) of 0: PopControl; 1: PopConfig; end; mesClasses.Free; end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 procedure TFenetrePrincipale.popConfig; begin //Crée l'instance si besoin if not Assigned(frameConfig) then frameConfig := TFrameConfig.Create(Self); //Place le frame dans la fenêtre principale frameConfig .Parent := Self; end;
Cette architecture est moche, pas modulable car ça me fait modifier ma fenêtre principale à chaque fois que je veux lui ajouter un écran. Et le nom des classes hardcodé etc ... Il me faut autre chose !
Après pas mal d'essai, j'ai pensé à la solution suivante, est-ce réalisable ou suis-je en train d'inventer la roue carré ?
- Ajouter à ma TFenetrePrincipale une property qui stocke l'écran affiché :
- Ajouter une property qui viendrai stocker le constructeur de la dernier frame pop
Code : Sélectionner tout - Visualiser dans une fenêtre à part property CurrentFrame : TFrame read FCurrentFrame write FCurrentFrame;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 type TProcedureCreate = procedure (AControl : TWinControl);L'affectation à se fait lors du la méthode popConfig (par ex)
Code : Sélectionner tout - Visualiser dans une fenêtre à part property LastCreate : TProcedureCreate read FLastCreate write FLastCreate;
Comme ça je peux avoir ma procedure de resetEcran qui devient tout bêtement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 procedure TFenetrePrincipale.popConfig; begin //Crée l'instance si besoin if not Assigned(frameConfig) then frameConfig := TFrameConfig.Create(Self); //Place le frame dans la fenêtre principale frameConfig .Parent := Self; LastCreate := @TFrameConfig.Create;//Ça compile end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 CurrentFrame.Free; CurrentFrame := LastCreate(Self);//Ça compile pas (type incompatible entre TFrame et pointer, procedure) CurrentFrame.Parent := Self;
Grâce à cette solution, je peux Free puis Create mon objet sans même connaitre sa classe. Qu'en pensez-vous ? Pourquoi ça ne compile pas ? Quelle solution auriez-vous adopté ?
PS : J'ai pas copié collé les bouts de code, juste réécrit en plus simple, ne m'en voulez pas si j'ai oublié quelque chose
Partager