Results 1 to 26 of 26

Thread: How to get the printer name selected in the common dialog?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    How to get the printer name selected in the common dialog?

    I want to get printer name selected in the common dialog.
    For example, I show printer dialog like following code.
    Code:
    CommonDialog1.Flags = cdlPDReturnDC + cdlPDNoPageNums
    CommonDialog1.PrinterDefault = False
    CommonDialog1.Flags = 0
    CommonDialog1.Orientation = cdlPortrait
    CommonDialog1.CancelError = True
    CommonDialog1.FontSize = 14
    CommonDialog1.FontName = "Tahoma"
    CommonDialog1.ShowPrinter
    I want to get printer name selected in the common dialog.
    How to get it?

  2. #2
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    VB6 basically just uses the default printer. There are ways you can change this default printer, but that's always what it's using.

    Here's some code to get the name of the default printer, which is basically what you're asking for:

    Code:
    
    Option Explicit
    '
    Private Declare Function GetDefaultPrinterAPI Lib "winspool.drv" Alias "GetDefaultPrinterA" (ByVal sPrinterName As String, lPrinterNameBufferSize As Long) As Long
    
    Private Sub Form_Load()
        MsgBox GetDefaultPrinter
    End Sub
    
    Public Function GetDefaultPrinter() As String
        GetDefaultPrinter = Space$(255)
        GetDefaultPrinterAPI ByVal GetDefaultPrinter, 255
        GetDefaultPrinter = RTrimNull(GetDefaultPrinter)
    End Function
    
    Public Function RTrimNull(s As String) As String
        Dim i As Integer
        i = InStr(s, vbNullChar)
        If i Then
            RTrimNull = Left$(s, i - 1)
        Else
            RTrimNull = s
        End If
    End Function
    
    
    
    Enjoy,
    Elroy

    p.s. I just threw it all into Form1 to test it.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: How to get the printer name selected in the common dialog?

    Actually I wanted to get the printer selected in the CommonDialog.
    If I run the code, GetDefaultPrinter returns system default printer, not the printer selected in the CommonDialog.
    Name:  printer.PNG
