Ho la necessità di creare delle stampe con GDI+ in quanto vorrei stampare i dati di mie classi e non dati presenti su un DB (attraverso Dataset).
Ho tutto abbastanza chiaro sul funzionamento ma mi trovo a scontrarmi con la gestione delle sezioni di stampa che in GDI+ non sono presenti (o almeno non ho trovato).
Per gestire il la stampa ho deciso di crearmi un sorta di stream personalizzato ereditando dalla classe PrintDocument. Fondamentalmente, estendo la classe PrintDocument con una collection e itero sulla collection per avere i vari oggetti da stampare in ordine: nel metodo PrintPage gestisco un oggetto della collection alla volta.
Per questo motivo ho deciso di spostare tutta la gestione dei dati nel mio streming mentre nel metodo PrintPage gestisco solo il layout di stampa.
Il tutto funziona bene quando mi trovo a stampare dei semplici elenchi "non strutturati", ma non riesco a capire come fare per stampare eventuali "sezioni" (rubando la terminologia a Crystal Report).
Nella fattispecie ho una serie di Commesse che sono formate da una serie di Componenti ciascuna. Praticamente ho una classe Commessa ed una classe Componente. La classe componente contiene una proprietà di tipo Commessa. Ho anche 2 classi collection per Commesse e per Componenti con dei costruttori che permettono di effettuare delle "selezioni" (ad esempio nella collection Componenti ho un costruttore che come parametro accetta una Commessa).
Per stampare un elenco di componenti di una singola commessa uso il seguente "stream":
Imports System.ComponentModel
Imports System.Drawing
Public Class PrintCommessa
Inherits Printing.PrintDocument
Private _offSet As Integer
Private _list As BindingList(Of Object)
Private _pageNumber As Integer
Private _hasMore As Boolean = False
Public Sub New(ByVal Commessa As Commessa)
_offSet = 0
_list = New BindingList(Of Object)
Dim cp As New Componenti.Componenti(Commessa)
For Each comp As Componenti.Componente In cp
_list.Add(comp)
Next
If _list.Count > 0 Then _hasMore = True
End Sub
Protected Friend Function GetNextObject() As Object
_offSet += 1
If _offSet = _list.Count Then _hasMore = False
Return _list(_offSet - 1)
End Function
Protected Friend Property PageNumber() As Integer
Get
Return _pageNumber
End Get
Set(ByVal value As Integer)
_pageNumber = value
End Set
End Property
Protected Friend ReadOnly Property HasMore() As Boolean
Get
Return _hasMore
End Get
End Property
End Class
Questo mi permette di stampare un elenco di Componenti per una singola commessa in quanto nel metodo PrintPage utilizzo il seguente ciclo:
Do Until doc.HasMore = False And AreaP.Y <= e.MarginBounds.Bottom
Dim o As Object = doc.GetNextObject
If TypeOf o Is Componente Then
'... Stampa dati componente...
End If
Loop
Questo mi permette di avere nel mio stream anche oggetti diversi e riesco ad identificare attraverso l'Offset su quale oggetto sono: inserendo in modo appropriato gli oggetti sullo "stream" posso anche capire quando devo stampare una intestazione di sezione.
Ora finalmente le domande (che sono una serie):
- Se volessi stampare un piede di sezione con i totali come posso fare a capire esattamente dove sono, essendo lo stream un elenco non strutturato?
- Se non volessi usare una List(Of Object) nella classe "Stream" dite che è possibile? (restituirei comunque un oggetto Object al metodo PrintPage ma avrei un maggiore controllo lato "stream").
- Ho pensato anche di far diventare l'OffSet una struttura per memorizzare dati sul posizionamento dello stream, ma non capisco come...
Avete consigli in merito? Anche solo delle indicazioni (ho cercato molto sul Web ma non tovo nulla se non stampe semplici).
Grazie mille, ogni suggerimento è assolutamente ben accetto.
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole