첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

▶ OrderItemModel.cs

namespace TestProject
{
    /// <summary>
    /// 주문 항목 모델
    /// </summary>
    public class OrderItemModel
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 항목명 - ItemName

        /// <summary>
        /// 항목명
        /// </summary>
        public string ItemName { get; set; }

        #endregion
        #region 수량 - Quantity

        /// <summary>
        /// 수량
        /// </summary>
        public string Quantity { get; set; }

        #endregion
        #region 항목 옵션 - ItemOption

        /// <summary>
        /// 항목 옵션
        /// </summary>
        public string ItemOption { get; set; }

        #endregion
    }
}

 

728x90

 

▶ OriderModel.cs

using System.Collections.Generic;

namespace TestProject
{
    /// <summary>
    /// 주문 모델
    /// </summary>
    public class OrderModel
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 주문 번호 - OrderNumber

        /// <summary>
        /// 주문 번호
        /// </summary>
        public string OrderNumber { get; set; }

        #endregion
        #region 주문일 - OrderDate

        /// <summary>
        /// 주문일
        /// </summary>
        public string OrderDate { get; set; }

        #endregion
        #region 주문 시간 - OrderTime

        /// <summary>
        /// 주문 시간
        /// </summary>
        public string OrderTime { get; set; }

        #endregion
        #region 도착일 - ArriveDate

        /// <summary>
        /// 도착일
        /// </summary>
        public string ArriveDate { get; set; }

        #endregion
        #region 주문 항목 리스트 - OrderItemList

        /// <summary>
        /// 주문 항목 리스트
        /// </summary>
        public List<OrderItemModel> OrderItemList { get; set; } = new List<OrderItemModel>();

        #endregion
    }
}

 

300x250

 

▶ DOCINFOA.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 문서 정보 A
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 문서명
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string DocumentName;

        /// <summary>
        /// 출력 파일
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string OutputFile;

        /// <summary>
        /// 데이터 타입
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string DataType;

        #endregion
    }
}

 

▶ PrinterHelper.cs

using System;
using System.Diagnostics;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;

namespace TestProject
{
    /// <summary>
    /// 프린터 헬퍼
    /// </summary>
    /// <remarks>
    /// SAM4S GIANT-100 감열 포스 영수증 프린터
    /// 직렬 포트 대신 USB로 연결한다.
    /// </remarks>
    public static class PrinterHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 프린터 열기 - OpenPrinter(printerName, printerHandle, defaultHandle)

        /// <summary>
        /// 프린터 열기
        /// </summary>
        /// <param name="printerName">프린터명</param>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <param name="defaultHandle">디폴트 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string printerName, out IntPtr printerHandle, IntPtr defaultHandle);

        #endregion
        #region 프린터 문서 인쇄 시작하기 - StartDocPrinter(printerHandle, level, documentInformation)

        /// <summary>
        /// 프린터 문서 인쇄 시작하기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <param name="level">레벨</param>
        /// <param name="documentInformation">문서 정보</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool StartDocPrinter(IntPtr printerHandle, int level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA documentInformation);

        #endregion
        #region 프린터 페이지 인쇄 시작하기 - StartPagePrinter(printerHandle)

        /// <summary>
        /// 프린터 페이지 인쇄 시작하기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool StartPagePrinter(IntPtr printerHandle);

        #endregion
        #region 프린터 쓰기 - WritePrinter(printerHandle, dataHandle, dataCount, countWritten)

        /// <summary>
        /// 프린터 쓰기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataCount">데이타 카운트 (단위 : 바이트)</param>
        /// <param name="countWritten">실제 쓴 카운트</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool WritePrinter(IntPtr printerHandle, IntPtr dataHandle, int dataCount, out int countWritten);

        #endregion
        #region 프린터 페이지 인쇄 종료하기 - EndPagePrinter(printerHandle)

        /// <summary>
        /// 프린터 페이지 인쇄 종료하기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool EndPagePrinter(IntPtr printerHandle);

        #endregion
        #region 프린터 문서 인쇄 종료하기 - EndDocPrinter(printerHandle)

        /// <summary>
        /// 프린터 문서 인쇄 종료하기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool EndDocPrinter(IntPtr printerHandle);

        #endregion
        #region 프린터 닫기 - ClosePrinter(printerHandle)

        /// <summary>
        /// 프린터 닫기
        /// </summary>
        /// <param name="printerHandle">프린터 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("winspool", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern bool ClosePrinter(IntPtr printerHandle);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 프린터명
        /// </summary>
        private static readonly string _prinertName = "SAM4S GIANT-100";

        /// <summary>
        /// 장치 ID
        /// </summary>
        private static readonly string _deviceID = "VID_1C8A&PID_3A0E";

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 연결 여부 구하기 - IsConnected()

        /// <summary>
        /// 연결 여부 구하기
        /// </summary>
        /// <returns>연결 여부</returns>
        public static bool IsConnected()
        {
            bool isConnected = false;

            string query = $"SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE '%{_deviceID}%'";

            try
            {
                using(ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("root\\CIMV2", query))
                {
                    foreach(ManagementObject managementObject in managementObjectSearcher.Get())
                    {
                        isConnected = true;

                        break;
                    }
                }
            }
            catch(Exception exception)
            {
                Debug.WriteLine(exception.ToString());
            }

            return isConnected;
        }