Views: 3961
Size:  23.6 KB
    In the screen capture, system default printer is "Bullzip PDF Printer".
    I selected "Microsoft XPS Document" in the CommonDialog, but GetDefaultPrinter() returns "Bullzip PDF Printer", not "Microsoft XPS Document".

  4. #4
    PowerPoster
    Join Date
    Dec 2004
    Posts
    25,618

    Re: How to get the printer name selected in the common dialog?

    microsoft has another printer dialog, that you can download and use, that will return the printer selected in the dialog

    unfortunately, on checking the link before posting, the link to that appears to have gone dead
    from memory, i think the file was called printdlg.dll
    there are some example here on the use of it
    i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case.
    Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next

    dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part

    come back and mark your original post as resolved if your problem is fixed
    pete

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Hmmm, if you want it as it's clicked, you'd almost certainly have to use an API call to bring up the dialog, rather than the CommonDialog control.

    Once doing it with the API, you may be able to set a callback procedure and monitor which printer is being clicked. And that's one of those UDTs (that's fed into the API) that's got some funky padding issues. In other words, it doesn't play well with VB6's UDT padding, so you have to do it with Byte array and some CopyMemory.

    I don't have anything obvious in my toolbox to give you the printer that's clicked as it's clicked, but I suspect there may be something in the CodeBank. If it were me, I'd try searching around there, or possibly using Google with "site:vbforums.com" as part of the search.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    WOW, I thought I'd play around a bit with the lpfnPrintHook address and PD_ENABLEPRINTHOOK flag, but code that worked on Win7 doesn't seem to work on Win10 (1803). Specifically, I'm talking about the code in this post.

    I even tried commenting out the call to lpfnSetupHook (along with the PD_ENABLESETUPHOOK flag), and it still crashed. Apparently Win10 no longer likes these CallBacks.

    Given that, I guess the only robust solution to this is to subclass the Print dialog form with another thread (probably another process). And even then, you've got some work to figure out which printer is highlighted.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  7. #7
    Hyperactive Member
    Join Date
    Nov 2011
    Posts
    498

    Re: How to get the printer name selected in the common dialog?

    why carn't you just set the default printer in code with API , then show dialog which will have the correct printer set.
    then once printed, put default printer back to the original. Thats what i do

  8. #8
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: How to get the printer name selected in the common dialog?

    k_zeon, How do you know which printer the user is going to select when shown the dialog so that you can preset it as the default?
    I have seven selections on the printer dialog. I can't know ahead of time which device the users is going to select.

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: How to get the printer name selected in the common dialog?

    What is the API for default printer setting?
    Last edited by jdy0803; Jun 19th, 2018 at 11:19 AM.

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Here's code I've used virtually forever (and is extremely well exercised) for setting the default printer:

    Code:
    
    Option Explicit
    '
    Private Declare Function GetProfileString Lib "kernel32" Alias "GetProfileStringA" (ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long) As Long
    Private Declare Function WriteProfileString Lib "kernel32" Alias "WriteProfileStringA" (ByVal lpszSection As String, ByVal lpszKeyName As String, ByVal lpszString As String) As Long
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
    '
    Private Const HWND_BROADCAST = &HFFFF
    Private Const WM_WININICHANGE = &H1A
    '
    
    Public Function SetPrinterAsDefault(ByVal DeviceName As String) As Boolean
        Dim Buffer As String
        Dim r As Long
        Dim sPrinterDevName As String
        Dim DriverName As String
        Dim PrinterPort As String
        Dim DeviceLine As String
        Dim l As Long
        Dim iDriver As Integer
        Dim iPort As Integer
        '
        ' Set up for changing the default.
        Buffer = Space(8192)
        r = GetProfileString("windows", "Device", vbNullString, Buffer, Len(Buffer))
        If r <> 0 Then
            ' Remove the wasted space
            Buffer = Mid(Buffer, 1, r)
            ' Store the current default printer before we change it
            sPrinterDevName = Mid(Buffer, 1, InStr(Buffer, ",") - 1)
            ' m_sPrevPrinterDriver = Mid(Buffer, InStr(Buffer, ",") + 1, InStrRev(Buffer, ",") - InStr(Buffer, ",") - 1)
            ' m_sPrevPrinterPort = Mid(Buffer, InStrRev(Buffer, ",") + 1)
        End If
        '
        ' If its not currently set as the default then set it...
        If sPrinterDevName <> DeviceName Then
            Buffer = Space(1024)
            r = GetProfileString("PrinterPorts", DeviceName, vbNullString, Buffer, Len(Buffer))
            '
            ' Parse the driver name and port name out of the buffer
            DriverName = vbNullString
            PrinterPort = vbNullString
    
            ' The driver name is first in the string terminated by a comma
            iDriver = InStr(Buffer, ",")
            If iDriver > 0 Then
                ' Strip out the driver name
                DriverName = Left(Buffer, iDriver - 1)
                ' The port name is the second entry after the driver name separated by commas.
                iPort = InStr(iDriver + 1, Buffer, ",")
                If iPort > 0 Then
                    'Strip out the port name
                    PrinterPort = Mid(Buffer, iDriver + 1, iPort - iDriver - 1)
                End If
            End If
            '
            If DriverName <> vbNullString And PrinterPort <> vbNullString Then
                DeviceLine = DeviceName & "," & DriverName & "," & PrinterPort
                ' Store the new printer information in the [WINDOWS] section of the WIN.INI file for the DEVICE= item
                r = WriteProfileString("windows", "Device", DeviceLine)
                If r Then
                    'Cause all applications to reload the INI file:
                    l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")
                    SetPrinterAsDefault = True
                Else
                    SetPrinterAsDefault = False
                End If
            Else
                SetPrinterAsDefault = False
            End If
        Else
            SetPrinterAsDefault = True
        End If
    End Function
    
    
    
    Enjoy,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  11. #11
    PowerPoster
    Join Date
    Dec 2004
    Posts
    25,618

    Re: How to get the printer name selected in the common dialog?

    there is also setdefaultprinter API
    i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case.
    Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next

    dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part

    come back and mark your original post as resolved if your problem is fixed
    pete

  12. #12
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the printer name selected in the common dialog?

    Some changes have been made to spooled printing in desktop Windows, starting in Windows 10 1511 or so. I don't know of any authoritative list of the changes, but they include things like "Let Windows manage my default printer."

    How to set a default printer in Windows 10

  13. #13
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Quote Originally Posted by dilettante View Post
    Some changes have been made to spooled printing in desktop Windows, starting in Windows 10 1511 or so. I don't know of any authoritative list of the changes, but they include things like "Let Windows manage my default printer."

    How to set a default printer in Windows 10
    Yeah, I haven't heard any complaints with my software, and I know that people change printers within it all the time (which executes the code in post #10). And my users are slowly moving to Windows 10, with quite a few on it now.

    However, I also haul my Windows 10 laptop all over the place, plugging in various printers at various user sites. The new Windows 10 printer management is pretty nice. Apparently, it poles the printers to see which one is available, and makes a recommendation based on availability. I like it, and it seems to be very backwards-compatible. So all is good.

    Y'all Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  14. #14
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,654

    Re: How to get the printer name selected in the common dialog?

    To answer the original question, I thought the dialog changed the current default so you could just get the name from the Printer object?

    If not, you can look at something like Krool's CommonDialog module, which does the (very complicated) work of retrieving the name from the PrintDlg API, which is better than the control anyway.

  15. #15
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,000

    Re: How to get the printer name selected in the common dialog?

    From this project, download the zip file at the end of the first post, but you only need to use cCDlg.cls that is in the "others" folder.

    It is a CommonDialog replacement that has a property to retrieve what printer was selected. The property name is DeviceName.

    Sample code:
    Code:
        Dim d As New CDlg
        
        d.ShowPrinter
        If Not d.Cancelled Then
            MsgBox d.DeviceName
        End If

  16. #16
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Quote Originally Posted by fafalone View Post
    To answer the original question, I thought the dialog changed the current default so you could just get the name from the Printer object?

    If not, you can look at something like Krool's CommonDialog module, which does the (very complicated) work of retrieving the name from the PrintDlg API, which is better than the control anyway.
    Hi fafalone,

    That's what I also originally thought. However, I progressed to the idea that he wanted the printer name as it was clicked but not necessarily double-clicked (i.e., selected) in the common dialog. The only way to do that was with the API callback, but I couldn't get that working under Windows 10.

    All The Best,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  17. #17
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,376

    Re: How to get the printer name selected in the common dialog?

    Quote Originally Posted by Elroy View Post
    Hi fafalone,

    That's what I also originally thought. However, I progressed to the idea that he wanted the printer name as it was clicked but not necessarily double-clicked (i.e., selected) in the common dialog. The only way to do that was with the API callback, but I couldn't get that working under Windows 10.

    All The Best,
    Elroy
    In my CommonControls CommonDialog is a property called 'HookEvents'. If true, you may declare WithEvents with the class to read the messages.

  18. #18
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,654

    Re: How to get the printer name selected in the common dialog?

    Does it work on Win10? This seems to a running theme lately, Win10 is breaking APIs.

  19. #19
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the printer name selected in the common dialog?

    I don't think Windows 10 is "breaking APIs" so much as it is breaking code hacks. We see a lot of people proudly using Windows wrong here, then crying when reliance on quirks fall apart on them.

    If you want long term stability you need to stick to documented operation as closely as possible. That can still change but it changes far less often than undocumented behaviors do.


    Either way crying and kicking helps nobody. Windows 10 is not going away and is not going to stop evolving.

  20. #20
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    *shakes head in puzzlement*

    Dil, I'm not sure I saw anyone crying and kicking. And I think we're all acutely aware that Win10 isn't going anywhere. But the code in this post seemed to work fine prior to Win10, and now it just freezes my system immediately after the first CallBack message box is clicked.

    The last system I thoroughly checked it on was Win7-64-bit. I've still got that machine. It would take a bit to power it up, but I'm willing to do that if need be to get this sorted.

    Best Regards,
    Elroy

    EDIT1: Well, "freezes my system" isn't quite right. But it does freeze that copy of VB6.
    Last edited by Elroy; Jun 21st, 2018 at 07:30 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  21. #21
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,376

    Re: How to get the printer name selected in the common dialog?

    Elroy, does my CommonDialog freeze on your copy on win10?

  22. #22
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Let me try it. I assume you're just talking about the rolled-up OCX. That's what I'll try first, as it's easiest.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  23. #23
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Hmmm, ok, I'm confused. Krool, where is your CommonDialog? I downloaded your OCX (found here), unzipped it, threw it into SysWOW64, and registered it with RegSvr32.

    Then, I started a new project and added it through Components, but I don't see the CommonDialog. Here's a screenshot of my Toolbox after your OCX has been added:

    Name:  Toolbox.png
