|
-
Apr 11th, 2015, 08:21 PM
#1
Thread Starter
Frenzied Member
[RESOLVED] PrintDlgEx API failed to return full name of printer
I used Krool's OpenPrinterEx function in CommonDialog class. The function failed to return the full name of the chosen printer. The printer name is "\\192.4.4.143\Canon iR2002/2202 UFRII LT(1)" showing on the Printer Dialog. But I watched the return printer name (NewPrinterName) is "\\192.4.4.143\Canon iR2002/220" which is 30 characters length. what is the reason?
When a Microsoft Windows application prints, it must identify the target printer by its full name. The DEVMODE structure that was introduced in 16-bit Windows version 3.1 has a limitation of 32 characters for a printer name. However, printer names in Win32 operating systems can be much longer.
Look like the string is being truncated. I tried to changed CCHDEVICENAME =32 to 128 to increase the buffer but still no luck. Maybe the DMDeviceName in DEVMODE structure should be defined to Pointer?
Code:
Private Type PRINTDLGEX
lStructSize As Long
hWndOwner As Long
hDevMode As Long
hDevNames As Long
hDC As Long
Flags As Long
Flags2 As Long
ExclusionFlags As Long
nPageRanges As Long
nMaxPageRanges As Long
lpPageRanges As Long
nMinPage As Long
nMaxPage As Long
nCopies As Long
hInstance As Long
lpPrintTemplateName As Long
lpCallback As Long
nPropertyPages As Long
lphPropertyPages As Long
nStartPage As Long
dwResultAction As Long
End Type
Private Const CCHDEVNAMESEXTRA As Long = 100
Private Type DEVNAMES
wDriverOffset As Integer
wDeviceOffset As Integer
wOutputOffset As Integer
wDefault As Integer
wExtra(0 To ((CCHDEVNAMESEXTRA * 2) - 1)) As Byte
End Type
Private Const CCHDEVICENAME As Long = 128 '32
Private Const CCHFORMNAME As Long = 32
Private Const DM_ORIENTATION As Long = &H1
Private Const DM_PAPERSIZE As Long = &H2
Private Const DM_COPIES As Long = &H100
Private Const DM_DEFAULTSOURCE As Long = &H200
Private Const DM_PRINTQUALITY As Long = &H400
Private Const DM_COLOR As Long = &H800
Private Const DM_DUPLEX As Long = &H1000
Private Const DM_COLLATE As Long = &H8000&
Private Type DEVMODE
DMDeviceName(0 To ((CCHDEVICENAME * 2) - 1)) As Byte
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(0 To ((CCHFORMNAME * 2) - 1)) As Byte
DMLogPixels As Integer
DMBitsPerPel As Long
DMPelsWidth As Long
DMPelsHeight As Long
DMDisplayFlags As Long
DMDisplayFrequency As Long
DMICMMethod As Long
DMICMIntent As Long
DMMediaType As Long
DMDitherType As Long
DMReserved1 As Long
DMReserved2 As Long
DMPanningWidth As Long
DMPanningHeight As Long
End Type
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function PrintDialogEx Lib "comdlg32" Alias "PrintDlgExW" (ByRef lpPrintDlgEx As PRINTDLGEX) As Long
Private PropFlags As Long
Private PropMin As Long, PropMax As Long
Private PropFromPage As Long, PropToPage As Long
Private PropPrinterDefault As Boolean
Code:
Public Function ShowPrinterEx() As CdlPDResultConstants
Dim PDLGEX As PRINTDLGEX, PPAGERANGE As PRINTPAGERANGE, DMODE As DEVMODE, DNAMES As DEVNAMES
Dim lpDevMode As Long, lpDevNames As Long
Dim ObjPrinter As VB.Printer, NewPrinterName As String, Buffer As String
With PDLGEX
.lStructSize = LenB(PDLGEX)
If Not Screen.ActiveForm Is Nothing Then
.hWndOwner = Screen.ActiveForm.hWnd
Else
.hWndOwner = GetActiveWindow()
End If
.Flags = PropFlags
.nPageRanges = 1
.nMaxPageRanges = 1
PPAGERANGE.nFromPage = PropFromPage
PPAGERANGE.nToPage = PropToPage
.nMinPage = PropMin
.nMaxPage = PropMax
.lpPageRanges = VarPtr(PPAGERANGE)
Const START_PAGE_GENERAL As Long = &HFFFFFFFF
.nStartPage = START_PAGE_GENERAL
End With
If VB.Printers.Count > 0 And (PDLGEX.Flags And CdlPDReturnDefault) = 0 Then
With VB.Printer
DMODE.DMSize = LenB(DMODE)
Buffer = Left$(.DeviceName, CCHDEVICENAME)
CopyMemory DMODE.DMDeviceName(0), ByVal StrPtr(Buffer), LenB(Buffer)
DMODE.DMFields = DM_ORIENTATION Or DM_PAPERSIZE Or DM_COPIES Or DM_DEFAULTSOURCE Or DM_PRINTQUALITY Or DM_COLOR Or DM_DUPLEX Or DM_COLLATE
DMODE.DMOrientation = .Orientation
DMODE.DMPaperSize = .PaperSize
DMODE.DMCopies = .Copies
DMODE.DMDefaultSource = .PaperBin
DMODE.DMPrintQuality = .PrintQuality
DMODE.DMColor = .ColorMode
DMODE.DMDuplex = .Duplex
DMODE.DMCollate = IIf((PDLGEX.Flags And CdlPDCollate) <> 0, 1, 0)
DNAMES.wDriverOffset = 4
DNAMES.wDeviceOffset = DNAMES.wDriverOffset + Len(.DriverName) + 1
DNAMES.wOutputOffset = DNAMES.wDeviceOffset + Len(.DeviceName) + 1
DNAMES.wDefault = 0
Buffer = Left$(.DriverName & vbNullChar & .DeviceName & vbNullChar & .Port & vbNullChar, CCHDEVNAMESEXTRA)
CopyMemory DNAMES.wExtra(0), ByVal StrPtr(Buffer), LenB(Buffer)
PDLGEX.nCopies = .Copies
PDLGEX.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, LenB(DMODE))
lpDevMode = GlobalLock(PDLGEX.hDevMode)
CopyMemory ByVal lpDevMode, DMODE, LenB(DMODE)
GlobalUnlock PDLGEX.hDevMode
PDLGEX.hDevNames = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, LenB(DNAMES))
lpDevNames = GlobalLock(PDLGEX.hDevNames)
CopyMemory ByVal lpDevNames, DNAMES, LenB(DNAMES)
GlobalUnlock PDLGEX.hDevNames
End With
End If
Dim ErrVal As Long
If PropHookEvents = False Then
ErrVal = PrintDialogEx(PDLGEX)
Else
Call ComCtlsCdlPDEXSetHook(Me)
ErrVal = PrintDialogEx(PDLGEX)
Call ComCtlsCdlPDEXRemoveHook
End If
If ErrVal = S_OK Then
If PDLGEX.dwResultAction <> CdlPDResultCancel Then
lpDevMode = GlobalLock(PDLGEX.hDevMode)
CopyMemory DMODE, ByVal lpDevMode, LenB(DMODE)
GlobalUnlock PDLGEX.hDevMode
GlobalFree PDLGEX.hDevMode
lpDevNames = GlobalLock(PDLGEX.hDevNames)
CopyMemory DNAMES, ByVal lpDevNames, LenB(DNAMES)
GlobalUnlock PDLGEX.hDevNames
GlobalFree PDLGEX.hDevNames
NewPrinterName = Left$(DMODE.DMDeviceName(), InStr(DMODE.DMDeviceName(), vbNullChar) - 1)
Dim PrinterFound As Boolean
If StrComp(VB.Printer.DeviceName, NewPrinterName, vbTextCompare) <> 0 Then
For Each ObjPrinter In VB.Printers
If StrComp(ObjPrinter.DeviceName, NewPrinterName, vbTextCompare) = 0 Then
Set VB.Printer = ObjPrinter
PrinterFound = True
Exit For
End If
Next ObjPrinter
Else
PrinterFound = True
End If
If PropPrinterDefault = True Then Call SetPrinterDefault(NewPrinterName)
If PrinterFound = True Then
On Error Resume Next
With VB.Printer
.Copies = DMODE.DMCopies
.Duplex = DMODE.DMDuplex
.Orientation = DMODE.DMOrientation
.PaperSize = DMODE.DMPaperSize
.PrintQuality = DMODE.DMPrintQuality
.ColorMode = DMODE.DMColor
.PaperBin = DMODE.DMDefaultSource
End With
On Error GoTo 0
End If
PropFlags = PDLGEX.Flags
If (PropFlags And CdlPDUseDevModeCopiesAndCollate) <> 0 Then
If DMODE.DMCollate = 1 And (PropFlags And CdlPDCollate) = 0 Then PropFlags = PropFlags Or CdlPDCollate
End If
PropFromPage = PPAGERANGE.nFromPage
PropToPage = PPAGERANGE.nToPage
PropMin = PDLGEX.nMinPage
PropMax = PDLGEX.nMaxPage
If (PropFlags And (CdlPDReturnDC Or CdlPDReturnIC)) <> 0 Then PropDC = PDLGEX.hDC
ShowPrinterEx = PDLGEX.dwResultAction
Else
If PropCancelError = True Then Err.Raise Number:=CdlCancel, Description:="Cancel was selected."
End If
Else
If PDLGEX.hDevMode <> 0 Then GlobalFree PDLGEX.hDevMode
If PDLGEX.hDevNames <> 0 Then GlobalFree PDLGEX.hDevNames
Const E_OUTOFMEMORY As Long = &H8007000E, E_INVALIDARG As Long = &H80070057, E_POINTER As Long = &H80004003, E_HANDLE As Long = &H80070006, E_FAIL As Long = &H80004005
Select Case ErrVal
Case E_OUTOFMEMORY, E_INVALIDARG, E_POINTER, E_HANDLE, E_FAIL
Err.Raise Number:=CdlInitFailure, Description:="The PrintDlgEx function failed during initialization."
Case Else
Err.Raise Number:=ErrVal, Description:="Unexpected error."
End Select
End If
End Function

Last edited by Jonney; Apr 12th, 2015 at 07:31 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|