简体   繁体   中英

How to print QR Code using Commands with Zebra RW 420 thermal printer via USB in C#

Before you go on and flag my question as a duplicate, believe me, its not. I have gone through virtually every solution provided here and I still can't get to get my app to work, so please will you just be nice and take some time to help me.

Scenario: I have a Zebra RW 420 thermal printer which I would like to use for printing vouchers with a QR Code on them. I am using C# and have followed all the help as given by Scott Chamberlain here and the code here for sending the commands to the printer. I have the EPL2 manual as well as the CPCL, and ZPL reference manuals with a whole lot of stuff on how to format my commands.

Problem: All the commands I am sending are either printing as plain text replicas of the commands or the printer just hangs with the small message icon showing on its display. I have tried sending the same commands using the Zebra Utilitis and still getting the same result as with my sample app. Below is the code snippets I have, please do advise me if there are any reference libraries I may require to get this to work.

private void btnPrint_Click(object sender, RoutedEventArgs e)
    {
        string s = "! 0 200 200 500 1\nB QR 10 100 M 2 U 10\nMA,QR code ABC123\nENDQR\nFORM\nPRINT"; 

// Have also tried \\r\\n for the line feeds with the same result.

        // Allow the user to select a printer.
        PrintDialog pd = new PrintDialog();

        if ((bool)pd.ShowDialog())
        {
            var bytes = Encoding.ASCII.GetBytes(s);
            // Send a printer-specific to the printer.
            RawPrinterHelper.SendBytesToPrinter(pd.PrintQueue.FullName, bytes, bytes.Length);
        }
    }

PrinterHelper class as modified by Scott here

public class RawPrinterHelper
{
    // Structure and API declarions:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA
    {
        [MarshalAs(UnmanagedType.LPStr)] public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)] public string pDataType;
    }

    [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi,
        ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter,
        IntPtr pd);

    [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true,
        CallingConvention = CallingConvention.StdCall)]
    public static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi,
        ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level,
        [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

    [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true,
        CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true,
        CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true,
        CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true,
        CallingConvention = CallingConvention.StdCall)]
    public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten);

    // SendBytesToPrinter()
    // When the function is given a printer name and an unmanaged array
    // of bytes, the function sends those bytes to the print queue.
    // Returns true on success, false on failure.
    public static bool SendBytesToPrinter(string szPrinterName, byte[] pBytes, Int32 dwCount)
    {
        Int32 dwError = 0, dwWritten = 0;
        IntPtr hPrinter = new IntPtr(0);
        DOCINFOA di = new DOCINFOA();
        bool bSuccess = false; // Assume failure unless you specifically succeed.

        di.pDocName = "Zebra Label";
        di.pDataType = "RAW";

        // Open the printer.
        if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
        {
            // Start a document.
            if (StartDocPrinter(hPrinter, 1, di))
            {
                // Start a page.
                if (StartPagePrinter(hPrinter))
                {
                    // Write your bytes.
                    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        // If you did not succeed, GetLastError may give more information
        // about why not.
        if (bSuccess == false)
        {
            dwError = Marshal.GetLastWin32Error();
            throw new Win32Exception(dwError);
        }
        return bSuccess;
    }

}

I did a lot of work on Zebra ZT230 and GX430t printers last year, and the thing I found out about them was using the ZPL instructions over TCP sockets via port 9100 was a LOT more reliable.

I know this is taking your conversation in a very different direction, but having tried the spool / Win32 approach I can tell you using sockets was a lot more reliable. Let me know if you need some sample code.

Wrote a kiosk application using a KR403 last year. I was able to successfully print and poll the status of the printer to see if there was a paper jam low paper etc via usb using the blog post below.

http://danielezanoli.blogspot.com/2010/06/usb-communications-with-zebra-printers.html

Using print spooler (Print only)

https://sharpzebra.codeplex.com/SourceControl/latest#src/Com.SharpZebra/Printing/RawPrinter.cs

I used the ZebraDesigner to do my initial layout. On the print screen inside the zebra designer there is a print to file option that will save your design as a txt file with ZPL in it. I then took that file broke it up into sections and created a helper class that uses a StringBuilder internally so I could focus on certain pieces of the zpl since it can be overwhelming to look at more than 1-2 lines.

var kioskTicketBuilder = new KioskTicketBuilder();
kioskTicketBuilder.SetPrinterDefaults();
kioskTicketBuilder.DisplayTicketHeader();
kioskTicketBuilder.DisplayInformationHeading(data.Name, data.todaysDate, data.ClientName, data.ClientCode);
kioskTicketBuilder.DisplayMoreStuff()
kioskTicketBuilder.DisplayBarcode(data.TrackingId);
kioskTicketBuilder.EndOfJob();
return kioskTicketBuilder.GetPrintJobToArray();

Also if you go to the the printer properties > Printing Defaults > Tools Tab There is an option to send a file of zpl to the printer or send individual commands. This is really good for testing your zpl seperate from your application.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM