Solved

Getting Printer Info from CommonDialog hDC

Posted on 1997-12-17
18
1,547 Views
Last Modified: 2012-05-04
I'm using a CommonDialog control to display a Print Dialog box.  I am trying to get the printer name, printer driver and printer port of the selected printer thru this dialog box WITHOUT changing the system default printer.  I want to send these values to a Crystal Reports control.  The dialog box returns an hDC value, but not the info that I need.  I am wondering if there is a way to retrieve the information I need using the hDC value returned by the dialog box.  I'm using VB 4.0 (16-bit).

Thanks in advance!
0
Comment
Question by:dcampagna
  • 6
  • 5
  • 4
  • +2
18 Comments
 
LVL 5

Expert Comment

by:dirtdart
ID: 1445621
Declare Function GetDeviceCaps Lib "gdi32" Alias "GetDeviceCaps" (ByVal hdc As Long, ByVal nIndex As Long) As Long

where nIndex is a value indicating what information you want to retrieve.

HORZSIZE
 Width, in millimeters, of the physical screen.
 
VERTSIZE
 Height, in millimeters, of the physical screen.
 
HORZRES
 Width, in pixels, of the screen.
 
VERTRES
 Height, in raster lines, of the screen.
 
LOGPIXELSX
 Number of pixels per logical inch along the screen width.
 
LOGPIXELSY
 Number of pixels per logical inch along the screen height.
 
BITSPIXEL
 Number of adjacent color bits for each pixel.
 
PLANES
 Number of color planes.
 
NUMBRUSHES
 Number of device-specific brushes.
 
NUMPENS
 Number of device-specific pens.
 
NUMFONTS
 Number of device-specific fonts.
 
NUMCOLORS
 Number of entries in the device’s color table, if the device has a color depth of no more than 8 bits per pixel. For devices with greater color depths, -1 is returned.
 
ASPECTX
 Relative width of a device pixel used for line drawing.
 
ASPECTY
 Relative height of a device pixel used for line drawing.
 
ASPECTXY
 Diagonal width of the device pixel used for line drawing.
 
PDEVICESIZE
 Reserved.
 
CLIPCAPS
 Flag that indicates the clipping capabilities of the device. If the device can clip to a rectangle, it is 1. Otherwise, it is 0.
 
SIZEPALETTE
 Number of entries in the system palette. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is compatible with Windows version 3.0 or later.
 
NUMRESERVED
 Number of reserved entries in the system palette. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is compatible with Windows version 3.0 or later.
 
COLORRES
 Actual color resolution of the device, in bits per pixel. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is compatible with Windows version 3.0 or later.
 
PHYSICALWIDTH
 For printing devices: the width of the physical page, in device units. For example, a printer set to print at 600 dpi on 8.5"x11" paper has a physical width value of 5100 device units. Note that the physical page is almost always greater than the printable area of the page, and never smaller.
 
PHYSICALHEIGHT
 For printing devices: the height of the physical page, in device units. For example, a printer set to print at 600 dpi on 8.5"x11" paper has a physical height value of 6600 device units. Note that the physical page is almost always greater than the printable area of the page, and never smaller.
 
PHYSICALOFFSETX
 For printing devices: the distance from the left edge of the physical page to the left edge of the printable area, in device units. For example, a printer set to print at 600 dpi on 8.5"x11" paper, that cannot print on the leftmost 0.25" of paper, has a horizontal physical offset of 150 device units.
 
PHYSICALOFFSETY
 For printing devices: the distance from the top edge of the physical page to the top edge of the printable area, in device units. For example, a printer set to print at 600 dpi on 8.5"x11" paper, that cannot print on the topmost 0.5" of paper, has a vertical physical offset of 300 device units.
 
VREFRESH
 Windows NT only: For display devices: the current vertical refresh rate of the device, in cycles per second (Hz).

A vertical refresh rate value of 0 or 1 represents the display hardware’s default refresh rate. This default rate is typically set by switches on a display card or computer motherboard, or by a configuration program that does not use Win32 display functions such as ChangeDisplaySettings.
 
