Printer: How to get the device name

Just starting out? Need help? Post your questions and find answers here.
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

Shardik wrote:Terry,
I am sorry that my code didn't work for you. Did you test it with Win98? I had no problems running both examples under WinNT SP6 and WinXP SP2.
Yes, I was on Win98SE.
Tell me, if you want to change the default setting to landscape mode (without displaying the print dialog) and I will post an adapted example for you.
Generally I want to change the default setting to landscape mode and then select the default printer without displaying the print dialog. However, sometimes I do want to display the print dialog for printer selection.

The links to the German forum post were very helpful. :)

Thanks for your interest and help.

Terry
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

Thanks to all who responded above!

Here is what I wanted to accomplish:
1) Open the default (or select) a printer.
2) Print one to many pages in portrait mode.
3) Switch to landscape mode and continue printing.
4) Switch back to portrait mode and continue printing.
5) Switch paper source and continue printing.
6) Return to original paper source and continue printing.

The following code is a scaled down version of the results. Unfotunately,
it uses the Windows API to accomplish the above. I say unfortunate,
because it will require thousands of code lines to change in my project.

Code: Select all

; Author: Andreas  from German Forum
; Date: 04 Dec, 2002
; Brought to my attention by Shardik
; Modified 08 Aug, 2006 by Terry Hough 

Procedure RoundToInteger(Tempvalue.f)
  Rounded.l = TempValue + 0.05
  ProcedureReturn Rounded
EndProcedure

