Newsgroup: it.comp.lang.visual-basic
Titolo: Variante sul problema stampante

Ciao a tutti. 
La triste assonanza del subj. era parzialmente voluta per muovere a 
compassione qualche anima pia, spingendola ad affrontare nuovamente questo  
tema, ormai più volte discusso in questo NG.
Premesso che ho riletto i post dall'inizio si Settembre, spulciato il sito 
comune (con cerca "printer") e cercato anche si Internet senza trovare una 
soluzione al problema, passo all'esposizione.
Sto scrivendo un programmino di prova di questa con VB6 SP5 che gira in 
Win2000 Sp3 ed i miei tentativi si sono l imitati all'esecuzione dello 
stesso all'interno dell'ambiente di sviluppo.
Il mio intento è quello di disegnare una cornice e della grafica all'interno 
di un form, in modo che le proporzioni siano dipendenti dalle dimensioni del 
foglio prescelto, e di inviarlo alla stampante. Per fare ciò, cerco di 
determinare la dimensione del foglio impostata nella stessa per poi 
impostare le dimensioni del form etc. e quindi stamparlo con printform.
La dialog box viene visualizzata correttamente ed il nome della stampante 
printer cambia in relazione alla mia selezione. Purtroppo la dimensione del 
foglio rimane sempre la stessa (sia come printer width e height, sia come 
papersize (nel mio caso sempre 9 = A4)). Ovviamente PrinterWidth e Height 
sarebbero molto più semplici nell'uso. 
    Printer.TrackDefault = True
    'frmMain.dbPrint.PrinterDefault = True    
    'imposto la dialog box stampante
    frmMain.dbPrint.CancelError = True ' genera errore con cancel
    frmMain.dbPrint.Flags = cdlPDHelpButton Or cdlPDNoPageNums Or     	    
	     	    	    	    	cdlPDNoSelection
 
    frmMain.dbPrint.ShowPrinter
    strNomeStampante = Printer.DeviceName
    intK = Printer.PaperSize
    lngPaperWidth = Printer.Width
    lngPaperHeight = Printer.Height
Le proprietà Trackdefault e PrinterDefault non sembrano essere state 
d'aiuto.
Ho trovato un post in cui si suggeriva di usare l'istruzione: 
Set Printer = Printers(x)
Dove X è il nome stampante o indice associato. Ho provato con il nome 
(Devicename) ma non funziona. Ho cercato di recuperare l'indice con le 
seguenti righe (visto che il nome della stampante veniva recepito 
correttamente)
    	Dim intI as integer, objX as printers
    	Dim intNomeStampante as string
    strNomeStampante = Printer.DeviceName
    intI = 0
    For Each objX In Printers
        If objX.DeviceName = strNomeStampante Then
            Exit For
        End If
        intI = intI + 1
    Next objX
    Set Printer = Printers(intI)
Vorrei evitare di usare chiamate alle API (essenzialmente perchè non 
padroneggio ancora bene questa tecnica ma neanche perchè mi pare che il 
risultato possa essere ottenuto, una volta colmata la lacuna nella mia 
conoscenza) ma, se non ci sono altre strade, anche tali suggerimenti saranno 
ben accetti (ammetto di non aver valutato pianemente gli esempi di tale 
tecnica, per la summenzionata scarsa padronanza).
Grazie per l'aiuto (e scusate al prolissità)
Ciao
Luca
 

 sarebbero molto più semplici nell'uso.
