fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 2022
-
8 avril 2013 à 13:02
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 2022
-
13 avril 2013 à 15:20
J'écris un programme qui contient beaucoup de labels. Je suis tout le temps en train d'écrire Label1.caption=ceci, label2.caption=cela... Je voudrais bien me simplifier la tâche en écrivant tout simplement c1:=ceci, c2:=cela ou à la rigueur c1^:=ceci c2^:=cela. Et bien sûr, les captions prendraient les valeurs données à c1 et c2.
Delphi me permet d'écrire: Addr(Label1) mais ça ne m'apporte rien. Si je pouvais écrire Addr(label1.caption), ce serait facile mais ça, Delphi ne l'accepte pas, c'est bien normal.
Avec quelques recherches, je peux trouver combien d'octets séparent le début de Label1 de sa caption (on peut appeler ça le décalage, l'offset) mais je ne vois pas comment je pourrais m'en servir.
En résumé: si je connais A, adresse de Label1, comment lire et modifier le contenu de [(adresse pointée par A) + offset de la caption)]. En Turbo-Pascal, on avait le mot Mem[adresse] qui permettait de faire tout ce qu'on voulait, y compris de grosses bêtises, mais Delphi me semble s'être cuirassé contre la possibilité de lire ou de modifier une adresse mémoire autrement qu'en y accédant par une variable.
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 8 avril 2013 à 14:33
Merci pour ta réponse. Tu as fort bien compris et je t'avoue que peu après avoir envoyé mon message, j'ai eu exactement la même idée: écrire une procédure ayant un nom très court et j'ai pensé moi aussi que le mieux était de l'appeler C. Et voilà: il me suffit d'écrire: C(1,ceci); C(2,cela).
En lecture, il me suffit d'écrire une fonction du même style et c'est gagné.
Mais tout de même, pour la beauté de la chose (et parce que ça m'arrangerait, ce serait trop long d'expliquer pourquoi), je pense que je vais continuer à chercher une solution qui me permettrait de représenter les captions par des raccourcis. Je vais chercher du côté des composants. J'imagine de créer un composant non visible pour ne pas me compliquer la vie, avec un nom très court et avec des propriétés qui s'appelleront c1,c2,etc... Pour chacune de ces propriétés, il y aura une procedure write et une fonction read dans laquelle, je pourrai faire ce que je voudrai. Le boulot à faire m'effraie un peu mais ce serait un bon exercice.
Et malgré tout, si certains ont des idées pour faire ça en passant par des manipulations de la mémoire, ce serait la solution la plus élégante. J'ai un label qui pointe vers une adresse A. À l'adresse pointée par A commence la description de mon label. Imaginons que l'offset de la caption est égal à 0. Le problème est simple: il me faut modifier le contenu de cette adresse pointée. Si seulement, je pouvais écrire MonPointeur: = Label1 (ce qui ne me parait pas absurde puisqu'en fait, un Label, c'est un pointeur), il me suffirait d'écrire: Monpointeur^:=ceci; Allez, zut, je continue à chercher.
beckerich
Messages postés302Date d'inscriptionjeudi 29 septembre 2005StatutMembreDernière intervention17 septembre 20132 8 avril 2013 à 19:05
Bonsoir,
ou aussi :
procedure setCaption(label: TLabel; const caption: string);
begin
label.Caption := caption;
end;
....
....
procedure TForm1.toto;
begin
// ALabel est un TLabel
// Edit1 est un TEdit
setCaption(ALabel, Edit1.Text);
end;
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 8 avril 2013 à 19:51
Merci Luc, mais je ne vois pas très bien comment utiliser cette procedure Toto. J'avais pensé à une procédure de ce genre mais plus étoffée pour tout mettre à jour d'un coup:
c1:= ceci;
c2:= cela;
toto;
La procedure toto étant:
..
procedure TForm1.toto;
begin
. setCaption(Label1,c1);
. setCaption(Label2,c2);
. etc...
end;
PS: j'aurais bien aimé mettre ma portion de programme sur fond gris comme tu l'as fait et aussi conserver l'indentation sans ajouter un point.. Tu peux me dire le secret ?
beckerich
Messages postés302Date d'inscriptionjeudi 29 septembre 2005StatutMembreDernière intervention17 septembre 20132 8 avril 2013 à 20:12
re,
non, toto n'est pas à suivre, mais quand tu as besoin de changer le caption d'un des tlabel, tu appelles la procedure setCaption avec comme premier paramètre le TLabel en question et en second paramètre le texte à afficher.
Ce n'est qu'un petit exemple de la façon de regrouper certaines actions répétitives. Tu pourrais aussi gérer un tableau de TCaption et afficher le tout dans une boucle, ...
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 10 avril 2013 à 17:17
Merci pour cette portion de programme nettement plus savante que ce que je fais habituellement. Je vais la tester ce soir même. Je n'y vois pas de pointeurs. Mais c'est pas plus mal.
Le mot Lol m'est inconnu mais tant mieux, c'est comme ça qu'on progresse.
J'étais parti sur la fabrication d'un composant ayant c1,c2,etc... comme propriétés privées et j'avais écrit:
property c1 read getc1 write setc1;
et bien sûr dans la procedure setc1, je comptais mettre un label1.caption:=...
Mais de toutes façons, même si d'autres procédés me donnent satisfaction, j'essaierai de faire quelque chose avec des pointeurs.
@Simon: Findcomponent n'est pas sensible à la casse. Je trouve ça plutôt normal.
Rendez-vous demain pour que je vous dise où j'en suis.
PS: Bien que pas très savant, j'aimerais bien être informé des questions qui arrivent sur ce forum. Que faut-il faire pour cela?
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 10 avril 2013 à 19:53
OK, j'ai coché cette case bien sûr mais elle ne concerne que ma petite question. Il y a peut-être eu d'autres questions qui ont été posées aujourd'hui et qui sait, j'aurais peut-être pu apporter des réponses. Je ne vois nulle part comment s'inscrire en tant que secouriste occasionnel.
sp40
Messages postés1276Date d'inscriptionmardi 28 octobre 2003StatutContributeurDernière intervention 3 juillet 201515 11 avril 2013 à 08:48
Bé il faut venir régulièrement sur le forum ou te charger un flux rss... Sur un sujet, même si tu n'interviens pas, tu as une option "suivre cette discussion"
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 11 avril 2013 à 09:59
@Simon: bon, je viendrai voir de temps en temps. C'est dommage qu'on ne puisse pas s'inscrire une bonne fois pour toutes et être informé dès qu'il y a quelque chose.
@fOxi: J'ai essayé le programme. Pas de problème, il marche. Mais pour bien le comprendre, je l'ai dépouillé à l'extrême. Je l'ai réduit à ça:
PROCEDURE Tform1.SetCaption(C:TControl; S:String{; Const ARefresh: Boolean= False});
Begin
C.SetTextBuf(PChar(S));
//IF ARefresh THEN
// Application.ProcessMessages;
End;
Comme ça, ça marche encore et je comprends que les contrôles ont une méthode SetTextBuf qui apparemment sert à écrire leur caption. C'est bon à savoir.
Je découvre qu'il n'est pas forcé que tous les arguments annoncés dans la procédure soient présents dans l'appel de cette procédure. Évidemment pour une constante dont on donne la valeur, ça parait normal.
Je découvre aussi qu'un argument peut être un array dont on ne donne pas les dimensions. Tiens, ça, ça pourrait m'être utile pour autre chose: écrire une procédure Sma Acronyme de (ShowMessageAmélioré) qui me permettrait d'écrire des ShowMessage de façon moins fatigante: la syntaxe serait
Sma('Les valeurs de x et y sont ',x,' et ',y); (Au diable les inttostr !)
Mais je ne comprends pas pourquoi il y a un Application.ProcessMessages. D'autant plus qu'il n'est jamais activé puisque ARefresh est fixé à false.
Pour moi, Application.ProcessMessages, ça veut dire: finis le travail que tu as laissé en plan avant d'aller plus loin. Ici, je n'en vois pas l'utilité. Et d'ailleurs, la procédure fonctionne aussi bien sans ça.
sp40
Messages postés1276Date d'inscriptionmardi 28 octobre 2003StatutContributeurDernière intervention 3 juillet 201515 11 avril 2013 à 10:10
Je découvre qu'il n'est pas forcé que tous les arguments annoncés dans la procédure soient présents dans l'appel de cette procédure
-> Si tu mets une valeur par défaut à un paramètre de ta fonction, le paramètre est en effet facultatif
Évidemment pour une constante dont on donne la valeur, ça parait normal.
-> Non, c'est juste que tu ne peux pas modifier ça valeur dans le corps de ta fonction, le mot "const" ajouté devant un paramètre sert à ça.
Mais je ne comprends pas pourquoi il y a un Application.ProcessMessages. D'autant plus qu'il n'est jamais activé puisque ARefresh est fixé à false.
-> Application.ProcessMessages permet de "dépiler" tous les messages windows en attente de traitement avant de continuer ton programme. Dans le cas présent, ça permet de rafraichir le caption de ton label. Si on reprend cette procedure :
PROCEDURE Tform1.SetCaption(C:TControl; S:String; Const ARefresh: Boolean= False);
Begin
C.SetTextBuf(PChar(S));
IF ARefresh THEN
Application.ProcessMessages;
End;
Tu as 3 façons de l'appeler :
1) SetCaption (Label1, 'Coucou'); -> Paramètre ARefresh = false, donc pas d'appel à Application.ProcessMessages;
2) SetCaption (Label1, 'Coucou', false); -> Idem à 1...
3) SetCaption (Label1, 'Coucou', True); -> Paramètre ARefresh = True, donc pas d'appel à Application.ProcessMessages;
Le const t'interdit juste de faire ça :
PROCEDURE Tform1.SetCaption(C:TControl; S:String; Const ARefresh: Boolean= False);
Begin
C.SetTextBuf(PChar(S));
ARefresh := True; // Là, tu dois avoir des problèmes...
IF ARefresh THEN
Application.ProcessMessages;
End;
beckerich
Messages postés302Date d'inscriptionjeudi 29 septembre 2005StatutMembreDernière intervention17 septembre 20132 11 avril 2013 à 10:31
Bonjour,
Application.ProcessMessages permet en effet à l'application de déplier les messages en attente.
Si tu ne désires que rafraîchir ton composant (TControl), tu peux aussi faire :
fredelem
Messages postés136Date d'inscriptiondimanche 29 octobre 2006StatutMembreDernière intervention 1 décembre 20222 11 avril 2013 à 13:05
@Simon: Merci pour toutes ces précisions, je m'étais vraiment mis le doigt dans l'oeil. Dire que j'ai quelques années d'expérience en Delphi et que j'ignorais qu'on pouvait passer un paramètre avec une valeur par défaut. J'avais bien remarqué que Delphi le faisait avec la fonction Booltostr qu'on peut appeler avec 1 seul arguments ou avec 2 mais je ne savais pas que nous, la foultitude, on pouvait faire la même chose.
@Luc: Toi aussi, tu m'apprends quelque chose. Je connaissais Repaint, Refresh mais pas Update.
@FOxi: ton programme m'a fait faire beaucoup de découvertes mais quel est l'avantage d'écrire:
C.SetTextBuf(PChar(S))
plutôt que:
C.Caption:=S; ?