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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Forms Discussion :

Découpage de texte


Sujet :

Windows Forms

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 69
    Par défaut Découpage de texte
    Bonjour.

    Mon problème n'est pas forcément facile à expliquer. J'ai créé un outil de génération / impression de rapport inspiré de celui d'Access 97. J'y gère l'impression d'images ou de textes simples et surtout courts. Mais j'ai désormais besoin de gérer également des textes dont la longueur peut être importante, et donc qui risquent de déborder de la page.

    J'utilise actuellement Graphics.DrawString pour "écrire" mes textes sur la page destinée à être imprimée (J'avais commencé avec Textrenderer mais c'était trop lent). Comment pourrais-je scinder précisémment mon texte en 2 de façon à en écrire la première partie sur la page actuelle et reporter l'impression du reste sur la suivante ? En gros comment déterminer où couper mon texte, à la fin de quel mot pour qu'il tienne dans la place restante de la page actuelle ?

    Textrenderer et Graphics permettent de mesurer un texte assez précisémment, mais de là à en déduire à quel mot je dois m'arrêter ? Suis-je obligé de rajouter chaque mot et de re-tester jusqu'à ce que ça "déborde" ? Ca me parait peu élégant comme méthode (et sans doute peu optimisé).

    En espérant que vous puissiez m'aider.

  2. #2
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut decouper un texte
    bonjour
    Dans la mesure ou tu parles de Page ,il me semble qu'il manque à ta conception de la "Page" une autre notion qui est la ligne ,hein une page sans ligne tu crois que ca à un sens .
    Structure ta page en -n-lignes
    C'est dans la poche l'impression.
    Alors mets ton texte dans un tableau de string de -n-lignes .

    le code pour mieux comprendre l'evenement printPage qui gere page et lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
     
    'un ListBox pour gerer les differents ZOOM
    'un PrintPreviewControl1
    'un Button Apercu
    'Une Classe TexteDocument pour gerer un Document Texte(numeropage,offset)
    'Un tableau string pour -definir les lignes de texte- 
    Imports System
    Imports System.Drawing
    Imports System.Windows.Forms
    Imports System.Drawing.Printing
    Partial Public Class frmPrintMonTexte
        Private doc As PrintDocument
     
        Private Sub frmPrintMonTexte_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            ' Fixe les choix Zoom dans un ListBox
            For i As Integer = 1 To 10
                listBoxZoom.Items.Add((i * 10).ToString)
            Next
            ' Cree un document texte avec 100 lignes.
            Dim Texte_Imprimer As String() = New String(100) {}
            For i As Integer = 1 To 100
                Texte_Imprimer(i) = i.ToString
                Texte_Imprimer(i) += ": Mon texte à imprimer decoupe en lignes..."
            Next
            'Init classe TexteDocument avec le texte à imprimer
            Dim doc As New TexteDocument(Texte_Imprimer)
            'Definit Handler pour event PrintPage
            AddHandler doc.PrintPage, AddressOf Doc_PrintPage
            ' Definit zoom initial dans ListBox à "100"
            listBoxZoom.Text = "100"
            'Configure le controle PrintPreviewControl pour afficher :
            'la page à 100% (Zoom = 1) 
            PrintPreviewControl1.Zoom = 1
            '2 pages verticalement (Rows = 2). 
            PrintPreviewControl1.Rows = 2
            'Assigne la variable "doc" à PrintPreviewControl1.Document
            PrintPreviewControl1.Document = doc
        End Sub
        Private Sub cmdPrint_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnPrintApercu.Click
            ' Reinitialise le Zoom.
            PrintPreviewControl1.Zoom = Single.Parse(listBoxZoom.Text) / 100
            ' Rebinde le PrintDocument pour rafraichir l'Apercu.
            PrintPreviewControl1.Document = doc
        End Sub
     
        Private Sub Doc_PrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs)
            ' Retrouve le document qui a declenche cet event.
            Dim doc As TexteDocument = DirectCast(sender, TexteDocument)
            ' Fixe le font et hauteur de ligne suivant font.
            Using fnt As New Font("Arial", 10)
                Dim lineHeight As Single = Font.GetHeight(e.Graphics)
                ' Cree 2 variables pour memoriser position dans page
                '(hors marges).
                Dim xPosPage As Single = e.MarginBounds.Left
                Dim yPosPage As Single = e.MarginBounds.Top
                ' Incremente compteur de page (page à imprimer).
                doc.NumeroPage += 1
                ' Imprime tout texte tenant sur une page.
                ' Boucle se termine quand prochaine ligne courante va au dela 
                ' marge basse , ou il n' y a plus de lignes sur la page .
                While ((yPosPage + lineHeight) < e.MarginBounds.Bottom And doc.Offset _
                        <= doc.Texte.GetUpperBound(0))
                    e.Graphics.DrawString(doc.Texte(doc.Offset), Font, _
                                            Brushes.Black, xPosPage, yPosPage)
                    ' Incremmente ligne suivante du doc.
                    doc.Offset += 1
                    ' Incremmente Coords Y de ligne suivante.
                    yPosPage += lineHeight
                End While
                If doc.Offset < doc.Texte.GetUpperBound(0) Then
                    ' S'il y a encore au moins une page . 
                    ' declenche PrintPage.
                    e.HasMorePages = True
                End If
            End Using
        End Sub
    End Class
    Public Class TexteDocument
        Inherits PrintDocument
     
        Private m_Texte As String()
        Private m_NumeroPage As Integer
        Private m_Offset As Integer
        Public Sub New(ByVal txt As String())
            Me.Texte = txt
        End Sub
        Public Property Texte() As String()
            Get
                Return m_Texte
            End Get
            Set(ByVal value As String())
                m_Texte = value
            End Set
        End Property
        Public Property NumeroPage() As Integer
            Get
                Return m_NumeroPage
            End Get
            Set(ByVal value As Integer)
                m_NumeroPage = value
            End Set
        End Property
        Public Property Offset() As Integer
            Get
                Return m_Offset
            End Get
            Set(ByVal value As Integer)
                m_Offset = value
            End Set
        End Property
     
    End Class
    bon code.....

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 69
    Par défaut
    Les pages en question lorsqu'elles sont imprimées le sont en mode graphique, pas textuel. La notion de ligne n'est donc pas pertinente pour la page.
    La notion de lignes n'est pas liée à la page elle-même puisque sur celle-ci je dessine des éléments divers (images et textes) placés précisemment au pixel près.

    Hors dans mon système les éléments texte sont des cadres qui peuvent avoir une largeur fixe mais dont la hauteur doit s'adapter au contenu. C'est là que les lignes interviennent. Il faut les déterminer dynamiquement d'après la largeur du cadre, la police et le texte lui-même.

    En l'absence d'autres suggestions j'en ai été réduit à "reconstruire" le texte mot à mot en le remesurant à chaque fois pour déterminer si une nouvelle ligne doit être créée, et le cas écheant passer à la page suivante.

    C'est lourd, lent et peu élégant. Si quelqu'un a mieux...

  4. #4
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Je dirais :
    Tu fais un measurestring qui va te donner le rectangle du ton texte
    Si ce rectangle deborde en hauteur la taille disponnible tu reduit ton texte de maniere proportionnelle au debordement

    Il y a certainement plusieur maniere d'affiner mais la meilleure approche sera dichotomique, il n'existe pas de methode directe permettant de determiner d'un coup ou couper le texte

    N.B. Font.Height est aussi utile a connaitre.

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2004
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 69
    Par défaut
    Merci pour ta réponse.

    C'est en fait ce que je fais déjà, mais à l'envers : je construis mon texte mot à mot en le mesurant à chaque fois pour déterminer si ça déborde et adapter en conséquence l'affichage.

    Je souhaitais simplement savoir s'il existait une méthode plus efficace et élégante.

  6. #6
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    Pour construire toutes les lignes, on peut créer une TextBox de travail (Visible=false, Multiline=true, WordWrap=true) utilisant la font cible et d'une largeur égale à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MyTextBox.Width= (Largeur_en_pixels_de_la_zone_texte_sur_imp*96) / 
       MyPrintDocument.PrinterSettings.DefaultPageSettings.PrinterResolution.X
    Ensuite, on pourra récupérer les lignes, via la propriété Lines de la TextBox.

Discussions similaires

  1. [MySQL] Système de découpage de texte html pour créer des pages
    Par heretik25 dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 19/01/2012, 16h00
  2. Utilitaire Windows pour le découpage de texte entre 2 balises
    Par toulouse4556 dans le forum Windows XP
    Réponses: 4
    Dernier message: 14/10/2009, 19h12
  3. Doute sur mon code, découpage de texte
    Par goblin dans le forum Langage
    Réponses: 3
    Dernier message: 16/10/2006, 20h26
  4. Réponses: 10
    Dernier message: 10/05/2006, 22h04
  5. découpage de fichier image + texte
    Par dirty_boy dans le forum C
    Réponses: 8
    Dernier message: 13/03/2006, 18h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo