
// MFCApplication1Dlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "MFCApplication1.h"
#include "MFCApplication1Dlg.h"
#include "afxdialogex.h"
#include "CvxText.h"
#include "BaseUtility.h"
#include "libpdf.h"
#include "AssignWords.h"
#include "lib_common_depence.h"
#include <direct.h>
#include <io.h>
#include "Buffers.h"
#include "Config.h"

#if defined(GNUC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored “-Wdeprecated-declarations”
#elif defined(_MSC_VER)
#pragma warning(disable : 4996)
#endif

#include <json/json.h>
#ifdef _DEBUG
#pragma comment(lib, "libpdfd.lib")
#pragma comment(lib, "lib_common_depence_d.lib")
#else
#pragma comment(lib, "libpdf.lib")
#pragma comment(lib, "lib_common_depence.lib")
#endif


#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define SAFETY_CLOSE_HANDLE( handle )									\
	if( NULL != handle )													\
{																		\
	CloseHandle( handle );												\
	handle = NULL;														\
}

#define SAFETY_EXIT_THREAD( hThread, Timeout )							\
	if( NULL != hThread )													\
{																		\
	if( WaitForSingleObject( hThread, Timeout ) == WAIT_TIMEOUT )		\
	TerminateThread( hThread, -1 );									\
	CloseHandle( hThread );												\
	hThread = NULL;														\
}


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFCApplication1Dlg 对话框

vector<string> g_vecFileList;//扫描文件列表
int g_scanCount = 0;//扫描文件个数
HANDLE _threadProcess = NULL;
DWORD WINAPI ProcessThread(void *param)
{
	CMFCApplication1Dlg* pWnd = (CMFCApplication1Dlg*)theApp.m_pMainWnd;
	
	std::vector<std::string> twoList;
	std::vector<std::string> threeList;
	std::vector<std::string> fourList;
	AssignWordsFromTest(UnicodeToGB2312(pWnd->m_strTextPath), twoList, threeList, fourList);

	auto CovertPdfFunc = [&](std::vector<std::string>&  vctFiles, int col, int& pageNum){
		std::string strPage1;
		for (size_t i = 0; i < vctFiles.size(); i += max_line * col)
		{
			std::vector<std::string> vecSmall;
			auto last = std::min(vctFiles.size(), i + max_line * col);
			vecSmall.insert(vecSmall.begin(), vctFiles.begin() + i, vctFiles.begin() + last);

			std::string strPagePath;
			dataCollectionPaper(col, pageNum, 30, 100, false, vecSmall, pWnd->m_strPdfDir, strPagePath);
			if (strPage1.length() == 0)
			{
				strPage1 = strPagePath;
			}
			else
			{
				CString strPdfPath;
				strPdfPath.Format(L"%s/pdf/%d.pdf", pWnd->m_strPdfDir, pageNum);
				PdfNewFromImage({ strPage1, strPagePath }, TstringToGB2312(strPdfPath.GetBuffer()));
				strPage1 = "";

				CString strMsg = L"";
				strMsg.Format(L"%s\r\n", strPdfPath);
				SendMessage(pWnd->m_hWnd, WM_SHOWINFO, (WPARAM)strMsg.GetBuffer(), 0);
				strMsg.ReleaseBuffer();
			}
			pageNum++;
		}
		if (strPage1.length() > 0)
		{
			CString strPdfPath;
			strPdfPath.Format(L"%s/pdf/%d.pdf", pWnd->m_strPdfDir, pageNum);
			PdfNewFromImage({ strPage1 }, TstringToGB2312(strPdfPath.GetBuffer()));
			CString strMsg = L"";
			strMsg.Format(L"%s\r\n", strPdfPath);
			SendMessage(pWnd->m_hWnd, WM_SHOWINFO, (WPARAM)strMsg.GetBuffer(), 0);
			strMsg.ReleaseBuffer();
		}
	};
	

	int pageNum = 100;
	CovertPdfFunc(twoList, 2, pageNum);
	CovertPdfFunc(threeList, 3, pageNum);
	CovertPdfFunc(fourList, 4, pageNum);

	//通知发送消息到窗口
	CString strErrorMsg = L"";
	strErrorMsg.Format(L"PDF生成完成!\r\n");
	SendMessage(pWnd->m_hWnd, WM_SHOWINFO, (WPARAM)strErrorMsg.GetBuffer(), 1);
	strErrorMsg.ReleaseBuffer();
	return 0L;
}

