Explorar o código

打印走通了

zhangyang %!s(int64=6) %!d(string=hai) anos
pai
achega
f91dd7839f

BIN=BIN
bin/Win32/Debug/zhipuzi_pos_windows/zhipuzi_pos_windows.exe


+ 61 - 33
lewaimai_dispatch/helper/CLewaimaiString.h

@@ -1,8 +1,9 @@
 #pragma once
 
-using namespace std;
+#include <codecvt>
+#include <iostream>
 
-#include <Windows.h>
+using namespace std;
 
 class CLewaimaiString
 {
@@ -15,45 +16,72 @@ public:
 
 	static void trim(string &s);
 
-	//将string转换成wstring  
-	static wstring string2wstring(string str)
+	static std::string UnicodeToUTF8(const std::wstring & wstr)
 	{
-		wstring result;
-
-		//获取缓冲区大小,并申请空间,缓冲区大小按字符计算  
-		int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0);
-		TCHAR* buffer = new TCHAR[len + 1];
-
-		//多字节编码转换成宽字节编码  
-		MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), buffer, len);
-
-		//添加字符串结尾  
-		buffer[len] = '\0';
-
-		//删除缓冲区并返回值  
-		result.append(buffer);
+		std::string ret;
+		try {
+			std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
+			ret = wcv.to_bytes(wstr);
+		}
+		catch (const std::exception & e) {
+			std::cerr << e.what() << std::endl;
+		}
+		return ret;
+	}
 
-		delete[] buffer;
-		return result;
+	static std::wstring UTF8ToUnicode(const std::string & str)
+	{
+		std::wstring ret;
+		try {
+			std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
+			ret = wcv.from_bytes(str);
+		}
+		catch (const std::exception & e) {
+			std::cerr << e.what() << std::endl;
+		}
+		return ret;
 	}
 
-	//将wstring转换成string  
-	static string wstring2string(wstring wstr)
+	static std::string UnicodeToANSI(const std::wstring & wstr)
 	{
-		string result;
-		//获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的  
-		int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
-		char* buffer = new char[len + 1];
+		std::string ret;
+		std::mbstate_t state = {};
+		const wchar_t *src = wstr.data();
+		size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
+		if (static_cast<size_t>(-1) != len) {
+			std::unique_ptr< char[] > buff(new char[len + 1]);
+			len = std::wcsrtombs(buff.get(), &src, len, &state);
+			if (static_cast<size_t>(-1) != len) {
+				ret.assign(buff.get(), len);
+			}
+		}
+		return ret;
+	}
 
-		//宽字节编码转换成多字节编码  
-		WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
-		buffer[len] = '\0';
+	static std::wstring ANSIToUnicode(const std::string & str)
+	{
+		std::wstring ret;
+		std::mbstate_t state = {};
+		const char *src = str.data();
+		size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
+		if (static_cast<size_t>(-1) != len) {
+			std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
+			len = std::mbsrtowcs(buff.get(), &src, len, &state);
+			if (static_cast<size_t>(-1) != len) {
+				ret.assign(buff.get(), len);
+			}
+		}
+		return ret;
+	}
 
-		//删除缓冲区并返回值  
-		result.append(buffer);
+	static std::string UTF8ToANSI(const std::string & str)
+	{
+		return UnicodeToANSI(UTF8ToUnicode(str));
+	}
 
-		delete[] buffer;
-		return result;
+	static std::string ANSIToUTF8(const std::string & str)
+	{
+		return UnicodeToUTF8(ANSIToUnicode(str));
 	}
 };
 

+ 1 - 1
lewaimai_dispatch/lewaimai_dispatch_windows.vcxproj

@@ -132,7 +132,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(SolutionDir)lib\debug</AdditionalLibraryDirectories>
-      <AdditionalDependencies>DuiLib_ud.lib;log4cplusUD.lib;dbghelp.lib;libcurl.dll.a;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>DuiLib_ud.lib;log4cplusUD.lib;dbghelp.lib;libcurl.dll.a;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
     </Link>
     <PostBuildEvent>

+ 1 - 0
lewaimai_dispatch/order/CWaimaiOrder.cpp

@@ -50,6 +50,7 @@ void CWaimaiOrder::InitData(std::string order_id, std::string order_no)
 
 			m_order_id = data["id"].GetString();
 			m_shop_id = data["shop_id"].GetString();
+			m_restaurant_number = data["restaurant_number"].GetString();
 			m_customer_id = data["customer_id"].GetString();
 			m_customer_name = data["customer_name"].GetString();
 			m_phone = data["phone"].GetString();

+ 1 - 0
lewaimai_dispatch/order/CWaimaiOrder.h

@@ -37,6 +37,7 @@ public:
 public:
 	std::string m_order_id;
 	std::string m_shop_id;
+	std::string m_restaurant_number;
 	std::string m_customer_id;
 	std::string m_customer_name;
 	std::string m_phone;

+ 246 - 1
lewaimai_dispatch/tool/CPosPrinter.cpp

@@ -1,12 +1,257 @@
+#include "../pch/pch.h"
 #include "CPosPrinter.h"
 
-
+#include <winioctl.h>
+#include <setupapi.h>
 
 CPosPrinter::CPosPrinter()
 {
+    Init();
 }
 
 
 CPosPrinter::~CPosPrinter()
 {
 }
+
+bool CPosPrinter::Init()
+{
+    //遍历USB设备,找到POS打印机路径
+    //设备路径
+    TCHAR * szDevicePath[MAX_DEVICE];
+    //设置中文字符
+    setlocale(LC_CTYPE, "chs");
+    TCHAR* Port = NULL;
+
+    //分配需要的空间
+    for(int i = 0; i < MAX_DEVICE; i++)
+    {
+        szDevicePath[i] = new TCHAR[256];
+    }
+
+    //取设备路径
+    int nDevice = GetDevicePath((LPGUID)&USB_GUID, szDevicePath);
+    int i = 0;
+
+    while(i < nDevice)
+    {
+        Port = szDevicePath[i++];
+        LOG_INFO("device.Port = " << Port);
+    }
+
+    m_hPort = CreateFile(Port, GENERIC_READ | GENERIC_WRITE,
+                         0, NULL,
+                         OPEN_EXISTING,
+                         FILE_ATTRIBUTE_NORMAL, NULL);
+
+    if(m_hPort == INVALID_HANDLE_VALUE)
+    {
+        // 打开端口失败
+        return false;
+    }
+
+    return true;
+}
+
+void CPosPrinter::PrintWaimaiOrder(CWaimaiOrder& order)
+{
+    POS_Reset();
+    POS_SetMotionUnit(180, 180);
+
+	string shop_name = "#" + order.m_restaurant_number + "   " + CLewaimaiString::UTF8ToANSI(order.m_shop_name);
+    POS_S_TextOut(shop_name);
+    POS_FeedLine();
+
+	POS_FeedLine();
+	POS_FeedLine();
+   
+    POS_CutPaper();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+//获取CreateFile的USB端口号
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// 根据GUID获得设备路径
+// lpGuid: GUID指针
+// pszDevicePath: 设备路径指针的指针,用于返回找到的路径
+// 返回: 成功得到的设备路径个数,可能不止1个
+int CPosPrinter::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;
+    wstring 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.c_str()) != 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;
+}
+
+int CPosPrinter::WriteData(string meg)
+{
+    DWORD dwWrite;
+    return WriteFile(m_hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
+}
+
+int CPosPrinter::WriteBuf(char *buf, int len)
+{
+    DWORD dwWrite;
+    return WriteFile(m_hPort, buf, len, &dwWrite, NULL);
+}
+
+int CPosPrinter::POS_Reset(void)
+{
+    string s;
+    s = "\x1B\x40";
+    WriteData(s);
+    return 0;
+}
+
+int CPosPrinter::POS_FeedLine(void)
+{
+    string s;
+    s = "\x0A";
+    WriteData(s);
+    return 0;
+}
+
+int CPosPrinter::POS_SetMotionUnit(int x, int y)
+{
+    string s;
+    s = "\x1D\x50\xB4\xB4";
+    WriteData(s);
+    s = "\x1B\x53";
+    WriteData(s);
+    return 0;
+}
+
+int CPosPrinter::POS_S_TextOut(string &abc)
+{
+    string s;
+    char SetAbsPos[4] = { 0x1B, 0x24, 0x46, 0x00 };
+    WriteBuf(SetAbsPos, 4);
+    char SelctFontType[3] = { 0x1B, 0x4D, 0x03 };
+    WriteBuf(SelctFontType, 3);
+    char SelctOutMode[3] = { 0x1D, 0x21, 0x00 };
+    WriteBuf(SelctOutMode, 3);
+    WriteData(abc);
+    return 0;
+}
+
+int CPosPrinter::POS_CutPaper()
+{
+    char CutPaperMode[4] = { 0x1D, 0x56, 0x41, 0x00 };
+    WriteBuf(CutPaperMode, 4);
+    return 0;
+}
+
+int CPosPrinter::POS_OutQRCode()
+{
+    char  QRCode1[8] = { 0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x43, 0x05 };
+    char  QRCode2[16] = { 0x1d, 0x28, 0x6b, 0x0b, 0x00, 0x31, 0x50, 0x30, 0x47, 0x70, 0x72, 0x69,
+                          0x6e, 0x74, 0x65, 0x72
+                        };
+    char  QRCode3[8] = { 0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x51, 0x30 };
+    WriteBuf(QRCode1, 8);
+    WriteBuf(QRCode2, 16);
+    WriteBuf(QRCode3, 8);
+    return 0;
+}

+ 29 - 6
lewaimai_dispatch/tool/CPosPrinter.h

@@ -1,16 +1,39 @@
 #pragma once
 
+#include "../pch/pch.h"
 #include "../order/CWaimaiOrder.h"
 
+//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}};
+
 class CPosPrinter
 {
 public:
-	CPosPrinter();
-	~CPosPrinter();
+    CPosPrinter();
+    ~CPosPrinter();
+
+	bool Init();
+    void PrintWaimaiOrder(CWaimaiOrder& order);
+
+private:
+	int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath);
+	int WriteData(string meg);
+	int WriteBuf(char *buf, int len);
 
-	void PrintWaimaiOrder(CWaimaiOrder& order)
-	{
+	int POS_Reset(void);
+	int POS_FeedLine(void);
+	int POS_SetMotionUnit(int x, int y);
+	int POS_S_TextOut(string &abc);
+	int POS_CutPaper();
+	int POS_OutQRCode();
 
-	}
-};
 
+private:
+	HANDLE m_hPort = NULL;
+};

+ 3 - 3
lewaimai_dispatch/wnd/CLoginWnd.cpp

@@ -19,8 +19,8 @@ void CLoginFrameWnd::HandleLogin()
 
     LOG_INFO("account:" << account.c_str() << ", password:" << password.c_str());
 
-    string s_account = CLewaimaiString::wstring2string(account);
-    string s_password = CLewaimaiString::wstring2string(password);
+    string s_account = CLewaimaiString::UnicodeToUTF8(account);
+    string s_password = CLewaimaiString::UnicodeToUTF8(password);
 
     CZhipuziHttpClient::Init(s_account, s_password);
 
@@ -48,7 +48,7 @@ void CLoginFrameWnd::HandleLogin()
         //登录失败了
         CLabelUI* pLoginResultLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("loginresult")));
 
-        pLoginResultLabel->SetText(std::wstring(_T("登录失败:") + CLewaimaiString::string2wstring(errmsg)).c_str());
+        pLoginResultLabel->SetText(std::wstring(_T("登录失败:") + CLewaimaiString::UTF8ToUnicode(errmsg)).c_str());
         pLoginResultLabel->SetVisible(true);
     }
 }

+ 6 - 6
lewaimai_dispatch/wnd/CWaimaiOrderItemUI.h

@@ -19,22 +19,22 @@ public:
 
 		m_orderid = orderinfo["id"].GetString();
 
-		std::wstring name_show = L"姓名:" + CLewaimaiString::string2wstring(m_name);
+		std::wstring name_show = L"姓名:" + CLewaimaiString::UTF8ToUnicode(m_name);
 		this->FindSubControl(L"waimai_order_list_name")->SetText(name_show.c_str());
 
-		std::wstring address_show = L"地址:" + CLewaimaiString::string2wstring(m_address);
+		std::wstring address_show = L"地址:" + CLewaimaiString::UTF8ToUnicode(m_address);
 		this->FindSubControl(L"waimai_order_list_address")->SetText(address_show.c_str());
 
-		std::wstring phone_show = L"电话:" + CLewaimaiString::string2wstring(m_phone);
+		std::wstring phone_show = L"电话:" + CLewaimaiString::UTF8ToUnicode(m_phone);
 		this->FindSubControl(L"waimai_order_list_phone")->SetText(phone_show.c_str());
 
-		std::wstring price_show = L"价格:" + CLewaimaiString::string2wstring(m_price);
+		std::wstring price_show = L"价格:" + CLewaimaiString::UTF8ToUnicode(m_price);
 		this->FindSubControl(L"waimai_order_list_price")->SetText(price_show.c_str());
 
-		std::wstring order_no_show = L"订单号:" + CLewaimaiString::string2wstring(m_order_no);
+		std::wstring order_no_show = L"订单号:" + CLewaimaiString::UTF8ToUnicode(m_order_no);
 		this->FindSubControl(L"waimai_order_list_order_no")->SetText(order_no_show.c_str());
 
-		std::wstring init_date_show = L"下单时间:" + CLewaimaiString::string2wstring(m_init_date);
+		std::wstring init_date_show = L"下单时间:" + CLewaimaiString::UTF8ToUnicode(m_init_date);
 		this->FindSubControl(L"waimai_order_list_init_date")->SetText(init_date_show.c_str());
 	}