张洋 2 dienas atpakaļ
vecāks
revīzija
87547fc8df

+ 1 - 1
bin/Win32/Debug/zhipuzi_pos_windows/skin/chengzhong_wnd.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Window size="700,434" caption="0,0,0,44" roundcorner="4,4" >
+<Window size="700,434" caption="0,0,0,44" roundcorner="4,4" shadowsize="3" showshadow="true">
 	<Font id="0" name="微软雅黑" size="26" />
 	<Font id="1" name="微软雅黑" size="32" />
 	<Font id="2" name="微软雅黑" size="22" />

+ 111 - 107
zhipuzi_pos_windows/print/CPosPrinterQueue.cpp

@@ -1,9 +1,9 @@
-#include "../pch/pch.h"
+#include "../pch/pch.h"
 #include "CPosPrinterQueue.h"
 
 #include "../helper/CComHelper.h"
 
-//boost库的头文件
+//boost库的头文件
 #include <boost/asio.hpp>
 #include <boost/asio/io_context.hpp>
 using boost::asio::ip::tcp;
@@ -19,13 +19,13 @@ void CPosPrinterQueue::StartWork()
 
 	m_nStopNum = 0;
 
-	//处理收银打印
+	//澶勭悊鏀堕摱鎵撳嵃
 	std::thread(&CPosPrinterQueue::HandleShouyinPrinter, this).detach();
 
-	//处理标签打印
+	//澶勭悊鏍囩�鎵撳嵃
 	std::thread(&CPosPrinterQueue::HandleBiaoqianPrinter, this).detach();
 
-	//处理厨房打印
+	//澶勭悊鍘ㄦ埧鎵撳嵃
 	std::thread(&CPosPrinterQueue::HandleChufangPrinter, this).detach();
 }
 
@@ -170,17 +170,17 @@ void CPosPrinterQueue::AddStopNum()
 
 	if (m_nStopNum == 8)
 	{
-		//确认所有子线程都退出了,再删除自己
+		//纭��鎵€鏈夊瓙绾跨▼閮介€€鍑轰簡锛屽啀鍒犻櫎鑷�繁
 		delete this;
 	}
 }
 
 void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
 {
-	//默认是句柄模式
+	//默认是句柄模式
 	int nType = 1;
 
-	//用于厨房打印机和网口类型的收银小票打印
+	//用于厨房打印机和网口类型的收银小票打印
 	boost::asio::io_context m_io;
 	boost::asio::ip::tcp::socket m_socket(m_io);
 
@@ -190,6 +190,10 @@ void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
 	{
 		InitUsb();
 
+		InitBingkou();
+
+		InitCom();
+
 		if (m_hShouyinPorts.size() == 0)
 		{
 			return;
@@ -220,12 +224,12 @@ void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
 	}
 	else if (printer_leixing == "wangkou")
 	{
-		//改为网口模式
+		//鏀逛负缃戝彛妯″紡
 		nType = 2;
 
 		std::string wangkou_ip = CSetting::GetInstance()->GetParam("setting_printer_wangkou_ip");
 
-		//初始化连接
+		//初始化连接
 		try
 		{
 			boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(wangkou_ip.c_str()), 9100);
@@ -234,51 +238,51 @@ void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
 		catch (std::exception& e)
 		{
 			std::string err = e.what();
-			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
+			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
 
-			MessageBoxW(NULL, (L"小票网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
+			MessageBoxW(NULL, (L"小票网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
 			return;
 		}
 	}
 
-	//开始发送数据
+	//开始发送数据
 	if (nType == 1)
 	{
-		//USB、串口、并口,走这里
+		//USB、串口、并口,走这里
 		for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
 		{
 			HANDLE hPort = *it;
 
-			//同步写数据
+			//同步写数据
 			DWORD dwWrite;
 
 			BOOL ret = WriteFile(hPort, data.c_str(), data.length(), &dwWrite, NULL);
 			if (!ret)
 			{
-				LOG_INFO("WriteFile Failed!, hPort:" << hPort);
+				LOG_INFO("WriteFile Failed!, hPort:" << hPort);
 			}
 		}
 	}
 	else
 	{
-		//网口走这里
+		//网口走这里
 		try
 		{
 			m_socket.write_some(boost::asio::buffer(data.c_str(), data.length()));
 		}
 		catch (const std::exception& e)
 		{
-			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 		}
 	}
 
-	//关闭设备
+	//鍏抽棴璁惧�
 	for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
 	{
 		CloseHandle(*it);
 	}
 
-	//删除之前旧的句柄
+	//鍒犻櫎涔嬪墠鏃х殑鍙ユ焺
 	m_hShouyinPorts.clear();
 
 	if (nType == 2)
@@ -289,10 +293,10 @@ void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
 
 void CPosPrinterQueue::SendDataToBiaoqianPirnter(std::string data)
 {
-	//默认是句柄模式
+	//默认是句柄模式
 	int nType = 1;
 
-	//用于厨房打印机和网口类型的收银小票打印
+	//用于厨房打印机和网口类型的收银小票打印
 	boost::asio::io_context m_io;
 	boost::asio::ip::tcp::socket m_socket(m_io);
 
@@ -303,7 +307,7 @@ void CPosPrinterQueue::SendDataToBiaoqianPirnter(std::string data)
 		std::string printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
 		std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb);
 
-		//连接usb端口
+		//杩炴帴usb绔�彛
 		bool ret = InitOneUsb(ws_printer_usb, 2);
 		if (ret == false)
 		{
@@ -312,12 +316,12 @@ void CPosPrinterQueue::SendDataToBiaoqianPirnter(std::string data)
 	}
 	else if (printer_leixing == "wangkou")
 	{
-		//改为网口模式
+		//鏀逛负缃戝彛妯″紡
 		nType = 2;
 
 		std::string wangkou_ip = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_wangkou_ip");
 
-		//初始化连接
+		//初始化连接
 		try
 		{
 			boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(wangkou_ip.c_str()), 9100);
@@ -326,45 +330,45 @@ void CPosPrinterQueue::SendDataToBiaoqianPirnter(std::string data)
 		catch (std::exception& e)
 		{
 			std::string err = e.what();
-			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
+			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
 
-			MessageBoxW(NULL, (L"标签网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
+			MessageBoxW(NULL, (L"标签网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
 			return;
 		}
 	}
 
-	//开始发送数据
+	//开始发送数据
 	if (nType == 1)
 	{
-		//USB、串口、并口,走这里
+		//USB、串口、并口,走这里
 		for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
 		{
 			HANDLE hPort = *it;
 
-			//同步写数据
+			//同步写数据
 			DWORD dwWrite;
 
 			BOOL ret = WriteFile(hPort, data.c_str(), data.length(), &dwWrite, NULL);
 			if (!ret)
 			{
-				LOG_INFO("WriteFile Failed!, hPort:" << hPort);
+				LOG_INFO("WriteFile Failed!, hPort:" << hPort);
 			}
 		}
 	}
 	else
 	{
-		//网口走这里
+		//网口走这里
 		try
 		{
 			m_socket.write_some(boost::asio::buffer(data.c_str(), data.length()));
 		}
 		catch (const std::exception& e)
 		{
-			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 		}
 	}
 
-	//关闭设备
+	//鍏抽棴璁惧�
 	for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
 	{
 		CloseHandle(*it);
@@ -383,13 +387,13 @@ void CPosPrinterQueue::SendDataToChufangPirnter(ChufangPrinterContent chufang_da
 	boost::asio::io_context m_io;
 	boost::asio::ip::tcp::socket m_socket(m_io);
 
-	//读取厨房打印机信息
+	//读取厨房打印机信息
 	std::vector<ChufangPrinter> total_printers = CSetting::GetInstance()->getChufangPrints();
 
 	std::string ip = chufang_data.ip;
 	std::string data = chufang_data.data;
 
-	//初始化连接
+	//初始化连接
 	try
 	{
 		boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(ip.c_str()), 9100);
@@ -398,39 +402,39 @@ void CPosPrinterQueue::SendDataToChufangPirnter(ChufangPrinterContent chufang_da
 	catch (std::exception& e)
 	{
 		std::string err = e.what();
-		LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
+		LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
 
-		MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK);
+		MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK);
 
-		//连接失败了,处理下一个厨房打印机
+		//杩炴帴澶辫触浜嗭紝澶勭悊涓嬩竴涓�帹鎴挎墦鍗版満
 		return;
 	}
 
-	//网口走这里
+	//网口走这里
 	try
 	{
 		m_socket.write_some(boost::asio::buffer(data.c_str(), data.length()));
 	}
 	catch (const std::exception& e)
 	{
-		LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+		LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 	}
 
 	m_socket.close();
 }
 
-//自动识别用于收银小票的USB打印机列表
+//自动识别用于收银小票的USB打印机列表
 void CPosPrinterQueue::InitUsb()
 {
-	//设置中文字符
+	//璁剧疆涓�枃瀛楃�
 	setlocale(LC_CTYPE, "chs");
 
-	//取设备路径
+	//取设备路径
 	m_usb_devices.clear();
 	int nDevice = GetDevicePath((LPGUID)&USB_GUID, m_usb_devices);
-	LOG_INFO("可用的USB打印机数量:" << nDevice);
+	LOG_INFO("鍙�敤鐨刄SB鎵撳嵃鏈烘暟閲忥細" << nDevice);
 
-	//添加usb端口
+	//娣诲姞usb绔�彛
 	int i = 0;
 
 	while (i < nDevice)
@@ -440,43 +444,43 @@ void CPosPrinterQueue::InitUsb()
 
 		if (CSetting::GetInstance()->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());
+		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());
+			LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str());
 
-			// 打开端口失败
+			// 鎵撳紑绔�彛澶辫触
 			DWORD error = GetLastError();
 
 			if (error == 2)
 			{
-				//没有指定的文件
-				LOG_INFO("没有找对对应的usb端口");
+				//没有指定的文件
+				LOG_INFO("娌℃湁鎵惧�瀵瑰簲鐨剈sb绔�彛");
 			}
 			else if (error == 5)
 			{
-				LOG_INFO("usb端口被占用!");
+				LOG_INFO("usb绔�彛琚�崰鐢�紒");
 			}
 
 			continue;
 		}
 
-		LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort);
+		LOG_INFO("鎵撳紑usb绔�彛鎴愬姛锛屽噯澶囪繘琛屾墦鍗版満妫€娴嬶紒 hPort:" << hPort);
 
 		m_hShouyinPorts.push_back(hPort);
 
 		i++;
 	}
 
-	//清空usb集合,下一次调用这个函数的时候会重新设置
+	//娓呯┖usb闆嗗悎锛屼笅涓€娆¤皟鐢ㄨ繖涓�嚱鏁扮殑鏃跺€欎細閲嶆柊璁剧疆
 	m_usb_devices.clear();
 }
 
@@ -491,25 +495,25 @@ bool CPosPrinterQueue::InitOneUsb(std::wstring usb_path, int nType)
 
 	if (hPort == INVALID_HANDLE_VALUE)
 	{
-		LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
+		LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
 
-		// 打开端口失败
+		// 鎵撳紑绔�彛澶辫触
 		DWORD error = GetLastError();
 
 		if (error == 2)
 		{
-			//没有指定的文件
-			LOG_INFO("没有找对对应的usb端口");
+			//没有指定的文件
+			LOG_INFO("娌℃湁鎵惧�瀵瑰簲鐨剈sb绔�彛");
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("usb端口被占用!");
+			LOG_INFO("usb绔�彛琚�崰鐢�紒");
 		}
 
 		return false;
 	}
 
-	LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort);
+	LOG_INFO("鎵撳紑usb绔�彛锛屽噯澶囪繘琛屾墦鍗版満妫€娴嬶紒 hPort:" << hPort);
 
 	if (nType == 1)
 	{
@@ -531,26 +535,26 @@ bool CPosPrinterQueue::InitBingkou()
 
 	if (hPort == INVALID_HANDLE_VALUE)
 	{
-		LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
+		LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
 
 		DWORD error = GetLastError();
 
 		if (error == 2)
 		{
-			//没有指定的文件
-			LOG_INFO("本机器没有并口!");
+			//没有指定的文件
+			LOG_INFO("鏈�満鍣ㄦ病鏈夊苟鍙o紒");
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("并口被占用!");
+			LOG_INFO("骞跺彛琚�崰鐢�紒");
 		}
 
 		return false;
 	}
 	else
 	{
-		//这个表示并口可以使用
-		LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort);
+		//杩欎釜琛ㄧず骞跺彛鍙�互浣跨敤
+		LOG_INFO("鎵惧埌骞跺彛锛屽噯澶囪繘琛屾墦鍗版満妫€娴嬶紒 hPort:" << hPort);
 
 		m_hShouyinPorts.push_back(hPort);
 	}
@@ -575,24 +579,24 @@ void CPosPrinterQueue::InitCom()
 
 			if (error == 2)
 			{
-				//没有指定的文件
-				LOG_INFO("没有找到对应的串口 " << com2Str.c_str());
+				//没有指定的文件
+				LOG_INFO("没有找到对应的串口 " << com2Str.c_str());
 			}
 			else if (error == 5)
 			{
-				LOG_INFO("串口被占用 " << com2Str.c_str());
+				LOG_INFO("串口被占用 " << com2Str.c_str());
 			}
 		}
 		else
 		{
 			LOG_INFO(com2Str.c_str() << " success, handle:" << hPort);
 
-			//扎到了可用的串口,设置串口波特率
+			//鎵庡埌浜嗗彲鐢ㄧ殑涓插彛锛岃�缃�覆鍙f尝鐗圭巼
 			DCB dcb;
 			dcb.DCBlength = sizeof(dcb);
 			GetCommState(hPort, &dcb);
 
-			//佳博的串口打印机,默认是这个波特率
+			//佳博的串口打印机,默认是这个波特率
 			dcb.BaudRate = 19200;
 
 			if (!SetCommState(hPort, &dcb))
@@ -603,7 +607,7 @@ void CPosPrinterQueue::InitCom()
 				continue;
 			}
 
-			//设定通讯端口超时参数
+			//璁惧畾閫氳�绔�彛瓒呮椂鍙傛暟
 			COMMTIMEOUTS tmouts;
 			tmouts.ReadIntervalTimeout = 100;
 			tmouts.ReadTotalTimeoutMultiplier = 100;
@@ -612,10 +616,10 @@ void CPosPrinterQueue::InitCom()
 			tmouts.WriteTotalTimeoutMultiplier = 100;
 			SetCommTimeouts(hPort, &tmouts);
 
-			//设置端口缓冲
+			//璁剧疆绔�彛缂撳啿
 			SetupComm(hPort, 1024, 1024);
 
-			//清除通讯端口缓存
+			//娓呴櫎閫氳�绔�彛缂撳瓨
 			PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
 
 			m_hShouyinPorts.push_back(hPort);
@@ -624,7 +628,7 @@ void CPosPrinterQueue::InitCom()
 }
 
 /*
- *获取CreateFile的USB端口号
+ *获取CreateFile的USB端口号
  **/
 int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& usb_devices)
 {
@@ -636,43 +640,43 @@ int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& us
 	int nTotle;
 	BOOL bResult;
 
-	//这2个字符串,用于根据usb的名字对比是否为打印机设备
-	std::wstring strUSBPrint = TEXT("USB 打印支持");
+	//这2个字符串,用于根据usb的名字对比是否为打印机设备
+	std::wstring strUSBPrint = TEXT("USB 鎵撳嵃鏀�寔");
 
-	//xp上是英文
+	//xp涓婃槸鑻辨枃
 	std::wstring strUSBPrint_EN = L"USB Printing Support";
 
-	// 取得一个该GUID相关的设备信息集句柄
+	// 鍙栧緱涓€涓��GUID鐩稿叧鐨勮�澶囦俊鎭�泦鍙ユ焺
 	hDevInfoSet = ::SetupDiGetClassDevs(lpGuid,     // class GUID
-		NULL,                    // 无关键字
-		NULL,                    // 不指定父窗口句柄
-		DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);    // 目前存在的设备
+		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... 逐一测试设备接口,到失败为止
+	// 璁惧�搴忓彿=0,1,2... 閫愪竴娴嬭瘯璁惧�鎺ュ彛锛屽埌澶辫触涓烘�
 	while (bResult)
 	{
 		nTotle++;
 		spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
 
-		// 枚举符合该GUID的设备接口
+		// 枚举符合该GUID的设备接口
 		bResult = ::SetupDiEnumDeviceInfo(
-			hDevInfoSet,     // 设备信息集句柄
-			(ULONG)nTotle,   // 设备信息集里的设备序号
-			&spDevInfoData);        // 设备接口信息
+			hDevInfoSet,     // 设备信息集句柄
+			(ULONG)nTotle,   // 设备信息集里的设备序号
+			&spDevInfoData);        // 璁惧�鎺ュ彛淇℃伅
 
 		if (bResult)
 		{
@@ -696,7 +700,7 @@ int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& us
 
 			std::wstring ws_buf = buf;
 
-			//是否是要找的设备类型
+			//鏄�惁鏄��鎵剧殑璁惧�绫诲瀷
 			if (ws_buf != strUSBPrint && ws_buf != strUSBPrint_EN)
 			{
 				LOG_INFO("not good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str());
@@ -706,24 +710,24 @@ int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& us
 			LOG_INFO("good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str());
 			ifData.cbSize = sizeof(ifData);
 
-			// 枚舉符合該GUID的設備接口
+			// 枚舉符合該GUID的設備接口
 			bResult = ::SetupDiEnumDeviceInterfaces(
-				hDevInfoSet,     // 設備信息集句柄
-				NULL,            // 不需額外的設備描述
+				hDevInfoSet,     // 設備信息集句柄
+				NULL,            // 不需額外的設備描述
 				lpGuid,          // GUID
-				(ULONG)nTotle,   // 設備信息集里的設備序號
-				&ifData);        // 設備接口信息
+				(ULONG)nTotle,   // 設備信息集里的設備序號
+				&ifData);        // 瑷�倷鎺ュ彛淇℃伅
 
 			if (bResult)
 			{
-				// 取得该设备接口的细节(设备路径)
+				// 鍙栧緱璇ヨ�澶囨帴鍙g殑缁嗚妭(璁惧�璺�緞)
 				bResult = SetupDiGetInterfaceDeviceDetail(
-					hDevInfoSet,    // 设备信息集句柄
-					&ifData,        // 设备接口信息
-					pDetail,        // 设备接口细节(设备路径)
-					INTERFACE_DETAIL_SIZE,    // 输出缓冲区大小
-					NULL,           // 不需计算输出缓冲区大小(直接用设定值)
-					NULL);          // 不需额外的设备描述
+					hDevInfoSet,    // 设备信息集句柄
+					&ifData,        // 璁惧�鎺ュ彛淇℃伅
+					pDetail,        // 璁惧�鎺ュ彛缁嗚妭(璁惧�璺�緞)
+					INTERFACE_DETAIL_SIZE,    // 输出缓冲区大小
+					NULL,           // 不需计算输出缓冲区大小(直接用设定值)
+					NULL);          // 不需额外的设备描述
 
 				if (bResult)
 				{
@@ -734,10 +738,10 @@ int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& us
 
 					LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str());
 
-					// 复制设备路径到输出缓冲区
+					// 澶嶅埗璁惧�璺�緞鍒拌緭鍑虹紦鍐插尯
 					usb_devices.push_back(DevicePath);
 
-					// 调整计数值
+					// 调整计数值
 					nCount++;
 
 					LOG_INFO("Cnt = " << nCount << ",pDetail->DevicePath =" << pDetail->DevicePath);
@@ -750,10 +754,10 @@ int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& us
 		}
 	}
 
-	// 释放设备接口数据空间
+	// 閲婃斁璁惧�鎺ュ彛鏁版嵁绌洪棿
 	::GlobalFree(pDetail);
 
-	// 关闭设备信息集句柄
+	// 关闭设备信息集句柄
 	::SetupDiDestroyDeviceInfoList(hDevInfoSet);
 	return nCount;
 }

+ 2 - 2
zhipuzi_pos_windows/ui/TouchWindowBase.cpp

@@ -105,7 +105,7 @@ LRESULT TouchWindowBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 						// 保存最后触摸点(用于惯性期间发送位置)
 						m_lastTouchPt = pt;
 
-						::PostMessage(target, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
+						//::PostMessage(target, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
 						::SetCapture(target);
 					}
 					// 触摸移动
@@ -165,7 +165,7 @@ LRESULT TouchWindowBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 							m_accumWheel = 0;
 							m_samples.clear();
 
-							::PostMessage(target, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
+							//::PostMessage(target, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
 							::ReleaseCapture();
 
 							// 启动惯性滚动(如果速度足够大)

+ 15 - 0
zhipuzi_pos_windows/wnd/CMainWnd.cpp

@@ -11,6 +11,7 @@
 #include <urlmon.h>
 
 #include "../wnd/CToastWnd.h"
+#include "../wnd/CVKWnd.h"
 
 #include "../worker/CMqttClientWorker.h"
 
@@ -1080,6 +1081,20 @@ void CMainWnd::ShowToast(std::wstring toast_value)
 	}
 }
 
+void CMainWnd::ShowVK(bool is_show)
+{
+	CVKWnd* pVKDlg = new CVKWnd();
+
+	if (pVKDlg != NULL)
+	{
+		pVKDlg->Create(m_pm.GetPaintWindow(), _T(""), UI_WNDSTYLE_DIALOG, WS_EX_WINDOWEDGE);
+		pVKDlg->SetIcon(IDI_ICON_DUILIB);
+		pVKDlg->CenterWindow();
+
+		pVKDlg->ShowWindow();
+	}
+}
+
 //根据更多里面的设置,刷新左边的功能导航
 void CMainWnd::UpdateGongnengDaohang()
 {

+ 1 - 0
zhipuzi_pos_windows/wnd/CMainWnd.h

@@ -117,6 +117,7 @@ public:
 
 	//展示toast
 	void ShowToast(std::wstring toast_value);
+	void ShowVK(bool is_show);
 
 	//根据更多里面的设置,刷新左边的功能导航
 	void UpdateGongnengDaohang();

+ 342 - 0
zhipuzi_pos_windows/wnd/CVKWnd.cpp

@@ -0,0 +1,342 @@
+#include "CVKWnd.h"
+#include "shellapi.h"
+#pragma comment(lib, "shell32.lib")
+
+CVKWnd::CVKWnd()
+{
+	m_pMinBtn = NULL;
+	m_pCloseBtn = NULL;
+	m_pTabLayout = NULL;
+	m_pSymbolTab = NULL;
+	m_pLShift = NULL;
+	m_pRShift = NULL;
+	m_pNum = NULL;
+	m_pCtrl = NULL;
+	m_pLSymbol = NULL;
+	m_pRSymbol = NULL;
+	m_pInputBtn = NULL;
+	m_bShiftDown = false;
+	m_bCtrlDown = false;
+}
+CVKWnd::~CVKWnd(void)
+{
+}
+
+void CVKWnd::LoadCom()
+{
+}
+void CVKWnd::OnPrepare()
+{
+}
+void CVKWnd::Init()
+{
+	m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
+	m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
+
+	m_pTabLayout = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("switch")));
+
+	m_pLShift = static_cast<COptionUI*>(m_pm.FindControl(_T("opt_shiftl")));
+	m_pRShift = static_cast<COptionUI*>(m_pm.FindControl(_T("opt_shiftr")));
+	m_pNum = static_cast<COptionUI*>(m_pm.FindControl(_T("opt_num")));
+	m_pCtrl = static_cast<COptionUI*>(m_pm.FindControl(_T("opt_ctrl")));
+	m_pSymbolTab = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("sswitch")));
+	m_pLSymbol = static_cast<CButtonUI*>(m_pm.FindControl(_T("lsymbol")));
+	m_pRSymbol = static_cast<CButtonUI*>(m_pm.FindControl(_T("rsymbol")));
+	m_pInputBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("inputtype")));
+
+	for (int i = 65; i < 91; i++)
+	{
+		CDuiString strTemp;
+		strTemp.Format(_T("btn_%d"), i);
+		CButtonUI* pBtn = static_cast<CButtonUI*>(m_pm.FindControl(strTemp.GetData()));
+		if (pBtn)
+		{
+			CDuiString str = pBtn->GetText();
+			m_pVecBtn.push_back(pBtn);
+		}
+	}
+}
+void CVKWnd::Notify(TNotifyUI& msg)
+{
+	if (msg.sType == _T("windowinit")) OnPrepare();
+	else if (msg.sType == _T("click"))
+	{
+		if (msg.pSender == m_pCloseBtn)
+		{
+			PostQuitMessage(0);
+			return;
+		}
+		else if (msg.pSender == m_pMinBtn)
+		{
+			SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
+			return;
+		}
+		else if (msg.pSender->GetName() == _T("handinput"))
+		{
+			CDuiString strapp = CPaintManagerUI::GetInstancePath() + _T("..\\app\\handinput\\handinput.exe");
+			ShellExecute(NULL, _T("open"), strapp.GetData(), NULL, NULL, SW_SHOWDEFAULT);
+			//	PostQuitMessage(0);
+		}
+		else if (msg.pSender == m_pCtrl)  //ctrl键
+		{
+			if (m_pCtrl->IsSelected())
+			{
+				m_bCtrlDown = false;
+				m_pLShift->SetEnabled();
+				m_pRShift->SetEnabled();
+			}
+			else
+			{
+				m_bCtrlDown = true;
+				m_pLShift->Selected(false);
+				m_pRShift->Selected(false);
+				m_pLShift->SetEnabled(false);
+				m_pRShift->SetEnabled(false);
+			}
+		}
+
+		else if (msg.pSender == m_pLSymbol) //符号左方向按钮
+		{
+			if (m_pSymbolTab)
+				m_pSymbolTab->SelectItem(0);
+			if (m_pLSymbol && m_pRSymbol)
+			{
+				m_pLSymbol->SetEnabled(false);
+				m_pRSymbol->SetEnabled();
+			}
+		}
+		else if (msg.pSender == m_pRSymbol) //符号右方向按钮
+		{
+			if (m_pSymbolTab)
+				m_pSymbolTab->SelectItem(1);
+			if (m_pLSymbol && m_pRSymbol)
+			{
+				m_pLSymbol->SetEnabled();
+				m_pRSymbol->SetEnabled(false);
+			}
+		}
+		else if (msg.pSender->GetName().Find(_T("btn_")) == 0) //普通按键
+		{
+			CDuiString strTemp = msg.pSender->GetName();
+			strTemp = strTemp.Right(strTemp.GetLength() - 4);
+			int iKey = _wtoi(strTemp.GetData());
+			OnClickVK(iKey);
+		}
+		else if (msg.pSender->GetName().Find(_T("lbtn_")) == 0 || msg.pSender->GetName().Find(_T("rbtn_")) == 0) //左右都有的按键
+		{
+			CDuiString strTemp = msg.pSender->GetName();
+			strTemp = strTemp.Right(strTemp.GetLength() - 5);
+			int iKey = _wtoi(strTemp.GetData());
+			OnClickVK(iKey);
+		}
+		else if (msg.pSender->GetName().Find(_T("opt_shift")) == 0) //shift键
+		{
+			if (msg.pSender == m_pLShift)
+			{
+				if (m_pLShift->IsSelected())
+				{
+					m_pRShift->Selected(false);
+					SwitchLetter(false);
+					m_bShiftDown = false;
+				}
+				else
+				{
+					m_pRShift->Selected(true);
+					SwitchLetter(true);
+					m_bShiftDown = true;
+				}
+			}
+			else
+			{
+				if (m_pRShift->IsSelected())
+				{
+					m_pLShift->Selected(false);
+					SwitchLetter(false);
+					m_bShiftDown = false;
+				}
+				else
+				{
+					m_pLShift->Selected(true);
+					SwitchLetter(true);
+					m_bShiftDown = true;
+				}
+			}
+		}
+		else if (msg.pSender == m_pNum) //数字键
+		{
+			if (m_pNum->IsSelected())
+			{
+				m_pTabLayout->SelectItem(0);
+				m_pCtrl->SetEnabled(true);
+
+				m_pLShift->Selected(false);
+				m_pRShift->Selected(false);
+				SwitchLetter(false);
+				m_bShiftDown = false;
+			}
+			else
+			{
+				m_bShiftDown = false;
+				m_pTabLayout->SelectItem(1);
+				m_pLShift->Selected(true);
+				m_pRShift->Selected(true);
+				m_pLShift->SetEnabled(true);
+				m_pRShift->SetEnabled(true);
+				m_pCtrl->Selected(false);
+				m_pCtrl->SetEnabled(false);
+			}
+		}
+		else if (msg.pSender->GetName().Find(_T("symbol_")) == 0) //符号键
+		{
+			CDuiString strTemp = msg.pSender->GetName();
+			strTemp = strTemp.Right(strTemp.GetLength() - 7);
+			int iKey = _wtoi(strTemp.GetData());
+			keybd_event(VK_SHIFT, 0, 0, 0);
+			keybd_event(iKey, 0, 0, 0);
+			keybd_event(iKey, 0, KEYEVENTF_KEYUP, 0);
+			keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
+		}
+	}
+}
+
+LRESULT CVKWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	LONG styleValue = ::GetWindowLong(*this, GWL_EXSTYLE);
+	styleValue &= ~WS_CAPTION;
+	::SetWindowLong(*this, GWL_EXSTYLE, styleValue | WS_EX_NOACTIVATE);
+
+	SetWindowPos(*this, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+	m_pm.Init(m_hWnd);
+	CDialogBuilder builder;
+	CControlUI* pRoot = builder.Create(_T("virtual_keyboard.xml"), (UINT)0, NULL, &m_pm);
+	ASSERT(pRoot && "Failed to parse XML");
+	m_pm.AttachDialog(pRoot);
+	m_pm.AddNotifier(this);
+
+	Init();
+
+	return 0;
+}
+
+LRESULT CVKWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	::PostQuitMessage(0L);
+
+	bHandled = FALSE;
+	return 0;
+}
+
+LRESULT CVKWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	if (::IsIconic(*this)) bHandled = FALSE;
+	return (wParam == 0) ? TRUE : FALSE;
+}
+LRESULT CVKWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	return 0;
+}
+LRESULT CVKWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	return 0;
+}
+LRESULT CVKWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
+	::ScreenToClient(*this, &pt);
+
+	RECT rcClient;
+	::GetClientRect(*this, &rcClient);
+
+	RECT rcCaption = m_pm.GetCaptionRect();
+	if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
+		&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom)
+	{
+		CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
+		if (pControl && _tcscmp(pControl->GetClass(), _T("ButtonUI")) != 0)
+			return HTCAPTION;
+	}
+
+	return HTCLIENT;
+}
+
+LRESULT CVKWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	if (!IsIconic(*this))
+	{
+		RECT rcClient;
+		GetClientRect(*this, &rcClient);
+		HRGN hRgn = ::CreateRoundRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, 3, 3);
+		SetWindowRgn(*this, hRgn, TRUE);
+		DeleteObject(hRgn);
+	}
+	bHandled = FALSE;
+	return 0;
+}
+
+LRESULT CVKWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+	bHandled = FALSE;
+	return 0;
+}
+LRESULT CVKWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	LRESULT lRes = 0;
+	BOOL bHandled = TRUE;
+	switch (uMsg)
+	{
+		case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
+		case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
+		case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
+		default:
+			bHandled = FALSE;
+	}
+	SetCursor(LoadCursor(NULL, IDC_ARROW));
+	if (bHandled)
+		return lRes;
+	if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
+		return lRes;
+	return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
+}
+
+LRESULT CVKWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
+{
+	if (uMsg == WM_KEYDOWN)
+	{
+		if (wParam == VK_RETURN)
+		{
+			return true;
+		}
+		else if (wParam == VK_ESCAPE)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void CVKWnd::OnClickVK(int iKeyValue)
+{
+	if (m_bCtrlDown && (iKeyValue == 65 || iKeyValue == 67 || iKeyValue == 86 || iKeyValue == 88 || iKeyValue == 90))
+	{
+		keybd_event(VK_CONTROL, 0, 0, 0);
+	}
+	if (m_bShiftDown)
+		keybd_event(VK_SHIFT, 0, 0, 0);
+	keybd_event(iKeyValue, 0, 0, 0);
+	Sleep(50);
+
+	keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
+
+	m_pCtrl->Selected(false);
+	m_bCtrlDown = false;
+}
+void CVKWnd::SwitchLetter(bool bUpper)
+{
+
+}

+ 83 - 0
zhipuzi_pos_windows/wnd/CVKWnd.h

@@ -0,0 +1,83 @@
+#pragma once
+
+#include "../pch/pch.h"
+#include "CMainWnd.h"
+
+class CVKWnd : public CWindowWnd, public INotifyUI, public IMessageFilterUI
+{
+public:
+	CVKWnd();
+	~CVKWnd(void);
+
+	LPCTSTR GetWindowClassName() const
+	{
+		return _T("CVKWnd");
+	};
+
+	UINT GetClassStyle() const
+	{
+		return UI_CLASSSTYLE_DIALOG;
+	};
+
+	void OnFinalMessage(HWND /*hWnd*/)
+	{
+		//WindowImplBase::OnFinalMessage(hWnd);
+		m_pm.RemovePreMessageFilter(this);
+
+		delete this;
+	};
+
+	void Init();
+
+	void Notify(TNotifyUI& msg);
+
+	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+	LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);
+
+	void LoadCom();
+	void OnPrepare();
+	void OnClickVK(int iKeyValue);
+	void SwitchLetter(bool bUpper);
+
+public:
+	CPaintManagerUI m_pm;
+
+private:
+	CButtonUI* m_pMinBtn = NULL;
+	CButtonUI* m_pCloseBtn = NULL;
+
+	CTabLayoutUI* m_pTabLayout = NULL;
+
+	COptionUI* m_pLShift = NULL;
+	COptionUI* m_pRShift = NULL;
+	COptionUI* m_pNum = NULL;
+	COptionUI* m_pCtrl = NULL;
+
+	CTabLayoutUI* m_pSymbolTab = NULL;
+	
+	CButtonUI* m_pLSymbol = NULL;
+	CButtonUI* m_pRSymbol = NULL;
+	CButtonUI* m_pInputBtn = NULL;
+
+	std::vector<CButtonUI*> m_pVecBtn;
+
+	bool m_bShiftDown = false;
+	bool m_bCtrlDown = false;
+};

+ 2 - 0
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj

@@ -244,6 +244,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="ai\SQLiteVecManager.h" />
     <ClInclude Include="ai\YoloClassName.h" />
     <ClInclude Include="ai\YoloFeatureManager.h" />
+    <ClInclude Include="wnd\CVKWnd.h" />
     <ClInclude Include="page\CAIxuexiPageUI.h" />
     <ClInclude Include="ui\TouchWindowBase.h" />
     <ClInclude Include="worker\CDiandanAIShibieWorker.h" />
@@ -376,6 +377,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClCompile Include="ai\test.cpp" />
     <ClCompile Include="ai\test.h" />
     <ClCompile Include="ai\YoloFeatureManager.cpp" />
+    <ClCompile Include="wnd\CVKWnd.cpp" />
     <ClCompile Include="page\CAIxuexiPageUI.cpp" />
     <ClCompile Include="ui\TouchWindowBase.cpp" />
     <ClCompile Include="worker\CDiandanAIShibieWorker.cpp" />

+ 6 - 0
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj.filters

@@ -402,6 +402,9 @@
     <ClInclude Include="ui\TouchWindowBase.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="wnd\CVKWnd.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="pch\pch.cpp">
@@ -764,6 +767,9 @@
     <ClCompile Include="ui\TouchWindowBase.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="wnd\CVKWnd.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="resource\zhipuzi.ico">