Seite 1 von 1

Anzahl der Druckkopien

Verfasst: 13.01.2006 10:08
von rolf
Hallo,
kennt jemand eine Möglichkeit, wie ich mit PB Systemweit (unter Windows) die Anzahl der Exemplare die ein Drucker ausgeben soll setzen kann?
Ich denke, dass dies nur über irgendwelche API-Aufrufe geht.

Gruß
Rolf

Verfasst: 26.07.2006 05:41
von Just_reading
Hab mich nie richtig damit befasst. Aber ich glaube EnumJobs_ könnte dir helfen.
MSDN birgt die Details.

Verfasst: 03.08.2006 11:49
von Shardik
Die Aufgabe, die Anzahl Kopien im Druck-Requester standardmäßig abzuändern (d.h. die Einstellung gilt nicht nur für den aktuellen Druck, sondern dauerhaft, also auch nach einem Rechner-Neustart), ist in der Tat nicht trivial und bedingt - wie vermutet - den heftigen Einsatz des WinAPI. Folgender Artikel in der Microsoft Knowledge Base bietet eine Lösung in VisualBASIC für die Änderung der Duplex-Druckeinstellung aus Word heraus, die aber abgewandelt auch zur Änderung der Anzahl Kopien oder für die Umschaltung zwischen Hoch- und Querdruck verwendet werden kann:

http://support.microsoft.com/kb/230743/en-us

Eine Umsetzung für PureBASIC:

Code: Alles auswählen

