| | |
| | | #include "MsgDlg.h" |
| | | #include "InputDialog.h" |
| | | #include "RecipeDeviceBindDlg.h" |
| | | #include "DeviceRecipeParamDlg.h" |
| | | |
| | | |
| | | // CPageRecipe 对话框 |
| | | |
| | |
| | | } |
| | | |
| | | m_listPPID.InsertColumn(0, _T(""), LVCFMT_RIGHT, 0); // 隐藏列 |
| | | m_listPPID.InsertColumn(1, _T("No."), LVCFMT_LEFT, width[1]); |
| | | m_listPPID.InsertColumn(1, _T("No."), LVCFMT_CENTER, width[1]); |
| | | m_listPPID.InsertColumn(2, _T("PPID"), LVCFMT_LEFT, width[2]); |
| | | m_listPPID.InsertColumn(3, _T("真空烘烤"), LVCFMT_LEFT, width[6]); |
| | | m_listPPID.InsertColumn(4, _T("Bonder1"), LVCFMT_LEFT, width[4]); |
| | |
| | | |
| | | m_listPPID.InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]); |
| | | m_listPPID.InsertColumn(1, _T("No."), LVCFMT_CENTER, width[1]); |
| | | m_listPPID.InsertColumn(2, _T("Recipe ID"), LVCFMT_CENTER, width[2]); |
| | | m_listPPID.InsertColumn(3, _T("Recipe 名称"), LVCFMT_CENTER, width[3]); |
| | | m_listPPID.InsertColumn(4, _T("Recipe 参数"), LVCFMT_CENTER, width[4]); |
| | | m_listPPID.InsertColumn(2, _T("Recipe ID"), LVCFMT_LEFT, width[2]); |
| | | m_listPPID.InsertColumn(3, _T("Recipe 名称"), LVCFMT_LEFT, width[3]); |
| | | m_listPPID.InsertColumn(4, _T("Recipe 参数"), LVCFMT_LEFT, width[4]); |
| | | } |
| | | |
| | | void CPageRecipe::UpdateRecipeByPPID(const CString& strPPID) |
| | |
| | | str.Format(_T("%d"), recipe.vecDeviceList.at(j).nRecipeID); |
| | | } |
| | | else { |
| | | str.Format(_T("%s"), CA2T(strRecipeName.c_str())); |
| | | str.Format(_T("%s"), strRecipeName.c_str()); |
| | | } |
| | | |
| | | m_listPPID.SetItemText(i, j + 3, str); |
| | |
| | | m_listPPID.SetColumnWidth(nColCount - 1, LVSCW_AUTOSIZE_USEHEADER); |
| | | } |
| | | |
| | | void CPageRecipe::FillRecipeListToListCtrl(SERVO::CRecipeList* pList) |
| | | void CPageRecipe::FillRecipeListToListCtrl(SERVO::CEquipment* pEq) |
| | | { |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PPID); |
| | | if (pListCtrl == nullptr || !::IsWindow(pListCtrl->m_hWnd)) { |
| | | return; |
| | | } |
| | | |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) { |
| | | return; |
| | | } |
| | | |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | if (nEqSel == CB_ERR) { |
| | | return; |
| | | } |
| | | |
| | | auto& mgr = RecipeManager::getInstance(); |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel); |
| | | if (pEq == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | // 清空当前CListCtrl中的所有项 |
| | | pListCtrl->DeleteAllItems(); |
| | | if (pList == nullptr) { |
| | | if (pRecipeList == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | // 遍历数据并插入到CListCtrl中 |
| | | std::map<int, short>& ids = pList->getIds(); |
| | | auto& mgr = RecipeManager::getInstance(); |
| | | std::map<int, short>& ids = pRecipeList->getIds(); |
| | | auto rawDatas = pRecipeList->getParamsRawData(); |
| | | for (auto item : ids) { |
| | | int index = m_listPPID.InsertItem(m_listPPID.GetItemCount(), _T("")); |
| | | m_listPPID.SetItemText(index, 1, std::to_string(item.first).c_str()); |
| | | m_listPPID.SetItemText(index, 2, std::to_string(item.second).c_str()); |
| | | |
| | | std::string strRecipeName = mgr.getDeviceRecipeName(pEq->getName(), item.second); |
| | | std::string strRecipeName = mgr.getDeviceRecipeName(SanitizeName(pEq->getName()), item.second); |
| | | m_listPPID.SetItemText(index, 3, strRecipeName.c_str()); |
| | | |
| | | std::string strDescription; |
| | | auto iter = rawDatas.find(item.second); |
| | | if (iter != rawDatas.end()) { |
| | | pEq->parsingParams((const char*)iter->second.data(), iter->second.size(), strDescription); |
| | | m_listPPID.SetItemText(index, 4, strDescription.c_str()); |
| | | } |
| | | |
| | | if (strRecipeName.empty()) { |
| | | strRecipeName = std::to_string(item.second); |
| | | mgr.addDeviceRecipe(pEq->getName(), item.second, strRecipeName); |
| | | mgr.addDeviceRecipe(SanitizeName(pEq->getName()), item.second, strRecipeName, strDescription); |
| | | } |
| | | m_listPPID.SetItemText(index, 3, strRecipeName.c_str()); |
| | | } |
| | | |
| | | // 获取列数 |
| | |
| | | pEq[i] == nullptr ? _T("Master") : pEq[i]->getName().c_str()); |
| | | pComboBox->SetItemDataPtr(i, pEq[i]); |
| | | |
| | | // 读取回来 |
| | | char szBuffer[_MAX_PATH]; |
| | | if (pEq[i]) { |
| | | pEq[i]->masterRecipeListRequest(0, nullptr); |
| | | sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq[i]->getID()); |
| | | std::string strFilepath(szBuffer); |
| | | pEq[i]->readRecipeList(0, strFilepath); |
| | | } |
| | | } |
| | | pComboBox->SetCurSel(0); |
| | |
| | | AfxMessageBox(_T("配方名称不能为空!")); |
| | | return; |
| | | } |
| | | if (RecipeManager::getInstance().updateDeviceRecipe(pEq->getName(), _ttoi(strID), std::string(CT2A(strText)))) { |
| | | |
| | | if (RecipeManager::getInstance().updateDeviceRecipeName(SanitizeName(pEq->getName()), _ttoi(strID), std::string(CT2A(strText)))) { |
| | | m_listPPID.SetItemText(nLine, 3, strText); |
| | | } |
| | | } |
| | |
| | | FillDataToListCtrl(vecData); |
| | | } |
| | | else { |
| | | // enable port |
| | | CMsgDlg msgDlg("请等待", "正在获取配方..."); |
| | | pEq->masterRecipeListRequest(0, [&, pEq](int status) -> void { |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("获取配方失败!") : _T("获取配方超时!")); |
| | | msgDlg.DelayClose(3000); |
| | | msgDlg.SetIcon(MSG_BOX_ERROR); |
| | | msgDlg.SetTitle(_T("操作失败")); |
| | | msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | msgDlg.SetMarquee(FALSE, 0); |
| | | msgDlg.SetCompleteCode(-1); |
| | | } |
| | | else if (status == SS_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("获取配方完成!")); |
| | | msgDlg.DelayClose(3000); |
| | | msgDlg.SetIcon(MSG_BOX_SUCCEED); |
| | | msgDlg.SetTitle(_T("操作成功")); |
| | | msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | msgDlg.SetMarquee(FALSE, 0); |
| | | msgDlg.SetCompleteCode(0); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | FillRecipeListToListCtrl(pRecipeList); |
| | | } |
| | | }); |
| | | // 获取配方列表 |
| | | CMsgDlg msgDlg("请等待", "正在获取配方列表..."); |
| | | msgDlg.SetData((DWORD_PTR)this); |
| | | msgDlg.SetDataEx((DWORD_PTR)pEq); |
| | | msgDlg.BeginThread(SyncThreadFunction); |
| | | msgDlg.DoModal(); |
| | | } |
| | | } |
| | |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem > 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | } |
| | | |
| | | void CPageRecipe::OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult) |
| | |
| | | return; |
| | | } |
| | | |
| | | CString strText = m_listPPID.GetItemText(nItem, 2); |
| | | CString strRecipeID = m_listPPID.GetItemText(nItem, 2); |
| | | CString strRecipeName = m_listPPID.GetItemText(nItem, 3); |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | if (nEqSel == CB_ERR) { |
| | | return; |
| | | } |
| | | |
| | | int nRecipeID = _ttoi(strRecipeID); |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel); |
| | | if (pEq == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | CDeviceRecipeParamDlg dlg(this); |
| | | dlg.setDeviceRecipeID(nRecipeID); |
| | | dlg.setDeviceRecipeName(strRecipeName); |
| | | dlg.setEquipment(pEq); |
| | | dlg.DoModal(); |
| | | } |
| | | |
| | | void CPageRecipe::OnCbnSelchangeComboEquipment() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd()); |
| | | int nItem = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd()); |
| | | |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0/* && selectedCount > 0*/); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_EDIT_KEYWORD)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_SEARCH)->EnableWindow(nEqSel == 0); |
| | | |
| | |
| | | } |
| | | else { |
| | | InitListCtrlHeaderForDevice(); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | FillRecipeListToListCtrl(pRecipeList); |
| | | FillRecipeListToListCtrl(pEq); |
| | | } |
| | | } |
| | | |
| | | UINT CPageRecipe::SyncThreadFunction(LPVOID lpvData) |
| | | { |
| | | CMsgDlg* pMsgDlg = (CMsgDlg*)lpvData; |
| | | CPageRecipe* pPageRecipe = (CPageRecipe*)pMsgDlg->GetData(); |
| | | return pPageRecipe->SyncThreadFunctionInner(pMsgDlg); |
| | | } |
| | | |
| | | UINT CPageRecipe::SyncThreadFunctionInner(CMsgDlg* pMsgDlg) |
| | | { |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pMsgDlg->GetDataEx(); |
| | | HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); |
| | | int nStep = 0; |
| | | |
| | | // 准备配方路径 |
| | | char szBuffer[_MAX_PATH]; |
| | | sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq->getID()); |
| | | std::string strFilepath(szBuffer); |
| | | |
| | | pEq->masterRecipeListRequest(0, [&, pEq, pMsgDlg, hEvent](int status) -> void { |
| | | Sleep(300); |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("获取配方列表失败!") : _T("获取配方列表超时!")); |
| | | pMsgDlg->SetIcon(MSG_BOX_ERROR); |
| | | pMsgDlg->SetTitle(_T("操作失败")); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | SetEvent(hEvent); |
| | | } |
| | | else if (status == SS_LIST_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("获取配方列表完成!")); |
| | | pMsgDlg->SetTitle(_T("操作成功")); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | if (pRecipeList != nullptr && !pRecipeList->getIds().empty()) { |
| | | nStep = 1; |
| | | } |
| | | SetEvent(hEvent); |
| | | } |
| | | }); |
| | | ::WaitForSingleObject(hEvent, INFINITE); |
| | | if (nStep != 1) { |
| | | pEq->saveRecipeList(0, strFilepath); |
| | | pMsgDlg->SetIcon(MSG_BOX_SUCCEED); |
| | | pMsgDlg->SetMarquee(FALSE, 0); |
| | | pMsgDlg->SetCompleteCode(-1); |
| | | pMsgDlg->DelayClose(3000); |
| | | } |
| | | ResetEvent(hEvent); |
| | | |
| | | |
| | | // 参数列表 |
| | | if (nStep == 1) { |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | ASSERT(pRecipeList); |
| | | auto& ids = pRecipeList->getIds(); |
| | | pMsgDlg->SetTitle(_T("正在获取参数")); |
| | | for (auto item : ids) { |
| | | int recipeId = item.second; |
| | | CString strMsg; |
| | | strMsg.Format(_T("正在获取配方 %d 参数..."), item.second); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | pEq->recipeParameterRequest(0, recipeId, 0, [&, pEq, pMsgDlg, recipeId, hEvent](int status) -> void { |
| | | Sleep(500); |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("获取配方 %d 参数失败!") : _T("获取配方 %d 参数超时!"), recipeId); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | |
| | | Sleep(30); |
| | | SetEvent(hEvent); |
| | | } |
| | | else if (status == SS_PARAMS_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("获取配方 %d 参数完成!"), item.second); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | |
| | | Sleep(30); |
| | | SetEvent(hEvent); |
| | | } |
| | | }); |
| | | ::WaitForSingleObject(hEvent, INFINITE); |
| | | ResetEvent(hEvent); |
| | | } |
| | | |
| | | |
| | | pEq->saveRecipeList(0, strFilepath); |
| | | pMsgDlg->SetIcon(MSG_BOX_SUCCEED); |
| | | pMsgDlg->SetTitle(_T("操作完成")); |
| | | pMsgDlg->SetCompleteCode(0); |
| | | pMsgDlg->SetMarquee(FALSE, 0); |
| | | pMsgDlg->DelayClose(3000); |
| | | }; |
| | | |
| | | FillRecipeListToListCtrl(pEq); |
| | | CloseHandle(hEvent); |
| | | |
| | | |
| | | // 在此打印配方参数以便核对数据 |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | ASSERT(pRecipeList); |
| | | auto rawDatas = pRecipeList->getParamsRawData(); |
| | | for (auto item : rawDatas) { |
| | | TRACE("================= 配方 %d\n", item.first); |
| | | |
| | | std::vector<CParam> params; |
| | | pEq->parsingParams((const char*)item.second.data(), item.second.size(), params); |
| | | for (auto p : params) { |
| | | if (p.getValueType() == PVT_INT) { |
| | | TRACE("%s: %d\n", p.getName().c_str(), p.getIntValue()); |
| | | } |
| | | else if (p.getValueType() == PVT_DOUBLE) { |
| | | TRACE("%s: %f\n", p.getName().c_str(), p.getDoubleValue()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | std::string CPageRecipe::SanitizeName(const std::string& name) |
| | | { |
| | | std::string result; |
| | | result.reserve(name.size()); |
| | | |
| | | for (char c : name) { |
| | | if (c == '(' || c == '(') { |
| | | break; |
| | | } |
| | | |
| | | unsigned char uc = static_cast<unsigned char>(c); |
| | | if (std::isalnum(uc) || c == '_') { |
| | | result.push_back(c); |
| | | } |
| | | else if (std::isspace(uc)) { |
| | | continue; |
| | | } |
| | | else { |
| | | result.push_back('_'); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | BOOL CPageRecipe::PreTranslateMessage(MSG* pMsg) |
| | | { |
| | | if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) { |
| | | return TRUE; |
| | | } |
| | | |
| | | return CDialogEx::PreTranslateMessage(pMsg); |
| | | } |