|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour à tous
Je cherche à améliorer l'écriture de mon code d'ouverture de fiche de référence (des listes sur des tables de référence) qui revient très régulièrement dans mon application. Je dispose d'une fiche ancêtre fAncetreListe qui expose notamment en public un champ ModeOuverture (string) et FermerDataSet (boolean). Je dois par la suite pouvoir modifier ces champs. Je crée donc une routine qui va, en simplifiant, prendre en paramètres (entre autre) le nom de la fiche à créer (string). J'arrive effectivement à ouvrir la fiche souhaitée (elle va hériter de fAncetreListe) avec un code du style : procedure CreateFormFromName( const FormName : string); var fc : TFormClass; f : TForm; begin fc := TFormClass(FindClass(FormName)); f := fc.Create(Application); f.Show; end; J'en arrive au point sur lequel je bute, je veux maintenant affecter une valeur à mes 2 champs dans mon code et cela ne fonctionne pas (cela fonctionne évidemment en utilisant l'ouverture via une variable du type de la fiche souhaitée). Je cherche un peu et je tombe sur une proposition d'utiliser SetStrProp de l'unité Typinfo afin d'affecter une valeur. Mais à l'exécution cela ne passe pas, le champ n'est pas trouvé (sans même parler du booléen). Apparemment cela ne fonctionne que sur une propriété published que je n'ai pas pu (su) mettre en place dans ma fiche ancêtre ("Le champ publié n'est pas un type classe ou interface"). Bon j'en suis là, je m'en suis sorti en conservant la partie générique de localisation via un TClientDataSet générique créé à la volée (pas de souci là dessus) mais je suis ensuite contraint de faire un (en simplifiant à nouveau) : if sClientDataSet = 'Coll' then begin r_coll := TfListeColl.Create(self); r_coll.ModeOuverture := 'Modal'; r_coll.FermerDataSet := False; ..... if sClientDataSet = 'Client' then begin r_client := TfListeClient.Create(self); r_client.ModeOuverture := 'Modal'; r_client.FermerDataSet := False; ... Au final j'ai bien une routine centralisée pour tous mes appels de liste de référence mais bon je ne trouve pas cela très satisfaisant, j'aurais souhaité éviter ces multiples tests. Auriez-vous une idée ou mieux un petit exemple ? |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
dans la fiche ancètre tu peux rajouter
public Constructor Create(AOwner: TComponent; Param1:string; param2:boolean);reintroduce; overload; constructor TForm.Create(AOwner: TComponent; Param1:string; param2:boolean); begin ModeOuverture :=Param1 FermerDataSet :=param2; end; et dans le code de l'appli: TFormClass(FindClass(FormName)).Create(Application , 'blabla', false); Si j'ai bien pigé ton problème... |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Salut et merci de ta réponse
En fait ça ne passe pas ("Trop de paramètres originaux"): f := TFormClass(FindClass('fListe'+sClientDataSet)).Cre ate(Application,'blabla',false); Il ne sait pas à la compilation que c'est une fiche qui hérite de fAncetreListe qui dispose donc d'un constructeur différent, comment puis-je lui indiquer ? "Don.José" <don.jose@libertysurf.fr> a écrit dans le message de news: fod2nq$gp0$1@sd-6836.dedibox.fr... > dans la fiche ancètre tu peux rajouter > > public > Constructor Create(AOwner: TComponent; Param1:string; > param2:boolean);reintroduce; overload; > > > > constructor TForm.Create(AOwner: TComponent; Param1:string; param2:boolean); > begin > ModeOuverture :=Param1 > FermerDataSet :=param2; > end; > > > et dans le code de l'appli: > > TFormClass(FindClass(FormName)).Create(Application , 'blabla', false); > > > Si j'ai bien pigé ton problème... |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
Salut,
Côme de Christen a écrit : > Salut et merci de ta réponse > > En fait ça ne passe pas ("Trop de paramètres originaux"): > > f := > TFormClass(FindClass('fListe'+sClientDataSet)).Cre ate(Application,'blabla',false); > > Il ne sait pas à la compilation que c'est une fiche qui hérite de fAncetreListe > qui dispose donc d'un constructeur différent, comment puis-je lui indiquer ? > et si dans ta routine de création, tu passais directement la classe de ta fiche plutôt que le nom de classe ? TFormAncetreClass = class of TFormAncetre; La routine devient : procedure CreateFormFromClass(AClass : TFormAncetreClass) var f : TFormAncetre; begin f := AClass.Create(Application, 'blabla', false); f.Show(); end; B.L. > "Don.José" <don.jose@libertysurf.fr> a écrit dans le message de news: > fod2nq$gp0$1@sd-6836.dedibox.fr... >> dans la fiche ancètre tu peux rajouter >> >> public >> Constructor Create(AOwner: TComponent; Param1:string; >> param2:boolean);reintroduce; overload; >> >> >> >> constructor TForm.Create(AOwner: TComponent; Param1:string; param2:boolean); >> begin >> ModeOuverture :=Param1 >> FermerDataSet :=param2; >> end; >> >> >> et dans le code de l'appli: >> >> TFormClass(FindClass(FormName)).Create(Application , 'blabla', false); >> >> >> Si j'ai bien pigé ton problème... > > |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
> et si dans ta routine de création, tu passais directement la classe de ta > fiche plutôt que le nom de classe ? > > TFormAncetreClass = class of TFormAncetre; > > La routine devient : > > procedure CreateFormFromClass(AClass : TFormAncetreClass) > var > f : TFormAncetre; > begin > f := AClass.Create(Application, 'blabla', false); > f.Show(); > end; Yes, En fait c'est comme-ça que je procède. Sans transtypage, je ne vois pas comment faire. |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Salut
Merci à toi ! Cela fonctionne parfaitement. (Il va me falloir digérer ces nouveaux aspects de programmation...) Reste le besoin de passer par un RegisterClass pour ce type de fiche. Pensez-vous que je puisse le faire en dynamique dans la routine (et donc potentiellement "réenregistrer" une classe déjà enregistrée, à moins de pouvoir tester si une classe est déjà enregistrée ?) ou bien faut-il vraiment le faire une fois à la création (fiche/datamodule) par : RegisterClass(TfListeColl); RegisterClass(TfListeClient); .... Je vois qu'il existe également un UnregisterClass. Est-ce malin à chaque appel de la routine d'enregistrer la classe pour la désenregistrer ensuite ? Je dirais que non mais bon c'est tentant de tout centraliser dans la routine qui peut alors être réutilisée telle que dans un autre projet. "blescouet" <si@jes.fr> a écrit dans le message de news: foenuh$8b9$1@sd-6836.dedibox.fr... > Salut, > > Côme de Christen a écrit : >> Salut et merci de ta réponse >> >> En fait ça ne passe pas ("Trop de paramètres originaux"): >> >> f := >> TFormClass(FindClass('fListe'+sClientDataSet)).Cre ate(Application,'blabla',false); >> >> Il ne sait pas à la compilation que c'est une fiche qui hérite de >> fAncetreListe qui dispose donc d'un constructeur différent, comment puis-je >> lui indiquer ? >> > > et si dans ta routine de création, tu passais directement la classe de ta > fiche plutôt que le nom de classe ? > > TFormAncetreClass = class of TFormAncetre; > > La routine devient : > > procedure CreateFormFromClass(AClass : TFormAncetreClass) > var > f : TFormAncetre; > begin > f := AClass.Create(Application, 'blabla', false); > f.Show(); > end; > > > B.L. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Côme de Christen a écrit :
> Salut > > Merci à toi ! Cela fonctionne parfaitement. > (Il va me falloir digérer ces nouveaux aspects de programmation...) > > Reste le besoin de passer par un RegisterClass pour ce type de fiche. > Pensez-vous que je puisse le faire en dynamique dans la routine (et donc > potentiellement "réenregistrer" une classe déjà enregistrée, à moins de pouvoir > tester si une classe est déjà enregistrée ?) ou bien faut-il vraiment le faire > une fois à la création (fiche/datamodule) par : > > RegisterClass(TfListeColl); > RegisterClass(TfListeClient); > ... > > Je vois qu'il existe également un UnregisterClass. Est-ce malin à chaque appel > de la routine d'enregistrer la classe pour la désenregistrer ensuite ? Je dirais > que non mais bon c'est tentant de tout centraliser dans la routine qui peut > alors être réutilisée telle que dans un autre projet. > > "blescouet" <si@jes.fr> a écrit dans le message de news: > foenuh$8b9$1@sd-6836.dedibox.fr... >> Salut, >> >> Côme de Christen a écrit : >>> Salut et merci de ta réponse >>> >>> En fait ça ne passe pas ("Trop de paramètres originaux"): >>> >>> f := >>> TFormClass(FindClass('fListe'+sClientDataSet)).Cre ate(Application,'blabla',false); >>> >>> Il ne sait pas à la compilation que c'est une fiche qui hérite de >>> fAncetreListe qui dispose donc d'un constructeur différent, comment puis-je >>> lui indiquer ? >>> >> et si dans ta routine de création, tu passais directement la classe de ta >> fiche plutôt que le nom de classe ? >> >> TFormAncetreClass = class of TFormAncetre; >> >> La routine devient : >> >> procedure CreateFormFromClass(AClass : TFormAncetreClass) >> var >> f : TFormAncetre; >> begin >> f := AClass.Create(Application, 'blabla', false); >> f.Show(); >> end; >> >> >> B.L. > > Pourquoi parles-tu de RegisterClass ? procedure CreateFormFromName( const FormName : string); var fc : TFormClass; f : TFormAncetre; begin fc := TFormClass(FindClass(FormName)); f := TFormAncetre(fc.Create(Application)); f.Show; end; |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
"BigGrizzly" <bigZIPPERgrizzly@Zoo-loCAgique.org> a écrit dans le message de
news: foes0j$9q9$1@sd-6836.dedibox.fr... > Pourquoi parles-tu de RegisterClass ? > > procedure CreateFormFromName( > const FormName : string); > var > fc : TFormClass; > f : TFormAncetre; > begin > fc := TFormClass(FindClass(FormName)); > f := TFormAncetre(fc.Create(Application)); > f.Show; > end; Salut ! Bon je reprends un peu, j'en suis là (datamodule): unit uData; interface uses .....uAncetreListe; // (ma fiche ancêtre) [....] TFormAncetreClass = class of TfAncetreListe; implementation uses .... uListeClient,uListeColl; // Mes différentes fiches de référence [...] procedure TData.EcranReference(sClientDataSet,sCode,sLib : string; var sCodeRetour,sLibRetour : string); // Création dynamique des fiches de référence Var UnClientDataSet : TClientDataSet; f : TfAncetreliste; begin // Localiser l'enregistrement si possible UnClientDataSet := TClientDataSet(FindComponent('CdsListe'+sClientDat aSet)); UnClientDataSet.refresh; // Nécessaire sinon le locate peut échouer ! if sCodeRetour<>'' then UnClientDataSet.Locate(sCode,sCodeRetour,[loPartialKey]) else UnClientDataSet.First; // Dialogue modal // Nécessaire sinon la fiche n'est pas trouvée à l'exécution // Je teste ici sur une fiche fListeColl RegisterClass(TfListeColl); f := TFormAncetreClass(FindClass('TfListe'+sClientDataS et)).Create(Application,'Modal',false); if f.showModal=mrOk then begin sCodeRetour := UnClientDataSet[sCode]; sLibRetour := UnClientDataSet[sLib]; end else begin sCodeRetour := ''; sLibRetour := ''; end; f.Free; end; A ce stade sans RegisterClass cela ne passe pas chez moi à l'exécution (D7) EClasseNotFound... |
|
![]() |
| Outils de la discussion | |
|
|