DESKTOPHORZRES
 Windows NT only: Width, in pixels, of the virtual desktop. This value may be larger than HORZRES if the device supports a virtual desktop or multiple displays.
 
DESKTOPVERTRES
 Windows NT only: Height, in pixels, of the virtual desktop. This value may be larger than VERTRES if the device supports a virtual desktop or multiple displays.
 
BLTALIGNMENT
 Windows NT only: Preferred horizontal drawing alignment, expressed as a multiple of pixels. For best drawing performance, windows should be horizontally aligned to a multiple of this value. A value of zero indicates that the device is accelerated, and any alignment may be used.
 
RASTERCAPS
 Value that indicates the raster capabilities of the device, as shown in the following table:
 
Capability
 Meaning
 
RC_BANDING
 Requires banding support.
 
RC_BITBLT
 Capable of transferring bitmaps.
 
RC_BITMAP64
 Capable of supporting bitmaps larger than 64K.
 
RC_DI_BITMAP
 Capable of supporting the SetDIBits and GetDIBits functions.
 
RC_DIBTODEV
 Capable of supporting the SetDIBitsToDevice function.
 
RC_FLOODFILL
 Capable of performing flood fills.
 
RC_GDI20_OUTPUT
 Capable of supporting features of Windows 2.0.
 
RC_PALETTE
 Specifies a palette-based device.
 
RC_SCALING
 Capable of scaling.
 
RC_STRETCHBLT
 Capable of performing the StretchBlt function.
 
RC_STRETCHDIB
 Capable of performing the StretchDIBits function.
 
CURVECAPS
 Value that indicates the curve capabilities of the device, as shown in the following table:
 
Value
 Meaning
 
CC_NONE
 Device does not support curves.
 
CC_CIRCLES
 Device can draw circles.
 
CC_PIE
 Device can draw pie wedges.
 
CC_CHORD
 Device can draw chord arcs.
 
CC_ELLIPSES
 Device can draw ellipses.
 
CC_WIDE
 Device can draw wide borders.
 
CC_STYLED
 Device can draw styled borders.
 
CC_WIDESTYLED
 Device can draw borders that are wide and styled.
 
CC_INTERIORS
 Device can draw interiors.
 
CC_ROUNDRECT
 Device can draw rounded rectangles.
 
LINECAPS
 Value that indicates the line capabilities of the device, as shown in the following table:
 
Value
 Meaning
 
LC_NONE
 Device does not support lines.
 
LC_POLYLINE
 Device can draw a polyline.
 
LC_MARKER
 Device can draw a marker.
 
LC_POLYMARKER
 Device can draw multiple markers.
 
LC_WIDE
 Device can draw wide lines.
 
LC_STYLED
 Device can draw styled lines.
 
LC_WIDESTYLED
 Device can draw lines that are wide and styled.
 
LC_INTERIORS
 Device can draw interiors.
 
POLYGONALCAPS
 Value that indicates the polygon capabilities of the device, as shown in the following table:
 
Value
 Meaning
 
PC_NONE
 Device does not support polygons.
 
PC_POLYGON
 Device can draw alternate-fill polygons.
 
PC_RECTANGLE
 Device can draw rectangles.
 
PC_WINDPOLYGON
 Device can draw winding-fill polygons.
 
PC_SCANLINE
 Device can draw a single scanline.
 
PC_WIDE
 Device can draw wide borders.
 
PC_STYLED
 Device can draw styled borders.
 
PC_WIDESTYLED
 Device can draw borders that are wide and styled.
 
PC_INTERIORS
 Device can draw interiors.
 
TEXTCAPS
 Value that indicates the text capabilities of the device, as shown in the following table:
 
Bit
 Meaning
 
TC_OP_CHARACTER
 Device is capable of character output precision.
 
TC_OP_STROKE
 Device is capable of stroke output precision.
 