int IdentifyCallback(result::spinfo& pinfo, void* param)
{
	CMFCApplication1Dlg* pWnd = (CMFCApplication1Dlg*)theApp.m_pMainWnd;
	if (pinfo.choiceRes.size() < 3 || pinfo.vecUrlAPath.size() == 0)
	{
		pWnd->PostMessage(WM_PROCESS, NULL, NULL);
		pWnd->FormatScanMsg("矫正图像失败原图为：%s", pinfo.vecUrlPath.size() > 0 ? pinfo.vecUrlPath[0].c_str() : "图像为空");
	}
	
	std::string strChoiceRes;
	for (auto& row : pinfo.choiceRes)
	{
		for (auto& col : row.vecRes)
		{
			strChoiceRes.append(col ? "1" : "0");
		}
	}

	int length = strChoiceRes.length();
	int number = 0;
	for (int i = 0; i < length; ++i)
	{
		if (strChoiceRes[i] == '1') // 其中注意if的判断两个条件相等的符号
			number += pow(2, length - 1 - i);
	}

	std::string strJsonDir = CT2A(CConfig::Instance()->m_strMode);
	strJsonDir.append("/");
	strJsonDir.append(std::to_string(number));
	strJsonDir.append(".json");
	std::string strSaveDir = CT2A(CConfig::Instance()->m_strCut);
	cutPaper(number, strJsonDir, pinfo.vecUrlAPath[0], strSaveDir);
	g_scanCount++;
	pWnd->PostMessage(WM_PROCESS, NULL, NULL);
	pWnd->FormatScanMsg("生成切割图像：%s", pinfo.vecUrlAPath[0].c_str());

	return 0;
}

enum EnumSearFileType {
	file,//扫描文件
	dir,//扫描文件夹
};

void GetImages(CString strPath)
{
	queue<CString>	queuePath;
	queuePath.push(strPath);
	EnumSearFileType serchType = file;
	CFileFind finder;
	do
	{
		bool bFinished = finder.FindFile(queuePath.front() + _T("\\*.JPG"));
		while (serchType == file && bFinished)
		{
			bFinished = finder.FindNextFile();
			if (finder.IsDirectory())continue;
			CString strPath = finder.GetFilePath();
			g_vecFileList.push_back(UnicodeToGB2312(strPath));
		}
		serchType = dir;
		bFinished = finder.FindFile(queuePath.front() + _T("\\*.*"));
		while (bFinished)
		{
			bFinished = finder.FindNextFile();
			if (finder.IsDirectory() && !finder.IsDots())
			{
				queuePath.push(finder.GetFilePath());
			}
		}
		queuePath.pop();
		serchType = file;
	} while (queuePath.size() > 0);
}

