how to use printerproperties api on winxp/win2k

I'm trying to use printerproperties api function from winspool.drv, but it dosen't work on winxp (it shows the about dialog of the printer driver or a basic property window), on win98, win95 or winME works perfectly. I need it because I want to make a custom printer dialog.

the code goes like this:

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As Any) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Function PrinterProperties Lib "winspool.drv" (ByVal hwnd As Long, ByVal hPrinter As Long) As Long
Private Sub Form_Load()
    Dim hPrinter As Long
    OpenPrinter Printer.DeviceName, hPrinter, ByVal 0&
    PrinterProperties Me.hwnd, hPrinter
    ClosePrinter hPrinter
End Sub

Is there any work around to this prob?
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

What about using commondialog to show printer properties?

SebaBigliaAuthor Commented:
I'm already using it, but I want to customize the printer dialog, to reduce the number of step you need to print. now the user needs to set my program's specifics opcions, then select a printer, and then configure the printer options, I want to put the two first dialogs in one.

You can set these options directly with OpenPrinter and GetPrinter APIs:

Private Type DEVMODE
    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

Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

SebaBigliaAuthor Commented:
I think that you aren't getting my point, I need to place a combo box in a dialog with the list of installed printers (done) and a button next to it to open the selected printer properties, that is what I want to do. It's is supposed to be done using the printerproperties API, but I don't know why it dosen't work on Win2k/WinXP, I need a workarround to this specific problem.

I think that there my be a way because a lot of commercial applications has a custom printing dialog an has the combo with the "properties..." button and it works OK on any OS.
Well why don't you then just enumerate all printers and put them to combobox?
SebaBigliaAuthor Commented:
I've already done it. But I wan't to open the printer properties window of the selected printer in the combobox with the "printerpoperties" API and it dosen't work, it just shows you a usless about form. If you try the same code on win98 it works just fine. That is my problem, I need to know if there is any way to make the code works on win2k/winxp.w
Private Const DM_OUT_BUFFER = 2
Private Const DM_IN_PROMPT = 4
Private Const DM_IN_BUFFER = 8
Private Const IDOK = 1
Private Const IDCANCEL = 2
Private Const PRINTER_ACCESS_USE = &H8

    pDatatype As String
    pDevMode As Long
    DesiredAccess As Long
End Type

Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal ByteLen As Long)
Private Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hwnd As Long, ByVal hPrinter As Long, ByVal pDeviceName As String, ByVal pDevModeOutput As Long, ByVal pDevModeInput As Long, ByVal fMode As Long) As Long
Private Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long
Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As Any) As Long
Private Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal Command As Long) As Long

Public Sub DocumentPropertiesDlg(ByVal hwnd As Long, ByVal PrinterName As String)
    Dim r As Long
    Dim hPrinter As Long
    Dim mDM() As Long
    Dim mPI2() As Long
    Dim BytesNeeded As Long
    Dim Drav As Long
    Dim ErrReport As Boolean
    ErrReport = True
    PD.DesiredAccess = PRINTER_ALL_ACCESS
    PD.pDatatype = vbNullString
    PD.pDevMode = 0
    r = OpenPrinter(PrinterName, hPrinter, PD)
    If (r = 0) Or (hPrinter = 0) Then
        GoTo Clean
    End If
    r = DocumentProperties(0, hPrinter, PrinterName, 0, 0, 0)
    If r < 0 Then
        GoTo Clean
    End If
    '1 Long = 4 Byte
    ReDim mDM(r / 4)
    r = DocumentProperties(hwnd, hPrinter, PrinterName, VarPtr(mDM(0)), VarPtr(mDM(0)), DM_OUT_BUFFER Or DM_IN_PROMPT)
    If r = IDCANCEL Then
        GoTo Clean
    End If
    GetPrinter hPrinter, 2, 0, 0, BytesNeeded
    If BytesNeeded = 0 Then
        GoTo Clean
    End If
    ReDim mPI2(BytesNeeded / 4)
    r = GetPrinter(hPrinter, 2, mPI2(0), BytesNeeded, Drav)
    If r = 0 Then
        GoTo Clean
    End If
    mPI2(7) = VarPtr(mDM(0))
    r = SetPrinter(hPrinter, 2, mPI2(0), 0)
    If CBool(r) = False Then
        GoTo Clean
    End If
    ErrReport = False
    If ErrReport And Err.LastDllError <> 0 Then
        MsgBox Err.LastDllError
    End If
    If hPrinter <> 0 Then
        ClosePrinter hPrinter
    End If
End Sub

Private Sub Command1_Click()
   DocumentPropertiesDlg Me.hwnd, Printer.DeviceName
End Sub

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SebaBigliaAuthor Commented:
Now we are talking, that's what I was looking for..

Works like a charm, thank's man.
You're welcome =)

At first I didn't understand what are you trying to do.. :)
SebaBigliaAuthor Commented:
I'm not a naturally english speaker (or writer), so maybe I didn't explain myself well.

I was looking for this tip for about two months. But everywere I look they talk about printerproperties function but none of them ever mention DocumentProperties.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.