TC_CP_STROKE
 Device is capable of stroke clip precision.
 
TC_CR_90
 Device is capable of 90-degree character rotation.
 
TC_CR_ANY
 Device is capable of any character rotation.
 
TC_SF_X_YINDEP
 Device can scale independently in the x- and y-directions.
 
TC_SA_DOUBLE
 Device is capable of doubled character for scaling.
 
TC_SA_INTEGER
 Device uses integer multiples only for character scaling.
 
TC_SA_CONTIN
 Device uses any multiples for exact character scaling.
 
TC_EA_DOUBLE
 Device can draw double-weight characters.
 
TC_IA_ABLE
 Device can italicize.
 
TC_UA_ABLE
 Device can underline.
 
TC_SO_ABLE
 Device can draw strikeouts.
 
TC_RA_ABLE
 Device can draw raster fonts.
 
TC_VA_ABLE
 Device can draw vector fonts.
 
TC_RESERVED
 Reserved; must be zero.
 
TC_SCROLLBLT
 Device cannot scroll using a bit-block transfer. Note that this meaning may be the opposite of what you expect.

Of course, not all of these values apply to a printer.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1445622
dirtdart, this doesn't satisfy the question "How can I get the printer name, printer driver and printer port from the hDC".  Do you have the answer to this question?

By the way, I emailed the address you sent to me but it came back undeliverable, so I emailed your email address in regard to the C, MASM question.

0
 
LVL 39

Expert Comment

by:abel
ID: 1445623
Before I post an answer, please tell if you're using Win95 or Win31, since the way to get the information differs a lot. In Win95 it's quite easy, I'll give you the code if you need it for that OS, for Win31 I actually don't know.
Besides, if you use Win95, you don't have to use a CommonDlg to get the properties of a printer.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1445624
abel, better read the question again, the question is "How can I get the printer name, printer driver and printer port form the hDC returned form the CommonDialog control" and note the statement "I'm using VB 4.0 (16-bit)" - this means that even when running under 95, the app would be accessing the same API exposed under Win 3.1
0
 

Author Comment

by:dcampagna
ID: 1445625
I did not see any nIndex values to retrieve the printer name, driver and port.  How would I use the GetDeviceCaps function to do this (the function returns a LONG datatype)?
0
 
LVL 39

Expert Comment

by:abel
ID: 1445626
Yeah, I saw it. I already hit the submit-button. This actually means that the GetPrinter API with the PRINTER_INFO_2 structure  can't be used....
0
 

Author Comment

by:dcampagna
ID: 1445627
I am programming on a WinNT machine, but I am currently programming for a Win31environment... so I would need a 16-bit solution.

 Anyone have other suggestions?
0
 
LVL 4

Expert Comment

by:rantanen
ID: 1445628
In Win 3.X this info for default printer is in WIN.INI in windows sections, eg.

[windows]
device=Canon Bubble-Jet BJ-300,CANON330,LPT1:

in the form Printer name, printer driver, printer port.

so something like this

    RC = GetProfileString("windows", "device", "", Temp, 255)

will get you that string from which you can parse out the info you need.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1445629
rantanen, better read the question again...  

The question is: "How can I get the printer name, printer driver and printer port form the hDC returned form the CommonDialog control WITHOUT changing the system default printer"
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 4

Expert Comment

by:rantanen
ID: 1445630
Yes, I know that but he said in his later comment he's programming for Windows 3.1, so what does it matter how he gets the info he needs and in Win 3.X reading info from Win.ini is the easiest way. If he does not agree with me, he can always reject the answer.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1445631
rantanen, I'm not knocking you, It's just that I think dcampagna is really seeking a way to determine what printer was selected by the commondialog control.  If you know just the device name, you could enumerate through the printers collection to get the driver and port info.  For example,

Dim P As Printer

For Each P In Printers
 If P.DeviceName = "THE DEVICE NAME" Then
  Debug.Print P.DeviceName, P.DriverName, P.Port
 End If
Next

dcampagna,