Procedure.L SetPrinterDefaultNumCopies(PrinterName.S, NumCopies.L)
  BufferSize.L
  BytesRetrieved.L
  *DEVMODEBuffer.DEVMODE
  *DEVMODEBufferCopy.DEVMODE
  ErrorMsg.S
  ModeFlag.L
  PRINTER_DEFAULTSStructure.PRINTER_DEFAULTS
  *PRINTER_INFO_2Buffer.PRINTER_INFO_2
  *PRINTER_INFO_2BufferCopy.PRINTER_INFO_2
  PrinterHandle.L
  Result.L

  ; ----- Drucker-Handle für gewünschten Drucker anfordern
  
  PRINTER_DEFAULTSStructure\DesiredAccess = #STANDARD_RIGHTS_REQUIRED | #PRINTER_ACCESS_ADMINISTER | #PRINTER_ACCESS_USE

  Result = OpenPrinter_(@PrinterName, @PrinterHandle, @PRINTER_DEFAULTSStructure)
  
  If Result = #False
    ErrorMsg = "Der Drucker " + PrinterName + " konnte nicht geöffnet werden!"
    Goto CleanUp
  EndIf
  
  If PrinterHandle = 0
    ErrorMsg = "Es konnte kein Drucker-Handle ermittelt werden!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Erforderliche Puffergröße für die DEVMODE-Struktur ermitteln

  ModeFlag = 0

  BufferSize = DocumentProperties_(0, PrinterHandle, @PrinterName, 0, 0, ModeFlag)
  
  If BufferSize < 0 Or ModeFlag <> 0
    ErrorMsg = "Die Größe der DEVMODE-Struktur konnte nicht ermittelt werden!"
    Goto CleanUp
    End
  EndIf

  ; ----- Speicherblock für die DEVMODE-Struktur anfordern
  
  *DEVMODEBuffer = AllocateMemory(BufferSize)
  
  If *DEVMODEBuffer = 0
    ErrorMsg = "Die Speicheranforderung für die DEVMODE-Struktur ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf
  
  ; ----- Speicherblock für eine Kopie der DEVMODE-Struktur anfordern
  
  *DEVMODEBufferCopy = AllocateMemory(BufferSize)
  
  If *DEVMODEBufferCopy = 0
    ErrorMsg = "Die Speicheranforderung für eine Kopie der DEVMODE-Struktur ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- DEVMODE-Struktur generieren lassen
  
  Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, 0, #DM_OUT_BUFFER)
  
  If Result < 0
    ErrorMsg = "Die Übergabe der DEVMODE-Struktur ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- DEVMODE-Struktur kopieren

  CopyMemory(*DEVMODEBuffer, *DEVMODEBufferCopy, BufferSize)

  ; ----- Prüfen ob die Duplex-Einstellung abgeändert werden kann

  If *DEVMODEBufferCopy\dmFields & #DM_COPIES <> #DM_COPIES
    ErrorMsg = "Die Einstellung der Kopien-Anzahl kann für diesen Drucker nicht geändert werden!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Duplex-Einstellung in Kopie der DEVMODE-Struktur abändern

  *DEVMODEBufferCopy\dmCopies = NumCopies

  ; ----- Angeben, welche Parameter geändert worden sind

  *DEVMODEBufferCopy\dmFields = #DM_COPIES

  ; ----- DEVMODE-Struktur mit veränderter Kopie überschreiben

  CopyMemory(*DEVMODEBufferCopy, *DEVMODEBuffer, BufferSize)

  ; ----- Veränderte DEVMODE-Struktur übergeben

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

  If Result <> #IDOK
    ErrorMsg = "Die Änderung der Kopienzahl ist auf diesem Drucker gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Erforderliche Puffergröße für PRINTER_INFO_2-Struktur ermitteln

  BufferSize = 0

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

  If BufferSize = 0
    ErrorMsg = "Die Ermittlung der Puffergröße für den Drucker ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  BufferSize = BufferSize + 100

  ; ----- Speicherblock für die PRINTER_INFO_2-Struktur anfordern

  *PRINTER_INFO_2Buffer = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2Buffer = 0
    ErrorMsg = "Die Speicheranforderung für die PRINTER_INFO_2-Struktur ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- Speicherblock für eine Kopie der PRINTER_INFO_2-Struktur anfordern

  *PRINTER_INFO_2BufferCopy = AllocateMemory(BufferSize)

  If *PRINTER_INFO_2BufferCopy = 0
    ErrorMsg = "Die Speicheranforderung für eine Kopie der PRINTER_INFO_2-Struktur ist gescheitert!"
    Result = #False
    Goto CleanUp
  EndIf

  ; ----- PRINTER_INFO_2-Struktur generieren lassen

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

  If Result = 0
    ErrorMsg = "Die Ermittlung der Drucker-Einstellungen ist gescheitert!"
    Goto CleanUp
  EndIf

  ; ----- PRINTER_INFO_2-Struktur kopieren

  CopyMemory(*PRINTER_INFO_2Buffer, *PRINTER_INFO_2BufferCopy, BufferSize)

  ; ----- PRINTER_INFO_2-Struktur abändern

  *PRINTER_INFO_2BufferCopy\pDevMode = *DEVMODEBuffer

  ; ----- PRINTER_INFO_2-Struktur mit veränderter Kopie überschreiben

  CopyMemory(*PRINTER_INFO_2BufferCopy, *PRINTER_INFO_2Buffer, BufferSize)

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

  If Result = 0
    ErrorMsg = "Die Abänderung der Drucker-Einstellungen ist gescheitert!"
  Else
    Result = #True
  EndIf

  MessageRequester("Drucker: " + PrinterName, "Neue Standard-Einstellung im Druck-Requester:" + #CR$ + "Anzahl Kopien = " + Str(*DEVMODEBuffer\dmCopies), #MB_ICONINFORMATION)

; ----- Printer-Handle und Speicherbereiche freigeben

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

; Prozedur zum Ermitteln des Default-Druckers
; http://www.purebasic.fr/english/viewtopic.php?t=11883

Procedure.S GetDefaultPrinter()
  PrinterNameBuffer.S

  PrinterNameBuffer = Space(260)

  If GetPrivateProfileString_("WINDOWS", "DEVICE", "", @PrinterNameBuffer, Len(PrinterNameBuffer), "Win.Ini")
    ProcedureReturn StringField(PrinterNameBuffer, 1, ",")
  EndIf

  MessageRequester("Fehler", "Die Ermittlung des Default-Druckers ist fehlgeschlagen!", #MB_ICONERROR)

  ProcedureReturn ""
EndProcedure

DefaultNumCopies.S
PrinterName.S

PrinterName = GetDefaultPrinter()

If PrinterName <> ""
  DefaultNumCopies = InputRequester("Drucker: " + PrinterName, "Anzahl standardmäßig zu druckender Kopien?", "")

  If DefaultNumCopies <> "" And Val(DefaultNumCopies)
    SetPrinterDefaultNumCopies(PrinterName, Val(DefaultNumCopies))
  EndIf
EndIf
Die vorgenommene Änderung gilt nur für den Default-Drucker. Soll die Anzahl Kopien für einen anderen Drucker abgeändert werden, wird entweder an die Prozedur SetPrinterDefaultNumCopies(PrinterName, NumCopies) der Name eines anderen Druckers übergeben oder es wird dem Anwender eine Liste der installierten Drucker zur Auswahl angeboten. Wie man eine Liste der installierten Drucker erstellt, hat gnozal bereits gezeigt:

http://www.purebasic.fr/english/viewtopic.php?t=11883