ZPL II Extended Characters

Mauro picture Mauro · Apr 21, 2010 · Viewed 11.4k times · Source

I'm trying to print extended code page 850 characters using ZPL II to a Zebra S4M. Whenever one of the extended characters I.E. ASCII value > 127 is used I get a box of varying shades of grey instead of the actual value.

I'm trying to print ± and ° (ALT+0177 and ALT+0176). I suspect its the RawPrinterHelper I am trying to use (as downloaded from MS, and another from CodeProject) however I cant see where the character codes are going wrong.

Weirdly, printing direct from Notepad renders the correct characters, which leads me to believe it is a problem with the raw printer helper class.

I am not tied to using the Raw Printer Helper class so if there is a better way of doing it, I am more than happy to see them.

SAMPLE ZPLII Without escaped chars

^XA
^FO30,200^AD^FH,18,10^FD35 ± 2 ° ^FS
^FS
^XZ

With escaped chars (tried both upper and lower case)

^XA
^FO30,200^AD^FH,18,10^FD35 _b0 2 _b1 ^FS
^FS
^XZ

Raw Printer Helper

[StructLayout(LayoutKind.Sequential)]
public struct DOCINFO
{
    [MarshalAs(UnmanagedType.LPWStr)]
    public string printerDocumentName;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string pOutputFile;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string printerDocumentDataType;
}

public class RawPrinter
{
    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long OpenPrinter(string pPrinterName, ref IntPtr phPrinter, int pDefault);

    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long StartDocPrinter(IntPtr hPrinter, int Level, ref DOCINFO pDocInfo);

    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long StartPagePrinter(IntPtr hPrinter);

    [
        DllImport("winspool.drv", CharSet = CharSet.Ansi, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long WritePrinter(IntPtr hPrinter, string data, int buf, ref int pcWritten);

    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long EndPagePrinter(IntPtr hPrinter);

    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long EndDocPrinter(IntPtr hPrinter);

    [
        DllImport("winspool.drv", CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
    public static extern long ClosePrinter(IntPtr hPrinter);

    public static void SendToPrinter(string printerJobName, string rawStringToSendToThePrinter,
                                     string printerNameAsDescribedByPrintManager)
    {
        IntPtr handleForTheOpenPrinter = new IntPtr();
        DOCINFO documentInformation = new DOCINFO();
        int printerBytesWritten = 0;
        documentInformation.printerDocumentName = printerJobName;
        documentInformation.printerDocumentDataType = "RAW";
        OpenPrinter(printerNameAsDescribedByPrintManager, ref handleForTheOpenPrinter, 0);
        StartDocPrinter(handleForTheOpenPrinter, 1, ref documentInformation);
        StartPagePrinter(handleForTheOpenPrinter);
        WritePrinter(handleForTheOpenPrinter, rawStringToSendToThePrinter, rawStringToSendToThePrinter.Length,
                     ref printerBytesWritten);
        EndPagePrinter(handleForTheOpenPrinter);
        EndDocPrinter(handleForTheOpenPrinter);
        ClosePrinter(handleForTheOpenPrinter);
    }
}

Actual Fix from the Accepted Answer set the Character Internationalisation ( Code ^CI27 ) to Code Page 1252.

^XA
^FO30,200^AD^CI27^FH,18,10^FD35 _b0 2 _b1 ^FS
^FS
^XZ

Answer

Hans Passant picture Hans Passant · Apr 21, 2010

Yes, the shaded boxes have those byte codes, in code page 1252. Which no doubt is the default code page for the printer, 1252 is the Windows code page for Western Europe and the Americas.

You'll have to send a command to switch the code page to 850. Judging from the manual, that requires ^CI to select character set 13.

Keeping the code page at 1252 and changing your character codes instead would be wise. The glyph tables are in the back of the manual.