Bonjour,
Je reprends la maintenance d’une appli qui commence sérieux à me faire ……..bip LOL
Je rencontre de grosses difficultés pour rendre générique une procédure d’affichage de frames.
Je m’explique en détails (scuzzy pour la tartine )
J’ai une application composée d’une fenêtre Principal qui charge des frames dans un conteneur TPanel.
Mes frames héritent de plusieurs frames maisons. J’ai en tout une bonne cinquantaine de frames.
Pour expliquer mon problème j’ai simplifié tout çà pour vous l’exposer : j’ai une classe TFrmModele qui hérite de TFrame.
Je crée ensuite plusieurs frames filles qui héritent de TFrmModele : FrEcran1, FrEcran2, FrEcran3
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 type TFrmModele = class(TFrame) PanelTitre: TPanel; Panel1: TPanel; BtnFermer: TButton; procedure BtnFermerClick(Sender: TObject); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Afficher; virtual; procedure Fermer; end;
Chaque fenetre fille surcharge la procédure Afficher pour permettre la personnalisation de la Frame.
Rien d’exceptionnel.
Pour charger mes frames actuellement, j’ai cette simple procédure au niveau de la form Principal :
Pour tester ma procédure, j’ai simplement mis en place une procédure OnClick à partir de ma form Principal, que je teste avec plusieurs TButton
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
19
20
21 Var (public) MyFrame :TFrmModele ; implementation uses FrEcran1, FrEcran2, FrEcran3; procedure TFPrincipal.AfficherEcran(PMyEcran:string;PConteneur:TPanel); begin try FreeAndNil(MyFrame); if PMyEcran='FrEcran1' then MyFrame := TFrmEcran1.Create(self) else if PMyEcran='FrEcran2' then MyFrame := TFrmEcran2.Create(self) else if PMyEcran='FrEcran3' then MyFrame := TFrmEcran3.Create(self) else exit; MyFrame.Parent := PConteneur; MyFrame.Afficher; except on E: Exception do MessageDlg('Contacter l''administrateur :'#13#10+E.Message,mtError,[mbOk],0); end; end;
Jusque là c’est pas tip top, mais çà marche.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 //------------------------------------------------------------------------------ procedure TFPrincipal.MenuClick(Sender: TObject); begin if Sender = Button1 then AfficherEcran('FrEcran1',self.PanelFrame) else if Sender = Button2 then AfficherEcran('FrEcran2', self.PanelFrame) else if Sender = Button3 then AfficherEcran('FrEcran3', self.PanelFrame) else if Sender = Button4 then AfficherEcran('FrEcran4', self.PanelFrame) else Exit; end;
Le pb que je dois résoudre désormais est que mes frames doivent pouvoir s’appeler les unes les autres, et cela avec une seule procédure AfficherEcran
Je dois par exemple demander à partir de ma frame FrEcran1, l’ouverture de la frame FrEcran 2 et vice versa. Cela je souhaiterai réussir à la faire en appelant uniquement la procédure de ma forme principale (que je souhaiterai ensuite gérer dans une class TMyGesFrames)
J’ai donc repris le code ci-dessus, en m’orientant sur une TList qui se chargerait de stocker des types records
Ce que je cherche à faire, c’est parcourir ma Tlist à chaque demande de chargement d’une frame.
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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 type PMyFrame=^TMyFrame; TMyFrame=record MyFrameName:string; MyFrame:TFrmModele; end; //Nouvelle procédure AfficherEcran //------------------------------------------------------------------------------ procedure TFPrincipal.AfficherMyEcran(PMyEcran:string;PConteneur:TPanel); var PMyFrameModel:PMyFrame; PList:integer; Find:boolean; ClassRef:TClass; begin try Find:=false; //--FIND INSTANCE STOCKEE : function GetFrame à faire for PList:=0 to FMyListFrames.Count-1 do begin PMyFrameModel:=FMyListFrames.Items[PList]; if PMyFrameModel^.MyFrameName=PMyEcran then begin ShowMessage('ON A RETROUVE '+PMyEcran+' instance de classe '+PMyFrameModel^.MyFrame.ClassName); Find:=true; exit; end; end; if not(Find) then begin new(PMyFrameModel); if PMyEcran='FrEcran1' then PMyFrameModel^.MyFrame := TFrmEcran1.Create(FPrincipal) else if PMyEcran='FrEcran2' then PMyFrameModel^.MyFrame := TFrmEcran2.Create(FPrincipal) else if PMyEcran='FrEcran3' then PMyFrameModel^.MyFrame := TFrmEcran3.Create(FPrincipal) else if PMyEcran='FrEcran4' then PMyFrameModel^.MyFrame := TFrmEcran4.Create(FPrincipal) else exit; PMyFrameModel^.MyFrameName:=PMyEcran; FMyListFrames.Add(PMyFrameModel); ClassRef:=PMyFrameModel^.MyFrame.ClassType; Showmessage('on a ajouté '+PMyEcran+' à la TList maison de classe '+ClassRef.ClassName); end; PMyFrameModel^.MyFrame.Parent := PConteneur; PMyFrameModel^.MyFrame.Afficher; except on E: Exception do MessageDlg('Contacter l''administrateur :'#13#10+E.Message,mtError,[mbOk],0); end; end;
S’il ne la retrouve pas il créé une nouvelle instance fille, en fonction du nom de l'écran passé en paramétre
S’il la trouve, je voudrai pouvoir l’utiliser pour appeler de nouveau la procédure surchargée ‘Appeler’.
* la création des nouvelles instances et le stockage dans la Tlist : ok çà fonctionne, la procédure Afficher lorsque je créé une nouvelle instance : ok çà fonctionne
* il retrouve bien mon instance fille une fois crée, la classe Référence de ma frame (ici dans le source ClassRef), mais l’appel de ma procédure Afficher ne marche pas, j’ai essayé en vain :
Je pense que pour que cela fonctionne il faut que j’arrive à un truc du genre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 PMyFrameModel^.MyFrame.Afficher; TFrmModele(PMyFrameModel^.MyFrame as ClassRef).Afficher; //pour tester récupération instance CAST if PMyEcran='FrEcran1' then (PMyFrameModel^.MyFrame as TFrmEcran1).Afficher..
Mais je n’y arrive pas !
Code : Sélectionner tout - Visualiser dans une fenêtre à part (PMyFrameModel^.MyFrame as ClassRef).Afficher
L’appel pour l’instant de ma procédure AfficherEcran depuis une frame chargée, me génére une violation d’accés.
Exemple d’appel depuis ma frame FrEcran1 (Evt OnClick par exemple):
Quid de ce qui ne và pas docteur ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 implementation uses Principal; procedure TFrmEcran1.Button1Click(Sender: TObject); begin FPrincipal.AfficherMyEcran('FrEcran2',FPrincipal.PanelFrame); end ;
1/ dans la gestion de ma Tlist pour récupérer une instance et pouvoir appeler la procédure surchargée ‘Appeler’
2/ dans l’appel de ma procédure Fprincipal.AfficherEcran depuis une frame ?
3/ si cela n’est pas abusé, j’aimerai également trouver une solution pour la création d’une instance et éviter de devoir faire :
if PMyEcran='FrEcran1' then PMyFrameModel^.MyFrame := TFrmEcran1.Create(FPrincipal)
else if PMyEcran='FrEcran2' then PMyFrameModel^.MyFrame := TFrmEcran2.Create(FPrincipal)
else if .......
j’ai une cinquantaire d’écrans c’est pas tip top. Comment peut-on rendre cela complémentement générique+Eviter dans les uses de ma feuille principal d’avoir mes 50 frames à implémenter ? RegisterClass ?
Merci d’avance aux courageux ki voudront bien m’aider en cette période estivale .
Partager