cs_wizad
Messages postés355Date d'inscriptionsamedi 30 octobre 2004StatutMembreDernière intervention14 avril 2009
-
19 juin 2006 à 15:40
cs_wizad
Messages postés355Date d'inscriptionsamedi 30 octobre 2004StatutMembreDernière intervention14 avril 2009
-
20 juin 2006 à 14:52
Bonjour à tous!
je suis entrain de créer une méthode permettant de justifier du texte pour l'impression (peut aussi être utilisé pour écrire avec la lib GDI).
Les variables d'entrées sont : un tableau de string pour chaque paragraphe, la taille de la page, la font à utilisé.
Principe de fonctionnement : à partir du tableau de paragraphe, effectuer le découpage des chaine de caractère en fonction de la place disponible. Pour ce faire je commence par découpé un paragraphe mot par mot, j'effectue un calcul pour déterminé le dernier mot qui peut être affiché en entier. Je calcul ensuite la longueur de la chain de mot mis bout à bout (sans aucun espace). A partir de cette distance, de la place disponible et du nombre de mot je calcul l'espace à mettre entre chaque mots.
A partir de la je place les mots un par un.
PrintPageEventArgs e //(paramètre de la méthode)
Brush PrintColor = Brushes.Black; //Brush standart
int abscisse = e.PageSettings.Margins.Left;
int ordonnee = e.PageSettings.Margins.Top;
int largeur = e.PageSettings.Bounds.Size.Width - (2 * abscisse); // Largeur de la zone cliente de la page
Font font = new Font("Times New Roman", 12, FontStyle.Regular); // Font utilisé pour le corps
// Variables pour le placement des mots composant le corps du document
float mot_y = ordonnee + 375;
float mot_x = abscisse;
// Le texte à écrire
string[] corps =
{
"Par la présente lettre, nous vous confirmons l'acceptation de votre inscription à la manifestation RétroGrainville qui se déroulera le Dimanche 3 septembre 2006 à Grainville sur Odon.",
"Conformément aux informations contenues dans votre dossier, vous participerez " + cat_info + " (voir convocation ci_jointe). Nous vous rappelons aussi que le petit déjeuner, et le déjeuner sont inclus dans votre inscription."
};
// Algorithme d'affichage
for (int i = 0; i < corps.Length; i++) // Boucle principale pour les paragraphes
{
string[] temp = corps[i].Split(' '); // On scinde le paragraphe en mots par mots
float alinea = 60; // Définition de la taille d'un alinéa
mot_x = abscisse + alinea; // On est au début du paragraphe on force donc l'alinéa
int first_word_ligne = 0; // Premier mot de la ligne (numéro dans le tableau)
int last_word_ligne = 0; //Dernier mot de la ligne
float larg_dispo = largeur - alinea; // Place disponible
while (last_word_ligne < (temp.Length-1)) // boucle pour chaque ligne
{
string temp1 = null;
float len = 0;
for (int j = first_word_ligne; j < temp.Length; j++) // on boucle pour trouver l'intervalle de mots à afficher (qui rentre dans la ligne)
{
if (j != 0) // juste pour éviter un espace devant le premier mot
{
temp1 = temp1 + " " + temp[j];
}
else
{
temp1 = temp[j];
}
// On cherche le dernier mot possible en ajoutant des espaces pour s'assurer d'avoir au minimum un espace normal entre chaque mot
if (e.Graphics.MeasureString(temp1, font).Width >= larg_dispo) // Si le dernier mot provoque le dépassement on enregistre et on sort de la boucle
{
last_word_ligne = j - 1;
break;
}
else
{
last_word_ligne = j; // Utilisé pour les fin de paragraphe : pu de mot mais bout de la ligne non atteint
}
}
//On calcul la taille de la chaine sans espace (mot collé les uns aux autres)
string temp2 = null;
for (int j = first_word_ligne; j <= last_word_ligne; j++)
{
temp2 = temp2 + temp[j];
}
len = e.Graphics.MeasureString(temp2, font).Width;
// on calcule l'espace à positioné entre chaque mots
float esp = (larg_dispo - len) / (last_word_ligne - first_word_ligne + 1);
// On boucle pour l'affichage des mots un par un
for (int j = first_word_ligne; j <= last_word_ligne; j++)
{
if (j != first_word_ligne)
mot_x = mot_x + esp + e.Graphics.MeasureString(temp[j-1], font).Width;
// On affiche chaque mot à sa place
e.Graphics.DrawString(temp[j], font, PrintColor, mot_x, mot_y);
}
// On passe à la ligne suivante
first_word_ligne = last_word_ligne + 1;
larg_dispo = largeur;
mot_y = mot_y + 14;
mot_x = abscisse;
}
// On passe au paragraphe suivant
mot_y = mot_y + 4;
}
Voilà l'algo en l'état actuel. Il ne produit aucune erreur mais par contre n'affiche pas le rendu escompté (les lignes dépasse de la pages et pas de justification aparente). Je poste donc pour avoir un avis extérieur...
Je suis bien entendu à toutes critiques constructives pour l'améliorer et l'optimiser.
dgouttegattat
Messages postés129Date d'inscriptionmardi 22 novembre 2005StatutMembreDernière intervention30 décembre 20073 20 juin 2006 à 12:05
J'ai fait quelques essais : le résultat est déjà beaucoup plus joli si tu utilises une des surcharges de la méthode MeasureString qui prend en paramètre un objet StringFormat, et en utilisant le StringFormat.GenericTypographic.
En revanche, comme la dernière ligne d'un paragraphe ne doit pas être justifié (sauf si tu tiens à avoir trois ou quatre mots répartis sur toute la largeur de la page avec une espace énorme entre eux, ce qui est très moche), il faut ajouter à ton code un test permettant de déterminer si tu es en train d'imprimer la dernière ligne, et si tel est le cas, tu utilises une espace normale. Rapidement, j'ai fait quelque chose comme ça :
// Utilisé pour les fin de paragraphe : pu de mot mais bout de la ligne non atteint is_last_line_of_paragraph (j temp.Length - 1);
}
...
float esp;
if (is_last_line_of_paragraph)
esp = 5.55f; // espace normale
else
esp = (larg_dispo - len) / (last_word_ligne - first_word_ligne + 1);
...
// On passe à la ligne suivante
is_last_line_of_paragraph = false;
...
<hr />
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 20 juin 2006 à 08:26
Salut,
A mon avis, tu t'es lancé dans un projet dont tu sous-estimes un peu l'ampleur...
Voici néanmoins une page sur le sujet qui devrait passablement t'aider !
dgouttegattat
Messages postés129Date d'inscriptionmardi 22 novembre 2005StatutMembreDernière intervention30 décembre 20073 20 juin 2006 à 09:53
Salut,
Je suis d'accord avec Bidou, tu t'attaques à un gros morceau.
Je pense qu'au lieu d'essayer de créer ta propre logique, tu devrais plutôt essayer d'implémenter des algorithmes qui ont déjà fait leurs preuves. En la matière, l'algorithme utilisé par TEX est généralement considéré comme l'un des meilleurs -- moi, je dirais LE meilleur, mais je ne suis pas objectif, je suis un utilisateur de TEX ;)
cs_wizad
Messages postés355Date d'inscriptionsamedi 30 octobre 2004StatutMembreDernière intervention14 avril 2009 20 juin 2006 à 10:01
Je cherche pas à créer un algorithme aussi performant et évolué que celui de tex mais plutôt un système me permettant d'avoir des lettre généré par mon programme suffisament propre pour être utilisé : bref mon premier objectif et de gérer les retour à la ligne de façon automatique et de conserver une marge minimum (comme un texte aligné à gauche) ce qui pour l'instant ne fonctionne pas tout à fait correctement.
Note : je ferais un screenshot de l'effet actuel si ça peu vous aider.
cs_wizad
Messages postés355Date d'inscriptionsamedi 30 octobre 2004StatutMembreDernière intervention14 avril 2009 20 juin 2006 à 13:27
je vais jetté un oeil sur les surcharges (j'y avais pas trop pensé :( )
sinon pour la fin de paragraphe j'avais prévu le code mais ne l'avais pas encore réalisé.
cs_wizad
Messages postés355Date d'inscriptionsamedi 30 octobre 2004StatutMembreDernière intervention14 avril 2009 20 juin 2006 à 14:13
Effectivement le résultat est propre à condition de ne pas toucher ce test
if (e.Graphics.MeasureString(temp1, font).Width >= larg_dispo)
sur lui la surcharge semble empècher le retour à la ligne.