string GetBatchId()
{
	SYSTEMTIME st;
	GetLocalTime(&st);
	char chBuf[24] = { 0 };
	sprintf(chBuf, "%02d%02d%02d%02d%02d%02d",
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
	return chBuf;
}

HANDLE _threadScan = NULL;
char* g_strIdentifyMsg[7] = { "正常","内部error","批次号异常","保存路径异常","模板为空","图像列表异常","图像列表不是模板整数倍" };
DWORD WINAPI ScanThread(void *param)
{
	g_scanCount = 0;
	g_vecFileList.clear();
	GetImages(CConfig::Instance()->m_strImg);
	CMFCApplication1Dlg* pWnd = (CMFCApplication1Dlg*)theApp.m_pMainWnd;
	pWnd->PostMessage(WM_PROCESS, NULL, NULL);
	pWnd->FormatScanMsg("启动扫描线程......");
	auto exitfun = [&]() {
		pWnd->FormatScanMsg("扫描线程退出。");
		SendMessage(pWnd->m_hWnd, WM_SHOWSCANINFO, 0, 1);
	};
	
	preinfo::templatesInfo  temeplatInfo;
	preinfo::SubjChiInfo sujChiInfo;
	std::string strTempDir = CT2A(CConfig::Instance()->m_strCut);
	/*if (_access(strTempDir.c_str(), 0) == -1)
	{
		_mkdir(strTempDir.c_str());
	}*/
	int nRet = PareseModeJson(temeplatInfo);
	if (nRet)
	{
		pWnd->FormatScanMsg("模板解析失败！");
		exitfun();
		return 0;
	}
	//生成批次号
	string strBatchId = GetBatchId();
	pWnd->FormatScanMsg("创建批次id：%s", strBatchId.c_str());
	nRet = api_processing_images(strBatchId.c_str(),
		strTempDir.c_str(),
		temeplatInfo,
		sujChiInfo,
		g_vecFileList,
		LOG_AUTO,
		false,
		OLNS,
		IdentifyCallback,
		NULL);
	////启动算法扫描功能
	if (nRet != RT_OK)
	{
		if (nRet >= 0 && nRet <= 6)
			pWnd->FormatScanMsg("扫描失败，错误描述:%s, errorCode:%d", g_strIdentifyMsg[nRet], nRet);
		else
			pWnd->FormatScanMsg("扫描失败，errorCode:%d", nRet);
	}
	exitfun();
	return  0L;
}
CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MFCAPPLICATION1_DIALOG, pParent)
	, m_strMsg(_T("")), m_strScanMsg(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT_MSG, m_strMsg);
	DDX_Text(pDX, IDC_EDIT_SCANMSG, m_strScanMsg);
}

BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, &CMFCApplication1Dlg::OnBnClickedOk)
	ON_MESSAGE(WM_SHOWINFO, OnShowInfo)
	ON_MESSAGE(WM_SHOWSCANINFO, OnShowScanInfo)
	ON_MESSAGE(WM_PROCESS, OnProcessInfo)
	ON_BN_CLICKED(IDCANCEL, &CMFCApplication1Dlg::OnBnClickedCancel)
	ON_BN_CLICKED(IDC_BTN_TXT, &CMFCApplication1Dlg::OnBnClickedBtnTxt)
	ON_BN_CLICKED(IDC_BTN_PDF, &CMFCApplication1Dlg::OnBnClickedBtnPdf)
	ON_BN_CLICKED(IDC_BTN_MODEPATH, &CMFCApplication1Dlg::OnBnClickedBtnModepath)
	ON_BN_CLICKED(IDC_BTN_IMGPATH, &CMFCApplication1Dlg::OnBnClickedBtnImgpath)
	ON_BN_CLICKED(IDC_BTN_CUTPATH, &CMFCApplication1Dlg::OnBnClickedBtnCutpath)
	ON_BN_CLICKED(ID_BTN_SCAN, &CMFCApplication1Dlg::OnBnClickedBtnScan)
END_MESSAGE_MAP()


// CMFCApplication1Dlg 消息处理程序

BOOL CMFCApplication1Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	CConfig::Instance()->LoadFromINI();
	GetDlgItem(IDC_EDIT_TXT)->SetWindowText(CConfig::Instance()->m_strTxt);
	GetDlgItem(IDC_EDIT_PDF)->SetWindowText(CConfig::Instance()->m_strPdf);

	GetDlgItem(IDC_EDIT_MODEPATH)->SetWindowText(CConfig::Instance()->m_strMode);
	GetDlgItem(IDC_EDIT_IMGPATH)->SetWindowText(CConfig::Instance()->m_strImg);
	GetDlgItem(IDC_EDIT_CUTPATH)->SetWindowText(CConfig::Instance()->m_strCut);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CMFCApplication1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CMFCApplication1Dlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CMFCApplication1Dlg::OnBnClickedOk()
{
	((CEdit*)GetDlgItem(IDC_EDIT_TXT))->GetWindowText(m_strTextPath);
	((CEdit*)GetDlgItem(IDC_EDIT_PDF))->GetWindowText(m_strPdfDir);
	
	if (m_strTextPath.GetLength() == 0)
	{
		AfxMessageBox(L"语料库文件未选择");
		return;
	}
	if (m_strPdfDir.GetLength() == 0)
	{
		AfxMessageBox(L"PDF文件夹未选择");
		return;
	}

	GetDlgItem(IDOK)->EnableWindow(FALSE);
	m_strMsg = "";

	CString strJsonDir(m_strPdfDir);
	strJsonDir.Append(L"\\json");
	if (!PathIsDirectory(strJsonDir))
	{
		::CreateDirectory(strJsonDir, 0);
	}

	CString strPdfDir(m_strPdfDir);
	strPdfDir.Append(L"\\pdf");
	if (!PathIsDirectory(strPdfDir))
	{
		::CreateDirectory(strPdfDir, 0);
	}
	
	SAFETY_EXIT_THREAD(_threadProcess, 100);
	_threadProcess = CreateThread(NULL, 0, ProcessThread, NULL, 0, NULL);

	
	//CDialogEx::OnOK();
}

