手头有一个佳博 GP-L80180 热敏打印机,该打印机有USB口 ,串口。
给的例子,串口通了,通过USB口,安装驱动之后,也可以打印测试页。
但是用VC程序 通过系统驱动打印的方式 ,不是很熟悉。
参考 ESPON 的一些例程,直接通过USB接口,发送ESCPOS指令给打印机。
下面是开发的过程的记录。
1.通过USB线 连接到PC,我的系统是win7 64位。
在设备管理器里面,
如果PC系统是英文版的,应该是叫另外一个名字:USB PRINTING SUPPORT,这个地方不确定。
使用BUS HOUND 查看打印机 USB接口
通过其他网友提供的工具,得到其GUID:
\?\USB#VID_8866&PID_0100#0001B0000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
下面开始第一步,对该USB设备进行枚举,首先找到这个设备,然后再打开。
使用vs2013 创建一个 win32 console 控制台工程:命名为GPL80_ESCPOS_USB
默认使用的字符集为:使用 Unicode 字符集
代码如下:
// GPL80_ESCPOS_USB.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <string>
#include <IOSTREAM>
#include <winioctl.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
using namespace std;
// SetupDiGetInterfaceDeviceDetail所需要的输出长度,定义足够大
#define INTERFACE_DETAIL_SIZE (1024)
//设备数量上限,假设16台上限
#define MAX_DEVICE 16
//USB类的GUID
const GUID USB_GUID = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath);
////////////////////////////////////////////////////////////////////////////////////////////////////////
//获取CreateFile的USB端口号
////////////////////////////////////////////////////////////////////////////////////////////////////////
// 根据GUID获得设备路径
// lpGuid: GUID指针
// pszDevicePath: 设备路径指针的指针,用于返回找到的路径
// 返回: 成功得到的设备路径个数,可能不止1个
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
{
HDEVINFO hDevInfoSet;
SP_DEVINFO_DATA spDevInfoData;
SP_DEVICE_INTERFACE_DATA ifData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
int nCount;
int nTotle;
BOOL bResult;
TCHAR* strUSBPrint = TEXT("USB 打印支持");
// 取得一个该GUID相关的设备信息集句柄
hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID
NULL, // 无关键字
NULL, // 不指定父窗口句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
// 失败...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
printf("failed \r\n");
return 0;
}
// 申请设备接口数据空间
pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
nTotle = -1;
nCount = 0;
bResult = TRUE;
// 设备序号=0,1,2... 逐一测试设备接口,到失败为止
while (bResult)
{
nTotle++;
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// 枚举符合该GUID的设备接口
bResult = ::SetupDiEnumDeviceInfo(
hDevInfoSet, // 设备信息集句柄
(ULONG)nTotle, // 设备信息集里的设备序号
&spDevInfoData); // 设备接口信息
if (bResult)
{
DWORD DataT;
TCHAR buf[MAX_PATH];
DWORD nSize = 0;
// get Friendly Name or Device Description
if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else {
lstrcpy(buf, _T("Unknown"));
}
_tprintf(_T("buf = %s \r\n"), buf);
//是否是要找的设备类型
if (_tcscmp(buf, strUSBPrint) != 0)
continue;
_tprintf(_T("OK\r\n"));
ifData.cbSize = sizeof(ifData);
// 枚舉符合該GUID的設備接口
bResult = ::SetupDiEnumDeviceInterfaces(
hDevInfoSet, // 設備信息集句柄
NULL, // 不需額外的設備描述
lpGuid, // GUID
(ULONG)nTotle, // 設備信息集里的設備序號
&ifData); // 設備接口信息
if (bResult)
{
// 取得该设备接口的细节(设备路径)
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 设备信息集句柄
&ifData, // 设备接口信息
pDetail, // 设备接口细节(设备路径)
INTERFACE_DETAIL_SIZE, // 输出缓冲区大小
NULL, // 不需计算输出缓冲区大小(直接用设定值)
NULL); // 不需额外的设备描述
if (bResult)
{
// 复制设备路径到输出缓冲区
::_tcscpy_s(pszDevicePath[nCount],256, pDetail->DevicePath);
// 调整计数值
nCount++;
_tprintf(_T("Cnt = %d,pDetail->DevicePath =%s\r\n"), nCount, pDetail->DevicePath);
}
}
}
}
// 释放设备接口数据空间
::GlobalFree(pDetail);
// 关闭设备信息集句柄
::SetupDiDestroyDeviceInfoList(hDevInfoSet);
return nCount;
}
HANDLE hPort = NULL; //句柄
int WriteData(string meg)
{
DWORD dwWrite;
return WriteFile(hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
}
int _tmain(int argc, _TCHAR* argv[])
{
//遍历USB设备,找到POS打印机路径
int i, nDevice;
TCHAR * szDevicePath[MAX_DEVICE]; // 设备路径
// string Port; //串口端口号
setlocale(LC_CTYPE, "chs");//设置中文字符
TCHAR * Port;
// 分配需要的空间
for (i = 0; i < MAX_DEVICE; i++)
{
szDevicePath[i] = new TCHAR[256];
}
// 取设备路径
nDevice = GetDevicePath((LPGUID)&USB_GUID, szDevicePath);
i = 0;
while (i < nDevice){
Port = szDevicePath[i++];
_tprintf(_T("device.Port = %s\n"), Port);
}
hPort = CreateFile(Port, GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hPort == INVALID_HANDLE_VALUE)
{ // 打开端口失败
return false;
}
DWORD iBytesLength;
char chInitCode[] = "\x0D\x1B\x40";
if (!WriteFile(hPort, chInitCode, (DWORD)3L, &iBytesLength, NULL)){
_tprintf(_T("Write File Error\r\n"));
return 0;
}
string s;
s = "OK打印完成\n\n";
WriteData(s);
s = "1233333\n\n";
WriteData(s);
s = "abc\n\n";
WriteData(s);
s = "cbde\n\n";
WriteData(s);
s = "\x1D\x56\x41\x00";
WriteData(s);
getchar();
return 0;
}
输出:
buf = USB Serial Converter
buf = USB 输入设备
buf = USB 打印支持
OK
Cnt = 1,pDetail->DevicePath =\\?\usb#vid_8866&pid_0100#0001b0000000#{a5dcbf10-65
30-11d2-901f-00c04fb951ed}
device.Port = \\?\usb#vid_8866&pid_0100#0001b0000000#{a5dcbf10-6530-11d2-901f-00
c04fb951ed}
开发中遇到的问题:
1. win32 的VC 控制台窗口如何输出中文 ? setlocale(LC_CTYPE, “chs”);//设置中文字符
2. TCHAR 语句 如何输出log ? _tprintf(_T(“abc”));
打印效果:
完整的项目工程附件如下,使用的是vs2013 ,修改一下,用其他的版本,应该也可以打开。
https://download.csdn.net/download/wowocpp/10488085
欢迎交流指导