Appunti di Programmazione

Creative Commons License

Pagina 1 2 3 4 5 6 7 8

Oggetti di stampa

Applicazione Windows Form

Il processo di stampa è presente in quasi ogni applicazione, sia essa un database, un CAD o un agenda elettronica, c'è sempre la necessità di mettere su carta il risultato del nostro lavoro.
Il .Net framework ci offre vari strumenti per inserire questa funzionalità nei propri programmi. Non à un processo difficile ma neanche così immediato come uno vorrebbe, ma con un poco di pazienza e di lavoro si ottengono ottimi risultati.

In quanto utente, per stampare su carta quello che ho sullo schermo, mi basta premere l'icona della stampante e per "MAGIA" i dati sul monitor vengono trasferiti su carta in pochi minuti.
Credevo, molto ingenuamente, che schermo e stampante fossero in simbiosi, ma cercando informazioni sulla realizzazione di questo processo, ho capito che non è così: inviare al monitor i dati da mostrare all'utente finale è un processo distinto da quello necessario per riprodurre su carta gli stessi dati, pertanto bisogna capire in che modo ragionare per raggiungere il nostro obiettivo.

Occorre pensare alla stampante come ad una periferica in cui è necessario riprodurre graficamente ogni più piccolo dettaglio, indipendentemente da come viene visualizzato sullo schermo, e in fin dei conti è pure giusto: un monitor ha dimensioni fisiche molto diverse dal formato dei fogli usati per la stampa.

Se dobbiamo stampare una DataGridView è necessario disegnare letteralmente la tabella, colorarla opportunamente e popolarla di dati disegnando il testo all'interno delle celle. Inoltre bisogna controllare se la lunghezza della tabella è tale da occupare più pagine ed eventualmente suddividerla in modo da non lasciare righe a metà.
Purtroppo non esiste un comando DataGridView.Print, e avere una tabella già formattata, colorata e riempita di dati sul monitor non serve assolutamente a niente.

Se dobbiamo stampare un'immagine, una foto o un disegno, è opportuno valutarne le dimensioni per rapportarle a quelle del foglio di stampa, in modo da capire se può essere messa su carta o è necessario scalarla per farla rientrare nei margini impostati.

La stampa del testo è un pò più facile, anche se diventa più laboriosa qualora il nostro documento contenga anche delle immagini.

Oggetti per Stampare

Nel .Net framework troviamo cinque oggetti:

1.PageSetupDialog: è una finestra di dialogo che permette di impostare vari parametri di stampa come il formato del foglio, l'orientamento, i margini e la stampante.

Imposta Pagina

2.PrintDialog: consente di visualizzare la classica finestra di stampa che propone varie opzioni di scelta fra tipo di stampante, numero di copie, intervallo di stampa... ecc.

Stampa

3.PrintPreviewDialog: con questo oggetto si accede alla finestra "Anteprima di Stampa"

Anteprima

4.PrintPreviewControl: si tratta di un componente (quello dentro il rettangolo rosso) che può essere inserito in modo permanente all'interno di una form per generare un'anteprima di stampa da visionare, senza dovere chiamare il controllo PrintPreviewDialog. Generalmente viene usato per creare un controllo personalizzato dell'anteprima di stampa.

Controllo Anteprima

5.PrintDocument: l'oggetto in assoluto più importante per generare una stampa. Esso rappresenta e descrive il documento da stampare. È al suo interno che vanno inserite tutte le istruzioni necessarie alla definizione dell'oggetto da mettere su carta.
Esso può generare 4 eventi:

- BeginPrint: viene intercettato questo evento quando il processo di stampa sta per iniziare. È quà che vengono impostati i dati, connessi i database e attivate qualunque altre azioni legate alla partenza della stampa.

- QueryPageSetting: prima della stampa, può essere utile catturare questo evento per modificare le impostazioni della pagina.

- PrintPage: l'evento più importante, perché è in esso che solitamente vengono inserite tutte le istruzioni per la definizione degli oggetti da stampare e la verifica se vi sono più pagine o meno da mettere su carta.

- EndPrint: evento che viene sollevato alla fine del processo di stampa. Può essere utilizzato per il rilascio delle risorse o la chiusura di un database a cui eravamo collegati.

