Raw Druck

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Lightsource.

    Etikettendrucker kann man als Generic/Text only ansprechen.
    Das heißt es wird mit VB.net nicht ein Grafik-Objekt erstellt, sondern man muss die Steuerkodes einzeln zum Drucker schicken.
    Ich hatte lange nach einer Lösung gesucht, und bin bisher nur auf die Lösung mit DLLs gestoßen.
    Hier mal ein Auszug, wer im Internet sucht, wird bestimmt den ganzen restlichen Code finden:

    VB.NET-Quellcode

    1. Public Class Class_Drucker
    2. ' Structure and API declarions:
    3. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
    4. Structure DOCINFOW
    5. <MarshalAs(UnmanagedType.LPWStr)> Public pDocName As String
    6. <MarshalAs(UnmanagedType.LPWStr)> Public pOutputFile As String
    7. <MarshalAs(UnmanagedType.LPWStr)> Public pDataType As String
    8. End Structure
    9. <DllImport("winspool.Drv", EntryPoint:="OpenPrinterW",
    10. SetLastError:=True, CharSet:=CharSet.Unicode,
    11. ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)>
    12. Public Shared Function OpenPrinter(ByVal src As String, ByRef hPrinter As IntPtr, ByVal pd As Long) As Boolean
    13. End Function
    14. Public Shared Function SendBytesToPrinter(ByVal szPrinterName As String, ByVal pBytes As IntPtr, ByVal dwCount As Integer) As Boolean
    15. 'Public Shared Function SendBytesToPrinter(ByVal szPrinterName As String, ByVal pBytes As IntPtr, ByVal dwCount As Int32) As Boolean
    16. Dim hPrinter As IntPtr ' The printer handle.
    17. 'Dim hPrinter As Long ' The printer handle.
    18. Dim dwError As Int32 ' Last error - in case there was trouble.
    19. Dim di As DOCINFOW ' Describes your document (name, port, data type).
    20. Dim dwWritten As Int32 ' The number of bytes written by WritePrinter().
    21. Dim bSuccess As Boolean ' Your success code.
    22. ' Set up the DOCINFO structure.
    23. With di
    24. .pDocName = "Etikett"
    25. .pDataType = "RAW"
    26. .pOutputFile = ""
    27. End With
    28. ' Assume failure unless you specifically succeed.
    29. bSuccess = False
    30. If OpenPrinter(szPrinterName, hPrinter, 0) Then
    31. If StartDocPrinter(CType(hPrinter, IntPtr), 1, di) Then
    32. If StartPagePrinter(CType(hPrinter, IntPtr)) Then
    33. ' Write your printer-specific bytes to the printer.
    34. bSuccess = WritePrinter(CType(hPrinter, IntPtr), pBytes, dwCount, dwWritten)
    35. EndPagePrinter(CType(hPrinter, IntPtr))
    36. End If
    37. EndDocPrinter(CType(hPrinter, IntPtr))
    38. End If
    39. ClosePrinter(CType(hPrinter, IntPtr))
    40. End If


    Mit einer früheren VB.Net Version ging alles glatt. Jetzt bekomme ich mit VS2019
    eine Fehlermeldung bzw. Warnung bei dieser Zeile:

    Quellcode

    1. If OpenPrinter(szPrinterName, hPrinter, 0) Then


    Die Fehlermeldung lautet:
    Assistent für verwaltetes Debuggen "PInvokeStackImbalance" : "Ein Aufruf an die PInvoke-Funktion "Salmiak_dotnet!Salmiak_dotnet.Class_Drucker::OpenPrinter" hat das Gleichgewicht des Stapels gestört. Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein. Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen."


    Ich dachte erst, es würde am ByRef hPrinter As IntPtr hängen, darum habe ich erst mal versucht jeweils Long zu verwenden.
    Das hat leider nichts gebracht. So ganz verstehe ich die Fehlermeldung auch nicht, ob das mit der unerwarteten Bytelänge auf dem Stapel zu tun hat?

    Hat jemand eine Idee was ich da machen kann. Wenn ich beim Debuggen den Fehler ignoriere wird trotzdem ein Etikett ausgedruckt.

    Irgendwie verstehe ich nicht, warum man heutzutage solche Klimmzüge machen muss, um einen Drucker anzusprechen.

    Die andere Möglichkeit nach der ich hier mal frage...
    Über die Serielle Schnittstelle kann man ja problemlos einzelne Bytes schicken.
    Kann man diese Funktionen nicht auch verwenden, um einen Drucker am USB-Port anzusprechen?
    Das wäre für mich die einfachste Möglichkeit.

    Lightsource schrieb:

    hat das Gleichgewicht des Stapels gestört.
    bedeutet, dass Deine Signatur nicht stimmt.
    Gugst Du pinvoke.net/search.aspx?search=OpenPrinter&namespace=[All]
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich spekulationiere: Dein pd As Long müsste eigentlich einen Integer verwenden, kein Long sein.
    Warum das so kompliziert ist: Weil Du eben einen RawPrinter nutzen willst. Einzelne Bytes an den Drucker zu schieben ist nun mal Low-Level. Aber falls es Dir was bringt, hier der RawPrinterHelper, den ich erfolgreich nutze (zusammen mit nem Epson-Drucker):

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Friend Class RawPrinterHelper
    3. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> Structure DOCINFOW
    4. <MarshalAs(UnmanagedType.LPWStr)> Friend DocumentName As String
    5. <MarshalAs(UnmanagedType.LPWStr)> Friend OutputFile As String
    6. <MarshalAs(UnmanagedType.LPWStr)> Friend DataType As String
    7. End Structure
    8. <DllImport("winspool.Drv", EntryPoint:="OpenPrinterW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function OpenPrinter(src As String, ByRef hPrinter As IntPtr, pd As Integer) As Boolean : End Function
    9. <DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function ClosePrinter(hPrinter As IntPtr) As Boolean : End Function
    10. <DllImport("winspool.Drv", EntryPoint:="StartDocPrinterW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function StartDocPrinter(hPrinter As IntPtr, level As Int32, ByRef pDI As DOCINFOW) As Boolean : End Function
    11. <DllImport("winspool.Drv", EntryPoint:="EndDocPrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function EndDocPrinter(hPrinter As IntPtr) As Boolean : End Function
    12. <DllImport("winspool.Drv", EntryPoint:="StartPagePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function StartPagePrinter(hPrinter As IntPtr) As Boolean : End Function
    13. <DllImport("winspool.Drv", EntryPoint:="EndPagePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function EndPagePrinter(hPrinter As IntPtr) As Boolean : End Function
    14. <DllImport("winspool.Drv", EntryPoint:="WritePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Friend Shared Function WritePrinter(hPrinter As IntPtr, pBytes As IntPtr, dwCount As Int32, ByRef dwWritten As Int32) As Boolean : End Function
    15. Friend Sub SendStringToPrinter(PrinterName As String, TextToPrint As String)
    16. Dim PointerToTextString = Marshal.StringToCoTaskMemAnsi(TextToPrint)
    17. Dim TextLength = TextToPrint.Length()
    18. SendBytesToPrinter(PrinterName, PointerToTextString, TextLength)
    19. Marshal.FreeCoTaskMem(PointerToTextString)
    20. End Sub
    21. Private Sub SendBytesToPrinter(PrinterName As String, PointerToTextString As IntPtr, TextLength As Integer)
    22. Dim PrinterHandle = IntPtr.Zero
    23. Dim DocumentInfo = New DOCINFOW With {.DocumentName = "VB.NET RAW document", .DataType = "RAW"}
    24. Dim WrittenBytesCount = 0
    25. If Not OpenPrinter(PrinterName, PrinterHandle, 0) Then Return
    26. If StartDocPrinter(PrinterHandle, 1, DocumentInfo) Then
    27. If StartPagePrinter(PrinterHandle) Then
    28. WritePrinter(PrinterHandle, PointerToTextString, TextLength, WrittenBytesCount)
    29. EndPagePrinter(PrinterHandle)
    30. End If
    31. EndDocPrinter(PrinterHandle)
    32. End If
    33. ClosePrinter(PrinterHandle)
    34. End Sub
    35. End Class

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()