IT’s Ha

[ETC] ZEBRA PrintDriver로 셋팅 후 ZPL 전송 본문

ETC

[ETC] ZEBRA PrintDriver로 셋팅 후 ZPL 전송

Deleloper Ha 2023. 4. 26. 11:45
728x90
반응형

안녕하세요. 이번 포스팅은 Zebra프린트를 사용할 경우 ZPL명령어를 이용해 출력을 하시는 경우가 있습니다. 그러나, Serial포트가 없어 USB드라이브로 셋팅하여 사용 하는 방법을 공유하겠습니다. 

먼저 ZPL이란?
- Zebra Technologies가 개발한 프린터 명령어 세트입니다. ZPL은 주로 바코드, 텍스트, 그래픽 및 기타 요소를 포함한 라벨 및 접지 형태의 출력물을 생성하는 데 사용되는 Zebra 라벨 프린터와 호환됩니다. ZPL은 각 요소를 표시할 위치와 속성을 정의하는 명령어를 사용하여 프린터가 인쇄 작업을 수행할 수 있게 합니다. 각 명령어는 일반적으로 '^' 기호로 시작하며, 이어서 명령어의 기능을 나타내는 대문자 알파벳 문자가 옵니다. 명령어는 추가적인 매개변수를 사용하여 요소의 크기, 스타일, 회전 등을 지정할 수 있습니다.

Windows API를 통하여 전송하는 예제입니다.

1. RawPrinterHelper.cs

using System;

using System.IO;
using System.Runtime.InteropServices;
using System.Text;


namespace ZPL
{
    public class RawPrinterHelper
    {
        [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, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            IntPtr hPrinter;
            DOCINFOA di = new DOCINFOA();
            Int32 dwError = 0, dwWritten = 0;
            bool success = false;

            di.pDocName = "ZPL Document";
            di.pDataType = "RAW";

            if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    if (StartPagePrinter(hPrinter))
                    {
                        success = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            if (!success)
            {
                dwError = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(dwError);
            }
            return success;
        }
        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            IntPtr pBytes;
            Int32 dwCount;
            byte[] rawData = Encoding.UTF8.GetBytes(szString);
            pBytes = Marshal.AllocCoTaskMem(rawData.Length);
            Marshal.Copy(rawData, 0, pBytes, rawData.Length);
            dwCount = rawData.Length;
            try
            {
                SendBytesToPrinter(szPrinterName, pBytes, dwCount);
            }
            finally
            {
                Marshal.FreeCoTaskMem(pBytes);
            }
            return true;
        }
        [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;
        }
    }
}

2. 실행

private void print()
{
    string printerName = "ZDesigner ZD421-203dpi ZPL"; // 프린터 이름으로 변경하세요
    string zplCommand = string.Empty;
    zplCommand = "^XA^F050,50^A0N,50,50^FDHello, World!^FS^XZ"; // ZPL 명령을 사용하거나 변경할 수 있습니다.

    try
    {
        RawPrinterHelper.SendStringToPrinter(printerName, zplCommand);
        Console.WriteLine("ZPL 명령이 성공적으로 전송되었습니다.");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"ZPL 명령 전송 중 오류 발생: {ex.Message}");
    }
}

전송을 하면 프린트가 출력이 되는 예제입니다.

프린트 드라이브를 통하여 전송하는 예제이고, 한글 폰트를 사용하기 위해서는 셋팅은 UTF-8로 설정을 해주셔야합니다. 
예를 들어 CW1,E:KFONT3.FNT^CI26^FS 의 명령어로 셋팅되어있다면, CW1,E:KFONT3.FNT^CI28^FS을 사용하셔야합니다. 

이번포스팅은 여기서 마치겠습니다. 

궁금하신 내용이나 잘못된 내용은 댓글이나 메일로 부탁드리겠습니다. 감사합니다.

728x90
반응형
Comments