; Find the default printer name
STDPrinterName$ = Space(260) 
GetPrivateProfileString_("WINDOWS","DEVICE","", @STDPrintername$, 260, "Win.Ini") 
STDPrintername$ = StringField(STDPrintername$, 1,",") 
PrinterHandle.l = 0 
OpenPrinter_(StdPrintername$,@PrinterHandle.l,0) 
;MessageRequester("",Str(PrinterHandle),#MB_ICONINFORMATION) 

Dim DevInp.DEVMODE(0) 
Dim DevOut.DEVMODE(0) 
DocumentProperties_(0,Printerhandle,StdPrintername$,DevInp(0),DevOut(0),#DM_OUT_BUFFER|#DM_IN_BUFFER) 
Global HDPI.l = GetDeviceCaps_(hDC,#LOGPIXELSX) ; Get devices' horizontal dots per inch
Global VDPI.l = GetDeviceCaps_(hDC,#LOGPIXELSY) ; Get devices' vertical dots per inch
ClosePrinter_(PrinterHandle) 

; Show the current paper orientation --------------------------
; Select DevInp\dmOrientation 
;   Case #DMORIENT_PORTRAIT
;     Msg.s = "Portrait" 
;   Case #DMORIENT_LANDSCAPE
;     Msg.s = "Landscape"
; EndSelect     
; MessageRequester("Print Orientation",Msg,#MB_ICONINFORMATION)
; -------------------------------------------------------------

; Modify one copy of the DEVMODE to desired settings
DevInp(0)\dmOrientation   = #DMORIENT_LANDSCAPE  ; Set to Landscape 
DevInp(0)\dmDefaultsource = #DMBIN_LOWER         ; Set to Lower Tray
; Open a printer with the original (current) DEVMODE
PrinterDC.l = CreateDC_("WINSPOOL",StdPrintername$,0,@DevOut(0)) 

; Set up a document information structure
DocInf.DOCINFO 
DocInf\cbSize = SizeOf(DOCINFO) 
DocInf\lpszDocName = @"Printer Orientation Test" 
DocInf\lpszOutput = #Null 

; Load a couple of fonts for later use.
LoadFont(1,"ARIAL", RoundToInteger((( 8*10)-20)/720*VDPI)) ; VDPI of printer
LoadFont(2,"ARIAL", RoundToInteger(((12*10)-30)/720*VDPI),#PB_Font_Bold)

; Start the printing 
If StartDoc_(PrinterDC,@DocInf) > 0 
  If StartPage_(PrinterDC) > 0 
    TextOut_(PrinterDC,60,70,"This page should be Portrait",28)
    EndPage_(PrinterDC)
  EndIf  
  If ResetDC_(PrinterDC,@DevInp(0)) = PrinterDC
    ;MessageRequester("Debug","ResetDC_ succeeded.",0)
  Else
    MessageRequester("Debug","ResetDC_ failed.",0)
  EndIf   
  If StartPage_(PrinterDC) > 0 
    TextOut_(PrinterDC,60,70,"This page should be Landscape",29) 
    EndPage_(PrinterDC)
  EndIf   
  If ResetDC_(PrinterDC,@DevOut(0)) = PrinterDC
  Else
    MessageRequester("Debug","ResetDC_ failed.",0)
  EndIf   
  If StartPage_(PrinterDC) > 0 
    SelectObject_(PrinterDC, FontID(1)) ; Select a font for TextOut_ use
    ;SetTextColor_(PrinterDC, $0000000) ; Only if you want to change text color
    TextOut_(PrinterDC,60,70,"Final page in Portrait",22)
    SelectObject_(PrinterDC, FontID(2)) ; Select a font for TextOut_ use
    TextOut_(PrinterDC,60,240,"Second font in Portrait",23)
    EndPage_(PrinterDC)
  EndIf  
  EndDoc_(PrinterDC) 
EndIf
DeleteDC_(PrinterDC)
End
NOTE: This code was tested on a Brother laser printer with two
input paper trays and duplex capability, so it may need some modification
to run on your printer. (this code does not illustrate duplexing)

QUESTION: Does anyone know how to obtain the
DocumentProperties of the printer selected by the PB commands
PrintRequester() or DefaultPrinter()? Or how to modify those document
properties similar to the code above? That would save me many hours.

Terry
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Forget the pb requester..
It's way to limited + you'll need more options over and over not being supported.

The example above is good.

(Besides some objects not being deselected)
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Tip, write wrapper functions the next time, then you can swap to custom code more easily.
but then, who cares, using plain API is the best anyway.
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

Edwin Knoppert wrote:The example above is good.

(Besides some objects not being deselected)
Thanks, Edwin.

I am not an API expert, more of a novice. So, tell me what I have
overlooked, please.
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

Terry,
thank you for posting your solution. I am glad that you found a solution for your printing problems.
The links to the German forum post were very helpful. :)

Thanks for your interest and help.
I owe you very much for your source code (especially the FTP File Exchanger from 05/20/2003 and several other programs. I learned a lot from it for my own FTP client Trex-FTP which transfers data between a PC and a huge IBM mainframe (T-rex). Especially the use of Win-API routines and your animation routines were implemented by me and make this program very fast and user friendly. Unfortunately this is no freeware because it was part of my job as a z/OS systems programmer and I was paid to develop this software. But of course I hope to give back some tricks and snippets of my own to the community.

I have still another (very complicated) solution for those who want to change the default settings of duplex or page orientation without displaying a print dialog. These settings remain intact even if you reboot your computer.

I developped this solution because I needed a possibility to print hundreds of PDF documents from within one application without the need to manually start the Acrobat reader and to load and print each document separately. The trick is to use the rather old Acrobat reader 4, which was the last version with (undocumented) switches to control it with batch commands for document name, printer port etc (via RunProgram()). Because you have no influence on the printer driver which is controlled by the Acrobat reader, you have no possibility to change the Acrobat reader's printer settings. Therefore I developped the following solution which changes the printer settings of a single printer permanently (not only for one single printout) until you change the setting again programmatically or manually via the print requester.

Here is my rather long example:

Code: Select all

;=============================================================================
;                Change global default settings for a printer
;
; Source code example from Microsoft in VisualBASIC for Word:
; "HOWTO: Set Duplex Printing for Word Automation"
; http://support.microsoft.com/kb/230743/en-us
;=============================================================================

Enumeration
  #WindowPrinterDefaultSettings
EndEnumeration

Enumeration
  #ComboPrinterNames
  #FrameDuplex
  #OptionHorizontal
  #OptionVertical
  #FrameSimplexDuplex
  #OptionSimplex
  #OptionDuplex
  #FrameOrientation
  #OptionPortrait
  #OptionLandscape
  #ButtonChange
  #ButtonCancel
EndEnumeration

DuplexMode.W
NewDuplexState.W
NewPageOrientation.W
NumInstalledPrinters.W
OldDuplexState.W
OldPageOrientation.W
PageOrientation.W
WindowEvent.L

NewList PrinterName.S()

Declare.L ChangePrinterDefaultSettings(PrinterName.S)
Declare.W GetInstalledPrinters()

NumInstalledPrinters = GetInstalledPrinters()

If NumInstalledPrinters = 0
  MessageRequester("Error", "Sorry, no installed printers found!", #MB_ICONERROR)
  End
EndIf

OpenWindow(#WindowPrinterDefaultSettings, 516, 412, 272, 347, "Change Printer Default Settings", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(#WindowPrinterDefaultSettings))
ComboBoxGadget(#ComboPrinterNames, 50, 15, 170, 70)
Frame3DGadget(#FrameDuplex, 50, 212, 177, 63, "")
OptionGadget(#OptionHorizontal, 62, 224, 159, 24, "Short Edge")
OptionGadget(#OptionVertical, 62, 248, 159, 24, "Long Edge (Book format)")
ButtonGadget(#ButtonChange, 40, 306, 72, 24, "Change")
ButtonGadget(#ButtonCancel, 156, 306, 72, 24, "Cancel")
Frame3DGadget(#FrameSimplexDuplex, 17, 148, 236, 138, "Simplex or Duplex Print")
OptionGadget(#OptionSimplex, 32, 170, 210, 24, "Print only on one side of page (Simplex)")
OptionGadget(#OptionDuplex, 32, 194, 210, 24, "Print on both sides of page (Duplex)")
Frame3DGadget(#FrameOrientation, 80, 50, 104, 76, "Page Orientation")
OptionGadget(#OptionPortrait, 92, 70, 80, 20, "Portrait")
OptionGadget(#OptionLandscape, 92, 94, 80, 20, "Landscape")

PageOrientation = #DMORIENT_PORTRAIT
SetGadgetState(#OptionPortrait, #True)

DuplexMode = #DMDUP_SIMPLEX
SetGadgetState(#OptionSimplex, #True)
DisableGadget(#FrameDuplex, #True)
DisableGadget(#OptionHorizontal, #True)
DisableGadget(#OptionVertical, #True)

ForEach PrinterName()
  AddGadgetItem(#ComboPrinterNames, -1, PrinterName())
Next

SetGadgetState(#ComboPrinterNames, 0)

Repeat
  WindowEvent = WaitWindowEvent()

  If WindowEvent = #PB_Event_Gadget
    Select EventGadget()
      Case #OptionPortrait
        PageOrientation = #DMORIENT_PORTRAIT
      Case #OptionLandscape
        PageOrientation = #DMORIENT_LANDSCAPE
      Case #OptionSimplex
        DisableGadget(#FrameDuplex, #True)
        DisableGadget(#OptionHorizontal, #True)
        DisableGadget(#OptionVertical, #True)
      Case #OptionDuplex
        DisableGadget(#FrameDuplex, #False)
        DisableGadget(#OptionHorizontal, #False)
        DisableGadget(#OptionVertical, #False)
        SetGadgetState(#OptionVertical, #True)
      Case #ButtonChange
        If GetGadgetState(#OptionSimplex) = #True
          DuplexMode = #DMDUP_SIMPLEX
        Else
          If GetGadgetState(#OptionHorizontal) = #True
            DuplexMode = #DMDUP_HORIZONTAL
          Else
            DuplexMode = #DMDUP_VERTICAL
          EndIf
        EndIf

        If ChangePrinterDefaultSettings(GetGadgetText(#ComboPrinterNames)) = #True
          MessageRequester("Printer Settings", "Printer: " + GetGadgetText(#ComboPrinterNames) + #CR$ + #CR$ + "Old Page Orientation: " + Str(OldPageOrientation) + #CR$ + "New Page Orientation: " + Str(NewPageOrientation) + #CR$ + "Old Duplex Setting: " + Str(OldDuplexState) + #CR$ + "New Duplex Setting: " + Str(NewDuplexState))
        EndIf
        Break
      Case #ButtonCancel
        Break
    EndSelect
  EndIf
Until WindowEvent = #PB_Event_CloseWindow

End


Procedure.L ChangePrinterDefaultSettings(PrinterName.S)
  Shared DuplexMode.W
  Shared NewDuplexState.W
  Shared NewPageOrientation.W
  Shared OldDuplexState.W
  Shared OldPageOrientation.W
  Shared PageOrientation.W
  Shared PrinterName.S()

  BufferSize.L
  BytesRetrieved.L
  *DEVMODEBuffer.DEVMODE
  *DEVMODEBufferCopy.DEVMODE
  DOCINFOStructure.DOCINFO
  ErrorMsg.S
  ModeFlag.L
  PrintText.S
  PRINTER_DEFAULTSStructure.PRINTER_DEFAULTS
  *PRINTER_INFO_2Buffer.PRINTER_INFO_2
  *PRINTER_INFO_2BufferCopy.PRINTER_INFO_2
  PrinterHandle.L
  Result.L

  ; ----- Get printer handle
  
  PRINTER_DEFAULTSStructure\DesiredAccess = #STANDARD_RIGHTS_REQUIRED | #PRINTER_ACCESS_ADMINISTER | #PRINTER_ACCESS_USE

  Result = OpenPrinter_(@PrinterName, @PrinterHandle, @PRINTER_DEFAULTSStructure)
  
  
  If Result = #False Or PrinterHandle = 0
    ErrorMsg = "Could not obtain printer handle!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for DEVMODE structure

  ModeFlag = 0

  BufferSize = DocumentProperties_(0, PrinterHandle, @PrinterName, 0, 0, ModeFlag)
  
  If BufferSize < 0 Or ModeFlag <> 0
    ErrorMsg = "The size of the DEVMODE structure couldn't be obtained!"
    Goto CleanUp
    End
  EndIf

  ; ----- Get memory buffer for DEVMODE structure
  
  *DEVMODEBuffer = AllocateMemory(BufferSize)
  
  If *DEVMODEBuffer = 0
    ErrorMsg = "A memory request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf
  
  ; ----- Get memory buffer for copy of DEVMODE structure
  
  *DEVMODEBufferCopy = AllocateMemory(BufferSize)
  
  If *DEVMODEBufferCopy = 0
    ErrorMsg = "A memory request for a copy of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate DEVMODE structure
  
  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, 0, #DM_OUT_BUFFER)
  
  If Result < 0
    ErrorMsg = "The request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Copy DEVMODE structure

  CopyMemory(*DEVMODEBuffer, *DEVMODEBufferCopy, BufferSize)

  ; ----- Does driver allow to activate duplex setting?

  If *DEVMODEBufferCopy\dmFields & #DM_DUPLEX <> #DM_DUPLEX
    ErrorMsg = "The duplex setting cannot be activated for this printer!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Change page orientation in copy of DEVMODE structure

  OldPageOrientation = *DEVMODEBufferCopy\dmOrientation
  *DEVMODEBufferCopy\dmOrientation = PageOrientation

  ; ----- Change duplex setting in copy of DEVMODE structure

  OldDuplexState = *DEVMODEBufferCopy\dmDuplex
  *DEVMODEBufferCopy\dmDuplex = DuplexMode

  ; ----- Specify which parameters are to be changed

  *DEVMODEBufferCopy\dmFields = #DM_ORIENTATION | #DM_DUPLEX

  ; ----- Overwrite DEVMODE structure with modified copy

  CopyMemory(*DEVMODEBufferCopy, *DEVMODEBuffer, BufferSize)

  ; ----- Hand over the modified DEVMODE structure

  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, *DEVMODEBuffer, #DM_IN_BUFFER | #DM_OUT_BUFFER)

  If Result <> #IDOK
    ErrorMsg = "The hand over of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for PRINTER_INFO_2-Struktur

  BufferSize = 0

  GetPrinter_(PrinterHandle, 2, 0, 0, @BufferSize)

  If BufferSize = 0
    ErrorMsg = "The size of the PRINTER_INFO_2 structure couldn't be obtained!"
    Result = #False
    Goto CleanUp
  EndIf

  BufferSize = BufferSize + 100

  ; ----- Get memory buffer for PRINTER_INFO_2 structure

  *PRINTER_INFO_2Buffer = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2Buffer = 0
    ErrorMsg = "A memory request for the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get memory buffer for copy of PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2BufferCopy = 0
    ErrorMsg = "The memory request for a copy of the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate PRINTER_INFO_2 structure

  Result = GetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, BufferSize, @BytesRetrieved)

  If Result = 0
    ErrorMsg = "The evaluation of printer settings failed!"
    Goto CleanUp
  EndIf

  ; ----- Copy PRINTER_INFO_2 structure

  CopyMemory(*PRINTER_INFO_2Buffer, *PRINTER_INFO_2BufferCopy, BufferSize)

  ; ----- Change PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy\pDevMode = *DEVMODEBuffer
  *PRINTER_INFO_2BufferCopy\pSecurityDescriptor = 0

  ; ----- Overwrite PRINTER_INFO_2 structure with modified copy

  CopyMemory(*PRINTER_INFO_2BufferCopy, *PRINTER_INFO_2Buffer, BufferSize)

  Result = SetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, 0)

  If Result = 0
    ErrorMsg = "The change of the printer settings failed!"
  Else
    Result = #True
  EndIf

  NewPageOrientation = *DEVMODEBuffer\dmOrientation
  NewDuplexState = *DEVMODEBuffer\dmDuplex

; ----- Free printer handle and memory buffers

CleanUp:
  If PrinterHandle <> 0
    ClosePrinter_(PrinterHandle)
  EndIf

  If *DEVMODEBuffer <> 0
    FreeMemory(*DEVMODEBuffer)
  EndIf

  If *DEVMODEBufferCopy <> 0
    FreeMemory(*DEVMODEBufferCopy)
  EndIf

  If *PRINTER_INFO_2Buffer <> 0
    FreeMemory(*PRINTER_INFO_2Buffer)
  EndIf

  If *PRINTER_INFO_2BufferCopy <> 0
    FreeMemory(*PRINTER_INFO_2BufferCopy)
  EndIf

  If Result = #False
    MessageRequester("Fehler", ErrorMsg, #MB_ICONERROR)
  EndIf

  ProcedureReturn Result
EndProcedure


Procedure.W GetInstalledPrinters()
  Shared PrinterName.S()

  BufferSize.L
  PrinterName.S
  TempString.S
  TempStringLength.W
  TempPrinter.S

  ClearList(PrinterName())

  BufferSize = 8192
  TempPrinter = Space(1024)

  *Buffer = GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, BufferSize) 

  If GetProfileString_("Devices", 0, "", *Buffer, BufferSize)
    TempString = PeekS(*Buffer)
    TempStringLength = Len(TempString)

    While TempString <> ""
      GetPrivateProfileString_("Devices", TempString, "", TempPrinter, 1024, "Win.Ini")
      AddElement(PrinterName())
      PrinterName() = TempString
      TempString = PeekS(*Buffer + TempStringLength + 1)
      TempStringLength = TempStringLength + Len(TempString) + 1
    Wend
  EndIf

  GlobalFree_(*Buffer)

  ProcedureReturn CountList(PrinterName())
EndProcedure
I hope someone will find some use in it. I have tested this example under WinNT SP6, Win2K Server and WinXP SP2. I had a very hard time until it was running :wink: and there appear still to be some quirks in it, especially the duplex switching on 2 Hitachi DDP 70 still doesn't work correctly although the page orientation switching does. Other tested printers from HP, Lexmark and Brother worked...

Added: Works also with Win98SE :wink:
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Printer: How to get the device name

Post by IdeasVacuum »

Hi Shardik

Stumbled across your code for presetting a printer - works really well (minor tweaks to suit PB4.61). How do I make it work when compiling as Unicode?

Code: Select all

;=============================================================================
;                Change global default settings for a printer
;
; Source code example from Microsoft in VisualBASIC for Word:
; "HOWTO: Set Duplex Printing for Word Automation"
; http://support.microsoft.com/kb/230743/en-us
;=============================================================================

Enumeration
  #WindowPrinterDefaultSettings
EndEnumeration

Enumeration
  #ComboPrinterNames
  #FrameDuplex
  #OptionHorizontal
  #OptionVertical
  #FrameSimplexDuplex
  #OptionSimplex
  #OptionDuplex
  #FrameOrientation
  #OptionPortrait
  #OptionLandscape
  #ButtonChange
  #ButtonCancel
EndEnumeration

DuplexMode.W
NewDuplexState.W
NewPageOrientation.W
NumInstalledPrinters.W
OldDuplexState.W
OldPageOrientation.W
PageOrientation.W
WindowEvent.L

NewList PrinterName.S()

Declare.L ChangePrinterDefaultSettings(PrinterName.S)
Declare.W GetInstalledPrinters()

NumInstalledPrinters = GetInstalledPrinters()

If NumInstalledPrinters = 0
  MessageRequester("Error", "Sorry, no installed printers found!", #MB_ICONERROR)
  End
EndIf

OpenWindow(#WindowPrinterDefaultSettings, 516, 412, 272, 347, "Change Printer Default Settings", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)

ComboBoxGadget(#ComboPrinterNames, 10, 15, 250, 20)
Frame3DGadget(#FrameDuplex, 50, 212, 177, 63, "")
OptionGadget(#OptionHorizontal, 62, 224, 159, 24, "Short Edge")
OptionGadget(#OptionVertical, 62, 248, 159, 24, "Long Edge (Book format)")
ButtonGadget(#ButtonChange, 40, 306, 72, 24, "Change")
ButtonGadget(#ButtonCancel, 156, 306, 72, 24, "Cancel")
Frame3DGadget(#FrameSimplexDuplex, 17, 148, 236, 138, "Simplex or Duplex Print")
OptionGadget(#OptionSimplex, 32, 170, 210, 24, "Print only on one side of page (Simplex)")
OptionGadget(#OptionDuplex, 32, 194, 210, 24, "Print on both sides of page (Duplex)")
Frame3DGadget(#FrameOrientation, 80, 50, 104, 76, "Page Orientation")
OptionGadget(#OptionPortrait, 92, 70, 80, 20, "Portrait")
OptionGadget(#OptionLandscape, 92, 94, 80, 20, "Landscape")

PageOrientation = #DMORIENT_PORTRAIT
SetGadgetState(#OptionPortrait, #True)

DuplexMode = #DMDUP_SIMPLEX
SetGadgetState(#OptionSimplex, #True)
DisableGadget(#FrameDuplex, #True)
DisableGadget(#OptionHorizontal, #True)
DisableGadget(#OptionVertical, #True)

ForEach PrinterName()
  AddGadgetItem(#ComboPrinterNames, -1, PrinterName())
Next

SetGadgetState(#ComboPrinterNames, 0)

Repeat
  WindowEvent = WaitWindowEvent()

  If WindowEvent = #PB_Event_Gadget
    Select EventGadget()
      Case #OptionPortrait
        PageOrientation = #DMORIENT_PORTRAIT
      Case #OptionLandscape
        PageOrientation = #DMORIENT_LANDSCAPE
      Case #OptionSimplex
        DisableGadget(#FrameDuplex, #True)
        DisableGadget(#OptionHorizontal, #True)
        DisableGadget(#OptionVertical, #True)
      Case #OptionDuplex
        DisableGadget(#FrameDuplex, #False)
        DisableGadget(#OptionHorizontal, #False)
        DisableGadget(#OptionVertical, #False)
        SetGadgetState(#OptionVertical, #True)
      Case #ButtonChange
        If GetGadgetState(#OptionSimplex) = #True
          DuplexMode = #DMDUP_SIMPLEX
        Else
          If GetGadgetState(#OptionHorizontal) = #True
            DuplexMode = #DMDUP_HORIZONTAL
          Else
            DuplexMode = #DMDUP_VERTICAL
          EndIf
        EndIf

        If ChangePrinterDefaultSettings(GetGadgetText(#ComboPrinterNames)) = #True
          ;MessageRequester("Printer Settings", "Printer: " + GetGadgetText(#ComboPrinterNames) + #CR$ + #CR$ + "Old Page Orientation: " + Str(OldPageOrientation) + #CR$ + "New Page Orientation: " + Str(NewPageOrientation) + #CR$ + "Old Duplex Setting: " + Str(OldDuplexState) + #CR$ + "New Duplex Setting: " + Str(NewDuplexState))
        EndIf
        Break
      Case #ButtonCancel
        Break
    EndSelect
  EndIf
Until WindowEvent = #PB_Event_CloseWindow

End


Procedure.L ChangePrinterDefaultSettings(PrinterName.S)
;------------------------------------------------------
  Shared DuplexMode.W
  Shared NewDuplexState.W
  Shared NewPageOrientation.W
  Shared OldDuplexState.W
  Shared OldPageOrientation.W
  Shared PageOrientation.W
  Shared PrinterName.S()

  BufferSize.L
  BytesRetrieved.L
  *DEVMODEBuffer.DEVMODE
  *DEVMODEBufferCopy.DEVMODE
  DOCINFOStructure.DOCINFO
  ErrorMsg.S
  ModeFlag.L
  PrintText.S
  PRINTER_DEFAULTSStructure.PRINTER_DEFAULTS
  *PRINTER_INFO_2Buffer.PRINTER_INFO_2
  *PRINTER_INFO_2BufferCopy.PRINTER_INFO_2
  PrinterHandle.L
  Result.L

  ; ----- Get printer handle
 
  PRINTER_DEFAULTSStructure\DesiredAccess = #STANDARD_RIGHTS_REQUIRED | #PRINTER_ACCESS_ADMINISTER | #PRINTER_ACCESS_USE

  Result = OpenPrinter_(@PrinterName, @PrinterHandle, @PRINTER_DEFAULTSStructure)
 
 
  If Result = #False Or PrinterHandle = 0
    ErrorMsg = "Could not obtain printer handle!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for DEVMODE structure

  ModeFlag = 0

  BufferSize = DocumentProperties_(0, PrinterHandle, @PrinterName, 0, 0, ModeFlag)
 
  If BufferSize < 0 Or ModeFlag <> 0
    ErrorMsg = "The size of the DEVMODE structure couldn't be obtained!"
    Goto CleanUp
    End
  EndIf

  ; ----- Get memory buffer for DEVMODE structure
 
  *DEVMODEBuffer = AllocateMemory(BufferSize)
 
  If *DEVMODEBuffer = 0
    ErrorMsg = "A memory request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf
 
  ; ----- Get memory buffer for copy of DEVMODE structure
 
  *DEVMODEBufferCopy = AllocateMemory(BufferSize)
 
  If *DEVMODEBufferCopy = 0
    ErrorMsg = "A memory request for a copy of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate DEVMODE structure
 
  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, 0, #DM_OUT_BUFFER)
 
  If Result < 0
    ErrorMsg = "The request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Copy DEVMODE structure

  CopyMemory(*DEVMODEBuffer, *DEVMODEBufferCopy, BufferSize)

  ; ----- Does driver allow to activate duplex setting?

  If *DEVMODEBufferCopy\dmFields & #DM_DUPLEX <> #DM_DUPLEX
    ErrorMsg = "The duplex setting cannot be activated for this printer!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Change page orientation in copy of DEVMODE structure

  OldPageOrientation = *DEVMODEBufferCopy\dmOrientation
  *DEVMODEBufferCopy\dmOrientation = PageOrientation

  ; ----- Change duplex setting in copy of DEVMODE structure

  OldDuplexState = *DEVMODEBufferCopy\dmDuplex
  *DEVMODEBufferCopy\dmDuplex = DuplexMode

  ; ----- Specify which parameters are to be changed

  *DEVMODEBufferCopy\dmFields = #DM_ORIENTATION | #DM_DUPLEX

  ; ----- Overwrite DEVMODE structure with modified copy

  CopyMemory(*DEVMODEBufferCopy, *DEVMODEBuffer, BufferSize)

  ; ----- Hand over the modified DEVMODE structure

  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, *DEVMODEBuffer, #DM_IN_BUFFER | #DM_OUT_BUFFER)

  If Result <> #IDOK
    ErrorMsg = "The hand over of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for PRINTER_INFO_2-Struktur

  BufferSize = 0

  GetPrinter_(PrinterHandle, 2, 0, 0, @BufferSize)

  If BufferSize = 0
    ErrorMsg = "The size of the PRINTER_INFO_2 structure couldn't be obtained!"
    Result = #False
    Goto CleanUp
  EndIf

  BufferSize = BufferSize + 100

  ; ----- Get memory buffer for PRINTER_INFO_2 structure

  *PRINTER_INFO_2Buffer = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2Buffer = 0
    ErrorMsg = "A memory request for the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get memory buffer for copy of PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2BufferCopy = 0
    ErrorMsg = "The memory request for a copy of the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate PRINTER_INFO_2 structure

  Result = GetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, BufferSize, @BytesRetrieved)

  If Result = 0
    ErrorMsg = "The evaluation of printer settings failed!"
    Goto CleanUp
  EndIf

  ; ----- Copy PRINTER_INFO_2 structure

  CopyMemory(*PRINTER_INFO_2Buffer, *PRINTER_INFO_2BufferCopy, BufferSize)

  ; ----- Change PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy\pDevMode = *DEVMODEBuffer
  *PRINTER_INFO_2BufferCopy\pSecurityDescriptor = 0

  ; ----- Overwrite PRINTER_INFO_2 structure with modified copy

  CopyMemory(*PRINTER_INFO_2BufferCopy, *PRINTER_INFO_2Buffer, BufferSize)

  Result = SetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, 0)

  If Result = 0
    ErrorMsg = "The change of the printer settings failed!"
  Else
    Result = #True
  EndIf

  NewPageOrientation = *DEVMODEBuffer\dmOrientation
  NewDuplexState = *DEVMODEBuffer\dmDuplex

; ----- Free printer handle and memory buffers

CleanUp:
  If PrinterHandle <> 0
    ClosePrinter_(PrinterHandle)
  EndIf

  If *DEVMODEBuffer <> 0
    FreeMemory(*DEVMODEBuffer)
  EndIf

  If *DEVMODEBufferCopy <> 0
    FreeMemory(*DEVMODEBufferCopy)
  EndIf

  If *PRINTER_INFO_2Buffer <> 0
    FreeMemory(*PRINTER_INFO_2Buffer)
  EndIf

  If *PRINTER_INFO_2BufferCopy <> 0
    FreeMemory(*PRINTER_INFO_2BufferCopy)
  EndIf

  If Result = #False
    MessageRequester("Fehler", ErrorMsg, #MB_ICONERROR)
  EndIf

  ProcedureReturn Result
EndProcedure


Procedure.W GetInstalledPrinters()
  Shared PrinterName()

  BufferSize.L
  PrinterName.S
  TempString.S
  TempStringLength.W
  TempPrinter.S

  ClearList(PrinterName())

  BufferSize = 8192
  TempPrinter = Space(1024)

  *Buffer = GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, BufferSize)

  If GetProfileString_("Devices", 0, "", *Buffer, BufferSize)
    TempString = PeekS(*Buffer)
    TempStringLength = Len(TempString)

    While TempString <> ""
      GetPrivateProfileString_("Devices", TempString, "", TempPrinter, 1024, "Win.Ini")
      AddElement(PrinterName())
      PrinterName() = TempString
      TempString = PeekS(*Buffer + TempStringLength + 1)
      TempStringLength = TempStringLength + Len(TempString) + 1
    Wend
  EndIf

  GlobalFree_(*Buffer)

  ProcedureReturn  ListSize(PrinterName()) 

EndProcedure
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Printer: How to get the device name

Post by IdeasVacuum »

Hello Edwin. Tried your code below and it works perfectly, but only if the app is compiled in ASCII mode. In Unicode mode, an English printer name such as "EPSON Stylus Photo R220 Series" is returned in Chinese characters. Tried playing with PeekS Flag #PB_Ascii but that doesn't work - it seems that the DEVNAMES structure does work with Unicode, but how to use it?
Edwin Knoppert wrote:I rewrote it and shows the printername:

Code: Select all


PrintDlg.PRINTDLG 
PrintDlg\hDevMode = 0 
PrintDlg\hDevNames = 0
PrintDlg\lStructSize = SizeOf(PRINTDLG) 
PrintDlg\Flags = #PD_ALLPAGES 

If PrintDlg_(PrintDlg) <> #FALSE 
    *DEVNAMES.DEVNAMES = GlobalLock_(PrintDlg\hDevNames) 
    MessageRequester("Printer Device Name", PeekS(*DEVNAMES + *DEVNAMES\wDeviceOffset), #MB_ICONINFORMATION) 
    GlobalUnlock_(PrintDlg\hDevNames)
EndIf 

; Only at the end of the app
GlobalFree_(PrintDlg\hDevNames)
Of course it lacks testing for valid memory and such..
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Printer: How to get the device name

Post by Shardik »

IdeasVacuum wrote:Stumbled across your code for presetting a printer - works really well (minor tweaks to suit PB4.61). How do I make it work when compiling as Unicode?
In order to work in ASCII and Unicode mode you have to change Len() to StringByteLenght() and the fixed count of 1 for the string terminator to SizeOf(Character). So this code

Code: Select all

      TempString = PeekS(*Buffer + TempStringLength + 1)
      TempStringLength = TempStringLength + Len(TempString) + 1
has to be changed to

Code: Select all

      TempString = PeekS(*Buffer + TempStringLength + SizeOf(Character))
      TempStringLength = TempStringLength + StringByteLength(TempString) + SizeOf(Character)
For your conveniance I have adapted the whole code example for PB 4.61:

Code: Select all

;=============================================================================
;                Change global default settings for a printer
;
; Source code example from Microsoft in VisualBASIC for Word:
; "HOWTO: Set Duplex Printing for Word Automation"
; http://support.microsoft.com/kb/230743/en-us
;=============================================================================

EnableExplicit

Enumeration
  #WindowPrinterDefaultSettings
EndEnumeration

Enumeration
  #ComboPrinterNames
  #FrameDuplex
  #OptionHorizontal
  #OptionVertical
  #FrameSimplexDuplex
  #OptionSimplex
  #OptionDuplex
  #FrameOrientation
  #OptionPortrait
  #OptionLandscape
  #ButtonChange
  #ButtonCancel
EndEnumeration

Define DuplexMode.I
Define NewDuplexState.I
Define NewPageOrientation.I
Define NumInstalledPrinters.I
Define OldDuplexState.I
Define OldPageOrientation.I
Define PageOrientation.I
Define WindowEvent.I

NewList PrinterName.S()

Declare.I ChangePrinterDefaultSettings(PrinterName.S)
Declare.I GetInstalledPrinters()

NumInstalledPrinters = GetInstalledPrinters()

If NumInstalledPrinters = 0
  MessageRequester("Error", "Sorry, no installed printers found!", #MB_ICONERROR)
  End
EndIf

OpenWindow(#WindowPrinterDefaultSettings, 516, 412, 272, 347, "Change Printer Default Settings", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
ComboBoxGadget(#ComboPrinterNames, 50, 15, 170, 20)
Frame3DGadget(#FrameDuplex, 50, 212, 177, 63, "")
OptionGadget(#OptionHorizontal, 62, 224, 159, 24, "Short Edge")
OptionGadget(#OptionVertical, 62, 248, 159, 24, "Long Edge (Book format)")
ButtonGadget(#ButtonChange, 40, 306, 72, 24, "Change")
ButtonGadget(#ButtonCancel, 156, 306, 72, 24, "Cancel")
Frame3DGadget(#FrameSimplexDuplex, 17, 148, 236, 138, "Simplex or Duplex Print")
OptionGadget(#OptionSimplex, 32, 170, 210, 24, "Print only on one side of page (Simplex)")
OptionGadget(#OptionDuplex, 32, 194, 210, 24, "Print on both sides of page (Duplex)")
Frame3DGadget(#FrameOrientation, 80, 50, 104, 76, "Page Orientation")
OptionGadget(#OptionPortrait, 92, 70, 80, 20, "Portrait")
OptionGadget(#OptionLandscape, 92, 94, 80, 20, "Landscape")

PageOrientation = #DMORIENT_PORTRAIT
SetGadgetState(#OptionPortrait, #True)

DuplexMode = #DMDUP_SIMPLEX
SetGadgetState(#OptionSimplex, #True)
DisableGadget(#FrameDuplex, #True)
DisableGadget(#OptionHorizontal, #True)
DisableGadget(#OptionVertical, #True)

ForEach PrinterName()
  AddGadgetItem(#ComboPrinterNames, -1, PrinterName())
Next

SetGadgetState(#ComboPrinterNames, 0)

Repeat
  WindowEvent = WaitWindowEvent()

  If WindowEvent = #PB_Event_Gadget
    Select EventGadget()
      Case #OptionPortrait
        PageOrientation = #DMORIENT_PORTRAIT
      Case #OptionLandscape
        PageOrientation = #DMORIENT_LANDSCAPE
      Case #OptionSimplex
        DisableGadget(#FrameDuplex, #True)
        DisableGadget(#OptionHorizontal, #True)
        DisableGadget(#OptionVertical, #True)
      Case #OptionDuplex
        DisableGadget(#FrameDuplex, #False)
        DisableGadget(#OptionHorizontal, #False)
        DisableGadget(#OptionVertical, #False)
        SetGadgetState(#OptionVertical, #True)
      Case #ButtonChange
        If GetGadgetState(#OptionSimplex) = #True
          DuplexMode = #DMDUP_SIMPLEX
        Else
          If GetGadgetState(#OptionHorizontal) = #True
            DuplexMode = #DMDUP_HORIZONTAL
          Else
            DuplexMode = #DMDUP_VERTICAL
          EndIf
        EndIf

        If ChangePrinterDefaultSettings(GetGadgetText(#ComboPrinterNames)) = #True
          MessageRequester("Printer Settings", "Printer: " + GetGadgetText(#ComboPrinterNames) + #CR$ + #CR$ + "Old Page Orientation: " + Str(OldPageOrientation) + #CR$ + "New Page Orientation: " + Str(NewPageOrientation) + #CR$ + "Old Duplex Setting: " + Str(OldDuplexState) + #CR$ + "New Duplex Setting: " + Str(NewDuplexState))
        EndIf
        Break
      Case #ButtonCancel
        Break
    EndSelect
  EndIf
Until WindowEvent = #PB_Event_CloseWindow

End


Procedure.I ChangePrinterDefaultSettings(PrinterName.S)
  Shared DuplexMode.I
  Shared NewDuplexState.I
  Shared NewPageOrientation.I
  Shared OldDuplexState.I
  Shared OldPageOrientation.I
  Shared PageOrientation.I
  Shared PrinterName.S()

  Protected BufferSize.I
  Protected BytesRetrieved.I
  Protected *DEVMODEBuffer.DEVMODE
  Protected *DEVMODEBufferCopy.DEVMODE
  Protected DOCINFOStructure.DOCINFO
  Protected ErrorMsg.S
  Protected ModeFlag.I
  Protected PrintText.S
  Protected PRINTER_DEFAULTSStructure.PRINTER_DEFAULTS
  Protected *PRINTER_INFO_2Buffer.PRINTER_INFO_2
  Protected *PRINTER_INFO_2BufferCopy.PRINTER_INFO_2
  Protected PrinterHandle.I
  Protected Result.I

  ; ----- Get printer handle
  
  PRINTER_DEFAULTSStructure\DesiredAccess = #STANDARD_RIGHTS_REQUIRED | #PRINTER_ACCESS_ADMINISTER | #PRINTER_ACCESS_USE

  Result = OpenPrinter_(@PrinterName, @PrinterHandle, @PRINTER_DEFAULTSStructure)
  
  
  If Result = #False Or PrinterHandle = 0
    ErrorMsg = "Could not obtain printer handle!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for DEVMODE structure

  ModeFlag = 0

  BufferSize = DocumentProperties_(0, PrinterHandle, @PrinterName, 0, 0, ModeFlag)
  
  If BufferSize < 0 Or ModeFlag <> 0
    ErrorMsg = "The size of the DEVMODE structure couldn't be obtained!"
    Goto CleanUp
    End
  EndIf

  ; ----- Get memory buffer for DEVMODE structure
  
  *DEVMODEBuffer = AllocateMemory(BufferSize)
  
  If *DEVMODEBuffer = 0
    ErrorMsg = "A memory request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf
  
  ; ----- Get memory buffer for copy of DEVMODE structure
  
  *DEVMODEBufferCopy = AllocateMemory(BufferSize)
  
  If *DEVMODEBufferCopy = 0
    ErrorMsg = "A memory request for a copy of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate DEVMODE structure
  
  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, 0, #DM_OUT_BUFFER)
  
  If Result < 0
    ErrorMsg = "The request for the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Copy DEVMODE structure

  CopyMemory(*DEVMODEBuffer, *DEVMODEBufferCopy, BufferSize)

  ; ----- Does driver allow to activate duplex setting?

  If *DEVMODEBufferCopy\dmFields & #DM_DUPLEX <> #DM_DUPLEX
    ErrorMsg = "The duplex setting cannot be activated for this printer!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Change page orientation in copy of DEVMODE structure

  OldPageOrientation = *DEVMODEBufferCopy\dmOrientation
  *DEVMODEBufferCopy\dmOrientation = PageOrientation

  ; ----- Change duplex setting in copy of DEVMODE structure

  OldDuplexState = *DEVMODEBufferCopy\dmDuplex
  *DEVMODEBufferCopy\dmDuplex = DuplexMode

  ; ----- Specify which parameters are to be changed

  *DEVMODEBufferCopy\dmFields = #DM_ORIENTATION | #DM_DUPLEX

  ; ----- Overwrite DEVMODE structure with modified copy

  CopyMemory(*DEVMODEBufferCopy, *DEVMODEBuffer, BufferSize)

  ; ----- Hand over the modified DEVMODE structure

  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, *DEVMODEBuffer, #DM_IN_BUFFER | #DM_OUT_BUFFER)

  If Result <> #IDOK
    ErrorMsg = "The hand over of the DEVMODE structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get buffer size for PRINTER_INFO_2-Struktur

  BufferSize = 0

  GetPrinter_(PrinterHandle, 2, 0, 0, @BufferSize)

  If BufferSize = 0
    ErrorMsg = "The size of the PRINTER_INFO_2 structure couldn't be obtained!"
    Result = #False
    Goto CleanUp
  EndIf

  BufferSize = BufferSize + 100

  ; ----- Get memory buffer for PRINTER_INFO_2 structure

  *PRINTER_INFO_2Buffer = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2Buffer = 0
    ErrorMsg = "A memory request for the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Get memory buffer for copy of PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2BufferCopy = 0
    ErrorMsg = "The memory request for a copy of the PRINTER_INFO_2 structure failed!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Generate PRINTER_INFO_2 structure

  Result = GetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, BufferSize, @BytesRetrieved)

  If Result = 0
    ErrorMsg = "The evaluation of printer settings failed!"
    Goto CleanUp
  EndIf

  ; ----- Copy PRINTER_INFO_2 structure

  CopyMemory(*PRINTER_INFO_2Buffer, *PRINTER_INFO_2BufferCopy, BufferSize)

  ; ----- Change PRINTER_INFO_2 structure

  *PRINTER_INFO_2BufferCopy\pDevMode = *DEVMODEBuffer
  *PRINTER_INFO_2BufferCopy\pSecurityDescriptor = 0

  ; ----- Overwrite PRINTER_INFO_2 structure with modified copy

  CopyMemory(*PRINTER_INFO_2BufferCopy, *PRINTER_INFO_2Buffer, BufferSize)

  Result = SetPrinter_(PrinterHandle, 2, *PRINTER_INFO_2Buffer, 0)

  If Result = 0
    ErrorMsg = "The change of the printer settings failed!"
  Else
    Result = #True
  EndIf

  NewPageOrientation = *DEVMODEBuffer\dmOrientation
  NewDuplexState = *DEVMODEBuffer\dmDuplex

; ----- Free printer handle and memory buffers

CleanUp:
  If PrinterHandle <> 0
    ClosePrinter_(PrinterHandle)
  EndIf

  If *DEVMODEBuffer <> 0
    FreeMemory(*DEVMODEBuffer)
  EndIf

  If *DEVMODEBufferCopy <> 0
    FreeMemory(*DEVMODEBufferCopy)
  EndIf

  If *PRINTER_INFO_2Buffer <> 0
    FreeMemory(*PRINTER_INFO_2Buffer)
  EndIf

  If *PRINTER_INFO_2BufferCopy <> 0
    FreeMemory(*PRINTER_INFO_2BufferCopy)
  EndIf

  If Result = #False
    MessageRequester("Fehler", ErrorMsg, #MB_ICONERROR)
  EndIf

  ProcedureReturn Result
EndProcedure


Procedure.I GetInstalledPrinters()
  Shared PrinterName.S()

  Protected *Buffer
  Protected BufferSize.I
  Protected PrinterName.S
  Protected TempString.S
  Protected TempStringLength.I
  Protected TempPrinter.S

  ClearList(PrinterName())

  BufferSize = 8192
  TempPrinter = Space(1024)

  *Buffer = AllocateMemory(BufferSize)

  If GetProfileString_("Devices", 0, "", *Buffer, BufferSize)
    TempString = PeekS(*Buffer)
    TempStringLength = StringByteLength(TempString)

    While TempString <> ""
      GetPrivateProfileString_("Devices", TempString, "", TempPrinter, 1024, "Win.Ini")
      AddElement(PrinterName())
      PrinterName() = TempString
      TempString = PeekS(*Buffer + TempStringLength + SizeOf(Character))
      TempStringLength = TempStringLength + StringByteLength(TempString) + SizeOf(Character)
    Wend
  EndIf

  FreeMemory(*Buffer)

  ProcedureReturn ListSize(PrinterName())
EndProcedure
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Printer: How to get the device name

Post by IdeasVacuum »

Ah that's excellent Shardik, thank you. I've been working too many hours of late, what little brain I have left is totally fried. :?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Printer: How to get the device name

Post by IdeasVacuum »

Still trying to get the selected printer name (PrintDlg_()) when my app is compiled as unicode. The following works fine in ASCII mode, does not work at all if switched to unicode:

Code: Select all


iCharCnt.i = 1

CompilerIf(#PB_Compiler_Unicode = 1)

   iCharCnt = 2

CompilerEndIf

sPrinterName.s

PrintDlg.PRINTDLG
PrintDlg\lStructSize = SizeOf(PRINTDLG)
PrintDlg\hDevMode = 0
PrintDlg\hDevNames = 0
PrintDlg\Flags = #PD_ALLPAGES

If PrintDlg_(PrintDlg) <> #False

    *DEVNAMES.DEVNAMES = GlobalLock_(PrintDlg\hDevNames)

    While (i < 64) And (PeekC(*DEVNAMES + *DEVNAMES\wDeviceOffset + i) <> 0)

           sPrinterName = sPrinterName + Chr(PeekC(*DEVNAMES + *DEVNAMES\wDeviceOffset + i))

                      i = i + iCharCnt
    Wend

    Debug sPrinterName

    GlobalUnlock_(PrintDlg\hDevNames)

EndIf

GlobalFree_(PrintDlg\hDevNames)
End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Printer: How to get the device name

Post by netmaestro »

You can give this a try, it works here:

Code: Select all

Procedure.s GetDefaultPrinterName() ; netmaestro 2012
  Protected sPrinterName.s, PrintDlg.PRINTDLG, *DEVNAMES.DEVNAMES
  With PrintDlg
    \lStructSize = SizeOf(PRINTDLG)
    \Flags = #PD_RETURNDEFAULT ; This suppresses the dialog coming up
  EndWith
  PrintDlg_(PrintDlg)
  *DEVNAMES = GlobalLock_(PrintDlg\hDevNames)
  sPrinterName = PeekS(*DEVNAMES + (*DEVNAMES\wDeviceOffset * SizeOf(Character))) ; wDeviceOffset is in characters, not bytes
  GlobalUnlock_(PrintDlg\hDevNames)
  GlobalFree_(PrintDlg\hDevNames)
  ProcedureReturn sPrinterName
EndProcedure

MessageRequester("Default Printer Name:", GetDefaultPrinterName())

BERESHEIT
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Printer: How to get the device name

Post by IdeasVacuum »

That works a treat Netmaestro, thank you! 8)

To get the currently selected printer name instead of the default printer name, change:

\Flags = #PD_RETURNDEFAULT

to

\Flags = #PD_ALLPAGES (or no flags. Obviously the dialog must be displayed for the User to select the printer if the default will not be used).
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply