Appunti di Programmazione

Creative Commons License

Pagina 1 2 3 4 5 6 7 8

Stampare del testo multi-pagina

E se il testo fosse lungo diverse pagine?

Come detto in precedenza si utilizza la proprietà e.HasMorePages; però è anche necessario valutare lo spazio che abbiamo a disposizione, per verificare se le righe che compongono il paragrafo che stiamo processando, possono essere inserite, o bisogna passare alla pagina successiva.

Area di Stampa

Si procede in questo modo:

Si preleva il testo da stampare, da un file e lo si inserisce in una stringa (Testo).
Attraverso un ciclo si scorre tutto il documento suddividendolo in paragrafi e depositandoli in una collection (ListaParagrafi) il cui contenuto sarà letto di volta in volta dalla stringa TestoM.
Ovviamente si devono definire il font (NuovoFont) e il tipo di formattazione per il nostro documento (CustomFormat). In questo caso abbiamo deciso per un allineamento a sinistra (StringAlignment.Near), e abbiamo imposto che, qualora in una riga una parola sia troppo lunga da inserire, essa debba essere scritta nella linea successiva (StringTrimming.Word), piuttosto che divisa a metà.
Inoltre per quanto riguarda l'ultima linea della pagina, abbiamo scelto di visualizzare solo righe intere (StringFormatFlags.LineLimit), in quanto può capitare che con una particolare dimensione di un font, la riga in questione venga disegnata per metà in una pagina e per metà nella successiva, impedendo al lettore di leggere correttamente quanto scritto.

A questo punto si può procedere con lo stampare il testo nella pagina.
Inizialmente lo spazio a disposizione (AreaDisponibile) è pari a tutto il foglio, esclusi i margini di stampa.
Si prendono i paragrafi uno alla volta e li misuriamo valutandone le dimensioni (DimensioneTesto) per potere capire quanto spazio occupano e in quale posizione (y) iniziare a scriverli. Vi sono due variabili, characters_fitted e line_filled che memorizzano il numero di caratteri inseriti e le linee occupate dal paragrafo, recuperabili, come riferimenti, dal metodo Graphics.MeasureString(...).
Se il paragrafo contiene dei caratteri significa che non è una linea vuota e che può essere disegnato, altrimenti si procede oltre. Finito di scrivere il paragrafo, si recupera dalla variabile characters_fitted, quanti caratteri sono stati effettivamente disegnati e la stringa che contiene il testo (TestoM) viene aggiornata perché contenga l'eventuale rimanenza di caratteri da stampare.

Questa è una situazione che si verifica soltanto quando viene processato un paragrafo che è prossimo alla fine della pagina. Se esso occupa una spazio maggiore di quello disponibile, si rende necessario dividerlo in due parti, da visualizzare alla fine di una pagina e all'inizio della successiva rispettivamente.
Se ciò accade, automaticamente viene valutata la proprietà e.HasMorePages e se risulta True, viene richiamato il metodo PrintDocument1_PrintPage1 per continuare la stampa in una nuova pagina, altrimenti si va avanti fino a quando finisce la pagina o finisce il documento.

Per concludere, nell'evento PrintDocument1_EndPrint1 si insericono le procedure per il rilascio delle risorse.

Imports System.Drawing.Printing

