SAP Knowledge Base Article - Public

1184381 - How to keep the settings for a printer when using the 'SelectPrinter' method

Symptom

At an operating system level, is it possible to define the settings for a specific tray/paper format for a given printer?

When invoking the SelectPrinter method, the settings for the printer will be default ones so any customization at the Control Panel level is lost.

Cause

The behaviour is normal.

Resolution

When the customized settings for the printer need to be retained, the workaround is to write a routine which

  • retrieves the settings for the required printer (in COM invoking the WINSPOOL API)
  • changes the printer settings for the CRViewer object.

The codes returned from the API vary from printer to printer and are not the same as the constants used by Crystal Reports so another function will be needed to to translate the codes returned by WINSPOOL onto the Crystal Reports constants.

Below is sample code in Visual Basic, which demonstrates a possible solution, when you need to print using the paper tray defined on the printer settings in the control panel.

' #### START OF CODE ############
' THIS PART OF CODE GOES IN A MODULE
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 OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long
Private Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, buffer As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'---------------------------------------------------------------
' Retrieve the vb object "printer" corresponding to the window's
' default printer.
'---------------------------------------------------------------
Public Function GetDefaultPrinter() As Printer
    Dim strBuffer As String * 254
    Dim iRetValue As Long
    Dim strDefaultPrinterInfo As String
    Dim tblDefaultPrinterInfo() As String
    Dim objPrinter As Printer
    ' Retreive current default printer information
    iRetValue = GetProfileString("windows", "device", ",,,", _
                strBuffer, 254)
    strDefaultPrinterInfo = Left(strBuffer, InStr(strBuffer, Chr(0)) - 1)
    tblDefaultPrinterInfo = Split(strDefaultPrinterInfo, ",")
    For Each objPrinter In Printers
        If objPrinter.DeviceName = tblDefaultPrinterInfo(0) Then
            ' Default printer found !
            Exit For
        End If
    Next
    ' If not found, return nothing
    If objPrinter.DeviceName <> tblDefaultPrinterInfo(0) Then
        Set objPrinter = Nothing
    End If
    Set GetDefaultPrinter = objPrinter
End Function
Public Function setDefaultPrinter(strPrinterName As String)
Dim myPrinter As Printer
For Each myPrinter In Printers
    If myPrinter.DeviceName = strPrinterName Then
        Set Printer = myPrinter
        Exit For
    End If
Next
End Function
' ----------------------
' --- THE FOLLOWING CODE GOES BETWEEN THE SELECTPRINTER AND PRINTOUT METHODS 
Dim iDefSourceWin as integer   ' this variable will store the value returned  from Windows for the papersource set for the printer
Dim P as Printer
P = GetDefaultPrinter
 
iDefSourceWin = GetPrinterPaperBin(P.Devicename, P.HDC) 
' now we need to convert the windows value to the one for crystal
iDefsourceCR = ConvertPaperBinCodeWtoCR(iDefSourceWin,  P.DeviceName)
crxReport.PaperSource = iDefSourceCR
' THIS IS THE FUNCTION  GetPrinterPaperBin WHICH RETURNS THE TRAY
' THE TRAY IS RETURNED AS A INTEGER,
Function GetPrinterPaperBin(szPrinterName As String, hdc As Long) As Integer
      Dim hPrinter As Long
      Dim nSize As Long
      Dim pDevMode As DEVMODE
      Dim aDevMode() As Byte
      Dim TempStr As String
        If OpenPrinter(szPrinterName, hPrinter, NULLPTR) <> 0 Then
           nSize = DocumentProperties(NULLPTR, hPrinter, szPrinterName, _
           NULLPTR, NULLPTR, 0)
          If nSize < 1 Then
            GetPrinterPaperBin = 0
            Exit Function
          End If
          ReDim aDevMode(1 To nSize)
          nSize = DocumentProperties(NULLPTR, hPrinter, szPrinterName, _
          aDevMode(1), NULLPTR, DM_OUT_BUFFER)
          If nSize < 0 Then
            GetPrinterPaperBin = 0
            Exit Function
          End If
         Call CopyMemory(pDevMode, aDevMode(1), Len(pDevMode))
      
         GetPrinterPaperBin = pDevMode.dmDefaultSource   
              
         Call ClosePrinter(hPrinter)
      Else
         GetPrinterPaperBin = 0
      End If
   
End Function
' THIS IS THE FUNCTION  ConvertPaperBinCodeWtoCR which translates the value from  Windows to CR coding
' WIN CODES MAY BE SPECIFIC TO PRINTER MODELS, SO YOU NEED TO CREATE YOUR OWN  CONVERSION TABLE
' SOME VALUES ARE THE SAME FOR ALL PRINTERS
Public Function ConvertPaperBinCodeWtoCR(iWinCode as integer, strPrinter as  string ) as Integer
' this routine converts an integer value, corresponding to the paperbin value returned by the winspool api for a given printer.
' below the list of constants for the bin selection used by crystal reports
' constant value
' ------------------------
' crPRBinAuto   8
' crPRBinCassette 14
' crPRBinEnvelope  5
' crPRBinManual   6
' crPRBinFormSource 15
' crPRBinLargeCapacity  11
' crPRBinLargeFmt 10
' crPRBinLower   2
' crPRBinManual   4
' crPRBinMiddle   3
' crPRBinSmallFmt  9
' crPRBinTractor  8
' crPRBinUpper   1                              
' ------------------------
Dim iResult
iResult = 8  ' if no value is returned, will set to automatic
Select Case strPrinter    
    Case "HP laserjet 4000"           
            Select Case iWinCode
                Case 15 ' automatic
                   iResult = 8          
                Case 257  ' cassette
                   iResult = 14
      End Select
    Case "Fujitsu DL 1100"
                        Select Case iWinCode
                Case 15,8 ' automatic - tractor
                 iResult = 8
          
                End Select
End Select
                                 
' returning the converted value.
ConvertPaperBinCodeWtoCR = iResult                    
End Function
' #### END OF CODE #######

Keywords

selectprinter, crystal, sdk, rdc, default printer settings lost , 1869514 , KBA , BI-RA-CR , Crystal Reports designer or BusinessViews Manager , How To

Product

SAP Crystal Reports 10.0 ; SAP Crystal Reports 9.0 ; SAP Crystal Reports XI ; SAP Crystal Reports XI R2 ; SAP Crystal Reports, version for Visual Studio .NET 2005 ; SAP Crystal Reports, version for Visual Studio .NET 2008 ; SAP Crystal Reports, version for Visual Studio .NET 9.1