Views: 3224
Size:  9.4 KB

    I hovered over each new control, and none of them seem to be a CommonDialog.

    I'll try it now from your demo project.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  24. #24
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Hmmm, ok, it seems to be working in your demo project. It wasn't a UC, but I found it anyway. I'm assuming we're talking about your CommonDialog.cls class.

    To test it, I first put this at the top of your MainForm:

    Code:
    Dim WithEvents cd As CommonDialog
    And then, I put a new button on that form (Command5), and put this in it:

    Code:
    Private Sub Command5_Click()
        Set cd = New CommonDialog
        cd.HookEvents = True
        cd.ShowPrinter
    End Sub
    I also placed this in that MainForm code:

    Code:
    Private Sub cd_InitDialog(ByVal Action As Integer, ByVal hDlg As Long)
        Debug.Print "InitDialog"
    End Sub
    It did fire that cd_InitDialog event when Command5 was clicked.

    To further test, I looked at your ShowPrinter() code within CommonDialog.cls, and saw where you were setting the callback. You seemed to use the same callback for both the SetupHook and the PrintHook (ComCtlsCdlPDCallbackProc), so I went there. To further test, I just placed the following at the top of that callback procedure:

    Code:
    Debug.Print "Callback ";
    Interestingly, it streamed that "Callback " string in my Immediate Window, so all seems to be good.

    I glanced at your setup of the PRINTDLG UDT. I checked the way you use Len(PDLG), and it correctly reports 66 bytes. I also noticed you're doing something fancy with Word Endianness. I didn't study it in detail so I'm not sure what that's about. But I'm thinking that has more to do with the funky way VB6 pads UDTs and your work-around.

    Obviously it works, so my CopyMemory approach is apparently doing something wrong. I'll study it more a bit later.

    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  25. #25
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,376

    Re: How to get the printer name selected in the common dialog?

    Problem here is the uneven (5) integers in a row and then Longs. That's why Len() instead of LenB() must be used. (2 bytes overhang)
    But thats not enough to just report the necessary length of the struct.
    The actual struct needs to represent this quirk to not confuse VB6, that's why the fancy word splits are in the Struct.

    Most APIs also consider such padding so VB6's LenB() is most of time accurate but obviously not for this one.
    Last edited by Krool; Jun 21st, 2018 at 10:53 PM. Reason: Typo

  26. #26
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,862

    Re: How to get the printer name selected in the common dialog?

    Quote Originally Posted by Krool View Post
    Problem here is the uneven (5) integers in a row and then Longs. That's why Len() instead of LenB() must be used. (2 bit overhang)
    But thats not enough to just report the necessary length of the struct.
    The actual struct needs to represent this quirk to not confuse VB6, that's why the fancy word splits are in the Struct.

    Most APIs also consider such padding so VB6's LenB() is most of time accurate but obviously not for this one.
    Yeah, I thought I had done it correctly with a Byte array (and some CopyMemory), but apparently I need to take another look. I've got some other stuff going on, so I'll have to look at it later.

    Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width