Hallo zusammen,
ich habe hier im Forum schon viele Anregungen, Tips und Lösungen finden können. Dafür erst mal vielen Dank.
Nun wende ich mich mit einer Frage an Euch.
Ich habe einen Drucker (Canon iR2270) mit 4 Papierkassetten.
In jeder liegen unterschiedliche Kopfbögen. Nun möchte ich aus meinem Programm je nach Selektion eines Dokumentes, dass automatisch aus der richtigen Kassette gedruckt wird ohne das der Anwender sie einstellen muß.
Wir programmiere ich diesen Aufruf? Schon mal vielen Dank für Eure Hilfe.
Drucken aus vorher festgelegter Papierkassette
- Fluid Byte
- Beiträge: 3110
- Registriert: 27.09.2006 22:06
- Wohnort: Berlin, Mitte
Geht soweit ich weiß nur über den Treiber. Mir ist keine Windows API-Funktion bekannt womit man die Ausgabefächer direkt ansprechen kann. Wird 'ne harte Nuss, ist aber eigentlich auch sinnlos. Wenn der Druckdialog kommt musst du lediglich auf "Optionen" (oder ähnlich) klicken und das Ausgabefach auswählen. Das sind zwei Klicks und gibt somit zu bedenken ob das den Aufwand wert ist. Zudem musst bei einem Wechsel des Druckermodels dich erneut durch die entsprechende API kämpfen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Diese Aussage ist nicht korrekt. Gib einmal in der PureBASIC-IDE #DMB ein und Du siehst, daß dort 16 Einträge mit #DMBIN_xxx angezeigt werden. Dies sind allesamt vordefinierte Konstanten für die Papierschacht-Auswahl. Und TerryHough hat im englischen Forum ein Code-Beispiel veröffentlicht, in dem er neben Simplex/Duplex-Druck auch zwischen zumindest 2 Papiereinzugsschächten umschaltet:Fluid Byte hat geschrieben: Geht soweit ich weiß nur über den Treiber. Mir ist keine Windows API-Funktion bekannt womit man die Ausgabefächer direkt ansprechen kann.
http://www.purebasic.fr/english/viewtop ... 10&start=8
- Fluid Byte
- Beiträge: 3110
- Registriert: 27.09.2006 22:06
- Wohnort: Berlin, Mitte
Ruhig brauner, das hab ich auch nicht behauptet. Es war lediglich eine Annahme.Shardik hat geschrieben:Diese Aussage ist nicht korrekt.

Das Problem ist das diese begrenzt sind. Wenn man 4, 5 oder sogar mehr Fächer hat wie z. B. bei einen Multidrucker (Drucker+Kopierer Combo) dann kommst du damit nicht weit. Ich muss nochmal genauer suchen aber ich glaube man kann die Anzahl der Fächer iregendwie ermitteln und den Wert dann bei dmDefaultSource der DEVMODE Struktur setzen.Shardik hat geschrieben:Gib einmal in der PureBASIC-IDE #DMB ein und Du siehst, daß dort 16 Einträge mit #DMBIN_xxx angezeigt werden.
Dies sind allesamt vordefinierte Konstanten für die Papierschacht-Auswahl.
This member can be one of the following values, or it can be a device-specific value greater than or equal to DMBIN_USE
Ich habe zuhause keinen Drucker deshalb muss ich mal versuchen den Code morgen in der Firma zu testen.Shardik hat geschrieben:Und TerryHough hat im englischen Forum ein Code-Beispiel veröffentlicht, in dem er neben Simplex/Duplex-Druck auch zwischen zumindest 2 Papiereinzugsschächten umschaltet:
http://www.purebasic.fr/english/viewtop ... 10&start=8
Windows 10 Pro, 64-Bit / Outtakes | Derek
So geht es (Ermittlung der Anzahl Einzugfächer und ihrer Namen):Fluid Byte hat geschrieben: Ich muss nochmal genauer suchen aber ich glaube man kann die Anzahl der Fächer iregendwie ermitteln
Code: Alles auswählen
EnableExplicit
#BinNameLength = 24
Define BinNameBuffer.S
Define Buffer.S
Define DefaultPrinterName.S
Define DefaultPortName.S
Define i.L
Define Info.S
Define NumBins.L
Define Result.L
BinNameBuffer = Space(20 * #BinNameLength) ; maximal 20 Papiereinzugfach-Namen passen hier hinein!
Buffer = Space(260)
; Default-Druckernamen und Drucker-Port ermitteln
GetPrivateProfileString_("WINDOWS", "DEVICE", "", @Buffer, 260, "Win.Ini")
DefaultPrinterName = StringField(Buffer, 1, ",")
DefaultPortName = StringField(Buffer, 3, ",")
; Namen der Fächer ermitteln
NumBins = DeviceCapabilities_(@DefaultPrinterName, @DefaultPortName, #DC_BINNAMES, @BinNameBuffer, 0)
Select NumBins
Case -1
Info = Info + #CR$ + "Der Aufruf der Windows-Funktion DeviceCapabilities() ist fehlgeschlagen!"
Case 0
Info = Info + #CR$ + "Der Abfrage der Papiereinzugfach-Namen wird vom Druckertreiber nicht unterstützt!"
Default
For i = 0 To NumBins - 1
Info + #CR$ + Trim(PeekS(@BinNameBuffer + i * #BinNameLength))
Next i
EndSelect
MessageRequester("Papiereinzugfach-Namen von " + DefaultPrinterName, Info, #MB_ICONINFORMATION)
>Ruhig brauner
Für den, der diese Bemerkung nicht versteht, Wikipedia hilft:

http://en.wikipedia.org/wiki/Shardik
http://en.wikipedia.org/wiki/Shardik_%28bear%29
Allerdings ist Shardik schon nicht mehr braun, sondern fast weiß und sogar noch etwas älter als ts-soft

/OT
Hier ist ein (etwas komplizierteres) Komplett-Beispiel, das alle Papiereinzugsfächer des Default-Druckers zur Auswahl anbietet, aus dem ausgewählten Fach eine Seite einzieht und die Seite mit der Bezeichnung des Faches versehen ausdruckt:
Code: Alles auswählen
EnableExplicit
#BinNameLength = 24
Procedure.L ChangeBin(PrinterName.S, BinID.W)
Protected BufferSize.L
Protected BytesRetrieved.L
Protected *DEVMODEBuffer.DEVMODE
Protected *DEVMODEBufferCopy.DEVMODE
Protected ErrorMsg.S
Protected ModeFlag.L
Protected PRINTER_DEFAULTSStructure.PRINTER_DEFAULTS
Protected PrinterHandle.L
Protected Result.L
; ----- Drucker Handle ermitteln
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 = "Die Windows-Funktion OpenPrinter() ist fehlgeschlagen!"
Result = #False
Goto CleanUp
EndIf
; ----- Buffer für DEVMODE-Struktur
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
; ----- Speicher-Buffer für DEVMODE-Struktur
*DEVMODEBuffer = AllocateMemory(BufferSize)
If *DEVMODEBuffer = 0
ErrorMsg = "Die Speicheranforderung für die DEVMODE-Struktur ist gescheitert!"
Result = #False
Goto CleanUp
EndIf
; ----- Speicher-Buffer für Kopier der DEVMODE-Struktur
*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 Windows-Funktion DocumentProperties() ist fehlgeschlagen!"
Result = #False
Goto CleanUp
EndIf
; ----- DEVMODE-Struktur kopieren
CopyMemory(*DEVMODEBuffer, *DEVMODEBufferCopy, BufferSize)
; ----- Einzugsfach abändern
*DEVMODEBufferCopy\dmDefaultSource = BinID
; ----- Papierformat definieren
*DEVMODEBufferCopy\dmPaperSize = #DMPAPER_A4
; ----- Angeben, welche Parameter geändert werden sollen
*DEVMODEBufferCopy\dmFields = #DM_DEFAULTSOURCE | #DM_PAPERSIZE
; ----- DEVMODE-Struktur mit modifizierter Kopie überschreiben
CopyMemory(*DEVMODEBufferCopy, *DEVMODEBuffer, BufferSize)
; ----- Modifizierte DEVMODE-Struktur übergeben
Result = DocumentProperties_(0, PrinterHandle, @PrinterName, *DEVMODEBuffer, *DEVMODEBuffer, #DM_IN_BUFFER | #DM_OUT_BUFFER)
If Result <> #IDOK
ErrorMsg = "Die Übergabe der modifizierten DEVMODE-Struktur ist gescheitert!"
Result = #False
EndIf
; ----- Drucker Handle und Speicherbereiche freigeben
CleanUp:
If PrinterHandle <> 0
ClosePrinter_(PrinterHandle)
EndIf
If *DEVMODEBufferCopy <> 0
FreeMemory(*DEVMODEBufferCopy)
EndIf
If Result = #False
If *DEVMODEBuffer <> 0
FreeMemory(*DEVMODEBuffer)
EndIf
MessageRequester("Error", ErrorMsg, #MB_ICONERROR)
ProcedureReturn #False
EndIf
ProcedureReturn *DEVMODEBuffer
EndProcedure
Define BinID.L
Define BinIDBuffer.S
Define BinNameBuffer.S
Define Buffer.S
Define DefaultPrinterName.S
Define DefaultPortName.S
Define *DEVMODEBuffer
Define DocInfo.DOCINFO
Define Driver.S
Define i.L
Define Info.S
Define NumBins.L
Define PrinterDC.L
Define Result.L
Define SelectedBinID.W
Define SelectedBinName.S
Define Text.S
Define WindowEvent.L
BinIDBuffer = Space(20 * 2) ; maximal 20 Papiereinzugfach-IDs passen hier hinein!
BinNameBuffer = Space(20 * #BinNameLength) ; maximal 20 Papiereinzugfach-Namen passen hier hinein!
Buffer = Space(260)
; ----- Default-Druckernamen und Drucker-Port ermitteln
GetPrivateProfileString_("WINDOWS", "DEVICE", "", @Buffer, 260, "Win.Ini")
DefaultPrinterName = StringField(Buffer, 1, ",")
DefaultPortName = StringField(Buffer, 3, ",")
; ----- Namen der Fächer ermitteln
NumBins = DeviceCapabilities_(@DefaultPrinterName, @DefaultPortName, #DC_BINNAMES, @BinNameBuffer, 0)
Select NumBins
Case -1
MessageRequester("Fehler", "Der Aufruf der Windows-Funktion DeviceCapabilities() ist fehlgeschlagen!", #MB_ICONERROR)
End
Case 0
MessageRequester("Fehler", "Der Abfrage der Papiereinzugfach-Namen wird vom Druckertreiber nicht unterstützt!", #MB_ICONERROR)
End
EndSelect
If OpenWindow(0, 0, 0, 200, 100, "Fach-Auswahl", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
If CreateGadgetList(WindowID(0))
ComboBoxGadget(0, 10, 10, 180, 200)
ButtonGadget(1, 50, 70, 100, 20, "Drucken")
For i = 0 To NumBins - 1
AddGadgetItem(0, -1, Trim(PeekS(@BinNameBuffer + i * #BinNameLength)))
Next i
SetGadgetState(0, 0)
WindowEvent = WaitWindowEvent()
Repeat
WindowEvent = WaitWindowEvent()
Select WindowEvent
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
If EventGadget() = 1 And EventType() = #PB_EventType_LeftClick
Break
EndIf
EndSelect
ForEver
EndIf
EndIf
SelectedBinName = GetGadgetText(0)
SelectedBinID = GetGadgetState(0)
CloseWindow(0)
; ----- Einzugfach-ID ermitteln
NumBins = DeviceCapabilities_(@DefaultPrinterName, @DefaultPortName, #DC_BINS, @BinIDBuffer, 0)
Select NumBins
Case -1
MessageRequester("Fehler", "Der Aufruf der Windows-Funktion DeviceCapabilities() ist fehlgeschlagen!", #MB_ICONERROR)
End
Case 0
MessageRequester("Fehler", "Der Abfrage der Papiereinzugfach-Namen wird vom Druckertreiber nicht unterstützt!", #MB_ICONERROR)
End
EndSelect
SelectedBinID = PeekW(@BinIDBuffer + SelectedBinID * 2)
; ----- Papiereinzugfach wechseln
*DEVMODEBuffer = ChangeBin(DefaultPrinterName, SelectedBinID)
If *DEVMODEBuffer = 0
End
EndIf
; ----- Test-Seite ausdrucken und dabei Papier aus gewünschtem Fach ziehen
PrinterDC = CreateDC_(@Driver, @DefaultPrinterName, 0, *DEVMODEBuffer)
DocInfo\cbSize = SizeOf(DOCINFO)
DocInfo\lpszDocName = @"PureBASIC Test-Seite"
DocInfo\lpszOutput = #Null
Text = "Diese Seite sollte aus dem Fach " + SelectedBinName + " gezogen worden sein!"
If StartDoc_(PrinterDC, @DocInfo) > 0
If StartPage_(PrinterDC) > 0
TextOut_(PrinterDC, 300, 100, Text, Len(Text))
EndPage_(PrinterDC)
EndIf
EndDoc_(PrinterDC)
EndIf
FreeMemory(*DEVMODEBuffer)
If PrinterDC <> 0
DeleteDC_(PrinterDC)
EndIf