La Stampa in pratica

La scrittura del codice per gestire il processo di stampa si può riassumere in questi punti:

- Importare il Namespaces System.Drawing.Printing che contiene gli oggetti necessari per la stampa e la gestione delle periferiche atte a mettere su carta i nostri documenti.

Imports System.Drawing.Printing

- Utilizzare uno o più degli oggetti sopra descritti ( PageSetupDialog, PrintDialog, PrintPreviewDialog, PrintPreviewControl e PrintDocument), per impostare la pagina, la periferica di stampa e inviare i dati alla stampante.

- Impostare i dati da processare all'interno dell'evento NomeDocumento_PrintPage, dove NomeDocumento è un'istanza dell'oggetto PrintDocument.

Private Sub NomeDocumento_PrintPage1(ByVal sender As Object, ByVal e As System.Drawing.Printing. PrintPageEventArgs) Handles NomeDocumento.PrintPage

... ...

End Sub

- Gestione della proprietà e.HasMorePages per consentire la stampa di più pagine.
Se tale proprietà risulta True il compilatore richiama l'evento NomeDocumento_PrintPage e continua a stampare fino a che la proprietà diventa False o termina il flusso di dati da gestire.

Il codice necessario può essere simile al seguente:

If condizione then

e.HasMorePages = True 'fintanto risulta True vengono stampate altre pagine

Else

e.HasMorePages = False 'quando diventa False termina il processo di stampa

End If

Oppure

e.HasMorePage=(condizione)

Tenete presente che per stampare qualunque cosa, anche del semplice testo, è necessario usare comandi grafici della GDI+ (Graphics Device Interface +).

e.Graphics.DrawLine(...) per disegnare una linea
e.Graphics.DrawRectangle(...) per disegnare un rettangolo
e.Graphics.DrawEllipse(...) per disegnare un ellisse o un cerchio
e.Graphics.DrawPolygon(...) per disegnare un poligono
e.Graphics.DrawString(...) per disegnare del testo
... ...

Facciamo un esempio per concretizzare quanto esposto finora.

Imports System.Drawing.Printing

Public Class Form1

    'il nostro Documento da Stampare
    Friend WithEvents DocumentoDaStampare As New PrintDocument

    'pulsante per la stampa diretta senza finestre di dialogo
    Private WithEvents btnStampa As New Button

    'pulsante per stampare attraverso la normale e consueta finestra di dialogo "STAMPA"
    Private WithEvents btnPrintDialog As New Button

    'pulsante per l'utilizzo dell'anteprima
    Private WithEvents btnPrintPreviewDialog As New Button

    'pulsante per impostare la pagina di stampa
    Private WithEvents btnPageSetupDialog As New Button

    'i nostri oggetti per la stampa:
    'finestra di dialogo "STAMPA"
    Private PrintDialog1 As New PrintDialog

    'finestra "ANTEPRIMA"
    Private PrintPreviewDialog1 As New PrintPreviewDialog

    'Fimestra "IMPOSTA PAGINA"
    Private PageSetupDialog1 As New PageSetupDialog

    'controllo "ANTEPRIMA" da usare nei controlli utente personalizzati
    Friend WithEvents PrintPreviewControl1 As New PrintPreviewControl

    Public Sub New()

        InitializeComponent()

        'impostiamo la nostra form
        With Me
            Size = New Size(500, 500)
            .Text = "Oggetti di Stampa"
        End With

        'impostiamo il pulsante per la stampa diretta
        With btnStampa
            .Size = New Size(125, 25)
            .Location = New Point(25, 25)
            .Text = "Stampa"
        End With

        'impostiamo il pulsante per la visualizzazione della finestra Stampa
        With btnPrintDialog
            .Size = New Size(125, 25)
            .Location = New Point(25, 55)
            .Text = "PrintDialog"
        End With

        'sistemiamo quello per la finestra Anteprima
        With btnPrintPreviewDialog
            .Size = New Size(125, 25)
            .Location = New Point(25, 85)
            .Text = "PrintPreviewDialog"
        End With

        'quello per le impostazioni della pagina
        With btnPageSetupDialog
            .Size = New Size(125, 25)
            .Location = New Point(25, 115)
            .Text = "PageSetupDialog"
        End With

        'e infine per il controllo per la rappresentazione permanente dell'anteprima
        With PrintPreviewControl1
            .Size = New Size(300, 400)
            .Location = New Point(170, 25)
            .Document = DocumentoDaStampare
            .Zoom = 0.25
            .UseAntiAlias = True
            .Anchor = CType((((System.Windows.Forms.AnchorStyles.Top _
                               Or System.Windows.Forms.AnchorStyles.Bottom) _
                               Or System.Windows.Forms.AnchorStyles.Left) _
                               Or System.Windows.Forms.AnchorStyles.Right),  _
                               System.Windows.Forms.AnchorStyles)
        End With


        'aggiungiamo i controlli appena impostati alla nostra form
        Me.Controls.Add(btnStampa)
        Me.Controls.Add(btnPrintDialog)
        Me.Controls.Add(btnPrintPreviewDialog)
        Me.Controls.Add(btnPageSetupDialog)
        Me.Controls.Add(PrintPreviewControl1)

    End Sub

    Private Sub btnStampa_Click(ByVal sender As Object, ByVal e As System.EventArgs)Handles btnStampa.Click

        'stampa diretta: si invia alla stampante il nostro documento
        DocumentoDaStampare.Print()

    End Sub

    Private Sub btnPrintDialog_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles btnPrintDialog.Click

        'se nella finestra di dialogo STAMPA viene premuto il tasto OK allora...
        If PrintDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then

            'il documento da mettere su carta=il nostro documento da stampare
            PrintDialog1.Document = DocumentoDaStampare

            ' e infine lo si stampa
            PrintDialog1.Document.Print()

        End If

    End Sub

    Private Sub btnPrintPreviewDialog_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles btnPrintPreviewDialog.Click

        'associamo il nostro documento da stampare alla finestra ANTEPRIMA
        PrintPreviewDialog1.Document = DocumentoDaStampare

        'quindi visualizziamo la finestra con il contenuto del nostro documento
        PrintPreviewDialog1.ShowDialog()

    End Sub

    Private Sub btnPageSetupDialog_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles btnPageSetupDialog.Click

        'creaiamo un nuovo oggetto Impostazioni Pagina
        PageSetupDialog1.PageSettings = New System.Drawing.Printing.PageSettings

        'e un nuovo oggetto Impostazioni stampante
        PageSetupDialog1.PrinterSettings = New System.Drawing.Printing.PrinterSettings

        'associamo il nostro documento da stampare alla finestra di dialogo IMPOSTA PAGINA
        PageSetupDialog1.Document = DocumentoDaStampare

        'mostriamo la finestra
        PageSetupDialog1.ShowDialog()

    End Sub

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

        'istanziamo una nuova penna
        Dim penna As New Pen(Color.Black, 10)

        'creiamo una matrice di 4 punti che raccolgono le coordinate dei vertici del rombo che disegneremo 
        Dim punti() As Point = { _
                New Point(e.MarginBounds.Left + e.MarginBounds.Width \ 2, e.MarginBounds.Top), _
                New Point(e.MarginBounds.Right, e.MarginBounds.Top + e.MarginBounds.Height \ 2), _
                New Point(e.MarginBounds.Left + e.MarginBounds.Width \ 2, e.MarginBounds.Bottom), _
                New Point(e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height \ 2)}

        'disegnamo il poligono composto dai 4 vertici appena dichiarati
        e.Graphics.DrawPolygon(penna, punti)

        'rilasciamo le risorse occupate dalla penna
        penna.Dispose()

        'impostiamo la proprietà a False per comunicare al compilatore che la pagina da stampare è una soltanto
        e.HasMorePages = False

    End Sub

End Class

Oggetti di Stampa

Download sorgente "Oggetti_di_Stampa.zip" ( 67KB )

Avviando il progetto apparirà una form con 4 pulsanti sulla sinistra e un controllo PrintPreviewControl sulla destra che mostra un'anteprima di stampa del documento impostato nell'evento DocumentoDaStampare_PrintPage.
I pulsanti attivano i componenti sopra descritti, tranne il primo che mostra come sia possibile inviare alla stampante il nostro documento (un normale rombo) in modo diretto senza passare attraverso finestre di dialogo.

Pagina 1 2 3 4 5 6 7 8