Public Class Form1

    'definizione di un button
    Private WithEvents Button1 As New Button

    'definizione di un documento di stampa
    Private WithEvents PrintDocument1 As New PrintDocument

    'definizione della finestra di dialogo "Anteprima"
    Private PrintPreviewDialog1 As New PrintPreviewDialog

    'definizione di un nuovo font
    Private NuovoFont As Font

    'definizione della variabile che contiene il testo
    Dim Testo As String

    'definizione del formato del testo
    Dim CustomFormat As New StringFormat

    'definizione dei paragrafi che compongono il testo
    Dim ListaParagrafi As Collection

    'definizione del contatore per la collection paragrafi
    Dim conteggio As Integer

    'inizializzazione dei componenti Form e Button
    Public Sub New()

        InitializeComponent()

        'imposta la form
        Me.Size = New Size(210, 180)
        Me.Text = "Stampa Testo"

        'imposta il button
        Button1.Size = New Size(100, 30)
        Button1.Location = New Point(51, 58)
        Button1.Text = "Anteprima"

        'aggiunge il button alla form
        Me.Controls.Add(Button1)

    End Sub

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

        'anteprima di stampa del "documento"
        PrintPreviewDialog1.Document = PrintDocument1
        PrintPreviewDialog1.Show()

    End Sub

    'Inpostazioni iniziali prima dell'avvio del processo di stampa
    Private Sub PrintDocument1_BeginPrint1(ByVal sender As Object, ByVal e As _
    System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

        'creazione di una nuova istanza di tipo collection
        ListaParagrafi = New Collection

        'legge il testo contenuto nel file indicato
        Testo = My.Computer.FileSystem.ReadAllText("d:\documenti\Prova.txt")

        'suddivide il testo in paragrafi e li inserisce nella collection ListaParagrafi
        Dim paragrafo As String = ""

        'legge il testo carattere per carattere...
        For Each carattere As Char In Testo

            'se il carattere corrisponde ad un'ANDATA A CAPO
            If carattere = vbLf Then

                'aggiunge il paragrafo alla collection
                ListaParagrafi.Add(paragrafo)

                'resetta il paragrafo
                paragrafo = ""

            Else

                'aggiunge il carattere al paragrafo
                paragrafo += carattere

            End If

        Next

        'aggiorna il conteggio dei paragrafi
        conteggio = ListaParagrafi.Count

        'definisce il font
        NuovoFont = New Font("Arial", 20, FontStyle.Regular, GraphicsUnit.Pixel)

        'allineamento orizzontale: vicino (near) al margine sinistro
        CustomFormat.Alignment = StringAlignment.Near

        'Impone di visualizzare solo linee intere. Potrebbe accadere che l'ultima linea sia disegnata per metà alla fine
        'di una pagina e per l'altra metà all'inizio della successiva; questa istruzione impone che siano disegnate solo
        'linee intere
        CustomFormat.FormatFlags = StringFormatFlags.LineLimit

        'Impone di visualizzare parole intere impedendo che siano troncate quando vengono stampate
        'vicino alla fine della riga
        CustomFormat.Trimming = StringTrimming.Word

    End Sub

    Private Sub PrintDocument1_PrintPage1(ByVal sender As Object, ByVal e As _
    System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

        'Area a disoposizione in cui è possibile scrivere il paragrafo che viene processato in quel momento
        Dim areaDisponibile As RectangleF

        'dimensioni dello spazio occupato dal paragrafo quando viene valutato
        Dim dimensioniTesto As SizeF

        'numero dei caratteri totali che compongono il paragrafo
        Dim characters_fitted As Integer

        'linee occupate del paragrago in questione
        Dim line_filled As Integer

        'coordinata y alla quale viene inserito il paragrafo in corso di scrittura
        Dim y As Integer = 0

        'valore dell'indice della collection "ListaParagrafi"
        Dim indice As Integer

        'stringa che contiene il testo modificato
        Dim TestoM As String

        Do While conteggio > 0

            'se la posizione del prossimo paragrafo non ha ancora raggiunto il margine inferiore...
            If (y + e.MarginBounds.Top) < e.MarginBounds.Bottom Then

                'definizione dell'AreaDisponibile
                areaDisponibile = New RectangleF(e.MarginBounds.Left, _
                e.MarginBounds.Top + y, _
                e.MarginBounds.Width, _
                e.MarginBounds.Bottom - e.MarginBounds.Top - y)

                'imposta l'indice della colection
                indice = ListaParagrafi.Count - conteggio + 1

                'recupera il testo del paragrafo inserito nella colection
                TestoM = ListaParagrafi.Item(indice).ToString

                'valutazione della dimensione del testo
                dimensioniTesto = e.Graphics.MeasureString(TestoM, _
                NuovoFont, _
                New SizeF(areaDisponibile.Width, areaDisponibile.Height), _
                CustomFormat, characters_fitted, line_filled)

                'se il paragrafo è composto da caratteri allora lo si scrive ( potrebbe essere una linea vuota...)
                If characters_fitted > 0 Then

                    e.Graphics.DrawString(TestoM, _
                    NuovoFont, Brushes.Black, _
                    areaDisponibile, CustomFormat)
                    y += CType(dimensioniTesto.Height, Integer)

                End If

                'la variabile per il testo modificato contiene il documento rimanente qualora non vi sia stato spazio
                'sufficiente per disegnare tutto il contenuto del paragrafo.
                'Substring permette di recuperare il testo finale della stringa a partire dall'indice indicato.
                TestoM = TestoM.Substring(characters_fitted)

                'se il testo modificato contiene caratteri allora vuol dire che siamo a fine pagina
                'pertanto sostituiamo il paragrafo che stiamo valutando con il contenuto di TestoM
                'quindi si esce dal ciclo Do...Loop
                If TestoM.Length > 0 Then

                    'rimozione del paragrafo originale
                    ListaParagrafi.Remove(indice)

                    'riscrittura del nuovo paragarfo
                    ListaParagrafi.Add(TestoM, , indice, )

                    Exit Do

                End If

            End If

            'aggiorna il contatore
            conteggio -= 1

        Loop

        'quando arriviamo a fine pagina viene controllata e.HasMorePages per sapere se vi sono altri fogli da stampare
        'e ciò avviene se il risultato è True.
        e.HasMorePages = (conteggio > 0)

    End Sub

    Private Sub PrintDocument1_EndPrint1(ByVal sender As Object, ByVal e As _
    System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.EndPrint

        'rilascia le risorse occupate dal testo
        NuovoFont.Dispose()
        NuovoFont = Nothing

    End Sub

End Class

Stampa testo multi-pagina

Download sorgente "Stampa_Tante_Pagine.zip" ( 68KB )

Pagina 1 2 3 4 5 6 7 8