Ho cercato a lungo (anche fra i miei appunti), ma non trovo proprio più
l'indirizzo di MSDN che mi aveva portato alla soluzione (codice copiato
paro-paro da MSDN). Allora (ora non so, fatto sta che ho lasciato le cose
così e va tutto bene), il normale CommonDialog e metodo ShowPrinter,
perfettamente funzionante in ambiente Win9x/Me, non consentiva/sbagliava
molte cose in ambiente NT/2000/XP.
Ecco il mio codice (che chiamo se l'applicativo gira in ambiente NT o
superiore), non mi chiede cosa fa, non lo so e nonmenepòfregàdemeno, però
funziona ;-):
'----------------------------
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Public Const GMEM_FIXED = &H0
Public Const GMEM_MOVEABLE = &H2
Public Const GMEM_ZEROINIT = &H40
Public Const DM_DUPLEX = &H1000&
Public Const DM_ORIENTATION = &H1&
Public Const PD_ALLPAGES = &H0
Public Const PD_COLLATE = &H10
Public Const PD_DISABLEPRINTTOFILE = &H80000
Public Const PD_ENABLEPRINTHOOK = &H1000
Public Const PD_ENABLEPRINTTEMPLATE = &H4000
Public Const PD_ENABLEPRINTTEMPLATEHANDLE = &H10000
Public Const PD_ENABLESETUPHOOK = &H2000
Public Const PD_ENABLESETUPTEMPLATE = &H8000
Public Const PD_ENABLESETUPTEMPLATEHANDLE = &H20000
Public Const PD_HIDEPRINTTOFILE = &H100000
Public Const PD_NONETWORKBUTTON = &H200000
Public Const PD_NOPAGENUMS = &H8
Public Const PD_NOSELECTION = &H4
Public Const PD_NOWARNING = &H80
Public Const PD_PAGENUMS = &H2
Public Const PD_PRINTSETUP = &H40
Public Const PD_PRINTTOFILE = &H20
Public Const PD_RETURNDC = &H100
Public Const PD_RETURNDEFAULT = &H400
Public Const PD_RETURNIC = &H200
Public Const PD_SELECTION = &H1
Public Const PD_SHOWHELP = &H800
Public Const PD_USEDEVMODECOPIES = &H40000
Public Const PD_USEDEVMODECOPIESANDCOLLATE = &H40000
Public Const DLG_PRINT = 0
Public Const DLG_PRINTSETUP = 1
Type PRINTDLG_TYPE
    lStructSize As Long
    hWndOwner As Long
    hDevMode As Long
    hDevNames As Long
    hdc As Long
    Flags As Long
    nFromPage As Integer
    nToPage As Integer
    nMinPage As Integer
    nMaxPage As Integer
    nCopies As Integer
    hInstance As Long
    lCustData As Long
    lpfnPrintHook As Long
    lpfnSetupHook As Long
    lpPrintTemplateName As String
    lpSetupTemplateName As String
    hPrintTemplate As Long
    hSetupTemplate As Long
End Type
Type DEVNAMES_TYPE
    wDriverOffset As Integer
    wDeviceOffset As Integer
    wOutputOffset As Integer
    wDefault As Integer
    extra As String * 100
End Type
Type DEVMODE_TYPE
    dmDeviceName As String * CCHDEVICENAME
    dmSpecVersion As Integer
    dmDriverVersion As Integer
    dmSize As Integer
    dmDriverExtra As Integer
    dmFields As Long
    dmOrientation As Integer
    dmPaperSize As Integer
    dmPaperLength As Integer
    dmPaperWidth As Integer
    dmScale As Integer
    dmCopies As Integer
    dmDefaultSource As Integer
    dmPrintQuality As Integer
    dmColor As Integer
    dmDuplex As Integer
    dmYResolution As Integer
    dmTTOption As Integer
    dmCollate As Integer
    dmFormName As String * CCHFORMNAME
    dmUnusedPadding As Integer
    dmBitsPerPel As Integer
    dmPelsWidth As Long
    dmPelsHeight As Long
    dmDisplayFlags As Long
    dmDisplayFrequency As Long
End Type
Sub DIALOGO_STAMPA_NT(frmOwner As Form, Optional PrintFlags = 0, Optional
printdlgflags = 0)
'=======================
    Dim PrintDlg As PRINTDLG_TYPE
    Dim DevMode As DEVMODE_TYPE
    Dim DevName As DEVNAMES_TYPE
    Dim lpDevMode As Long, lpDevName As Long
    Dim bReturn As Integer
    Dim objPrinter As Printer, NewPrinterName As String
    Dim strSetting As String
'       Use PrintDialog to get the handle to a memory
'       block with a DevMode and DevName structures
    PrintDlg.lStructSize = Len(PrintDlg)
    PrintDlg.hWndOwner = frmOwner.hWND
    PrintDlg.Flags = PrintFlags
