#include "../pch/pch.h" #include "CPosPrinter.h" #include "../tool/CComHelper.h" #include "../helper/CBitmapHelper.h" #include CPosPrinter::CPosPrinter(): m_socket(m_io) { } CPosPrinter::~CPosPrinter() { } /* *usbType是1表示只查找收银小票打印机,会排除已知的标签打印机 *usbType为2表示所有usb打印机都查找,包含标签与非标签 **/ void CPosPrinter::InitUsb(int usbType) { //设置中文字符 setlocale(LC_CTYPE, "chs"); //取设备路径 int nDevice = GetDevicePath((LPGUID)&USB_GUID, usbType); LOG_INFO("可用的USB打印机数量:" << nDevice); //添加usb端口 int i = 0; while(i < nDevice) { std::string setting_biaoqian_printer_usb = CSetting::GetParam("setting_biaoqian_printer_usb"); std::wstring ws_setting_biaoqian_printer_usb = CLewaimaiString::UTF8ToUnicode(setting_biaoqian_printer_usb); if (CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1" && ws_setting_biaoqian_printer_usb == m_usb_devices[i]) { //碰到了一个标签打印机 i++; continue; } LOG_INFO("准备打开端口 Port = " << m_usb_devices[i].c_str()); HANDLE hPort = CreateFile(m_usb_devices[i].c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hPort == INVALID_HANDLE_VALUE) { LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str()); // 打开端口失败 DWORD error = GetLastError(); if(error == 2) { //没有指定的文件 LOG_INFO("没有找对对应的usb端口"); } else if(error == 5) { LOG_INFO("usb端口被占用!"); } continue; } LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort); if(PortTest(hPort) == true) { //端口测试连通,保存起来 PrinterHandle newHandle; newHandle.hPort = hPort; newHandle.type = 1; m_hPorts.push_back(newHandle); } else { //端口打印机没有连接,那么就直接关闭掉并口,避免占用 CloseHandle(hPort); } i++; } } bool CPosPrinter::InitOneUsb(wstring usb_path) { if (usb_path == L"") { return false; } HANDLE hPort = CreateFile(usb_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hPort == INVALID_HANDLE_VALUE) { LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str()); // 打开端口失败 DWORD error = GetLastError(); if(error == 2) { //没有指定的文件 LOG_INFO("没有找对对应的usb端口"); } else if(error == 5) { LOG_INFO("usb端口被占用!"); } return false; } LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort); if(PortTest(hPort) == true) { //端口测试连通,保存起来 PrinterHandle newHandle; newHandle.hPort = hPort; newHandle.type = 1; m_hPorts.push_back(newHandle); } else { //端口打印机没有连接,那么就直接关闭掉并口,避免占用 CloseHandle(hPort); return false; } return true; } bool CPosPrinter::InitBingkou() { std::wstring LptStr = L"lpt1"; HANDLE hPort = CreateFile(LptStr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hPort == INVALID_HANDLE_VALUE) { LOG_INFO("打开并口失败, Port = " << LptStr.c_str()); DWORD error = GetLastError(); if(error == 2) { //没有指定的文件 LOG_INFO("本机器没有并口!"); } else if(error == 5) { LOG_INFO("并口被占用!"); } return false; } else { //这个表示并口可以使用 LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort); if(PortTest(hPort) == true) { //并口测试连通,保存起来 PrinterHandle newHandle; newHandle.hPort = hPort; newHandle.type = 2; m_hPorts.push_back(newHandle); } else { //并口打印机没有连接,那么就直接关闭掉并口,避免占用 CloseHandle(hPort); return false; } } return true; } void CPosPrinter::InitCom() { CComHelper helper; std::vector comVector = helper.getComPort(); for(std::vector::iterator it = comVector.begin(); it != comVector.end(); it++) { std::wstring com2Str = *it; HANDLE hPort = CreateFile(com2Str.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hPort == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); if(error == 2) { //没有指定的文件 LOG_INFO("没有找到对应的串口 " << com2Str.c_str()); } else if(error == 5) { LOG_INFO("串口被占用 " << com2Str.c_str()); } } else { LOG_INFO(com2Str.c_str() << " success, handle:" << hPort); //扎到了可用的串口,设置串口波特率 DCB dcb; dcb.DCBlength = sizeof(dcb); GetCommState(hPort, &dcb); //佳博的串口打印机,默认是这个波特率 dcb.BaudRate = 19200; if(!SetCommState(hPort, &dcb)) { LOG_INFO("set baudRate failed!"); CloseHandle(hPort); continue; } //设定通讯端口超时参数 COMMTIMEOUTS tmouts; tmouts.ReadIntervalTimeout = 100; tmouts.ReadTotalTimeoutMultiplier = 100; tmouts.ReadTotalTimeoutConstant = 100; tmouts.WriteTotalTimeoutConstant = 100; tmouts.WriteTotalTimeoutMultiplier = 100; SetCommTimeouts(hPort, &tmouts); //设置端口缓冲 SetupComm(hPort, 1024, 1024); //清除通讯端口缓存 PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT); //保存端口 PrinterHandle newHandle; newHandle.hPort = hPort; newHandle.type = 3; m_hPorts.push_back(newHandle); } } } /* *找到所有可用的小票打印机,这里只初始化USB,不包含并口、串口、网口 *智能识别模式不再自动处理串口,串口的需要人工去选择类型 **/ void CPosPrinter::InitShouyin() { //开始添加usb InitUsb(); } /* *获取CreateFile的USB端口号 **/ int CPosPrinter::GetDevicePath(LPGUID lpGuid, int usbType) { HDEVINFO hDevInfoSet; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA ifData; PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail; int nCount; int nTotle; BOOL bResult; //这2个字符串,用于根据usb的名字对比是否为打印机设备 wstring strUSBPrint = TEXT("USB 打印支持"); //xp上是英文 wstring strUSBPrint_EN = L"USB Printing Support"; // 取得一个该GUID相关的设备信息集句柄 hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID NULL, // 无关键字 NULL, // 不指定父窗口句柄 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备 // 失败... if(hDevInfoSet == INVALID_HANDLE_VALUE) { LOG_INFO("SetupDiGetClassDevs 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] = { 0 }; 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")); } wstring ws_buf = buf; //是否是要找的设备类型 if(ws_buf != strUSBPrint && ws_buf != strUSBPrint_EN) { LOG_INFO("not good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str()); continue; } LOG_INFO("good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str()); 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) { wstring DevicePath = pDetail->DevicePath; wstring vid = DevicePath.substr(DevicePath.find(_T("vid_"), 0) + 4, 4); wstring pid = DevicePath.substr(DevicePath.find(_T("pid_"), 0) + 4, 4); LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str()); if(usbType == 1 && GetPrinterType(vid, pid) == 2) { //标签打印机,暂时不处理打印 LOG_INFO("标签打印机,暂时不打印!"); continue; } // 复制设备路径到输出缓冲区 m_usb_devices.push_back(DevicePath); // 调整计数值 nCount++; LOG_INFO("Cnt = " << nCount << ",pDetail->DevicePath =" << pDetail->DevicePath); } } } else { //LOG_INFO("SetupDiEnumDeviceInfo FAILED!@"); } } // 释放设备接口数据空间 ::GlobalFree(pDetail); // 关闭设备信息集句柄 ::SetupDiDestroyDeviceInfoList(hDevInfoSet); return nCount; } /* *返回打印机的类型, 1:普通热敏打印机 2:标签打印机 3:发票打印机 *这里因为不同厂家对vid pid定义不一样,有时候会出现佳博的标签打印机的vid和pid,在别的品牌上变成了热敏打印机,这里如果排除掉别的品牌的热敏打印机就无法打印了,所以这里不能轻易排除 **/ int CPosPrinter::GetPrinterType(wstring vid, wstring pid) { if(vid == L"6868" && pid == L"0500") { //佳博标签打印机 return 2; } else if (vid == L"XXX" && pid == L"XXX") { //发票打印机 return 3; } return 1; } /* *打印收银小票 **/ void CPosPrinter::PrintWaimaiOrderShouyin(CWaimaiOrder& order) { LOG_INFO("_______________________________开始打印收银小票,订单编号:"< 0) { POS_TextOut(printer_tip_name, false, true, 1); POS_FeedLine(); POS_FeedLine(); } //打印预约、即时配送的提醒 /* bool setting_printer_peisongshijian_big = false; if (CSetting::GetParam("setting_printer_peisongshijian_big") == "1") { setting_printer_peisongshijian_big = true; } }*/ if (order.m_is_selftake == "1") { string date = "【自取单】" + CLewaimaiString::UTF8ToANSI(order.m_delivery_date); POS_TextOut(date, false, true); POS_TextOut("取货", false, false); POS_FeedLine(); } else { if (order.m_is_book == "1") { //预约单 string date = "【预约单】" + CLewaimaiString::UTF8ToANSI(order.m_delivery_date); POS_TextOut(date, false, true); POS_TextOut("送达", false, false); POS_FeedLine(); } else { //非预约单 string date = "【即时单】立即送达"; POS_TextOut(date, false, true, 1); POS_FeedLine(); } } POS_FeedLine(); //打印取货方式 /* bool setting_printer_quhuo_big = false; if(CSetting::GetParam("setting_printer_quhuo_big") == "1") { setting_printer_quhuo_big = true; } if(order.m_is_selftake == "1") { POS_TextOut("到店自取订单", false, setting_printer_quhuo_big, 1); POS_FeedLine(); POS_FeedLine(); } else { POS_TextOut("外卖订单", false, setting_printer_quhuo_big, 1); POS_FeedLine(); } POS_FeedLine(); */ //订单来源 string from_type = "订单来源:" + CLewaimaiString::UTF8ToANSI(order.m_from_type); POS_TextOut(from_type); POS_FeedLine(); //订单号 bool setting_printer_dingdanhao_big = false; if(CSetting::GetParam("setting_printer_dingdanhao_big") == "1") { setting_printer_dingdanhao_big = true; } string order_num = "订 单 号:" + CLewaimaiString::UTF8ToANSI(order.m_order_num); POS_TextOut(order_num, false, setting_printer_dingdanhao_big); POS_FeedLine(); //下单时间 bool setting_printer_xiadanshijian_big = false; if(CSetting::GetParam("setting_printer_xiadanshijian_big") == "1") { setting_printer_xiadanshijian_big = true; } string order_date = "下单时间:" + CLewaimaiString::UTF8ToANSI(order.m_order_date); POS_TextOut(order_date, false, setting_printer_xiadanshijian_big); POS_FeedLine(); //姓名 bool setting_printer_name_big = false; if(CSetting::GetParam("setting_printer_name_big") == "1") { setting_printer_name_big = true; } if(order.m_is_selftake != "1") { string name = "姓名:" + CLewaimaiString::UTF8ToANSI(order.m_customer_name); //把下单次数也一起打印 if (order.m_showordernum == "1") { name += "(第 " + CLewaimaiString::UTF8ToANSI(order.m_customer_order_total) + " 次下单)"; } POS_TextOut(name, false, setting_printer_name_big); POS_FeedLine(); } //电话 bool setting_printer_phone_big = false; if(CSetting::GetParam("setting_printer_phone_big") == "1") { setting_printer_phone_big = true; } //看看电话是否要脱敏 if (order.m_show_whole_phone == "0") { order.m_phone.replace(3, 4, 4, '*'); } string phone = "电话:" + CLewaimaiString::UTF8ToANSI(order.m_phone); POS_TextOut(phone, false, setting_printer_phone_big); POS_FeedLine(); //地址 bool setting_printer_address_big = false; if(CSetting::GetParam("setting_printer_address_big") == "1") { setting_printer_address_big = true; } if(order.m_is_selftake != "1") { string address = "地址:" + CLewaimaiString::UTF8ToANSI(order.m_address); POS_TextOut(address, false, setting_printer_address_big); POS_FeedLine(); } //预设选项 if(order.m_order_field.size() > 1) { for(std::vector::iterator it = order.m_order_field.begin(); it != order.m_order_field.end() - 1; it++) { string order_field = CLewaimaiString::UTF8ToANSI((*it).name) + ":" + CLewaimaiString::UTF8ToANSI((*it).value); POS_TextOut(order_field, false, false, 0); POS_FeedLine(); } } //准备开始打印商品详情 string lines; if(guige == "58") { lines = "--------------------------------"; } else { lines = "------------------------------------------------"; } POS_TextOut(lines); POS_FeedLine(); //商品标题 bool setting_printer_shangpin_big = false; if(CSetting::GetParam("setting_printer_shangpin_big") == "1") { setting_printer_shangpin_big = true; } if(guige == "58") { POS_TextOut("商品 单价 数量 金额", false, setting_printer_shangpin_big); } else { POS_TextOut("商品 单价 数量 金额", false, setting_printer_shangpin_big); } POS_FeedLine(); if (order.m_manzeng_name.length() > 0) { CWaimaiOrderItem manzengItem; manzengItem.m_food_name = CLewaimaiString::ANSIToUTF8("【满赠】" + CLewaimaiString::UTF8ToANSI(order.m_manzeng_name)); order.m_order_items.push_back(manzengItem); } //商品内容 for(std::vector::iterator it = order.m_order_items.begin(); it != order.m_order_items.end(); it++) { std::string food_name = (*it).m_food_name; std::string food_price = (*it).m_item_price; std::string quantity = (*it).m_quantity; //计算总价 double item_price = atof(food_price.c_str()) * atof(quantity.c_str()); std::string food_total_price = CLewaimaiString::DoubleToString(item_price, 2); if (food_total_price == "0.00") { //这里是特殊处理满赠的展示 food_total_price = ""; } food_name = CLewaimaiString::UTF8ToANSI(food_name); //先输出商品名字 std::vector m_names; if(guige == "58") { m_names = HandleFoodname(food_name, 1); } else { m_names = HandleFoodname(food_name, 2); } std::string firstLine = m_names[0]; int nGuige; if(guige == "58") { nGuige = 1; } else { nGuige = 2; } std::string priceShow = HandleFoodItemPrice(food_price, nGuige); std::string quantityShow = HandleFoodQuantity(quantity, nGuige); std::string priceTotalShow = HandleFoodTotalPrice(food_total_price, nGuige); std::string firstLineShow = firstLine + priceShow + quantityShow + priceTotalShow; POS_TextOut(firstLineShow, false, setting_printer_shangpin_big); POS_FeedLine(); for(std::vector::iterator it = m_names.begin() + 1; it != m_names.end(); it++) { POS_TextOut((*it), false, setting_printer_shangpin_big); POS_FeedLine(); } } //判断是否有备注 if(order.m_memo.length() > 0) { bool setting_printer_memo_big = false; if(CSetting::GetParam("setting_printer_memo_big") == "1") { setting_printer_memo_big = true; } POS_FeedLine(); string address = "顾客备注:" + CLewaimaiString::UTF8ToANSI(order.m_memo); POS_TextOut(address, false, setting_printer_memo_big); POS_FeedLine(); } //结束商品详情打印 POS_TextOut(lines); POS_FeedLine(); //开始打印其他的费用 bool is_other_money = false; bool setting_printer_price_big = false; if(CSetting::GetParam("setting_printer_price_big") == "1") { setting_printer_price_big = true; } if(order.m_delivery > 0) { string delivery = "配送费:" + CLewaimaiString::DoubleToString((double)order.m_delivery, 2); POS_TextOut(delivery, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } if(order.m_is_dabao == "1") { string dabao = "打包费:" + CLewaimaiString::UTF8ToANSI(order.m_dabao_money); POS_TextOut(dabao, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } //开始显示增值服务费 if(order.m_addservie.size() > 0) { for(std::vector::iterator it = order.m_addservie.begin(); it != order.m_addservie.end(); it++) { string addservice = CLewaimaiString::UTF8ToANSI((*it).name) + ":" + CLewaimaiString::DoubleToString((double)atof((*it).value.c_str()), 2); POS_TextOut(addservice, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } is_other_money = true; } if(order.m_discount < 10) { string discount = "打折:" + CLewaimaiString::DoubleToString((double)order.m_discount, 2) + "折"; POS_TextOut(discount, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } if(order.m_is_member_discount == "1") { string member_discount = "会员优惠:-" + order.m_member_discount; POS_TextOut(member_discount, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } if(order.m_is_firstcut == "1") { string firstcut = "首单优惠:-" + order.m_firstcut_value; POS_TextOut(firstcut, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } //满减 string::size_type position = order.m_promotion.find(":"); if(position != order.m_promotion.npos) { string promotion_value; promotion_value.assign(order.m_promotion, position + 1); string promotion = "满减优惠:-" + CLewaimaiString::DoubleToString((double)(atof(promotion_value.c_str())), 2); POS_TextOut(promotion, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } if(order.m_coupon > 0) { string coupon = "优惠券:-" + CLewaimaiString::DoubleToString((double)order.m_coupon, 2); POS_TextOut(coupon, false, setting_printer_price_big); POS_FeedLine(); is_other_money = true; } if(is_other_money) { POS_TextOut(lines); POS_FeedLine(); } //最后显示总价 POS_TextOut("总计:¥" + CLewaimaiString::DoubleToString(order.m_price, 2), false, setting_printer_price_big, 2); POS_FeedLine(); //显示付款方式 bool setting_printer_pay_big = false; if(CSetting::GetParam("setting_printer_pay_big") == "1") { setting_printer_pay_big = true; } POS_TextOut("支付方式:" + CLewaimaiString::UTF8ToANSI(order.m_pay_type), false, setting_printer_pay_big, 2); POS_FeedLine(); POS_FeedLine();; POS_FeedLine(); //准备开始打印二维码 std::string order_no = order.m_order_no; order_no = CLewaimaiString::UTF8ToANSI(order_no); if (order.m_show_qiangdan_qrcode == "1") { POS_OutQRCode(order_no); POS_FeedLine(); POS_FeedLine(); POS_TextOut("请使用配送员app扫码绑定订单", false, false, 1); } //走纸几行再切 POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_CutPaper(); } //还原打印机初始设置,有些傻逼收银设备居然不是自动调用,比如哗啦啦 POS_Reset(); //关闭设备 for(std::vector::iterator it = m_hPorts.begin(); it != m_hPorts.end(); it++) { CloseHandle((*it).hPort); } if (m_type == 2) { m_socket.close(); } LOG_INFO("_______________________________结束打印收银小票,订单编号:" << order.m_order_num.c_str() << "_________________________"); LOG_INFO(" "); } void CPosPrinter::PrintWaimaiOrderBiaoqian(CWaimaiOrder& order) { m_type = 1; std::string printer_usb = CSetting::GetParam("setting_biaoqian_printer_usb"); std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb); //读取标签纸的规格和方向 int biaoqian_width, biaoqian_height; std::string printer_guige = CSetting::GetParam("setting_biaoqian_printer_guige"); if (printer_guige == "40*30mm") { biaoqian_width = 40; biaoqian_height = 30; } else if (printer_guige == "35*25mm") { biaoqian_width = 35; biaoqian_height = 25; } else if (printer_guige == "30*25mm") { biaoqian_width = 30; biaoqian_height = 25; } else if (printer_guige == "30*20mm") { biaoqian_width = 30; biaoqian_height = 20; } else { biaoqian_width = 40; biaoqian_height = 30; } int nDIRECTION; std::string printer_fangxiang = CSetting::GetParam("setting_biaoqian_printer_fangxiang"); if (printer_fangxiang == "1") { nDIRECTION = 1; } else { nDIRECTION = 0; } //连接usb端口 InitOneUsb(ws_printer_usb); //初始化标签打印机 BIAOQIAN_Reset(biaoqian_width, biaoqian_height, nDIRECTION); std::vector cur_printer_use = order.m_order_items; //先计算商品的总数量 int foodNum = 0; for(std::vector::iterator it = cur_printer_use.begin(); it != cur_printer_use.end(); it++) { std::string quantity = (*it).m_quantity; foodNum += atoi(quantity.c_str()); } //商品内容 int curFoodNum = 0; for(std::vector::iterator it = cur_printer_use.begin(); it != cur_printer_use.end(); it++) { std::string food_name = (*it).m_food_name; std::string food_price = (*it).m_item_price; std::string quantity = (*it).m_quantity; //每份商品打印一个标签 int nQuantity = atoi(quantity.c_str()); for(int i = 0; i < nQuantity; i++) { std::string textData = ""; curFoodNum++; //打印小票自定义名称 string printer_tip_name = CLewaimaiString::UTF8ToANSI(order.m_printer_tip_name); if (printer_tip_name.length() == 0) { printer_tip_name = "外卖"; } std::string restaurant_number = order.m_restaurant_number; std::string order_num_info = printer_tip_name + " #" + CLewaimaiString::UTF8ToANSI(restaurant_number); //纸张宽度40mm的,是 320个点位(每mm8个),刚好可以放13个汉字,每个汉字宽度差不多是24,商品换行显示的时候, //每行最多12个汉字,也就是空24个,因此这里设置12,刚好左右各空一半 textData += BIAOQIAN_TEXTGet(order_num_info, 12, 6, 1, 1); //打印份数 std::string numInfo = to_string(curFoodNum) + "/" + to_string(foodNum); textData += BIAOQIAN_TEXTGet(numInfo, 180, 6, 1, 1); //每行最多显示12个汉字,这里要计算一下换行(要先转成ANSI格式) std::string handle_food_name = CLewaimaiString::UTF8ToANSI(food_name); std::vector foodNameVector = HandleBiaoqianFoodname(handle_food_name, biaoqian_width); int nRow = 0; //考虑是否用大号字体 bool is_big_name = false; if(foodNameVector.size() <= 2) { //不超过2行,可以用大的字体 is_big_name = true; } //LOG_INFO("foodNameVector size:" << foodNameVector.size()); for(std::vector::iterator it = foodNameVector.begin(); it != foodNameVector.end(); it++) { //LOG_INFO("nRow:" << nRow << ", 准备打印商品名字:" << (*it).c_str()); if(is_big_name) { textData += BIAOQIAN_TEXTGet(*it, 12, 42 + 60 * nRow, 1, 2); } else { textData += BIAOQIAN_TEXTGet(*it, 12, 42 + 30 * nRow, 1, 1); } nRow++; } int nPriceY; if (biaoqian_height == 30) { nPriceY = 170; } else if (biaoqian_height == 25) { nPriceY = 130; } else if (biaoqian_height == 20) { nPriceY = 90; } //打印价格 std::string priceInfo = CLewaimaiString::UTF8ToANSI(food_price) + "元"; textData += BIAOQIAN_TEXTGet(priceInfo, 12, nPriceY, 1, 1); //打印订单号 std::string order_num = "订单号:" + CLewaimaiString::UTF8ToANSI(order.m_order_num); textData += BIAOQIAN_TEXTGet(order_num, 12, nPriceY + 30, 1, 1); WriteData(textData); BIAOQIAN_PRINT(); BIAOQIAN_CLS(); } } } void CPosPrinter::PrintWaimaiOrderChufang(CWaimaiOrder& order) { //设置模式,后面输出数据不会错 m_type = 2; //读取厨房打印机信息 std::vector total_printers = CSetting::getChufangPrints(); for(std::vector::iterator it = total_printers.begin(); it != total_printers.end(); it++) { ChufangPrinter printer = *it; std::string ip = printer.ip; //初始化连接 try { boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(ip.c_str()), 9100); m_socket.connect(ep); } catch(std::exception& e) { std::string err = e.what(); LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str()); MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK); //连接失败了,处理下一个厨房打印机 continue; } std::string guige = printer.guige; std::string fendan = printer.fendan; std::string fenlei = printer.fenlei; std::string fenlei_ids = printer.fenlei_ids; std::vector cur_printer_use; if (fenlei == "0") { cur_printer_use = order.m_order_items; } else { //如果开启了分类打印,就要比对了 std::map ids_map; std::vector ids = CLewaimaiString::Split(fenlei_ids, ","); for (std::vector::iterator it = ids.begin(); it != ids.end(); it++) { ids_map[(*it)] = true; } for (std::vector::iterator it = order.m_order_items.begin(); it != order.m_order_items.end(); it++) { if (ids_map.find((*it).m_type_id) != ids_map.end()) { //如果当前商品的分类,在厨房打印机设置的分类里面,才加入 cur_printer_use.push_back(*it); } } } if (cur_printer_use.size() == 0) { //如果这个厨房打印机没有商品可以打印(开启了商品分类打印可能出现),就直接跳过 m_socket.close(); continue; } if(fendan == "0") { POS_Reset(); POS_TextOut("派工单", true, true, 1); POS_FeedLine(); POS_FeedLine(); string order_type = "#" + order.m_restaurant_number + " "; if(order.m_is_selftake == "1") { POS_TextOut(order_type + "到店自取订单", false, true, 1); POS_FeedLine(); POS_FeedLine(); } else { POS_TextOut(order_type + "外卖订单", false, true, 1); POS_FeedLine(); POS_FeedLine(); } //预设选项 if(order.m_order_field.size() > 1) { for(std::vector::iterator it = order.m_order_field.begin(); it != order.m_order_field.end() - 1; it++) { string order_field = CLewaimaiString::UTF8ToANSI((*it).name) + ":" + CLewaimaiString::UTF8ToANSI((*it).value); POS_TextOut(order_field, false, true, 0); POS_FeedLine(); } } //准备开始打印商品详情 string lines; if(guige == "58") { lines = "--------------------------------"; } else { lines = "------------------------------------------------"; } POS_TextOut(lines); POS_FeedLine(); //商品标题 if(guige == "58") { POS_TextOut("商品 单价 数量 金额", false, true); } else { POS_TextOut("商品 单价 数量 金额", false, true); } POS_FeedLine(); //商品内容 for(std::vector::iterator it = cur_printer_use.begin(); it != cur_printer_use.end(); it++) { std::string food_name = (*it).m_food_name; std::string food_price = (*it).m_item_price; std::string quantity = (*it).m_quantity; //计算总价 double item_price = atof(food_price.c_str()) * atof(quantity.c_str()); std::string food_total_price = CLewaimaiString::DoubleToString(item_price, 2); food_name = CLewaimaiString::UTF8ToANSI(food_name); //先输出商品名字 std::vector m_names; if(guige == "58") { m_names = HandleFoodname(food_name, 1); } else { m_names = HandleFoodname(food_name, 2); } std::string firstLine = m_names[0]; int nGuige; if(guige == "58") { nGuige = 1; } else { nGuige = 2; } std::string priceShow = HandleFoodItemPrice(food_price, nGuige); std::string quantityShow = HandleFoodQuantity(quantity, nGuige); std::string priceTotalShow = HandleFoodTotalPrice(food_total_price, nGuige); std::string firstLineShow = firstLine + priceShow + quantityShow + priceTotalShow; POS_TextOut(firstLineShow, false, true, 0); POS_FeedLine(); for(std::vector::iterator it = m_names.begin() + 1; it != m_names.end(); it++) { POS_TextOut((*it), false, true, 0); POS_FeedLine(); } } //判断是否有备注 if(order.m_memo.length() > 0) { POS_FeedLine(); string address = "顾客备注:" + CLewaimaiString::UTF8ToANSI(order.m_memo); POS_TextOut(address, false, true, 0); POS_FeedLine(); } //结束商品详情打印 POS_TextOut(lines); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_CutPaper(); //还原打印机初始设置,有些傻逼收银设备居然不是自动调用,比如哗啦啦 POS_Reset(); } else { POS_Reset(); //分单模式下,每个商品打印一张单 for(std::vector::iterator it = cur_printer_use.begin(); it != cur_printer_use.end(); it++) { POS_TextOut("派工单", true, true, 1); POS_FeedLine(); POS_FeedLine(); string order_type = "#" + order.m_restaurant_number + " "; if(order.m_is_selftake == "1") { POS_TextOut(order_type + "到店自取订单", false, true, 1); POS_FeedLine(); POS_FeedLine(); } else { POS_TextOut(order_type + "外卖订单", false, true, 1); POS_FeedLine(); POS_FeedLine(); } //预设选项 if(order.m_order_field.size() > 1) { for(std::vector::iterator it = order.m_order_field.begin(); it != order.m_order_field.end() - 1; it++) { string order_field = CLewaimaiString::UTF8ToANSI((*it).name) + ":" + CLewaimaiString::UTF8ToANSI((*it).value); POS_TextOut(order_field, false, true, 0); POS_FeedLine(); } } //准备开始打印商品详情 string lines; if(guige == "58") { lines = "--------------------------------"; } else { lines = "------------------------------------------------"; } POS_TextOut(lines); POS_FeedLine(); //商品标题 if(guige == "58") { POS_TextOut("商品 单价 数量 金额", false, true); } else { POS_TextOut("商品 单价 数量 金额", false, true); } POS_FeedLine(); std::string food_name = (*it).m_food_name; std::string food_price = (*it).m_item_price; std::string quantity = (*it).m_quantity; //计算总价 double item_price = atof(food_price.c_str()) * atof(quantity.c_str()); std::string food_total_price = CLewaimaiString::DoubleToString(item_price, 2); food_name = CLewaimaiString::UTF8ToANSI(food_name); //先输出商品名字 std::vector m_names; if(guige == "58") { m_names = HandleFoodname(food_name, 1); } else { m_names = HandleFoodname(food_name, 2); } std::string firstLine = m_names[0]; std::string priceShow = HandleFoodItemPrice(food_price, 2); std::string quantityShow = HandleFoodQuantity(quantity, 2); std::string priceTotalShow = HandleFoodTotalPrice(food_total_price, 2); std::string firstLineShow = firstLine + priceShow + quantityShow + priceTotalShow; POS_TextOut(firstLineShow, false, true, 0); POS_FeedLine(); for(std::vector::iterator it = m_names.begin() + 1; it != m_names.end(); it++) { POS_TextOut((*it), false, true, 0); POS_FeedLine(); } //判断是否有备注 if(order.m_memo.length() > 0) { POS_FeedLine(); string address = "顾客备注:" + CLewaimaiString::UTF8ToANSI(order.m_memo); POS_TextOut(address, false, true, 0); POS_FeedLine(); } //结束商品详情打印 POS_TextOut(lines); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_FeedLine(); POS_CutPaper(); } //还原打印机初始设置,有些傻逼收银设备居然不是自动调用,比如哗啦啦 POS_Reset(); } m_socket.close(); } } std::vector CPosPrinter::getUsbDevices() { return m_usb_devices; } int CPosPrinter::WriteData(string msg) { return WriteBuf((unsigned char*)msg.c_str(), msg.length()); } /* *这个函数只负责把数据拼接到打印缓存里面,不负责实际的发送数据 **/ int CPosPrinter::WriteBuf(const unsigned char* buf, int len) { if(m_type == 1) { //USB、串口、并口,走这里 for(std::vector::iterator it = m_hPorts.begin(); it != m_hPorts.end(); it++) { HANDLE hPort = (*it).hPort; //同步写数据 DWORD dwWrite; BOOL ret = WriteFile(hPort, buf, len, &dwWrite, NULL); if (!ret) { LOG_INFO("WriteFile Failed!, hPort:"<width; unsigned int unWidthAdjusted = unWidth * 8; unsigned int unHeightAjusted = unWidthAdjusted; unsigned char* realData = new unsigned char[unWidthAdjusted * unHeightAjusted]; memset(realData, 0, unWidthAdjusted * unHeightAjusted); unsigned char* pSourceData = qrCode->data; for (unsigned int i = 0; i < unHeightAjusted; i++) { int realHeight = i / 8; for (unsigned int j = 0; j < unWidthAdjusted; j++) { int realWeight = j / 8; if (pSourceData[unWidth * realHeight + realWeight] & 1) { //表示这个像素要打印 realData[unWidthAdjusted * i + j] = 1; } else { realData[unWidthAdjusted * i + j] = 0; } } } //设置行间距为0 unsigned char data[3] = { 0x1B, 0x33, 0x00 }; WriteBuf(data, 3); //设置图像居中对齐 unsigned char data2[3] = { 0x1B, 0x61, 0x01 }; WriteBuf(data2, 3); //选择位图模式 unsigned char escBmp[5] = { 0x1B, 0x2A, 0x21, 0x00, 0x00 }; escBmp[3] = (unsigned char)(unWidthAdjusted % 256); escBmp[4] = (unsigned char)(unWidthAdjusted / 256); //换行符,每打印一行都要发送这个,不然有些尺寸下图片会乱掉 unsigned char change_line_tag = '\n'; //存储每行数据的结构 unsigned char* dataTmp = new unsigned char[unWidthAdjusted * 3]; //循环图片像素打印图片 for (unsigned int i = 0; i < (unHeightAjusted / 24 + 1); i++) { //设置模式为位图模式 WriteBuf(escBmp, 5); //重新开始打印一行,置零 memset(dataTmp, 0, unWidthAdjusted * 3); //循环宽 for (unsigned int j = 0; j < unWidthAdjusted; j++) { for (unsigned int k = 0; k < 24; k++) { //找到有像素的区域,也就是未超出位图高度的区域 if (((i * 24) + k) < unHeightAjusted) { if (realData[unWidthAdjusted * (i * 24 + k) + j] == 1) { //如果本来是黑色的像素,那么就把对应的数据位设置为1 dataTmp[j * 3 + k / 8] += (unsigned char)(128 >> (k % 8)); } } } } WriteBuf(dataTmp, unWidthAdjusted * 3); //换行符,这里必须要发这个,不然图片会乱 WriteBuf(&change_line_tag, 1); } WriteBuf(&change_line_tag, 1); //还原默认的行间距 unsigned char data3[2] = { 0x1B, 0x32 }; WriteBuf(data3, 2); delete[] dataTmp; QRcode_free(qrCode); delete[] realData; return ; } void CPosPrinter::POS_OutBmp(std::wstring ImagePath) { //初始化 POS_Reset(); //设置行间距为0 unsigned char data[3] = { 0x1B, 0x33, 0x00 }; WriteBuf(data, 3); //设置图像居中对齐 unsigned char data2[3] = { 0x1B, 0x61, 0x01 }; WriteBuf(data2, 3); CBitmapHelper helper; helper.LoadImage(ImagePath.c_str()); Bitmap* bmp = helper.getBmp(); //先进行图片预处理 unsigned int nWidth = bmp->GetWidth(); unsigned int nHeight = bmp->GetHeight(); //压缩尺寸 if (nWidth > 380) { int newWidth = 380; int newHeight = (int)(nHeight / (nWidth / 380.0)); helper.ScaleBitmap(newWidth, newHeight);; nWidth = newWidth; nHeight = newHeight; } //二值化 helper.Image2Values(); //获得最新的图像指针 bmp = helper.getBmp(); //选择位图模式 unsigned char escBmp[5] = { 0x1B, 0x2A, 0x21, 0x00, 0x00 }; escBmp[3] = (unsigned char)(nWidth % 256); escBmp[4] = (unsigned char)(nWidth / 256); Gdiplus::Color pixelColor; //换行符,每打印一行都要发送这个,不然有些尺寸下图片会乱掉 unsigned char change_line_tag = '\n'; //存储每行数据的结构 unsigned char* dataTmp = new unsigned char[nWidth * 3]; //循环图片像素打印图片 for (unsigned int i = 0; i < (nHeight / 24 + 1); i++) { //设置模式为位图模式 WriteBuf(escBmp, 5); //重新开始打印一行,置零 memset(dataTmp, 0, nWidth * 3); //循环宽 for (unsigned int j = 0; j < nWidth; j++) { for (unsigned int k = 0; k < 24; k++) { //找到有像素的区域,也就是未超出位图高度的区域 if (((i * 24) + k) < nHeight) { bmp->GetPixel(j, (i * 24) + k, &pixelColor); unsigned char r = pixelColor.GetR(); if (r == 0) { //如果本来是黑色的像素,那么就把对应的数据位设置为1 dataTmp[j * 3 + k / 8] += (unsigned char)(128 >> (k % 8)); } } } } WriteBuf(dataTmp, nWidth * 3); //换行符,这里必须要发这个,不然图片会乱 WriteBuf(&change_line_tag, 1); } WriteBuf(&change_line_tag, 1); //还原默认的行间距 unsigned char data3[2] = { 0x1B, 0x32 }; WriteBuf(data3, 2); delete[] dataTmp; } void CPosPrinter::BIAOQIAN_Reset(int nWidth, int nHeight, int nDirection) { char endTag[3] = {0x0d, 0x0a, 0x00}; std::string size = "SIZE " + to_string(nWidth) + " mm," + to_string(nHeight) + " mm"; size += endTag; std::string gap = "GAP 2 mm,0 mm"; gap += endTag; std::string speed = "SPEED 4.0"; speed += endTag; std::string density = "DENSITY 12"; density += endTag; std::string DIRECTION = "DIRECTION " + to_string(nDirection); DIRECTION += endTag; std::string REFERENCE = "REFERENCE 0,0"; REFERENCE += endTag; std::string PEER = "SET PEEL OFF"; PEER += endTag; std::string TEAR = "SET TEAR ON"; TEAR += endTag; std::string cls = "CLS"; cls += endTag; std::string data = size + gap + speed + density + DIRECTION + REFERENCE + PEER + TEAR + cls; WriteData(data); } /* *前进一张纸 **/ void CPosPrinter::BIAOQIAN_FORMFEED() { char endTag[3] = { 0x0d, 0x0a, 0x00 }; std::string formfeed = "FORMFEED"; formfeed += endTag; WriteData(formfeed); } void CPosPrinter::BIAOQIAN_TEXTOUT(std::string content, int x, int y, int x_multiplication, int y_multiplication) { char endTag[3] = { 0x0d, 0x0a, 0x00 }; string text = "TEXT "; text += to_string(x) + "," + to_string(y) + ","; text += "\"TSS24.BF2\","; text += to_string(0) + ","; text += to_string(x_multiplication) + "," + to_string(y_multiplication) + ","; text += "\"" + content + "\""; text += endTag; WriteData(text); } std::string CPosPrinter::BIAOQIAN_TEXTGet(std::string content, int x, int y, int x_multiplication, int y_multiplication) { char endTag[3] = { 0x0d, 0x0a, 0x00 }; string text = "TEXT "; text += to_string(x) + "," + to_string(y) + ","; text += "\"TSS24.BF2\","; text += to_string(0) + ","; text += to_string(x_multiplication) + "," + to_string(y_multiplication) + ","; text += "\"" + content + "\""; text += endTag; return text; } void CPosPrinter::BIAOQIAN_PRINT() { char endTag[3] = { 0x0d, 0x0a, 0x00 }; std::string print = "PRINT 1"; print += endTag; WriteData(print); } void CPosPrinter::BIAOQIAN_CLS() { char endTag[3] = { 0x0d, 0x0a, 0x00 }; std::string cls = "CLS"; cls += endTag; WriteData(cls); } void CPosPrinter::CalWord(string s, int& nHanzi, int& nZimu) { nHanzi = 0; nZimu = 0; const char* buffer = s.c_str(); while(*buffer != '\0') { if(!(*buffer >= 0 && *buffer <= 127)) { //汉字 buffer++; buffer++; nHanzi++; } else { //字母 buffer++; nZimu++; } } } /* *规格 1:58mm 2:80mm **/ std::vectorCPosPrinter::HandleFoodname(std::string oldname, int guige) { std::vector newnameArray; int nHanzi, nZimu; CalWord(oldname, nHanzi, nZimu); int nWidth = nHanzi * 2 + nZimu; int maxWidth; if(guige == 1) { maxWidth = 15; } else { maxWidth = 28; } if(nWidth <= maxWidth) { //对于nWidth补空格 for(int i = 0; i < maxWidth - nWidth; i++) { oldname += " "; } newnameArray.push_back(oldname); return newnameArray; } //宽度大于15的情况,如果超过了,就要进行换行截取 const char* s = oldname.c_str(); int nTmp = 0; int nTotal = 0; while(*s != '\0') { if(!(*s >= 0 && *s <= 127)) { //汉字的情况 s++; nTmp++; nTotal++; s++; nTmp++; nTotal++; } else { //字母的情况 s++; nTmp++; nTotal++; } if(nTmp == maxWidth) { //这里开始要换行了 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); newnameArray.push_back(newnameItem); nTmp = 0; } else if(nTmp == maxWidth - 1) { //如果是第14个了,判断下一个是不是中文,如果是的话也要换行 if(!(*(s + 1) >= 0 && *(s + 1) <= 127)) { //下一个是中文,也要换行了,补齐一个空格 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); newnameItem += " "; newnameArray.push_back(newnameItem); nTmp = 0; } } } if(nTmp > 0) { //处理分隔后的最后一行 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); for(int i = 0; i < maxWidth - nTmp; i++) { newnameItem += " "; } newnameArray.push_back(newnameItem); } return newnameArray; } std::string CPosPrinter::HandleFoodItemPrice(std::string oldprice, int guige) { double price = atof(oldprice.c_str()); if(price < 10.00) { //单位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else if(price > 9.99 && price < 100.00) { //双位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else if(price > 99.99 && price < 1000.00) { //三位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else { //四位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } } std::string CPosPrinter::HandleFoodQuantity(std::string oldquantity, int guige) { int n = atoi(oldquantity.c_str()); if(n < 10) { if(guige == 1) { return " " + oldquantity; } else { return " " + oldquantity; } } else if(n >= 10 && n <= 99) { if(guige == 1) { return " " + oldquantity; } else { return " " + oldquantity; } } else { if(guige == 1) { return "" + oldquantity; } else { return " " + oldquantity; } } } std::string CPosPrinter::HandleFoodTotalPrice(std::string oldprice, int guige) { double price = atof(oldprice.c_str()); if(price < 10.00) { //单位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else if(price > 9.99 && price < 100.00) { //双位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else if(price > 99.99 && price < 1000.00) { //三位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } else { //四位数 if(guige == 1) { return " " + oldprice; } else { return " " + oldprice; } } } std::vector CPosPrinter::HandleBiaoqianFoodname(std::string oldname, int nBiaoqianWidth) { std::vector newnameArray; int nHanzi, nZimu; CalWord(oldname, nHanzi, nZimu); //文字内容的实际宽度,1个汉字算2个宽度,1个英文或者数字、标点算1个(40mm宽度最多打印12个汉字 ) int nWidth = nHanzi * 2 + nZimu; //40 *30mmm的标签,宽度最大24 int maxWidth; if (nBiaoqianWidth == 40) { maxWidth = 24; } else if (nBiaoqianWidth == 35) { maxWidth = 21; } else if (nBiaoqianWidth == 30) { maxWidth = 18; } else { maxWidth = 24; } if(nWidth <= maxWidth) { //对于nWidth补空格 for(int i = 0; i < maxWidth - nWidth; i++) { oldname += " "; } newnameArray.push_back(oldname); return newnameArray; } //宽度大于15的情况,如果超过了,就要进行换行截取 const char* s = oldname.c_str(); int nTmp = 0; int nTotal = 0; while(*s != '\0') { if(!(*s >= 0 && *s <= 127)) { //汉字的情况 s++; nTmp++; nTotal++; s++; nTmp++; nTotal++; } else { //字母的情况 s++; nTmp++; nTotal++; } if(nTmp == maxWidth) { //这里开始要换行了 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); newnameArray.push_back(newnameItem); nTmp = 0; } else if(nTmp == maxWidth - 1) { //如果是第14个了,判断下一个是不是中文,如果是的话也要换行 if(!(*(s + 1) >= 0 && *(s + 1) <= 127)) { //下一个是中文,也要换行了,补齐一个空格 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); newnameItem += " "; newnameArray.push_back(newnameItem); nTmp = 0; } } } if(nTmp > 0) { //处理分隔后的最后一行 string newnameItem; newnameItem.assign(oldname, nTotal - nTmp, nTmp); for(int i = 0; i < maxWidth - nTmp; i++) { newnameItem += " "; } newnameArray.push_back(newnameItem); } return newnameArray; }