IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Taille optimale d'objets

Cette Note Technique explore TAILLE OBJET OPTIMALE, une commande apparue avec 4D 2003. Celle-ci vous retourne les dimensions « optimales » requises pour qu’un objet puisse afficher son contenu que ce soit à l’écran ou sur un document papier. Vous utiliserez ces informations pour mieux ajuster vos formulaires ou optimiser le remplissage de vos imprimés. ♪

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Cette Note Technique explore TAILLE OBJET OPTIMALE, une commande apparue avec 4D 2003. Celle-ci vous retourne les dimensions « optimales » requises pour qu'un objet puisse afficher son contenu que ce soit à l'écran ou sur un document papier. Vous utiliserez ces informations pour mieux ajuster vos formulaires ou optimiser le remplissage de vos imprimés.

II. Syntaxe de la fonction

 
Sélectionnez
TAILLE OBJET OPTIMALE ({*;}objet; largeurOpti;hauteurOpti{;largeurMax})

La fonction retourne une hauteur et une largeur « optimale » de n'importe quel objet contenant un texte, et ceci quels que soient la plateforme utilisée, la police, la taille ou le style de la police. La fonction gère les césures et les retours de chariot.

TAILLE OBJET OPTIMALE fonctionne pour :

  • les alphas ;
  • les numériques ;
  • les booléens ;
  • les dates ;
  • les heures ;
  • les textes statiques ;
  • les boutons.

Dans ce document nous n'approfondirons que le cas des objets de type texte, mais ce que vous aurez appris pourra aisément être appliqué aux autres types d'objets.

Souvenez-vous que TAILLE OBJET OPTIMALE ne fait que retourner les meilleures dimensions pour l'objet lui-même sans prendre en compte ses éventuelles « décorations ». Supposons que votre objet soit en relief inversé, ait un ascenseur ou, si c'est un bouton, un cadre, vous devrez calculer par vous-même les dimensions de ces « apparences ». TAILLE OBJET OPTIMALE ne fait que retourner des dimensions brutes auxquelles vous ajouterez celles des décorations.

Lors de la manipulation d'objets de type texte, le paramètre optionnel « largeur fixe » est un paramètre quasiment obligatoire. En ne le précisant pas, vous risquez d'obtenir des objets si larges qu'ils pourraient ne pas tenir dans l'écran ou sur votre imprimé.

TAILLE OBJET OPTIMALE fonctionne également avec d'autres objets de formulaire : onglets, rectangles, lignes, etc. Dans ces cas-là TAILLE OBJET OPTIMALE retourne tout simplement des dimensions comme vous auriez pu les déduire avec la fonction LIRE RECT OBJET.

III. Utilisation de TAILLE OBJET OPTIMALE dans un formulaire entrée

La base exemple contient le formulaire ci-dessous. (Note : pour bien voir ce formulaire, la résolution de votre écran devra être au moins de 1024x768).

Pictures 0322x0262

Le formulaire contient trois objets à la taille variable : Acteurs, Image et Synopsis. Bien que vous puissiez utiliser TAILLE OBJET OPTIMALE sur pratiquement n'importe quel objet, l'exemple fourni se limitera au champ Synopsis.

En principe les acteurs devraient tenir dans la zone allouée et s'il devait y en avoir plus, l'utilisateur pourra alors jouer des ascenseurs pour voir l'excédent de texte.

Quant à l'image, elle peut varier énormément en taille, aussi, notre seule préoccupation est de la représenter de manière proportionnelle à l'original. La méthode formulaire utilise PROPRIETE IMAGE pour redimensionner le champ tout en gardant à l'esprit certaines limites physiques.

Venons-en à notre champ Synopsis : la méthode formulaire se termine en redimensionnant la fenêtre de manière à montrer le maximum de texte du champ Synopsis, mais dans la limite des dimensions de l'écran. De plus, le code replacera correctement toute portion de la fenêtre qui aurait pu déborder de l'écran.

La méthode formulaire de la base fournie est, vue dans son intégralité, plus complexe. Aussi vous ne l'étudierez que si vous souhaitez en connaître le moindre détail des fonctionnalités. Voici simplement la portion de code qui redimensionne le champ synopsis et son libellé.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
` manipulation sur le champ synopsis
LIRE RECT OBJET([Produits]Synopsis;$LSynopsisLeft;$LSynopsisTop;$LSynopsisRight;$LSynopsisBottom)

` calcul de la taille avec l'ascenceur
$LSynopsisFixedWidth:=$LPictureLeft+$LPictureWidth-$LSynopsisLeft-16
TAILLE OBJET OPTIMALE([Produits]Synopsis;$LWidth;$LSynopsisIdealHeight;$LSynopsisFixedWidth)