'       Set the current orientation and duplex setting
    DevMode.dmDeviceName = Printer.DeviceName
    DevMode.dmSize = Len(DevMode)
    'DevMode.dmFields = DM_ORIENTATION Or DM_DUPLEX
    DevMode.dmFields = 2 ^ 31 - 1    'Alza tutti i bits di Long meno il piu'
alto (31)
    On Error Resume Next
    DevMode.dmOrientation = Printer.Orientation
    DevMode.dmDuplex = Printer.Duplex
    '
    DevMode.dmPaperSize = Printer.PaperSize
    DevMode.dmPrintQuality = Printer.PrintQuality
    DevMode.dmColor = Printer.ColorMode
    DevMode.dmDefaultSource = Printer.PaperBin
    On Error GoTo errore
'       Allocate memory for the initialization hDevMode structure
'       and copy the settings gathered above into this memory
    PrintDlg.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT,
Len(DevMode))
    lpDevMode = GlobalLock(PrintDlg.hDevMode)
    If lpDevMode > 0 Then
        CopyMemory ByVal lpDevMode, DevMode, Len(DevMode)
        bReturn = GlobalUnlock(PrintDlg.hDevMode)
    End If
'       Set the current driver, device, and port name strings
    With DevName
        .wDriverOffset = 8
        .wDeviceOffset = .wDriverOffset + 1 + Len(Printer.DriverName)
        .wOutputOffset = .wDeviceOffset + 1 + Len(Printer.Port)
        .wDefault = 0
    End With
    With Printer
        DevName.extra = .DriverName & Chr(0) & .DeviceName & Chr(0) & .Port
& Chr(0)
    End With
'       Allocate memory for the initial hDevName structure
'       and copy the settings gathered above into this memory
    PrintDlg.hDevNames = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT,
Len(DevName))
    lpDevName = GlobalLock(PrintDlg.hDevNames)
    If lpDevName > 0 Then
        CopyMemory ByVal lpDevName, DevName, Len(DevName)
        bReturn = GlobalUnlock(lpDevName)
    End If
'       Call the print dialog up and let the user make changes
    If PrintDialog(PrintDlg) Then
'           First get the DevName structure.
        lpDevName = GlobalLock(PrintDlg.hDevNames)
        CopyMemory DevName, ByVal lpDevName, 45
        bReturn = GlobalUnlock(lpDevName)
        GlobalFree PrintDlg.hDevNames
'           Next get the DevMode structure and set the printer
'           properties appropriately
        lpDevMode = GlobalLock(PrintDlg.hDevMode)
        CopyMemory DevMode, ByVal lpDevMode, Len(DevMode)
        bReturn = GlobalUnlock(PrintDlg.hDevMode)
        GlobalFree PrintDlg.hDevMode
        NewPrinterName = UCase(Left(DevMode.dmDeviceName,
InStr(DevMode.dmDeviceName, Chr(0)) - 1))
        If Printer.DeviceName <> NewPrinterName Then
            For Each objPrinter In Printers
                If UCase(objPrinter.DeviceName) = NewPrinterName Then
                    Set Printer = objPrinter
                End If
            Next
        End If
        On Error Resume Next
'           Set printer object properties according to selections made by
user
        DoEvents
        On Error Resume Next
        With Printer
            .Copies = DevMode.dmCopies
            .Duplex = DevMode.dmDuplex
            .Orientation = DevMode.dmOrientation
            .PaperSize = DevMode.dmPaperSize
            .PrintQuality = DevMode.dmPrintQuality
            .ColorMode = DevMode.dmColor
            .PaperBin = DevMode.dmDefaultSource
        End With
        printdlgflags = PrintDlg.Flags      'Per PrintToFile
        On Error GoTo errore
    End If
    Exit Sub
errore:
    Call F_ERRORE(Err)    'Genera errore
End Sub

 End Sub
Grazie per il suggerimento. Il codice che mi hai mandato era carente di
qualche inizializzazione, per cui, cogliendo lo spunto che mi hai dato
(prendendo come riferimento le chiamate nel tuo codice) ho trovato un
corposo esempio su 
www.allapi.net
. Questo funziona bene, anche se ho
trovato un ultreriore problema. Prima di scocciarvi ancora, comunque,
provo a sbrogliarmelo da solo. Grazie
Ciao
Luca