Newsgroup: it.comp.lang.visual-basic
Titolo: [vb2005] disporre testo e immagini, date coordinate in mm

Salve a tutti,
è la prima volta che lavoro con immagini e testo da stampare usando 
printdocument e printpreviewdialog
Ho necessità di disporre alcune immagini in un foglio A4 esattamente nel 
punto in cui dovrebbero essere, date le coordinate in millimetri.
Questo perchè la stampa avverrà su fogli con etichette adesive.
Ho provato a cercare in giro ma non sono riuscito a cavare un granchè.
Ho usato le proprietà DpiX e DpiY (mi restituiscono 96dpi ciascuna). 
Quindi ho fatto questo calcolo:
1 pollice = 2,54 cm
96dpi = 96 punti per pollice
quindi 248 punti per centimetro (247,84)
Allora ho convertito le mie coordinate da mm a pixel (ad esempio 21mm 
corrispondono a 94px).
Non capisco perchè, ma la cosa non funziona e le immagini sono 
posizionate molto più verso l'angolo alto/sinistro dello schermo.
Cosa sbaglio?
Nicola

 Non capisco perchè, ma la cosa non funziona e le immagini sono posizionate molto più verso l'angolo alto/sinistro dello schermo. 
Anche questo va precisato. Con i valori calcolati le immagini sono del 
tutto sproporzionate, e fuori dal foglio (in anteprima ho un foglio bianco)
In realtà se divido i valori per 10 (es 520/10=52) ottengo che tutto si 
sposta verso l'angolo alto/sinistro della pagina, e quindi le immagini 
sono almeno visibili, ma comunque sproporzionate.
Come fare?

 ha scritto nel messaggio 
news:46434fff$0$7735

Questo perchè è un casino 'sta stampa!
Ecco, partiamo da questo presupposto :)
Ci ho perso un sacco di tempo per capire il perchè di questo problema.
Prima di tutto, non ti fidare dei 96dpi, perchè non sono fissi ma dipendono 
dalla risoluzione video (in genere è sempre 96dpi).
Poi, la differenza che tu noti è data dal fatto che dipende da dove stai 
stampando (es. se su stampante o a video per l'anteprima).
Devi controllare la proprietà PageUnit del Graphics di destinazione, il 
problema è che non è così intuitivo: se stai stampando ti affidi alla 
proprietà, che in genere vale Display (e qui me la spiegheranno), se è in 
preview lo forzi a Display, se invece disegni a video (es. il Graphics è 
quello di un controllo) lo forzi a Pixel.
Poi, usi questa funzioncina che io mi sono fatto, dove
- value è il valore nella tua unità di misura,
- dpi è il dpi X o Y a seconda se il valore è verticale o orizzontale,
- ScaleMode è un mio enumerativo che indica l'unità di misura di partenza
- unit è la famosa proprietà di Graphics
(In realtà la teoria vorrebbe che si sfruttasse la GraphicUnit per 
convertire un'unità di misura in un'altra, ma a me non piace molto perchè ti 
lega ai suoi valori).
public static int ToPixels(float value, float dpi, ScaleMode fromScale, 
GraphicsUnit unit)
{
switch (unit)
{
case GraphicsUnit.Display:
dpi = 100f;
break;
case GraphicsUnit.Document:
dpi = 300;
break;
case GraphicsUnit.Point:
dpi = 72f;
break;
}
float ret = value * dpi;
switch (fromScale)
{
case ScaleMode.Inches:
return Convert.ToInt32(ret);
case ScaleMode.Centimeters:
return Convert.ToInt32(ret / 2.54f);
case ScaleMode.Millimeters:
return Convert.ToInt32(ret / 25.4f);
case ScaleMode.Points:
return Convert.ToInt32(ret / 72f);
case ScaleMode.Pixels:
return Convert.ToInt32(value);
}
return Convert.ToInt32(ret);
}
Detto questo, se tu usassi il mio progetto di stampa se non hai necessità 
particolari a quest'ora avresti già finito, una delle ultime modifiche è 
proprio la possibilità di stampare su etichette, probabilmente più di una 
per colonna, che mi era stato chiesto da un po' di persone che lo usano. :)
Ciao

 per colonna, che mi era stato chiesto da un po' di persone che lo usano. :)
Eh, ma il problema è che devo stampare etichette con codice a barre, il 
cui codice a barre è generato in una picturebox.
Nel caso, potrei anche usare un font barcode abbinato al tuo progetto di 
stampa.
Nicola

Ho tradotto la tua funzione in 
VB.NET
 e l'ho implementata... stampa alla 
perfezione!!!
In realtà ci sono degli sfasamenti di millimetri, ma nulla che non sia 
tarabile.
Alla fine posto il progetto su SC così che altri possano usufruire della 
cosa.
Nicola

 tarabile.
In realtà non dovrebbero esserci, ma se si tratta di un paio di millimetri 
protrebbe essere il margine fisico della stampante (che però dovrebbe 
"tagliare" la stampa e non spostarla).
Ciao 


Ma anche questo è stato fatto perchè era un'altra richiesta frequente :)
Ciao 

 "tagliare" la stampa e non spostarla).
