Redimensionnements complexes des formulaires

Roland LANNUZEL

Cette note technique propose une méthode qui permet d’effectuer toutes sortes de déplacements et de redimensionnements et de les combiner entre eux, et ce de façon simple et logique. ♪

- Titre : Redimensionnements complexes des formulaires

- Auteur : Roland LANNUZEL

- Parution : 1 mars 2003

- Licence : Ce document est issu de https://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Introduction

- II. Déplacements ou agrandissements

- III. Ce que l’homme(*) veut…

- IV. Le zoom parfait ?

- V. Mise en pratique dans un exemple

- VI. « En deux temps, 'n’ mouvements »

- VII. Contrôle de la taille de la fenêtre

- VIII. Conclusion

- IX. Base exemple

I - Introduction

La plupart des formulaires de saisie sont redimensionnables, que ce soit pour afficher davantage d’informations, plus de texte ou plus d’éléments dans une liste par exemple, ou bien pour afficher ces mêmes informations en plus grand (ou plus petit) afin de s’adapter aux besoins de l’utilisateur.

4e Dimension offre directement la possibilité, sans programmation, d’agrandir ou bien de déplacer des objets. Cependant, ces options sont parfois insuffisantes et il faut recourir à la programmation et utiliser les commandes de déplacement des objets.

Cette note technique propose une méthode qui permettra d’effectuer toutes sortes de déplacements et de redimensionnements et de les combiner entre eux, et ce de façon relativement simple et logique.

II - Déplacements ou agrandissements

Entre ce qui semble naturel d’un point de vue humain et logique de celui de l’ordinateur, il y a une marge dont tout le monde a fait l’expérience plus ou moins douloureuse. Le redimensionnement des objets n’échappe pas à la règle. En effet, si deux objets sont côte à côte et que le développeur souhaite les voir s’agrandir tous les deux lorsque l’on agrandit la fenêtre, il aura pris soin de cliquer sur le bouton « agrandir » pour chacun des objets. L’ordinateur exécutera la demande à la lettre, les deux objets s’agrandiront… et l’objet de gauche débordera sur l’objet de droite ! « Logiquement », le développeur pensait que l’objet de droite serait « poussé » et que l’espacement entre les deux objets serait respecté.

Que faire alors ? Eh bien il suffit de cliquer « agrandir » sur l’objet de gauche et « déplacer » sur celui de droite, ou bien n’autoriser que l’objet de droite à grandir et laisser celui de gauche tel quel.

Cette solution est parfois suffisante, mais forcément frustrante, car, dans un cas comme dans l’autre, l’utilisateur n’a pas ce qu’il souhaitait au départ.

III - Ce que l’homme(*) veut…

(*) Dans le sens « humain », que les femmes ne se sentent pas exclues !

Quand on agrandit une fenêtre, la place gagnée (en hachuré dans le graphique ci-dessous) devrait être répartie entre les objets de façon uniforme. Autrement dit, si un formulaire contient 4 objets côte à côte, ils devront chacun s’agrandir de 25 % de ce que la fenêtre a gagné en largeur (et non pas 25 % de leurs propres tailles), et, bien entendu, se déplacer d’autant que son voisin de gauche s’est agrandi (et déplacé !), afin de ne pas être « mordus ».

Que s’est-il passé exactement ?

L’objet rose s’est agrandi de 25 % et n’a pas bougé.

L’objet bleu s’est agrandi de 25 % et à bougé de 25 % (25 % = agrandissement + déplacement de l’objet rose)

L’objet vert s’est agrandi de 25 % et à bougé de 50 % (50 % = agrandissement + déplacement de l’objet bleu)

L’objet jaune s’est agrandi de 25 % et à bougé de 75 % (75 % = agrandissement + déplacement de l’objet vert)

25 % c’est 100 (pourcentage à répartir) divisé par 4 (nombre de d’objets). Cela est vrai dans cet exemple, car les objets sont de taille identique, mais dans le cas où les objets sont différents, la répartition du pourcentage pourra être différente de façon à ce que l’aspect général reste inchangé, quelle que soit la taille des objets et des espaces qui les séparent.

Les objets ont des tailles différentes

Avant de poursuivre, précisons que ce que nous expliquons s’applique à la largeur des objets, mais serait, bien entendu, applicable à leur hauteur. De même, en ce qui concerne l’agrandissement des fenêtres, le raisonnement reste vrai lorsque la taille de celles-ci diminue.

Dans l’exemple ci-dessous, l’objet rose occupe 50 % de la largeur de la fenêtre et les deux autres 25 % ; Il est donc logique qu’il occupe toujours 50 % de la largeur quand la fenêtre sera agrandie. Pour cela, il faut donc qu’il gagne en largeur 50 % de la surface gagnée, les deux autres objets se contentant de 25 % chacun (cela dit, la souplesse de la solution que nous allons mettre en place permettra d’en décider tout autrement, et de faire en sorte que les proportions changent du tout au tout… mais cela reste au choix du programmeur en concertation avec les utilisateurs).

Et les marges ? Et les espaces entre les objets ?

Tout ce que nous avons dit plus haut reste vrai. Le graphique ci-dessous devrait vous en convaincre. Si on applique exactement les mêmes répartitions, on obtient exactement les mêmes résultats. En effet, c’est toujours la largeur gagnée qui est répartie, il est donc normal que les intervalles restent les mêmes…

N.B. Les marges sont plus importantes que les intervalles entre les objets… ces espaces ne sont absolument pas modifiés après modification de la taille de la fenêtre.

IV - Le zoom parfait ?

Un agrandissement vraiment « naturel » agrandirait les objets et également les espaces entre ces objets, et ce, de façon exactement proportionnelle à leur occupation dans la fenêtre d’origine. Dans la réalité, l’effet visuel est généralement plus important que la justesse, c’est pourquoi, il est inutile de mesurer les objets un par un afin de leur affecter très précisément un coefficient d’agrandissement. La seule chose réellement importante, c’est que la somme de ces coefficients fasse exactement 100 %, il faut donc bien définir ce que l’on souhaite avant de se lancer dans des paramétrages hasardeux.

Reprenons l’exemple précédent :

Nous désirons cette fois augmenter la taille des objets et des espaces.

Que constatons-nous ?

- L’objet Rose est deux fois plus grand que l’objet bleu et que l’objet vert.
- Les marges sont à peu près trois fois plus larges que les espaces interobjets.
- Les espaces représentent grosso modo 20 % de la largeur.

-> La répartition se fera donc grosso modo à 20 % pour les espaces et 80 % pour les objets.
-> Pour les espaces, on va prendre 6 % + 2 % +2 % +6 % = 16 % (ce qui est proche de 20 %).
-> Il reste donc 100-16 = 84 % pour les objets soit 42 % pour le rose et 21 % pour les bleus et verts.

Ce qui nous donnera finalement la forme ci-dessous, visuellement et fonctionnellement acceptable :

V - Mise en pratique dans un exemple

Nous voulons réaliser une calculette redimensionnable…

Cet objet si familier est pourtant relativement complexe :
- les boutons sont nombreux (17) ;
- ils sont de tailles différentes ('C’ et 'O' sont deux fois plus larges, '=' est deux fois plus haut) ;
- les « marges » sont inégales (haut et bas) ;
- la taille de l’afficheur lui-même doit aussi varier… etc.

Si l’on fait le compte, cette calculatrice compte en tout 21 objets dont voici le détail :
- 17 boutons ;
- un afficheur (fond jaune) ;
- le résultat affiché ;
- le fond gris ;
- L'objet de redimensionnement hachuré en bas à droite ;
- un bouton invisible sur cet objet graphique.

Nous allons donc devoir définir, pour chacun de ces objets les informations suivantes :
- coordonnées d’origine (X et Y) ;
- largeur et hauteur ;
- % de déplacement (X et Y) ;
- % d’agrandissement (X et Y) ;
… soit huit paramètres par objet.

À moins de vouloir gérer très précisément les mouvements, ces paramètres pourront être mémorisés dans des tableaux de type « entier long ».

Afin de faciliter la compréhension de cette note technique, ces valeurs sont stockées dans une table et mises en tableau au moment de leur utilisation. À votre convenance, ces valeurs pourront être stockées tout autrement (directement codées, dans une méthode d’initialisation, dans une blob des données, dans des ressources, etc.)
Afin de les rendre exploitables, nous associerons à ces huit tableaux un neuvième, qui contiendra le nom de l’objet concerné.

Détails des paramètres

Il serait fastidieux de détailler toutes les valeurs, mais il ne semble pas inutile d’en commenter certaines…

Le choix fait ici est d’augmenter la taille des objets ET des espaces.

Cela apparaît clairement pour les boutons 7, 8, 9 et '-' Ils ont chacun un coefficient de 20 % d’agrandissement ce qui donne un total de 80 %. Les 20 % restants seront répartis dans les 5 espaces, soit 4 % par espace. Les espaces ne sont pas des objets et ne sont donc pas matérialisés dans la liste ci-dessous.
En revanche, on constate que le bouton '7' grandit de 20 % et se déplace de 4 % (l’espace à sa gauche va donc grandir).
Le bouton '8' va faire de même. Il va grandir de 20 % et se déplacer de 4 % PLUS le déplacement (4 %) PLUS l’agrandissement (20 %) du bouton '7' situé à sa gauche, soit un total de 28 %.
Il en va de même pour les boutons '9' et '-' ce qui explique la progression 4-28-52-76 des déplacements.

On peut vérifier la cohérence de tout cela :
4+20+4 = 28 ;
28+20+4 = 52 ;
52+20+4 = 76 ;
76+20+4 = 100 % !

Dernier point :
On pourrait penser que le bouton 'C’ qui est deux fois plus large que les autres, va s’agrandit de 40 % au lieu de 20 %. Ce serait oublier l’espace situé entre les autres boutons qui lui aussi grandit (de 4 %). La valeur de croissance du bouton 'C’ est donc de 20+20+4 = 44 %.

Nous vous laissons le soin si vous le désirez d’examiner les coefficients affectés aux boutons et à l’afficheur pour le redimensionnement vertical, le principe étant strictement identique.

VI - « En deux temps, 'n’ mouvements »

Deux événements formulaires vont ici être traités :
sur chargement pour l’initialisation des tableaux et des objets, puis ;
sur redimensionnement pour les déplacements.

Une fois le paramétrage des objets effectué, la suite est très simple…

Sur chargement

1. `Mémorisation des coordonnées de référence de la fenêtre

2. RefWinX:=270

3. RefWinY:=300

5. TABLEAU ALPHA(80;_skObjectName;0)

6. TABLEAU ENTIER LONG(_skLeft;0)

7. TABLEAU ENTIER LONG(_skTop;0)

8. TABLEAU ENTIER LONG(_skSizeX;0)

9. TABLEAU ENTIER LONG(_skSizeY;0)

10. TABLEAU REEL(_skMoveX;0)

11. TABLEAU REEL(_skGrowX;0)

12. TABLEAU REEL(_skMoveY;0)

13. TABLEAU REEL(_skGrowY;0)

15. `lecture des paramétrages des objets

16. TOUT SELECTIONNER([Elements])

17. SELECTION VERS TABLEAU([Elements]ObjectName; _skObjectName;

18. [Elements]TopPosition; _skTop;

19. [Elements]LeftPosition; _skLeft;

20. [Elements]SizeX; _skSizeX;

21. [Elements]SizeY; _skSizeY;

22. [Elements]MoveX; _skMoveX;

23. [Elements]GrowX; _skGrowX;

24. [Elements]MoveY; _skMoveY;

25. [Elements]GrowY; _skGrowY)

26. $n:=Taille tableau(_skObjectName)

28. `mise en place des objets sur le formulaire

29. Boucle ($i;1;$n)

30. DEPLACER OBJET(*;_skObjectName{$i}; _skLeft{$i}; _skTop{$i};

31. _skLeft{$i}+_skSizeX{$i};

32. _skTop{$i}+_skSizeY{$i}; *)

33. Fin de boucle

35. `calcul de ta taille de la police à affecter à l’afficheur et aux boutons

36. LIRE RECT OBJET(*;"CalcResult";$Left;$Top;$Right;$Bottom)

37. $H:=($Bottom-$Top)

38. CHANGER TAILLE(*;"CalcResult";$H*0,6)

39. CHANGER TAILLE(*;"bIm@";$H*0,4)

Sur redimensionnement

1. COORDONNEES FENETRE($Left;$Top;$Right;$Bottom)

3. `calcul du chagement de taille par rapport à la taille d’origine de la fenetre

4. $DeltaX:=($Right-$left)-RefWinX

5. $DeltaY:=($Bottom-$Top)-RefWinY

6. $n:=Taille tableau(_skObjectName)

8. `répartition des modifications sur chacun des objets

9. Boucle ($i;1;$n)

10. DEPLACER OBJET (*; _skObjectName{$i}; _skLeft{$i}+(_skMoveX{$i}*$DeltaX/100);

11. _skTop{$i}+(_skMoveY{$i}*$DeltaY/100);

12. _skLeft{$i}+(_skMoveX{$i}*$DeltaX/100)

13. +_skSizeX{$i}+(_skGrowX{$i}*$DeltaX/100);

14. _skTop{$i}+(_skMoveY{$i}*$DeltaY/100)

15. +_skSizeY{$i}+(_skGrowY{$i}*$DeltaY/100); *)

16. Fin de boucle

18. `calcul de ta taille de la police à affecter à l’afficheur et aux boutons

19. LIRE RECT OBJET(*;"CalcResult";$Left;$Top;$Right;$Bottom)

20. $H:=($Bottom-$Top)

21. CHANGER TAILLE(*;"CalcResult";$H*0,6)

22. CHANGER TAILLE(*;"bIm@";$H*0,4)

VII - Contrôle de la taille de la fenêtre

Afin de pouvoir contrôler le redimensionnement de la fenêtre et son rapport largeur/hauteur nous appellerons une méthode spécifique via un objet invisible situé en bas à droite de la fenêtre.

Cet objet est en fait un petit thermomètre dont la fonction de base a été détournée. Il a l’avantage de pouvoir exécuter un script en continu tant que le bouton de la souris reste enfoncé.

La méthode appelée (ResizeWindow) contrôlera la position de la souris et, si les conditions de taille et de ratio sont respectées, se chargera de redimensionner la fenêtre (pourtant définie comme taille fixe, non redimensionnable). L’événement Sur redimensionnement sera alors activé et les objets déplacés.

VIII - Conclusion

D’autres applications sont envisageables avec cette méthode. Citons par exemple la possibilité de créer des « skins »(*) évolués via des objets statiques, des boutons images (dont l’apparence peut venir, rappelons-le, soit de ressources, soit de la bibliothèque d’images, mais également de variables images)…

Il serait également possible d’utiliser cette méthode pour faire apparaître ou non des objets en fonction des droits des utilisateurs, etc.

De bien beaux formulaires en perspective !

(*) Skin : éléments graphiques d’interface

IX - Base exemple

Téléchargez la base exemple :

Base pour Windows

Base pour Mac OS