        #endregion
        #region 인쇄하기 - Print(order)

        /// <summary>
        /// 인쇄하기
        /// </summary>
        /// <param name="order">주문</param>
        public static void Print(OrderModel order)
        {
            byte[] centerCommandByteArray = new byte[] { 0x1B, 0x61, 0x01 };
            byte[] leftCommandByteArray   = new byte[] { 0x1B, 0x61, 0x00 };
            byte[] bigCommandByteArray    = new byte[] { 0x1D, 0x21, ((byte)0xF0 & ((byte)0x01 << 4) | ((byte)0x0F & (byte)(0x01))) };
            byte[] normalCommandByteArray = new byte[] { 0x1D, 0x21, 0x00 };
            byte[] cutCommandByteArray    = new byte[] { 0x1D, 0x56, 0x01 };

            //                  0        1         2         3         4
            //                  123456789012345678901234567890123456789012
            string line      = "------------------------------------------";
            string endLine   = "\n  \n";
            string orderNo   = $"[ORDER NUMBER : {order.OrderNumber}]";
            string orderDate = $"ORDER TIME : {order.OrderDate} {order.OrderTime}";
            string orderETA  = $"ORDER ETA  : {order.ArriveDate}";

            StringBuilder stringBuilder = new StringBuilder();
            
            foreach(OrderItemModel orderItem in order.OrderItemList)
            {
                stringBuilder.AppendLine($"ITEM     : {orderItem.ItemName  }");
                stringBuilder.AppendLine($"QUANTITY : {orderItem.Quantity  }");
                stringBuilder.AppendLine($"OPTION   : {orderItem.ItemOption}");
                stringBuilder.AppendLine($"{line}");
            }

            string title = $"\n{orderNo}{endLine}";
            string body  = $"{orderDate}\n{orderETA}\n{line}\n{stringBuilder.ToString()}{endLine}{endLine}";

            byte[] titleByteArray = Encoding.Default.GetBytes(title);
            byte[] bodyByteArray = Encoding.Default.GetBytes(body);

            byte[] printDocumentByteArray = new byte
            [
                centerCommandByteArray.Length +
                bigCommandByteArray.Length    +
                titleByteArray.Length         +
                leftCommandByteArray.Length   +
                normalCommandByteArray.Length +
                bodyByteArray.Length          +
                cutCommandByteArray.Length
            ];

            int offset = 0;

            Buffer.BlockCopy(centerCommandByteArray, 0, printDocumentByteArray, offset, centerCommandByteArray.Length);

            offset += centerCommandByteArray.Length;

            Buffer.BlockCopy(bigCommandByteArray, 0, printDocumentByteArray, offset, bigCommandByteArray.Length);

            offset += bigCommandByteArray.Length;

            Buffer.BlockCopy(titleByteArray, 0, printDocumentByteArray, offset, titleByteArray.Length);

            offset += titleByteArray.Length;

            Buffer.BlockCopy(leftCommandByteArray, 0, printDocumentByteArray, offset, leftCommandByteArray.Length);

            offset += leftCommandByteArray.Length;

            Buffer.BlockCopy(normalCommandByteArray, 0, printDocumentByteArray, offset, normalCommandByteArray.Length);

            offset += normalCommandByteArray.Length;

            Buffer.BlockCopy(bodyByteArray, 0, printDocumentByteArray, offset, bodyByteArray.Length);

            offset += bodyByteArray.Length;

            Buffer.BlockCopy(cutCommandByteArray, 0, printDocumentByteArray, offset, cutCommandByteArray.Length);

            IntPtr printDocumentHandle = Marshal.AllocCoTaskMem(printDocumentByteArray.Length);

            Marshal.Copy(printDocumentByteArray, 0, printDocumentHandle, printDocumentByteArray.Length);

            SendData(printDocumentHandle, printDocumentByteArray.Length);

            Marshal.FreeCoTaskMem(printDocumentHandle);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region 데이터 보내기 - SendData(dataHandle, dataCount)

        /// <summary>
        /// 데이터 보내기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataCount">데이터 카운트 (단위 : 바이트)</param>
        /// <returns>처리 결과</returns>
        private static bool SendData(IntPtr dataHandle, int dataCount)
        {
            int      errorCode           = 0;
            int      countWritten        = 0;
            IntPtr   printerHandle       = new IntPtr(0);
            DOCINFOA documentInformation = new DOCINFOA();
            bool     result              = false;

            documentInformation.DocumentName = "ORDER";
            documentInformation.DataType     = "RAW";

            if(OpenPrinter(_prinertName, out printerHandle, IntPtr.Zero))
            {
                if(StartDocPrinter(printerHandle, 1, documentInformation))
                {
                    if(StartPagePrinter(printerHandle))
                    {
                        result = WritePrinter(printerHandle, dataHandle, dataCount, out countWritten);

                        EndPagePrinter(printerHandle);
                    }

                    EndDocPrinter(printerHandle);
                }

                ClosePrinter(printerHandle);
            }

            if(result == false)
            {
                errorCode = Marshal.GetLastWin32Error();
            }

            return result;
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요