`Autorise de l'espace supplémentaire pour la saisie
$LSynopsisIdealHeight:=$LSynopsisIdealHeight+16
$LDescriptionTop:=$LSynopsisIdealHeight-($LSynopsisBottom-$LSynopsisTop)
$LMove:=$LPictureHeight+$LPictureTop+10-$LSynopsisTop
DEPLACER OBJET(*;"SynopsisLabel";0;$LMove)

Si (($LSynopsisIdealHeight+$LSynopsisTop+120)>$LMaxScreenHeight)
$LSynopsisIdealHeight:=$LMaxScreenHeight-$LSynopsisTop-120
Fin de si

Si ($LSynopsisIdealHeight<32) ` Set minimum height / fixer la hauteur mini
$LSynopsisIdealHeight:=32
Fin de si

` déplacer le champ
DEPLACER OBJET(*;"SynopsisField";0;$LMove;$LSynopsisFixedWidth-($LSynopsisRight-$LSynopsisLeft);
$LSynopsisIdealHeight-($LSynopsisBottom-$LSynopsisTop)+7)

Ce code récupère la hauteur optimale du champ Synopsis et la compare à celle de la fenêtre : est-elle trop grande ou nécessite-t-elle une hauteur minimum ? Ensuite l'objet est déplacé. Quant au libellé, il n'est déplacé que si la taille de l'image est trop grande en hauteur.

IV. Utilisation de TAILLE OBJET OPTIMALE dans une impression « côte à côte » d’un état

Une question qui revient régulièrement :
« comment puis-je imprimer un état avec des colonnes contigües alors que le texte varie d'une colonne à l'autre et d'un état à l'autre ? ».

Utilisons le formulaire ci-dessous :

Pictures 0554x0129

Il est très facile de boucler sur les trois champs Titre, Acteurs et Synopsis pour découvrir à l'aide de TAILLE OBJET OPTIMALE quel sera le champ le plus grand puis d'ajuster les taquets au plus grand des trois objets. Vous obtenez le résultat qui suit :

Pictures 0366x0374

La méthode formulaire est très simple :

 
Sélectionnez
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.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
Si (Faux)
` Form Method: PrintSideBySide
` 4D Technical Note
` Making the most of Best Object Size
` Created by: Kent Wilbur
` Date: 1/21/03
◊f_Version2003:= Vrai
◊fK_Wilbur:= Vrai
Fin de si

C_ENTIER LONG($i)
C_ENTIER LONG($LBottom)
C_ENTIER LONG($LFixedWidth)
C_ENTIER LONG($LFormEvent)
C_ENTIER LONG($LFormHeight)
C_ENTIER LONG($LHeight)
C_ENTIER LONG($LLeft)
C_ENTIER LONG($LMarkerPosition)
C_ENTIER LONG($LMoveMarker)
C_ENTIER LONG($LOriginalHeight)
C_ENTIER LONG($LPrintedHeight)
C_ENTIER LONG($LResize)
C_ENTIER LONG($LRight)
C_ENTIER LONG($LTop)
C_ENTIER LONG($LWidth)

$LFormEvent:=Evenement formulaire

Au cas ou

  : ($LFormEvent=Sur impression corps )

LIRE ZONE IMPRESSION($LFormHeight)
$LPrintedHeight:=Lire hauteur imprimee+5 ` pour les pieds
$LMoveMarker:=0
$LMarkerPosition:=Lire taquet impression(Corps formulaire )

TABLEAU POINTEUR($apFields;3)
$apFields{1}:=->[Produits]Titre
$apFields{2}:=->[Produits]Acteurs
$apFields{3}:=->[Produits]Synopsis

Boucle ($i;1;3)
    LIRE RECT OBJET($apFields{$i}->;$LLeft;$LTop;$LRight;$LBottom)
    $LFixedWidth:=$LRight-$LLeft
    $LOriginalHeight:=$LBottom-$LTop
    TAILLE OBJET OPTIMALE($apFields{$i}->;$LWidth;$LHeight;$LFixedWidth)
    $LResize:=$LHeight-$LOriginalHeight
    Si ($LResize>0)
        DEPLACER OBJET($apFields{$i}->;$LLeft;$LTop;$LRight;$LHeight+$LTop;*)
        Si ($LResize>$LMoveMarker)
            $LMoveMarker:=$LResize
        Fin de si
    Fin de si
Fin de boucle

Si ($LFormHeight>($LPrintedHeight+$LMoveMarker+$LOriginalHeight))
    Si ($LMoveMarker>0)
        FIXER TAQUET IMPRESSION(Corps formulaire ;$LMarkerPosition+$LMoveMarker;*)
    Fin de si
Sinon
    NE PAS VALIDER
Fin de si

Fin de cas

Ce code utilise plusieurs nouvelles fonctionnalités propres à la 2003. Tout d'abord vous pouvez récupérer et fixer les taquets lors de l'événement formulaire Sur impression corps. C'est nouveau. Ensuite, mais tout aussi important, vous pouvez à présent ANNULER une impression au cours d'un Imprimer ligne pour que ce formulaire ne soit pas enregistré. De plus, la méthode qui appelle Imprimer ligne n'est pas stoppée. En revenant dans cette méthode, vous n'aurez qu'à tester l'annulation et agir en conséquence.

Voici donc la méthode qui imprime l'état en appelant Imprimer ligne.

Note : une meilleure solution consiste à créer un tableau de pointeurs (tableau process) en dehors de la méthode formulaire : ainsi le tableau n'aura pas a être recrée à chaque enregistrement. Dans notre exemple, nous créons un tableau local afin de mieux vous faire saisir le déroulement des opérations.

 
Sélectionnez
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.
Si (Faux)
` Method: M_PrintSideBySide
` 4D Technical Note
` Making the most of Best Object Size
` Created by: Kent Wilbur
` Date: 1/21/03
◊f_Version2003:=Vrai
◊fK_Wilbur:=Vrai
Fin de si

C_ENTIER LONG($i)
C_ENTIER LONG($LHeight)
PARAMETRES IMPRESSION

Si (OK=1)

`Sauvegarder la sélection originale et la trier
COPIER SELECTION([Produits];"OriginalSelection")
TRIER([Produits];[Produits]Titre)
$LHeight:=Imprimer ligne([Produits];"PrintSideBySide";Entête formulaire )

Boucle ($i;1;Enregistrements trouves([Produits]))
    $LHeight:=Imprimer ligne([Produits];"PrintSideBySide";Corps formulaire )
    Si (OK=0) `ANNULER a été demandé dans la méthode formulaire
        SAUT DE PAGE
        $LHeight:=Imprimer ligne([Produits];"PrintSideBySide";Entête formulaire )
        $LHeight:=Imprimer ligne([Produits];"PrintSideBySide";Corps formulaire )
    Fin de si
    ENREGISTREMENT SUIVANT([Produits])
Fin de boucle

SAUT DE PAGE ` on n'oublie pas la dernière page !

` revenir à la sélection d'origine
UTILISER SELECTION("OriginalSelection")
EFFACER SELECTION("OriginalSelection")

Fin de si

Le code de cette méthode projet est simple : nous bouclons sur la sélection d'enregistrements à imprimer. Si au cours de l'opération une annulation est détectée, nous éjectons la page, imprimons un entête et réimprimons le même formulaire.

Comme vous le constatez, avec quelques lignes de code et un formulaire, imprimer un rapport « side by side » est relativement indolore.

V. Utilisation de TAILLE OBJET OPTIMALE pour créer un état style « catalogue »

Par le passé, imprimer un « catalogue » avec 4D était virtuellement impossible. Par « catalogue », nous entendons un état qui soit comparable à un produit réaliser en PAO. Ce type de rapport a classiquement un ou plusieurs champs qui fluctuent en taille alors qu'ils ont besoin de suivre une maquette prédéfinie. Par nature, ce format n'est pas linéaire.

Pour l'exemple nous avons préparé les formulaires suivants :

Pictures 0423x0220

Dans la série « pourquoi faire compliqué quand on peut faire simple », ce formulaire ne se préoccupera que des deux champs qui changent le plus fréquemment : Acteurs et Synopsis. Cependant rien n'empêcherait d'utiliser TAILLE OBJET OPTIMALE pour les autres champs.

De par la proximité du libellé Genre avec le bas de l'image, le champ Acteurs sera de trois lignes sans à avoir à être modifié. Il ne le serait que si l'espace requis dépasse ces trois lignes.

Quant au champ synopsis, il changera à chaque enregistrement. La distance entre de ce champ et le taquet du corps est là pour créer une séparation entre chaque produit. Nous aurions pu ajouter une ligne ou tout autre objet, mais gardons le code au plus simple.

Voici le résultat que nous escomptons :

Pictures 0377x0359

Quelques évidences :
Mission Impossible a cinq lignes d'acteurs alors que Mission pour Mars n'en comporte que deux. Mais il y a un peu plus d'espace entre Mission pour Mars et le haut du synopsis. Au premier coup d'œil il n'est pas facile de déterminer le nombre de lignes qui auraient pu être ajoutées.

La seule façon d'être certain à 100 % que tous les objets ont été redimensionnés sera de jeter un œil à l'alignement des libellés Genre et Synopsis qui est différent d'un enregistrement à l'autre : dans le cas de Mission Impossible le libellé Synopsis est deux lignes plus bas.

Afin d'obtenir ces déplacements, nous avons utilisé la même technique que précédemment lors de l'impression « côte à côte ». Voici la méthode formulaire de notre listing de films :

 
Sélectionnez
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.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
Si (Faux)
` Méthode formulaire : PrintFormCatalog
` 4D Technical Note
` Taille optimale d'objet
` Créée par : : Kent Wilbur
` Date : 11/20/02
◊f_Version2003:=Vrai
◊fK_Wilbur:=Vrai
Fin de si

C_ENTIER LONG($LBottom)
C_ENTIER LONG($LFixedWidth)
C_ENTIER LONG($LFormEvent)
C_ENTIER LONG($LFormHeight)
C_ENTIER LONG($LHeight)
C_ENTIER LONG($LLeft)
C_ENTIER LONG($LMarkerPosition)
C_ENTIER LONG($LMoveMarker)
C_ENTIER LONG($LOriginalHeight)
C_ENTIER LONG($LPrintedHeight)
C_ENTIER LONG($LResize)
C_ENTIER LONG($LRight)
C_ENTIER LONG($LTop)
C_ENTIER LONG($LWidth)
C_REEL($rRatio)

$LFormEvent:=Evenement formulaire

Au cas ou

  : ($LFormEvent=Sur impression corps )

LIRE ZONE IMPRESSION($LFormHeight)
` Add the needed pixels for a footer / ajouter des pixels pour le pied
$LPrintedHeight:=Lire hauteur imprimee+20

$LMoveMarker:=0
$LMarkerPosition:=Lire taquet impression(Corps formulaire )

` retravailler l'image proportionnellement
LIRE RECT OBJET([Products]Picture;$LLeft;$LTop;$LRight;$LBottom)
PROPRIETES IMAGE([Products]Picture;$LWidth;$LHeight)

Au cas ou

  : ($LHeight>$LWidth)

    $rRatio:=($LBottom-$LTop)/$LHeight
    DEPLACER OBJET([Products]Picture;$LLeft;$LTop;$LLeft+($LWidth*$rRatio);$LBottom;*)

  : ($LHeight<$LWidth)

    $rRatio:=($LRight-$LLeft)/$LWidth
    DEPLACER OBJET([Products]Picture;$LLeft;$LTop;$LRight;$LTop+($LHeight*$rRatio);*) 

Fin de cas

` tester si la zone Acteurs est suffisamment grande
LIRE RECT OBJET([Products]Actors;$LLeft;$LTop;$LRight;$LBottom)
$LFixedWidth:=$LRight-$LLeft
$LOriginalHeight:=$LBottom-$LTop
TAILLE OBJET OPTIMALE([Products]Actors;$LWidth;$LHeight;$LFixedWidth)
$LResize:=$LHeight-$LOriginalHeight

Si ($LResize>0) ` We need more size for the Actors text area / on veut de la place
    FIXER TAQUET IMPRESSION(Corps formulaire ;$LMarkerPosition+$LResize;*)
    DEPLACER OBJET([Products]Actors;$LLeft;$LTop;$LRight;$LHeight+$LTop;*)
    LIRE RECT OBJET([Products]Synopsis;$LLeft;$LTop;$LRight;$LBottom)
    DEPLACER OBJET([Products]Synopsis;$LLeft;$LTop+$LResize;$LRight;$LBottom+$LResize;*)
    LIRE RECT OBJET(*;"SynopsisLabel";$LLeft;$LTop;$LRight;$LBottom)
    DEPLACER OBJET(*;"SynopsisLabel";$LLeft;$LTop+$LResize;$LRight;$LBottom+$LResize;*)
Fin de si

` test de la taille synopsis
LIRE RECT OBJET([Products]Synopsis;$LLeft;$LTop;$LRight;$LBottom)
$LFixedWidth:=$LRight-$LLeft
$LOriginalHeight:=$LBottom-$LTop
TAILLE OBJET OPTIMALE([Products]Synopsis;$LWidth;$LHeight;$LFixedWidth)
$LResize:=$LHeight-$LOriginalHeight