No, meno di un paio di millimetri... mezzo millimetro perso in un A4, ma 
mi è bastato correggere leggermente (dopotutto ho misurato il foglio con 
una comune squadra, quindi può esserci un errore di misurazione).
Adesso però ho un altro "piccolo" problema. Il codice a barre nella 
picturebox viene perfetto e non sgranato. Nell'Anteprima e nella stampa 
invece sembra che vi sia stata una sorta di "sfumatura" dei bordi... 
simile all'effetto dell'antialiasing, ma ho controllato... su 
printpreviewdialog ho la proprietà UseAntiAlias=False
bye

 Ma anche questo č stato fatto perchč era un'altra richiesta frequente :)
eh vabbč... vuoi mettere il gusto di creare la routine personale... 
avrei potuto usare il tuo neoreport (che reputo un buon programma), ma 
questo progetto lo sto scrivendo per imparare il piů possibile sul 
framework (č il mio primo progetto "serio" in .net), quindi ogni 
occasione č buona per imparare qualcosa di nuovo.
bye

Dunque, il problema dell'allineamento è ormai risolto.
Ora si è presentato il problema che ti descrivevo in un post precedente.
In pratica sulla picturebox l'immagine è nitida, mentre nell'anteprima 
al 100% viene sfocata. Allora, facendo uno zoom al 500% nel 
printpreviewdialog, vediamo che avviene questo:
http://www.gestioneottica.it/images/barcode.jpg
I contorni del codice a barre (ma anche del testo) vengono sfumati, come 
se fosse attivata una qualche funzione antialias. Ovviamente io vorrei 
che i contorni fossero netti.
Posto un pò di codice, magari a me sfugge qualcosa:
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, 
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles 
PrintDocument1.PrintPage
[CUT]
For y = 1 To NumEtY
  For x = 1 To NumEtX
   PosX = MargineSxPagina + (x - 1) * (LarghezzaEt + SpazioVerticale)
   PosY = MargineAltoPagina + (y - 1) * AltezzaEt
   e.Graphics.DrawImage(pbx(x * y).Image, PosX, PosY)
  Next
Next
End Sub
Secondo me l'errore è in quel
  e.Graphics.DrawImage(pbx(x * y).Image, PosX, PosY)
Perchè se provo a fare
Me.PictureBox1.Image = pbx(x * y).Image
l'immagine si vede nitida nella picturebox.
C'è qualcosa che sbaglio?

> C'è qualcosa che sbaglio?
Risolto!
Prima di
e.Graphics.DrawImage(pbx(x * y).Image, PosX, PosY)
andrebbe aggiunto
e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
Nicola


Posso chiederti cosa usi per generare le immagini dei barcode?
Ciao 

> Posso chiederti cosa usi per generare le immagini dei barcode?
E' un modulo che ho trovato in giro... se non ricordo male su 
PlanetSourceCode... comunque partendo da quel modulo ho modificato buona 
parte del codice, aggiungendo alcune funzioni che prima non c'erano.
Ti posto direttamente il codice (è fortemente personalizzato, quindi non 
va bene per tutti):
Option Explicit On
Imports System.Drawing
'* Module BarCodeFunctions.vb
'*
'*    Author : Paulo S. Silva Jr.
'*      Date : February 2003
'* Objective : Gather Function to draw Barcodes
'*
'* Methods :
'*
'* 
+-------------------+----------------------------------------------------+
'*   | Name              | Description 
       |
'* 
+-------------------+----------------------------------------------------+
'*   | EAN2Bin           | Convert an EAN Code on its binary form 
       |
'*   | PrintEANBarCode   | Print an EAN Barcode on a PictureBox 
       |
'* 
+-------------------+----------------------------------------------------+
'*
'*
Module BarCodeFunctions
     '*
     '* Function  : EAN2Bin
     '*
     '* Objective : Convert an EAN8 or EAN13 in a sequence of 1 and 0
     '*                  where 1 means a stripe and 0 means a space
     '*
     Private Function EAN2Bin(ByVal strEANCode As String) As String
         Dim K As Integer
         Dim strAux As String
         Dim strExit As String
         Dim strCode As String
         strEANCode = Trim(strEANCode)
         strAux = strEANCode
         '*
         '* Check to see what kind of EAN the code will be
         '*
         If (strAux.Length <> 13) And (strAux.Length <> 8) Then
             '*
             '* If it's not 8 nor 13 "Error: Invalid Function Call"
             '*
             Err.Raise(5, "EAN2Bin", "Invalid EAN Code")
         End If
         '*
         '* Check for numbers only
         '*
         For K = 0 To strEANCode.Length - 1
             Select Case (strAux.Chars(K).ToString)
                 Case Is < "0", Is > "9"
                     '*
                     '* Invalid char "Error: Invalid Function Call"
                     '*
                     Err.Raise(5, "EAN2Bin", "Invalid char on EAN Code")
             End Select
         Next
         '*
         '* It's EAN13
         '*
         If (strAux.Length = 13) Then
             '*
             '* The EAN13 is a special code formated as follow
             '*
             '*          CnnnnnnnnnnnK
             '*
             '* Where : C - is not part of the code, but coded in the 
next 6 digits
             '*         n - THE NUMBER
             '*         K - is a check digit (this function do not 
calculate this)
             '*
             '* When the first digit of an EAN13 code is 0 (zero) it 
matches an UPC (12 digits) code
             '*
             '* Skip the first digit of the code
             '*
             strAux = Mid(strAux, 2)
             '*
             '* Select the proper code based on the first digit
             '*
             Select Case CInt(Left(strEANCode, 1))
                 Case 0
                     strCode = "000000"
                 Case 1
                     strCode = "001011"
                 Case 2
                     strCode = "001101"
                 Case 3
                     strCode = "001110"
                 Case 4
                     strCode = "010011"
                 Case 5
                     strCode = "011001"
                 Case 6
                     strCode = "011100"
                 Case 7
                     strCode = "010101"
                 Case 8
                     strCode = "010110"
                 Case 9
                     strCode = "011010"
             End Select
         Else
             strCode = "0000"
         End If
         '*
         '* The EAN BarCode starts with a "guardian"
         '*
         strExit = "000101"
         '*
         '* First half of the code
         '*
         For K = 1 To Len(strAux) \ 2
             Select Case CInt(Mid(strAux, K, 1))
                 Case 0
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0001101", 
"0100111")
                 Case 1
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0011001", 
"0110011")
                 Case 2
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0010011", 
"0011011")
                 Case 3
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0111101", 
"0100001")
                 Case 4
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0100011", 
"0011101")
                 Case 5
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0110001", 
"0111001")
                 Case 6
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0101111", 
"0000101")
                 Case 7
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0111011", 
"0010001")
                 Case 8
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0110111", 
"0001001")
                 Case 9
                     strExit &= IIf(Mid(strCode, K, 1) = "0", "0001011", 
"0010111")
             End Select
         Next K
         '*
         '* Middle "guardian" separator
         '*
         strExit &= "01010"
         '*
         '* Second half of the code
         '*
         For K = Len(strAux) \ 2 + 1 To Len(strAux)
             Select Case CInt(Mid(strAux, K, 1))
                 Case 0
                     strExit &= "1110010"
                 Case 1
                     strExit &= "1100110"
                 Case 2
                     strExit &= "1101100"
                 Case 3
                     strExit &= "1000010"
                 Case 4
                     strExit &= "1011100"
                 Case 5
                     strExit &= "1001110"
                 Case 6
                     strExit &= "1010000"
                 Case 7
                     strExit &= "1000100"
                 Case 8
                     strExit &= "1001000"
                 Case 9
                     strExit &= "1110100"
             End Select
         Next K
         '*
         '* The EAN BarCode also finish with a "guardian"
         '*
         strExit &= "101000"
         EAN2Bin = strExit
     End Function
     '* Function : PrintEANBarCode(strEANCode, objPicBox)
     '*
     '*
     Public Sub PrintEANBarCode(ByVal strEANCode As String, _
                                 ByVal objGraphics As Graphics, _
                                 ByVal Picbox As PictureBox, _
                                 Optional ByVal sngX1 As Single = (-1), _
                                 Optional ByVal sngY1 As Single = (-1), _
                                 Optional ByVal sngX2 As Single = (-1), _
                                 Optional ByVal sngY2 As Single = (-1), _
                                 Optional ByVal FontForText As Font = 
Nothing, _
                                 Optional ByVal SecondaRiga As String = 
"", _
                                 Optional ByVal TerzaRiga As String = "")
         Dim K As Single
         Dim sngPosX As Single
         Dim sngPosY As Single
         Dim sngScaleX As Single
         Dim strEANBin As String
         Dim strFormat As New StringFormat()
         '*
         '* Convert the code on its binary representation
         '*
         strEANBin = EAN2Bin(strEANCode)
         '*
         '* Define the font to be printed
         '*
         If (FontForText Is Nothing) Then
             FontForText = New Font("Arial", 30, FontStyle.Bold)
         End If
         '*
         '* Defines the boundaries to the barcode
         '*
         If sngX1 = (-1) Then sngX1 = 0
         If sngY1 = (-1) Then sngY1 = 0
         If sngX2 = (-1) Then sngX2 = Picbox.Width
         If sngY2 = (-1) Then sngY2 = Picbox.Height
         '*
         '* Defines the boundaries of the barcode
         '*
         sngPosX = sngX1
         sngPosY = sngY2 - CSng(1.5 * FontForText.Height)
         '*
         '* Clears the area
         '*
         objGraphics.FillRectangle(New 
System.Drawing.SolidBrush(Color.White), sngX1, sngY1, sngX2 - sngX1, 
sngY2 - sngY1)
         '*
         '* Calculates the scale
         '*
         sngScaleX = (sngX2 - sngX1) / strEANBin.Length
         '*
         '* Draw the BarCode
         '*
         For K = 1 To Len(strEANBin)
             If Mid(strEANBin, K, 1) = "1" Then
                 objGraphics.FillRectangle(New 
System.Drawing.SolidBrush(Color.Black), sngPosX, sngY1, sngScaleX, sngPosY)
             End If
             sngPosX = sngX1 + (K * sngScaleX)
         Next K
         '*
         '* Draw the human-friendly code
         '*
         strFormat.Alignment = StringAlignment.Center
         strFormat.FormatFlags = StringFormatFlags.NoWrap
         Dim sngPosText As Single
         sngPosText = sngPosY + CSng(FontForText.Height)
         objGraphics.DrawString(strEANCode, FontForText, New 
System.Drawing.SolidBrush(Color.Black), CSng((sngX2 - sngX1) / 2), 
sngPosText, strFormat)
         sngPosText = sngPosText + CSng(FontForText.Height)
         objGraphics.DrawString(SecondaRiga, FontForText, New 
System.Drawing.SolidBrush(Color.Black), CSng((sngX2 - sngX1) / 2), 
sngPosText, strFormat)
         sngPosText = sngPosText + CSng(FontForText.Height)
         objGraphics.DrawString(TerzaRiga, FontForText, New 
System.Drawing.SolidBrush(Color.Black), CSng((sngX2 - sngX1) / 2), 
sngPosText, strFormat)
     End Sub
End Module

 va bene per tutti):
Ma è solo per gli EAN? :(
Ciao 

Fabio ha scritto:

Si, e tanto mi basta.
Avevo anche qualcosa per Code3of9, ma l'ambito che mi interessa è 
commerciale (il mio gestionale per ottici) quindi il 100% dei prodotti 
ha un codice EAN.
bye