Newsgroup: it.comp.lang.visual-basic
Titolo: Chiamo una API ma crasha tutto vb xchè? (lo fà anche a voi?)

Allora come sapete sto cercando di aprire una comunicazione con la stampante
di default del sistema... in questo modo pensavo di riuscirci ma quando vado
a cliccare sul command button (dove è il codice) mi si "inchioda" visual
basic con un errore di run-time.
----------------------------------------------------------------------------
-------------------------------------------------------------------
Private Declare Function EnumPrinters Lib "winspool.drv" Alias
"EnumPrintersA" (ByVal flags As Long, ByVal name As String, ByVal Level As
Long, pPrinterEnum As Byte, ByVal cdBuf As Long, pcbNeeded As Long,
pcReturned As Long) As Long
Private Const PRINTER_ENUM_DEFAULT = &H1
Private Type PRINTER_INFO_1
        flags As Long
        pDescription As String
        pName As String
        pComment As String
End Type
Private Sub Command1_Click()
Dim retval As Long
Dim Info(0 To 3025) As Long
Dim need, stampanti As Long
numbytes = 3024
retval = EnumPrinters(PRINTER_ENUM_DEFAULT, "", 1, ByVal Info(0), 3025,
need, stampanti)
End Sub
----------------------------------------------------------------------------
-------------------------------------------------------------------
Qualcuno può provare il codice x vedere se è un problema solo mio oppure è
un problema che sbaglio la chiamata?
Grazie a tutti x l'aiuto!
by Ale(xand[17])

 wrote in message
8r4qot$fot$1...@nslave1.tin.it...


 wrote in message
8r4rua$dm8$1...@serv1.albacom.net...





 need, stampanti)
Per procedere con l'enumerazione (termine "volgare" ? Qui ci vorrebbe pal)
occorre per prima cosa farsi dire quanto spazio è necessario allocare per
contenere le informazioni in arrivo. Per questo la prima chiamata è "informativa",
ossia serve per farsi restituire il numero di byte realmente necessari. Quindi:
retval = EnumPrinters(PRINTER_ENUM_DEFAULT, vbNullString, _
            &H1, 0, 0, _
            need, stampanti)
Se la chiamata riesce, [need] contiene il numero di byte da allocare.
Quindi, dato che la struttura PRINTER_INFO_1 è costituita da 4
variabili Long, si ridimensiona opportunamente l'array in base al
valore di [need] :
Redim Info((need \ 16))
Poi si richiama la funzione per ottenere le informazioni "concrete":
retval = EnumPrinters(PRINTER_ENUM_DEFAULT, vbNullString, _
            &H1, Info(0), need, _
            need, stampanti)
La variabile [stampanti] contiene il numero di strutture recuperate
(in questo caso dovrebbe essere una, almeno si spera).
Dato che la struttura PRINTER_INFO_1 contiene i puntatori alle
stringhe, occorre recuperare la stringhe. Allo scopo, fanno la loro
apparizione le funzioni:
Public Declare Function lstrlen Lib "kernel32" _
        Alias "lstrlenA" _
        (ByVal lpString As Any) As Long
e
Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" _
        (ByVal lpString1 As String, _
        ByVal lpPointer As Long) As Long
Leggermente modificate (anche queste) rispetto alla dichiarazione
presente nell'API Viewer.
Per ottenere, ad esempio, il nome (pName) della stampante occorre
ottenere la lunghezza della stringa di cui pName è il puntatore e allocare
un buffer che conterrà il valore:
[NomeStampante] = String(lstrlen(Info(0).pName), "0")
Call lstrcpy(ByVal [NomeStampante], ByVal Info(0).pName)
PS
Le dichiarazioni presenti nell'API Text Viewer non sono in sé
sbagliate, semplicemente occorre adattarle all'uso che se ne fa.
PS2
Alcune sono sbagliate.