void CMFCApplication1Dlg::UpdateMsg(CString strMsg)
{
	m_strMsg += strMsg;
	UpdateData(FALSE);
}

void CMFCApplication1Dlg::UpdateScanMsg(CString strMsg)
{
	m_strScanMsg += strMsg;
	UpdateData(FALSE);
}



LRESULT CMFCApplication1Dlg::OnShowInfo(WPARAM  wParam, LPARAM  lParam)
{
	wchar_t* p = (wchar_t*)wParam;
	CString str;
	str.Format(_T("%s"), p);
	m_strMsg += str;
	UpdateData(FALSE);

	if (lParam == 1)
	{
		GetDlgItem(IDOK)->EnableWindow(TRUE);
	}
	return 0;
}

LRESULT CMFCApplication1Dlg::OnShowScanInfo(WPARAM  wParam, LPARAM  lParam)
{
	if (lParam == 1)
	{
		GetDlgItem(ID_BTN_SCAN)->EnableWindow(TRUE);
		return 0;
	}
	wchar_t* p = (wchar_t*)wParam;
	CString str;
	str.Format(_T("%s"), p);
	m_strScanMsg += str;
	UpdateData(FALSE);

	return 0;
}

LRESULT CMFCApplication1Dlg::OnProcessInfo(WPARAM wParam, LPARAM lParam)
{
	CString strProcess = _T("--");
	if (g_vecFileList.size())
	{
		float fProcess = (float)g_scanCount / (float)g_vecFileList.size();
		strProcess.Format(L"%0.0lf%%", fProcess*100);
	}
	SetDlgItemText(IDC_EDIT_SCANPROCESS, strProcess);
	return 0;
}

void CMFCApplication1Dlg::OnBnClickedCancel()
{
	SAFETY_EXIT_THREAD(_threadProcess, 100);
	SAFETY_EXIT_THREAD(_threadScan, 100);
	CConfig::Instance()->SaveSetting();
	CDialogEx::OnCancel();
}

void CMFCApplication1Dlg::SelectFolder(HWND hwnd, CString& lpszFolder)
{
	TCHAR szFolderPath[MAX_PATH];
	szFolderPath[0] = 0;
	BROWSEINFO	sInfo;
	::ZeroMemory(&sInfo, sizeof(BROWSEINFO));
	sInfo.pidlRoot = 0;
	sInfo.lpszTitle = _T("请选择一个文件夹");
	sInfo.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_EDITBOX;
	sInfo.lpfn = NULL;
	sInfo.hwndOwner = hwnd;
	LPITEMIDLIST  lpidlBrowse = ::SHBrowseForFolder(&sInfo);

	if (lpidlBrowse != NULL) {
		if (::SHGetPathFromIDList(lpidlBrowse, szFolderPath)) {
			lpszFolder = szFolderPath;
			lpszFolder.Replace('\\', '/');
		}
		::CoTaskMemFree(lpidlBrowse);
	}
}

void CMFCApplication1Dlg::SelectFile(CString& lpszFile)
{
	CString OpenFilter = _T("文本文件(*.txt)|*.txt;|");
	CFileDialog FileOpen(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, OpenFilter);
	if (IDOK == FileOpen.DoModal())
	{
		lpszFile = FileOpen.GetPathName();
		lpszFile.Replace('\\', '/');
	}
}

void CMFCApplication1Dlg::OnBnClickedBtnTxt()
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_TXT);
	if (!pEdit)
	{
		return;
	}
	CString strText;
	SelectFile(strText);
	if (strText.GetLength() == 0)
	{
		return;
	}
	pEdit->SetWindowText(strText);
	CConfig::Instance()->m_strTxt = strText;
}


