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
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] 누겟 설치 : System.Collections.Immutable (0) | 2021.06.26 |
---|---|
[C#/COMMON] 누겟 설치 : System.Threading.Channels (0) | 2021.06.26 |
[C#/COMMON] 누겟 설치 : System.Reactive (0) | 2021.06.26 |
[C#/COMMON] Task 클래스 : Delay 정적 메소드를 사용해 1초 대기하기 (0) | 2021.06.26 |
[C#/COMMON] SerialPort 클래스 : 유진시스텍 YJ-730T 키오스크 프린터 사용하기 (0) | 2021.06.20 |
[C#/COMMON] SAM4S GIANT-100 감열 포스 영수증 프린터 사용하기 (0) | 2021.06.20 |
[C#/COMMON] 윈도우즈 화면 잠금 여부 구하기 (0) | 2021.06.11 |
[C#/COMMON] Process 클래스 : GetProcessesByName 정적 메소드를 사용해 윈도우즈 화면 잠금 여부 구하기 (0) | 2021.06.11 |
[C#/COMMON] Process 클래스 : 부모 프로세스 구하기 (0) | 2021.06.09 |
[C#/COMMON] Win32Exception 클래스 사용하기 (0) | 2021.05.26 |
[C#/COMMON] WIN32 API 마지막 에러 메시지 구하기 (0) | 2021.05.26 |
댓글을 달아 주세요