A suggestion: why not save the value of the current printer device, permit the commondialog to change the default, get the information you're seeking by getting the values from the printer object, for example,

DevName = printer.devicename
DevDriver = printer.drivername
DevPort = printer.port

And then set the default printer back to what it was at the beginning of this process.

I think the problem here is that this was an oversight on Microsoft's part.  I don't think there is a way to do it using the commondialog control without setting the default printer.

I'm guessing that if a valid hDC were returned - is wouldn't actually be an hDC for the printer selected, but rather, a handle for a device context created for the current printer.  I believe this because if VB created a device context for any printer you select in the control - the DC would have to be destroyed at some point... how would VB know when the DC was no longer needed?... and since you'd have no way to use it... why would it be created?

I’m running VB5 and when I try using the commondialog control to select a printer with the PrinterDefault = False, the commondialog.hdc always returns zero (0) after returning from the showprinter method.  Nothing could be determined from this value anyway.  But I'm not certain about what is returned using VB4.  If you do get a valid handle, try checking it against the printer object's hDC when you've selected a printer other than the default printer.

0
 
LVL 4

Expert Comment

by:rantanen
ID: 1445632
ok mrmick, I did not read the question careful enough...it really indicates that he's not after the default printer, so what you suggested about saving the default printer, letting user change the printer and then change it back to the default sounds like a solution.

dcampagna, sorry I misundertood your question.
0
 

Author Comment

by:dcampagna
ID: 1445633
mrmick,
Thanks for the suggestion... but I've already tried something like that without success.  Following is code simular to what I tried a week or two ago (with the CommonDialog (cdlgPrinter) PrinterDefault=TRUE):


Sub PrintCRWToPrinter()

   Dim x As Printer
   Dim DefaultDeviceName As String

   DefaultDeviceName = Printer.DeviceName
   cdlgPrinter.CancelError = True
   On Error GoTo ErrHandler
   cdlgPrinter.Flags = &H100& + &H100000 + &H4&
Debug.Print "1     " & Printer.DeviceName & "    " & DefaultDeviceName
      cdlgPrinter.ShowPrinter

      If cdlgPrinter.Flags And &H2 Then   ' Print Range
         crwReport.PrinterStartPage = cdlgPrinter.FromPage
         crwReport.PrinterStopPage = cdlgPrinter.ToPage
      Else   'NewValue = 0 (Print All Pages)
         crwReport.PrinterStartPage = -1
         crwReport.PrinterStopPage = -1
      End If
     
      If cdlgPrinter.Flags And &H10 Then   ' Collate Copies
         crwReport.PrinterCollation = 1
      Else
         crwReport.PrinterCollation = 0
      End If
     
      crwReport.PrinterCopies = cdlgPrinter.Copies
      crwReport.Destination = 1
      crwReport.Action = 1
     
Debug.Print "2     " & Printer.DeviceName & "    " & DefaultDeviceName
    For Each x In Printers
Debug.Print "Loop   " & x.DeviceName & "  " & DefaultDeviceName
       If x.DeviceName = DefaultDeviceName Then
       'Set system printer back to original
          Set Printer = x
          Exit For
       End If
    Next
Debug.Print "3     " & Printer.DeviceName & "    " & DefaultDeviceName

    Exit Sub
     
ErrHandler:
   ' User pressed the Cancel button
   Exit Sub

End Sub


I've been thru this code a thousand times, and it seems like it should work, but it doesn't.


btw, rantanen, not that it matters, but...  I'm a "she", not a "he"
0
 

Author Comment

by:dcampagna
ID: 1445634
mrmick,
In reference to your code, although I am by no means an "expert", I thought you might want to check that your CommonDialog Flags property has be set to receive the hDC value as follows:  MyCommonDialog.Flags = &H100&
dcampagna

0
 
LVL 8

Expert Comment

by:mrmick
ID: 1445635
Ok, but what about it doesn't work?
0
 
LVL 8

Accepted Solution

by:
mrmick earned 150 total points
ID: 1445636
I'm assuming the problem is in setting the printer back to the original default printer.  This is a bug in VB.

Check out Microsoft Knowledge Base
Article ID: Q167735
Title: "BUG: Setting Printer to Item in the Printers Collection Fails"
http://premium.microsoft.com/support/kb/articles/q167/7/35.asp

This article states that it applies to VB5, but it should have included earlier versions as well.  The method you’ll need to use to reset the default printer can be found in the procedure below; however, you'll have to provide the appropriate 16 bit API declares and convert the following procedure to correctly call the 16 bit API functions.

     Private Sub SetDefaultPrinter(ByVal PrinterName As String, _
          ByVal DriverName As String, ByVal PrinterPort As String)
          Dim DeviceLine As String
          Dim r As Long
          Dim l As Long
          DeviceLine = PrinterName & "," & 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)
          ' Cause all applications to reload the INI file:
          l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")
      End Sub

0
 
LVL 4

Expert Comment

by:rantanen
ID: 1445637
dcampagna,

sorry ... it seems I never learn to write politically correct English.
Because I'm a "he" I automatically think that everybody else is also a "he" :-).

No - seriously - I have a difficulty with this even if I see with whom I'm discussing, because my own language does not have different words like "he" and "she".
0
 

Author Comment

by:dcampagna
ID: 1445638
mrmick,
Thanks!  Your fix seems to work.  Although I was hoping that I wouldn't have to change the system default printer, this solution should work for now.  Following is my code:

Sub PrintCRWToPrinter()

     Dim X As Printer
     Dim DefaultDeviceName As String

      DefaultDeviceName = Printer.DeviceName
      cdlgPrinter.CancelError = True
      On Error GoTo ErrHandler
      cdlgPrinter.Flags = &H100& + &H100000 + &H4&
      cdlgPrinter.ShowPrinter
     
      If cdlgPrinter.Flags And &H2 Then   ' Print Range
         crwReport.PrinterStartPage = cdlgPrinter.FromPage
         crwReport.PrinterStopPage = cdlgPrinter.ToPage
      Else   'NewValue = 0 (Print All Pages)
         crwReport.PrinterStartPage = -1
         crwReport.PrinterStopPage = -1
      End If
     
      If cdlgPrinter.Flags And &H10 Then   ' Collate Copies
         crwReport.PrinterCollation = 1
      Else
         crwReport.PrinterCollation = 0
      End If
     
      crwReport.PrinterCopies = cdlgPrinter.Copies
      crwReport.Destination = 1
      crwReport.Action = 1
     
    For Each X In Printers
       If X.DeviceName = DefaultDeviceName Then
          SetDefaultPrinter X.DeviceName, X.DriverName, X.Port
          Exit For
       End If
    Next

   Exit Sub
     
ErrHandler:
   ' User pressed the Cancel button
    For Each X In Printers
       If X.DeviceName = DefaultDeviceName Then
          SetDefaultPrinter X.DeviceName, X.DriverName, X.Port
          Exit For
       End If
    Next
   Exit Sub

End Sub


Private Sub SetDefaultPrinter(ByVal PrinterName As String, _
     ByVal DriverName As String, ByVal PrinterPort As String)
     
   Dim DeviceLine As String
   Dim r As Long
   Dim l As Long
   
   DeviceLine = PrinterName & "," & DriverName & "," & PrinterPort
   ' Store the new printer information in the [WINDOWS] section of
   ' the WIN.INI file for the DEVICE= item
   '*****************************************
   '*****************************************
   'I made the following change which appears
   'to update either a WinNT Registry or a
   'Win3.11 win.ini file.
   '*****************************************
   'Changed the following line:
   'r = WriteProfileString("windows", "Device", DeviceLine)
   'To the following line:
   SaveSetting "win", "windows", "Device", DeviceLine
   '*****************************************
   '*****************************************
   ' Cause all applications to reload the INI file:
   l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")
End Sub

dcampagna
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now