PDA

View Full Version : [VB.NET] Problema formato di stampa personalizzato


jackk87
13-11-2009, 06:29
Buongiorno,
ho bisogno di effettuare la stampa su un formato personalizzato cioè il formato per un contocorrente e nell'evento load del form ho inserito questo:

Dim pSize As New PaperSize()
pSize.PaperName = "Conto Corrente"
pSize.Width = 326.8
pSize.Height = 433.1

PrintDocument1.PrinterSettings.DefaultPageSettings.PaperSize = pSize


effettuo l'anteprima di stampa e tutto funziona correttamente.
Addesso se io nel programma voglio cambiare stampante o voglio cambiare un margine di stampa allora utilizzo PageSetupDialog settato così:


PSDialog.PageSettings = New System.Drawing.Printing.PageSettings

PSDialog.AllowPaper = True
PSDialog.AllowOrientation = False
PSDialog.PrinterSettings = New System.Drawing.Printing.PrinterSettings

PSDialog.Document = documentoCC

PSDialog.ShowDialog()


La pagina si apre correttamente e funziona correttamente cioè se cambio la stampante la cambia se cambio i margini la cambia però il problema è il formato di stampa cioè se cambio margine o la stampante e successivamente faccio ok per apportare le modifiche si prende anche il formato che viene visualizzato tra i formati come faccio per far visualizzare il formato personalizzato Conto Corrente tra i Formati di Default della stampante?

Spero che qualcuno può aiutarmi grazie in anticipo a tutti :help:

MarcoGG
13-11-2009, 13:08
Non ho ben chiaro cosa tu vuoi / non ti riesce di fare... :stordita:
Se per un certo job di stampa il formato è sempre quello ( il tuo "Conto Corrente" ) perchè permettere all'utente di modificarlo con una PageSetupDialog ? Non potresti semplicemente mandare in stampa il documento con le dimensioni personalizzate ?

jackk87
13-11-2009, 14:03
Non ho ben chiaro cosa tu vuoi / non ti riesce di fare... :stordita:
Se per un certo job di stampa il formato è sempre quello ( il tuo "Conto Corrente" ) perchè permettere all'utente di modificarlo con una PageSetupDialog ? Non potresti semplicemente mandare in stampa il documento con le dimensioni personalizzate ?

Ciao Marco,
si hai perfettamente ragione posso mandare direttamente in stampa il documento con le impostazioni personalizzate però devo permettere anche all'utente di impostare i margini e di cambiare la stampante ecco perchè stavo pensado al pagesetupdialog.
Se far comparire il formato personalizzato tra i formati della pagesetupdialog (che cambiano da stampante a stampante) è impossibile oppure è qualcosa di complicato, stavo pensando di crearmi un form tipo quello di pagesetupdialog dove l'utente può impostare i margini e un pulsante che va a chiamare una printdialog così da impostare la stampante se serve cosa ne pensi?hai qualche altra idea?

grazie Marco :D

MarcoGG
14-11-2009, 08:57
1. Anzitutto non ho ben capito il perchè del tuo codice... :confused: . Perchè nel secondo blocco fai :

PSDialog.PageSettings = New System.Drawing.Printing.PageSettings
...
PSDialog.PrinterSettings = New System.Drawing.Printing.PrinterSettings

2. Tutte le proprietà attinenti alla collection dei formati di stampa disponibili per ogni stampante sulla PageSetupDialog, some ad esempio PageSetupDialog.PrinterSettings.PaperSizes, sono ReadOnly, perciò con ogni probabilità non riuscirai mai ad infilarci il tuo formato personalizzato...

3. Alla fin fine, questa PageSetupDialog non è così indispensabile, e non è certo difficile da replicare. Puoi costruirti la "tua PageSetupDialog", molto più completa e flessibile, ad esempio filtrando e aggiungendo sulla Combo dei formati disponibili...
Scrivere codice pemettere di costruire oggetti molto più interessanti rispetto a soluzioni precucinate...
Ad esempio, per iniziare, puoi inserire sulla tua "PageSetupDialog", 3 Combo :
- cmb_printers
- cmb_formati
- cmb_alimentazioni

La dichiarazione del document è Private a livello di Form :
Private DOC As New Printing.PrintDocument

cmb_printers contiene l'elenco delle stampanti installate :

cmb_printers.DropDownStyle = ComboBoxStyle.DropDownList
cmb_printers.Items.Clear()
For Each printer As String In Printing.PrinterSettings.InstalledPrinters
cmb_printers.Items.Add(printer)
Next
cmb_printers.SelectedIndex = 0

Sul SelectedIndexChanged della cmb_printers vai a popolare le altre :

Private Sub cmb_printers_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_printers.SelectedIndexChanged

DOC.PrinterSettings.PrinterName = cmb_printers.Text

'Formati disponibili per printer
cmb_formati.DropDownStyle = ComboBoxStyle.DropDownList
cmb_formati.Items.Clear()
For Each psz As Printing.PaperSize In DOC.PrinterSettings.PaperSizes
cmb_formati.Items.Add(psz.PaperName)
Next
cmb_formati.SelectedIndex = 0

'Alimentazioni disponibili per printer
cmb_alimentazioni.DropDownStyle = ComboBoxStyle.DropDownList
cmb_alimentazioni.Items.Clear()
For Each psc As Printing.PaperSource In DOC.PrinterSettings.PaperSources
cmb_alimentazioni.Items.Add(psc.SourceName)
Next
cmb_alimentazioni.SelectedIndex = 0

End Sub

Ogni azione sulla Form va ad aggiungere o modificare qualcosa su DOC, che è il vero elemento centrale di tutto, non le varie Dialog... ;)

jackk87
14-11-2009, 10:35
Marco grazie veramente di tutto ora cerco di fare il tutto se ho qualche problema ti faccio sapere :D sei un grande!

jackk87
14-11-2009, 22:41
Ciao Marco mi sono creato la mia PageSetupDialog personalizzata ciò inserito anche un pulsante proprietà al fianco della combobox stampanti che vorrei che al click si apre le proprietà della stampante (ancora non ci sono riuscito se mi puoi aiutare altrimenti non è importante) la cosa più importante è che al click di ok della mia PageSetupDialog come faccio ad impostare quel formato quella stampante alla mia pagina in modo che quando lancio la stampa prende quelle impostazioni?

Marco grazie per la disponibilità

MarcoGG
15-11-2009, 10:43
Ciao Marco mi sono creato la mia PageSetupDialog personalizzata ciò inserito anche un pulsante proprietà al fianco della combobox stampanti che vorrei che al click si apre le proprietà della stampante (ancora non ci sono riuscito se mi puoi aiutare altrimenti non è importante) la cosa più importante è che al click di ok della mia PageSetupDialog come faccio ad impostare quel formato quella stampante alla mia pagina in modo che quando lancio la stampa prende quelle impostazioni?

Marco grazie per la disponibilità

- Proprietà stampante : si può fare direttamente con un certo giro di chiamate API. Ovviamente NON lo farei, fossi in te. Rischi di creare un secondo "binario parallelo" a ciò che già stai facendo con la tua PageSetupDialog custom, mettendo l'utente nella possibilità di cambiare impostazioni che vanno in conflitto con quelle definite a livello di PrintDocument... Non è una bella idea.

- Come già detto l'oggetto su cui focalizzare le azioni è il PrintDocument, ossia DOC, nel mio esempio. Il codice che avevi scritto va bene :

Dim pSize As New Printing.PaperSize
pSize.PaperName = "Conto Corrente"
pSize.Width = 326.8
pSize.Height = 433.1
DOC.DefaultPageSettings.PaperSize = pSize

Per i margini puoi evere 4 TextBox, esattamente come sulla PageSetupDialog, e impostarli sul DOC, una volta definiti :

DOC.DefaultPageSettings.Margins.Bottom = x
DOC.DefaultPageSettings.Margins.Left = y
DOC.DefaultPageSettings.Margins.Right = t
DOC.DefaultPageSettings.Margins.Top = z

In generale il concetto è che tu non "fai prendere alla stampante" il DOC, con tutte le sue impostazioni.
Al centro della scena non c'è la stampante, ed infatti non esiste un oggetto Printer, ma il PrintDocument.
Il percorso è al contrario. Prima fai una lista delle InstalledPrinters, e poi è DOC che semmai "si prende la stampante", come ho già scritto :

Private Sub cmb_printers_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_printers.SelectedIndexChanged

DOC.PrinterSettings.PrinterName = cmb_printers.Text
...
...
...

La scelta della stampante la si fa per prima. Se l'utente cambia stampante, è ovvio che bisogna resettare tutte le proprietà di DOC fin qui impostate e ricominciare da capo, perchè ad esempio, il tipo di alimentazione fogli scelto per la stampante A può non essere supportato dalla stampante B, e così per il formato, e per mille altre impostazioni...
Spero di essermi spiegato.

jackk87
18-11-2009, 19:27
Ciao MarcoGG ti sei spiegato perfettamente infatti funziona tutto alla perfezione vorrei chiederti un'ultimo consiglio riguardo i margini di stampa.
C'è la possibilità di impostare i margini di stampa come millimetri e non come centesimi di pollice?se no c'è qualche conversione già preimpostata?oppure devo farmi io la formula per convertire?

grazie ancora una volta :cool:

MarcoGG
19-11-2009, 11:44
Ciao MarcoGG ti sei spiegato perfettamente infatti funziona tutto alla perfezione vorrei chiederti un'ultimo consiglio riguardo i margini di stampa.
C'è la possibilità di impostare i margini di stampa come millimetri e non come centesimi di pollice?se no c'è qualche conversione già preimpostata?oppure devo farmi io la formula per convertire?

grazie ancora una volta :cool:

Se richiede centesimi di pollice, è comunque cosa di facile soluzione :

Private Function CentesimiPollice(ByVal millimetri As Double) As Integer
Return millimetri * 100 / 25.4
End Function

VB pensa a restituire già il valore Integer con le dovute approssimazioni per eccesso o difetto... ;)

jackk87
19-11-2009, 14:42
Grazie Marco sei un mito :cool:

jackk87
21-11-2009, 13:52
Ciao Marco,
ho un problema con i margini il codice è:

doc.OriginAtMargins=true

DOC.DefaultPageSettings.Margins.Left = CentesimiPollice(sinistra.Text)
DOC.DefaultPageSettings.Margins.Left = CentesimiPollice(sopra.Text)

dove sulla textbox sinistra se ci scrivo 5 che per me sarebbe che il margine sinistro deve essere di 5 millimetri e sopra imposto 10 e deve essere dieci millimetri.
poi con msgbox(DOC.DefaultPageSettings.Margins.Left.tostring) vedo che il margine di sinistra è uguale a 20 e quello di sopra è uguale a 39.

nell'anteprima mi cambiano in base a come cambio la stampante e questo è il primo problema.

il secondo è che ho provato a fare una stampa con questi margini stampando 2 linee una che mi parte con Y=0 e l'altra con X=0 prendendo le misure con un righello il risultato è:
Margine sinistro=10 mm
Margine superiore=31 mm

non c'è una relazione di unità di misura tra il margine superiore e il sinistro non sono ne millimetri ne centesimi di pollice non ci sto capendo più niente :muro:

Spero che mi puoi aiutare :help:

MarcoGG
22-11-2009, 12:01
Anzitutto bisogna capire COME stampi sul PrintDocument.

Nell'utilizzo standard bisogna usare l'evento .PrintPage di PrintDocument, nel mio esempio "DOC".

Non è vero che non c'è relazione tra le misure. Quando ad esempio si usa e.Graphics nell'evento PrintPage, le misure inserite nei vari Metodi Draw ( .DrawString, .DrawLine, ecc... ) vengono direttamente interpretate in centesimi di pollice.

Ti posto un semplice test di stampa che puoi provare con ogni stampante, e per capire cosa intendo per "uso corretto" ( o almeno, uno degli usi corretti ) del PrintDocument :

> Dichiarazioni :
Private WithEvents DOC As New Printing.PrintDocument
Private fontTesto1 As New Font("Arial", 14, FontStyle.Regular)

