Hi,
Dear Burt,
I have tried your code (on XP). Actually it is quite complete. You
have practically
done the all job. I also appreciated your correction about setting
the printer name.
You are really an angel!
I have not tried yet to print because now its night here and I am
not at my office,
but the printer properties dialog pops up fine. In case of problems
I will tell you.
If I may, I would need some further info for some refinements.
I am loading the printer names in a combo (or perhaps I will use a
treeview):
with something like:
-------------------------------------
Private Sub YourPrinterSettingsDialog_Load(ByVal sender...) Handles
MyBase.Load
Dim PrinterNames As New ArrayList
For Each PrinterName As String In
PrinterSettings.InstalledPrinters
Try
PrinterNames.Add(PrinterName)
Catch
End Try
Next PrinterName
Me.ComboBoxPrinterNames.Items.AddRange(PrinterNames.ToArray)
End Sub
------------------------------------
I need to recognize: 1. the Default Printer, 2. Network printers, to
change the appearance
of their icons. So, I guess, I need 2 boolean functions:
function IsDefaulPrinter(PrinterName as string) as boolean
function IsNetworkPrinter(PrinterName as string) as boolean
(others assumed local, I guess)
I understand you want to customize the PrintDialog, is there anything in
particular that you want to change or add, it is possible to create your
own, but it will involve a lot of pinvoke.
About default and network printers, it's not that simple, if you want to do
this for all printers then you need to think about speed. You can use the
native function EnumPrinters(see MSDN) but it gets complicated because a
different level is needed for wxp/2000 or w9x/me.
The example shows you how you can do it using 2 additional classes:
PrinterInfo (name, isdefault, isnetwork)
PrinterApi (thin wrapper around w32 native Printer Functions)
YourPrintDialog.vb
------------------
Public Class YourPrintDialog
' ....
Private Sub LoadPrinters()
ComboBoxPrinterNames.Clear()
For Each pi As PrinterInfo In PrinterInfo.InstalledPrinters
Console.WriteLine("Name={0} Def={1} Network={2}", _
pi.Name, pi.IsDefault, pi.IsNetwork)
ComboBoxPrinterNames.Items.Add(pi.Name)
If (pi.IsDefault) Then ComboBoxPrinterNames.Text = pi.Name
Next
End Sub
' ....
End Class
PrinterInfo.vb
--------------
Public Class PrinterInfo
Public Name As String
Public IsDefault As Boolean
Public IsNetwork As Boolean
Public Shared ReadOnly Property InstalledPrinters() As PrinterInfo()
Get
Dim infos As New ArrayList
If (Environment.OSVersion.Platform = PlatformID.Win32NT) Then
' window xp,2000
Dim DefName As String = PrinterApi.GetDefPrinter()
For Each pi4 As PrinterApi.PRINTER_INFO_4 In _
PrinterApi.EnumInfo4( _
PrinterApi.PRINTER_ENUM_LOCAL Or _
PrinterApi.PRINTER_ENUM_CONNECTIONS)
Dim pi As New PrinterInfo
pi.Name = pi4.PrinterName
pi.IsDefault = Equals(pi4.PrinterName, DefName)
pi.IsNetwork = (pi4.Attributes And
PrinterApi.PRINTER_ATTRIBUTE_NETWORK) > 0
infos.Add(pi)
Next
Else
' windows 95,98,me
For Each pi5 As PrinterApi.PRINTER_INFO_5 In _
PrinterApi.EnumInfo5(PrinterApi.PRINTER_ENUM_LOCAL)
Dim pi As New PrinterInfo
pi.Name = pi5.PrinterName
pi.IsDefault = (pi5.Attributes And
PrinterApi.PRINTER_ATTRIBUTE_DEFAULT) > 0
pi.IsNetwork = (pi5.Attributes And
PrinterApi.PRINTER_ATTRIBUTE_NETWORK) > 0
infos.Add(pi)
Next
End If
Return infos.ToArray(GetType(PrinterInfo))
End Get
End Property
End Class
PrinterApi.vb
--------------
Imports System.Runtime.InteropServices
Imports System.Text
Public Class PrinterApi
Private Declare Auto Function EnumPrinters Lib "winspool.drv" ( _
ByVal flags As Int32, ByVal name As String, ByVal level As Int32, _
ByVal pPrinterEnum As IntPtr, ByVal cbBuf As Int32, _
ByRef pcbNeeded As Int32, ByRef pcReturned As Int32) As Int32
Private Declare Auto Function GetDefaultPrinter Lib "winspool.drv" ( _
ByVal szBuffer As StringBuilder, _
ByRef cchBuffer As Int32) As Int32
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class PRINTER_INFO_4
Public PrinterName As String
Public ServerName As String
Public Attributes As Integer
End Class
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class PRINTER_INFO_5
Public PrinterName As String
Public PortName As String
Public Attributes As Integer
Public DeviceNotSelectedTimeout As Integer
Public TransmissionRetryTimeout As Integer
End Class
Public Const PRINTER_ATTRIBUTE_NETWORK As Int32 = &H10
Public Const PRINTER_ENUM_CONNECTIONS As Int32 = &H4
Public Const PRINTER_ENUM_LOCAL As Int32 = &H2
Public Const PRINTER_ATTRIBUTE_DEFAULT As Int32 = &H4
Public Shared Function GetDefPrinter() As String
Dim sbName As New StringBuilder(32)
GetDefaultPrinter( sbName, 32 )
return sbName.ToString()
End Function
Public Shared Function EnumInfo4(ByVal Flags As Int32) As PRINTER_INFO_4()
' level 4 enum
Return DirectCast( _
EnumInfo(4, Flags, GetType(PRINTER_INFO_4)), _
PRINTER_INFO_4())
End Function
Public Shared Function EnumInfo5(ByVal Flags As Int32) As PRINTER_INFO_5()
' level 5 enum
Return DirectCast( _
EnumInfo(5, Flags, GetType(PRINTER_INFO_5)), _
PRINTER_INFO_5())
End Function
Private Shared Function EnumInfo(ByVal Level As Int32, _
ByVal Flags As Int32, ByVal InfoType As Type) As Object()
Dim cbNeeded As Int32, cReturned As Int32
Dim pBuffer As IntPtr, pBuf As IntPtr
Dim pi As Object
Dim infos As New ArrayList
' enumerate printers
EnumPrinters(Flags, Nothing, Level, IntPtr.Zero, 0, cbNeeded, cReturned)
pBuffer = Marshal.AllocHGlobal(cbNeeded)
EnumPrinters(Flags, Nothing, Level, pBuffer, cbNeeded, cbNeeded,
cReturned)
pBuf = pBuffer
For i As Int32 = 0 To cReturned - 1
pi = Marshal.PtrToStructure(pBuf, InfoType)
infos.Add(pi)
pBuf = New IntPtr(pBuf.ToInt64() + Marshal.SizeOf(InfoType))
Next
Marshal.FreeHGlobal(pBuffer)
Return infos.ToArray(InfoType)
End Function
End Class
HTH,
Greetings