Questo è l'esempio dell'apiguide di 
www.allapi.net
.
Nota che la dichiarazione è diversa.
Ciao
' Get information about all of the local printers using structure 1.  Note
how
' the elements of the array are loaded into an array of data structures
manually.  Also
' note how the following special declares must be used to allow numeric
string pointers
' to be used in place of strings:
Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyA" (ByVal
lpString1 As String, ByVal lpString2 As Long) As Long
Private Declare Function lstrlen Lib "kernel32.dll" Alias "lstrlenA" (ByVal
lpString As Long) As Long
Private Declare Function EnumPrinters Lib "winspool.drv" Alias
"EnumPrintersA" (ByVal flags As Long, ByVal name As String, ByVal Level As
Long, pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long,
pcReturned As Long) As Long
Const PRINTER_ENUM_LOCAL = &H2
Private Type PRINTER_INFO_1
        flags As Long
        pDescription As String
        pName As String
        pComment As String
End Type
Private Sub Form_Load()
    'KPD-Team 1999
    'URL: 
http://www.allapi.net/
    'E-Mail: KPD...@Allapi.net
    Dim longbuffer() As Long  ' resizable array receives information from
the function
    Dim printinfo() As PRINTER_INFO_1  ' values inside longbuffer() will be
put into here
    Dim numbytes As Long  ' size in bytes of longbuffer()
    Dim numneeded As Long  ' receives number of bytes necessary if
longbuffer() is too small
    Dim numprinters As Long  ' receives number of printers found
    Dim c As Integer, retval As Long  ' counter variable & return value
    Me.AutoRedraw = True 'Set current graphic mode to persistent
    ' Get information about the local printers
    numbytes = 3076  ' should be sufficiently big, but it may not be
    ReDim longbuffer(0 To numbytes / 4) As Long  ' resize array -- note how
1 Long = 4 bytes
    retval = EnumPrinters(PRINTER_ENUM_LOCAL, "", 1, longbuffer(0),
numbytes, numneeded, numprinters)
    If retval = 0 Then  ' try enlarging longbuffer() to receive all
necessary information
        numbytes = numneeded
        ReDim longbuffer(0 To numbytes / 4) As Long  ' make it large enough
        retval = EnumPrinters(PRINTER_ENUM_LOCAL, "", 1, longbuffer(0),
numbytes, numneeded, numprinters)
        If retval = 0 Then ' failed again!
            Debug.Print "Could not successfully enumerate the printes."
        End  ' abort program
    End If
    End If
    ' Convert longbuffer() data into printinfo()
    ReDim printinfo(0 To numprinters - 1) As PRINTER_INFO_1  ' room for each
printer
    For c = 0 To numprinters - 1  ' loop, putting each set of information
into each element
        ' longbuffer(4 * c) = .flags, longbuffer(4 * c + 1) = .pDescription,
etc.
        ' For each string, the string is first buffered to provide enough
room, and then the string is copied.
        printinfo(c).flags = longbuffer(4 * c)
        printinfo(c).pDescription = Space(lstrlen(longbuffer(4 * c + 1)))
        retval = lstrcpy(printinfo(c).pDescription, longbuffer(4 * c + 1))
        printinfo(c).pName = Space(lstrlen(longbuffer(4 * c + 2)))
        retval = lstrcpy(printinfo(c).pName, longbuffer(4 * c + 2))
        printinfo(c).pComment = Space(lstrlen(longbuffer(4 * c + 3)))
        retval = lstrcpy(printinfo(c).pComment, longbuffer(4 * c + 3))
    Next c
    ' Display name of each printer
    For c = 0 To numprinters - 1
        Me.Print "Name of printer"; c + 1; " is: "; printinfo(c).pName
    Next c
End Sub

 > 8r4qot$fot$1...@nslave1.tin.it...


 basic con un errore di run-time.
solamente un paio di consigli:
1) per vedere le stampanti installate localmente, puoi usare le seguenti 4
righe di codice VB
    Dim objPrn As Printer
    For Each objPrn In Printers
        Debug.Print objPrn.DeviceName
    Next
2) la stampante definita come default nel sistema è definita dall'oggetto
globale Printer
    Debug.Print Printer.DeviceName
ciao