WithEvents per poter scrivere l'evento .PrintPage.

> pSize, margini e colore :
Dim pSize As New Printing.PaperSize
pSize.PaperName = "PROVA_A4"
pSize.Height = CentesimiPollice(297)
pSize.Width = CentesimiPollice(210)
DOC.DefaultPageSettings.PaperSize = pSize

'Margini
DOC.OriginAtMargins = True
DOC.DefaultPageSettings.Margins.Bottom = CentesimiPollice(txtmarginf.Text)
DOC.DefaultPageSettings.Margins.Left = CentesimiPollice(txtmargsn.Text)
DOC.DefaultPageSettings.Margins.Right = CentesimiPollice(txt_margdx.Text)
DOC.DefaultPageSettings.Margins.Top = CentesimiPollice(txt_margsup.Text)

'Colore / BN
If DOC.PrinterSettings.SupportsColor Then
DOC.DefaultPageSettings.Color = True
Else
DOC.DefaultPageSettings.Color = False
End If

La stampante di DOC è già stata scelta, col sistema illustrato in precedenza...

> Il PrintPage :

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

Dim corniceX As Integer = DOC.DefaultPageSettings.PaperSize.Width - DOC.DefaultPageSettings.Margins.Right - DOC.DefaultPageSettings.Margins.Left
Dim corniceY As Integer = DOC.DefaultPageSettings.PaperSize.Height - DOC.DefaultPageSettings.Margins.Top - DOC.DefaultPageSettings.Margins.Bottom

e.Graphics.DrawLine(Pens.Red, 0, 0, corniceX, 0)
e.Graphics.DrawLine(Pens.Red, corniceX, 0, corniceX, corniceY)
e.Graphics.DrawLine(Pens.Red, 0, 0, 0, corniceY)
e.Graphics.DrawLine(Pens.Red, 0, corniceY, corniceX, corniceY)

For i As Integer = 1 To 5
e.Graphics.DrawString(i * 25 & " mm", fontTesto1, Brushes.Green, 0, i * 50)
e.Graphics.DrawLine(Pens.Green, 0, i * 50, CentesimiPollice(i * 25), i * 50)
Next

End Sub

> La solita Function di conversione :
Private Function CentesimiPollice(ByVal millimetri As Double) As Integer
Return millimetri * 100 / 25.4
End Function

A questo punto, con DOC.Print(), parte la stampa effettiva, e si ottiene un foglio A4 bianco, con un riquadro rosso coincidente con i margini. Al suo interno 5 righe verdi di lunghezze diverse e relative quote. Dopo la stampa puoi controllare che margini e righe hanno distanze e lunghezze corrette. ;)

jackk87
22-11-2009, 13:20
Grazie Marco sei stato molto chiaro provo e se ho qualche problema ti faccio sapere grazie ancora ;)

jackk87
22-11-2009, 15:12
Ciao Marco finalmente grazie a te funziona tutto alla perfezione ora volevo chiederti una cosa che ho guardato anche su msdn ma niente l'unico che mi può aiutare sei tu.
Allora io nella mia form ho due pulsanti uno "Anteprima" e l'altro "Stampa":

Private Sub stampa_cc()
'stampa del documento
documentoCC.Print()
If MsgBox("Conti Corrente stampato correttamente?", MsgBoxStyle.YesNo, "Avviso!") = MsgBoxResult.Yes Then
datacc()
visualizzacc()
End If
End Sub


datacc è una procedura che mi memorizza la data e visualizzacc mi aggiorna i dati visualizzati perchè io ho bisogno che al momento della stampa devo memorizzare la data in modo che so quando è stato stampato e questo funziona tutto alla perfezione.

il pulsante anteprima contiene:

Private Sub anteprimacc()

Anteprima.Document = documentoCC

Anteprima.ShowDialog()
End Sub


dove anteprima è un printpreviewdialog il mio problema è come faccio a sapere in visual basic che ho premuto il pulsante stampa della form anteprima?
ho provato ad utilizzare l'evento end_print del printdocument ma me la memorizza più volte quindi l'unica soluzione è intercettare la pressione del pulsante stampa spero che mi puoi aiutare grazie ancora Marco per la pasienza :help:

MarcoGG
22-11-2009, 17:14
Semplice. Non usare la PrintPreviewDialog. Usa un PrintPreviewControl direttamente sulla tua Dialog personalizzata. Dovrai scrivere un po' di codice in più, ma avrai pieno controllo su tutto ciò che succede... ;)

jackk87
22-11-2009, 22:11
Marco ho capito come con la pagesetupdialog ;) grazie ancora di tutto

jackk87
27-11-2009, 15:08
CIao Marco,
ho un problema riguardo l'impostazione della pagina cioè l'alimentazione del foglio carico la combobox alimentazione (questo funziona bene):


For Each psc As Printing.PaperSource In main.documentoCC.PrinterSettings.PaperSources
cmbAlimentazioni.Items.Add(psc.SourceName)
Next


poi quando salvo i dati li salvo:

main.documentoCC.DefaultPageSettings.PaperSource.SourceName = cmbAlimentazioni.Text


se poi sul caricamento della form inserisco:

msgbox(main.documentoCC.DefaultPageSettings.PaperSource.SourceName)


vedo che mi stampa sempre l'alimentazione di default e non quella che ho selezionato nella combobox mentre per la stampante per il formato per i margini funziona tutto alla perfezione.

Grazie in anticipo :help:

MarcoGG
27-11-2009, 17:56
se poi sul caricamento della form inserisco:

msgbox(main.documentoCC.DefaultPageSettings.PaperSource.SourceName)


vedo che mi stampa sempre l'alimentazione di default e non quella che ho selezionato nella combobox mentre per la stampante per il formato per i margini funziona tutto alla perfezione.

Grazie in anticipo :help:

Spiegati meglio. Sul caricamento di quale Form ? In ogni caso se l'assegnazione viene fatta tramite selezione da oggetti grafici come le Combo, non è mai una buona idea interrogarne il valore sul Load delle Form...

jackk87
27-11-2009, 18:07
Ciao Marco,
allora ora ti spiego se l'impostazione pagina viene aperta per la prima volta mi visualizza la stampante predefinita con tutti i valori predefiniti altrimenti mi visualizza tutti i valori che ho impostato io per esempio:
stampante: Canon
Formato: A4
Alimentazione:Vassoio Superiore
Orientamento: Orizzontale

se io imposto questo poi se la vado a riaprire mi trovo:
stampante: Canon
Formato: A4
Alimentazione:Cassetto
Orientamento: Orizzontale

e trovo tutti i dati come gli ho impostati in precedenza solo alimentazione mi torna come quella predefinita della stampante. io invece vorrei che rimane quella che ho impostata
Spero di essere stato chiaro :D Grazie ancora

MarcoGG
28-11-2009, 08:33
In effetti sembra ci sia un problema. Lo fa anche con la mia Canon Pixma...
Non so ancora se è legato solo ad alcune stampanti, o se dipenda da altro.
Se l'assegnazione dell'alimentatore viene fatta da SourceName :

Private Sub cmb_alimentazioni_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_alimentazioni.SelectedIndexChanged

DOC.DefaultPageSettings.PaperSource.SourceName = cmb_alimentazioni.Text

MsgBox(DOC.DefaultPageSettings.PaperSource.SourceName)

End Sub

l'impostazione di fatto non viene settata su DOC, anche se la procedura non restituisce eccezioni.
Se invece passo l'indice di PrinterSettings.PaperSources, restituito dalla selezione sulla Combo, tutto fila liscio :

Private Sub cmb_alimentazioni_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_alimentazioni.SelectedIndexChanged

DOC.DefaultPageSettings.PaperSource = DOC.PrinterSettings.PaperSources(cmb_alimentazioni.SelectedIndex)

MsgBox(DOC.DefaultPageSettings.PaperSource.SourceName)

End Sub

Sicuramente c'è un problema "silenzioso" nel passaggio diretto del SourceName, in ogni caso la seconda soluzione funziona. ;)

jackk87
28-11-2009, 10:03
Grazie tante Marco sei un grande :D