Windows 프린터 스풀러로 라벨 프린터에 인쇄 명령 보내기
- 최초 작성일: 2023년 3월 15일 (수)
- 참고: https://www.zebra.com/content/dam/zebra_new_ia/en-us/manuals/printers/common/programming/zpl-zbi2-pm-en.pdf
목차
[TOC]
내용
Windows 프린터 스풀러를 사용하여 TSC P200 라벨 프린터에 라벨링 정보와 인쇄 명령을 전송하는 C++ 프로그램이며, 코드는 다음과 같은 단계로 작동한다.
- 프린터 이름 설정
- std::wstring printerName = L”TSC P200”;에서 프린터 이름을 설정한다.
- 이 예에서는 TSC P200라는 이름을 사용하였으나, 실제 사용하는 프린터의 이름으로 변경해야 한다.
- 인쇄 명령 설정
- std::string command에 인쇄할 라벨의 정보와 명령을 설정한다.
- 여기서는 30x10 mm 크기의 라벨에 ‘Hello, World!’라는 텍스트를 인쇄하는 예제가 포함되어 있다.
- 프린터 열기
- OpenPrinterW() 함수를 사용하여 프린터를 연다. 이 함수는 프린터 이름을 입력으로 받아 프린터와 연결을 설정한다.
- 연결이 성공하면 프린터 핸들을 반환한다.
- 인쇄 작업 정보 설정
- DOC_INFO_1A 구조체를 사용하여 인쇄 작업에 대한 정보를 설정한다.
- 이 구조체는 작업 이름, 출력 파일 및 데이터 유형을 포함한다.
- 이 예에서는 데이터 유형을 ‘RAW’로 설정하여 명령을 직접 프린터에 전송한다.
- 인쇄 작업 시작
- StartDocPrinterA() 함수를 사용하여 인쇄 작업을 시작한다.
- 이 함수는 프린터 핸들 및 DOC_INFO_1A 구조체를 입력으로 받는다. 6 인쇄 페이지 시작
- StartPagePrinter() 함수를 사용하여 인쇄 페이지를 시작한다. 이 함수는 프린터 핸들을 입력으로 받는다.
- 프린터에 데이터 쓰기
- WritePrinter() 함수를 사용하여 프린터에 명령을 전송한다.
- 이 함수는 프린터 핸들, 명령 데이터 및 데이터 크기를 입력으로 받는다.
- 인쇄 페이지 종료
- EndPagePrinter() 함수를 사용하여 인쇄 페이지를 종료한다.
- 이 함수는 프린터 핸들을 입력으로 받는다.
- 인쇄 작업 종료
- EndDocPrinter() 함수를 사용하여 인쇄 작업을 종료한다.
- 이 함수는 프린터 핸들을 입력으로 받는다.
- 프린터 닫기
- ClosePrinter() 함수를 사용하여 프린터를 닫고, 프린터와의 연결을 해제한다.
- 이 함수는 프린터 핸들을 입력으로 받는다.
이 코드를 사용하면 Windows 프린터 스풀러를 통해 프린터에 명령을 전송할 수 있다. 프린터 이름을 실제 사용하는 프린터 이름으로 바꾸고, 인쇄할 라벨의 정보와 명령을 필요에 따라 수정하여 코드를 사용할 수 있다.
이 코드를 컴파일하고 실행하면, 설정한 라벨 정보와 프린트 명령을 TSC P200 라벨 프린터로 전송하여 인쇄가 진행된다.
이 코드는 대부분의 에러 상황을 감지하고 적절한 오류 메시지를 출력하여 사용자에게 알린다. 이를 통해 프린터 열기, 설정, 인쇄 작업 및 페이지 시작/종료 등 과정에서 발생할 수 있는 문제를 쉽게 파악할 수 있다.
정리하면, 이 코드는 Windows의 프린터 스풀러를 사용하여 TSC P200 라벨 프린터와 통신하는 C++ 프로그램이다.
프린터 이름, 라벨 정보 및 인쇄 명령을 설정한 후, 프린터와 연결하고 인쇄 작업을 시작하여 라벨을 인쇄하고 작업을 종료한다.
이 과정에서 발생할 수 있는 오류를 처리하고 사용자에게 알리는 기능도 포함되어 있다.
버전 1
#include <iostream>
#include <string>
#include <Windows.h>
int main() {
// 프린터 이름 설정. 실제 사용하는 프린터 이름 변경
std::wstring printerName = L"TSC P200";
// 인쇄할 라벨의 정보와 명령을 설정
std::string command = "SIZE 30 mm, 10 mm\n"
"GAP 3 mm, 0\n"
"DIRECTION 1\n"
"CLS\n"
"TEXT 10, 10, \"3\", 0, 1, 1, \"Hello, World!\"\n"
"PRINT 1\n";
// 프린터 핸들 초기화
HANDLE hPrinter;
// 프린터와 연결 시도. 실패하면 에러 메시지를 출력하고 종료.
if (!OpenPrinterW(const_cast<LPWSTR>(printerName.c_str()), &hPrinter, nullptr)) {
std::cerr << "Error opening printer: " << GetLastError() << std::endl;
return 1;
}
// 인쇄 작업 정보 설정.
DOC_INFO_1A docInfo;
docInfo.pDocName = const_cast<char*>("TSC P200 Printing");
docInfo.pOutputFile = nullptr;
docInfo.pDatatype = const_cast<char*>("RAW");
// 인쇄 작업을 시작. 실패하면 에러 메시지를 출력하고 종료.
DWORD jobId = StartDocPrinterA(hPrinter, 1, reinterpret_cast<LPBYTE>(&docInfo));
if (jobId == 0) {
std::cerr << "Error starting print job: " << GetLastError() << std::endl;
ClosePrinter(hPrinter);
return 1;
}
// 페이지 인쇄를 시작. 실패하면 에러 메시지를 출력하고 종료.
if (!StartPagePrinter(hPrinter)) {
std::cerr << "Error starting page: " << GetLastError() << std::endl;
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 설정한 라벨 정보와 명령을 프린터로 전송.
DWORD bytesWritten;
if (!WritePrinter(hPrinter, const_cast<char*>(command.data()), command.size(), &bytesWritten)) {
std::cerr << "Error writing to printer: " << GetLastError() << std::endl;
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 페이지 인쇄를 종료. 실패하면 에러 메시지를 출력하고 종료.
if (!EndPagePrinter(hPrinter)) {
std::cerr << "Error ending page: " << GetLastError() << std::endl;
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 인쇄 작업을 종료. 실패하면 에러 메시지를 출력하고 종료.
if (!EndDocPrinter(hPrinter)) {
std::cerr << "Error ending print job: " << GetLastError() << std::endl;
ClosePrinter(hPrinter);
return 1;
}
// 프린터와의 연결 종료.
ClosePrinter(hPrinter);
return 0;
}
버전 2 (ZPL)
std::string command = "^XA\n"
"^MMT\n"
"^PW203\n"
"^LL203\n"
"^LS0\n"
"^FO10,10^A0N,28,28^FDHello,World!^FS\n"
"^PQ1,0,1,Y^XZ\n";
이 커맨드는 ZPL 프린터 언어를 사용하여 라벨 프린터에서 Hello,World! 라는 문자열을 출력하는 명령어이다.
- ^XA: 라벨 프린트 시작
- ^MMT: 미리 정의된 단위(mm)로 설정
- ^PW203: 프린터의 페이퍼 폭을 설정(203 DPI의 경우 2인치)
- ^LL203: 라벨의 길이를 설정(203 DPI의 경우 2인치)
- ^LS0: 프린트 방식(각자가 해야 할 작업만 진행)
- ^FO10,10: 출력을 시작할 위치(x좌표, y좌표)를 설정
- ^A0N,28,28: 폰트 타입, 폰트 크기, 줄 간격 설정
- ^FDHello,World!: 출력할 문자열
- ^FS: 출력을 끝내고 다음 출력 준비
- ^PQ1,0,1,Y: 프린트 수량, 장치 수량(0으로 설정하면 무한), 모든 장치에서 프린트
- ^XZ: 라벨 프린트 종료
커맨드에서 ^A0N,28,28은 폰트 타입을 A, 폰트 크기를 28포인트, 줄 간격을 28포인트로 설정한다.
폰트 타입은 A,B,C,D,E,F,X,U 등 여러 가지가 있으며, 폰트 크기와 줄 간격은 출력하고자 하는 라벨의 크기와 디자인에 맞게 설정해야 한다.
#include <iostream>
#include <string>
#include <Windows.h>
int main() {
// 프린터 이름을 설정합니다. 실제 사용하는 프린터 이름으로 변경하세요.
std::wstring printerName = L"TSC P200";
// 인쇄할 라벨의 정보와 명령을 설정합니다.
std::string command = "^XA\n"
"^MMT\n"
"^PW203\n"
"^LL203\n"
"^LS0\n"
"^FO10,10^A0N,28,28^FDHello,World!^FS\n"
"^PQ1,0,1,Y^XZ\n";
// 프린터 핸들을 초기화합니다.
HANDLE hPrinter;
// 프린터와 연결을 시도합니다. 실패하면 에러 메시지를 출력하고 종료합니다.
if (!OpenPrinterW(const_cast<LPWSTR>(printerName.c_str()), &hPrinter, nullptr)) {
std::cerr << "Error opening printer: " << GetLastError() << std::endl;
return 1;
}
// 인쇄 작업에 대한 정보를 설정합니다.
DOC_INFO_1A docInfo;
docInfo.pDocName = const_cast<char*>("TSC P200 Printing");
docInfo.pOutputFile = nullptr;
docInfo.pDatatype = const_cast<char*>("RAW");
// 인쇄 작업을 시작합니다. 실패하면 에러 메시지를 출력하고 종료합니다.
DWORD jobId = StartDocPrinterA(hPrinter, 1, reinterpret_cast<LPBYTE>(&docInfo));
if (jobId == 0) {
std::cerr << "Error starting print job: " << GetLastError() << std::endl;
ClosePrinter(hPrinter);
return 1;
}
// 페이지 인쇄를 시작합니다. 실패하면 에러 메시지를 출력하고 종료합니다.
if (!StartPagePrinter(hPrinter)) {
std::cerr << "Error starting page: " << GetLastError() << std::endl;
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 설정한 라벨 정보와 명령을 프린터로 전송합니다.
DWORD bytesWritten;
if (!WritePrinter(hPrinter, const_cast<char*>(command.data()), command.size(), &bytesWritten)) {
std::cerr << "Error writing to printer: " << GetLastError() << std::endl;
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 페이지 인쇄를 종료합니다. 실패하면 에러 메시지를 출력하고 종료합니다.
if (!EndPagePrinter(hPrinter)) {
std::cerr << "Error ending page: " << GetLastError() << std::endl;
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
return 1;
}
// 인쇄 작업을 종료합니다. 실패하면 에러 메시지를 출력하고 종료합니다.
if (!EndDocPrinter(hPrinter)) {
std::cerr << "Error ending print job: " << GetLastError() << std::endl;
ClosePrinter(hPrinter);
return 1;
}
// 프린터와의 연결을 종료합니다.
ClosePrinter(hPrinter);
return 0;
}