Si ($LResize>0) ` on veut de la place
    FIXER TAQUET IMPRESSION(Corps formulaire ;$LMarkerPosition+$LResize;*)
    DEPLACER OBJET([Products]Synopsis;$LLeft;$LTop;$LRight;$LHeight+$LTop;*)
Fin de si

Si ($LPrintedHeight+$LHeight+$LTop>$LFormHeight) ` l'enregistrement ne tiendra pas dans la fenêtre
    NE PAS VALIDER ` annule l'impression de CET enregistrement
Fin de si

Fin de cas

Ce code diffère de celui du « côte à côte » précédent parce que les objets sont « empilés » : il manipule deux objets séparément au lieu de le faire en même temps.

La méthode projet d'impression est également un brin plus compliquée, car utilisant la méthode PRINT_PrintForm, que nous ne détaillerons, car discutée dans une note différente.

 
Sélectionnez
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.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
Si (Faux)
` Method: M_PrintFormCatalog
` 4D Technical Note
` Making the most of Best Object Size
` Created by: Kent Wilbur
` Date: 11/20/02
` Objectif : Montrer l'utilisation de la méthode PRINT FORM pour l'impression d'un
` listing genre catalogue
◊f_Version2003:=Vrai
◊fK_Wilbur:=Vrai
Fin de si

C_ENTIER LONG($i)
C_ALPHA(2;$sFirstCharacter)

` Utilisé par la méthode PRINT_PrintForm, mais pas dans cette base
fPrintPage2ColumnHeaders:=Faux
PARAMETRES IMPRESSION

Si (OK=1)
`sauver la sélection et la TRIER
COPIER SELECTION([Products];"OriginalSelection")
TRIER([Products]Title)
` on récupère le 1er caractère pour le mettre en entête
$sFirstCharacter:=[Products]Title≤1≥
PRINT_PrintForm (->[Products];"PrintFormCatalog";"MainHeader")
PRINT_PrintForm (->[Products];"PrintFormCatalog";"Header1")

Boucle ($i;1;Enregistrements trouves([Products]))

    ` en haut de la page on met la lettre
    Si ($sFirstCharacter#[Products]Title≤1)
        SAUT DE PAGE
        PRINT_PrintForm (->[Products];"PrintFormCatalog";"MainHeader")
        PRINT_PrintForm (->[Products];"PrintFormCatalog";"Header1")
        $sFirstCharacter:=[Products]Title≤1Fin de si

    PRINT_PrintForm (->[Products];"PrintFormCatalog";"Detail")

    Si (OK=0) ` impression annulée à cause du bas de la page
        SAUT DE PAGE
        PRINT_PrintForm (->[Products];"PrintFormCatalog";"MainHeader")
        PRINT_PrintForm (->[Products];"PrintFormCatalog";"Header1")
        PRINT_PrintForm (->[Products];"PrintFormCatalog";"Detail")
    Fin de si

    ENREGISTREMENT SUIVANT([Products])

Fin de boucle

SAUT DE PAGE `Make sure that the last page is printed / on n'oublie pas la dernière page

` Restore the original selection/on récupère la sélection originale
UTILISER SELECTION("OriginalSelection")
EFFACER SELECTION("OriginalSelection")

Fin de si

VI. Conclusion

TAILLE OBJET OPTIMALE est probablement l'ajout le plus important à 4e Dimension depuis Créer fenêtre formulaire. Le plus grand bénéfice de cette fonction est de pouvoir influer sur les capacités d'impression de 4D. Combinée avec les ajouts et les modifications apportés à l'impression dès la 6.8.1 et sans cesse améliorés en 2003, vous comblez des demandes que vos utilisateurs finaux faisaient depuis fort longtemps.

VII. Base exemple

Téléchargez la base exemple :

Base pour Windows

Base pour Mac OS

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

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.