您现在的位置是:网站首页> C/C++
打印实现
- C/C++
- 2022-04-17
- 1108人已阅读
VC WinUSB VC++ HIDAPI实现USB数据读写
bSuccess = WriteFile(m_hCom, pbuff, len, &written, &m_ov);
if (!bSuccess )
{
if (ERROR_IO_PENDING == GetLastError())
{
WaitForSingleObject(m_ov.hEvent, 10); // 无纸或其他情况阻塞只等待10毫秒
// return -1;
}
}
//链接打印机
int InitPort(PrintDevice &device)
{
hPort = CreateFile(device.Port.c_str(), GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hPort == INVALID_HANDLE_VALUE)
{ // 打开端口失败
return false;
}
else
{
printf("InitPort Hello\r\n");
//设置端口缓冲
SetupComm(hPort, 1024, 1024);
// 设定通讯端口超时参数
COMMTIMEOUTS tmouts;
tmouts.ReadIntervalTimeout = 100;
tmouts.ReadTotalTimeoutMultiplier = 100;
tmouts.ReadTotalTimeoutConstant = 100;
tmouts.WriteTotalTimeoutConstant = 100;
tmouts.WriteTotalTimeoutMultiplier = 100;
SetCommTimeouts(hPort, &tmouts);
//设定通讯端口通讯参数
DCB dcb;
BOOL bol = TRUE;
//dcb.DCBlength = sizeof(dcb);
bol = GetCommState(hPort, &dcb);
dcb.BaudRate = device.BawdRate;
dcb.ByteSize = device.DataBits;
dcb.StopBits = device.StopBits;
dcb.Parity = device.Parity;
bol = SetCommState(hPort, &dcb); //配置串口
// 清除通讯端口缓存
PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
// 初始化重叠IO对象
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
HANDLE m_hStopCommEvent;
HANDLE m_hDataReady;
memset(&m_OverlappedRead, 0, sizeof(OVERLAPPED));
m_OverlappedRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
memset(&m_OverlappedWrite, 0, sizeof(OVERLAPPED));
m_OverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 初始化事件对象
m_hStopCommEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hDataReady = CreateEvent(NULL, FALSE, FALSE, NULL);
//初始化打印ESC @
DWORD iBytesLength;
char chInitCode[] = "\x0D\x1B\x40";
if (!WriteFile(hPort, chInitCode, (DWORD)3L, &iBytesLength, NULL))
return false;
}
return true;
}
int WriteData(string meg)
{
DWORD dwWrite;
return WriteFile(hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
}
//打印数据,meg打印字符串,bBold=true粗体,nZoom=2大一号字体, nHAil=2居中对齐,nHAil=3右对齐。部分打印机可能中文字体设置无效,请加上FS !命令设置中文字体。
bool OnWriteData(string meg, bool bBold, bool bDTall, bool bDWide, int nHAil)
{
char s[120] = "";
memset(s, 0, 120);
long nMode = 0;
DWORD iBytesLength;
if (bBold)
nMode += 8;
if (bDTall)
nMode += 16;
if (bDWide)
nMode += 32;
if (nMode > 0)
{
//sprintf(s, "\x1B\x21%c", nMode);
sprintf_s(s, sizeof(s), "\x1B\x21%c", nMode);
if (strlen(s) < 3)
{
iBytesLength = 0;
WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);
}
else
WriteData(s);
}
switch (nHAil)
{
case 1:
break;
case 2:
strcat_s(s, strlen("\x1B\x61\x01") + 1, "\x1B\x61\x01");
WriteData(s);
break;
case 3:
strcat_s(s, strlen("\x1B\x61\x02") + 1, "\x1B\x61\x02");
WriteData(s);
break;
default:
break;
}
WriteData(meg);
iBytesLength = 0;
strcpy_s(s, strlen("\x1B\x21\x00") + 1, "\x1B\x21\x00");
WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);
return true;
};
//获取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;
char* strUSBPrint = "USB 打印支持";
// 取得一个该GUID相关的设备信息集句柄
hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID
NULL, // 无关键字
NULL, // 不指定父窗口句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
// 失败...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
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"));
}
//是否是要找的设备类型
if (strcmp(buf, strUSBPrint) != 0)
continue;
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)
{
// 复制设备路径到输出缓冲区
::strcpy_s(pszDevicePath[nCount], 256, pDetail->DevicePath);
// 调整计数值
nCount++;
}
}
}
}
// 释放设备接口数据空间
::GlobalFree(pDetail);
// 关闭设备信息集句柄
::SetupDiDestroyDeviceInfoList(hDevInfoSet);
return nCount;
}
C++ win32 USB打印机开发
基于打印驱动
1 : 获得本地打印驱动
struct PrintInfo
{
BOOL m_bisPrintPage;
string sDeviceName;
string sPortName;
string sShareName;
string sLoction;
string sPaperType;
int nWidthMin;
bool bisPrint;
PrintInfo()
{
m_bisPrintPage = FALSE;
sDeviceName = "";
sPortName = "";
sShareName = "";
sLoction = "";
sPaperType = "";
nWidthMin = 0;
bisPrint = FALSE;
}
};
typedef vector<PrintInfo> PrintInfo_Ary;
int GetLocalPrinterDrivers(PrintInfo_Ary &Drivers)
{
DWORD Flags = PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL; //local printers
DWORD cbBuf;
DWORD pcReturned;
DWORD index;
DWORD Level = 2;
CHAR Name[500];
LPPRINTER_INFO_2A pPrinterEnum = NULL;
memset(Name, 0, sizeof(CHAR)* 500);
::EnumPrintersA(Flags, Name, Level, NULL, 0, &cbBuf, &pcReturned);
pPrinterEnum = (LPPRINTER_INFO_2A)LocalAlloc(LPTR, cbBuf + 4);
if (!pPrinterEnum)
{
goto clean_up;
}
if (!EnumPrintersA(
Flags, // DWORD Flags, printer object types
Name, // LPTSTR Name, name of printer object
Level, // DWORD Level, information level
(LPBYTE)pPrinterEnum, // LPBYTE pPrinterEnum, printer information buffer
cbBuf, // DWORD cbBuf, size of printer information buffer
&cbBuf, // LPDWORD pcbNeeded, bytes received or required
&pcReturned) // LPDWORD pcReturned number of printers enumerated
)
{
goto clean_up;
}
if (pcReturned > 0)
{
for (index = 0; index < pcReturned; index++)
{
PrintInfo DeviceDate;
if ((pPrinterEnum + index)->pPrinterName != NULL)
DeviceDate.sDeviceName = (pPrinterEnum + index)->pPrinterName;
else
DeviceDate.sDeviceName ="";
if ((pPrinterEnum + index)->pPortName != NULL)
DeviceDate.sPortName = (pPrinterEnum + index)->pPortName;
else
DeviceDate.sPortName = "";
if ((pPrinterEnum + index)->pShareName != NULL)
DeviceDate.sShareName = (pPrinterEnum + index)->pShareName;
else
DeviceDate.sShareName = "";
if ((pPrinterEnum + index)->pLocation != NULL)
DeviceDate.sLoction = (pPrinterEnum + index)->pLocation;
else
DeviceDate.sLoction = "";
if ((pPrinterEnum + index)->pDevMode)
{
DeviceDate.nWidthMin = (pPrinterEnum + index)->pDevMode->dmPaperWidth;
DeviceDate.sPaperType = (char*)((pPrinterEnum + index)->pDevMode->dmFormName);
}
//DeviceDate.nWidthMin = (pPrinterEnum + index)->pDevMode->dmPaperWidth;
//DeviceDate.sPaperType = (char*)((pPrinterEnum + index)->pDevMode->dmFormName);
DWORD nstuse = (pPrinterEnum + index)->Status;
DWORD Attributes = (pPrinterEnum + index)->Attributes;
DeviceDate.m_bisPrintPage = BisConnectedA(nstuse, Attributes);
Drivers.push_back(DeviceDate);
}
}
clean_up:
LocalFree(LocalHandle(pPrinterEnum));
return (int)Drivers.size();
}
2: 打开设备进行打印打开一个打印机驱动DriverName 是驱动名称
{
HDC hdcPrint = CreateDC(NULL, DriverName, NULL, NULL);
HFONT Font = CreateFont(32, 0, 0, 0, fontWeight, 0, 0, 0,
DEFAULT_CHARSET, OUT_TT_PRECIS,
CLIP_TT_ALWAYS, PROOF_QUALITY,VARIABLE_PITCH | FF_MODERN | 0x04,L"宋体");
//设置打印梯子
SelectObject(hdcPaint,Font);
LPCWSTR Lp = L"task";
DOCINFO div={sizeof (DOCINFO),Lp};
//编辑一个文档
StartDoc(hdcPrint, &m_di);
//编辑一个文档的一页
StartPage(hdcPrint);
RECT rect;
rect.top = 0;
rect.bottom = 200;
rect.left = 0;
rect.right = 380;
DrawTextA(hdcPrint, "helleo world",13, &rect, DT_LEFT | DT_TOP | DT_EXPANDTABS | DT_NOPREFIX | DT_EDITCONTROL | DT_WORDBREAK | DT_EXTERNALLEADI NG | DT_CALCRECT);
DrawTextA(hdcPrint,"helleo world",13,&rect, DT_LEFT | DT_TOP | DT_EXPANDTABS | DT_NOPREFIX | DT_EDITCONTROL | DT_WORDBREAK | DT_EXTERNALLEADING );
//....
//结束编辑页
EndPage(hdcPrint);
//结束整个文本编辑
EndDoc(hdcPrint);
CloseHandle(hdcPrint);
}
基于硬件驱动开发
1: 获得打印设备信息
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <windows.h>
#include <devguid.h>
#include <setupapi.h>
#include <vector>
#pragma comment (lib, "setupapi.lib")
const char DRIVER_NAME_USBPRINT[] = "USB 打印支持";
const char DRIVER_NAME_USBPRINT_EN[] = "USB Printing Support";
struct deviceinfo {
std::string sdeviceid;
std::string sdesc;
std::string sdevicepath;
std::string sdeviceshow;
deviceinfo() {
sdeviceid = "";
sdesc = "";
sdevicepath = "";
sdeviceshow = "";
}
};
std::vector<deviceinfo > g_printerdevices;
const GUID GUID_DEVINTERFACE_USB_HUB = { 0xf18a0e88L, 0xc30c, 0x11d0, { 0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8 } };
const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3abf6f2dL, 0x71c4, 0x462a, { 0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27 } };
const GUID GUID_USB_WMI_STD_DATA = { 0x4E623B20L, 0xCB14, 0x11D1, { 0xB3, 0x31, 0x00, 0xA0, 0xC9, 0x59, 0xBB, 0xD2 } };
const GUID GUID_USB_WMI_STD_NOTIFICATION = { 0x4E623B20L, 0xCB14, 0x11D1, { 0xB3, 0x31, 0x00, 0xA0, 0xC9, 0x59, 0xBB, 0xD2 } };
const GUID USBPrinterGUID = { 0x4d36e979L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
//GUID__DEVINTERFACE_USB_DEVICE
int GetUSBPrintDevices(const GUID guid)
{
const GUID GUID_DEVINTERFACE_USB_DEVICE = guid;
const GUID* InterfaceGuid = &GUID_DEVINTERFACE_USB_DEVICE;
// that contains all devices of a specified class
HDEVINFO hDevInfo = SetupDiGetClassDevsA(InterfaceGuid,
NULL, // Enumerator
NULL,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return 1;
}
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
PSP_DEVINFO_DATA pDeviceInfoData = &DeviceInfoData;
DWORD MemberIndex;
bool found_usb_printer_flag = false;
for (MemberIndex = 0;
SetupDiEnumDeviceInfo(hDevInfo,
MemberIndex,
pDeviceInfoData) == TRUE;
MemberIndex++)
{
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
PSP_DEVICE_INTERFACE_DATA pDeviceInterfaceData = &DeviceInterfaceData;
DWORD RequiredSize;
PDWORD pRequiredSize = &RequiredSize;
DWORD InnerMemberIndex;
for (InnerMemberIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo,
pDeviceInfoData,
InterfaceGuid,
InnerMemberIndex,
pDeviceInterfaceData) == TRUE;
InnerMemberIndex++)
{
DWORD DeviceInterfaceDetailDataSize = 0;
BOOL first_call_result = SetupDiGetDeviceInterfaceDetailA(hDevInfo,
pDeviceInterfaceData,
NULL, // NULL DeviceInterfaceDetailData pointer
0, // DeviceInterfaceDetailDataSize of zero
pRequiredSize,
pDeviceInfoData);
if (first_call_result == TRUE)
{
continue;
}
else
{
DWORD first_call_error = GetLastError();
if (first_call_error != ERROR_INSUFFICIENT_BUFFER)
{
continue;
}
else
{
CHAR* buffer = new CHAR[RequiredSize];
PSP_DEVICE_INTERFACE_DETAIL_DATA_A pDeviceInterfaceDetailData =
(PSP_DEVICE_INTERFACE_DETAIL_DATA_A)buffer;
pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
DWORD DeviceInterfaceDetailDataSize = RequiredSize;
PDWORD pDeviceInterfaceDetailDataSize = &DeviceInterfaceDetailDataSize;
BOOL second_call_result = SetupDiGetDeviceInterfaceDetailA(hDevInfo,
pDeviceInterfaceData,
pDeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize,
&RequiredSize,
pDeviceInfoData);
if (second_call_result == FALSE)
{
DWORD last_error_number_second_call = GetLastError();
CHAR last_error_message_second_call[512];
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0,
last_error_number_second_call, 0,
last_error_message_second_call,
1024, NULL);
}
else
{
DWORD dwNumberOfBytesWritten = 0;
CHAR szDescription[MAX_PATH];
memset(szDescription, 0, MAX_PATH);
const GUID* ClassGuid = &(pDeviceInfoData->ClassGuid);
SetupDiGetClassDescriptionA(ClassGuid, szDescription, MAX_PATH, &RequiredSize);
memset(szDescription, 0, MAX_PATH);
SetupDiGetDeviceInstanceIdA(hDevInfo, pDeviceInfoData, szDescription, MAX_PATH, 0);
char szName[64] = {0};
if (SetupDiGetDeviceRegistryProperty(hDevInfo,
pDeviceInfoData,
SPDRP_FRIENDLYNAME,
0L,
(PBYTE)szName,
63,
0))
{
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfo,
pDeviceInfoData,
SPDRP_DEVICEDESC,
0L,
(PBYTE)szName,
63,
0))
{
};
std::string sdrivername = szName;
if(sdrivername.find(DRIVER_NAME_USBPRINT) != std::string::npos || sdrivername.find(DRIVER_NAME_USBPRINT_EN) != std::string::npos)
{
deviceinfo device;
device.sdeviceid = szDescription;
device.sdesc = szName;
device.sdevicepath = pDeviceInterfaceDetailData->DevicePath;
GetShowNames(device.sdeviceid ,device.sdeviceshow);
g_printerdevices.push_back(device);
}
} // end if second call returned true
// now free the buffer
delete[] buffer;
} // end if first call was successful
} // end if on second call
} // end iterate through device interfacess
} // end iterate through device info
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
2. 选取一个设备打印
const char initialize_printer_command[] = {ESCAPE_CODE, AT_CODE, NULL_CODE};
const char ESC_WIDTHANDHEGHIT2[] = {0x1c,0x21,12};
int WiterFileInfo(HANDLE handle,const char* sdata)
{
DWORD dwInitializePrinterNumberOfBytesToWrite = 0;
DWORD dwInitializePrinterNumberOfBytesWritten = 0;
dwInitializePrinterNumberOfBytesToWrite = (DWORD)strlen(sdata);
BOOL ret = WriteFile( handle,
sdata,
dwInitializePrinterNumberOfBytesToWrite,
&(dwInitializePrinterNumberOfBytesWritten),
NULL);
return dwInitializePrinterNumberOfBytesWritten;
}
int USBPrintData(deviceinfo &driver)
{
HANDLE handle = CreateFileA(driver.sdevicepath.c_str(),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
return 0;
}
else
{
int i = 0;
}
DWORD dwInitializePrinterNumberOfBytesToWrite = 0;
DWORD dwInitializePrinterNumberOfBytesWritten = 0;
//ESC 指令打印
WiterFileInfo(handle,initialize_printer_command);
sprintf(write,"%s两倍大小字体\n",ESC_WIDTHANDHEGHIT2);
WiterFileInfo(handle,write);
//空白纸走3行
WiterFileInfo(handle," \n \n \n");
CloseHandle(handle);
return 0;
}
一点ESC指令测试
const char ESC_INIT_RWX[] = {0x1B,0x40}; //初始化;
const char ESC_LINE_TAB[] = {0x0A}; //换行
const char ESC_LINE_ADD[] = {0x1B,0x21,0x28}; //加粗
//const char ESC_LINE_H2[] = {0x1D,0x21,0x04}; //倍高 垂直( 三位符(倍高度) 1 2 4 8 1-7 倍)
//const char ESC_LINE_W2[] = {0x1D,0x21,0x20}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_H1[] = {0x1D,0x21,0x01}; //倍高 垂直( 三位符(倍高度) 1 2 4 8 1-7 倍)
const char ESC_LINE_H2[] = {0x1D,0x21,0x02}; //倍高 垂直( 三位符(倍高度) 1 2 4 8 1-7 倍)
const char ESC_LINE_H3[] = {0x1D,0x21,0x04}; //倍高 垂直( 三位符(倍高度) 1 2 4 8 1-7 倍)
const char ESC_LINE_W1[] = {0x1D,0x21,0x10}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_W2[] = {0x1D,0x21,0x20}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_W3[] = {0x1D,0x21,0x30}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_T1[] = {0x1B,0x21,0x02}; //原始高度
const char ESC_LINE_T2[] = {0x1D,0x21,0x11}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_T3[] = {0x1D,0x21,0x22}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_T4[] = {0x1D,0x21,0x34}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
const char ESC_LINE_T5[] = {0x1D,0x21,0x48}; //倍高 垂直( 三位符(倍高度) 10 20 30 40 宽度 )
无驱打印
使用Win32 API打印原始数据(强烈建议)
#include "stdafx.h"
#include <windows.h>
#include <string>
#include <IOSTREAM>
#include <winioctl.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
using namespace std;
typedef struct DataInfo
{
string Port; //串口端口号
int BawdRate;//波特率
int DataBits; //数据位
char Parity; //校验位
int ReceiveBuffer; //缓冲区
int StopBits;//停止位
}PrintDevice;
// 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}};
HANDLE hPort=NULL; //句柄
//封装的打印函数
int WriteData(string meg);
//打印内容
bool OnWriteData(string meg, bool bBold = false, bool bDTall = false, bool bDWide = false, int nHAil = 1);
//链接设备
int InitPort(PrintDevice &device);
//参数初始化
void InitializeDevicePar(PrintDevice &device);
//找设备
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath);
int _tmain(int argc, _TCHAR* argv[])
{
//////////////////////////////////////////////////////////////////////////////////////////////////
//遍历USB设备,找到POS打印机路径
int i, nDevice;
char* szDevicePath[MAX_DEVICE]; // 设备路径
// 分配需要的空间
for (i = 0; i < MAX_DEVICE; i++)
{
szDevicePath[i] = new char[256];
}
// 取设备路径
nDevice = GetDevicePath((LPGUID)&USB_GUID, szDevicePath);
// GUID_CLASS_USB_DEVICE;
//////////////////////////////////////////////////////////////////////////////////////////////////
i = 0;
while (i < nDevice)
{
PrintDevice device;
InitializeDevicePar(device); //初始化打印机参数
device.Port = szDevicePath[i++];
printf("device.Port = %s\n",device.Port.c_str());
InitPort(device); //初始化打印机端口
string s;
////////////////////////////打印头信息开始//////////////////////////////////
OnWriteData("*****Now You See Me*****\n\n",true, true, true);
OnWriteData("- - - - - - - - - - - - - - - -\n");
OnWriteData("So You Want?\n",false, true);
OnWriteData("- - - - - - - - - - - - - - - -\n");
OnWriteData("这是一个基于ESC_POS打印机的USB无驱动打印Demo\n",true, true, true);
OnWriteData("我找到了你的电脑上所有的USB打印机\n",true, true, true, 2);
OnWriteData("然后给所有找到的打印机发送打印命令\n", true, true, true, 3);
OnWriteData("* * * * * * * * * * * * * * * *\n");
OnWriteData("OK打印完成\n\n",false, false, true, 2);
s = "\x1D\x56\x41\x00";
WriteData(s);
CloseHandle(hPort);//关闭端口
}
// 释放空间
for (i = 0; i< MAX_DEVICE; i++)
{
delete szDevicePath[i];
}
return 0;
}
//初始化参数
void InitializeDevicePar(PrintDevice &device)
{
device.Port="COM4";
device.BawdRate=9600;
device.DataBits=8;
device.StopBits=ONESTOPBIT;
device.Parity=NOPARITY; //NONE
device.ReceiveBuffer=256;
}
//链接打印机
int InitPort(PrintDevice &device)
{
hPort = CreateFile(device.Port.c_str(), GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if (hPort == INVALID_HANDLE_VALUE)
{ // 打开端口失败
return false;
}
else
{
printf("InitPort Hello\r\n");
//设置端口缓冲
SetupComm(hPort, 1024, 1024);
// 设定通讯端口超时参数
COMMTIMEOUTS tmouts;
tmouts.ReadIntervalTimeout = 100;
tmouts.ReadTotalTimeoutMultiplier = 100;
tmouts.ReadTotalTimeoutConstant = 100;
tmouts.WriteTotalTimeoutConstant = 100;
tmouts.WriteTotalTimeoutMultiplier = 100;
SetCommTimeouts(hPort, &tmouts);
//设定通讯端口通讯参数
DCB dcb;
BOOL bol = TRUE;
//dcb.DCBlength = sizeof(dcb);
bol=GetCommState(hPort, &dcb);
dcb.BaudRate = device.BawdRate;
dcb.ByteSize =device.DataBits;
dcb.StopBits = device.StopBits;
dcb.Parity = device.Parity;
bol = SetCommState(hPort, &dcb); //配置串口
// 清除通讯端口缓存
PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
// 初始化重叠IO对象
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
HANDLE m_hStopCommEvent;
HANDLE m_hDataReady;
memset(&m_OverlappedRead, 0, sizeof(OVERLAPPED));
m_OverlappedRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
memset(&m_OverlappedWrite, 0, sizeof(OVERLAPPED));
m_OverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 初始化事件对象
m_hStopCommEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hDataReady = CreateEvent(NULL, FALSE, FALSE, NULL);
//初始化打印ESC @
DWORD iBytesLength;
char chInitCode[] = "\x0D\x1B\x40";
if (!WriteFile(hPort, chInitCode, (DWORD)3L, &iBytesLength, NULL))
return false;
}
return true;
}
int WriteData(string meg)
{
DWORD dwWrite;
return WriteFile(hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
}
//打印数据,meg打印字符串,bBold=true粗体,nZoom=2大一号字体, nHAil=2居中对齐,nHAil=3右对齐。部分打印机可能中文字体设置无效,请加上FS !命令设置中文字体。
bool OnWriteData(string meg, bool bBold, bool bDTall, bool bDWide, int nHAil)
{
char s[120] = "";
memset(s, 0, 120);
long nMode = 0;
DWORD iBytesLength;
if (bBold)
nMode += 8;
if (bDTall)
nMode += 16;
if (bDWide)
nMode += 32;
if (nMode > 0)
{
sprintf(s, "\x1B\x21%c", nMode);
if (strlen(s) < 3)
{
iBytesLength = 0;
WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);
}
else
WriteData(s);
}
switch (nHAil)
{
case 1:
break;
case 2:
strcat(s, "\x1B\x61\x01");
WriteData(s);
break;
case 3:
strcat(s, "\x1B\x61\x02");
WriteData(s);
break;
default:
break;
}
WriteData(meg);
iBytesLength = 0;
strcpy(s, "\x1B\x21\x00");
WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);
return true;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
//获取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;
char* strUSBPrint = "USB 打印支持";
// 取得一个该GUID相关的设备信息集句柄
hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID
NULL, // 无关键字
NULL, // 不指定父窗口句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
// 失败...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
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"));
}
//是否是要找的设备类型
if (strcmp(buf, strUSBPrint) != 0)
continue;
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)
{
// 复制设备路径到输出缓冲区
::strcpy_s(pszDevicePath[nCount], 256,pDetail->DevicePath);
// 调整计数值
nCount++;
}
}
}
}
// 释放设备接口数据空间
::GlobalFree(pDetail);
// 关闭设备信息集句柄
::SetupDiDestroyDeviceInfoList(hDevInfoSet);
return nCount;
}
用VC++实现USB接口读写数据的程序
使用一个GUIDguidHID_1查找并打开一个USB设备
extern "C" int PASCAL SearchUSBDevice()
{
HANDLE hUsb;
int nCount, i, j;//标记同一设备个数
HDEVINFO hDevInfoSet;
BOOL bResult;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail =NULL;
memset(m_sysversion, 0, 20);
GetSysVersion(m_sysversion);
// 检索相关GUID的USB设备总设备个数
if (!GetUSBList())
{
return 0;
}
// 取得一个该GUID相关的设备信息集句柄
hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // class GUID
NULL, // 无关键字
NULL, // 不指定父窗口句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
// 失败...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
return NULL;
}
// 申请设备接口数据空间
nCount = 0;
bResult = TRUE;
for (i=0; i< 34; i++)
{
bDeviceOpen[i] = FALSE;
memset(m_DeviceDesc[i], 0, 256);
}
SP_DEVICE_INTERFACE_DATA ifdata;
// 设备序号=0,1,2... 逐一测试设备接口,到失败为止
while (bResult)
{
ifdata.cbSize = sizeof(ifdata);
// 枚举符合该GUID的设备接口
bResult = ::SetupDiEnumDeviceInterfaces(
hDevInfoSet, // 设备信息集句柄
NULL, // 不需额外的设备描述
(LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // GUID
(ULONG)nCount, // 设备信息集里的设备序号
&ifdata); // 设备接口信息
if (bResult)
{
ULONG predictedLength = 0;
ULONG requiredLength = 0;
// 取得该设备接口的细节(设备路径)
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 设备信息集句柄
&ifdata, // 设备接口信息
NULL, // 设备接口细节(设备路径)
0, // 输出缓冲区大小
&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)
NULL); // 不需额外的设备描述
// 取得该设备接口的细节(设备路径)
predictedLength=requiredLength;
// if(pDetail)
// {
// pDetail =NULL;
// }
pDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, predictedLength);
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 设备信息集句柄
&ifdata, // 设备接口信息
pDetail, // 设备接口细节(设备路径)
predictedLength, // 输出缓冲区大小
&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)
NULL); // 不需额外的设备描述
if (bResult)
{
// 复制设备路径到输出缓冲区
//::strcpy(pszDevicePath[nCount], pDetail->DevicePath);
if (strcmp(m_sysversion, "winnt")==0)
{
char ch[18];
for(i=0;i<17;i++){
ch[i]=*(pDetail->DevicePath+8+i);
}
ch[17]='\0';
if (strcmp(ch,"vid_0471&pid_0666")==0)//比较版本号,防止意外出错
{
memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;
memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;
READ_OS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (READ_OS.hEvent == NULL)
{
break;
}
WRITE_OS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (NULL == WRITE_OS.hEvent)
{
CloseHandle( READ_OS.hEvent );
break;
}
hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,//
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL/*|
FILE_FLAG_OVERLAPPED*/,
NULL);
if (hUsb != NULL)
{
// 比较定位找到的USB在哪个USB PORT上
char id[30];
memset(id, 0, 30);
i=0;
do
{
id[i]=*(pDetail->DevicePath+26+i);
i++;
}
while(id[i-1]!='#');
id[i-1] = '\0';
for (j=0; j<34; j++)
{
if(strcmp(id, m_USBList[j])==0)
{
sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath);
m_USBPositionMap[nCount] = j+1;
break;
}
}
CloseHandle(hUsb);
nCount++;
// break;
}
}// 比较驱动版本
}// 比较操作系统版本
else
{
memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;
memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;
READ_OS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (READ_OS.hEvent == NULL)
{
break;
}
WRITE_OS.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (NULL == WRITE_OS.hEvent)
{
CloseHandle( READ_OS.hEvent );
break;
}
hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,//
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL/*|
FILE_FLAG_OVERLAPPED*/,
NULL);
if (hUsb != NULL)
{
if(strcmp(pDetail->DevicePath, m_USBList[j])==0)
{
sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath);
m_USBPositionMap[nCount] = j+1;
break;
}
CloseHandle(hUsb);
nCount++;
// break;
}
}
}
}
}
// 释放设备接口数据空间
::GlobalFree(pDetail);
// 关闭设备信息集句柄
::SetupDiDestroyDeviceInfoList(hDevInfoSet);
iDeviceCount = nCount;
return nCount;
}
// 写
BOOL Writestr(char *buf,int buflen, int index)
{
BOOL fWriteStat;
DWORD dwErrorFlags;
DWORD dwError;
COMSTAT ComStat;
char szError[ 10 ] ;
DWORD ret;
int len, i, j, packet;
div_t div_result;
BYTE sendpacket[65];
BYTE xorcode="0x00";
if (m_gphdCom[index] == NULL) // no usb device(jk100c)
{
return -1;
}
div_result = div(buflen, 58);
if (div_result.rem == 0)
{
packet = div_result.quot;
}
else
{
packet = div_result.quot+1;
}
for (i=0; i<packet; i++)
{
memset(sendpacket, 0, 65);
if(i==packet-1)
{
// end packet
if (div_result.rem == 0)
{
len = 58;
}
else
{
len = div_result.rem;
}
}
else
{
len = 58;
}
sendpacket[0] = 0x13;
sendpacket[1] = 3+len;
sendpacket[2] = 0x01;
sendpacket[3] = packet*16+i+1;
memcpy(sendpacket+4, buf+(i*58), len);
for(j=0;j<len+3;j++)
{
xorcode^=sendpacket[j+1];
}
sendpacket[len+4] = (char)xorcode;
sendpacket[len+5] = 0x23;
PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);
// Sleep(10);
fWriteStat = WriteFile(m_gphdCom[index], sendpacket, len+6,&ret, NULL);
if (!fWriteStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
dwError = GetLastError();
// an error occurred, try to recover
wsprintf( szError, "\n\r <CE-%u>", dwError ) ;
OutputDebugString(szError);
ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags >0)
{
wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;
OutputDebugString(szError);
}
}
else
{
// some other error occurred
ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0)
{
wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;
OutputDebugString(szError);
}
return FALSE;
}
}
if (i != packet-1)
{
// should be receive ack
if (ReceivePacketAnswer(index) != 0)
{
return FALSE;
}
}
}
return TRUE;
}
// 读
int Readstr(char *buf,int nMaxLength, int index)
{
BOOL fReadStat ;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
char szError[ 10 ];
if (fCOMMOpened==0)
{
return FALSE; //串口未打开
}
// only try to read number of bytes in queue
ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat) ;
//dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
dwLength=nMaxLength;
if (dwLength > 0)
{
if (olap==TRUE)
{
fReadStat = ReadFile(m_gphdCom[index],buf, dwLength, &dwLength,&READ_OS) ;
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
OutputDebugString("\n\rIO Pending");
while(!GetOverlappedResult(m_gphdCom[index], &READ_OS,
&dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE) continue;
else
{
// an error occurred, try to recover
ClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;
break;
}
}
}
else // end-----if (GetLastError() == ERROR_IO_PENDING)
{
// some other error occurred
dwLength = 0 ;
ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags >0)
{
wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;
OutputDebugString(szError);
}
}
} // end-----if (!fReadStat)
} // end-----if (olap==TRUE)
else
{
fReadStat = ReadFile( m_gphdCom[index],buf, dwLength, &dwLength, NULL ) ;
if (!fReadStat)
{
dwError = GetLastError();
ClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;
if (dwErrorFlags >0)
{
wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;
OutputDebugString(szError);
}
}
PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);
}
}
return dwLength;
}
下一篇:Qt OpenCV开发笔记