void CMFCApplication1Dlg::OnBnClickedBtnPdf()
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PDF);
	if (!pEdit)
	{
		return;
	}
	CString strText;
	SelectFolder(GetSafeHwnd(), strText);
	if (strText.GetLength() == 0)
	{
		return;
	}
	pEdit->SetWindowText(strText);
	CConfig::Instance()->m_strPdf = strText;
}


void CMFCApplication1Dlg::OnBnClickedBtnModepath()
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_MODEPATH);
	if (!pEdit)
	{
		return;
	}
	CString strText;
	SelectFolder(GetSafeHwnd(), strText);
	if (strText.GetLength() == 0)
	{
		return;
	}
	pEdit->SetWindowText(strText);
	CConfig::Instance()->m_strMode = strText;
}


void CMFCApplication1Dlg::OnBnClickedBtnImgpath()
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_IMGPATH);
	if (!pEdit)
	{
		return;
	}
	CString strText;
	SelectFolder(GetSafeHwnd(), strText);
	if (strText.GetLength() == 0)
	{
		return;
	}
	pEdit->SetWindowText(strText);
	CConfig::Instance()->m_strImg = strText;
}


void CMFCApplication1Dlg::OnBnClickedBtnCutpath()
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_CUTPATH);
	if (!pEdit)
	{
		return;
	}
	CString strText;
	SelectFolder(GetSafeHwnd(), strText);
	if (strText.GetLength() == 0)
	{
		return;
	}
	pEdit->SetWindowText(strText);
	CConfig::Instance()->m_strCut = strText;
}


void CMFCApplication1Dlg::OnBnClickedBtnScan()
{
	((CEdit*)GetDlgItem(IDC_EDIT_MODEPATH))->GetWindowText(m_strModePath);
	((CEdit*)GetDlgItem(IDC_EDIT_IMGPATH))->GetWindowText(m_strImgPath);
	((CEdit*)GetDlgItem(IDC_EDIT_CUTPATH))->GetWindowText(m_strCutPath);

	if (m_strModePath.GetLength() == 0)
	{
		AfxMessageBox(L"模板文件夹未选择");
		return;
	}
	if (m_strImgPath.GetLength() == 0)
	{
		AfxMessageBox(L"答题卡文件夹未选择");
		return;
	}
	if (m_strCutPath.GetLength() == 0)
	{
		AfxMessageBox(L"切割生成文件夹未选择");
		return;
	}
	GetDlgItem(ID_BTN_SCAN)->EnableWindow(FALSE);
	m_strScanMsg = "";

	CString strNormal(m_strCutPath);
	strNormal.Append(L"/normal");
	if (!PathIsDirectory(strNormal))
	{
		::CreateDirectory(strNormal, 0);
	}

	CString strAbnormal(m_strCutPath);
	strAbnormal.Append(L"/abnormal");
	if (!PathIsDirectory(strAbnormal))
	{
		::CreateDirectory(strAbnormal, 0);
	}

	SAFETY_EXIT_THREAD(_threadScan, 100);
	_threadScan = CreateThread(NULL, 0, ScanThread, NULL, 0, NULL);
}

void CMFCApplication1Dlg::FormatScanMsg(const char *szFmt, ...)
{
	if (!szFmt)
		return;

	va_list ap;
	va_start(ap, szFmt);
	size_t nLength = _vsnprintf(nullptr, 0, szFmt, ap) + 1;
	CBuffers buffer;
	char* szLogMsg = buffer.GetBuf(nLength);
	_vsnprintf(szLogMsg, nLength, szFmt, ap);
	va_end(ap);
	SYSTEMTIME st;
	GetLocalTime(&st);
	char chBuf[24] = { 0 };
	sprintf(chBuf, "%02d-%02d-%02d %02d:%02d:%02d ",
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

	CString strMsg;
	// 扫描异常
	strMsg.Format(L"%s %s\r\n", GB2312ToTstring(chBuf).c_str(), GB2312ToTstring(szLogMsg).c_str());
	SendMessage(WM_SHOWSCANINFO, (WPARAM)strMsg.GetBuffer(), 0);
}